5 static $out_props = array(
6 'eClass' => array('props', 'events', 'methods'),
7 'eMixin' => array('props', 'events', 'methods'),
8 'eTypedef' => array('name', 'type', 'sig', 'static', 'desc','memberOf'),
9 'eProperty' => array('name', 'type', 'desc','memberOf'),
10 'eConstant' => array('name', 'type', 'desc','memberOf'),
11 'eMethod' => array('name', 'type', 'sig', 'static', 'desc','memberOf', 'isConstructor'),
12 'eConstructor' => array('name', 'type', 'sig', 'static', 'desc','memberOf', 'isConstructor'),
13 'eEnum' => array('name', 'type', 'desc','memberOf'), // fixme .. .values.?
14 'eFunction' => array('name', 'type', 'sig', 'static', 'desc','memberOf', 'isConstructor'),// fixme .. .memberof == package.
15 'Prop' => array('name', 'type', 'desc','memberOf'),
21 var $isDeprecated = false;
23 function __construct($ar)
25 foreach($ar as $k=>$v) {
34 $dom = new DomDocument();
35 libxml_use_internal_errors(true);
36 echo "Reading : {$this->href}\n";
37 $dom->loadHTMLFile(FDIR . $this->href);
38 libxml_clear_errors();
39 $xp = new DomXPath($dom);
40 $desc = $this->getElementsByClassName($dom, 'desc');
42 $this->desc = $this->innerHTML($desc->item(0));
44 $sc = $this->getElementsByClassName($dom, 'source-code');
46 $this->example = $this->innerHTML($sc->item(0));
51 function getElementsByClassName($dom, $class)
53 $xp = new DomXPath($dom);
54 return $xp->query("//*[contains(concat(' ', @class, ' '), ' ".$class." ')]");
56 function innerHTML($node)
61 $dom= $node->ownerDocument;
63 foreach ($node->childNodes as $child)
65 $ret.= $dom->saveHTML($child);
70 function parseType($sp)
74 echo "parseType got invalid value";
76 $ar = $sp->getElementsByTagName('a');
78 $this->type = $sp->textContent;
80 if ($ar->length == 1) {
81 $this->type = eClass::$url_map[$ar->item(0)->getAttribute('href')]->name;
84 $this->types = array();
86 for($i =0;$i<$ar->length;$i++) {
87 $add = eClass::$url_map[$ar->item($i)->getAttribute('href')]->name;;
88 $this->types[] = $add;
90 $t .= ($i == 0) ? $add : ('<'. $add );
93 for($i =0;$i<$ar->length-1;$i++) {
100 function toSummaryArray()
103 if (!isset(self::$out_props[get_class($this)] )) {
104 die("don't know how to handle class: " . get_class($this));
106 foreach(self::$out_props[get_class($this)] as $k) {
108 if (is_array($out)) {
110 foreach($this->{$k} as $v) {
111 $out[] = $v->toSummaryArray();
125 class Ns extends Obj {
126 static $tree = array();
127 static $kv = array();
131 var $isFakeNamespace = false;
132 function __construct($ar)
134 parent::__construct($ar);
136 if ($this->isFakeNamespace) {
140 $bits= explode('.', $this->name);
142 self::$kv[$this->name] = $this;
144 if (count($bits) == 1 ) {
145 self::$tree[] = $this;
149 $par = implode('.', $bits);
150 $this->memberOf = $par;
155 static function add($cls)
157 self::$kv[$cls->memberOf]->cn[] = $cls;
163 foreach($this->cn as $c) {
164 if (!isset($c->shortname)) {
167 $map[$c->shortname] = $c;
174 foreach($this->cn as $c) {
175 if (!isset($c->shortname)) {
178 $bits = preg_split('/(?<=[a-z])(?=[A-Z])|(?=[A-Z][a-z])/',
179 $c->shortname, -1, PREG_SPLIT_NO_EMPTY);
181 if (count($bits) < 2 ) {
185 if (!isset($map[$bits[0]])) {
187 'name' => $c->memberOf .'.'. $bits[0],
188 'isFakeNamespace' => true,
191 $map[$bits[0]] = $add;
195 $map[$bits[0]]->cn[] = $c;
199 // finally remove from tree if it's saving '1'
202 if (empty($c->isFakeNamespace)) {
206 if (count($c->cn) < 2) {
219 function toTreeArray()
221 // tidy the tree before starting...
226 'name' => $this->name,
230 // in theory flutter has a flat tree... ?
231 foreach($this->cn as $e) {
232 if (in_array(get_class($e) , array('eClass', 'eMixin', 'Ns'))) {
233 $ret['cn'][] = $e->toTreeArray();
242 class eClass extends Obj {
244 static $all = array();
245 static $url_map = array();
247 var $extends = array();
248 var $memberOf; /// really the package..
249 var $events = array();
250 var $methods = array();
251 var $props = array();
252 var $isMixin = false;
254 var $isTypedef = false;
255 var $isConstant = false;
256 var $isAbstract = false;
257 var $implementors = array();
258 var $realImplementors = array();
260 function __construct($ar)
262 parent::__construct($ar);
263 $bits = explode('.', $this->name);
264 $this->shortname = array_pop($bits);
266 self::$all[$this->name] = $this;
267 self::$url_map[$this->href] = $this;
273 // do children first..
277 $dom = parent::parseHTML();
279 $sc = $this->getElementsByClassName($dom,'self-crumb');
281 // abstracts actually impletment stuff in flutter...
282 if (preg_match('/abstract class/', $this->innerHTML($sc->item(0)))) {
283 $this->isAbstract = true;
290 $dl = $dom->getElementsByTagName('dl')->item(0);
291 if ($dl->getAttribute('class') != 'dl-horizontal') {
292 $this->extends = array();
296 if (strpos($this->innerHTML($dl), '@deprecated')) {
297 $this->isDeprecated = true;
302 $dt = $dl->getElementsByTagName('dt');
306 if ($this->innerHTML($dt->item(0)) != 'Inheritance') {
310 $dd = $dl->getElementsByTagName('dd');
314 $as = $dd->item(0)->getElementsByTagName('a');
315 $this->extends = array();
316 for($i = $as->length-1;$i > -1; $i--) {
318 if (!isset(self::$url_map[$as->item($i)->getAttribute('href')])) {
319 die("could not find " . $as->item($i)->getAttribute('href') . " when parsing" . $this->href);
322 $this->extends[] = self::$url_map[$as->item($i)->getAttribute('href')]->name;
323 self::$url_map[$as->item($i)->getAttribute('href')]->addImplementor($this->name);
331 function addImplementor($n)
333 if (!in_array($n, $this->implementors)) {
334 $this->implementors[] = $n;
337 function expandImplementors($exclude = array())
339 $exclude[] = $this->name;
341 $orig = $this->implementors;
342 foreach($orig as $c) {
343 if (in_array($c, $exclude)) {
346 $cl = self::$all[$c]->expandImplementors($exclude);
347 foreach($cl as $cc) {
348 if (!in_array($cc, $this->implementors)) {
349 $this->implementors[]= $cc;
353 return $this->implementors;
356 function realImplementors()
359 $this->realImplementors = array();
360 foreach($this->implementors as $c) {
361 if (self::$all[$c]->isAbstract) {
364 $this->realImplementors[] = $c;
372 foreach($this->events as $e) {
375 foreach($this->methods as $e) {
378 foreach($this->props as $e) {
381 // loop through children.
384 function toTreeArray()
387 foreach($this->cn as $e) {
388 if (in_array(get_class($e) , array('eClass', 'eMixin'))) {
389 $cn[] = $e->toTreeArray();
392 $child = $this->prop('child');
393 $child = $child ? $child : $this->prop('children');
394 $child = $child ? $child : $this->prop('home'); // MaterialApp??
395 // above might be a constant... - technically we could work out the type of that..
396 if ($child && !in_array(get_class($child), array( 'eProperty', 'Prop'))) {
403 // to complicated to check if these are widget children ... some are wrappers around
406 $childtypes = $child->isA('dart:core.List') ? 2 : 1;
407 $childtype = count($child->types) ? array_pop($child->types) : $child->type;
412 'name' => $this->name,
415 'extends' => $this->extends,
416 'is_abstract' => $this->isAbstract,
417 'childtypes' => $childtypes,
418 'childtype' => $childtype,
419 'implementors' => $this->realImplementors, // this is not really complete...
424 return in_array($name,$this->extends);
428 foreach($this->props as $p) {
429 if ($p->name == $name) {
438 class eMixin extends eClass
442 $dom = Obj::parseHTML();
445 class eConstant extends Obj
450 $dom = Obj::parseHTML();
454 class eEnum extends eClass // enums look alot like classes..
459 $dom = Obj::parseHTML();
463 class eProperty extends Obj
471 $dom = Obj::parseHTML();
475 class Prop extends Obj {
478 var $types = array(); // generics...
481 var $isConstant = false;
484 $dom = Obj::parseHTML();
485 // work out the type..
486 $rt = $this->getElementsByClassName($dom, 'returntype');
487 $this->parseType($rt->item(0));
491 if (empty($this->types)) {
492 return $name == $this->type;
495 if (in_array($name,$this->types)) {
498 foreach($this->types as $ty) {
499 if (!isset(eClass::$all[$ty])) {
501 die("could not find type $ty\n");
503 if (in_array($name, eClass::$all[$ty]->extends)) {
513 class eMethod extends Obj { // doubles up for events? - normally 'on' is the name
515 var $type = ''; // return...
520 var $params = array();
522 //"isStatic" : false,
523 var $isConstructor = false;
525 // "deprecated" : "",
532 $dom = parent::parseHTML();
533 $sp = $this->getElementsByClassName($dom,'returntype')->item(0);
534 $this->parseType($sp);
537 $ar = $this->getElementsByClassName($dom,'parameter');
538 for($i =0;$i<$ar->length;$i++) {
539 $this->params[] = new Param( $ar->item($i) );
546 class eConstructor extends eMethod {
550 $dom = Obj::parseHTML();
551 // doesnt have a 'type'
553 $ar = $this->getElementsByClassName($dom,'parameter');
554 for($i =0;$i<$ar->length;$i++) {
555 $this->params[] = new Param( $ar->item($i) );
563 class eFunction extends eMethod
565 function __construct($ar)
567 parent::__construct($ar);
568 eClass::$all[$this->name] = $this;
569 eClass::$url_map[$this->href] = $this;
575 // loop through children.
581 $dom = parent::parseHTML();
584 class eTypedef extends eFunction
588 class Param extends Obj {
592 var $isOptional = true;
593 function __construct($node)
596 $ar = $node->getElementsByTagName('span');
598 echo "mssing paramter info", $this->innerHTML($node); exit;
600 for($i = 0; $i < $ar->length; $i++) {
602 switch($ar->item($i)->getAttribute('class')) {
603 case 'parameter-name':
604 $this->name = $ar->item($i)->textContent;
606 case 'type-annotation':
607 $this->parseType($ar->item($i));