From 8daa46e73f30c30da4000e4cc8d3e5291815e6a1 Mon Sep 17 00:00:00 2001 From: SpacePossum Date: Wed, 5 Jan 2022 09:45:56 +0100 Subject: [PATCH] ArgumentsAnalyzer - support PHP8.1 readonly --- ...ypeDeclarationForDefaultNullValueFixer.php | 3 +- src/Tokenizer/Analyzer/ArgumentsAnalyzer.php | 24 +++-- ...eclarationForDefaultNullValueFixerTest.php | 23 +++++ .../Analyzer/ArgumentsAnalyzerTest.php | 88 +++++++++++++++---- 4 files changed, 112 insertions(+), 26 deletions(-) diff --git a/src/Fixer/FunctionNotation/NullableTypeDeclarationForDefaultNullValueFixer.php b/src/Fixer/FunctionNotation/NullableTypeDeclarationForDefaultNullValueFixer.php index 8aca8026a82..8c5faa8b711 100644 --- a/src/Fixer/FunctionNotation/NullableTypeDeclarationForDefaultNullValueFixer.php +++ b/src/Fixer/FunctionNotation/NullableTypeDeclarationForDefaultNullValueFixer.php @@ -98,8 +98,8 @@ protected function createConfigurationDefinition(): FixerConfigurationResolverIn protected function applyFix(\SplFileInfo $file, Tokens $tokens): void { $functionsAnalyzer = new FunctionsAnalyzer(); - $tokenKinds = [T_FUNCTION]; + if (\PHP_VERSION_ID >= 70400) { $tokenKinds[] = T_FN; } @@ -112,7 +112,6 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens): void } $arguments = $functionsAnalyzer->getFunctionArguments($tokens, $index); - $this->fixFunctionParameters($tokens, $arguments); } } diff --git a/src/Tokenizer/Analyzer/ArgumentsAnalyzer.php b/src/Tokenizer/Analyzer/ArgumentsAnalyzer.php index 964f35c1231..39d9c8922ca 100644 --- a/src/Tokenizer/Analyzer/ArgumentsAnalyzer.php +++ b/src/Tokenizer/Analyzer/ArgumentsAnalyzer.php @@ -87,6 +87,16 @@ public function getArguments(Tokens $tokens, int $openParenthesis, int $closePar public function getArgumentInfo(Tokens $tokens, int $argumentStart, int $argumentEnd): ArgumentAnalysis { + static $skipTypes = null; + + if (null === $skipTypes) { + $skipTypes = [T_ELLIPSIS, CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PUBLIC, CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PROTECTED, CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PRIVATE]; + + if (\defined('T_READONLY')) { // @TODO: drop condition when PHP 8.1+ is required + $skipTypes[] = T_READONLY; + } + } + $info = [ 'default' => null, 'name' => null, @@ -101,10 +111,16 @@ public function getArgumentInfo(Tokens $tokens, int $argumentStart, int $argumen for ($index = $argumentStart; $index <= $argumentEnd; ++$index) { $token = $tokens[$index]; + if (\defined('T_ATTRIBUTE') && $token->isGivenKind(T_ATTRIBUTE)) { + $index = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_ATTRIBUTE, $index); + + continue; + } + if ( $token->isComment() || $token->isWhitespace() - || $token->isGivenKind([T_ELLIPSIS, CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PUBLIC, CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PROTECTED, CT::T_CONSTRUCTOR_PROPERTY_PROMOTION_PRIVATE]) + || $token->isGivenKind($skipTypes) || $token->equals('&') ) { continue; @@ -122,12 +138,6 @@ public function getArgumentInfo(Tokens $tokens, int $argumentStart, int $argumen continue; } - if (\defined('T_ATTRIBUTE') && $token->isGivenKind(T_ATTRIBUTE)) { - $index = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_ATTRIBUTE, $index); - - continue; - } - if ($sawName) { $info['default'] .= $token->getContent(); } else { diff --git a/tests/Fixer/FunctionNotation/NullableTypeDeclarationForDefaultNullValueFixerTest.php b/tests/Fixer/FunctionNotation/NullableTypeDeclarationForDefaultNullValueFixerTest.php index 9916467b549..c086d0a92b5 100644 --- a/tests/Fixer/FunctionNotation/NullableTypeDeclarationForDefaultNullValueFixerTest.php +++ b/tests/Fixer/FunctionNotation/NullableTypeDeclarationForDefaultNullValueFixerTest.php @@ -500,4 +500,27 @@ function foo2(?string &/*comment*/$param2 = null) {} yield [$cases[0], $cases[1]]; yield [$cases[1], $cases[0], ['use_nullable_type_declaration' => false]]; } + + /** + * @dataProvider provideFix81Cases + * @requires PHP 8.1 + */ + public function testFix81(string $expected): void + { + $this->doTest($expected); + } + + public function provideFix81Cases(): iterable + { + yield [ + 'getArguments($tokens, $openIndex, $closeIndex)); } - public function provideArguments73Cases(): array + public function provideArguments73Cases(): iterable { - return [ - [' 3]], - [' 3]], - [' 14]], - [' 15]], - [' 5, 7 => 7, 9 => 9, 11 => 11, 13 => 13]], - [' 3, 5 => 7]], - ]; + yield [' 3]]; + yield [' 3]]; + yield [' 14]]; + yield [' 15]]; + yield [' 5, 7 => 7, 9 => 9, 11 => 11, 13 => 13]]; + yield [' 3, 5 => 7]]; } /** @@ -146,10 +144,7 @@ public function testArgumentInfo(string $code, int $openIndex, int $closeIndex, $tokens = Tokens::fromCode($code); $analyzer = new ArgumentsAnalyzer(); - static::assertSame( - serialize($expected), - serialize($analyzer->getArgumentInfo($tokens, $openIndex, $closeIndex)) - ); + self::assertArgumentAnalysis($expected, $analyzer->getArgumentInfo($tokens, $openIndex, $closeIndex)); } public function provideArgumentsInfoCases(): \Generator @@ -284,10 +279,7 @@ public function testArgumentInfo80(string $code, int $openIndex, int $closeIndex $tokens = Tokens::fromCode($code); $analyzer = new ArgumentsAnalyzer(); - static::assertSame( - serialize($expected), - serialize($analyzer->getArgumentInfo($tokens, $openIndex, $closeIndex)) - ); + self::assertArgumentAnalysis($expected, $analyzer->getArgumentInfo($tokens, $openIndex, $closeIndex)); } public function provideArgumentsInfo80Cases(): \Generator @@ -326,4 +318,66 @@ public function provideArgumentsInfo80Cases(): \Generator ]; } } + + /** + * @requires PHP 8.1 + * @dataProvider provideArgumentsInfo81Cases + */ + public function testArgumentInfo81(string $code, int $openIndex, int $closeIndex, ArgumentAnalysis $expected): void + { + $tokens = Tokens::fromCode($code); + $analyzer = new ArgumentsAnalyzer(); + + self::assertArgumentAnalysis($expected, $analyzer->getArgumentInfo($tokens, $openIndex, $closeIndex)); + } + + public function provideArgumentsInfo81Cases(): \Generator + { + yield [ + 'getDefault(), $actual->getDefault(), 'Default.'); + static::assertSame($expected->getName(), $actual->getName(), 'Name.'); + static::assertSame($expected->getNameIndex(), $actual->getNameIndex(), 'Name index.'); + static::assertSame($expected->hasDefault(), $actual->hasDefault(), 'Has default.'); + static::assertSame($expected->hasTypeAnalysis(), $actual->hasTypeAnalysis(), 'Has type analysis.'); + + if ($expected->hasTypeAnalysis()) { + $expectedTypeAnalysis = $expected->getTypeAnalysis(); + $actualTypeAnalysis = $actual->getTypeAnalysis(); + + static::assertSame($expectedTypeAnalysis->getEndIndex(), $actualTypeAnalysis->getEndIndex(), 'Type analysis end index.'); + static::assertSame($expectedTypeAnalysis->getName(), $actualTypeAnalysis->getName(), 'Type analysis name.'); + static::assertSame($expectedTypeAnalysis->getStartIndex(), $actualTypeAnalysis->getStartIndex(), 'Type analysis start index.'); + static::assertSame($expectedTypeAnalysis->isNullable(), $actualTypeAnalysis->isNullable(), 'Type analysis nullable.'); + static::assertSame($expectedTypeAnalysis->isReservedType(), $actualTypeAnalysis->isReservedType(), 'Type analysis reserved type.'); + } else { + static::assertNull($actual->getTypeAnalysis()); + } + + static::assertSame(serialize($expected), serialize($actual)); + } }