|
15 | 15 | use PhpCsFixer\AbstractFixer;
|
16 | 16 | use PhpCsFixer\FixerDefinition\CodeSample;
|
17 | 17 | use PhpCsFixer\FixerDefinition\FixerDefinition;
|
| 18 | +use PhpCsFixer\Tokenizer\Analyzer\NamespacesAnalyzer; |
18 | 19 | use PhpCsFixer\Tokenizer\CT;
|
19 | 20 | use PhpCsFixer\Tokenizer\Token;
|
20 | 21 | use PhpCsFixer\Tokenizer\Tokens;
|
@@ -63,40 +64,16 @@ public function isCandidate(Tokens $tokens)
|
63 | 64 | */
|
64 | 65 | protected function applyFix(\SplFileInfo $file, Tokens $tokens)
|
65 | 66 | {
|
66 |
| - $this->replaceClassKeywords($tokens); |
67 |
| - } |
| 67 | + $namespacesAnalyzer = new NamespacesAnalyzer(); |
68 | 68 |
|
69 |
| - /** |
70 |
| - * Replaces ::class keyword, namespace by namespace. |
71 |
| - * |
72 |
| - * It uses recursive method to get rid of token index changes. |
73 |
| - * |
74 |
| - * @param int $namespaceNumber |
75 |
| - */ |
76 |
| - private function replaceClassKeywords(Tokens $tokens, $namespaceNumber = -1) |
77 |
| - { |
78 |
| - $namespaceIndexes = array_keys($tokens->findGivenKind(T_NAMESPACE)); |
79 |
| - |
80 |
| - // Namespace blocks |
81 |
| - if (\count($namespaceIndexes) && isset($namespaceIndexes[$namespaceNumber])) { |
82 |
| - $startIndex = $namespaceIndexes[$namespaceNumber]; |
83 |
| - |
84 |
| - $namespaceBlockStartIndex = $tokens->getNextTokenOfKind($startIndex, [';', '{']); |
85 |
| - $endIndex = $tokens[$namespaceBlockStartIndex]->equals('{') |
86 |
| - ? $tokens->findBlockEnd(Tokens::BLOCK_TYPE_CURLY_BRACE, $namespaceBlockStartIndex) |
87 |
| - : $tokens->getNextTokenOfKind($namespaceBlockStartIndex, [T_NAMESPACE]); |
88 |
| - $endIndex = $endIndex ?: $tokens->count() - 1; |
89 |
| - } elseif (-1 === $namespaceNumber) { // Out of any namespace block |
90 |
| - $startIndex = 0; |
91 |
| - $endIndex = \count($namespaceIndexes) ? $namespaceIndexes[0] : $tokens->count() - 1; |
92 |
| - } else { |
93 |
| - return; |
| 69 | + $previousNamespaceScopeEndIndex = 0; |
| 70 | + foreach ($namespacesAnalyzer->getDeclarations($tokens) as $declaration) { |
| 71 | + $this->replaceClassKeywordsSection($tokens, '', $previousNamespaceScopeEndIndex, $declaration->getStartIndex()); |
| 72 | + $this->replaceClassKeywordsSection($tokens, $declaration->getFullName(), $declaration->getStartIndex(), $declaration->getScopeEndIndex()); |
| 73 | + $previousNamespaceScopeEndIndex = $declaration->getScopeEndIndex(); |
94 | 74 | }
|
95 | 75 |
|
96 |
| - $this->storeImports($tokens, $startIndex, $endIndex); |
97 |
| - $tokens->rewind(); |
98 |
| - $this->replaceClassKeywordsSection($tokens, $startIndex, $endIndex); |
99 |
| - $this->replaceClassKeywords($tokens, $namespaceNumber + 1); |
| 76 | + $this->replaceClassKeywordsSection($tokens, '', $previousNamespaceScopeEndIndex, $tokens->count() - 1); |
100 | 77 | }
|
101 | 78 |
|
102 | 79 | /**
|
@@ -152,21 +129,29 @@ static function ($import) {
|
152 | 129 | }
|
153 | 130 |
|
154 | 131 | /**
|
155 |
| - * @param int $startIndex |
156 |
| - * @param int $endIndex |
| 132 | + * @param string $namespace |
| 133 | + * @param int $startIndex |
| 134 | + * @param int $endIndex |
157 | 135 | */
|
158 |
| - private function replaceClassKeywordsSection(Tokens $tokens, $startIndex, $endIndex) |
| 136 | + private function replaceClassKeywordsSection(Tokens $tokens, $namespace, $startIndex, $endIndex) |
159 | 137 | {
|
| 138 | + if ($endIndex - $startIndex < 3) { |
| 139 | + return; |
| 140 | + } |
| 141 | + |
| 142 | + $this->storeImports($tokens, $startIndex, $endIndex); |
| 143 | + |
160 | 144 | $ctClassTokens = $tokens->findGivenKind(CT::T_CLASS_CONSTANT, $startIndex, $endIndex);
|
161 | 145 | foreach (array_reverse(array_keys($ctClassTokens)) as $classIndex) {
|
162 |
| - $this->replaceClassKeyword($tokens, $classIndex); |
| 146 | + $this->replaceClassKeyword($tokens, $namespace, $classIndex); |
163 | 147 | }
|
164 | 148 | }
|
165 | 149 |
|
166 | 150 | /**
|
167 |
| - * @param int $classIndex |
| 151 | + * @param string $namespace |
| 152 | + * @param int $classIndex |
168 | 153 | */
|
169 |
| - private function replaceClassKeyword(Tokens $tokens, $classIndex) |
| 154 | + private function replaceClassKeyword(Tokens $tokens, $namespace, $classIndex) |
170 | 155 | {
|
171 | 156 | $classEndIndex = $tokens->getPrevMeaningfulToken($classIndex);
|
172 | 157 | $classEndIndex = $tokens->getPrevMeaningfulToken($classEndIndex);
|
@@ -218,20 +203,21 @@ private function replaceClassKeyword(Tokens $tokens, $classIndex)
|
218 | 203 |
|
219 | 204 | $tokens->insertAt($classBeginIndex, new Token([
|
220 | 205 | T_CONSTANT_ENCAPSED_STRING,
|
221 |
| - "'".$this->makeClassFQN($classImport, $classString)."'", |
| 206 | + "'".$this->makeClassFQN($namespace, $classImport, $classString)."'", |
222 | 207 | ]));
|
223 | 208 | }
|
224 | 209 |
|
225 | 210 | /**
|
| 211 | + * @param string $namespace |
226 | 212 | * @param false|string $classImport
|
227 | 213 | * @param string $classString
|
228 | 214 | *
|
229 | 215 | * @return string
|
230 | 216 | */
|
231 |
| - private function makeClassFQN($classImport, $classString) |
| 217 | + private function makeClassFQN($namespace, $classImport, $classString) |
232 | 218 | {
|
233 | 219 | if (false === $classImport) {
|
234 |
| - return $classString; |
| 220 | + return ('' !== $namespace ? ($namespace.'\\') : '').$classString; |
235 | 221 | }
|
236 | 222 |
|
237 | 223 | $classStringArray = explode('\\', $classString);
|
|
0 commit comments