Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

PhpdocToPropertyTypeFixer - introduction #4592

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
67 changes: 67 additions & 0 deletions doc/rules/function_notation/phpdoc_to_property_type.rst
@@ -0,0 +1,67 @@
================================
Rule ``phpdoc_to_property_type``
================================

EXPERIMENTAL: Takes ``@var`` annotation of non-mixed types and adjusts
accordingly the property signature. Requires PHP >= 7.4.

.. warning:: Using this rule is risky.

This rule is EXPERIMENTAL and [1] 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) will not be fixed. [3]
Manual actions might be required for newly typed properties that are read
before initialization.

Configuration
-------------

``scalar_types``
~~~~~~~~~~~~~~~~

Fix also scalar types; may have unexpected behaviour due to PHP bad type
coercion system.

Allowed types: ``bool``

Default value: ``true``

Examples
--------

Example #1
~~~~~~~~~~

*Default* configuration.

.. code-block:: diff

--- Original
+++ New
<?php
class Foo {
/** @var int */
- private $foo;
+ private int $foo;
/** @var \Traversable */
- private $bar;
+ private \Traversable $bar;
}

Example #2
~~~~~~~~~~

With configuration: ``['scalar_types' => false]``.

.. code-block:: diff

--- Original
+++ New
<?php
class Foo {
/** @var int */
private $foo;
/** @var \Traversable */
- private $bar;
+ private \Traversable $bar;
}
2 changes: 1 addition & 1 deletion doc/rules/function_notation/phpdoc_to_return_type.rst
Expand Up @@ -11,7 +11,7 @@ accordingly the function signature. Requires PHP >= 7.0.
promise. [2] ``@return`` annotation is mandatory for the fixer to make
changes, signatures of methods 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.
properly documented.

Configuration
-------------
Expand Down
2 changes: 2 additions & 0 deletions doc/rules/index.rst
Expand Up @@ -249,6 +249,8 @@ Function Notation
Adds or removes ``?`` before type declarations for parameters with a default ``null`` value.
- `phpdoc_to_param_type <./function_notation/phpdoc_to_param_type.rst>`_ *(risky)*
EXPERIMENTAL: Takes ``@param`` annotations of non-mixed types and adjusts accordingly the function signature. Requires PHP >= 7.0.
- `phpdoc_to_property_type <./function_notation/phpdoc_to_property_type.rst>`_ *(risky)*
EXPERIMENTAL: Takes ``@var`` annotation of non-mixed types and adjusts accordingly the property signature. Requires PHP >= 7.4.
- `phpdoc_to_return_type <./function_notation/phpdoc_to_return_type.rst>`_ *(risky)*
EXPERIMENTAL: Takes ``@return`` annotation of non-mixed types and adjusts accordingly the function signature. Requires PHP >= 7.0.
- `regular_callable_call <./function_notation/regular_callable_call.rst>`_ *(risky)*
Expand Down
28 changes: 18 additions & 10 deletions src/AbstractPhpdocToTypeDeclarationFixer.php
Expand Up @@ -87,14 +87,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);
Expand All @@ -108,18 +105,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
);
Expand Down
2 changes: 1 addition & 1 deletion src/Fixer/Comment/CommentToPhpdocFixer.php
Expand Up @@ -54,7 +54,7 @@ public function isRisky()
/**
* {@inheritdoc}
*
* Must run before GeneralPhpdocAnnotationRemoveFixer, GeneralPhpdocTagRenameFixer, NoBlankLinesAfterPhpdocFixer, NoEmptyPhpdocFixer, NoSuperfluousPhpdocTagsFixer, PhpdocAddMissingParamAnnotationFixer, PhpdocAlignFixer, PhpdocAlignFixer, PhpdocAnnotationWithoutDotFixer, PhpdocInlineTagFixer, PhpdocInlineTagNormalizerFixer, PhpdocLineSpanFixer, PhpdocNoAccessFixer, PhpdocNoAliasTagFixer, PhpdocNoEmptyReturnFixer, PhpdocNoPackageFixer, PhpdocNoUselessInheritdocFixer, PhpdocOrderByValueFixer, PhpdocOrderFixer, PhpdocReturnSelfReferenceFixer, PhpdocSeparationFixer, PhpdocSingleLineVarSpacingFixer, PhpdocSummaryFixer, PhpdocTagCasingFixer, PhpdocTagTypeFixer, PhpdocToCommentFixer, PhpdocToParamTypeFixer, PhpdocToReturnTypeFixer, PhpdocTrimConsecutiveBlankLineSeparationFixer, PhpdocTrimFixer, PhpdocTypesOrderFixer, PhpdocVarAnnotationCorrectOrderFixer, PhpdocVarWithoutNameFixer.
* Must run before GeneralPhpdocAnnotationRemoveFixer, GeneralPhpdocTagRenameFixer, NoBlankLinesAfterPhpdocFixer, NoEmptyPhpdocFixer, NoSuperfluousPhpdocTagsFixer, PhpdocAddMissingParamAnnotationFixer, PhpdocAlignFixer, PhpdocAlignFixer, PhpdocAnnotationWithoutDotFixer, PhpdocInlineTagFixer, PhpdocInlineTagNormalizerFixer, PhpdocLineSpanFixer, PhpdocNoAccessFixer, PhpdocNoAliasTagFixer, PhpdocNoEmptyReturnFixer, PhpdocNoPackageFixer, PhpdocNoUselessInheritdocFixer, PhpdocOrderByValueFixer, PhpdocOrderFixer, PhpdocReturnSelfReferenceFixer, PhpdocSeparationFixer, PhpdocSingleLineVarSpacingFixer, PhpdocSummaryFixer, PhpdocTagCasingFixer, PhpdocTagTypeFixer, PhpdocToCommentFixer, PhpdocToParamTypeFixer, PhpdocToPropertyTypeFixer, PhpdocToReturnTypeFixer, PhpdocTrimConsecutiveBlankLineSeparationFixer, PhpdocTrimFixer, PhpdocTypesOrderFixer, PhpdocVarAnnotationCorrectOrderFixer, PhpdocVarWithoutNameFixer.
* Must run after AlignMultilineCommentFixer.
*/
public function getPriority()
Expand Down
8 changes: 6 additions & 2 deletions src/Fixer/FunctionNotation/PhpdocToParamTypeFixer.php
Expand Up @@ -124,9 +124,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, false);

if (null === $typeInfo) {
Expand Down