Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 4411227

Browse files
committed
feature #2708 Add PhpUnitTestClassRequiresCoversFixer (keradus)
This PR was squashed before being merged into the 2.3-dev branch (closes #2708). Discussion ---------- Add PhpUnitTestClassRequiresCoversFixer I originally used slightly modified version to add `@covers \Foo` annotations, but it wasn't generic enough to work for all cases. Here, generic version to ensure that any of those annotation is present Commits ------- 14ce819 Add PhpUnitTestClassRequiresCoversFixer
2 parents 24a0bd6 + 14ce819 commit 4411227

7 files changed

Lines changed: 430 additions & 0 deletions

File tree

.php_cs.dist

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ return PhpCsFixer\Config::create()
3131
'ordered_class_elements' => true,
3232
'ordered_imports' => true,
3333
'php_unit_strict' => true,
34+
'php_unit_test_class_requires_covers' => true,
3435
'phpdoc_add_missing_param_annotation' => true,
3536
'phpdoc_order' => true,
3637
'semicolon_after_instruction' => true,

README.rst

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -830,6 +830,11 @@ Choose from the list of available rules:
830830
``['assertAttributeEquals', 'assertAttributeNotEquals', 'assertEquals',
831831
'assertNotEquals']``
832832

833+
* **php_unit_test_class_requires_covers**
834+
835+
Adds a default ``@coversNothing`` annotation to PHPUnit test classes that
836+
have no ``@covers*`` annotation.
837+
833838
* **phpdoc_add_missing_param_annotation**
834839

835840
Phpdoc should contain @param for all params.
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
<?php
2+
3+
/*
4+
* This file is part of PHP CS Fixer.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
* Dariusz Rumiński <[email protected]>
8+
*
9+
* This source file is subject to the MIT license that is bundled
10+
* with this source code in the file LICENSE.
11+
*/
12+
13+
namespace PhpCsFixer\Fixer\PhpUnit;
14+
15+
use PhpCsFixer\AbstractFixer;
16+
use PhpCsFixer\DocBlock\DocBlock;
17+
use PhpCsFixer\DocBlock\Line;
18+
use PhpCsFixer\Fixer\WhitespacesAwareFixerInterface;
19+
use PhpCsFixer\FixerDefinition\CodeSample;
20+
use PhpCsFixer\FixerDefinition\FixerDefinition;
21+
use PhpCsFixer\Indicator\PhpUnitIndicator;
22+
use PhpCsFixer\Tokenizer\Token;
23+
use PhpCsFixer\Tokenizer\Tokens;
24+
25+
/**
26+
* @author Dariusz Rumiński <[email protected]>
27+
*/
28+
final class PhpUnitTestClassRequiresCoversFixer extends AbstractFixer implements WhitespacesAwareFixerInterface
29+
{
30+
/**
31+
* {@inheritdoc}
32+
*/
33+
public function getDefinition()
34+
{
35+
return new FixerDefinition(
36+
'Adds a default `@coversNothing` annotation to PHPUnit test classes that have no `@covers*` annotation.',
37+
[
38+
new CodeSample(
39+
'<?php
40+
final class MyTest extends \PHPUnit_Framework_TestCase
41+
{
42+
public function testSomeTest()
43+
{
44+
$this->assertSame(a(), b());
45+
}
46+
}
47+
'
48+
),
49+
]
50+
);
51+
}
52+
53+
/**
54+
* {@inheritdoc}
55+
*/
56+
public function isCandidate(Tokens $tokens)
57+
{
58+
return $tokens->isTokenKindFound(T_CLASS);
59+
}
60+
61+
/**
62+
* {@inheritdoc}
63+
*/
64+
protected function applyFix(\SplFileInfo $file, Tokens $tokens)
65+
{
66+
$phpUnitIndicator = new PhpUnitIndicator();
67+
68+
for ($index = $tokens->count() - 1; $index >= 0; --$index) {
69+
if (!$tokens[$index]->isGivenKind(T_CLASS)) {
70+
continue;
71+
}
72+
73+
if (!$phpUnitIndicator->isPhpUnitClass($tokens, $index)) {
74+
continue;
75+
}
76+
77+
$prevIndex = $tokens->getPrevMeaningfulToken($index);
78+
$index = $tokens[$prevIndex]->isGivenKind(T_FINAL) ? $prevIndex : $index;
79+
80+
$indent = $tokens[$index - 1]->isGivenKind(T_WHITESPACE)
81+
? preg_replace('/^.*\R*/', '', $tokens[$index - 1]->getContent())
82+
: '';
83+
84+
$prevIndex = $tokens->getPrevNonWhitespace($index);
85+
$doc = null;
86+
$docIndex = null;
87+
88+
if ($tokens[$prevIndex]->isGivenKind(T_DOC_COMMENT)) {
89+
$docIndex = $prevIndex;
90+
$docContent = $tokens[$docIndex]->getContent();
91+
92+
// ignore one-line phpdocs like `/** foo */`, as there is no place to put new annotations
93+
if (false === strpos($docContent, "\n")) {
94+
continue;
95+
}
96+
97+
$doc = new DocBlock($docContent);
98+
99+
// skip if already has annotation
100+
if (!empty($doc->getAnnotationsOfType([
101+
'covers',
102+
'coversDefaultClass',
103+
'coversNothing',
104+
]))) {
105+
continue;
106+
}
107+
} else {
108+
$docIndex = $index;
109+
$tokens->insertAt($docIndex, [
110+
new Token([T_DOC_COMMENT, sprintf('/**%s%s */', $this->whitespacesConfig->getLineEnding(), $indent)]),
111+
new Token([T_WHITESPACE, sprintf('%s%s', $this->whitespacesConfig->getLineEnding(), $indent)]),
112+
]);
113+
114+
if (!$tokens[$docIndex - 1]->isGivenKind(T_WHITESPACE)) {
115+
$extraNewLines = $this->whitespacesConfig->getLineEnding();
116+
117+
if (!$tokens[$docIndex - 1]->isGivenKind(T_OPEN_TAG)) {
118+
$extraNewLines .= $this->whitespacesConfig->getLineEnding();
119+
}
120+
121+
$tokens->insertAt($docIndex, [
122+
new Token([T_WHITESPACE, $extraNewLines.$indent]),
123+
]);
124+
++$docIndex;
125+
}
126+
127+
$doc = new DocBlock($tokens[$docIndex]->getContent());
128+
}
129+
130+
$lines = $doc->getLines();
131+
array_splice(
132+
$lines,
133+
count($lines) - 1,
134+
0,
135+
[
136+
new Line(sprintf(
137+
'%s * @coversNothing%s',
138+
$indent,
139+
$this->whitespacesConfig->getLineEnding()
140+
)),
141+
]
142+
);
143+
144+
$tokens[$docIndex]->setContent(implode('', $lines));
145+
}
146+
}
147+
}

src/Indicator/PhpUnitIndicator.php

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php
2+
3+
/*
4+
* This file is part of PHP CS Fixer.
5+
*
6+
* (c) Fabien Potencier <[email protected]>
7+
* Dariusz Rumiński <[email protected]>
8+
*
9+
* This source file is subject to the MIT license that is bundled
10+
* with this source code in the file LICENSE.
11+
*/
12+
13+
namespace PhpCsFixer\Indicator;
14+
15+
use PhpCsFixer\Tokenizer\Tokens;
16+
17+
/**
18+
* @internal
19+
*/
20+
final class PhpUnitIndicator
21+
{
22+
public function isPhpUnitClass(Tokens $tokens, $index)
23+
{
24+
if (!$tokens[$index]->isGivenKind(T_CLASS)) {
25+
throw new \LogicException(sprintf('No T_CLASS at given index %d, got %s.', $index, $tokens[$index]->getName()));
26+
}
27+
28+
$prevIndex = $tokens->getPrevMeaningfulToken($index);
29+
30+
if ($tokens[$prevIndex]->isGivenKind(T_ABSTRACT)) {
31+
return false;
32+
}
33+
34+
$classNameIndex = $tokens->getNextMeaningfulToken($index);
35+
if (0 !== preg_match('/(?:Test|TestCase)$/', $tokens[$classNameIndex]->getContent())) {
36+
return true;
37+
}
38+
39+
$braceIndex = $tokens->getNextTokenOfKind($index, ['{']);
40+
$maybeParentSubNameToken = $tokens[$tokens->getPrevMeaningfulToken($braceIndex)];
41+
42+
if (
43+
$maybeParentSubNameToken->isGivenKind(T_STRING) &&
44+
0 !== preg_match('/(?:Test|TestCase)$/', $maybeParentSubNameToken->getContent())
45+
) {
46+
return true;
47+
}
48+
49+
return false;
50+
}
51+
}

tests/AutoReview/ProjectCodeTest.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ final class ProjectCodeTest extends \PHPUnit_Framework_TestCase
5454
\PhpCsFixer\Fixer\Operator\AlignDoubleArrowFixerHelper::class,
5555
\PhpCsFixer\Fixer\Operator\AlignEqualsFixerHelper::class,
5656
\PhpCsFixer\Fixer\Phpdoc\GeneralPhpdocAnnotationRemoveFixer::class,
57+
\PhpCsFixer\Indicator\PhpUnitIndicator::class,
5758
\PhpCsFixer\Linter\LintingException::class,
5859
\PhpCsFixer\Linter\ProcessLintingResult::class,
5960
\PhpCsFixer\Linter\TokenizerLintingResult::class,

0 commit comments

Comments
 (0)