Skip to content

Commit

Permalink
Merge branch 'master' into console-deprecation-warnings
Browse files Browse the repository at this point in the history
  • Loading branch information
SpacePossum committed May 19, 2018
2 parents 4dc047a + 0f95a25 commit a462bdf
Show file tree
Hide file tree
Showing 12 changed files with 429 additions and 202 deletions.
3 changes: 2 additions & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -373,7 +373,8 @@ Choose from the list of available rules:

* **comment_to_phpdoc**

Comments with annotation should be docblock.
Comments with annotation should be docblock when used on structural
elements.

*Risky rule: risky as new docblocks might mean more, e.g. a Doctrine entity might have a new column in database.*

Expand Down
6 changes: 2 additions & 4 deletions src/Console/WarningsDetector.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,8 @@ public function __construct(ToolInfoInterface $toolInfo)

public function detectOldMajor()
{
/*
* @TODO 3.0 to be activated with new MAJOR release
* $this->warnings[] = 'You are running PHP CS Fixer v2, which is not maintained anymore. Please update to v3.';
*/
// @TODO 3.0 to be activated with new MAJOR release
// $this->warnings[] = 'You are running PHP CS Fixer v2, which is not maintained anymore. Please update to v3.';
}

public function detectOldVendor()
Expand Down
14 changes: 11 additions & 3 deletions src/Fixer/Comment/CommentToPhpdocFixer.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public function isRisky()
*/
public function getPriority()
{
// Should be run before PhpdocToCommentFixer
// Should be run before all other PHPDoc fixers
return 26;
}

Expand All @@ -58,8 +58,8 @@ public function getPriority()
public function getDefinition()
{
return new FixerDefinition(
'Comments with annotation should be docblock.',
[new CodeSample("<?php /* @var bool \$isFoo */\n")],
'Comments with annotation should be docblock when used on structural elements.',
[new CodeSample("<?php /* header */ \$x = true; /* @var bool \$isFoo */ \$isFoo = true;\n")],
null,
'Risky as new docblocks might mean more, e.g. a Doctrine entity might have a new column in database'
);
Expand All @@ -79,6 +79,14 @@ protected function applyFix(\SplFileInfo $file, Tokens $tokens)
continue;
}

if ($commentsAnalyzer->isHeaderComment($tokens, $index)) {
continue;
}

if (!$commentsAnalyzer->isBeforeStructuralElement($tokens, $index)) {
continue;
}

$commentIndices = $commentsAnalyzer->getCommentBlockIndices($tokens, $index);

