Overview

Namespaces

  • None
  • Peg
    • Cli
      • Commands
    • Config
    • Custom
      • Command
        • Action
          • Generate
          • Parse
      • CommandLine
      • Config
      • Localization
      • Utilities
    • Lib
      • Definitions
        • Element
      • Generator
      • Lexers
      • Plugins
      • Signals
        • Data
          • Definitions
          • Lexers
        • Type
  • PHP

Classes

  • Base
  • Doxygen
  • Overview
  • Namespace
  • Class
  • Tree
  • Todo
   1: <?php
   2: /**
   3:  * A doxygen definitions extractor that is divided into different methods.
   4:  *
   5:  * @author Jefferson González
   6:  * @license MIT
   7:  * @link http://github.com/peg-org/peg-src Source code.
   8:  */
   9: 
  10: namespace Peg\Lib\Lexers;
  11: 
  12: use \DOMDocument;
  13: use \DOMXPath;
  14: 
  15: /**
  16:  * Implements a doxygen xml extractor of definitions.
  17:  */
  18: class Doxygen extends \Peg\Lib\Lexers\Base
  19: {
  20: 
  21:     /**
  22:      * Reference to the index.xml file initialized on the Start() method.
  23:      * @var \DOMDocument
  24:      */
  25:     private $document;
  26: 
  27:     /**
  28:      * Initializes the parsing process
  29:      * @param string $path Were the doxygen xml documentation resides.
  30:      */
  31:     public function Start()
  32:     {
  33:         $this->definitions_path = rtrim($this->definitions_path, "/\\");
  34: 
  35:         $this->document = new DOMDocument();
  36:         $this->document->load($this->definitions_path . "/index.xml");
  37: 
  38:         $this->ExtractConstants($this->document);
  39:         $this->ExtractEnumerations($this->document);
  40:         $this->ExtractVariables($this->document);
  41:         $this->ExtractTypeDefinitions($this->document);
  42:         $this->ExtractFunctions($this->document);
  43:         $this->ExtractClasses($this->document);
  44:     }
  45: 
  46:     /**
  47:      * Extract #defines and anonymous enumerations.
  48:      * @param \DOMDocument $document
  49:      * @param string $namespace
  50:      */
  51:     private function ExtractConstants(\DOMDocument $document, $namespace = "")
  52:     {
  53:         $xpath = new DOMXPath($document);
  54: 
  55:         $entries = $xpath->evaluate(
  56:             "//compound[@kind='file'] | //compound[@kind='namespace']", 
  57:             $document
  58:         );
  59: 
  60:         for($i = 0; $i < $entries->length; $i++)
  61:         {
  62:             $kind = $entries->item($i)->getAttribute("kind");
  63:             $refid = $entries->item($i)->getAttribute("refid");
  64:             $name = $entries->item($i)->childNodes->item(0)->nodeValue;
  65: 
  66:             if($kind == "namespace")
  67:                 $namespace = str_replace("::", "\\", $name);
  68:             else
  69:                 $namespace = "\\";
  70: 
  71:             $file_doc = new DOMDocument();
  72:             $file_doc->load($this->definitions_path . "/$refid.xml");
  73: 
  74:             $file_xpath = new DOMXPath($file_doc);
  75: 
  76:             $file_members = $file_xpath->evaluate(
  77:                 "//memberdef[@kind='define'] | //memberdef[@kind='enum']", 
  78:                 $file_doc
  79:             );
  80: 
  81:             for($member = 0; $member < $file_members->length; $member++)
  82:             {
  83:                 $kind = $file_members->item($member)->getAttribute("kind");
  84: 
  85:                 $location = str_replace(
  86:                     $this->headers_path, 
  87:                     "", 
  88:                     str_replace(
  89:                         "\\", 
  90:                         "/", 
  91:                         $file_xpath->evaluate(
  92:                             "location", 
  93:                             $file_members->item($member)
  94:                         )->item(0)->getAttribute("file")
  95:                     )
  96:                 );
  97: 
  98:                 if($kind == "define")
  99:                 {
 100:                     $define_name = $file_xpath->evaluate(
 101:                         "name", 
 102:                         $file_members->item($member)
 103:                     )->item(0)->nodeValue;
 104:                     
 105:                     $define_description = $file_xpath->evaluate(
 106:                         "briefdescription", 
 107:                         $file_members->item($member)
 108:                     )->item(0)->nodeValue;
 109: 
 110:                     $define_initializer = true;
 111: 
 112:                     if(is_object($file_xpath->evaluate("initializer", $file_members->item($member))->item(0)))
 113:                         $define_initializer = $file_xpath->evaluate(
 114:                             "initializer", 
 115:                             $file_members->item($member)
 116:                         )->item(0)->nodeValue;
 117:                     
 118:                     else
 119:                         $this->SendMessage(
 120:                             t("Warning:") . " " 
 121:                             . t("no initializer value for") 
 122:                             . " #" . $define_name 
 123:                         );
 124: 
 125:                     // Skip macro function defines
 126:                     if($file_xpath->evaluate("param", $file_members->item($member))->length > 0)
 127:                     {
 128:                         continue;
 129:                     }
 130: 
 131:                     // Skip defines used for compiler
 132:                     if($define_name{0} == "_" && $define_name{1} == "_")
 133:                     {
 134:                         continue;
 135:                     }
 136: 
 137:                     $constant = new \Peg\Lib\Definitions\Element\Constant(
 138:                         $define_name,
 139:                         $define_initializer,
 140:                         $define_description
 141:                     );
 142:                     
 143:                     $this->symbols->AddConstant(
 144:                         $constant, 
 145:                         $location, 
 146:                         $namespace
 147:                     );
 148:                 }
 149: 
 150:                 // Also add anonymous enumerations as constants
 151:                 elseif($kind == "enum")
 152:                 {
 153:                     $enum_name = $file_xpath->evaluate(
 154:                         "name", 
 155:                         $file_members->item($member)
 156:                     )->item(0)->nodeValue;
 157:                     
 158:                     $enum_description = $file_xpath->evaluate(
 159:                         "briefdescription", 
 160:                         $file_members->item($member)
 161:                     )->item(0)->nodeValue;
 162: 
 163:                     // Skip non anonymous enumerations
 164:                     if($enum_name{0} != "@")
 165:                         continue;
 166: 
 167:                     $enum_values = $file_xpath->evaluate(
 168:                         "enumvalue", 
 169:                         $file_members->item($member)
 170:                     );
 171: 
 172:                     for($enum_value = 0; $enum_value < $enum_values->length; $enum_value++)
 173:                     {
 174:                         $enum_option = $file_xpath->evaluate(
 175:                             "name", 
 176:                             $enum_values->item($enum_value)
 177:                         )->item(0)->nodeValue;
 178:                         
 179:                         $constant = new \Peg\Lib\Definitions\Element\Constant(
 180:                             $enum_option,
 181:                             1,
 182:                             $enum_description
 183:                         );
 184: 
 185:                         $this->symbols->AddConstant(
 186:                             $constant, 
 187:                             $location, 
 188:                             $namespace
 189:                         );
 190:                     }
 191:                 }
 192:             }
 193:         }
 194:     }
 195: 
 196:     /**
 197:      * Extract named enumerations.
 198:      * @param \DOMDocument $document
 199:      * @param string $namespace
 200:      */
 201:     private function ExtractEnumerations(\DOMDocument $document, $namespace = "")
 202:     {
 203:         $xpath = new DOMXPath($document);
 204: 
 205:         $entries = $xpath->evaluate(
 206:             "//compound[@kind='file'] | //compound[@kind='namespace']", 
 207:             $document
 208:         );
 209: 
 210:         for($i = 0; $i < $entries->length; $i++)
 211:         {
 212:             $kind = $entries->item($i)->getAttribute("kind");
 213:             $refid = $entries->item($i)->getAttribute("refid");
 214:             $name = $entries->item($i)->childNodes->item(0)->nodeValue;
 215: 
 216:             if($kind == "namespace")
 217:                 $namespace = str_replace("::", "\\", $name);
 218:             else
 219:                 $namespace = "\\";
 220: 
 221:             $file_doc = new DOMDocument();
 222:             $file_doc->load($this->definitions_path . "/$refid.xml");
 223: 
 224:             $file_xpath = new DOMXPath($file_doc);
 225: 
 226:             $file_members = $file_xpath->evaluate(
 227:                 "//memberdef[@kind='enum']", 
 228:                 $file_doc
 229:             );
 230: 
 231:             for($member = 0; $member < $file_members->length; $member++)
 232:             {
 233:                 $location = str_replace(
 234:                     $this->headers_path, 
 235:                     "", 
 236:                     str_replace(
 237:                         "\\", 
 238:                         "/", 
 239:                         $file_xpath->evaluate(
 240:                             "location", 
 241:                             $file_members->item($member)
 242:                         )->item(0)->getAttribute("file")
 243:                     )
 244:                 );
 245: 
 246:                 $enum_name = $file_xpath->evaluate(
 247:                     "name", 
 248:                     $file_members->item($member)
 249:                 )->item(0)->nodeValue;
 250:                 
 251:                 $enum_description = $file_xpath->evaluate(
 252:                     "briefdescription", 
 253:                     $file_members->item($member)
 254:                 )->item(0)->nodeValue;
 255: 
 256:                 // Just extract named enumerations
 257:                 // Anonymous enumerations go on constants.json
 258:                 if($enum_name{0} != "@")
 259:                 {
 260:                     $enum_values = $file_xpath->evaluate(
 261:                         "enumvalue", 
 262:                         $file_members->item($member)
 263:                     );
 264:                     
 265:                     $enum_options = array();
 266: 
 267:                     for(
 268:                         $enum_value = 0; 
 269:                         $enum_value < $enum_values->length; 
 270:                         $enum_value++
 271:                     )
 272:                     {
 273:                         $enum_options[] = $file_xpath->evaluate(
 274:                             "name", 
 275:                             $enum_values->item($enum_value)
 276:                         )->item(0)->nodeValue;
 277:                     }
 278:                     
 279:                     $enumeration = new \Peg\Lib\Definitions\Element\Enumeration(
 280:                         $enum_name,
 281:                         $enum_options,
 282:                         $enum_description
 283:                     );
 284:                     
 285:                     $this->symbols->AddEnumeration(
 286:                         $enumeration, 
 287:                         $location, 
 288:                         $namespace
 289:                     );
 290:                 }
 291:             }
 292:         }
 293:     }
 294: 
 295:     /**
 296:      * Extract global variables.
 297:      * @param \DOMDocument $document
 298:      * @param string $namespace
 299:      */
 300:     private function ExtractVariables(\DOMDocument $document, $namespace = "")
 301:     {
 302:         $xpath = new DOMXPath($document);
 303: 
 304:         $entries = $xpath->evaluate(
 305:             "//compound[@kind='file'] | //compound[@kind='namespace']", 
 306:             $document
 307:         );
 308: 
 309:         for($i = 0; $i < $entries->length; $i++)
 310:         {
 311:             $kind = $entries->item($i)->getAttribute("kind");
 312:             $refid = $entries->item($i)->getAttribute("refid");
 313:             $name = $entries->item($i)->childNodes->item(0)->nodeValue;
 314: 
 315:             if($kind == "namespace")
 316:                 $namespace = str_replace("::", "\\", $name);
 317:             else
 318:                 $namespace = "\\";
 319: 
 320:             $file_doc = new DOMDocument();
 321:             $file_doc->load($this->definitions_path . "/$refid.xml");
 322: 
 323:             $file_xpath = new DOMXPath($file_doc);
 324: 
 325:             $file_members = $file_xpath->evaluate(
 326:                 "//memberdef[@kind='variable']", 
 327:                 $file_doc
 328:             );
 329: 
 330:             for($member = 0; $member < $file_members->length; $member++)
 331:             {
 332:                 $location = str_replace(
 333:                     $this->headers_path, 
 334:                     "", 
 335:                     str_replace(
 336:                         "\\", 
 337:                         "/", 
 338:                         $file_xpath->evaluate(
 339:                             "location", 
 340:                             $file_members->item($member)
 341:                         )->item(0)->getAttribute("file")
 342:                     )
 343:                 );
 344: 
 345:                 $global_variable_name = $file_xpath->evaluate(
 346:                     "name", 
 347:                     $file_members->item($member)
 348:                 )->item(0)->nodeValue;
 349:                 
 350:                 $global_variable_type = $file_xpath->evaluate(
 351:                     "type", 
 352:                     $file_members->item($member)
 353:                 )->item(0)->nodeValue;
 354:                 
 355:                 $global_variable_description = $file_xpath->evaluate(
 356:                     "briefdescription", 
 357:                     $file_members->item($member)
 358:                 )->item(0)->nodeValue;
 359: 
 360:                 $variable = new \Peg\Lib\Definitions\Element\GlobalVariable(
 361:                     $global_variable_name, 
 362:                     str_replace(
 363:                         array(" *", " &"), 
 364:                         array("*", "&"), 
 365:                         $global_variable_type
 366:                     ),
 367:                     $global_variable_description
 368:                 );
 369:                 
 370:                 $this->symbols->AddGlobalVar($variable, $location, $namespace);
 371:             }
 372:         }
 373:     }
 374: 
 375:     /**
 376:      * Extract typedef declared on the source files.
 377:      * @param \DOMDocument $document
 378:      * @param type $namespace
 379:      */
 380:     private function ExtractTypeDefinitions(\DOMDocument $document, $namespace = "")
 381:     {
 382:         $xpath = new DOMXPath($document);
 383: 
 384:         $entries = $xpath->evaluate(
 385:             "//compound[@kind='file'] | //compound[@kind='namespace']", 
 386:             $document
 387:         );
 388: 
 389:         for($i = 0; $i < $entries->length; $i++)
 390:         {
 391:             $kind = $entries->item($i)->getAttribute("kind");
 392:             $refid = $entries->item($i)->getAttribute("refid");
 393:             $name = $entries->item($i)->childNodes->item(0)->nodeValue;
 394: 
 395:             if($kind == "namespace")
 396:                 $namespace = str_replace("::", "\\", $name);
 397:             else
 398:                 $namespace = "\\";
 399: 
 400:             $file_doc = new DOMDocument();
 401:             $file_doc->load($this->definitions_path . "/$refid.xml");
 402: 
 403:             $file_xpath = new DOMXPath($file_doc);
 404: 
 405:             $file_members = $file_xpath->evaluate(
 406:                 "//memberdef[@kind='typedef']", 
 407:                 $file_doc
 408:             );
 409: 
 410:             for($member = 0; $member < $file_members->length; $member++)
 411:             {
 412:                 $location = str_replace(
 413:                     $this->headers_path, 
 414:                     "", 
 415:                     str_replace(
 416:                         "\\", 
 417:                         "/", 
 418:                         $file_xpath->evaluate(
 419:                             "location", 
 420:                             $file_members->item($member)
 421:                         )->item(0)->getAttribute("file")
 422:                     )
 423:                 );
 424: 
 425:                 $this->includes[$location] = true;
 426: 
 427:                 $typedef_name = $file_xpath->evaluate(
 428:                     "name", 
 429:                     $file_members->item($member)
 430:                 )->item(0)->nodeValue;
 431:                 
 432:                 $typedef_type = $file_xpath->evaluate(
 433:                     "type", 
 434:                     $file_members->item($member)
 435:                 )->item(0)->nodeValue;
 436:                 
 437:                 $typedef_description = $file_xpath->evaluate(
 438:                     "briefdescription", 
 439:                     $file_members->item($member)
 440:                 )->item(0)->nodeValue;
 441: 
 442:                 $typedef = new \Peg\Lib\Definitions\Element\TypeDef(
 443:                     $typedef_name, 
 444:                     $typedef_type, 
 445:                     $typedef_description
 446:                 );
 447:                 
 448:                 $this->symbols->AddTypeDef(
 449:                     $typedef, 
 450:                     $location, 
 451:                     $namespace
 452:                 );
 453:             }
 454:         }
 455:     }
 456: 
 457:     /**
 458:      * Extract functions its overloads and parameters information.
 459:      * @param \DOMDocument $document
 460:      * @param string $namespace
 461:      */
 462:     private function ExtractFunctions(\DOMDocument $document, $namespace = "")
 463:     {
 464:         $xpath = new DOMXPath($document);
 465: 
 466:         $entries = $xpath->evaluate(
 467:             "//compound[@kind='file'] | //compound[@kind='namespace']", 
 468:             $document
 469:         );
 470:         
 471:         // First we store all functions and their overloads, after
 472:         // we use this array to create FunctionElement objects and add
 473:         // them to the symbols object.
 474:         $functions = array();
 475: 
 476:         for($i = 0; $i < $entries->length; $i++)
 477:         {
 478:             $kind = $entries->item($i)->getAttribute("kind");
 479:             $refid = $entries->item($i)->getAttribute("refid");
 480:             $name = $entries->item($i)->childNodes->item(0)->nodeValue;
 481: 
 482:             if($kind == "namespace")
 483:                 $namespace = str_replace("::", "\\", $name);
 484:             else
 485:                 $namespace = "\\";
 486: 
 487:             $file_doc = new DOMDocument();
 488:             $file_doc->load($this->definitions_path . "/$refid.xml");
 489: 
 490:             $file_xpath = new DOMXPath($file_doc);
 491: 
 492:             $file_members = $file_xpath->evaluate(
 493:                 "//memberdef[@kind='function']", 
 494:                 $file_doc
 495:             );
 496: 
 497:             for($member = 0; $member < $file_members->length; $member++)
 498:             {
 499:                 $location = str_replace(
 500:                     $this->headers_path, "", str_replace(
 501:                         "\\", 
 502:                         "/", 
 503:                         $file_xpath->evaluate(
 504:                             "location", 
 505:                             $file_members->item($member)
 506:                         )->item(0)->getAttribute("file")
 507:                     )
 508:                 );
 509: 
 510:                 $function_name = $file_xpath->evaluate(
 511:                     "name", 
 512:                     $file_members->item($member)
 513:                 )->item(0)->nodeValue;
 514: 
 515:                 $function_type = $file_xpath->evaluate(
 516:                     "type", 
 517:                     $file_members->item($member)
 518:                 )->item(0)->nodeValue;
 519:                 
 520:                 $function_description = trim(
 521:                     $file_xpath->evaluate(
 522:                         "briefdescription", 
 523:                         $file_members->item($member)
 524:                     )->item(0)->nodeValue
 525:                 );
 526:                 
 527:                 $function_type = str_replace(
 528:                     array(" *", " &"), 
 529:                     array("*", "&"), 
 530:                     $function_type
 531:                 );
 532: 
 533:                 $function_overload = new \Peg\Lib\Definitions\Element\Overload(
 534:                     $function_description
 535:                 );
 536:                 
 537:                 $function_overload->SetReturnType(
 538:                     new \Peg\Lib\Definitions\Element\ReturnType(
 539:                         $function_type
 540:                     )
 541:                 );
 542:                 
 543:                 // Retrieve all function parameters
 544:                 $function_parameters = $file_xpath->evaluate(
 545:                     "param", 
 546:                     $file_members->item($member)
 547:                 );
 548: 
 549:                 $parameters = array();
 550: 
 551:                 for(
 552:                     $function_parameter = 0; 
 553:                     $function_parameter < $function_parameters->length; 
 554:                     $function_parameter++
 555:                 )
 556:                 {
 557:                     // Default generated param name in case it doesn't have one.
 558:                    $param_name = "param" . $function_parameter;
 559: 
 560:                     if(is_object($file_xpath->evaluate("declname", $function_parameters->item($function_parameter))->item(0)))
 561:                     {
 562:                         $param_name = $file_xpath->evaluate(
 563:                             "declname", 
 564:                             $function_parameters->item(
 565:                                 $function_parameter
 566:                             ))->item(0)->nodeValue
 567:                         ;
 568:                     }
 569:                     else
 570:                     {
 571:                         $this->SendMessage(t("Skipping:") . " " . t("function") 
 572:                             . " '" . $function_name . "' " 
 573:                             . t("seems to be a macro with undocumented parameter types.") 
 574:                         );
 575: 
 576:                         continue 2;
 577:                     }
 578: 
 579:                     $param_type = str_replace(
 580:                         array(" *", " &"), 
 581:                         array("*", "&"), 
 582:                         $file_xpath->evaluate(
 583:                             "type", 
 584:                             $function_parameters->item($function_parameter)
 585:                         )->item(0)->nodeValue
 586:                     );
 587: 
 588:                     // Check if parameter is array
 589:                     $param_array = false;
 590:                     if($file_xpath->evaluate("array", $function_parameters->item($function_parameter))->length > 0)
 591:                     {
 592:                         $array_value = $file_xpath->evaluate(
 593:                             "array", 
 594:                             $function_parameters->item(
 595:                                 $function_parameter)
 596:                             )->item(0)->nodeValue
 597:                         ;
 598: 
 599:                         if($array_value == "[]")
 600:                         {
 601:                             $param_array = true;
 602:                         }
 603:                         else
 604:                         {
 605:                             //$parameters[$function_parameter]["extra"] = $array_value;
 606:                         }
 607:                     }
 608: 
 609:                     // Get default value
 610:                     $param_value = "";
 611:                     if($file_xpath->evaluate("defval", $function_parameters->item($function_parameter))->length > 0)
 612:                     {
 613:                         $param_value = $file_xpath->evaluate(
 614:                             "defval", 
 615:                             $function_parameters->item(
 616:                                 $function_parameter)
 617:                             )->item(0)->nodeValue
 618:                         ;
 619:                     }
 620:                     
 621:                     $parameter = new \Peg\Lib\Definitions\Element\Parameter(
 622:                         $param_name, 
 623:                         $param_type, 
 624:                         $param_value
 625:                     );
 626:                     
 627:                     $parameter->is_array = $param_array;
 628:                     
 629:                     $function_overload->AddParameter($parameter);
 630:                 }
 631: 
 632:                 $functions[$function_name][] = [
 633:                     $location,
 634:                     $namespace,
 635:                     $function_overload
 636:                 ];
 637:             }
 638:         }
 639:         
 640:         foreach($functions as $function_name=>$function_overloads)
 641:         {
 642:             $function = new \Peg\Lib\Definitions\Element\FunctionElement(
 643:                 $function_name
 644:             );
 645:             
 646:             $header = "";
 647:             $namespace = "";
 648:             
 649:             foreach($function_overloads as $overload)
 650:             {
 651:                 if(!$header)
 652:                 {
 653:                     $header = $overload[0];
 654:                     $namespace = $overload[1];
 655:                 }
 656:                 
 657:                 $function->AddOverload($overload[2]);
 658:             }
 659:             
 660:             $this->symbols->AddFunction(
 661:                 $function, 
 662:                 $header,
 663:                 $namespace
 664:             );
 665:         }
 666:     }
 667: 
 668:     /**
 669:      * Extracts classes and its properties, methods, methods overloads, paramter
 670:      * details, enumerations and member variables.
 671:      * @param \DOMDocument $document
 672:      * @param string $namespace
 673:      * @todo Also extract a class unnamed enums and handle array parameters
 674:      * with non bracket array elements.
 675:      */
 676:     private function ExtractClasses(\DOMDocument $document, $namespace = "")
 677:     {
 678:         $xpath = new DOMXPath($document);
 679: 
 680:         $entries = $xpath->evaluate(
 681:             "//compound[@kind='class'] | //compound[@kind='struct']", 
 682:             $document
 683:         );
 684: 
 685:         for($i = 0; $i < $entries->length; $i++)
 686:         {
 687:             $kind = $entries->item($i)->getAttribute("kind");
 688:             $refid = $entries->item($i)->getAttribute("refid");
 689:             
 690:             $class_name = $entries->item($i)->childNodes->item(0)->nodeValue;
 691: 
 692:             // Check if class is part of a namespace
 693:             $name_parts = explode("::", $class_name);
 694: 
 695:             if(count($name_parts) > 0)
 696:             {
 697:                 $class_name = $name_parts[count($name_parts) - 1];
 698:                 unset($name_parts[count($name_parts) - 1]);
 699:                 $namespace = implode("\\", $name_parts);
 700:             }
 701:             else
 702:             {
 703:                 $namespace = "\\";
 704:             }
 705: 
 706:             $class_doc = new DOMDocument();
 707:             $class_doc->load($this->definitions_path . "/$refid.xml");
 708: 
 709:             $class_xpath = new DOMXPath($class_doc);
 710:             
 711:             // Retreive class description
 712:             $class_description = $class_xpath->evaluate(
 713:                 "/doxygen/compounddef/briefdescription", 
 714:                 $class_doc
 715:             )->item(0)->nodeValue;
 716: 
 717:             // Retreive include file
 718:             $header_file = $class_xpath->evaluate(
 719:                 "//includes", 
 720:                 $class_doc
 721:             )->item(0)->nodeValue;
 722: 
 723:             $class_is_struct = false;
 724:             if($kind == "struct")
 725:             {
 726:                 $class_is_struct = true;
 727:             }
 728: 
 729:             // Check from which classes this one inherits
 730:             $class_parents = array();
 731:             
 732:             $class_inherits = $class_xpath->evaluate(
 733:                 "//inheritancegraph", 
 734:                 $class_doc
 735:             );
 736: 
 737:             if($class_inherits->length > 0)
 738:             {
 739:                 $class_inherit_nodes = $class_xpath->evaluate(
 740:                     "node", 
 741:                     $class_inherits->item(0)
 742:                 );
 743:                 
 744:                 for($node = 0; $node < $class_inherit_nodes->length; $node++)
 745:                 {
 746:                     if($class_inherit_nodes->item($node)->childNodes->item(1)->nodeValue == $class_name)
 747:                     {
 748:                         $class_inherit_childnodes = $class_xpath->evaluate(
 749:                             "childnode", 
 750:                             $class_inherit_nodes->item($node)
 751:                         );
 752: 
 753:                         if($class_inherit_nodes->length > 0)
 754:                         {
 755:                             for(
 756:                                 $childnode = 0; 
 757:                                 $childnode < $class_inherit_childnodes->length; 
 758:                                 $childnode++
 759:                             )
 760:                             {
 761:                                 $parent_class_id = $class_inherit_childnodes
 762:                                     ->item($childnode)
 763:                                     ->attributes
 764:                                     ->getNamedItem("refid")
 765:                                     ->value
 766:                                 ;
 767:                                 
 768:                                 $parent_class_node = $class_xpath->evaluate(
 769:                                     '//node[@id="' . $parent_class_id . '"]', 
 770:                                     $class_doc
 771:                                 );
 772: 
 773:                                 if($parent_class_node->length > 0)
 774:                                 {
 775:                                     $parent_class_name = $parent_class_node
 776:                                         ->item(0)
 777:                                         ->childNodes
 778:                                         ->item(1)
 779:                                         ->nodeValue
 780:                                     ;
 781:                                     
 782:                                     $class_parents[] = str_replace(
 783:                                         "::",
 784:                                         "\\",
 785:                                         $parent_class_name
 786:                                     );
 787:                                 }
 788:                             }
 789:                         }
 790: 
 791:                         break;
 792:                     }
 793:                 }
 794:             }
 795: 
 796:             // If class is implemented only on some platforms we store them.
 797:             // This feature is wxWidgets specific as far as I know.
 798:             $class_platforms = array();
 799:             
 800:             $class_availability = $class_xpath->evaluate(
 801:                 "/doxygen/compounddef/detaileddescription/para/onlyfor", 
 802:                 $class_doc
 803:             );
 804:             
 805:             if($class_availability->length > 0)
 806:             {
 807:                 $class_platforms = explode(
 808:                     ",", 
 809:                     $class_availability->item(0)->nodeValue
 810:                 );
 811:             }
 812:             
 813:             // Initialize class object
 814:             $class = new \Peg\Lib\Definitions\Element\ClassElement(
 815:                 $class_name, 
 816:                 $class_description
 817:             );
 818:             
 819:             $class->struct = $class_is_struct;
 820:             
 821:             $class->AddParents($class_parents);
 822:             
 823:             // First we store all methods and their overloads, after,
 824:             // we use this array to create FunctionElement objects and add
 825:             // them to the class object.
 826:             $methods = array();
 827: 
 828:             // Get the member functions of the class
 829:             $class_member = $class_xpath->evaluate("//memberdef", $class_doc);
 830:             for($member = 0; $member < $class_member->length; $member++)
 831:             {
 832: 
 833:                 // Class functions
 834:                 if($class_member->item($member)->getAttribute("kind") == "function")
 835:                 {
 836:                     // Retreive function name
 837:                     $function_name = $class_xpath->evaluate(
 838:                         "name", 
 839:                         $class_member->item($member)
 840:                     )->item(0)->nodeValue;
 841: 
 842:                     // skip destructor
 843:                     if($function_name{0} == "~")
 844:                         continue;
 845:                     
 846:                     // Retrieve brief description
 847:                     $function_description = trim(
 848:                         $class_xpath->evaluate(
 849:                             "briefdescription", 
 850:                             $class_member->item($member)
 851:                         )->item(0)->nodeValue
 852:                     );
 853:                     
 854:                     // Retrieve member return type
 855:                     $function_type = str_replace(
 856:                         array(" *", " &"), 
 857:                         array("*", "&"), 
 858:                         $class_xpath->evaluate(
 859:                             "type", 
 860:                             $class_member->item($member)
 861:                         )->item(0)->nodeValue
 862:                     );
 863:                     
 864:                     // Store type base class to later check which bases classes aren't documented
 865:                     if("" . stristr($function_type, "Base") . "" != "")
 866:                     {
 867:                         $base_classes[
 868:                             str_replace(
 869:                                 array("&", " ", "*", "const"), 
 870:                                 "", 
 871:                                 $function_type
 872:                             )
 873:                         ] = 1;
 874:                     }
 875:                     
 876:                     // Create method overload
 877:                     $function_overload = new \Peg\Lib\Definitions\Element\Overload(
 878:                         $function_description
 879:                     );
 880: 
 881:                     $function_overload->SetReturnType(
 882:                         new \Peg\Lib\Definitions\Element\ReturnType(
 883:                             $function_type
 884:                         )
 885:                     );
 886:                     
 887:                     // Check if a method has been deprecated.
 888:                     $function_deprecated = false;
 889: 
 890:                     if(
 891:                         strstr(
 892:                             $class_xpath->evaluate(
 893:                                 "detaileddescription", 
 894:                                 $class_member->item($member)
 895:                             )->item(0)->nodeValue, 
 896:                             "Deprecated"
 897:                         ) !== false
 898:                     )
 899:                     {
 900:                         $function_deprecated = true;
 901:                     }
 902: 
 903:                     // If method is implemented only on some platforms we store them
 904:                     // This seems to be wxWidgets specific.
 905:                     $function_platforms = array();
 906:                     
 907:                     $member_availability = $class_xpath->evaluate(
 908:                         "detaileddescription/para/onlyfor", 
 909:                         $class_member->item($member)
 910:                     );
 911:                     
 912:                     if($member_availability->length > 0)
 913:                     {
 914:                         $function_platforms = explode(
 915:                             ",", 
 916:                             $member_availability->item(0)->nodeValue
 917:                         );
 918:                     }
 919: 
 920:                     // Check if member is constant
 921:                     if($class_member->item($member)->getAttribute("const") == "yes")
 922:                         $function_overload->constant = true;
 923: 
 924:                     // Check if member is static
 925:                     if($class_member->item($member)->getAttribute("static") == "yes")
 926:                         $function_overload->static = true;
 927: 
 928:                     // Check if member is virtual
 929:                     if($class_member->item($member)->getAttribute("virt") == "virtual")
 930:                         $function_overload->virtual = true;
 931: 
 932:                     // Check if member is pure virtual
 933:                     if($class_member->item($member)->getAttribute("virt") == "pure-virtual")
 934:                         $function_overload->pure_virtual = true;
 935: 
 936:                     if($class_member->item($member)->getAttribute("prot") == "protected")
 937:                         $function_overload->protected = true;
 938: 
 939: 
 940:                     // Check all member parameters
 941:                     $function_parameters = $class_xpath->evaluate(
 942:                         "param", 
 943:                         $class_member->item($member)
 944:                     );
 945:                     
 946:                     if($function_parameters->length > 0)
 947:                     {
 948:                         for(
 949:                             $parameter = 0; 
 950:                             $parameter < $function_parameters->length; 
 951:                             $parameter++
 952:                         )
 953:                         {
 954:                             // Get param name
 955:                             $param_name = "param" . $parameter;
 956: 
 957:                             if(is_object($class_xpath->evaluate("declname", $function_parameters->item($parameter))->item(0)))
 958:                                 $param_name = $class_xpath->evaluate(
 959:                                     "declname", 
 960:                                     $function_parameters->item($parameter)
 961:                                 )->item(0)->nodeValue;
 962:                             else
 963:                                 $this->SendMessage(
 964:                                     t("Warning:") . " " . t("parameter") . " " 
 965:                                     . ($parameter + 1) . " " . t("on method") 
 966:                                     . " " . $class_name . "::" . $function_name 
 967:                                     . " " . t("does not have a name.")
 968:                                 );
 969: 
 970:                             // Get param type
 971:                             $param_type = str_replace(
 972:                                 array(" *", " &"), 
 973:                                 array("*", "&"), 
 974:                                 $class_xpath->evaluate(
 975:                                     "type", 
 976:                                     $function_parameters->item($parameter)
 977:                                 )->item(0)->nodeValue
 978:                             );
 979: 
 980:                             // Check if parameter is array
 981:                             $param_array = false;
 982:                             if($class_xpath->evaluate("array", $function_parameters->item($parameter))->length > 0)
 983:                             {
 984:                                 $array_value = $class_xpath->evaluate(
 985:                                     "array", 
 986:                                     $function_parameters->item($parameter)
 987:                                 )->item(0)->nodeValue;
 988: 
 989:                                 if($array_value == "[]")
 990:                                 {
 991:                                     $param_array = true;
 992:                                 }
 993:                                 else
 994:                                 {
 995:                                     //TODO: Handle non bracket array elements
 996:                                     //$parameters[$parameter]["extra"] = $array_value;
 997:                                 }
 998:                             }
 999: 
1000:                             // Store type base class to later check which bases classes aren't documented
1001:                             $the_type = str_replace(
1002:                                 array(" *", " &"), 
1003:                                 array("*", "&"), 
1004:                                 $class_xpath->evaluate(
1005:                                     "type", 
1006:                                     $function_parameters->item($parameter)
1007:                                 )->item(0)->nodeValue
1008:                             );
1009:                             
1010:                             if("" . stristr($the_type, "Base") . "" != "")
1011:                             {
1012:                                 $base_classes[str_replace(array("&", " ", "*", "const"), "", $the_type)] = 1;
1013:                             }
1014: 
1015:                             // Get param default value
1016:                             $param_value = "";
1017:                             if($class_xpath->evaluate("defval", $function_parameters->item($parameter))->length > 0)
1018:                             {
1019:                                 $param_value = $class_xpath->evaluate(
1020:                                     "defval", 
1021:                                     $function_parameters->item($parameter)
1022:                                 )->item(0)->nodeValue;
1023:                             }
1024:                             
1025:                             $param = new \Peg\Lib\Definitions\Element\Parameter( 
1026:                                 $param_name, 
1027:                                 $param_type, 
1028:                                 $param_value
1029:                             );
1030:                             
1031:                             $param->is_array = $param_array;
1032:                             
1033:                             $function_overload->AddParameter($param);
1034:                         }
1035:                     }
1036: 
1037:                     $methods[$function_name][] = $function_overload;
1038:                 }
1039: 
1040:                 // Class enumerations
1041:                 elseif($class_member->item($member)->getAttribute("kind") == "enum")
1042:                 {
1043:                     $enum_name = $class_xpath->evaluate(
1044:                         "name", 
1045:                         $class_member->item($member)
1046:                     )->item(0)->nodeValue;
1047:                     
1048:                     $enum_description = $class_xpath->evaluate(
1049:                         "briefdescription", 
1050:                         $class_member->item($member)
1051:                     )->item(0)->nodeValue;
1052: 
1053:                     //Skip unnamed enums TODO: implement them
1054:                     if($enum_name{0} == "@")
1055:                         continue;
1056: 
1057:                     $enum_values = $class_xpath->evaluate("enumvalue", $class_member->item($member));
1058: 
1059:                     $enum_options = array();
1060:                     
1061:                     for(
1062:                         $enum_value = 0; 
1063:                         $enum_value < $enum_values->length; 
1064:                         $enum_value++
1065:                     )
1066:                     {
1067:                         $enum_options[] = $class_xpath->evaluate(
1068:                             "name", 
1069:                             $enum_values->item($enum_value)
1070:                         )->item(0)->nodeValue;
1071:                     }
1072:                     
1073:                     $enumeration = new \Peg\Lib\Definitions\Element\Enumeration(
1074:                         $enum_name,
1075:                         $enum_options,
1076:                         $enum_description
1077:                     );
1078:                     
1079:                     $class->AddEnumeration(
1080:                         $enumeration
1081:                     );
1082:                 }
1083:                 // Class variables
1084:                 elseif($class_member->item($member)->getAttribute("kind") == "variable")
1085:                 {
1086:                     $variable_name = $class_xpath->evaluate(
1087:                         "name", 
1088:                         $class_member->item($member)
1089:                     )->item(0)->nodeValue;
1090: 
1091:                     $variable_type = $class_xpath->evaluate(
1092:                         "type", 
1093:                         $class_member->item($member)
1094:                     )->item(0)->nodeValue;
1095:                     
1096:                     $variable_description = $class_xpath->evaluate(
1097:                         "briefdescription", $class_member->item($member)
1098:                     )->item(0)->nodeValue;
1099:                     
1100:                     $variable = new \Peg\Lib\Definitions\Element\ClassVariable(
1101:                         $variable_name, 
1102:                         $variable_type, 
1103:                         $variable_description
1104:                     );
1105: 
1106:                     if($class_member->item($member)->getAttribute("static") != "no")
1107:                         $variable->static = true;
1108: 
1109:                     if($class_member->item($member)->getAttribute("mutable") != "no")
1110:                         $variable->mutable = true;
1111: 
1112:                     if($class_member->item($member)->getAttribute("prot") == "protected")
1113:                         $variable->protected = true;
1114: 
1115:                     if($class_member->item($member)->getAttribute("prot") == "public")
1116:                         $variable->public = true;
1117:                     
1118:                     $class->AddVariable($variable);
1119:                 }
1120:                 //Store not handled members of the class
1121:                 else
1122:                 {
1123:                     //$class_not_handle[$class_member->item($member)->getAttribute("kind")]++;
1124:                 }
1125:             }
1126:             
1127:             foreach($methods as $method_name=>$method_overloads)
1128:             {
1129:                 $function = new \Peg\Lib\Definitions\Element\FunctionElement(
1130:                     $method_name
1131:                 );
1132: 
1133:                 foreach($method_overloads as $overload)
1134:                 {
1135:                     $function->AddOverload($overload);
1136:                 }
1137: 
1138:                 $class->AddMethod($function);
1139:             }
1140:             
1141:             $this->symbols->AddClass($class, $header_file, $namespace);
1142:         }
1143:     }
1144: 
1145: }
PEG Api API documentation generated by ApiGen 2.8.0