Skip to content

Commit

Permalink
Add support for intersection and DNF types
Browse files Browse the repository at this point in the history
  • Loading branch information
haszi committed Feb 15, 2024
1 parent 7f12e72 commit 2aa363f
Show file tree
Hide file tree
Showing 6 changed files with 135 additions and 28 deletions.
5 changes: 3 additions & 2 deletions phpdotnet/phd/Package/Generic/XHTML.php
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
90 changes: 70 additions & 20 deletions phpdotnet/phd/Package/PHP/XHTML.php
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down Expand Up @@ -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(
Expand Down Expand Up @@ -176,16 +186,17 @@ 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(),
),
);

/** @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 "&amp;" */
private $type_separator = [];

/** @var bool|null Decides whether the union type can be displayed by using "?" */
private $simple_nullable = null;
Expand Down Expand Up @@ -356,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" => "&amp;",
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++;
Expand All @@ -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 .= '</span>';
Expand All @@ -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" => "&amp;",
};
}
} 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 "";
Expand Down Expand Up @@ -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[] = '<span class="type">' . $formatted_type .'</span>';
}
Expand All @@ -543,7 +571,17 @@ private function format_types($type_separator, $paramOrReturnType) {
}
}

$type = implode($this->type_separator ?? '', $types);
$type = "";
$isDnfType = (in_array("&amp;", $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] === "&amp;" && $previousSeparator !== "&amp;") ? "(" : "";
$closingParenthesis = ($isDnfType && $type_separators[$i] !== "&amp;" && $previousSeparator === "&amp;") ? ")" : "";

$type .= $openingParenthesis . $types[$i] . $closingParenthesis . $type_separators[$i];
}
$type = rtrim($type, end($type_separators));

if (count($types) > 1) {
$type = '<span class="type">' . $type . '</span>';
}
Expand All @@ -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 "";
}
Expand Down Expand Up @@ -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" => "&amp;",
};
}
} 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 "";
}
Expand Down Expand Up @@ -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);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,23 @@
</section>

<section>
<para>9. Constructor with more than three parameters</para>
<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>
Expand Down
18 changes: 17 additions & 1 deletion tests/php/data/type_rendering_methodsynopsis_parameters.xml
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,23 @@
</section>

<section>
<para>8. Function/method with more than three parameters</para>
<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>
Expand Down
16 changes: 14 additions & 2 deletions tests/php/type_rendering_002.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -80,9 +80,21 @@ Content:
</div>

<div class="section">
<p class="para">8. Function/method with more than three parameters</p>
<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>&amp;<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>&amp;<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>&nbsp;&nbsp;&nbsp;&nbsp;<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>&nbsp;&nbsp;&nbsp;&nbsp;<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>&nbsp;&nbsp;&nbsp;&nbsp;<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>&nbsp;&nbsp;&nbsp;&nbsp;<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>
</div>
16 changes: 14 additions & 2 deletions tests/php/type_rendering_003.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,21 @@ Content:
</div>

<div class="section">
<p class="para">9. Constructor with more than three parameters</p>
<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>&amp;<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>&amp;<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>&nbsp;&nbsp;&nbsp;&nbsp;<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>&nbsp;&nbsp;&nbsp;&nbsp;<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>&nbsp;&nbsp;&nbsp;&nbsp;<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>&nbsp;&nbsp;&nbsp;&nbsp;<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>
</div>

0 comments on commit 2aa363f

Please sign in to comment.