Skip to content

Commit

Permalink
bug #6243 PhpdocTypesOrderFixer - fix for intersection types (kubawer…
Browse files Browse the repository at this point in the history
…los)

This PR was merged into the master branch.

Discussion
----------

PhpdocTypesOrderFixer - fix for intersection types

Fixes #6238

Commits
-------

0a19733 PhpdocTypesOrderFixer - fix for intersection types
  • Loading branch information
SpacePossum committed Feb 4, 2022
2 parents b0a9fca + 0a19733 commit 55aec39
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 10 deletions.
2 changes: 1 addition & 1 deletion src/DocBlock/Annotation.php
Expand Up @@ -208,7 +208,7 @@ public function setTypes(array $types): void
{
$pattern = '/'.preg_quote($this->getTypesContent(), '/').'/';

$this->lines[0]->setContent(Preg::replace($pattern, implode('|', $types), $this->lines[0]->getContent(), 1));
$this->lines[0]->setContent(Preg::replace($pattern, implode($this->getTypeExpression()->getTypesGlue(), $types), $this->lines[0]->getContent(), 1));

$this->clearCache();
}
Expand Down
17 changes: 13 additions & 4 deletions src/DocBlock/TypeExpression.php
Expand Up @@ -99,7 +99,7 @@ final class TypeExpression
)
)
(?:
\h*[|&]\h*
\h*(?<glue>[|&])\h*
(?&type)
)*
)
Expand All @@ -120,6 +120,8 @@ final class TypeExpression
*/
private $innerTypeExpressions = [];

private string $typesGlue = '|';

/**
* @var null|NamespaceAnalysis
*/
Expand Down Expand Up @@ -165,15 +167,15 @@ static function (array $type) { return $type['expression']->toString(); },
/**
* @param callable(self $a, self $b): int $compareCallback
*/
public function sortUnionTypes(callable $compareCallback): void
public function sortTypes(callable $compareCallback): void
{
foreach (array_reverse($this->innerTypeExpressions) as [
'start_index' => $startIndex,
'expression' => $inner,
]) {
$initialValueLength = \strlen($inner->toString());

$inner->sortUnionTypes($compareCallback);
$inner->sortTypes($compareCallback);

$this->value = substr_replace(
$this->value,
Expand All @@ -190,10 +192,15 @@ static function (array $type): self { return $type['expression']; },
$compareCallback
);

$this->value = implode('|', $this->getTypes());
$this->value = implode($this->getTypesGlue(), $this->getTypes());
}
}

public function getTypesGlue(): string
{
return $this->typesGlue;
}

public function getCommonType(): ?string
{
$aliases = $this->getAliases();
Expand Down Expand Up @@ -254,6 +261,8 @@ private function parse(): void
return;
}

$this->typesGlue = $matches['glue'] ?? $this->typesGlue;

$index = '' !== $matches['nullable'] ? 1 : 0;

if ($matches['type'] !== $matches['types']) {
Expand Down
2 changes: 1 addition & 1 deletion src/Fixer/Phpdoc/PhpdocTypesOrderFixer.php
Expand Up @@ -170,7 +170,7 @@ private function sortTypes(TypeExpression $typeExpression): array
return Preg::replace('/^\\??\\\?/', '', $type);
};

$typeExpression->sortUnionTypes(
$typeExpression->sortTypes(
function (TypeExpression $a, TypeExpression $b) use ($normalizeType): int {
$a = $normalizeType($a->toString());
$b = $normalizeType($b->toString());
Expand Down
1 change: 1 addition & 0 deletions tests/DocBlock/AnnotationTest.php
Expand Up @@ -473,6 +473,7 @@ public function provideTypesCases(): array
[['RUNTIMEEEEeXCEPTION'], [\Throwable::class], "*\t@throws\t \t RUNTIMEEEEeXCEPTION\t\t\t\t\t\t\t\n\n\n", "*\t@throws\t \t Throwable\t\t\t\t\t\t\t\n\n\n"],
[['RUNTIMEEEEeXCEPTION'], [\Throwable::class], "*@throws\t \t RUNTIMEEEEeXCEPTION\t\t\t\t\t\t\t\n\n\n", "*@throws\t \t Throwable\t\t\t\t\t\t\t\n\n\n"],
[['string'], ['string', 'null'], ' * @method string getString()', ' * @method string|null getString()'],
[['Foo', 'Bar'], ['Bar', 'Foo'], ' * @param Foo&Bar $x', ' * @param Bar&Foo $x'],
];
}

Expand Down
32 changes: 28 additions & 4 deletions tests/DocBlock/TypeExpressionTest.php
Expand Up @@ -86,6 +86,22 @@ public function provideGetTypesCases(): \Generator
yield ['array < int , callable ( string ) : bool >', ['array < int , callable ( string ) : bool >']];
}

/**
* @dataProvider provideGetTypesGlueCases
*/
public function testGetTypesGlue(string $expectedTypesGlue, string $typesExpression): void
{
$expression = new TypeExpression($typesExpression, null, []);
static::assertSame($expectedTypesGlue, $expression->getTypesGlue());
}

public static function provideGetTypesGlueCases(): iterable
{
yield ['|', 'string']; // for backward behaviour
yield ['|', 'bool|string'];
yield ['&', 'Foo&Bar'];
}

/**
* @param NamespaceUseAnalysis[] $namespaceUses
*
Expand Down Expand Up @@ -181,20 +197,20 @@ public function provideAllowsNullCases(): \Generator
}

/**
* @dataProvider provideSortUnionTypesCases
* @dataProvider provideSortTypesCases
*/
public function testSortUnionTypes(string $typesExpression, string $expectResult): void
public function testSortTypes(string $typesExpression, string $expectResult): void
{
$expression = new TypeExpression($typesExpression, null, []);

$expression->sortUnionTypes(static function (TypeExpression $a, TypeExpression $b): int {
$expression->sortTypes(static function (TypeExpression $a, TypeExpression $b): int {
return strcasecmp($a->toString(), $b->toString());
});

static::assertSame($expectResult, $expression->toString());
}

public function provideSortUnionTypesCases(): iterable
public function provideSortTypesCases(): iterable
{
yield 'not a union type' => [
'int',
Expand Down Expand Up @@ -264,5 +280,13 @@ public function provideSortUnionTypesCases(): iterable
'?array{0: Foo|Bar}',
'?array{0: Bar|Foo}',
];
yield 'simple types alternation' => [
'array<Foo&Bar>',
'array<Bar&Foo>',
];
yield 'nesty stuff' => [
'array<Level11&array<Level2|array<Level31&Level32>>>',
'array<array<array<Level31&Level32>|Level2>&Level11>',
];
}
}
16 changes: 16 additions & 0 deletions tests/Fixer/Phpdoc/PhpdocTypesOrderFixerTest.php
Expand Up @@ -411,6 +411,22 @@ public function provideFixWithAlphaAlgorithmCases(): array
[
'<?php /** @return array<int, callable(array<string, null|string> , DateTime): bool> */',
],
[
'<?php /** @return A&B&C */',
'<?php /** @return A&C&B */',
],
[
'<?php /** @return array<A&B&C> */',
'<?php /** @return array<A&C&B> */',
],
[
'<?php /** @return array<A&B&C>|bool|string */',
'<?php /** @return bool|array<A&B&C>|string */',
],
[
'<?php /** @return A&B<X|Y|Z>&C&D */',
'<?php /** @return A&D&B<X|Y|Z>&C */',
],
];
}

Expand Down

0 comments on commit 55aec39

Please sign in to comment.