if ($this->isCommentCandidate($tokens, $commentIndices)) {
Expand Down
3 changes: 2 additions & 1 deletion src/Fixer/ControlStructure/YodaStyleFixer.php
Original file line number Diff line number Diff line change
Expand Up @@ -558,8 +558,9 @@ private function isVariable(Tokens $tokens, $index, $end)
) {
$index = $tokens->findBlockEnd(
$next->equals('[') ? Tokens::BLOCK_TYPE_INDEX_SQUARE_BRACE : Tokens::BLOCK_TYPE_ARRAY_INDEX_CURLY_BRACE,
$index + 1
$nextIndex
);

if ($index === $end) {
return true;
}
Expand Down
155 changes: 4 additions & 151 deletions src/Fixer/Phpdoc/PhpdocToCommentFixer.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
use PhpCsFixer\AbstractFixer;
use PhpCsFixer\FixerDefinition\CodeSample;
use PhpCsFixer\FixerDefinition\FixerDefinition;
use PhpCsFixer\Tokenizer\CT;
use PhpCsFixer\Tokenizer\Analyzer\CommentsAnalyzer;
use PhpCsFixer\Tokenizer\Token;
use PhpCsFixer\Tokenizer\Tokens;

Expand Down Expand Up @@ -73,169 +73,22 @@ public function getDefinition()
*/
protected function applyFix(\SplFileInfo $file, Tokens $tokens)
{
static $controlStructures = [
T_FOREACH,
T_IF,
T_SWITCH,
T_WHILE,
T_FOR,
];

static $languageStructures = [
T_LIST,
T_PRINT,
T_ECHO,
CT::T_DESTRUCTURING_SQUARE_BRACE_OPEN,
];
$commentsAnalyzer = new CommentsAnalyzer();

foreach ($tokens as $index => $token) {
if (!$token->isGivenKind(T_DOC_COMMENT)) {
continue;
}

$nextIndex = $index;
do {
$nextIndex = $tokens->getNextMeaningfulToken($nextIndex);
} while (null !== $nextIndex && $tokens[$nextIndex]->equals('('));

if (null === $nextIndex || $tokens[$nextIndex]->equals('}')) {
$tokens[$index] = new Token([T_COMMENT, '/*'.ltrim($token->getContent(), '/*')]);

continue;
}

$nextToken = $tokens[$nextIndex];

if ($this->isStructuralElement($nextToken)) {
continue;
}

if ($nextToken->isGivenKind($controlStructures) && $this->isValidControl($tokens, $token, $nextIndex)) {
continue;
}

if ($nextToken->isGivenKind(T_VARIABLE) && $this->isValidVariable($tokens, $nextIndex)) {
if ($commentsAnalyzer->isHeaderComment($tokens, $index)) {
continue;
}

if ($nextToken->isGivenKind($languageStructures) && $this->isValidLanguageConstruct($tokens, $token, $nextIndex)) {
continue;
}

// First docblock after open tag can be file-level docblock, so its left as is.
$prevIndex = $tokens->getPrevMeaningfulToken($index);
if ($tokens[$prevIndex]->isGivenKind([T_OPEN_TAG, T_NAMESPACE])) {
if ($commentsAnalyzer->isBeforeStructuralElement($tokens, $index)) {
continue;
}

$tokens[$index] = new Token([T_COMMENT, '/*'.ltrim($token->getContent(), '/*')]);
}
}

/**
* @see https://github.com/phpDocumentor/fig-standards/blob/master/proposed/phpdoc.md#3-definitions
*
* @param Token $token
*
* @return bool
*/
private function isStructuralElement(Token $token)
{
static $skip = [
T_PRIVATE,
T_PROTECTED,
T_PUBLIC,
T_VAR,
T_FUNCTION,
T_ABSTRACT,
T_CONST,
T_NAMESPACE,
T_REQUIRE,
T_REQUIRE_ONCE,
T_INCLUDE,
T_INCLUDE_ONCE,
T_FINAL,
T_STATIC,
];

return $token->isClassy() || $token->isGivenKind($skip);
}

/**
* Checks control structures (while, if, foreach, switch) for correct docblock usage.
*
* @param Tokens $tokens
* @param Token $docsToken docs Token
* @param int $controlIndex index of control structure Token
*
* @return bool
*/
private function isValidControl(Tokens $tokens, Token $docsToken, $controlIndex)
{
$index = $tokens->getNextMeaningfulToken($controlIndex);
$endIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_PARENTHESIS_BRACE, $index);
$docsContent = $docsToken->getContent();

for ($index = $index + 1; $index < $endIndex; ++$index) {
$token = $tokens[$index];

if (
$token->isGivenKind(T_VARIABLE) &&
false !== strpos($docsContent, $token->getContent())
) {
return true;
}
}

return false;
}

/**
* Checks variable assignments through `list()`, `print()` etc. calls for correct docblock usage.
*
* @param Tokens $tokens
* @param Token $docsToken docs Token
* @param int $languageConstructIndex index of variable Token
*
* @return bool
*/
private function isValidLanguageConstruct(Tokens $tokens, Token $docsToken, $languageConstructIndex)
{
$endKind = $tokens[$languageConstructIndex]->isGivenKind(CT::T_DESTRUCTURING_SQUARE_BRACE_OPEN)
? [CT::T_DESTRUCTURING_SQUARE_BRACE_CLOSE]
: ')'
;

$endIndex = $tokens->getNextTokenOfKind($languageConstructIndex, [$endKind]);

$docsContent = $docsToken->getContent();

for ($index = $languageConstructIndex + 1; $index < $endIndex; ++$index) {
$token = $tokens[$index];

if (
$token->isGivenKind(T_VARIABLE)
&& false !== strpos($docsContent, $token->getContent())
) {
return true;
}
}

return false;
}

/**
* Checks variable assignments for correct docblock usage.
*
* @param Tokens $tokens
* @param int $variableIndex index of variable Token
*
* @return bool
*/
private function isValidVariable(Tokens $tokens, $variableIndex)
{
$nextIndex = $tokens->getNextMeaningfulToken($variableIndex);

return $tokens[$nextIndex]->equals('=');
}
}

0 comments on commit a462bdf

Please sign in to comment.