private function getConstants() : array {
static $pattern = '/
\*\s+
+ (?:[<]span[ ]class="constant"[>])?
(?<name>\w+)
+ (?:[<]\/span[>])?
(?:\s*=\s*(?P<value>.+))?
(?P<desc>(?:\s*\n\s*[^\*\n#].*)*)
/x';
static $pattern = '/
\*\s+
(?P<modifiers>\w+\s+)*
+ (?:\((?P<usages>(?:(?:\w+)\s*)*)\))*\s*
(?P<type>[\\\\\w]+)\s+
(?<name>\$\w+)
(?:\s*=\s*(?P<defval>.+))?
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';
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];
}
// 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);
$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 {
public $ns;
public $props;
- static $lastNs;
-
function format() {
if ($this->ns !== StructureOfNs::$last) {
printf("namespace %s;\n", $this->ns);
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(")");
public $type;
public $desc;
public $modifiers;
+ public $usages;
public $defval;
+ public $ref;
function formatDefval() {
if (strlen($this->defval)) {
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) {
}
}
}
- 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();
}
}