diff --git a/phpdotnet/phd/Package/Generic/XHTML.php b/phpdotnet/phd/Package/Generic/XHTML.php index 256aa71a7..9e6d64bb6 100644 --- a/phpdotnet/phd/Package/Generic/XHTML.php +++ b/phpdotnet/phd/Package/Generic/XHTML.php @@ -478,8 +478,9 @@ abstract class Package_Generic_XHTML extends Format_Abstract_XHTML { "modifier" => "public", ), "methodsynopsis" => array( - "returntypes" => [], - "type_separator" => null, + "returntypes" => array(), + "type_separator" => array(), + "type_separator_stack" => array(), ), "co" => 0, "callouts" => 0, @@ -1277,10 +1278,10 @@ public function format_parameter($open, $name, $attrs, $props) } public function format_void($open, $name, $attrs, $props) { - if ($props['sibling'] == 'methodname') { + if (isset($props['sibling']) && $props['sibling'] == 'methodname') { return '('; } else { - return '<span class="type"><span class="type void">void</span></span>'; + return '<span class="type"><a href="language.types.void.html" class="type void">void</a></span>'; } } diff --git a/phpdotnet/phd/Package/PHP/XHTML.php b/phpdotnet/phd/Package/PHP/XHTML.php index 7c59b05b4..f1cc5e3b1 100644 --- a/phpdotnet/phd/Package/PHP/XHTML.php +++ b/phpdotnet/phd/Package/PHP/XHTML.php @@ -11,8 +11,13 @@ abstract class Package_PHP_XHTML extends Package_Generic_XHTML { 'colophon' => 'format_chunk', 'function' => 'format_function', 'methodname' => 'format_function', + 'methodparam' => 'format_methodparam', 'methodsynopsis' => 'format_methodsynopsis', 'legalnotice' => 'format_chunk', + 'parameter' => array( + /* DEFAULT */ 'format_parameter', + 'methodparam' => 'format_methodparam_parameter', + ), 'part' => 'format_container_chunk', 'partintro' => 'format_partintro', 'preface' => 'format_chunk', @@ -70,9 +75,16 @@ abstract class Package_PHP_XHTML extends Package_Generic_XHTML { 'type' => array( /* DEFAULT */ 'format_type', 'methodsynopsis' => 'format_methodsynopsis_type', + 'methodparam' => 'format_type_methodparam', 'type' => array( /* DEFAULT */ 'format_type', - 'methodsynopsis' => 'format_suppressed_tags', + 'methodsynopsis' => 'format_methodsynopsis_type', + 'methodparam' => 'format_type_methodparam', + 'type' => array( + /* DEFAULT */ 'format_type', + 'methodsynopsis' => 'format_methodsynopsis_type', + 'methodparam' => 'format_type_methodparam', + ), ), ), 'varname' => array( @@ -120,14 +132,20 @@ abstract class Package_PHP_XHTML extends Package_Generic_XHTML { ), 'refname' => 'format_refname_text', 'type' => array( - /* DEFAULT */ 'format_type_if_object_or_pseudo_text', + /* DEFAULT */ 'format_type_text', 'classsynopsisinfo' => false, - 'fieldsynopsis' => 'format_type_if_object_or_pseudo_text', - 'methodparam' => 'format_type_if_object_or_pseudo_text', + 'fieldsynopsis' => 'format_type_text', + 'methodparam' => 'format_type_methodparam_text', 'methodsynopsis' => 'format_type_methodsynopsis_text', 'type' => array( - /* DEFAULT */ 'format_type_if_object_or_pseudo_text', + /* DEFAULT */ 'format_type_text', 'methodsynopsis' => 'format_type_methodsynopsis_text', + 'methodparam' => 'format_type_methodparam_text', + 'type' => array( + /* DEFAULT */ 'format_type_text', + 'methodsynopsis' => 'format_type_methodsynopsis_text', + 'methodparam' => 'format_type_methodparam_text', + ), ), ), 'titleabbrev' => array( @@ -167,13 +185,18 @@ abstract class Package_PHP_XHTML extends Package_Generic_XHTML { "refname" => array(), "alternatives" => array(), "refsynopsisdiv" => null, + "methodparam" => array( + "type_separator" => array(), + "type_separator_stack" => array(), + "paramtypes" => array(), + ), ); /** @var int|null Number of already formatted types in the current compound type */ private $num_types = null; - /** @var string|null The character to separate the current compound type, i.e. "|" or "&" */ - private $type_separator = null; + /** @var array<string> The characters to separate the current compound types, i.e. "|" or "&" */ + private $type_separator = []; /** @var bool|null Decides whether the union type can be displayed by using "?" */ private $simple_nullable = null; @@ -344,14 +367,19 @@ public function format_type($open, $tag, $attrs, $props) { strpos($props["innerXml"], '<type xmlns="http://docbook.org/ns/docbook">null</type>') !== false ) { $this->simple_nullable = true; - $this->type_separator = ""; + $this->type_separator[] = ""; $retval .= '<span class="type">?</span>'; } else { - $this->type_separator = $isUnionType ? "|" : "&"; + $typeSeparator = match ($attrs[Reader::XMLNS_DOCBOOK]["class"]) { + "union" => "|", + "intersection" => "&", + default => "", + }; + $this->type_separator[] = $typeSeparator; } } elseif (isset($this->num_types)) { if ($this->num_types > 0) { - $retval .= $this->type_separator; + $retval .= end($this->type_separator); } $this->num_types++; @@ -361,7 +389,7 @@ public function format_type($open, $tag, $attrs, $props) { } else { if (isset($attrs[Reader::XMLNS_DOCBOOK]["class"])) { $this->num_types = null; - $this->type_separator = null; + array_pop($this->type_separator); $this->simple_nullable = null; } $retval .= '</span>'; @@ -370,10 +398,23 @@ public function format_type($open, $tag, $attrs, $props) { return $retval; } - public function format_methodsynopsis_type($open, $tag, $attrs) - { - if ($open && isset($attrs[Reader::XMLNS_DOCBOOK]["class"])) { - $this->cchunk["methodsynopsis"]["type_separator"] = $attrs[Reader::XMLNS_DOCBOOK]["class"] === "union" ? "|" : "&"; + public function format_methodsynopsis_type($open, $tag, $attrs) { + if ($open) { + if (isset($attrs[Reader::XMLNS_DOCBOOK]["class"])) { + $this->cchunk["methodsynopsis"]["type_separator_stack"][] = match ($attrs[Reader::XMLNS_DOCBOOK]["class"]) { + "union" => "|", + "intersection" => "&", + }; + } + } else { + if ( + isset($attrs[Reader::XMLNS_DOCBOOK]["class"]) + && ($attrs[Reader::XMLNS_DOCBOOK]["class"] === "union" + || $attrs[Reader::XMLNS_DOCBOOK]["class"] === "intersection") + ) { + $lastSeparator = array_pop($this->cchunk["methodsynopsis"]["type_separator_stack"]); + $this->cchunk["methodsynopsis"]["type_separator"][count($this->cchunk["methodsynopsis"]["type_separator"]) - 1] = end($this->cchunk["methodsynopsis"]["type_separator_stack"]) ?: $lastSeparator; + } } return ""; @@ -481,64 +522,136 @@ public function format_methodsynopsis($open, $name, $attrs, $props) { $content = ""; if ($this->params["paramCount"] > 3) { $content .= "<br>"; + } else if ($this->params["paramCount"] === 0) { + $content .= "("; } $content .= ")"; if ($this->cchunk["methodsynopsis"]["returntypes"]) { - $types = []; - $this->type_separator = $this->cchunk["methodsynopsis"]["type_separator"]; + $type = $this->format_types( + $this->cchunk["methodsynopsis"]["type_separator"], + $this->cchunk["methodsynopsis"]["returntypes"] + ); - if ( - $this->type_separator === "|" && - count($this->cchunk["methodsynopsis"]["returntypes"]) === 2 && - in_array("null", $this->cchunk["methodsynopsis"]["returntypes"], true) - ) { - $this->simple_nullable = true; - $this->type_separator = ""; - $types[] = '<span class="type">?</span>'; - } + $content .= ': ' . $type; + } - foreach ($this->cchunk["methodsynopsis"]["returntypes"] as $return_type) { - $formatted_type = self::format_type_if_object_or_pseudo_text($return_type, "type"); - if ($formatted_type === false) { - $formatted_type = $return_type; - } - if ($formatted_type !== "") { + $content .= "</div>\n"; + $this->cchunk["methodsynopsis"] = $this->dchunk["methodsynopsis"]; + + return $content; + } + + private function format_types($type_separators, $paramOrReturnType) { + $types = []; + + if ( + $type_separators[0] === "|" && + count($paramOrReturnType) === 2 && + in_array("null", $paramOrReturnType, true) + ) { + $this->simple_nullable = true; + $type_separators[0] = ""; + $formatted_type = self::format_type_text("?", "type"); + $types[] = '<span class="type">' . $formatted_type .'</span>'; + } + + foreach ($paramOrReturnType as $individualType) { + $formatted_type = self::format_type_text($individualType, "type"); + if ($formatted_type === false) { + $formatted_type = $individualType; + } + if ($formatted_type !== "") { + if ($individualType === "void") { + $types[] = $formatted_type; + } else { $types[] = '<span class="type">' . $formatted_type . '</span>'; } } + } - $type = implode($this->type_separator ?? '', $types); - if (count($types) > 1) { - $type = '<span class="type">' . $type . '</span>'; - } - $content .= ': ' . $type; - $this->simple_nullable = null; + $type = ""; + $isDnfType = (in_array("&", $type_separators, true) && in_array("|", $type_separators, true)); + for ($i = 0; $i < count($types); $i++) { + $previousSeparator = ($i > 0 ) ? $type_separators[$i - 1] : ""; + $openingParenthesis = ($isDnfType && $type_separators[$i] === "&" && $previousSeparator !== "&") ? "(" : ""; + $closingParenthesis = ($isDnfType && $type_separators[$i] !== "&" && $previousSeparator === "&") ? ")" : ""; + + $type .= $openingParenthesis . $types[$i] . $closingParenthesis . $type_separators[$i]; } + $type = rtrim($type, end($type_separators)); - $content .= "</div>\n"; - $this->cchunk["methodsynopsis"] = $this->dchunk["methodsynopsis"]; + if (count($types) > 1) { + $type = '<span class="type">' . $type . '</span>'; + } + $this->simple_nullable = null; - return $content; + return $type; } public function format_type_methodsynopsis_text($type, $tagname) { $this->cchunk["methodsynopsis"]["returntypes"][] = $type; + $this->cchunk["methodsynopsis"]["type_separator"][] = end($this->cchunk["methodsynopsis"]["type_separator_stack"]); return ""; } - public function format_type_if_object_or_pseudo_text($type, $tagname) { - if (strtolower($type) === "null" && $this->simple_nullable) { - return ""; + public function format_methodparam_parameter($open, $name, $attrs, $props) { + $type = ""; + if ($open) { + if ($this->cchunk["methodparam"]["paramtypes"]) { + $type = $this->format_types( + $this->cchunk["methodparam"]["type_separator"], + $this->cchunk["methodparam"]["paramtypes"] + ); + } + $this->cchunk["methodparam"] = $this->dchunk["methodparam"]; } + return $type . parent::format_methodparam_parameter($open, $name, $attrs, $props); + } - if (in_array(strtolower($type), array("bool", "int", "double", "boolean", "integer", "float", "string", "array", "object", "resource", "null"))) { - return false; + public function format_methodparam($open, $name, $attrs) { + if ($open) { + $this->cchunk["methodparam"] = $this->dchunk["methodparam"]; + return parent::format_methodparam($open, $name, $attrs); } - return self::format_type_text($type, $tagname); + if ($this->params["opt"] && !$this->params["init"]) { + return '<span class="initializer"> = ?</span></span>'; + } + $this->params["init"] = false; + $this->cchunk["methodparam"] = $this->dchunk["methodparam"]; + return "</span>"; + } + + public function format_type_methodparam($open, $tag, $attrs) { + if ($open) { + if (isset($attrs[Reader::XMLNS_DOCBOOK]["class"])) { + $this->cchunk["methodparam"]["type_separator_stack"][] = match ($attrs[Reader::XMLNS_DOCBOOK]["class"]) { + "union" => "|", + "intersection" => "&", + }; + } + } else { + if ( + isset($attrs[Reader::XMLNS_DOCBOOK]["class"]) + && ($attrs[Reader::XMLNS_DOCBOOK]["class"] === "union" + || $attrs[Reader::XMLNS_DOCBOOK]["class"] === "intersection") + ) { + $lastSeparator = array_pop($this->cchunk["methodparam"]["type_separator_stack"]); + $this->cchunk["methodparam"]["type_separator"][count($this->cchunk["methodparam"]["type_separator"]) - 1] = end($this->cchunk["methodparam"]["type_separator_stack"]) ?: $lastSeparator; + } + } + + return ""; + } + + public function format_type_methodparam_text($type, $tagname) { + $this->cchunk["methodparam"]["paramtypes"][] = $type; + $this->cchunk["methodparam"]["type_separator"][] = end($this->cchunk["methodparam"]["type_separator_stack"]); + + return ""; } public function format_type_text($type, $tagname) { @@ -546,6 +659,8 @@ public function format_type_text($type, $tagname) { $href = $fragment = ""; switch($t) { + case "void": + return $this->format_void(false, '', [], []); case "bool": $href = "language.types.boolean"; break; @@ -555,6 +670,17 @@ public function format_type_text($type, $tagname) { case "double": $href = "language.types.float"; break; + case "?": + $href = "language.types.null"; + break; + case "false": + case "true": + $href = "language.types.value"; + break; + case "null": + if ($this->simple_nullable) { + return ""; + } case "boolean": case "integer": case "float": @@ -562,30 +688,38 @@ public function format_type_text($type, $tagname) { case "array": case "object": case "resource": - case "null": - if ($this->simple_nullable) { - return ""; - } case "callable": case "iterable": - $href = "language.types.$t"; - break; case "mixed": - $href = "language.types.declarations"; - $fragment = "language.types.declarations.$t"; + case "never": + $href = "language.types.$t"; break; default: /* Check if its a classname. */ $href = Format::getFilename("class.$t"); } + if ($href === false) { + return false; + } + + $classNames = ($type === "?") ? ($tagname . ' null') : ($tagname . ' ' . $type); if ($href && $this->chunked) { - return '<a href="' .$href. $this->getExt().($fragment ? "#$fragment" : ""). '" class="' .$tagname. ' ' .$type. '">' .$type. '</a>'; + return '<a href="' .$href. $this->getExt().($fragment ? "#$fragment" : ""). '" class="' . $classNames . '">' .$type. '</a>'; } if ($href) { - return '<a href="#' .($fragment ? $fragment : $href). '" class="' .$tagname. ' ' .$type. '">' .$type. '</a>'; + return '<a href="#' .($fragment ? $fragment : $href). '" class="' . $classNames . '">' .$type. '</a>'; + } + return '<span class="' . $classNames . '">' .$type. '</span>'; + } + + public function format_void($open, $name, $attrs, $props) { + if (isset($props['sibling']) && $props['sibling'] == 'methodname') { + $this->cchunk["methodsynopsis"]["returntypes"][] = "void"; + $this->cchunk["methodsynopsis"]["type_separator"][] = ""; + return ''; } - return '<span class="' .$tagname. ' ' .$type. '">' .$type. '</span>'; + return parent::format_void($open, $name, $attrs, $props); } public function format_example_title($open, $name, $attrs, $props) { diff --git a/tests/php/bug49102-1.phpt b/tests/php/bug49102-1.phpt index d3f0f0ffe..e489ded72 100644 --- a/tests/php/bug49102-1.phpt +++ b/tests/php/bug49102-1.phpt @@ -63,26 +63,28 @@ Content: <div class="classsynopsisinfo classsynopsisinfo_comment">/* Methods */</div> <div class="constructorsynopsis dc-description"> - <span class="methodname"><strong>__construct</strong></span>()</div> + <span class="methodname"><strong>__construct</strong></span>(): <span class="type"><a href="language.types.void.html" class="type void">void</a></span></div> - <div class="methodsynopsis dc-description"><span class="methodname"><strong>setIteratorMode</strong></span>(<span class="methodparam"><span class="type">int</span> <code class="parameter">$mode</code></span>): <span class="type"><span class="type void">void</span></span></div> + <div class="methodsynopsis dc-description"><span class="methodname"><strong>setIteratorMode</strong></span>(<span class="methodparam"><span class="type"><a href="language.types.integer.html" class="type int">int</a></span> <code class="parameter">$mode</code></span>): <span class="type"><a href="language.types.void.html" class="type void">void</a></span></div> <div class="classsynopsisinfo classsynopsisinfo_comment">/* Inherited methods */</div> - <div class="methodsynopsis dc-description"><span class="methodname"><strong>SplDoublyLinkedList::bottom</strong></span>(): <span class="type"><a href="language.types.declarations.html#language.types.declarations.mixed" class="type mixed">mixed</a></span></div> + <div class="methodsynopsis dc-description"><span class="methodname"><strong>SplDoublyLinkedList::bottom</strong></span>(): <span class="type"><span class="type"><a href="language.types.mixed.html" class="type mixed">mixed</a></span><span class="type"><a href="language.types.void.html" class="type void">void</a></span></span></div> - <div class="methodsynopsis dc-description"><span class="methodname"><strong>SplDoublyLinkedList::count</strong></span>(): <span class="type">int</span></div> + <div class="methodsynopsis dc-description"><span class="methodname"><strong>SplDoublyLinkedList::count</strong></span>(): <span class="type"><span class="type"><a href="language.types.integer.html" class="type int">int</a></span><span class="type"><a href="language.types.void.html" class="type void">void</a></span></span></div> - <div class="methodsynopsis dc-description"><span class="methodname"><strong>SplDoublyLinkedList::current</strong></span>(): <span class="type"><a href="language.types.declarations.html#language.types.declarations.mixed" class="type mixed">mixed</a></span></div> + <div class="methodsynopsis dc-description"><span class="methodname"><strong>SplDoublyLinkedList::current</strong></span>(): <span class="type"><span class="type"><a href="language.types.mixed.html" class="type mixed">mixed</a></span><span class="type"><a href="language.types.void.html" class="type void">void</a></span></span></div> - <div class="methodsynopsis dc-description"><span class="methodname"><strong>SplDoublyLinkedList::getIteratorMode</strong></span>(): <span class="type">int</span></div> + <div class="methodsynopsis dc-description"><span class="methodname"><strong>SplDoublyLinkedList::getIteratorMode</strong></span>(): <span class="type"><span class="type"><a href="language.types.integer.html" class="type int">int</a></span><span class="type"><a href="language.types.void.html" class="type void">void</a></span></span></div> - <div class="methodsynopsis dc-description"><span class="methodname"><strong>SplDoublyLinkedList::offsetExists</strong></span>(<span class="methodparam"><span class="type"><a href="language.types.declarations.html#language.types.declarations.mixed" class="type mixed">mixed</a></span> <code class="parameter">$index</code></span>): <span class="type">bool</span></div> + <div class="methodsynopsis dc-description"><span class="methodname"><strong>SplDoublyLinkedList::offsetExists</strong></span>(<span class="methodparam"><span class="type"><a href="language.types.mixed.html" class="type mixed">mixed</a></span> <code class="parameter">$index</code></span>): <span class="type"><a href="language.types.boolean.html" class="type bool">bool</a></span></div> - <div class="methodsynopsis dc-description"><span class="methodname"><strong>SplDoublyLinkedList::offsetGet</strong></span>(<span class="methodparam"><span class="type"><a href="language.types.declarations.html#language.types.declarations.mixed" class="type mixed">mixed</a></span> <code class="parameter">$index</code></span>): <span class="type"><a href="language.types.declarations.html#language.types.declarations.mixed" class="type mixed">mixed</a></span></div> + <div class="methodsynopsis dc-description"><span class="methodname"><strong>SplDoublyLinkedList::offsetGet</strong></span>(<span class="methodparam"><span class="type"><a href="language.types.mixed.html" class="type mixed">mixed</a></span> <code class="parameter">$index</code></span>): <span class="type"><a href="language.types.mixed.html" class="type mixed">mixed</a></span></div> }</div> </div> </div> </div> + + diff --git a/tests/php/data/type_rendering_constructorsynopsis_parameters-and-return-type.xml b/tests/php/data/type_rendering_constructorsynopsis_parameters-and-return-type.xml new file mode 100644 index 000000000..2d531928b --- /dev/null +++ b/tests/php/data/type_rendering_constructorsynopsis_parameters-and-return-type.xml @@ -0,0 +1,94 @@ +<?xml version="1.0" encoding="utf-8"?> +<chapter xml:id="type-rendering-constructorsynopsis-parameters-and-return-type"> + + <section> + <para>1. Constructor with no parameters, no return type</para> + <constructorsynopsis> + <modifier>final</modifier> <modifier>public</modifier> <methodname>ClassName::__construct</methodname> + </constructorsynopsis> + </section> + + <section> + <para>2. Constructor with no parameters, void (element) return type</para> + <constructorsynopsis> + <modifier>final</modifier> <modifier>public</modifier> <methodname>ClassName::__construct</methodname> + <void/> + </constructorsynopsis> + </section> + + <section> + <para>3. Constructor with one parameter</para> + <constructorsynopsis> + <modifier>final</modifier> <modifier>private</modifier> <methodname>ClassName::__construct</methodname> + <methodparam><type>mixed</type><parameter>anything</parameter></methodparam> + </constructorsynopsis> + </section> + + <section> + <para>4. Constructor with optional parameter</para> + <constructorsynopsis> + <modifier>final</modifier> <modifier>protected</modifier> <methodname>ClassName::__construct</methodname> + <methodparam choice="opt"><type>int</type><parameter>count</parameter><initializer>0</initializer></methodparam> + </constructorsynopsis> + </section> + + <section> + <para>5. Constructor with nullable parameter</para> + <constructorsynopsis> + <modifier>final</modifier> <modifier>public</modifier> <methodname>ClassName::__construct</methodname> + <methodparam><type class="union"><type>float</type><type>null</type></type><parameter>value</parameter></methodparam> + </constructorsynopsis> + </section> + + <section> + <para>6. Constructor with nullable optional parameter</para> + <constructorsynopsis> + <modifier>final</modifier> <modifier>private</modifier> <methodname>ClassName::__construct</methodname> + <methodparam choice="opt"><type class="union"><type>string</type><type>null</type></type><parameter>options</parameter><initializer>""</initializer></methodparam> + </constructorsynopsis> + </section> + + <section> + <para>7. Constructor with reference parameter</para> + <constructorsynopsis> + <modifier>final</modifier> <modifier>protected</modifier> <methodname>ClassName::__construct</methodname> + <methodparam><type>array</type><parameter role="reference">reference</parameter></methodparam> + </constructorsynopsis> + </section> + + <section> + <para>8. Constructor with union type parameter</para> + <constructorsynopsis> + <modifier>final</modifier> <modifier>public</modifier> <methodname>ClassName::__construct</methodname> + <methodparam><type class="union"><type>iterable</type><type>resource</type><type>callable</type><type>null</type></type><parameter>option</parameter></methodparam> + </constructorsynopsis> + </section> + + <section> + <para>9. Constructor with intersection type parameter</para> + <constructorsynopsis> + <modifier>final</modifier> <modifier>public</modifier> <methodname>ClassName::__construct</methodname> + <methodparam><type class="intersection"><type>Countable</type><type>Traversable</type></type><parameter>option</parameter></methodparam> + </constructorsynopsis> + </section> + + <section> + <para>10. Constructor with DNF (Disjunctive Normal Form) type parameter</para> + <constructorsynopsis> + <modifier>final</modifier> <modifier>public</modifier> <methodname>ClassName::__construct</methodname> + <methodparam><type class="union"><type class="intersection"><type>Countable</type><type>Traversable</type></type><type>DOMAttr</type></type><parameter>option</parameter></methodparam> + </constructorsynopsis> + </section> + + <section> + <para>11. Constructor with more than three parameters</para> + <constructorsynopsis> + <modifier>final</modifier> <modifier>private</modifier> <methodname>ClassName::__construct</methodname> + <methodparam><type>int</type><parameter>count</parameter></methodparam> + <methodparam><type>string</type><parameter>name</parameter></methodparam> + <methodparam><type>bool</type><parameter>isSomething</parameter></methodparam> + <methodparam><type>array</type><parameter>list</parameter></methodparam> + </constructorsynopsis> + </section> + +</chapter> diff --git a/tests/php/data/type_rendering_methodsynopsis_parameters.xml b/tests/php/data/type_rendering_methodsynopsis_parameters.xml new file mode 100644 index 000000000..f2912f1f3 --- /dev/null +++ b/tests/php/data/type_rendering_methodsynopsis_parameters.xml @@ -0,0 +1,86 @@ +<?xml version="1.0" encoding="utf-8"?> +<chapter xml:id="type-rendering-methodsynopsis-parameters"> + + <section> + <para>1. Function/method with no parameters</para> + <methodsynopsis> + <methodname>function_name</methodname> + </methodsynopsis> + </section> + + <section> + <para>2. Function/method with one parameter</para> + <methodsynopsis> + <methodname>function_name</methodname> + <methodparam><type>mixed</type><parameter>anything</parameter></methodparam> + </methodsynopsis> + </section> + + <section> + <para>3. Function/method with optional parameter</para> + <methodsynopsis> + <methodname>function_name</methodname> + <methodparam choice="opt"><type>int</type><parameter>count</parameter><initializer>0</initializer></methodparam> + </methodsynopsis> + </section> + + <section> + <para>4. Function/method with nullable parameter</para> + <methodsynopsis> + <methodname>function_name</methodname> + <methodparam><type class="union"><type>float</type><type>null</type></type><parameter>value</parameter></methodparam> + </methodsynopsis> + </section> + + <section> + <para>5. Function/method with nullable optional parameter</para> + <methodsynopsis> + <methodname>function_name</methodname> + <methodparam choice="opt"><type class="union"><type>string</type><type>null</type></type><parameter>options</parameter><initializer>""</initializer></methodparam> + </methodsynopsis> + </section> + + <section> + <para>6. Function/method with reference parameter</para> + <methodsynopsis> + <methodname>function_name</methodname> + <methodparam><type>array</type><parameter role="reference">reference</parameter></methodparam> + </methodsynopsis> + </section> + + <section> + <para>7. Function/method with union type parameter</para> + <methodsynopsis> + <methodname>function_name</methodname> + <methodparam><type class="union"><type>iterable</type><type>resource</type><type>callable</type><type>null</type></type><parameter>option</parameter></methodparam> + </methodsynopsis> + </section> + + <section> + <para>8. Function/method with intersection type parameter</para> + <methodsynopsis> + <methodname>function_name</methodname> + <methodparam><type class="intersection"><type>Countable</type><type>Traversable</type></type><parameter>option</parameter></methodparam> + </methodsynopsis> + </section> + + <section> + <para>9. Function/method with DNF (Disjunctive Normal Form) type parameter</para> + <methodsynopsis> + <methodname>function_name</methodname> + <methodparam><type class="union"><type class="intersection"><type>Countable</type><type>Traversable</type></type><type>DOMAttr</type></type><parameter>option</parameter></methodparam> + </methodsynopsis> + </section> + + <section> + <para>10. Function/method with more than three parameters</para> + <methodsynopsis> + <methodname>function_name</methodname> + <methodparam><type>int</type><parameter>count</parameter></methodparam> + <methodparam><type>string</type><parameter>name</parameter></methodparam> + <methodparam><type>bool</type><parameter>isSomething</parameter></methodparam> + <methodparam><type>array</type><parameter>list</parameter></methodparam> + </methodsynopsis> + </section> + +</chapter> diff --git a/tests/php/data/type_rendering_methodsynopsis_return_types.xml b/tests/php/data/type_rendering_methodsynopsis_return_types.xml new file mode 100644 index 000000000..cc973a88f --- /dev/null +++ b/tests/php/data/type_rendering_methodsynopsis_return_types.xml @@ -0,0 +1,75 @@ +<?xml version="1.0" encoding="utf-8"?> +<chapter xml:id="type-rendering-methodsynopsis-return-types"> + + <section> + <para>1. Function/method with no return type</para> + <methodsynopsis> + <methodname>function_name</methodname> + </methodsynopsis> + </section> + + <section> + <para>2. Function/method with one return type - never</para> + <methodsynopsis> + <type>never</type><methodname>function_name</methodname> + </methodsynopsis> + </section> + + <section> + <para>3. Function/method with one return type - void</para> + <methodsynopsis> + <type>void</type><methodname>function_name</methodname> + </methodsynopsis> + </section> + + <section> + <para>4. Function/method with one return type - void element</para> + <methodsynopsis> + <methodname>function_name</methodname> + <void/> + </methodsynopsis> + </section> + + <section> + <para>5. Function/method with one return type - mixed</para> + <methodsynopsis> + <type>mixed</type><methodname>function_name</methodname> + </methodsynopsis> + </section> + + <section> + <para>6. Function/method with union return type</para> + <methodsynopsis> + <type class="union"><type>int</type><type>float</type><type>false</type></type><methodname>function_name</methodname> + </methodsynopsis> + </section> + + <section> + <para>7. Function/method with nullable return type</para> + <methodsynopsis> + <type class="union"><type>object</type><type>null</type></type><methodname>function_name</methodname> + </methodsynopsis> + </section> + + <section> + <para>8. Function/method with nullable union return type</para> + <methodsynopsis> + <type class="union"><type>string</type><type>array</type><type>resource</type><type>callable</type><type>iterable</type><type>true</type><type>null</type></type><methodname>function_name</methodname> + </methodsynopsis> + </section> + + <section> + <para>9. Function/method with unknown return type</para> + <methodsynopsis> + <type>UnknownType</type><methodname>function_name</methodname> + </methodsynopsis> + </section> +<!-- TODO: fix known class return type - need to add a class to the index + <section role="description"> + <para>10. Function/method with known class return type</para> + <methodsynopsis> + <type>stdClass</type><methodname>function_name</methodname> + </methodsynopsis> + </section> +--> +</chapter> diff --git a/tests/php/type_rendering_001.phpt b/tests/php/type_rendering_001.phpt new file mode 100644 index 000000000..3e0d2545e --- /dev/null +++ b/tests/php/type_rendering_001.phpt @@ -0,0 +1,94 @@ +--TEST-- +Type rendering 001 - Methodsynopsis return types +--FILE-- +<?php +namespace phpdotnet\phd; + +require_once __DIR__ . "/../setup.php"; +require_once __DIR__ . "/TestChunkedXHTML.php"; + +$formatclass = "TestChunkedXHTML"; +$xml_file = __DIR__ . "/data/type_rendering_methodsynopsis_return_types.xml"; + +$opts = array( + "index" => true, + "xml_root" => dirname($xml_file), + "xml_file" => $xml_file, + "output_dir" => __DIR__ . "/output/", +); + +$extra = array( + "lang_dir" => __PHDDIR__ . "phpdotnet/phd/data/langs/", + "phpweb_version_filename" => dirname($xml_file) . '/version.xml', + "phpweb_acronym_filename" => dirname($xml_file) . '/acronyms.xml', +); + +$render = new TestRender($formatclass, $opts, $extra); + +if (Index::requireIndexing() && !file_exists($opts["output_dir"])) { + mkdir($opts["output_dir"], 0755); +} + +$render->run(); +?> +--EXPECT-- +Filename: type-rendering-methodsynopsis-return-types.html +Content: +<div id="type-rendering-methodsynopsis-return-types" class="chapter"> + + <div class="section"> + <p class="para">1. Function/method with no return type</p> + <div class="methodsynopsis dc-description"> + <span class="methodname"><strong>function_name</strong></span>()</div> + + </div> + + <div class="section"> + <p class="para">2. Function/method with one return type - never</p> + <div class="methodsynopsis dc-description"><span class="methodname"><strong>function_name</strong></span>(): <span class="type"><a href="language.types.never.html" class="type never">never</a></span></div> + + </div> + + <div class="section"> + <p class="para">3. Function/method with one return type - void</p> + <div class="methodsynopsis dc-description"><span class="methodname"><strong>function_name</strong></span>(): <span class="type"><a href="language.types.void.html" class="type void">void</a></span></div> + + </div> + + <div class="section"> + <p class="para">4. Function/method with one return type - void element</p> + <div class="methodsynopsis dc-description"><span class="methodname"><strong>function_name</strong></span>(): <span class="type"><a href="language.types.void.html" class="type void">void</a></span></div> + + </div> + + <div class="section"> + <p class="para">5. Function/method with one return type - mixed</p> + <div class="methodsynopsis dc-description"><span class="methodname"><strong>function_name</strong></span>(): <span class="type"><a href="language.types.mixed.html" class="type mixed">mixed</a></span></div> + + </div> + + <div class="section"> + <p class="para">6. Function/method with union return type</p> + <div class="methodsynopsis dc-description"><span class="methodname"><strong>function_name</strong></span>(): <span class="type"><span class="type"><a href="language.types.integer.html" class="type int">int</a></span>|<span class="type"><a href="language.types.float.html" class="type float">float</a></span>|<span class="type"><a href="language.types.value.html" class="type false">false</a></span></span></div> + + </div> + + <div class="section"> + <p class="para">7. Function/method with nullable return type</p> + <div class="methodsynopsis dc-description"><span class="methodname"><strong>function_name</strong></span>(): <span class="type"><span class="type"><a href="language.types.null.html" class="type null">?</a></span><span class="type"><a href="language.types.object.html" class="type object">object</a></span></span></div> + + </div> + + <div class="section"> + <p class="para">8. Function/method with nullable union return type</p> + <div class="methodsynopsis dc-description"><span class="methodname"><strong>function_name</strong></span>(): <span class="type"><span class="type"><a href="language.types.string.html" class="type string">string</a></span>|<span class="type"><a href="language.types.array.html" class="type array">array</a></span>|<span class="type"><a href="language.types.resource.html" class="type resource">resource</a></span>|<span class="type"><a href="language.types.callable.html" class="type callable">callable</a></span>|<span class="type"><a href="language.types.iterable.html" class="type iterable">iterable</a></span>|<span class="type"><a href="language.types.value.html" class="type true">true</a></span>|<span class="type"><a href="language.types.null.html" class="type null">null</a></span></span></div> + + </div> + + <div class="section"> + <p class="para">9. Function/method with unknown return type</p> + <div class="methodsynopsis dc-description"><span class="methodname"><strong>function_name</strong></span>(): <span class="type">UnknownType</span></div> + + </div> + +</div> diff --git a/tests/php/type_rendering_002.phpt b/tests/php/type_rendering_002.phpt new file mode 100644 index 000000000..e44a1c80a --- /dev/null +++ b/tests/php/type_rendering_002.phpt @@ -0,0 +1,100 @@ +--TEST-- +Type rendering 002 - Methodsynopsis parameters and parameter types +--FILE-- +<?php +namespace phpdotnet\phd; + +require_once __DIR__ . "/../setup.php"; +require_once __DIR__ . "/TestChunkedXHTML.php"; + +$formatclass = "TestChunkedXHTML"; +$xml_file = __DIR__ . "/data/type_rendering_methodsynopsis_parameters.xml"; + +$opts = array( + "index" => true, + "xml_root" => dirname($xml_file), + "xml_file" => $xml_file, + "output_dir" => __DIR__ . "/output/", +); + +$extra = array( + "lang_dir" => __PHDDIR__ . "phpdotnet/phd/data/langs/", + "phpweb_version_filename" => dirname($xml_file) . '/version.xml', + "phpweb_acronym_filename" => dirname($xml_file) . '/acronyms.xml', +); + +$render = new TestRender($formatclass, $opts, $extra); + +if (Index::requireIndexing() && !file_exists($opts["output_dir"])) { + mkdir($opts["output_dir"], 0755); +} + +$render->run(); +?> +--EXPECT-- +Filename: type-rendering-methodsynopsis-parameters.html +Content: +<div id="type-rendering-methodsynopsis-parameters" class="chapter"> + + <div class="section"> + <p class="para">1. Function/method with no parameters</p> + <div class="methodsynopsis dc-description"> + <span class="methodname"><strong>function_name</strong></span>()</div> + + </div> + + <div class="section"> + <p class="para">2. Function/method with one parameter</p> + <div class="methodsynopsis dc-description"><span class="methodname"><strong>function_name</strong></span>(<span class="methodparam"><span class="type"><a href="language.types.mixed.html" class="type mixed">mixed</a></span> <code class="parameter">$anything</code></span>)</div> + + </div> + + <div class="section"> + <p class="para">3. Function/method with optional parameter</p> + <div class="methodsynopsis dc-description"><span class="methodname"><strong>function_name</strong></span>(<span class="methodparam"><span class="type"><a href="language.types.integer.html" class="type int">int</a></span> <code class="parameter">$count</code><span class="initializer"> = 0</span></span>)</div> + + </div> + + <div class="section"> + <p class="para">4. Function/method with nullable parameter</p> + <div class="methodsynopsis dc-description"><span class="methodname"><strong>function_name</strong></span>(<span class="methodparam"><span class="type"><span class="type"><a href="language.types.null.html" class="type null">?</a></span><span class="type"><a href="language.types.float.html" class="type float">float</a></span></span> <code class="parameter">$value</code></span>)</div> + + </div> + + <div class="section"> + <p class="para">5. Function/method with nullable optional parameter</p> + <div class="methodsynopsis dc-description"><span class="methodname"><strong>function_name</strong></span>(<span class="methodparam"><span class="type"><span class="type"><a href="language.types.null.html" class="type null">?</a></span><span class="type"><a href="language.types.string.html" class="type string">string</a></span></span> <code class="parameter">$options</code><span class="initializer"> = ""</span></span>)</div> + + </div> + + <div class="section"> + <p class="para">6. Function/method with reference parameter</p> + <div class="methodsynopsis dc-description"><span class="methodname"><strong>function_name</strong></span>(<span class="methodparam"><span class="type"><a href="language.types.array.html" class="type array">array</a></span> <code class="parameter reference">&$reference</code></span>)</div> + + </div> + + <div class="section"> + <p class="para">7. Function/method with union type parameter</p> + <div class="methodsynopsis dc-description"><span class="methodname"><strong>function_name</strong></span>(<span class="methodparam"><span class="type"><span class="type"><a href="language.types.iterable.html" class="type iterable">iterable</a></span>|<span class="type"><a href="language.types.resource.html" class="type resource">resource</a></span>|<span class="type"><a href="language.types.callable.html" class="type callable">callable</a></span>|<span class="type"><a href="language.types.null.html" class="type null">null</a></span></span> <code class="parameter">$option</code></span>)</div> + + </div> + + <div class="section"> + <p class="para">8. Function/method with intersection type parameter</p> + <div class="methodsynopsis dc-description"><span class="methodname"><strong>function_name</strong></span>(<span class="methodparam"><span class="type"><span class="type">Countable</span>&<span class="type">Traversable</span></span> <code class="parameter">$option</code></span>)</div> + + </div> + + <div class="section"> + <p class="para">9. Function/method with DNF (Disjunctive Normal Form) type parameter</p> + <div class="methodsynopsis dc-description"><span class="methodname"><strong>function_name</strong></span>(<span class="methodparam"><span class="type">(<span class="type">Countable</span>&<span class="type">Traversable</span>)|<span class="type">DOMAttr</span></span> <code class="parameter">$option</code></span>)</div> + + </div> + + <div class="section"> + <p class="para">10. Function/method with more than three parameters</p> + <div class="methodsynopsis dc-description"><span class="methodname"><strong>function_name</strong></span>(<br> <span class="methodparam"><span class="type"><a href="language.types.integer.html" class="type int">int</a></span> <code class="parameter">$count</code></span>,<br> <span class="methodparam"><span class="type"><a href="language.types.string.html" class="type string">string</a></span> <code class="parameter">$name</code></span>,<br> <span class="methodparam"><span class="type"><a href="language.types.boolean.html" class="type bool">bool</a></span> <code class="parameter">$isSomething</code></span>,<br> <span class="methodparam"><span class="type"><a href="language.types.array.html" class="type array">array</a></span> <code class="parameter">$list</code></span><br>)</div> + + </div> + +</div> diff --git a/tests/php/type_rendering_003.phpt b/tests/php/type_rendering_003.phpt new file mode 100644 index 000000000..03a30c7d4 --- /dev/null +++ b/tests/php/type_rendering_003.phpt @@ -0,0 +1,106 @@ +--TEST-- +Type rendering 003 - Constructorsynopsis parameters and parameter types +--FILE-- +<?php +namespace phpdotnet\phd; + +require_once __DIR__ . "/../setup.php"; +require_once __DIR__ . "/TestChunkedXHTML.php"; + +$formatclass = "TestChunkedXHTML"; +$xml_file = __DIR__ . "/data/type_rendering_constructorsynopsis_parameters-and-return-type.xml"; + +$opts = array( + "index" => true, + "xml_root" => dirname($xml_file), + "xml_file" => $xml_file, + "output_dir" => __DIR__ . "/output/", +); + +$extra = array( + "lang_dir" => __PHDDIR__ . "phpdotnet/phd/data/langs/", + "phpweb_version_filename" => dirname($xml_file) . '/version.xml', + "phpweb_acronym_filename" => dirname($xml_file) . '/acronyms.xml', +); + +$render = new TestRender($formatclass, $opts, $extra); + +if (Index::requireIndexing() && !file_exists($opts["output_dir"])) { + mkdir($opts["output_dir"], 0755); +} + +$render->run(); +?> +--EXPECT-- +Filename: type-rendering-constructorsynopsis-parameters-and-return-type.html +Content: +<div id="type-rendering-constructorsynopsis-parameters-and-return-type" class="chapter"> + + <div class="section"> + <p class="para">1. Constructor with no parameters, no return type</p> + <div class="constructorsynopsis dc-description"> + <span class="modifier">final</span> <span class="modifier">public</span> <span class="methodname"><strong>ClassName::__construct</strong></span>()</div> + + </div> + + <div class="section"> + <p class="para">2. Constructor with no parameters, void (element) return type</p> + <div class="constructorsynopsis dc-description"><span class="modifier">final</span> <span class="modifier">public</span> <span class="methodname"><strong>ClassName::__construct</strong></span>(): <span class="type"><a href="language.types.void.html" class="type void">void</a></span></div> + + </div> + + <div class="section"> + <p class="para">3. Constructor with one parameter</p> + <div class="constructorsynopsis dc-description"><span class="modifier">final</span> <span class="modifier">private</span> <span class="methodname"><strong>ClassName::__construct</strong></span>(<span class="methodparam"><span class="type"><a href="language.types.mixed.html" class="type mixed">mixed</a></span> <code class="parameter">$anything</code></span>)</div> + + </div> + + <div class="section"> + <p class="para">4. Constructor with optional parameter</p> + <div class="constructorsynopsis dc-description"><span class="modifier">final</span> <span class="modifier">protected</span> <span class="methodname"><strong>ClassName::__construct</strong></span>(<span class="methodparam"><span class="type"><a href="language.types.integer.html" class="type int">int</a></span> <code class="parameter">$count</code><span class="initializer"> = 0</span></span>)</div> + + </div> + + <div class="section"> + <p class="para">5. Constructor with nullable parameter</p> + <div class="constructorsynopsis dc-description"><span class="modifier">final</span> <span class="modifier">public</span> <span class="methodname"><strong>ClassName::__construct</strong></span>(<span class="methodparam"><span class="type"><span class="type"><a href="language.types.null.html" class="type null">?</a></span><span class="type"><a href="language.types.float.html" class="type float">float</a></span></span> <code class="parameter">$value</code></span>)</div> + + </div> + + <div class="section"> + <p class="para">6. Constructor with nullable optional parameter</p> + <div class="constructorsynopsis dc-description"><span class="modifier">final</span> <span class="modifier">private</span> <span class="methodname"><strong>ClassName::__construct</strong></span>(<span class="methodparam"><span class="type"><span class="type"><a href="language.types.null.html" class="type null">?</a></span><span class="type"><a href="language.types.string.html" class="type string">string</a></span></span> <code class="parameter">$options</code><span class="initializer"> = ""</span></span>)</div> + + </div> + + <div class="section"> + <p class="para">7. Constructor with reference parameter</p> + <div class="constructorsynopsis dc-description"><span class="modifier">final</span> <span class="modifier">protected</span> <span class="methodname"><strong>ClassName::__construct</strong></span>(<span class="methodparam"><span class="type"><a href="language.types.array.html" class="type array">array</a></span> <code class="parameter reference">&$reference</code></span>)</div> + + </div> + + <div class="section"> + <p class="para">8. Constructor with union type parameter</p> + <div class="constructorsynopsis dc-description"><span class="modifier">final</span> <span class="modifier">public</span> <span class="methodname"><strong>ClassName::__construct</strong></span>(<span class="methodparam"><span class="type"><span class="type"><a href="language.types.iterable.html" class="type iterable">iterable</a></span>|<span class="type"><a href="language.types.resource.html" class="type resource">resource</a></span>|<span class="type"><a href="language.types.callable.html" class="type callable">callable</a></span>|<span class="type"><a href="language.types.null.html" class="type null">null</a></span></span> <code class="parameter">$option</code></span>)</div> + + </div> + + <div class="section"> + <p class="para">9. Constructor with intersection type parameter</p> + <div class="constructorsynopsis dc-description"><span class="modifier">final</span> <span class="modifier">public</span> <span class="methodname"><strong>ClassName::__construct</strong></span>(<span class="methodparam"><span class="type"><span class="type">Countable</span>&<span class="type">Traversable</span></span> <code class="parameter">$option</code></span>)</div> + + </div> + + <div class="section"> + <p class="para">10. Constructor with DNF (Disjunctive Normal Form) type parameter</p> + <div class="constructorsynopsis dc-description"><span class="modifier">final</span> <span class="modifier">public</span> <span class="methodname"><strong>ClassName::__construct</strong></span>(<span class="methodparam"><span class="type">(<span class="type">Countable</span>&<span class="type">Traversable</span>)|<span class="type">DOMAttr</span></span> <code class="parameter">$option</code></span>)</div> + + </div> + + <div class="section"> + <p class="para">11. Constructor with more than three parameters</p> + <div class="constructorsynopsis dc-description"><span class="modifier">final</span> <span class="modifier">private</span> <span class="methodname"><strong>ClassName::__construct</strong></span>(<br> <span class="methodparam"><span class="type"><a href="language.types.integer.html" class="type int">int</a></span> <code class="parameter">$count</code></span>,<br> <span class="methodparam"><span class="type"><a href="language.types.string.html" class="type string">string</a></span> <code class="parameter">$name</code></span>,<br> <span class="methodparam"><span class="type"><a href="language.types.boolean.html" class="type bool">bool</a></span> <code class="parameter">$isSomething</code></span>,<br> <span class="methodparam"><span class="type"><a href="language.types.array.html" class="type array">array</a></span> <code class="parameter">$list</code></span><br>)</div> + + </div> + +</div>