33namespace ImportDetection \Sniffs \Imports ;
44
55use ImportDetection \Symbol ;
6- use ImportDetection \ImportedSymbol ;
76use ImportDetection \SniffHelpers ;
87use ImportDetection \FileSymbolRecord ;
98use PHP_CodeSniffer \Sniffs \Sniff ;
@@ -22,13 +21,17 @@ public function process(File $phpcsFile, $stackPtr) {
2221 $ helper = new SniffHelpers ();
2322 $ tokens = $ phpcsFile ->getTokens ();
2423 $ token = $ tokens [$ stackPtr ];
24+ // Keep one set of symbol records per file
2525 $ this ->symbolRecordsByFile [$ phpcsFile ->path ] = $ this ->symbolRecordsByFile [$ phpcsFile ->path ] ?? new FileSymbolRecord ;
2626 if ($ token ['type ' ] === 'T_WHITESPACE ' ) {
2727 $ this ->debug ('found whitespace ' );
2828 return $ this ->processEndOfFile ($ phpcsFile , $ stackPtr );
2929 }
3030 if ($ token ['type ' ] === 'T_USE ' ) {
3131 $ this ->debug ('found import ' );
32+ if (in_array ($ helper ->getImportType ($ phpcsFile , $ stackPtr ), ['function ' , 'const ' , 'class ' ])) {
33+ $ this ->recordImportedSymbols ($ phpcsFile , $ stackPtr );
34+ }
3235 return $ this ->processUse ($ phpcsFile , $ stackPtr );
3336 }
3437 $ symbol = $ helper ->getFullSymbol ($ phpcsFile , $ stackPtr );
@@ -150,30 +153,37 @@ private function processUse(File $phpcsFile, $stackPtr) {
150153 }
151154 }
152155
153- private function recordImportedSymbols (File $ phpcsFile , int $ stackPtr , array $ importNames ) {
154- foreach ($ importNames as $ symbol ) {
155- $ this ->symbolRecordsByFile [$ phpcsFile ->path ]->importedSymbolRecords [] = new ImportedSymbol ($ stackPtr , $ symbol );
156- }
156+ private function recordImportedSymbols (File $ phpcsFile , int $ stackPtr ) {
157+ $ helper = new SniffHelpers ();
158+ $ symbols = $ helper ->getImportedSymbolsFromImportStatement ($ phpcsFile , $ stackPtr );
159+ $ this ->debug ('recording imported symbols: ' . implode (', ' , array_map (function (Symbol $ symbol ): string {
160+ return $ symbol ->getName ();
161+ }, $ symbols )));
162+ $ symbols = array_map (function ($ symbol ) {
163+ if ($ this ->isSymbolIgnored ($ symbol )) {
164+ $ this ->debug ('found ignored imported symbol: ' . $ symbol ->getName ());
165+ $ symbol ->markUsed ();
166+ }
167+ return $ symbol ;
168+ }, $ symbols );
169+ $ this ->symbolRecordsByFile [$ phpcsFile ->path ]->addImportedSymbolRecords ($ symbols );
157170 }
158171
159172 private function saveFunctionImport (File $ phpcsFile , $ stackPtr ) {
160173 $ helper = new SniffHelpers ();
161174 $ importNames = $ helper ->getImportNames ($ phpcsFile , $ stackPtr );
162- $ this ->recordImportedSymbols ($ phpcsFile , $ stackPtr , $ importNames );
163175 $ this ->symbolRecordsByFile [$ phpcsFile ->path ]->addImportedFunctions ($ importNames );
164176 }
165177
166178 private function saveConstImport (File $ phpcsFile , $ stackPtr ) {
167179 $ helper = new SniffHelpers ();
168180 $ importNames = $ helper ->getImportNames ($ phpcsFile , $ stackPtr );
169- $ this ->recordImportedSymbols ($ phpcsFile , $ stackPtr , $ importNames );
170181 $ this ->symbolRecordsByFile [$ phpcsFile ->path ]->addImportedConsts ($ importNames );
171182 }
172183
173184 private function saveClassImport (File $ phpcsFile , $ stackPtr ) {
174185 $ helper = new SniffHelpers ();
175186 $ importNames = $ helper ->getImportNames ($ phpcsFile , $ stackPtr );
176- $ this ->recordImportedSymbols ($ phpcsFile , $ stackPtr , $ importNames );
177187 $ this ->symbolRecordsByFile [$ phpcsFile ->path ]->addImportedClasses ($ importNames );
178188 }
179189
@@ -228,16 +238,20 @@ private function isConstDefined(File $phpcsFile, string $functionName): bool {
228238 }
229239
230240 private function markSymbolUsed (File $ phpcsFile , Symbol $ symbol ) {
231- $ record = $ this ->getSymbolRecord ($ phpcsFile , $ symbol );
241+ $ record = $ this ->getRecordedImportedSymbolMatchingSymbol ($ phpcsFile , $ symbol );
232242 if (! $ record ) {
243+ // Symbol records only exist for imported symbols, so if a used symbol
244+ // has not been imported we don't need to mark anything.
245+ $ this ->debug ("ignoring marking symbol used since it was never imported: {$ symbol ->getName ()}" );
233246 return ;
234247 }
235248 $ record ->markUsed ();
236249 }
237250
238- private function getSymbolRecord (File $ phpcsFile , Symbol $ symbol ) {
251+ private function getRecordedImportedSymbolMatchingSymbol (File $ phpcsFile , Symbol $ symbol ) {
239252 foreach ($ this ->symbolRecordsByFile [$ phpcsFile ->path ]->importedSymbolRecords as $ record ) {
240- if ($ record ->getName () === $ symbol ->getTopLevelNamespace ()) {
253+ $ this ->debug ("comparing symbol {$ symbol ->getTopLevelNamespace ()} to alias {$ record ->getAlias ()}" );
254+ if ($ record ->getAlias () === $ symbol ->getTopLevelNamespace ()) {
241255 return $ record ;
242256 }
243257 }
@@ -253,8 +267,9 @@ private function processEndOfFile(File $phpcsFile, int $stackPtr) {
253267 // For each import, if the Symbol was not used, mark a warning
254268 foreach ($ this ->symbolRecordsByFile [$ phpcsFile ->path ]->importedSymbolRecords as $ record ) {
255269 if (! $ record ->isUsed ()) {
270+ $ this ->debug ("found unused symbol: {$ record ->getName ()}" );
256271 $ error = "Found unused symbol ' {$ record ->getName ()}'. " ;
257- $ phpcsFile ->addWarning ($ error , $ record ->getPtr (), 'Import ' );
272+ $ phpcsFile ->addWarning ($ error , $ record ->getSymbolPosition (), 'Import ' );
258273 }
259274 }
260275 }
0 commit comments