diff --git a/phpdotnet/phd/Package/Generic/XHTML.php b/phpdotnet/phd/Package/Generic/XHTML.php index a9800ec4..9e6d64bb 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, diff --git a/phpdotnet/phd/Package/PHP/XHTML.php b/phpdotnet/phd/Package/PHP/XHTML.php index ca277857..f1cc5e3b 100644 --- a/phpdotnet/phd/Package/PHP/XHTML.php +++ b/phpdotnet/phd/Package/PHP/XHTML.php @@ -78,8 +78,13 @@ abstract class Package_PHP_XHTML extends Package_Generic_XHTML { 'methodparam' => 'format_type_methodparam', 'type' => array( /* DEFAULT */ 'format_type', - 'methodsynopsis' => 'format_suppressed_tags', - 'methodparam' => '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( @@ -136,6 +141,11 @@ abstract class Package_PHP_XHTML extends Package_Generic_XHTML { /* 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( @@ -176,7 +186,8 @@ abstract class Package_PHP_XHTML extends Package_Generic_XHTML { "alternatives" => array(), "refsynopsisdiv" => null, "methodparam" => array( - "type_separator" => "", + "type_separator" => array(), + "type_separator_stack" => array(), "paramtypes" => array(), ), ); @@ -184,8 +195,8 @@ abstract class Package_PHP_XHTML extends Package_Generic_XHTML { /** @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 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; @@ -356,14 +367,19 @@ public function format_type($open, $tag, $attrs, $props) { strpos($props["innerXml"], 'null') !== false ) { $this->simple_nullable = true; - $this->type_separator = ""; + $this->type_separator[] = ""; $retval .= '?'; } 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++; @@ -373,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 .= ''; @@ -382,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 ""; @@ -514,17 +543,16 @@ public function format_methodsynopsis($open, $name, $attrs, $props) { return $content; } - private function format_types($type_separator, $paramOrReturnType) { + private function format_types($type_separators, $paramOrReturnType) { $types = []; - $this->type_separator = $type_separator; if ( - $this->type_separator === "|" && + $type_separators[0] === "|" && count($paramOrReturnType) === 2 && in_array("null", $paramOrReturnType, true) ) { $this->simple_nullable = true; - $this->type_separator = ""; + $type_separators[0] = ""; $formatted_type = self::format_type_text("?", "type"); $types[] = '' . $formatted_type .''; } @@ -543,7 +571,17 @@ private function format_types($type_separator, $paramOrReturnType) { } } - $type = implode($this->type_separator ?? '', $types); + $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)); + if (count($types) > 1) { $type = '' . $type . ''; } @@ -554,6 +592,7 @@ private function format_types($type_separator, $paramOrReturnType) { 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 ""; } @@ -588,19 +627,29 @@ public function format_methodparam($open, $name, $attrs) { public function format_type_methodparam($open, $tag, $attrs) { if ($open) { - $this->cchunk["methodparam"] = $this->dchunk["methodparam"]; if (isset($attrs[Reader::XMLNS_DOCBOOK]["class"])) { - $this->cchunk["methodparam"]["type_separator"] = match ($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 ""; } @@ -667,6 +716,7 @@ public function format_type_text($type, $tagname) { 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 parent::format_void($open, $name, $attrs, $props); 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 index 7e89a014..2d531928 100644 --- a/tests/php/data/type_rendering_constructorsynopsis_parameters-and-return-type.xml +++ b/tests/php/data/type_rendering_constructorsynopsis_parameters-and-return-type.xml @@ -65,7 +65,23 @@
- 9. Constructor with more than three parameters + 9. Constructor with intersection type parameter + + final public ClassName::__construct + CountableTraversableoption + +
+ +
+ 10. Constructor with DNF (Disjunctive Normal Form) type parameter + + final public ClassName::__construct + CountableTraversableDOMAttroption + +
+ +
+ 11. Constructor with more than three parameters final private ClassName::__construct intcount diff --git a/tests/php/data/type_rendering_methodsynopsis_parameters.xml b/tests/php/data/type_rendering_methodsynopsis_parameters.xml index 42d57ad1..f2912f1f 100644 --- a/tests/php/data/type_rendering_methodsynopsis_parameters.xml +++ b/tests/php/data/type_rendering_methodsynopsis_parameters.xml @@ -57,7 +57,23 @@
- 8. Function/method with more than three parameters + 8. Function/method with intersection type parameter + + function_name + CountableTraversableoption + +
+ +
+ 9. Function/method with DNF (Disjunctive Normal Form) type parameter + + function_name + CountableTraversableDOMAttroption + +
+ +
+ 10. Function/method with more than three parameters function_name intcount diff --git a/tests/php/type_rendering_002.phpt b/tests/php/type_rendering_002.phpt index 424141d3..5ef17104 100644 --- a/tests/php/type_rendering_002.phpt +++ b/tests/php/type_rendering_002.phpt @@ -80,9 +80,21 @@ Content:
-

8. Function/method with more than three parameters

+

8. Function/method with intersection type parameter

+
function_name(Countable&Traversable $option)
+ +
+ +
+

9. Function/method with DNF (Disjunctive Normal Form) type parameter

+
function_name((Countable&Traversable)|DOMAttr $option)
+ +
+ +
+

10. Function/method with more than three parameters

function_name(
    int $count,
    string $name,
    bool $isSomething,
    array $list
)
- + \ No newline at end of file diff --git a/tests/php/type_rendering_003.phpt b/tests/php/type_rendering_003.phpt index 4e0b1fc4..a219094d 100644 --- a/tests/php/type_rendering_003.phpt +++ b/tests/php/type_rendering_003.phpt @@ -86,9 +86,21 @@ Content:
-

9. Constructor with more than three parameters

+

9. Constructor with intersection type parameter

+
final public ClassName::__construct(Countable&Traversable $option)
+ +
+ +
+

10. Constructor with DNF (Disjunctive Normal Form) type parameter

+
final public ClassName::__construct((Countable&Traversable)|DOMAttr $option)
+ +
+ +
+

11. Constructor with more than three parameters

final private ClassName::__construct(
    int $count,
    string $name,
    bool $isSomething,
    array $list
)
- + \ No newline at end of file