move formatting from JS to PHP
[mdref/mdref] / mdref / Structure.php
index aed35897892864a16b101f319a063e927d9c7763..ace780b4d0c62b340be869c124cdefebc3132cda 100644 (file)
@@ -129,7 +129,9 @@ class Structure {
        private function getConstants() : array {
                static $pattern = '/
                        \*\s+
+                       (?:[<]span[ ]class="constant"[>])?
                        (?<name>\w+)
+                       (?:[<]\/span[>])?
                        (?:\s*=\s*(?P<value>.+))?
                        (?P<desc>(?:\s*\n\s*[^\*\n#].*)*)
                /x';
@@ -149,6 +151,7 @@ class Structure {
                static $pattern = '/
                        \*\s+
                        (?P<modifiers>\w+\s+)*
+                       (?:\((?P<usages>(?:(?:\w+)\s*)*)\))*\s*
                        (?P<type>[\\\\\w]+)\s+
                        (?<name>\$\w+)
                        (?:\s*=\s*(?P<defval>.+))?
@@ -187,8 +190,8 @@ class Structure {
                static $pattern = '/
                        \*\s+
                        (?P<modifiers>\w+\s+)*
-                       (?P<type>[\\\\\w]+)\s+
-                       (?<name>\$\w+)
+                       (?P<type>[\\\\\w_]+)\s+
+                       (?P<ref>&)?(?P<name>\$[\w_]+)
                        (?:\s*=\s*(?P<defval>.+))?
                        (?P<desc>(?:\s*[^*]*\n(?!\n)\s*[^\*].*)*)
                /x';
@@ -204,20 +207,17 @@ class Structure {
        private function getReturns() : array {
                static $pattern = '/
                        \*\s+
-                       (?<type>[\\\\\w]+)
+                       (?<type>[\\\\\w_]+)
                        \s*,?\s*
                        (?P<desc>(?:.|\n(?!\s*\*))*)
                /x';
-               
+
                $returns = $this->splitList($pattern, $this->getSection("Returns"));
-               $retdesc = "";
+               $retvals = [];
                foreach ($returns as list(, $type, $desc)) {
-                       if (strlen($retdesc)) {
-                               $retdesc .= "\n\t or $type $desc";
-                       } else {
-                               $retdesc = $desc;
-                       }
+                       $retvals[] = [$type, $desc];
                }
+               return $retvals;
                return [implode("|", array_unique(array_column($returns, "type"))), $retdesc];
        }
 
@@ -252,11 +252,11 @@ abstract class StructureOf {
 
        // abstract function format();
 
-       function formatDesc(int $level, array $tags = []) {
+       function formatDesc($level, array $tags = []) {
                $indent = str_repeat("\t", $level);
                $desc = trim($this->desc);
                if (false !== stristr($desc, "deprecated in")) {
-                       $tags[] = "@deprecated";
+                       $tags[] = "deprecated";
                }
                if ($tags) {
                        $desc .= "\n\n@" . implode("\n@", $tags);
@@ -264,6 +264,43 @@ abstract class StructureOf {
                $desc = preg_replace('/[\t ]*\n/',"\n$indent * ", $desc);
                printf("%s/**\n%s * %s\n%s */\n", $indent, $indent, $desc, $indent);
        }
+
+       function saneTypes(array $types) {
+               $sane = [];
+               foreach ($types as $type) {
+                       if (strlen($s = $this->saneType($type, false))) {
+                               $sane[] = $s;
+                       }
+               }
+               return $sane;
+       }
+
+       function saneType($type, $strict = true) {
+               switch (strtolower($type)) {
+                       case "object":
+                       case "resource":
+                       case "stream":
+                       case "mixed":
+                       case "true":
+                       case "false":
+                       case "null":
+                               if ($strict) {
+                                       break;
+                               }
+                               /* fallthrough */
+                       case "bool":
+                       case "int":
+                       case "float":
+                       case "string":
+                       case "array":
+                       case "callable":
+                               return $type;
+                               break;
+                       default:
+                               return ($type[0] === "\\" ? "":"\\") . $type;
+                               break;
+               }
+       }
 }
 
 class StructureOfRoot extends StructureOf {
@@ -319,8 +356,6 @@ class StructureOfClass extends StructureOfNs
        public $ns;
        public $props;
 
-       static $lastNs;
-
        function format() {
                if ($this->ns !== StructureOfNs::$last) {
                        printf("namespace %s;\n", $this->ns);
@@ -362,23 +397,54 @@ class StructureOfFunc extends StructureOf {
        public $returns;
        public $throws;
 
+       function omitParamTypes() {
+               switch ($this->name) {
+                       // ArrayAccess
+                       case "offsetGet":
+                       case "offsetSet":
+                       case "offsetExists":
+                       case "offsetUnset":
+                       // Serializable
+                       case "serialize":
+                       case "unserialize":
+                               return true;
+               }
+               return false;
+       }
+
        function format(int $level) {
                $tags = [];
                foreach ($this->params as $param) {
-                       $tags[] = "param {$param->type} {$param->name} {$param->desc}";
+                       $type = $this->saneType($param->type, false);
+                       $tags[] = "param {$type} {$param->name} {$param->desc}";
                }
                foreach ($this->throws as $throws) {
-                       $tags[] = "throws $throws";
+                       $tags[] = "throws " . $this->saneType($throws);
                }
-               if ($this->name !== "__construct" && $this->returns[0]) {
-                       $tags[] = "return {$this->returns[0]} {$this->returns[1]}";
+               if ($this->name !== "__construct" && $this->returns) {
+
+                       if (count($this->returns) > 1) {
+                               $type = implode("|", $this->saneTypes(array_column($this->returns, 0)));
+                               $desc = "";
+                               foreach ($this->returns as list($typ, $ret)) {
+                                       if (strlen($desc)) {
+                                               $desc .= "\n\t\t or ";
+                                       }
+                                       $desc .= $this->saneType($typ, false) . " " . $ret;
+                               }
+                       } else {
+                               $type = $this->saneType($this->returns[0][0], false);
+                               $desc = $this->returns[0][1];
+                       }
+                       $tags[] = "return $type $desc";
                }
                $this->formatDesc(1, $tags);
                printf("\tfunction %s(", $this->name);
                $comma = "";
+               $omit = $this->omitParamTypes();
                foreach ($this->params as $param) {
                        print $comma;
-                       $param->formatAsParam($level);
+                       $param->formatAsParam($level, !$omit);
                        $comma = ", ";
                }
                printf(")");
@@ -403,7 +469,9 @@ class StructureOfVar extends StructureOf {
        public $type;
        public $desc;
        public $modifiers;
+       public $usages;
        public $defval;
+       public $ref;
 
        function formatDefval() {
                if (strlen($this->defval)) {
@@ -411,6 +479,9 @@ class StructureOfVar extends StructureOf {
                                printf(" = ");
                                var_export(constant($this->defval));
                        } else if (strlen($this->defval)) {
+                               if (false !== strchr($this->defval, "\\") && $this->defval[0] != "\\") {
+                                       $this->defval = "\\" . $this->defval;
+                               }
                                printf(" = %s", $this->defval);
                        }
                } elseif ($this->modifiers) {
@@ -419,18 +490,21 @@ class StructureOfVar extends StructureOf {
                        }
                }
        }
-       function formatAsProp(int $level) {
+       function formatAsProp($level) {
                $indent = str_repeat("\t", $level);
                $this->formatDesc($level,
-                       preg_split('/\s+/', $this->modifiers, -1, PREG_SPLIT_NO_EMPTY)
-                       + [-1 => "var {$this->type}"]
+                       preg_split('/\s+/', $this->modifiers ." " . $this->usages, -1, PREG_SPLIT_NO_EMPTY)
+                       + [-1 => "var " . $this->saneType($this->type, false)]
                );
                printf("%s%s %s", $indent, $this->modifiers, $this->name);
                $this->formatDefval();
        }
 
-       function formatAsParam(int $level) {
-               printf("%s", $this->name);
+       function formatAsParam($level, $with_type = true) {
+               if ($with_type && strlen($type = $this->saneType($this->type))) {
+                       printf("%s ", $type);
+               }
+               printf("%s%s", $this->ref, $this->name);
                $this->formatDefval();
        }
 }