Skip to content

Commit 9b5f363

Browse files
committed
UnusedUsesSniff - rewritten searching in annotations to simple fulltext search
1 parent 232ef22 commit 9b5f363

File tree

3 files changed

+45
-122
lines changed

3 files changed

+45
-122
lines changed

SlevomatCodingStandard/Helpers/ReferencedNameHelper.php

Lines changed: 4 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,13 @@ class ReferencedNameHelper
2828
/**
2929
* @param \PHP_CodeSniffer_File $phpcsFile
3030
* @param integer $openTagPointer
31-
* @param boolean $searchAnnotations
3231
* @return \SlevomatCodingStandard\Helpers\ReferencedName[] referenced names
3332
*/
34-
public static function getAllReferencedNames(PHP_CodeSniffer_File $phpcsFile, $openTagPointer, $searchAnnotations = false)
33+
public static function getAllReferencedNames(PHP_CodeSniffer_File $phpcsFile, $openTagPointer)
3534
{
36-
$cacheKey = $phpcsFile->getFilename() . '-' . $openTagPointer . ($searchAnnotations ? '-annotations' : '-no-annotations');
35+
$cacheKey = $phpcsFile->getFilename() . '-' . $openTagPointer;
3736
if (!isset(self::$allReferencedTypesCache[$cacheKey])) {
38-
self::$allReferencedTypesCache[$cacheKey] = self::createAllReferencedNames($phpcsFile, $openTagPointer, $searchAnnotations);
37+
self::$allReferencedTypesCache[$cacheKey] = self::createAllReferencedNames($phpcsFile, $openTagPointer);
3938
}
4039

4140
return self::$allReferencedTypesCache[$cacheKey];
@@ -44,77 +43,22 @@ public static function getAllReferencedNames(PHP_CodeSniffer_File $phpcsFile, $o
4443
/**
4544
* @param \PHP_CodeSniffer_File $phpcsFile
4645
* @param integer $openTagPointer
47-
* @param boolean $searchAnnotations
4846
* @return \SlevomatCodingStandard\Helpers\ReferencedName[] referenced names
4947
*/
50-
private static function createAllReferencedNames(PHP_CodeSniffer_File $phpcsFile, $openTagPointer, $searchAnnotations)
48+
private static function createAllReferencedNames(PHP_CodeSniffer_File $phpcsFile, $openTagPointer)
5149
{
5250
$beginSearchAtPointer = $openTagPointer + 1;
5351
$tokens = $phpcsFile->getTokens();
54-
$phpDocTypes = [
55-
T_DOC_COMMENT_STRING,
56-
T_DOC_COMMENT_TAG,
57-
];
5852

5953
$searchTypes = array_merge([T_RETURN_TYPE], TokenHelper::$nameTokenCodes);
60-
if ($searchAnnotations) {
61-
$searchTypes = array_merge($phpDocTypes, $searchTypes);
62-
}
63-
6454
$types = [];
6555

66-
$matchTypesInAnnotation = function ($annotation, $nameStartPointer) use (&$types) {
67-
$annotation = trim($annotation, '@ ');
68-
if (preg_match('#([a-zA-Z0-9_|\[\]\\\]+)#', $annotation, $matches) > 0) {
69-
$referencedNames = array_filter(array_map(function ($name) {
70-
return trim($name, '[]');
71-
}, explode('|', $matches[1])), function ($match) {
72-
return !in_array($match, [
73-
'null',
74-
'self',
75-
'static',
76-
'mixed',
77-
'array',
78-
'string',
79-
'int',
80-
'integer',
81-
'bool',
82-
'boolean',
83-
'callable',
84-
], true);
85-
});
86-
foreach ($referencedNames as $name) {
87-
$types[] = new ReferencedName($name, $nameStartPointer, ReferencedName::TYPE_DEFAULT);
88-
}
89-
}
90-
};
91-
9256
while (true) {
9357
$nameStartPointer = $phpcsFile->findNext($searchTypes, $beginSearchAtPointer);
9458
if ($nameStartPointer === false) {
9559
break;
9660
}
9761
$nameStartToken = $tokens[$nameStartPointer];
98-
if (in_array($nameStartToken['code'], $phpDocTypes, true)) {
99-
if ($nameStartToken['code'] === T_DOC_COMMENT_TAG) {
100-
if (
101-
!StringHelper::startsWith($nameStartToken['content'], '@var')
102-
&& !StringHelper::startsWith($nameStartToken['content'], '@param')
103-
&& !StringHelper::startsWith($nameStartToken['content'], '@return')
104-
&& !StringHelper::startsWith($nameStartToken['content'], '@throws')
105-
&& !StringHelper::startsWith($nameStartToken['content'], '@see')
106-
&& !StringHelper::startsWith($nameStartToken['content'], '@link')
107-
&& !StringHelper::startsWith($nameStartToken['content'], '@inherit')
108-
) {
109-
$matchTypesInAnnotation($nameStartToken['content'], $nameStartPointer);
110-
}
111-
} elseif ($nameStartToken['code'] === T_DOC_COMMENT_STRING) {
112-
$matchTypesInAnnotation($nameStartToken['content'], $nameStartPointer);
113-
}
114-
115-
$beginSearchAtPointer = $nameStartPointer + 1;
116-
continue;
117-
}
11862
$nameEndPointer = self::findReferencedNameEndPointer($phpcsFile, $nameStartPointer);
11963
if ($nameEndPointer === null) {
12064
$beginSearchAtPointer = TokenHelper::findNextExcluding(

SlevomatCodingStandard/Sniffs/Namespaces/UnusedUsesSniff.php

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public function register()
3434
public function process(PHP_CodeSniffer_File $phpcsFile, $openTagPointer)
3535
{
3636
$unusedNames = UseStatementHelper::getUseStatements($phpcsFile, $openTagPointer);
37-
$referencedNames = ReferencedNameHelper::getAllReferencedNames($phpcsFile, $openTagPointer, $this->searchAnnotations);
37+
$referencedNames = ReferencedNameHelper::getAllReferencedNames($phpcsFile, $openTagPointer);
3838

3939
foreach ($referencedNames as $referencedName) {
4040
$name = $referencedName->getNameAsReferencedInFile();
@@ -60,6 +60,27 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $openTagPointer)
6060
}
6161
}
6262

63+
if ($this->searchAnnotations) {
64+
$tokens = $phpcsFile->getTokens();
65+
$searchAnnotationsPointer = $openTagPointer + 1;
66+
while (true) {
67+
$phpDocTokenPointer = $phpcsFile->findNext([T_DOC_COMMENT_TAG, T_DOC_COMMENT_STRING], $searchAnnotationsPointer);
68+
if ($phpDocTokenPointer === false) {
69+
break;
70+
}
71+
72+
foreach ($unusedNames as $i => $useStatement) {
73+
if (strpos($tokens[$phpDocTokenPointer]['content'], $useStatement->getNameAsReferencedInFile()) === false) {
74+
continue;
75+
}
76+
77+
unset($unusedNames[$i]);
78+
}
79+
80+
$searchAnnotationsPointer = $phpDocTokenPointer + 1;
81+
}
82+
}
83+
6384
foreach ($unusedNames as $value) {
6485
$fullName = $value->getFullyQualifiedTypeName();
6586
if ($value->getNameAsReferencedInFile() !== $fullName) {

tests/Helpers/ReferencedNameHelperTest.php

Lines changed: 19 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -5,72 +5,30 @@
55
class ReferencedNameHelperTest extends \SlevomatCodingStandard\Helpers\TestCase
66
{
77

8-
public function dataGetAllReferencedNames()
9-
{
10-
return [
11-
[
12-
[
13-
['\ExtendedClass', false, false],
14-
['\ImplementedInterface', false, false],
15-
['\FullyQualified\SomeOtherTrait', false, false],
16-
['SomeTrait', false, false],
17-
['TypehintedName', false, false],
18-
['ClassInstance', false, false],
19-
['StaticClass', false, false],
20-
['\Foo\Bar\SpecificException', false, false],
21-
['\Foo\Bar\Baz\SomeOtherException', false, false],
22-
['callToFunction', true, false],
23-
['FOO_CONSTANT', false, true],
24-
['BAZ_CONSTANT', false, true],
25-
['LoremClass', false, false],
26-
['IpsumClass', false, false],
27-
],
28-
false,
29-
],
30-
[
31-
[
32-
['\ExtendedClass', false, false],
33-
['\ImplementedInterface', false, false],
34-
['\FullyQualified\SomeOtherTrait', false, false],
35-
['SomeTrait', false, false],
36-
['ORM\Column', false, false],
37-
['Bar', false, false],
38-
['Lorem', false, false],
39-
['Ipsum', false, false],
40-
['Rasmus', false, false],
41-
['Lerdorf', false, false],
42-
['\Foo\BarBaz', false, false],
43-
['TypehintedName', false, false],
44-
['AnotherTypehintedName', false, false],
45-
['Returned_Typehinted_Underscored_Name', false, false],
46-
['TypehintedName', false, false],
47-
['ClassInstance', false, false],
48-
['StaticClass', false, false],
49-
['\Foo\Bar\SpecificException', false, false],
50-
['\Foo\Bar\Baz\SomeOtherException', false, false],
51-
['callToFunction', true, false],
52-
['FOO_CONSTANT', false, true],
53-
['BAZ_CONSTANT', false, true],
54-
['LoremClass', false, false],
55-
['IpsumClass', false, false],
56-
],
57-
true,
58-
],
59-
];
60-
}
61-
62-
/**
63-
* @dataProvider dataGetAllReferencedNames
64-
* @param string[] $foundTypes
65-
* @param boolean $searchAnnotations
66-
*/
67-
public function testGetAllReferencedNames(array $foundTypes, $searchAnnotations)
8+
public function testGetAllReferencedNames()
689
{
6910
$codeSnifferFile = $this->getCodeSnifferFile(
7011
__DIR__ . '/data/lotsOfReferencedNames.php'
7112
);
7213

73-
$names = ReferencedNameHelper::getAllReferencedNames($codeSnifferFile, 0, $searchAnnotations);
14+
$foundTypes = [
15+
['\ExtendedClass', false, false],
16+
['\ImplementedInterface', false, false],
17+
['\FullyQualified\SomeOtherTrait', false, false],
18+
['SomeTrait', false, false],
19+
['TypehintedName', false, false],
20+
['ClassInstance', false, false],
21+
['StaticClass', false, false],
22+
['\Foo\Bar\SpecificException', false, false],
23+
['\Foo\Bar\Baz\SomeOtherException', false, false],
24+
['callToFunction', true, false],
25+
['FOO_CONSTANT', false, true],
26+
['BAZ_CONSTANT', false, true],
27+
['LoremClass', false, false],
28+
['IpsumClass', false, false],
29+
];
30+
31+
$names = ReferencedNameHelper::getAllReferencedNames($codeSnifferFile, 0);
7432
$this->assertCount(count($foundTypes), $names);
7533
foreach ($names as $i => $referencedName) {
7634
$this->assertSame($foundTypes[$i][0], $referencedName->getNameAsReferencedInFile());

0 commit comments

Comments
 (0)