Mercurial > hg > isophonics-drupal-site
comparison vendor/drupal/coder/coder_sniffer/Drupal/Sniffs/Classes/UnusedUseStatementSniff.php @ 0:4c8ae668cc8c
Initial import (non-working)
author | Chris Cannam |
---|---|
date | Wed, 29 Nov 2017 16:09:58 +0000 |
parents | |
children | 129ea1e6d783 |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:4c8ae668cc8c |
---|---|
1 <?php | |
2 /** | |
3 * Drupal_Sniffs_Classes_UnusedUseStatementSniff. | |
4 * | |
5 * @category PHP | |
6 * @package PHP_CodeSniffer | |
7 * @link http://pear.php.net/package/PHP_CodeSniffer | |
8 */ | |
9 | |
10 /** | |
11 * Checks for "use" statements that are not needed in a file. | |
12 * | |
13 * @category PHP | |
14 * @package PHP_CodeSniffer | |
15 * @link http://pear.php.net/package/PHP_CodeSniffer | |
16 */ | |
17 class Drupal_Sniffs_Classes_UnusedUseStatementSniff implements PHP_CodeSniffer_Sniff | |
18 { | |
19 | |
20 | |
21 /** | |
22 * Returns an array of tokens this test wants to listen for. | |
23 * | |
24 * @return array | |
25 */ | |
26 public function register() | |
27 { | |
28 return array(T_USE); | |
29 | |
30 }//end register() | |
31 | |
32 | |
33 /** | |
34 * Processes this test, when one of its tokens is encountered. | |
35 * | |
36 * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. | |
37 * @param int $stackPtr The position of the current token in | |
38 * the stack passed in $tokens. | |
39 * | |
40 * @return void | |
41 */ | |
42 public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) | |
43 { | |
44 $tokens = $phpcsFile->getTokens(); | |
45 | |
46 // Only check use statements in the global scope. | |
47 if (empty($tokens[$stackPtr]['conditions']) === false) { | |
48 return; | |
49 } | |
50 | |
51 // Seek to the end of the statement and get the string before the semi colon. | |
52 $semiColon = $phpcsFile->findEndOfStatement($stackPtr); | |
53 if ($tokens[$semiColon]['code'] !== T_SEMICOLON) { | |
54 return; | |
55 } | |
56 | |
57 $classPtr = $phpcsFile->findPrevious( | |
58 PHP_CodeSniffer_Tokens::$emptyTokens, | |
59 ($semiColon - 1), | |
60 null, | |
61 true | |
62 ); | |
63 | |
64 if ($tokens[$classPtr]['code'] !== T_STRING) { | |
65 return; | |
66 } | |
67 | |
68 // Search where the class name is used. PHP treats class names case | |
69 // insensitive, that's why we cannot search for the exact class name string | |
70 // and need to iterate over all T_STRING tokens in the file. | |
71 $classUsed = $phpcsFile->findNext(T_STRING, ($classPtr + 1)); | |
72 $lowerClassName = strtolower($tokens[$classPtr]['content']); | |
73 | |
74 // Check if the referenced class is in the same namespace as the current | |
75 // file. If it is then the use statement is not necessary. | |
76 $namespacePtr = $phpcsFile->findPrevious([T_NAMESPACE], $stackPtr); | |
77 // Check if the use statement does aliasing with the "as" keyword. Aliasing | |
78 // is allowed even in the same namespace. | |
79 $aliasUsed = $phpcsFile->findPrevious(T_AS, ($classPtr - 1), $stackPtr); | |
80 | |
81 if ($namespacePtr !== false && $aliasUsed === false) { | |
82 $nsEnd = $phpcsFile->findNext( | |
83 [ | |
84 T_NS_SEPARATOR, | |
85 T_STRING, | |
86 T_WHITESPACE, | |
87 ], | |
88 ($namespacePtr + 1), | |
89 null, | |
90 true | |
91 ); | |
92 $namespace = trim($phpcsFile->getTokensAsString(($namespacePtr + 1), ($nsEnd - $namespacePtr - 1))); | |
93 | |
94 $useNamespacePtr = $phpcsFile->findNext([T_STRING], ($stackPtr + 1)); | |
95 $useNamespaceEnd = $phpcsFile->findNext( | |
96 [ | |
97 T_NS_SEPARATOR, | |
98 T_STRING, | |
99 ], | |
100 ($useNamespacePtr + 1), | |
101 null, | |
102 true | |
103 ); | |
104 $use_namespace = rtrim($phpcsFile->getTokensAsString($useNamespacePtr, ($useNamespaceEnd - $useNamespacePtr - 1)), '\\'); | |
105 | |
106 if (strcasecmp($namespace, $use_namespace) === 0) { | |
107 $classUsed = false; | |
108 } | |
109 }//end if | |
110 | |
111 while ($classUsed !== false) { | |
112 if (strtolower($tokens[$classUsed]['content']) === $lowerClassName) { | |
113 // If the name is used in a PHP 7 function return type declaration | |
114 // stop. | |
115 if ($tokens[$classUsed]['code'] === T_RETURN_TYPE) { | |
116 return; | |
117 } | |
118 | |
119 $beforeUsage = $phpcsFile->findPrevious( | |
120 PHP_CodeSniffer_Tokens::$emptyTokens, | |
121 ($classUsed - 1), | |
122 null, | |
123 true | |
124 ); | |
125 // If a backslash is used before the class name then this is some other | |
126 // use statement. | |
127 if ($tokens[$beforeUsage]['code'] !== T_USE && $tokens[$beforeUsage]['code'] !== T_NS_SEPARATOR) { | |
128 return; | |
129 } | |
130 | |
131 // Trait use statement within a class. | |
132 if ($tokens[$beforeUsage]['code'] === T_USE && empty($tokens[$beforeUsage]['conditions']) === false) { | |
133 return; | |
134 } | |
135 }//end if | |
136 | |
137 $classUsed = $phpcsFile->findNext([T_STRING, T_RETURN_TYPE], ($classUsed + 1)); | |
138 }//end while | |
139 | |
140 $warning = 'Unused use statement'; | |
141 $fix = $phpcsFile->addFixableWarning($warning, $stackPtr, 'UnusedUse'); | |
142 if ($fix === true) { | |
143 // Remove the whole use statement line. | |
144 $phpcsFile->fixer->beginChangeset(); | |
145 for ($i = $stackPtr; $i <= $semiColon; $i++) { | |
146 $phpcsFile->fixer->replaceToken($i, ''); | |
147 } | |
148 | |
149 // Also remove whitespace after the semicolon (new lines). | |
150 while (isset($tokens[$i]) === true && $tokens[$i]['code'] === T_WHITESPACE) { | |
151 $phpcsFile->fixer->replaceToken($i, ''); | |
152 if (strpos($tokens[$i]['content'], $phpcsFile->eolChar) !== false) { | |
153 break; | |
154 } | |
155 | |
156 $i++; | |
157 } | |
158 | |
159 // Replace @var data types in doc comments with the fully qualified class | |
160 // name. | |
161 $useNamespacePtr = $phpcsFile->findNext([T_STRING], ($stackPtr + 1)); | |
162 $useNamespaceEnd = $phpcsFile->findNext( | |
163 [ | |
164 T_NS_SEPARATOR, | |
165 T_STRING, | |
166 ], | |
167 ($useNamespacePtr + 1), | |
168 null, | |
169 true | |
170 ); | |
171 $fullNamespace = $phpcsFile->getTokensAsString($useNamespacePtr, ($useNamespaceEnd - $useNamespacePtr)); | |
172 | |
173 $tag = $phpcsFile->findNext(T_DOC_COMMENT_TAG, ($stackPtr + 1)); | |
174 | |
175 while ($tag !== false) { | |
176 if (($tokens[$tag]['content'] === '@var' || $tokens[$tag]['content'] === '@return') | |
177 && isset($tokens[($tag + 1)]) === true | |
178 && $tokens[($tag + 1)]['code'] === T_DOC_COMMENT_WHITESPACE | |
179 && isset($tokens[($tag + 2)]) === true | |
180 && $tokens[($tag + 2)]['code'] === T_DOC_COMMENT_STRING | |
181 && strpos($tokens[($tag + 2)]['content'], $tokens[$classPtr]['content']) === 0 | |
182 ) { | |
183 $replacement = '\\'.$fullNamespace.substr($tokens[($tag + 2)]['content'], strlen($tokens[$classPtr]['content'])); | |
184 $phpcsFile->fixer->replaceToken(($tag + 2), $replacement); | |
185 } | |
186 | |
187 $tag = $phpcsFile->findNext(T_DOC_COMMENT_TAG, ($tag + 1)); | |
188 } | |
189 | |
190 $phpcsFile->fixer->endChangeset(); | |
191 }//end if | |
192 | |
193 }//end process() | |
194 | |
195 | |
196 }//end class |