Skip to content

Commit 1275eb7

Browse files
authored
Merge pull request #6 from sirbrillig/update/fix-trait-use
Do not ignore trait usage
2 parents 43f861e + 2316477 commit 1275eb7

File tree

5 files changed

+61
-3
lines changed

5 files changed

+61
-3
lines changed

ImportDetection/SniffHelpers.php

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ public function isPredefinedClass(File $phpcsFile, $stackPtr) {
6262

6363
public function getImportType(File $phpcsFile, $stackPtr): string {
6464
$tokens = $phpcsFile->getTokens();
65+
if (! empty($tokens[$stackPtr]['conditions'])) {
66+
return 'trait-application';
67+
}
6568
$nextStringPtr = $phpcsFile->findNext([T_STRING], $stackPtr + 1);
6669
if (! $nextStringPtr) {
6770
return 'unknown';
@@ -154,7 +157,11 @@ public function isWithinNamespaceStatement(File $phpcsFile, $stackPtr): bool {
154157
return !! $phpcsFile->findPrevious([T_NAMESPACE], $stackPtr - 1, $previousStatementPtr);
155158
}
156159

157-
public function isWithinUseStatement(File $phpcsFile, $stackPtr): bool {
160+
public function isWithinImportStatement(File $phpcsFile, $stackPtr): bool {
161+
$tokens = $phpcsFile->getTokens();
162+
if (! empty($tokens[$stackPtr]['conditions'])) {
163+
return false;
164+
}
158165
$isClosureImport = $phpcsFile->findNext([T_OPEN_PARENTHESIS], $stackPtr + 1, $stackPtr + 5);
159166
if ($isClosureImport) {
160167
return false;
@@ -192,7 +199,7 @@ public function isFunctionAMethod(File $phpcsFile, $stackPtr): bool {
192199

193200
public function isSymbolADefinition(File $phpcsFile, Symbol $symbol): bool {
194201
// if the previous non-whitespace token is const, function, class, or trait, it is a definition
195-
// Note: this does not handle use statements, for that use isWithinUseStatement
202+
// Note: this does not handle use statements, for that use isWithinImportStatement
196203
$stackPtr = $symbol->getSymbolPosition();
197204
$prevToken = $this->getPreviousNonWhitespaceToken($phpcsFile, $stackPtr) ?? [];
198205
return $this->isTokenADefinition($prevToken) || $this->isWithinDefineCall($phpcsFile, $stackPtr) || $this->isWithinDeclareCall($phpcsFile, $stackPtr);

ImportDetection/Sniffs/Imports/RequireImportsSniff.php

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,60 +26,81 @@ public function process(File $phpcsFile, $stackPtr) {
2626
$tokens = $phpcsFile->getTokens();
2727
$token = $tokens[$stackPtr];
2828
if ($token['type'] === 'T_WHITESPACE') {
29+
$this->debug('found whitespace');
2930
return $this->processEndOfFile($phpcsFile, $stackPtr);
3031
}
3132
if ($token['type'] === 'T_USE') {
33+
$this->debug('found import');
3234
return $this->processUse($phpcsFile, $stackPtr);
3335
}
3436
$symbol = $helper->getFullSymbol($phpcsFile, $stackPtr);
3537
// If the symbol has been seen before (if this is a duplicate), ignore it
3638
if (in_array($symbol, $this->seenSymbols)) {
39+
$this->debug('found duplicate symbol ' . $symbol->getName());
3740
return;
3841
}
3942
$this->seenSymbols[] = $symbol;
4043
// If the symbol is in the ignore list, ignore it
4144
if ($this->isSymbolIgnored($symbol)) {
45+
$this->debug('found ignored symbol ' . $symbol->getName());
4246
$this->markSymbolUsed($symbol);
4347
return;
4448
}
4549
// If the symbol is a fully-qualified namespace, ignore it
4650
if ($symbol->isAbsoluteNamespace()) {
51+
$this->debug('found absolute namespaced symbol ' . $symbol->getName());
4752
return;
4853
}
4954
// If this symbol is a definition, ignore it
5055
if ($helper->isSymbolADefinition($phpcsFile, $symbol)) {
56+
$this->debug('found definition symbol ' . $symbol->getName());
5157
return;
5258
}
5359
// If this symbol is a static reference or an object reference, ignore it
5460
if ($helper->isStaticReference($phpcsFile, $stackPtr) || $helper->isObjectReference($phpcsFile, $stackPtr)) {
61+
$this->debug('found static symbol ' . $symbol->getName());
5562
return;
5663
}
5764
// If this symbol is a namespace definition, ignore it
5865
if ($helper->isWithinNamespaceStatement($phpcsFile, $symbol->getSymbolPosition())) {
66+
$this->debug('found namespace definition symbol ' . $symbol->getName());
5967
return;
6068
}
6169
// If this symbol is an import, ignore it
62-
if ($helper->isWithinUseStatement($phpcsFile, $symbol->getSymbolPosition())) {
70+
if ($helper->isWithinImportStatement($phpcsFile, $symbol->getSymbolPosition())) {
71+
$this->debug('found symbol inside an import ' . $symbol->getName());
6372
return;
6473
}
6574
// If the symbol is predefined, ignore it
6675
if ($helper->isPredefinedConstant($phpcsFile, $stackPtr) || $helper->isBuiltInFunction($phpcsFile, $stackPtr)) {
76+
$this->debug('found predefined symbol ' . $symbol->getName());
6777
return;
6878
}
6979
// If this symbol is a predefined typehint, ignore it
7080
if ($helper->isPredefinedTypehint($phpcsFile, $stackPtr)) {
81+
$this->debug('found typehint symbol ' . $symbol->getName());
7182
return;
7283
}
7384
// If the symbol's namespace is imported or defined, ignore it
7485
// If the symbol has no namespace and is itself is imported or defined, ignore it
7586
if ($this->isSymbolDefined($phpcsFile, $symbol)) {
87+
$this->debug('found defined symbol ' . $symbol->getName());
7688
$this->markSymbolUsed($symbol);
7789
return;
7890
}
7991
$error = "Found unimported symbol '{$symbol->getName()}'.";
8092
$phpcsFile->addWarning($error, $stackPtr, 'Symbol');
8193
}
8294

95+
private function debug(string $message) {
96+
if (! defined('PHP_CODESNIFFER_VERBOSITY')) {
97+
return;
98+
}
99+
if (PHP_CODESNIFFER_VERBOSITY > 3) {
100+
echo PHP_EOL . "RequireImportsSniff: DEBUG: $message" . PHP_EOL;
101+
}
102+
}
103+
83104
private function isSymbolIgnored(Symbol $symbol): bool {
84105
$symbolName = $symbol->getName();
85106
$pattern = $this->getIgnoredSymbolPattern();

phpcs.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@
3333

3434
<!-- variables: https://github.com/sirbrillig/VariableAnalysis/ -->
3535
<rule ref="VariableAnalysis"/>
36+
<rule ref="VariableAnalysis.CodeAnalysis.VariableAnalysis">
37+
<properties>
38+
<property name="allowUnusedCaughtExceptions" value="true"/>
39+
</properties>
40+
</rule>
3641
<rule ref="VariableAnalysis.CodeAnalysis.VariableAnalysis.UndefinedVariable">
3742
<type>error</type>
3843
</rule>

tests/Sniffs/Imports/RequireImportsSniffTest.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,4 +88,15 @@ public function testRequireImportsSniffDoesNotCountMethodNames() {
8888
$expectedLines = [ 11 ];
8989
$this->assertEquals($expectedLines, $lines);
9090
}
91+
92+
public function testRequireImportsSniffCountsTraitUseAsUsage() {
93+
$fixtureFile = __DIR__ . '/UsedTraitFixture.php';
94+
$sniffFile = __DIR__ . '/../../../ImportDetection/Sniffs/Imports/RequireImportsSniff.php';
95+
$helper = new SniffTestHelper();
96+
$phpcsFile = $helper->prepareLocalFileForSniffs($sniffFile, $fixtureFile);
97+
$phpcsFile->process();
98+
$lines = $helper->getWarningLineNumbersFromFile($phpcsFile);
99+
$expectedLines = [10];
100+
$this->assertEquals($expectedLines, $lines);
101+
}
91102
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
declare(strict_types=1);
3+
4+
namespace Services\Kitchen;
5+
6+
use Services\Appliance;
7+
8+
class Toaster {
9+
use Appliance;
10+
use UnimportedSymbol; // this should be a warning
11+
public function makeToast() {
12+
$this->energize();
13+
}
14+
}

0 commit comments

Comments
 (0)