Skip to content

Commit

Permalink
feature #3881 Add PhpdocVarAnnotationCorrectOrderFixer (kubawerlos)
Browse files Browse the repository at this point in the history
This PR was merged into the 2.14-dev branch.

Discussion
----------

Add PhpdocVarAnnotationCorrectOrderFixer

Closes #2159

Commits
-------

8e031b2 Add PhpdocVarAnnotationCorrectOrderFixer
  • Loading branch information
keradus committed Jan 1, 2019
2 parents 1c70e39 + 8e031b2 commit ea1c305
Show file tree
Hide file tree
Showing 5 changed files with 239 additions and 1 deletion.
5 changes: 5 additions & 0 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1549,6 +1549,11 @@ Choose from the list of available rules:
- ``sort_algorithm`` (``'alpha'``, ``'none'``): the sorting algorithm to apply;
defaults to ``'alpha'``

* **phpdoc_var_annotation_correct_order** [@PhpCsFixer]

``@var`` and ``@type`` annotations must have type and name in the correct
order.

* **phpdoc_var_without_name** [@Symfony, @PhpCsFixer]

``@var`` and ``@type`` annotations should not contain the variable name.
Expand Down
67 changes: 67 additions & 0 deletions src/Fixer/Phpdoc/PhpdocVarAnnotationCorrectOrderFixer.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?php

/*
* This file is part of PHP CS Fixer.
*
* (c) Fabien Potencier <fabien@symfony.com>
* Dariusz Rumiński <dariusz.ruminski@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/

namespace PhpCsFixer\Fixer\Phpdoc;

use PhpCsFixer\AbstractFixer;
use PhpCsFixer\FixerDefinition\CodeSample;
use PhpCsFixer\FixerDefinition\FixerDefinition;
use PhpCsFixer\Preg;
use PhpCsFixer\Tokenizer\Token;
use PhpCsFixer\Tokenizer\Tokens;

/**
* @author Kuba Werłos <werlos@gmail.com>
*/
final class PhpdocVarAnnotationCorrectOrderFixer extends AbstractFixer
{
public function getDefinition()
{
return new FixerDefinition(
'`@var` and `@type` annotations must have type and name in the correct order.',
[new CodeSample('<?php
/** @var $foo int */
$foo = 2 + 2;
')]
);
}

public function isCandidate(Tokens $tokens)
{
return $tokens->isTokenKindFound(T_DOC_COMMENT);
}

protected function applyFix(\SplFileInfo $file, Tokens $tokens)
{
foreach ($tokens as $index => $token) {
if (!$token->isGivenKind(T_DOC_COMMENT)) {
continue;
}

if (false === stripos($token->getContent(), '@var') && false === stripos($token->getContent(), '@type')) {
continue;
}

$newContent = Preg::replace(
'/(@(?:type|var)\s*)(\$\S+)(\s+)([^\$](?:[^<\s]|<[^>]*>)*)(\s|\*)/i',
'$1$4$3$2$5',
$token->getContent()
);

if ($newContent === $token->getContent()) {
continue;
}

$tokens[$index] = new Token([$token->getId(), $newContent]);
}
}
}
1 change: 1 addition & 0 deletions src/RuleSet.php
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ final class RuleSet implements RuleSetInterface
'phpdoc_order' => true,
'phpdoc_trim_consecutive_blank_line_separation' => true,
'phpdoc_types_order' => true,
'phpdoc_var_annotation_correct_order' => true,
'return_assignment' => true,
'single_line_comment_style' => true,
],
Expand Down
2 changes: 1 addition & 1 deletion tests/Fixer/Alias/NoAliasFunctionsFixerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ public function provideFixCases()
$cases = [];

foreach (['internalSet', 'imapSet'] as $setStaticAttributeName) {
/** @var $aliases string[] */
/** @var string[] $aliases */
$aliases = $this->getStaticAttribute(\PhpCsFixer\Fixer\Alias\NoAliasFunctionsFixer::class, $setStaticAttributeName);

foreach ($aliases as $alias => $master) {
Expand Down
165 changes: 165 additions & 0 deletions tests/Fixer/Phpdoc/PhpdocVarAnnotationCorrectOrderFixerTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
<?php

/*
* This file is part of PHP CS Fixer.
*
* (c) Fabien Potencier <fabien@symfony.com>
* Dariusz Rumiński <dariusz.ruminski@gmail.com>
*
* This source file is subject to the MIT license that is bundled
* with this source code in the file LICENSE.
*/

namespace PhpCsFixer\Tests\Fixer\Phpdoc;

use PhpCsFixer\Tests\Test\AbstractFixerTestCase;

/**
* @internal
*
* @author Kuba Werłos <werlos@gmail.com>
*
* @covers \PhpCsFixer\Fixer\Phpdoc\PhpdocVarAnnotationCorrectOrderFixer
*/
final class PhpdocVarAnnotationCorrectOrderFixerTest extends AbstractFixerTestCase
{
/**
* @param string $expected
* @param null|string $input
*
* @dataProvider provideFixCases
*/
public function testFix($expected, $input = null)
{
$this->doTest($expected, $input);
}

public function provideFixCases()
{
yield [ // It's @param, we care only about @var
'<?php /** @param $foo Foo */',
];

yield [ // This is already fine
'<?php /** @var Foo $foo */ ',
];

yield [ // What? Two variables, I'm not touching this
'<?php /** @var $foo $bar */',
];

yield [ // Two classes are not to touch either
'<?php /** @var Foo Bar */',
];

yield ['<?php /** @var */'];

yield ['<?php /** @var $foo */'];

yield ['<?php /** @var Bar */'];

yield [
'<?php
/**
* @var Foo $foo
* @var Bar $bar
*/
',
'<?php
/**
* @var $foo Foo
* @var $bar Bar
*/
',
];

yield [
'<?php
/**
* @var Foo $foo Some description
*/
',
'<?php
/**
* @var $foo Foo Some description
*/
',
];

yield [
'<?php /** @var Foo $foo */',
'<?php /** @var $foo Foo */',
];

yield [
'<?php /** @type Foo $foo */',
'<?php /** @type $foo Foo */',
];

yield [
'<?php /** @var Foo $foo*/',
'<?php /** @var $foo Foo*/',
];

yield [
'<?php /** @var Foo[] $foos */',
'<?php /** @var $foos Foo[] */',
];

yield [
'<?php /** @Var Foo $foo */',
'<?php /** @Var $foo Foo */',
];

yield [
'<?php
/** @var Foo|Bar|mixed|int $someWeirdLongNAME__123 */
',
'<?php
/** @var $someWeirdLongNAME__123 Foo|Bar|mixed|int */
',
];

yield [
'<?php
/**
* @var Foo $bar long description
* goes here
*/
',
'<?php
/**
* @var $bar Foo long description
* goes here
*/
',
];

yield [
'<?php
/** @var array<int, int> $foo */
',
'<?php
/** @var $foo array<int, int> */
',
];

yield [
'<?php
/** @var array<int, int> $foo Array of something */
',
'<?php
/** @var $foo array<int, int> Array of something */
',
];

yield [
'<?php
/** @var Foo|array<int, int>|null $foo */
',
'<?php
/** @var $foo Foo|array<int, int>|null */
',
];
}
}

0 comments on commit ea1c305

Please sign in to comment.