Skip to content

Commit

Permalink
PhpdocTo(Param|Property|Return)TypeFixer - fix for type intersections
Browse files Browse the repository at this point in the history
  • Loading branch information
kubawerlos authored and SpacePossum committed Dec 21, 2021
1 parent 1f4f55a commit 6bf7ba5
Show file tree
Hide file tree
Showing 7 changed files with 54 additions and 13 deletions.
10 changes: 3 additions & 7 deletions src/DocBlock/TypeExpression.php
Expand Up @@ -29,7 +29,7 @@ final class TypeExpression
* @internal
*/
public const REGEX_TYPES = '
(?<types> # alternation of several types separated by `|`
(?<types> # several types separated by `|` or `&`
(?<type> # single type
\?? # optionally nullable
(?:
Expand Down Expand Up @@ -88,13 +88,9 @@ final class TypeExpression
[\\\\\w-]++
)
)
(?: # intersection
\h*&\h*
(?&type)
)*
)
(?:
\h*\|\h*
\h*[|&]\h*
(?&type)
)*
)
Expand Down Expand Up @@ -129,7 +125,7 @@ public function __construct(string $value, ?NamespaceAnalysis $namespace, array

$this->types[] = $matches['type'];
$value = Preg::replace(
'/^'.preg_quote($matches['type'], '/').'(\h*\|\h*)?/',
'/^'.preg_quote($matches['type'], '/').'(\h*[|&]\h*)?/',
'',
$value
);
Expand Down
4 changes: 2 additions & 2 deletions src/Fixer/Phpdoc/NoSuperfluousPhpdocTagsFixer.php
Expand Up @@ -386,7 +386,7 @@ private function parseTypeHint(Tokens $tokens, int $index): array
while (true) {
$type = '';

while ($tokens[$index]->isGivenKind([T_NS_SEPARATOR, T_STATIC, T_STRING, CT::T_ARRAY_TYPEHINT, T_CALLABLE, CT::T_TYPE_INTERSECTION])) {
while ($tokens[$index]->isGivenKind([T_NS_SEPARATOR, T_STATIC, T_STRING, CT::T_ARRAY_TYPEHINT, T_CALLABLE])) {
$type .= $tokens[$index]->getContent();
$index = $tokens->getNextMeaningfulToken($index);
}
Expand All @@ -397,7 +397,7 @@ private function parseTypeHint(Tokens $tokens, int $index): array

$types[] = $type;

if (!$tokens[$index]->isGivenKind(CT::T_TYPE_ALTERNATION)) {
if (!$tokens[$index]->isGivenKind([CT::T_TYPE_ALTERNATION, CT::T_TYPE_INTERSECTION])) {
break;
}

Expand Down
4 changes: 2 additions & 2 deletions tests/DocBlock/AnnotationTest.php
Expand Up @@ -382,11 +382,11 @@ public function provideTypeParsingCases(): array
'/** @var class-string<Foo> */',
],
[
['A&B'],
['A', 'B'],
'/** @var A&B */',
],
[
['A & B'],
['A', 'B'],
'/** @var A & B */',
],
[
Expand Down
4 changes: 2 additions & 2 deletions tests/DocBlock/TypeExpressionTest.php
Expand Up @@ -69,8 +69,8 @@ public function provideGetTypesCases(): \Generator
yield ['null|true|false|1|1.5|\'a\'|"b"', ['null', 'true', 'false', '1', '1.5', "'a'", '"b"']];
yield ['int | "a" | A<B<C, D>, E<F::*|G[]>>', ['int', '"a"', 'A<B<C, D>, E<F::*|G[]>>']];
yield ['class-string<Foo>', ['class-string<Foo>']];
yield ['A&B', ['A&B']];
yield ['A & B', ['A & B']];
yield ['A&B', ['A', 'B']];
yield ['A & B', ['A', 'B']];
yield ['array{1: bool, 2: bool}', ['array{1: bool, 2: bool}']];
yield ['array{a: int|string, b?: bool}', ['array{a: int|string, b?: bool}']];
yield ['array{\'a\': "a", "b"?: \'b\'}', ['array{\'a\': "a", "b"?: \'b\'}']];
Expand Down
18 changes: 18 additions & 0 deletions tests/Fixer/FunctionNotation/PhpdocToParamTypeFixerTest.php
Expand Up @@ -416,6 +416,24 @@ function bar() {
}
',
],
'intersection types' => [
'<?php
/** @param Bar&Baz $x */
function bar($x) {}
',
],
'very long class name before ampersand' => [
'<?php
/** @param Baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaar&Baz $x */
function bar($x) {}
',
],
'very long class name after ampersand' => [
'<?php
/** @param Bar&Baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaz $x */
function bar($x) {}
',
],
];
}
}
Expand Up @@ -449,6 +449,15 @@ public abstract function getFoo();
'<?php new class { /** @var int */ private int $foo; };',
'<?php new class { /** @var int */ private $foo; };',
],
'intersection types' => [
'<?php class Foo { /** @var Bar&Baz */ private $x; }',
],
'very long class name before ampersand' => [
'<?php class Foo { /** @var Baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaar&Baz */ private $x; }',
],
'very long class name after ampersand' => [
'<?php class Foo { /** @var Bar&Baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaz */ private $x; }',
],
];
}

Expand Down
18 changes: 18 additions & 0 deletions tests/Fixer/FunctionNotation/PhpdocToReturnTypeFixerTest.php
Expand Up @@ -313,6 +313,24 @@ function my_foo() {}
'<?php /** @return string[]|int[] */ function my_foo(): array {}',
'<?php /** @return string[]|int[] */ function my_foo() {}',
],
'intersection types' => [
'<?php
/** @return Bar&Baz */
function bar() {}
',
],
'very long class name before ampersand' => [
'<?php
/** @return Baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaar&Baz */
function bar() {}
',
],
'very long class name after ampersand' => [
'<?php
/** @return Bar&Baaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaz */
function bar() {}
',
],
];
}

Expand Down

0 comments on commit 6bf7ba5

Please sign in to comment.