diff --git a/README.rst b/README.rst index fd23e19b0a0..841eab022d4 100644 --- a/README.rst +++ b/README.rst @@ -1723,6 +1723,18 @@ Choose from the list of available rules: - ``scalar_types`` (``bool``): fix also scalar types; may have unexpected behaviour due to PHP bad type coercion system; defaults to ``true`` +* **phpdoc_to_property_type** + + EXPERIMENTAL: Takes ``@var`` annotation of non-mixed types and adjusts + accordingly the property signature. Requires PHP >= 7.4. + + *Risky rule: [1] This rule is EXPERIMENTAL and is not covered with backward compatibility promise. [2] ``@var`` annotation is mandatory for the fixer to make changes, signatures of properties without it (no docblock, inheritdocs) will not be fixed. [3] Manual actions are required if inherited signatures are not properly documented. [4] ``@inheritdocs`` support is under construction.* + + Configuration options: + + - ``scalar_types`` (``bool``): fix also scalar types; may have unexpected + behaviour due to PHP bad type coercion system; defaults to ``true`` + * **phpdoc_to_return_type** EXPERIMENTAL: Takes ``@return`` annotation of non-mixed types and adjusts diff --git a/src/AbstractFixer.php b/src/AbstractFixer.php index b8ae6ddb411..f11bbaabac1 100644 --- a/src/AbstractFixer.php +++ b/src/AbstractFixer.php @@ -97,6 +97,9 @@ public function getName() /** * {@inheritdoc} + * + * Must run before PhpdocAlignFixer. + * Must run after CommentToPhpdocFixer, PhpdocIndentFixer, PhpdocScalarFixer, PhpdocToCommentFixer, PhpdocTypesFixer. */ public function getPriority() { diff --git a/src/AbstractPhpdocToTypeDeclarationFixer.php b/src/AbstractPhpdocToTypeDeclarationFixer.php index df7a7251052..da03d02c1f1 100644 --- a/src/AbstractPhpdocToTypeDeclarationFixer.php +++ b/src/AbstractPhpdocToTypeDeclarationFixer.php @@ -83,14 +83,11 @@ protected function createConfigurationDefinition() } /** - * Find all the annotations of given type in the function's PHPDoc comment. + * @param int $index The index of the function token * - * @param string $name - * @param int $index The index of the function token - * - * @return Annotation[] + * @return null|int */ - protected function findAnnotations($name, Tokens $tokens, $index) + protected function findFunctionDocComment(Tokens $tokens, $index) { do { $index = $tokens->getPrevNonWhitespace($index); @@ -104,18 +101,29 @@ protected function findAnnotations($name, Tokens $tokens, $index) T_STATIC, ])); - if (!$tokens[$index]->isGivenKind(T_DOC_COMMENT)) { - return []; + if ($tokens[$index]->isGivenKind(T_DOC_COMMENT)) { + return $index; } + return null; + } + + /** + * @param string $name + * @param int $docCommentIndex + * + * @return Annotation[] + */ + protected function getAnnotationsFromDocComment($name, Tokens $tokens, $docCommentIndex) + { $namespacesAnalyzer = new NamespacesAnalyzer(); - $namespace = $namespacesAnalyzer->getNamespaceAt($tokens, $index); + $namespace = $namespacesAnalyzer->getNamespaceAt($tokens, $docCommentIndex); $namespaceUsesAnalyzer = new NamespaceUsesAnalyzer(); $namespaceUses = $namespaceUsesAnalyzer->getDeclarationsInNamespace($tokens, $namespace); $doc = new DocBlock( - $tokens[$index]->getContent(), + $tokens[$docCommentIndex]->getContent(), $namespace, $namespaceUses ); diff --git a/src/Fixer/Comment/CommentToPhpdocFixer.php b/src/Fixer/Comment/CommentToPhpdocFixer.php index 290e0570c89..b3a35d00ff8 100644 --- a/src/Fixer/Comment/CommentToPhpdocFixer.php +++ b/src/Fixer/Comment/CommentToPhpdocFixer.php @@ -54,7 +54,7 @@ public function isRisky() /** * {@inheritdoc} * - * Must run before GeneralPhpdocAnnotationRemoveFixer, NoBlankLinesAfterPhpdocFixer, NoEmptyPhpdocFixer, NoSuperfluousPhpdocTagsFixer, PhpdocAddMissingParamAnnotationFixer, PhpdocAlignFixer, PhpdocAlignFixer, PhpdocAnnotationWithoutDotFixer, PhpdocInlineTagFixer, PhpdocLineSpanFixer, PhpdocNoAccessFixer, PhpdocNoAliasTagFixer, PhpdocNoEmptyReturnFixer, PhpdocNoPackageFixer, PhpdocNoUselessInheritdocFixer, PhpdocOrderByValueFixer, PhpdocOrderFixer, PhpdocReturnSelfReferenceFixer, PhpdocSeparationFixer, PhpdocSingleLineVarSpacingFixer, PhpdocSummaryFixer, PhpdocToCommentFixer, PhpdocToParamTypeFixer, PhpdocToReturnTypeFixer, PhpdocTrimConsecutiveBlankLineSeparationFixer, PhpdocTrimFixer, PhpdocTypesOrderFixer, PhpdocVarAnnotationCorrectOrderFixer, PhpdocVarWithoutNameFixer. + * Must run before GeneralPhpdocAnnotationRemoveFixer, NoBlankLinesAfterPhpdocFixer, NoEmptyPhpdocFixer, NoSuperfluousPhpdocTagsFixer, PhpdocAddMissingParamAnnotationFixer, PhpdocAlignFixer, PhpdocAlignFixer, PhpdocAnnotationWithoutDotFixer, PhpdocInlineTagFixer, PhpdocLineSpanFixer, PhpdocNoAccessFixer, PhpdocNoAliasTagFixer, PhpdocNoEmptyReturnFixer, PhpdocNoPackageFixer, PhpdocNoUselessInheritdocFixer, PhpdocOrderByValueFixer, PhpdocOrderFixer, PhpdocReturnSelfReferenceFixer, PhpdocSeparationFixer, PhpdocSingleLineVarSpacingFixer, PhpdocSummaryFixer, PhpdocToCommentFixer, PhpdocToParamTypeFixer, PhpdocToPropertyTypeFixer, PhpdocToReturnTypeFixer, PhpdocTrimConsecutiveBlankLineSeparationFixer, PhpdocTrimFixer, PhpdocTypesOrderFixer, PhpdocVarAnnotationCorrectOrderFixer, PhpdocVarWithoutNameFixer. */ public function getPriority() { diff --git a/src/Fixer/FunctionNotation/PhpdocToParamTypeFixer.php b/src/Fixer/FunctionNotation/PhpdocToParamTypeFixer.php index b168acafda4..61fbcc765bc 100644 --- a/src/Fixer/FunctionNotation/PhpdocToParamTypeFixer.php +++ b/src/Fixer/FunctionNotation/PhpdocToParamTypeFixer.php @@ -99,9 +99,13 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens) continue; } - $paramTypeAnnotations = $this->findAnnotations('param', $tokens, $index); + $docCommentIndex = $this->findFunctionDocComment($tokens, $index); - foreach ($paramTypeAnnotations as $paramTypeAnnotation) { + if (null === $docCommentIndex) { + continue; + } + + foreach ($this->getAnnotationsFromDocComment('param', $tokens, $docCommentIndex) as $paramTypeAnnotation) { $typeInfo = $this->getCommonTypeFromAnnotation($paramTypeAnnotation); if (null === $typeInfo) { diff --git a/src/Fixer/FunctionNotation/PhpdocToPropertyTypeFixer.php b/src/Fixer/FunctionNotation/PhpdocToPropertyTypeFixer.php new file mode 100644 index 00000000000..138dd8a279b --- /dev/null +++ b/src/Fixer/FunctionNotation/PhpdocToPropertyTypeFixer.php @@ -0,0 +1,219 @@ + + * Dariusz Rumiński + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Fixer\FunctionNotation; + +use PhpCsFixer\AbstractPhpdocToTypeDeclarationFixer; +use PhpCsFixer\DocBlock\Annotation; +use PhpCsFixer\FixerDefinition\FixerDefinition; +use PhpCsFixer\FixerDefinition\VersionSpecification; +use PhpCsFixer\FixerDefinition\VersionSpecificCodeSample; +use PhpCsFixer\Tokenizer\Token; +use PhpCsFixer\Tokenizer\Tokens; + +final class PhpdocToPropertyTypeFixer extends AbstractPhpdocToTypeDeclarationFixer +{ + /** + * {@inheritdoc} + */ + public function getDefinition() + { + return new FixerDefinition( + 'EXPERIMENTAL: Takes `@var` annotation of non-mixed types and adjusts accordingly the property signature. Requires PHP >= 7.4.', + [ + new VersionSpecificCodeSample( + ' false] + ), + ], + null, + '[1] This rule is EXPERIMENTAL and is not covered with backward compatibility promise. [2] `@var` annotation is mandatory for the fixer to make changes, signatures of properties without it (no docblock, inheritdocs) will not be fixed. [3] Manual actions are required if inherited signatures are not properly documented. [4] `@inheritdocs` support is under construction.' + ); + } + + /** + * {@inheritdoc} + */ + public function isCandidate(Tokens $tokens) + { + return \PHP_VERSION_ID >= 70400 && $tokens->isTokenKindFound(T_DOC_COMMENT); + } + + /** + * {@inheritdoc} + */ + protected function applyFix(\SplFileInfo $file, Tokens $tokens) + { + for ($index = $tokens->count() - 1; 0 < $index; --$index) { + if ($tokens[$index]->isGivenKind([T_CLASS, T_TRAIT])) { + $this->fixClass($tokens, $index); + } + } + } + + /** + * @param int $index + */ + private function fixClass(Tokens $tokens, $index) + { + $index = $tokens->getNextTokenOfKind($index, ['{']); + $classEndIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $index); + + for (; $index < $classEndIndex; ++$index) { + if ($tokens[$index]->isGivenKind(T_FUNCTION)) { + $index = $tokens->getNextTokenOfKind($index, ['{', ';']); + + if ($tokens[$index]->equals('{')) { + $index = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $index); + } + + continue; + } + + if (!$tokens[$index]->isGivenKind(T_DOC_COMMENT)) { + continue; + } + + $docCommentIndex = $index; + $propertyIndexes = $this->findNextUntypedPropertiesDeclaration($tokens, $docCommentIndex); + + if ([] === $propertyIndexes) { + continue; + } + + $typeInfo = $this->resolveAppliableType( + $propertyIndexes, + $this->getAnnotationsFromDocComment('var', $tokens, $docCommentIndex) + ); + + if (null === $typeInfo) { + continue; + } + + list($propertyType, $isNullable) = $typeInfo; + + if (\in_array($propertyType, ['void', 'callable'], true)) { + continue; + } + + $newTokens = array_merge( + $this->createTypeDeclarationTokens($propertyType, $isNullable), + [new Token([T_WHITESPACE, ' '])] + ); + + $tokens->insertAt(current($propertyIndexes), $newTokens); + + $index = max($propertyIndexes) + \count($newTokens) + 1; + $classEndIndex += \count($newTokens); + } + } + + /** + * @param int $index + * + * @return array + */ + private function findNextUntypedPropertiesDeclaration(Tokens $tokens, $index) + { + do { + $index = $tokens->getNextMeaningfulToken($index); + } while ($tokens[$index]->isGivenKind([ + T_PRIVATE, + T_PROTECTED, + T_PUBLIC, + T_STATIC, + T_VAR, + ])); + + if (!$tokens[$index]->isGivenKind(T_VARIABLE)) { + return []; + } + + $properties = []; + while (!$tokens[$index]->equals(';')) { + if ($tokens[$index]->isGivenKind(T_VARIABLE)) { + $properties[$tokens[$index]->getContent()] = $index; + } + + $index = $tokens->getNextMeaningfulToken($index); + } + + return $properties; + } + + /** + * @param array $propertyIndexes + * @param Annotation[] $annotations + */ + private function resolveAppliableType(array $propertyIndexes, array $annotations) + { + $propertyTypes = []; + + foreach ($annotations as $annotation) { + $propertyName = $annotation->getVariableName(); + + if (null === $propertyName) { + if (1 !== \count($propertyIndexes)) { + continue; + } + + $propertyName = key($propertyIndexes); + } + + if (!isset($propertyIndexes[$propertyName])) { + continue; + } + + $typeInfo = $this->getCommonTypeFromAnnotation($annotation); + + if (!isset($propertyTypes[$propertyName])) { + $propertyTypes[$propertyName] = []; + } elseif ($typeInfo !== $propertyTypes[$propertyName]) { + return null; + } + + $propertyTypes[$propertyName] = $typeInfo; + } + + if (\count($propertyTypes) !== \count($propertyIndexes)) { + return null; + } + + $type = array_shift($propertyTypes); + foreach ($propertyTypes as $propertyType) { + if ($propertyType !== $type) { + return null; + } + } + + return $type; + } +} diff --git a/src/Fixer/FunctionNotation/PhpdocToReturnTypeFixer.php b/src/Fixer/FunctionNotation/PhpdocToReturnTypeFixer.php index 68ecccfcd4b..c3c5342773f 100644 --- a/src/Fixer/FunctionNotation/PhpdocToReturnTypeFixer.php +++ b/src/Fixer/FunctionNotation/PhpdocToReturnTypeFixer.php @@ -116,7 +116,12 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens) continue; } - $returnTypeAnnotation = $this->findAnnotations('return', $tokens, $index); + $docCommentIndex = $this->findFunctionDocComment($tokens, $index); + if (null === $docCommentIndex) { + continue; + } + + $returnTypeAnnotation = $this->getAnnotationsFromDocComment('return', $tokens, $docCommentIndex); if (1 !== \count($returnTypeAnnotation)) { continue; } diff --git a/src/Fixer/Phpdoc/PhpdocAlignFixer.php b/src/Fixer/Phpdoc/PhpdocAlignFixer.php index ca5d78cba32..89b17ad9dbb 100644 --- a/src/Fixer/Phpdoc/PhpdocAlignFixer.php +++ b/src/Fixer/Phpdoc/PhpdocAlignFixer.php @@ -146,7 +146,7 @@ public function getDefinition() /** * {@inheritdoc} * - * Must run after CommentToPhpdocFixer, CommentToPhpdocFixer, GeneralPhpdocAnnotationRemoveFixer, NoBlankLinesAfterPhpdocFixer, NoEmptyPhpdocFixer, NoSuperfluousPhpdocTagsFixer, PhpdocAddMissingParamAnnotationFixer, PhpdocAddMissingParamAnnotationFixer, PhpdocAnnotationWithoutDotFixer, PhpdocIndentFixer, PhpdocIndentFixer, PhpdocInlineTagFixer, PhpdocLineSpanFixer, PhpdocNoAccessFixer, PhpdocNoAliasTagFixer, PhpdocNoEmptyReturnFixer, PhpdocNoPackageFixer, PhpdocNoUselessInheritdocFixer, PhpdocOrderByValueFixer, PhpdocOrderFixer, PhpdocReturnSelfReferenceFixer, PhpdocScalarFixer, PhpdocScalarFixer, PhpdocSeparationFixer, PhpdocSingleLineVarSpacingFixer, PhpdocSummaryFixer, PhpdocToCommentFixer, PhpdocToCommentFixer, PhpdocToParamTypeFixer, PhpdocToReturnTypeFixer, PhpdocTrimConsecutiveBlankLineSeparationFixer, PhpdocTrimFixer, PhpdocTypesFixer, PhpdocTypesFixer, PhpdocTypesOrderFixer, PhpdocVarAnnotationCorrectOrderFixer, PhpdocVarWithoutNameFixer. + * Must run after CommentToPhpdocFixer, CommentToPhpdocFixer, GeneralPhpdocAnnotationRemoveFixer, NoBlankLinesAfterPhpdocFixer, NoEmptyPhpdocFixer, NoSuperfluousPhpdocTagsFixer, PhpdocAddMissingParamAnnotationFixer, PhpdocAddMissingParamAnnotationFixer, PhpdocAnnotationWithoutDotFixer, PhpdocIndentFixer, PhpdocIndentFixer, PhpdocInlineTagFixer, PhpdocLineSpanFixer, PhpdocNoAccessFixer, PhpdocNoAliasTagFixer, PhpdocNoEmptyReturnFixer, PhpdocNoPackageFixer, PhpdocNoUselessInheritdocFixer, PhpdocOrderByValueFixer, PhpdocOrderFixer, PhpdocReturnSelfReferenceFixer, PhpdocScalarFixer, PhpdocScalarFixer, PhpdocSeparationFixer, PhpdocSingleLineVarSpacingFixer, PhpdocSummaryFixer, PhpdocToCommentFixer, PhpdocToCommentFixer, PhpdocToParamTypeFixer, PhpdocToPropertyTypeFixer, PhpdocToReturnTypeFixer, PhpdocTrimConsecutiveBlankLineSeparationFixer, PhpdocTrimFixer, PhpdocTypesFixer, PhpdocTypesFixer, PhpdocTypesOrderFixer, PhpdocVarAnnotationCorrectOrderFixer, PhpdocVarWithoutNameFixer. */ public function getPriority() { diff --git a/src/Fixer/Phpdoc/PhpdocIndentFixer.php b/src/Fixer/Phpdoc/PhpdocIndentFixer.php index 8a958080331..1e7f151dbd1 100644 --- a/src/Fixer/Phpdoc/PhpdocIndentFixer.php +++ b/src/Fixer/Phpdoc/PhpdocIndentFixer.php @@ -48,7 +48,7 @@ class DocBlocks /** * {@inheritdoc} * - * Must run before GeneralPhpdocAnnotationRemoveFixer, NoBlankLinesAfterPhpdocFixer, NoEmptyPhpdocFixer, NoSuperfluousPhpdocTagsFixer, PhpdocAddMissingParamAnnotationFixer, PhpdocAlignFixer, PhpdocAlignFixer, PhpdocAnnotationWithoutDotFixer, PhpdocInlineTagFixer, PhpdocLineSpanFixer, PhpdocNoAccessFixer, PhpdocNoAliasTagFixer, PhpdocNoEmptyReturnFixer, PhpdocNoPackageFixer, PhpdocNoUselessInheritdocFixer, PhpdocOrderByValueFixer, PhpdocOrderFixer, PhpdocReturnSelfReferenceFixer, PhpdocSeparationFixer, PhpdocSingleLineVarSpacingFixer, PhpdocSummaryFixer, PhpdocToParamTypeFixer, PhpdocToReturnTypeFixer, PhpdocTrimConsecutiveBlankLineSeparationFixer, PhpdocTrimFixer, PhpdocTypesFixer, PhpdocTypesOrderFixer, PhpdocVarAnnotationCorrectOrderFixer, PhpdocVarWithoutNameFixer. + * Must run before GeneralPhpdocAnnotationRemoveFixer, NoBlankLinesAfterPhpdocFixer, NoEmptyPhpdocFixer, NoSuperfluousPhpdocTagsFixer, PhpdocAddMissingParamAnnotationFixer, PhpdocAlignFixer, PhpdocAlignFixer, PhpdocAnnotationWithoutDotFixer, PhpdocInlineTagFixer, PhpdocLineSpanFixer, PhpdocNoAccessFixer, PhpdocNoAliasTagFixer, PhpdocNoEmptyReturnFixer, PhpdocNoPackageFixer, PhpdocNoUselessInheritdocFixer, PhpdocOrderByValueFixer, PhpdocOrderFixer, PhpdocReturnSelfReferenceFixer, PhpdocSeparationFixer, PhpdocSingleLineVarSpacingFixer, PhpdocSummaryFixer, PhpdocToParamTypeFixer, PhpdocToPropertyTypeFixer, PhpdocToReturnTypeFixer, PhpdocTrimConsecutiveBlankLineSeparationFixer, PhpdocTrimFixer, PhpdocTypesFixer, PhpdocTypesOrderFixer, PhpdocVarAnnotationCorrectOrderFixer, PhpdocVarWithoutNameFixer. * Must run after IndentationTypeFixer, PhpdocToCommentFixer. */ public function getPriority() diff --git a/src/Fixer/Phpdoc/PhpdocScalarFixer.php b/src/Fixer/Phpdoc/PhpdocScalarFixer.php index 7aa639f6a9d..43b38b36c1b 100644 --- a/src/Fixer/Phpdoc/PhpdocScalarFixer.php +++ b/src/Fixer/Phpdoc/PhpdocScalarFixer.php @@ -65,7 +65,7 @@ function sample($a, $b, $c) /** * {@inheritdoc} * - * Must run before GeneralPhpdocAnnotationRemoveFixer, NoBlankLinesAfterPhpdocFixer, NoEmptyPhpdocFixer, NoSuperfluousPhpdocTagsFixer, PhpdocAddMissingParamAnnotationFixer, PhpdocAlignFixer, PhpdocAlignFixer, PhpdocInlineTagFixer, PhpdocLineSpanFixer, PhpdocNoAccessFixer, PhpdocNoAliasTagFixer, PhpdocNoEmptyReturnFixer, PhpdocNoPackageFixer, PhpdocNoUselessInheritdocFixer, PhpdocOrderByValueFixer, PhpdocOrderFixer, PhpdocReturnSelfReferenceFixer, PhpdocSeparationFixer, PhpdocSingleLineVarSpacingFixer, PhpdocSummaryFixer, PhpdocToParamTypeFixer, PhpdocToReturnTypeFixer, PhpdocToReturnTypeFixer, PhpdocTrimConsecutiveBlankLineSeparationFixer, PhpdocTrimFixer, PhpdocTypesOrderFixer, PhpdocVarAnnotationCorrectOrderFixer, PhpdocVarWithoutNameFixer. + * Must run before GeneralPhpdocAnnotationRemoveFixer, NoBlankLinesAfterPhpdocFixer, NoEmptyPhpdocFixer, NoSuperfluousPhpdocTagsFixer, PhpdocAddMissingParamAnnotationFixer, PhpdocAlignFixer, PhpdocAlignFixer, PhpdocInlineTagFixer, PhpdocLineSpanFixer, PhpdocNoAccessFixer, PhpdocNoAliasTagFixer, PhpdocNoEmptyReturnFixer, PhpdocNoPackageFixer, PhpdocNoUselessInheritdocFixer, PhpdocOrderByValueFixer, PhpdocOrderFixer, PhpdocReturnSelfReferenceFixer, PhpdocSeparationFixer, PhpdocSingleLineVarSpacingFixer, PhpdocSummaryFixer, PhpdocToParamTypeFixer, PhpdocToPropertyTypeFixer, PhpdocToReturnTypeFixer, PhpdocToReturnTypeFixer, PhpdocTrimConsecutiveBlankLineSeparationFixer, PhpdocTrimFixer, PhpdocTypesOrderFixer, PhpdocVarAnnotationCorrectOrderFixer, PhpdocVarWithoutNameFixer. * Must run after PhpdocTypesFixer. */ public function getPriority() diff --git a/src/Fixer/Phpdoc/PhpdocToCommentFixer.php b/src/Fixer/Phpdoc/PhpdocToCommentFixer.php index e4c7dad8ab8..f9e2e0eb813 100644 --- a/src/Fixer/Phpdoc/PhpdocToCommentFixer.php +++ b/src/Fixer/Phpdoc/PhpdocToCommentFixer.php @@ -36,7 +36,7 @@ public function isCandidate(Tokens $tokens) /** * {@inheritdoc} * - * Must run before GeneralPhpdocAnnotationRemoveFixer, NoBlankLinesAfterPhpdocFixer, NoEmptyCommentFixer, NoEmptyPhpdocFixer, NoSuperfluousPhpdocTagsFixer, PhpdocAddMissingParamAnnotationFixer, PhpdocAlignFixer, PhpdocAlignFixer, PhpdocAnnotationWithoutDotFixer, PhpdocIndentFixer, PhpdocInlineTagFixer, PhpdocLineSpanFixer, PhpdocNoAccessFixer, PhpdocNoAliasTagFixer, PhpdocNoEmptyReturnFixer, PhpdocNoPackageFixer, PhpdocNoUselessInheritdocFixer, PhpdocNoUselessInheritdocFixer, PhpdocOrderByValueFixer, PhpdocOrderFixer, PhpdocReturnSelfReferenceFixer, PhpdocSeparationFixer, PhpdocSingleLineVarSpacingFixer, PhpdocSummaryFixer, PhpdocToParamTypeFixer, PhpdocToReturnTypeFixer, PhpdocTrimConsecutiveBlankLineSeparationFixer, PhpdocTrimFixer, PhpdocTypesOrderFixer, PhpdocVarAnnotationCorrectOrderFixer, PhpdocVarWithoutNameFixer. + * Must run before GeneralPhpdocAnnotationRemoveFixer, NoBlankLinesAfterPhpdocFixer, NoEmptyCommentFixer, NoEmptyPhpdocFixer, NoSuperfluousPhpdocTagsFixer, PhpdocAddMissingParamAnnotationFixer, PhpdocAlignFixer, PhpdocAlignFixer, PhpdocAnnotationWithoutDotFixer, PhpdocIndentFixer, PhpdocInlineTagFixer, PhpdocLineSpanFixer, PhpdocNoAccessFixer, PhpdocNoAliasTagFixer, PhpdocNoEmptyReturnFixer, PhpdocNoPackageFixer, PhpdocNoUselessInheritdocFixer, PhpdocNoUselessInheritdocFixer, PhpdocOrderByValueFixer, PhpdocOrderFixer, PhpdocReturnSelfReferenceFixer, PhpdocSeparationFixer, PhpdocSingleLineVarSpacingFixer, PhpdocSummaryFixer, PhpdocToParamTypeFixer, PhpdocToPropertyTypeFixer, PhpdocToReturnTypeFixer, PhpdocTrimConsecutiveBlankLineSeparationFixer, PhpdocTrimFixer, PhpdocTypesOrderFixer, PhpdocVarAnnotationCorrectOrderFixer, PhpdocVarWithoutNameFixer. * Must run after CommentToPhpdocFixer. */ public function getPriority() diff --git a/src/Fixer/Phpdoc/PhpdocTypesFixer.php b/src/Fixer/Phpdoc/PhpdocTypesFixer.php index 55afbe0e14c..2319c314cab 100644 --- a/src/Fixer/Phpdoc/PhpdocTypesFixer.php +++ b/src/Fixer/Phpdoc/PhpdocTypesFixer.php @@ -105,7 +105,7 @@ public function getDefinition() /** * {@inheritdoc} * - * Must run before GeneralPhpdocAnnotationRemoveFixer, NoBlankLinesAfterPhpdocFixer, NoEmptyPhpdocFixer, NoSuperfluousPhpdocTagsFixer, PhpdocAddMissingParamAnnotationFixer, PhpdocAlignFixer, PhpdocAlignFixer, PhpdocInlineTagFixer, PhpdocLineSpanFixer, PhpdocNoAccessFixer, PhpdocNoAliasTagFixer, PhpdocNoEmptyReturnFixer, PhpdocNoPackageFixer, PhpdocNoUselessInheritdocFixer, PhpdocOrderByValueFixer, PhpdocOrderFixer, PhpdocReturnSelfReferenceFixer, PhpdocScalarFixer, PhpdocSeparationFixer, PhpdocSingleLineVarSpacingFixer, PhpdocSummaryFixer, PhpdocToParamTypeFixer, PhpdocToReturnTypeFixer, PhpdocToReturnTypeFixer, PhpdocTrimConsecutiveBlankLineSeparationFixer, PhpdocTrimFixer, PhpdocTypesOrderFixer, PhpdocVarAnnotationCorrectOrderFixer, PhpdocVarWithoutNameFixer. + * Must run before GeneralPhpdocAnnotationRemoveFixer, NoBlankLinesAfterPhpdocFixer, NoEmptyPhpdocFixer, NoSuperfluousPhpdocTagsFixer, PhpdocAddMissingParamAnnotationFixer, PhpdocAlignFixer, PhpdocAlignFixer, PhpdocInlineTagFixer, PhpdocLineSpanFixer, PhpdocNoAccessFixer, PhpdocNoAliasTagFixer, PhpdocNoEmptyReturnFixer, PhpdocNoPackageFixer, PhpdocNoUselessInheritdocFixer, PhpdocOrderByValueFixer, PhpdocOrderFixer, PhpdocReturnSelfReferenceFixer, PhpdocScalarFixer, PhpdocSeparationFixer, PhpdocSingleLineVarSpacingFixer, PhpdocSummaryFixer, PhpdocToParamTypeFixer, PhpdocToPropertyTypeFixer, PhpdocToReturnTypeFixer, PhpdocToReturnTypeFixer, PhpdocTrimConsecutiveBlankLineSeparationFixer, PhpdocTrimFixer, PhpdocTypesOrderFixer, PhpdocVarAnnotationCorrectOrderFixer, PhpdocVarWithoutNameFixer. * Must run after PhpdocAnnotationWithoutDotFixer, PhpdocIndentFixer. */ public function getPriority() diff --git a/tests/AutoReview/FixerTest.php b/tests/AutoReview/FixerTest.php index 593a03a657b..c05b224b7f9 100644 --- a/tests/AutoReview/FixerTest.php +++ b/tests/AutoReview/FixerTest.php @@ -57,6 +57,7 @@ public function testFixerDefinitions(AbstractFixer $fixer) { static::assertInstanceOf(DefinedFixerInterface::class, $fixer); + $testIncompleteReason = null; $fixerName = $fixer->getName(); $definition = $fixer->getDefinition(); $fixerIsConfigurable = $fixer instanceof ConfigurationDefinitionFixerInterface; @@ -150,11 +151,11 @@ public function testFixerDefinitions(AbstractFixer $fixer) ]; if (\count($configSamplesProvided) < 2) { - if (\in_array($fixerName, $fixerNamesWithKnownMissingSamplesWithConfig, true)) { - static::markTestIncomplete(sprintf('[%s] Configurable fixer only provides a default configuration sample and none for its configuration options, please help and add it.', $fixerName)); + if (!\in_array($fixerName, $fixerNamesWithKnownMissingSamplesWithConfig, true)) { + static::fail(sprintf('[%s] Configurable fixer only provides a default configuration sample and none for its configuration options.', $fixerName)); } - static::fail(sprintf('[%s] Configurable fixer only provides a default configuration sample and none for its configuration options.', $fixerName)); + $testIncompleteReason = sprintf('[%s] Configurable fixer only provides a default configuration sample and none for its configuration options, please help and add it.', $fixerName); } elseif (\in_array($fixerName, $fixerNamesWithKnownMissingSamplesWithConfig, true)) { static::fail(sprintf('[%s] Invalid listed as missing code samples, please update the list.', $fixerName)); } @@ -171,6 +172,10 @@ public function testFixerDefinitions(AbstractFixer $fixer) } else { static::assertNull($definition->getRiskyDescription(), sprintf('[%s] Fixer is not risky so no description of it expected.', $fixerName)); } + + if (null !== $testIncompleteReason) { + static::markTestIncomplete($testIncompleteReason); + } } /** @@ -333,7 +338,7 @@ private static function assertCorrectCasing($needle, $haystack, $message) private static function assertValidDescription($fixerName, $descriptionType, $description) { static::assertInternalType('string', $description); - static::assertRegExp('/^[A-Z`][^"]+\.$/', $description, sprintf('[%s] The %s must start with capital letter or a ` and end with dot.', $fixerName, $descriptionType)); + static::assertRegExp('/^(\[1\] )?[A-Z`][^"]+\.$/', $description, sprintf('[%s] The %s must start with capital letter or a ` and end with dot.', $fixerName, $descriptionType)); static::assertNotContains('phpdocs', $description, sprintf('[%s] `PHPDoc` must not be in the plural in %s.', $fixerName, $descriptionType), true); static::assertCorrectCasing($description, 'PHPDoc', sprintf('[%s] `PHPDoc` must be in correct casing in %s.', $fixerName, $descriptionType)); static::assertCorrectCasing($description, 'PHPUnit', sprintf('[%s] `PHPUnit` must be in correct casing in %s.', $fixerName, $descriptionType)); diff --git a/tests/Fixer/FunctionNotation/PhpdocToPropertyTypeFixerTest.php b/tests/Fixer/FunctionNotation/PhpdocToPropertyTypeFixerTest.php new file mode 100644 index 00000000000..ff35fb94e9c --- /dev/null +++ b/tests/Fixer/FunctionNotation/PhpdocToPropertyTypeFixerTest.php @@ -0,0 +1,477 @@ + + * Dariusz Rumiński + * + * This source file is subject to the MIT license that is bundled + * with this source code in the file LICENSE. + */ + +namespace PhpCsFixer\Tests\Fixer\FunctionNotation; + +use PhpCsFixer\Tests\Test\AbstractFixerTestCase; + +/** + * @internal + * + * @covers \PhpCsFixer\Fixer\FunctionNotation\PhpdocToPropertyTypeFixer + */ +final class PhpdocToPropertyTypeFixerTest extends AbstractFixerTestCase +{ + /** + * @param string $expected + * @param null|string $input + * + * @dataProvider provideFixCases + */ + public function testFix($expected, $input = null, array $config = []) + { + if (null !== $input && \PHP_VERSION_ID < 70400) { + $expected = $input; + $input = null; + } + + $this->fixer->configure($config); + + $this->doTest($expected, $input); + } + + public function provideFixCases() + { + return [ + 'no phpdoc return' => [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' false], + ], + 'array native type' => [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' */ private array $foo; }', + ' */ private $foo; }', + ], + 'array of types' => [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + ' [ + 'fixer->configure($config); + + $this->doTest($expected, $input); + } + + public function provideFixPhp70Cases() + { + return [ + 'anonymous class' => [ + '