Chris@0
|
1 <?php
|
Chris@0
|
2 /**
|
Chris@17
|
3 * \Drupal\Sniffs\WhiteSpace\ScopeIndentSniff.
|
Chris@0
|
4 *
|
Chris@0
|
5 * @category PHP
|
Chris@0
|
6 * @package PHP_CodeSniffer
|
Chris@0
|
7 * @link http://pear.php.net/package/PHP_CodeSniffer
|
Chris@0
|
8 */
|
Chris@0
|
9
|
Chris@17
|
10 namespace Drupal\Sniffs\WhiteSpace;
|
Chris@17
|
11
|
Chris@17
|
12 use PHP_CodeSniffer\Files\File;
|
Chris@17
|
13 use PHP_CodeSniffer\Sniffs\Sniff;
|
Chris@17
|
14 use PHP_CodeSniffer\Config;
|
Chris@17
|
15 use PHP_CodeSniffer\Util\Tokens;
|
Chris@17
|
16
|
Chris@0
|
17 /**
|
Chris@17
|
18 * Largely copied from
|
Chris@17
|
19 * \PHP_CodeSniffer\Standards\Generic\Sniffs\WhiteSpace\ScopeIndentSniff,
|
Chris@17
|
20 * modified to make the exact mode working with comments and multi line
|
Chris@17
|
21 * statements.
|
Chris@0
|
22 *
|
Chris@0
|
23 * Checks that control structures are structured correctly, and their content
|
Chris@0
|
24 * is indented correctly. This sniff will throw errors if tabs are used
|
Chris@0
|
25 * for indentation rather than spaces.
|
Chris@0
|
26 *
|
Chris@0
|
27 * @category PHP
|
Chris@0
|
28 * @package PHP_CodeSniffer
|
Chris@0
|
29 * @link http://pear.php.net/package/PHP_CodeSniffer
|
Chris@0
|
30 */
|
Chris@17
|
31 class ScopeIndentSniff implements Sniff
|
Chris@0
|
32 {
|
Chris@0
|
33
|
Chris@0
|
34 /**
|
Chris@0
|
35 * A list of tokenizers this sniff supports.
|
Chris@0
|
36 *
|
Chris@0
|
37 * @var array
|
Chris@0
|
38 */
|
Chris@0
|
39 public $supportedTokenizers = array('PHP');
|
Chris@0
|
40
|
Chris@0
|
41 /**
|
Chris@0
|
42 * The number of spaces code should be indented.
|
Chris@0
|
43 *
|
Chris@0
|
44 * @var int
|
Chris@0
|
45 */
|
Chris@0
|
46 public $indent = 2;
|
Chris@0
|
47
|
Chris@0
|
48 /**
|
Chris@0
|
49 * Does the indent need to be exactly right?
|
Chris@0
|
50 *
|
Chris@0
|
51 * If TRUE, indent needs to be exactly $indent spaces. If FALSE,
|
Chris@0
|
52 * indent needs to be at least $indent spaces (but can be more).
|
Chris@0
|
53 *
|
Chris@0
|
54 * @var bool
|
Chris@0
|
55 */
|
Chris@0
|
56 public $exact = true;
|
Chris@0
|
57
|
Chris@0
|
58 /**
|
Chris@0
|
59 * Should tabs be used for indenting?
|
Chris@0
|
60 *
|
Chris@0
|
61 * If TRUE, fixes will be made using tabs instead of spaces.
|
Chris@0
|
62 * The size of each tab is important, so it should be specified
|
Chris@0
|
63 * using the --tab-width CLI argument.
|
Chris@0
|
64 *
|
Chris@0
|
65 * @var bool
|
Chris@0
|
66 */
|
Chris@0
|
67 public $tabIndent = false;
|
Chris@0
|
68
|
Chris@0
|
69 /**
|
Chris@0
|
70 * The --tab-width CLI value that is being used.
|
Chris@0
|
71 *
|
Chris@0
|
72 * @var int
|
Chris@0
|
73 */
|
Chris@0
|
74 private $_tabWidth = null;
|
Chris@0
|
75
|
Chris@0
|
76 /**
|
Chris@0
|
77 * List of tokens not needing to be checked for indentation.
|
Chris@0
|
78 *
|
Chris@0
|
79 * Useful to allow Sniffs based on this to easily ignore/skip some
|
Chris@0
|
80 * tokens from verification. For example, inline HTML sections
|
Chris@0
|
81 * or PHP open/close tags can escape from here and have their own
|
Chris@0
|
82 * rules elsewhere.
|
Chris@0
|
83 *
|
Chris@0
|
84 * @var int[]
|
Chris@0
|
85 */
|
Chris@0
|
86 public $ignoreIndentationTokens = array();
|
Chris@0
|
87
|
Chris@0
|
88 /**
|
Chris@0
|
89 * List of tokens not needing to be checked for indentation.
|
Chris@0
|
90 *
|
Chris@0
|
91 * This is a cached copy of the public version of this var, which
|
Chris@0
|
92 * can be set in a ruleset file, and some core ignored tokens.
|
Chris@0
|
93 *
|
Chris@0
|
94 * @var int[]
|
Chris@0
|
95 */
|
Chris@0
|
96 private $_ignoreIndentationTokens = array();
|
Chris@0
|
97
|
Chris@0
|
98 /**
|
Chris@0
|
99 * Any scope openers that should not cause an indent.
|
Chris@0
|
100 *
|
Chris@0
|
101 * @var int[]
|
Chris@0
|
102 */
|
Chris@0
|
103 protected $nonIndentingScopes = array();
|
Chris@0
|
104
|
Chris@0
|
105 /**
|
Chris@0
|
106 * Show debug output for this sniff.
|
Chris@0
|
107 *
|
Chris@0
|
108 * @var bool
|
Chris@0
|
109 */
|
Chris@0
|
110 private $_debug = false;
|
Chris@0
|
111
|
Chris@0
|
112
|
Chris@0
|
113 /**
|
Chris@0
|
114 * Returns an array of tokens this test wants to listen for.
|
Chris@0
|
115 *
|
Chris@0
|
116 * @return array
|
Chris@0
|
117 */
|
Chris@0
|
118 public function register()
|
Chris@0
|
119 {
|
Chris@0
|
120 if (defined('PHP_CODESNIFFER_IN_TESTS') === true) {
|
Chris@0
|
121 $this->_debug = false;
|
Chris@0
|
122 }
|
Chris@0
|
123
|
Chris@0
|
124 return array(T_OPEN_TAG);
|
Chris@0
|
125
|
Chris@0
|
126 }//end register()
|
Chris@0
|
127
|
Chris@0
|
128
|
Chris@0
|
129 /**
|
Chris@0
|
130 * Processes this test, when one of its tokens is encountered.
|
Chris@0
|
131 *
|
Chris@17
|
132 * @param \PHP_CodeSniffer\Files\File $phpcsFile All the tokens found in the document.
|
Chris@17
|
133 * @param int $stackPtr The position of the current token
|
Chris@17
|
134 * in the stack passed in $tokens.
|
Chris@0
|
135 *
|
Chris@0
|
136 * @return void
|
Chris@0
|
137 */
|
Chris@17
|
138 public function process(File $phpcsFile, $stackPtr)
|
Chris@0
|
139 {
|
Chris@17
|
140 $debug = Config::getConfigData('scope_indent_debug');
|
Chris@0
|
141 if ($debug !== null) {
|
Chris@0
|
142 $this->_debug = (bool) $debug;
|
Chris@0
|
143 }
|
Chris@0
|
144
|
Chris@0
|
145 if ($this->_tabWidth === null) {
|
Chris@17
|
146 $config = $phpcsFile->config;
|
Chris@17
|
147 if (isset($config->tabWidth) === false || $config->tabWidth === 0) {
|
Chris@0
|
148 // We have no idea how wide tabs are, so assume 4 spaces for fixing.
|
Chris@0
|
149 // It shouldn't really matter because indent checks elsewhere in the
|
Chris@0
|
150 // standard should fix things up.
|
Chris@0
|
151 $this->_tabWidth = 4;
|
Chris@0
|
152 } else {
|
Chris@17
|
153 $this->_tabWidth = $config->tabWidth;
|
Chris@0
|
154 }
|
Chris@0
|
155 }
|
Chris@0
|
156
|
Chris@0
|
157 $currentIndent = 0;
|
Chris@0
|
158 $lastOpenTag = $stackPtr;
|
Chris@0
|
159 $lastCloseTag = null;
|
Chris@0
|
160 $openScopes = array();
|
Chris@0
|
161 $adjustments = array();
|
Chris@0
|
162 $setIndents = array();
|
Chris@0
|
163
|
Chris@0
|
164 $tokens = $phpcsFile->getTokens();
|
Chris@0
|
165 $first = $phpcsFile->findFirstOnLine(T_INLINE_HTML, $stackPtr);
|
Chris@0
|
166 $trimmed = ltrim($tokens[$first]['content']);
|
Chris@0
|
167 if ($trimmed === '') {
|
Chris@0
|
168 $currentIndent = ($tokens[$stackPtr]['column'] - 1);
|
Chris@0
|
169 } else {
|
Chris@0
|
170 $currentIndent = (strlen($tokens[$first]['content']) - strlen($trimmed));
|
Chris@0
|
171 }
|
Chris@0
|
172
|
Chris@0
|
173 if ($this->_debug === true) {
|
Chris@0
|
174 $line = $tokens[$stackPtr]['line'];
|
Chris@0
|
175 echo "Start with token $stackPtr on line $line with indent $currentIndent".PHP_EOL;
|
Chris@0
|
176 }
|
Chris@0
|
177
|
Chris@0
|
178 if (empty($this->_ignoreIndentationTokens) === true) {
|
Chris@0
|
179 $this->_ignoreIndentationTokens = array(T_INLINE_HTML => true);
|
Chris@0
|
180 foreach ($this->ignoreIndentationTokens as $token) {
|
Chris@0
|
181 if (is_int($token) === false) {
|
Chris@0
|
182 if (defined($token) === false) {
|
Chris@0
|
183 continue;
|
Chris@0
|
184 }
|
Chris@0
|
185
|
Chris@0
|
186 $token = constant($token);
|
Chris@0
|
187 }
|
Chris@0
|
188
|
Chris@0
|
189 $this->_ignoreIndentationTokens[$token] = true;
|
Chris@0
|
190 }
|
Chris@0
|
191 }//end if
|
Chris@0
|
192
|
Chris@0
|
193 $this->exact = (bool) $this->exact;
|
Chris@0
|
194 $this->tabIndent = (bool) $this->tabIndent;
|
Chris@0
|
195
|
Chris@0
|
196 for ($i = ($stackPtr + 1); $i < $phpcsFile->numTokens; $i++) {
|
Chris@0
|
197 if ($i === false) {
|
Chris@0
|
198 // Something has gone very wrong; maybe a parse error.
|
Chris@0
|
199 break;
|
Chris@0
|
200 }
|
Chris@0
|
201
|
Chris@0
|
202 $checkToken = null;
|
Chris@0
|
203 $checkIndent = null;
|
Chris@0
|
204
|
Chris@0
|
205 $exact = (bool) $this->exact;
|
Chris@0
|
206 if ($exact === true && isset($tokens[$i]['nested_parenthesis']) === true) {
|
Chris@0
|
207 // Don't check indents exactly between parenthesis as they
|
Chris@0
|
208 // tend to have custom rules, such as with multi-line function calls
|
Chris@0
|
209 // and control structure conditions.
|
Chris@0
|
210 $exact = false;
|
Chris@0
|
211 }
|
Chris@0
|
212
|
Chris@0
|
213 // Detect line changes and figure out where the indent is.
|
Chris@0
|
214 if ($tokens[$i]['column'] === 1) {
|
Chris@0
|
215 $trimmed = ltrim($tokens[$i]['content']);
|
Chris@0
|
216 if ($trimmed === '') {
|
Chris@0
|
217 if (isset($tokens[($i + 1)]) === true
|
Chris@0
|
218 && $tokens[$i]['line'] === $tokens[($i + 1)]['line']
|
Chris@0
|
219 ) {
|
Chris@0
|
220 $checkToken = ($i + 1);
|
Chris@0
|
221 $tokenIndent = ($tokens[($i + 1)]['column'] - 1);
|
Chris@0
|
222 }
|
Chris@0
|
223 } else {
|
Chris@0
|
224 $checkToken = $i;
|
Chris@0
|
225 $tokenIndent = (strlen($tokens[$i]['content']) - strlen($trimmed));
|
Chris@0
|
226 }
|
Chris@0
|
227 }
|
Chris@0
|
228
|
Chris@0
|
229 // Closing parenthesis should just be indented to at least
|
Chris@0
|
230 // the same level as where they were opened (but can be more).
|
Chris@0
|
231 if (($checkToken !== null
|
Chris@0
|
232 && $tokens[$checkToken]['code'] === T_CLOSE_PARENTHESIS
|
Chris@0
|
233 && isset($tokens[$checkToken]['parenthesis_opener']) === true)
|
Chris@0
|
234 || ($tokens[$i]['code'] === T_CLOSE_PARENTHESIS
|
Chris@0
|
235 && isset($tokens[$i]['parenthesis_opener']) === true)
|
Chris@0
|
236 ) {
|
Chris@0
|
237 if ($checkToken !== null) {
|
Chris@0
|
238 $parenCloser = $checkToken;
|
Chris@0
|
239 } else {
|
Chris@0
|
240 $parenCloser = $i;
|
Chris@0
|
241 }
|
Chris@0
|
242
|
Chris@0
|
243 if ($this->_debug === true) {
|
Chris@0
|
244 $line = $tokens[$i]['line'];
|
Chris@0
|
245 echo "Closing parenthesis found on line $line".PHP_EOL;
|
Chris@0
|
246 }
|
Chris@0
|
247
|
Chris@0
|
248 $parenOpener = $tokens[$parenCloser]['parenthesis_opener'];
|
Chris@0
|
249 if ($tokens[$parenCloser]['line'] !== $tokens[$parenOpener]['line']) {
|
Chris@0
|
250 $parens = 0;
|
Chris@0
|
251 if (isset($tokens[$parenCloser]['nested_parenthesis']) === true
|
Chris@0
|
252 && empty($tokens[$parenCloser]['nested_parenthesis']) === false
|
Chris@0
|
253 ) {
|
Chris@0
|
254 end($tokens[$parenCloser]['nested_parenthesis']);
|
Chris@0
|
255 $parens = key($tokens[$parenCloser]['nested_parenthesis']);
|
Chris@0
|
256 if ($this->_debug === true) {
|
Chris@0
|
257 $line = $tokens[$parens]['line'];
|
Chris@0
|
258 echo "\t* token has nested parenthesis $parens on line $line *".PHP_EOL;
|
Chris@0
|
259 }
|
Chris@0
|
260 }
|
Chris@0
|
261
|
Chris@0
|
262 $condition = 0;
|
Chris@0
|
263 if (isset($tokens[$parenCloser]['conditions']) === true
|
Chris@0
|
264 && empty($tokens[$parenCloser]['conditions']) === false
|
Chris@0
|
265 ) {
|
Chris@0
|
266 end($tokens[$parenCloser]['conditions']);
|
Chris@0
|
267 $condition = key($tokens[$parenCloser]['conditions']);
|
Chris@0
|
268 if ($this->_debug === true) {
|
Chris@0
|
269 $line = $tokens[$condition]['line'];
|
Chris@0
|
270 $type = $tokens[$condition]['type'];
|
Chris@0
|
271 echo "\t* token is inside condition $condition ($type) on line $line *".PHP_EOL;
|
Chris@0
|
272 }
|
Chris@0
|
273 }
|
Chris@0
|
274
|
Chris@0
|
275 if ($parens > $condition) {
|
Chris@0
|
276 if ($this->_debug === true) {
|
Chris@0
|
277 echo "\t* using parenthesis *".PHP_EOL;
|
Chris@0
|
278 }
|
Chris@0
|
279
|
Chris@0
|
280 $parenOpener = $parens;
|
Chris@0
|
281 $condition = 0;
|
Chris@0
|
282 } else if ($condition > 0) {
|
Chris@0
|
283 if ($this->_debug === true) {
|
Chris@0
|
284 echo "\t* using condition *".PHP_EOL;
|
Chris@0
|
285 }
|
Chris@0
|
286
|
Chris@0
|
287 $parenOpener = $condition;
|
Chris@0
|
288 $parens = 0;
|
Chris@0
|
289 }
|
Chris@0
|
290
|
Chris@0
|
291 $exact = false;
|
Chris@0
|
292
|
Chris@0
|
293 $lastOpenTagConditions = array_keys($tokens[$lastOpenTag]['conditions']);
|
Chris@0
|
294 $lastOpenTagCondition = array_pop($lastOpenTagConditions);
|
Chris@0
|
295
|
Chris@0
|
296 if ($condition > 0 && $lastOpenTagCondition === $condition) {
|
Chris@0
|
297 if ($this->_debug === true) {
|
Chris@0
|
298 echo "\t* open tag is inside condition; using open tag *".PHP_EOL;
|
Chris@0
|
299 }
|
Chris@0
|
300
|
Chris@0
|
301 $checkIndent = ($tokens[$lastOpenTag]['column'] - 1);
|
Chris@0
|
302 if (isset($adjustments[$condition]) === true) {
|
Chris@0
|
303 $checkIndent += $adjustments[$condition];
|
Chris@0
|
304 }
|
Chris@0
|
305
|
Chris@0
|
306 $currentIndent = $checkIndent;
|
Chris@0
|
307
|
Chris@0
|
308 if ($this->_debug === true) {
|
Chris@0
|
309 $type = $tokens[$lastOpenTag]['type'];
|
Chris@0
|
310 echo "\t=> checking indent of $checkIndent; main indent set to $currentIndent by token $lastOpenTag ($type)".PHP_EOL;
|
Chris@0
|
311 }
|
Chris@0
|
312 } else if ($condition > 0
|
Chris@0
|
313 && isset($tokens[$condition]['scope_opener']) === true
|
Chris@0
|
314 && isset($setIndents[$tokens[$condition]['scope_opener']]) === true
|
Chris@0
|
315 ) {
|
Chris@0
|
316 $checkIndent = $setIndents[$tokens[$condition]['scope_opener']];
|
Chris@0
|
317 if (isset($adjustments[$condition]) === true) {
|
Chris@0
|
318 $checkIndent += $adjustments[$condition];
|
Chris@0
|
319 }
|
Chris@0
|
320
|
Chris@0
|
321 $currentIndent = $checkIndent;
|
Chris@0
|
322
|
Chris@0
|
323 if ($this->_debug === true) {
|
Chris@0
|
324 $type = $tokens[$condition]['type'];
|
Chris@0
|
325 echo "\t=> checking indent of $checkIndent; main indent set to $currentIndent by token $condition ($type)".PHP_EOL;
|
Chris@0
|
326 }
|
Chris@0
|
327 } else {
|
Chris@0
|
328 $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $parenOpener, true);
|
Chris@0
|
329
|
Chris@0
|
330 $checkIndent = ($tokens[$first]['column'] - 1);
|
Chris@0
|
331 if (isset($adjustments[$first]) === true) {
|
Chris@0
|
332 $checkIndent += $adjustments[$first];
|
Chris@0
|
333 }
|
Chris@0
|
334
|
Chris@0
|
335 if ($this->_debug === true) {
|
Chris@0
|
336 $line = $tokens[$first]['line'];
|
Chris@0
|
337 $type = $tokens[$first]['type'];
|
Chris@0
|
338 echo "\t* first token on line $line is $first ($type) *".PHP_EOL;
|
Chris@0
|
339 }
|
Chris@0
|
340
|
Chris@0
|
341 if ($first === $tokens[$parenCloser]['parenthesis_opener']) {
|
Chris@0
|
342 // This is unlikely to be the start of the statement, so look
|
Chris@0
|
343 // back further to find it.
|
Chris@0
|
344 $first--;
|
Chris@0
|
345 }
|
Chris@0
|
346
|
Chris@0
|
347 $prev = $phpcsFile->findStartOfStatement($first, T_COMMA);
|
Chris@0
|
348 if ($prev !== $first) {
|
Chris@0
|
349 // This is not the start of the statement.
|
Chris@0
|
350 if ($this->_debug === true) {
|
Chris@0
|
351 $line = $tokens[$prev]['line'];
|
Chris@0
|
352 $type = $tokens[$prev]['type'];
|
Chris@0
|
353 echo "\t* previous is $type on line $line *".PHP_EOL;
|
Chris@0
|
354 }
|
Chris@0
|
355
|
Chris@0
|
356 $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $prev, true);
|
Chris@0
|
357 $prev = $phpcsFile->findStartOfStatement($first, T_COMMA);
|
Chris@0
|
358 $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $prev, true);
|
Chris@0
|
359 if ($this->_debug === true) {
|
Chris@0
|
360 $line = $tokens[$first]['line'];
|
Chris@0
|
361 $type = $tokens[$first]['type'];
|
Chris@0
|
362 echo "\t* amended first token is $first ($type) on line $line *".PHP_EOL;
|
Chris@0
|
363 }
|
Chris@0
|
364 }
|
Chris@0
|
365
|
Chris@0
|
366 if (isset($tokens[$first]['scope_closer']) === true
|
Chris@0
|
367 && $tokens[$first]['scope_closer'] === $first
|
Chris@0
|
368 ) {
|
Chris@0
|
369 if ($this->_debug === true) {
|
Chris@0
|
370 echo "\t* first token is a scope closer *".PHP_EOL;
|
Chris@0
|
371 }
|
Chris@0
|
372
|
Chris@0
|
373 if (isset($tokens[$first]['scope_condition']) === true) {
|
Chris@0
|
374 $scopeCloser = $first;
|
Chris@0
|
375 $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $tokens[$scopeCloser]['scope_condition'], true);
|
Chris@0
|
376
|
Chris@0
|
377 $currentIndent = ($tokens[$first]['column'] - 1);
|
Chris@0
|
378 if (isset($adjustments[$first]) === true) {
|
Chris@0
|
379 $currentIndent += $adjustments[$first];
|
Chris@0
|
380 }
|
Chris@0
|
381
|
Chris@0
|
382 // Make sure it is divisible by our expected indent.
|
Chris@0
|
383 if ($tokens[$tokens[$scopeCloser]['scope_condition']]['code'] !== T_CLOSURE) {
|
Chris@0
|
384 $currentIndent = (int) (ceil($currentIndent / $this->indent) * $this->indent);
|
Chris@0
|
385 }
|
Chris@0
|
386
|
Chris@0
|
387 $setIndents[$first] = $currentIndent;
|
Chris@0
|
388
|
Chris@0
|
389 if ($this->_debug === true) {
|
Chris@0
|
390 $type = $tokens[$first]['type'];
|
Chris@0
|
391 echo "\t=> indent set to $currentIndent by token $first ($type)".PHP_EOL;
|
Chris@0
|
392 }
|
Chris@0
|
393 }//end if
|
Chris@0
|
394 } else {
|
Chris@0
|
395 // Don't force current indent to divisible because there could be custom
|
Chris@0
|
396 // rules in place between parenthesis, such as with arrays.
|
Chris@0
|
397 $currentIndent = ($tokens[$first]['column'] - 1);
|
Chris@0
|
398 if (isset($adjustments[$first]) === true) {
|
Chris@0
|
399 $currentIndent += $adjustments[$first];
|
Chris@0
|
400 }
|
Chris@0
|
401
|
Chris@0
|
402 $setIndents[$first] = $currentIndent;
|
Chris@0
|
403
|
Chris@0
|
404 if ($this->_debug === true) {
|
Chris@0
|
405 $type = $tokens[$first]['type'];
|
Chris@0
|
406 echo "\t=> checking indent of $checkIndent; main indent set to $currentIndent by token $first ($type)".PHP_EOL;
|
Chris@0
|
407 }
|
Chris@0
|
408 }//end if
|
Chris@0
|
409 }//end if
|
Chris@0
|
410 } else if ($this->_debug === true) {
|
Chris@0
|
411 echo "\t * ignoring single-line definition *".PHP_EOL;
|
Chris@0
|
412 }//end if
|
Chris@0
|
413 }//end if
|
Chris@0
|
414
|
Chris@0
|
415 // Closing short array bracket should just be indented to at least
|
Chris@0
|
416 // the same level as where it was opened (but can be more).
|
Chris@0
|
417 if ($tokens[$i]['code'] === T_CLOSE_SHORT_ARRAY
|
Chris@0
|
418 || ($checkToken !== null
|
Chris@0
|
419 && $tokens[$checkToken]['code'] === T_CLOSE_SHORT_ARRAY)
|
Chris@0
|
420 ) {
|
Chris@0
|
421 if ($checkToken !== null) {
|
Chris@0
|
422 $arrayCloser = $checkToken;
|
Chris@0
|
423 } else {
|
Chris@0
|
424 $arrayCloser = $i;
|
Chris@0
|
425 }
|
Chris@0
|
426
|
Chris@0
|
427 if ($this->_debug === true) {
|
Chris@0
|
428 $line = $tokens[$arrayCloser]['line'];
|
Chris@0
|
429 echo "Closing short array bracket found on line $line".PHP_EOL;
|
Chris@0
|
430 }
|
Chris@0
|
431
|
Chris@0
|
432 $arrayOpener = $tokens[$arrayCloser]['bracket_opener'];
|
Chris@0
|
433 if ($tokens[$arrayCloser]['line'] !== $tokens[$arrayOpener]['line']) {
|
Chris@0
|
434 $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $arrayOpener, true);
|
Chris@0
|
435 $checkIndent = ($tokens[$first]['column'] - 1);
|
Chris@0
|
436 if (isset($adjustments[$first]) === true) {
|
Chris@0
|
437 $checkIndent += $adjustments[$first];
|
Chris@0
|
438 }
|
Chris@0
|
439
|
Chris@0
|
440 $exact = false;
|
Chris@0
|
441
|
Chris@0
|
442 if ($this->_debug === true) {
|
Chris@0
|
443 $line = $tokens[$first]['line'];
|
Chris@0
|
444 $type = $tokens[$first]['type'];
|
Chris@0
|
445 echo "\t* first token on line $line is $first ($type) *".PHP_EOL;
|
Chris@0
|
446 }
|
Chris@0
|
447
|
Chris@0
|
448 if ($first === $tokens[$arrayCloser]['bracket_opener']) {
|
Chris@0
|
449 // This is unlikely to be the start of the statement, so look
|
Chris@0
|
450 // back further to find it.
|
Chris@0
|
451 $first--;
|
Chris@0
|
452 }
|
Chris@0
|
453
|
Chris@0
|
454 $prev = $phpcsFile->findStartOfStatement($first, T_COMMA);
|
Chris@0
|
455 if ($prev !== $first) {
|
Chris@0
|
456 // This is not the start of the statement.
|
Chris@0
|
457 if ($this->_debug === true) {
|
Chris@0
|
458 $line = $tokens[$prev]['line'];
|
Chris@0
|
459 $type = $tokens[$prev]['type'];
|
Chris@0
|
460 echo "\t* previous is $type on line $line *".PHP_EOL;
|
Chris@0
|
461 }
|
Chris@0
|
462
|
Chris@0
|
463 $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $prev, true);
|
Chris@0
|
464 $prev = $phpcsFile->findStartOfStatement($first, T_COMMA);
|
Chris@0
|
465 $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $prev, true);
|
Chris@0
|
466 if ($this->_debug === true) {
|
Chris@0
|
467 $line = $tokens[$first]['line'];
|
Chris@0
|
468 $type = $tokens[$first]['type'];
|
Chris@0
|
469 echo "\t* amended first token is $first ($type) on line $line *".PHP_EOL;
|
Chris@0
|
470 }
|
Chris@0
|
471 }
|
Chris@0
|
472
|
Chris@0
|
473 if (isset($tokens[$first]['scope_closer']) === true
|
Chris@0
|
474 && $tokens[$first]['scope_closer'] === $first
|
Chris@0
|
475 ) {
|
Chris@0
|
476 // The first token is a scope closer and would have already
|
Chris@0
|
477 // been processed and set the indent level correctly, so
|
Chris@0
|
478 // don't adjust it again.
|
Chris@0
|
479 if ($this->_debug === true) {
|
Chris@0
|
480 echo "\t* first token is a scope closer; ignoring closing short array bracket *".PHP_EOL;
|
Chris@0
|
481 }
|
Chris@0
|
482
|
Chris@0
|
483 if (isset($setIndents[$first]) === true) {
|
Chris@0
|
484 $currentIndent = $setIndents[$first];
|
Chris@0
|
485 if ($this->_debug === true) {
|
Chris@0
|
486 echo "\t=> indent reset to $currentIndent".PHP_EOL;
|
Chris@0
|
487 }
|
Chris@0
|
488 }
|
Chris@0
|
489 } else {
|
Chris@0
|
490 // Don't force current indent to be divisible because there could be custom
|
Chris@0
|
491 // rules in place for arrays.
|
Chris@0
|
492 $currentIndent = ($tokens[$first]['column'] - 1);
|
Chris@0
|
493 if (isset($adjustments[$first]) === true) {
|
Chris@0
|
494 $currentIndent += $adjustments[$first];
|
Chris@0
|
495 }
|
Chris@0
|
496
|
Chris@0
|
497 $setIndents[$first] = $currentIndent;
|
Chris@0
|
498
|
Chris@0
|
499 if ($this->_debug === true) {
|
Chris@0
|
500 $type = $tokens[$first]['type'];
|
Chris@0
|
501 echo "\t=> checking indent of $checkIndent; main indent set to $currentIndent by token $first ($type)".PHP_EOL;
|
Chris@0
|
502 }
|
Chris@0
|
503 }//end if
|
Chris@0
|
504 } else if ($this->_debug === true) {
|
Chris@0
|
505 echo "\t * ignoring single-line definition *".PHP_EOL;
|
Chris@0
|
506 }//end if
|
Chris@0
|
507 }//end if
|
Chris@0
|
508
|
Chris@0
|
509 // Adjust lines within scopes while auto-fixing.
|
Chris@0
|
510 if ($checkToken !== null
|
Chris@0
|
511 && $exact === false
|
Chris@0
|
512 && (empty($tokens[$checkToken]['conditions']) === false
|
Chris@0
|
513 || (isset($tokens[$checkToken]['scope_opener']) === true
|
Chris@0
|
514 && $tokens[$checkToken]['scope_opener'] === $checkToken))
|
Chris@0
|
515 ) {
|
Chris@0
|
516 if (empty($tokens[$checkToken]['conditions']) === false) {
|
Chris@0
|
517 end($tokens[$checkToken]['conditions']);
|
Chris@0
|
518 $condition = key($tokens[$checkToken]['conditions']);
|
Chris@0
|
519 } else {
|
Chris@0
|
520 $condition = $tokens[$checkToken]['scope_condition'];
|
Chris@0
|
521 }
|
Chris@0
|
522
|
Chris@0
|
523 $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $condition, true);
|
Chris@0
|
524
|
Chris@0
|
525 if (isset($adjustments[$first]) === true
|
Chris@0
|
526 && (($adjustments[$first] < 0 && $tokenIndent > $currentIndent)
|
Chris@0
|
527 || ($adjustments[$first] > 0 && $tokenIndent < $currentIndent))
|
Chris@0
|
528 ) {
|
Chris@0
|
529 $padding = ($tokenIndent + $adjustments[$first]);
|
Chris@0
|
530 if ($padding > 0) {
|
Chris@0
|
531 if ($this->tabIndent === true) {
|
Chris@0
|
532 $numTabs = floor($padding / $this->_tabWidth);
|
Chris@0
|
533 $numSpaces = ($padding - ($numTabs * $this->_tabWidth));
|
Chris@0
|
534 $padding = str_repeat("\t", $numTabs).str_repeat(' ', $numSpaces);
|
Chris@0
|
535 } else {
|
Chris@0
|
536 $padding = str_repeat(' ', $padding);
|
Chris@0
|
537 }
|
Chris@0
|
538 } else {
|
Chris@0
|
539 $padding = '';
|
Chris@0
|
540 }
|
Chris@0
|
541
|
Chris@0
|
542 if ($checkToken === $i) {
|
Chris@0
|
543 $phpcsFile->fixer->replaceToken($checkToken, $padding.$trimmed);
|
Chris@0
|
544 } else {
|
Chris@0
|
545 // Easier to just replace the entire indent.
|
Chris@0
|
546 $phpcsFile->fixer->replaceToken(($checkToken - 1), $padding);
|
Chris@0
|
547 }
|
Chris@0
|
548
|
Chris@0
|
549 if ($this->_debug === true) {
|
Chris@0
|
550 $length = strlen($padding);
|
Chris@0
|
551 $line = $tokens[$checkToken]['line'];
|
Chris@0
|
552 $type = $tokens[$checkToken]['type'];
|
Chris@0
|
553 echo "Indent adjusted to $length for $type on line $line".PHP_EOL;
|
Chris@0
|
554 }
|
Chris@0
|
555
|
Chris@0
|
556 $adjustments[$checkToken] = $adjustments[$first];
|
Chris@0
|
557
|
Chris@0
|
558 if ($this->_debug === true) {
|
Chris@0
|
559 $line = $tokens[$checkToken]['line'];
|
Chris@0
|
560 $type = $tokens[$checkToken]['type'];
|
Chris@0
|
561 echo "\t=> Add adjustment of ".$adjustments[$checkToken]." for token $checkToken ($type) on line $line".PHP_EOL;
|
Chris@0
|
562 }
|
Chris@0
|
563 }//end if
|
Chris@0
|
564 }//end if
|
Chris@0
|
565
|
Chris@0
|
566 // Scope closers reset the required indent to the same level as the opening condition.
|
Chris@0
|
567 if (($checkToken !== null
|
Chris@0
|
568 && isset($openScopes[$checkToken]) === true
|
Chris@0
|
569 || (isset($tokens[$checkToken]['scope_condition']) === true
|
Chris@0
|
570 && isset($tokens[$checkToken]['scope_closer']) === true
|
Chris@0
|
571 && $tokens[$checkToken]['scope_closer'] === $checkToken
|
Chris@0
|
572 && $tokens[$checkToken]['line'] !== $tokens[$tokens[$checkToken]['scope_opener']]['line']))
|
Chris@0
|
573 || ($checkToken === null
|
Chris@0
|
574 && isset($openScopes[$i]) === true
|
Chris@0
|
575 || (isset($tokens[$i]['scope_condition']) === true
|
Chris@0
|
576 && isset($tokens[$i]['scope_closer']) === true
|
Chris@0
|
577 && $tokens[$i]['scope_closer'] === $i
|
Chris@0
|
578 && $tokens[$i]['line'] !== $tokens[$tokens[$i]['scope_opener']]['line']))
|
Chris@0
|
579 ) {
|
Chris@0
|
580 if ($this->_debug === true) {
|
Chris@0
|
581 if ($checkToken === null) {
|
Chris@0
|
582 $type = $tokens[$tokens[$i]['scope_condition']]['type'];
|
Chris@0
|
583 $line = $tokens[$i]['line'];
|
Chris@0
|
584 } else {
|
Chris@0
|
585 $type = $tokens[$tokens[$checkToken]['scope_condition']]['type'];
|
Chris@0
|
586 $line = $tokens[$checkToken]['line'];
|
Chris@0
|
587 }
|
Chris@0
|
588
|
Chris@0
|
589 echo "Close scope ($type) on line $line".PHP_EOL;
|
Chris@0
|
590 }
|
Chris@0
|
591
|
Chris@0
|
592 $scopeCloser = $checkToken;
|
Chris@0
|
593 if ($scopeCloser === null) {
|
Chris@0
|
594 $scopeCloser = $i;
|
Chris@0
|
595 } else {
|
Chris@0
|
596 array_pop($openScopes);
|
Chris@0
|
597 }
|
Chris@0
|
598
|
Chris@0
|
599 if (isset($tokens[$scopeCloser]['scope_condition']) === true) {
|
Chris@0
|
600 $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $tokens[$scopeCloser]['scope_condition'], true);
|
Chris@0
|
601
|
Chris@0
|
602 $currentIndent = ($tokens[$first]['column'] - 1);
|
Chris@0
|
603 if (isset($adjustments[$first]) === true) {
|
Chris@0
|
604 $currentIndent += $adjustments[$first];
|
Chris@0
|
605 }
|
Chris@0
|
606
|
Chris@0
|
607 // Make sure it is divisible by our expected indent.
|
Chris@0
|
608 if ($tokens[$tokens[$scopeCloser]['scope_condition']]['code'] !== T_CLOSURE) {
|
Chris@0
|
609 $currentIndent = (int) (ceil($currentIndent / $this->indent) * $this->indent);
|
Chris@0
|
610 }
|
Chris@0
|
611
|
Chris@0
|
612 $setIndents[$scopeCloser] = $currentIndent;
|
Chris@0
|
613
|
Chris@0
|
614 if ($this->_debug === true) {
|
Chris@0
|
615 $type = $tokens[$scopeCloser]['type'];
|
Chris@0
|
616 echo "\t=> indent set to $currentIndent by token $scopeCloser ($type)".PHP_EOL;
|
Chris@0
|
617 }
|
Chris@0
|
618
|
Chris@0
|
619 // We only check the indent of scope closers if they are
|
Chris@0
|
620 // curly braces because other constructs tend to have different rules.
|
Chris@0
|
621 if ($tokens[$scopeCloser]['code'] === T_CLOSE_CURLY_BRACKET) {
|
Chris@0
|
622 $exact = true;
|
Chris@0
|
623 } else {
|
Chris@0
|
624 $checkToken = null;
|
Chris@0
|
625 }
|
Chris@0
|
626 }//end if
|
Chris@0
|
627 }//end if
|
Chris@0
|
628
|
Chris@0
|
629 // Handle scope for JS object notation.
|
Chris@0
|
630 if ($phpcsFile->tokenizerType === 'JS'
|
Chris@0
|
631 && (($checkToken !== null
|
Chris@0
|
632 && $tokens[$checkToken]['code'] === T_CLOSE_OBJECT
|
Chris@0
|
633 && $tokens[$checkToken]['line'] !== $tokens[$tokens[$checkToken]['bracket_opener']]['line'])
|
Chris@0
|
634 || ($checkToken === null
|
Chris@0
|
635 && $tokens[$i]['code'] === T_CLOSE_OBJECT
|
Chris@0
|
636 && $tokens[$i]['line'] !== $tokens[$tokens[$i]['bracket_opener']]['line']))
|
Chris@0
|
637 ) {
|
Chris@0
|
638 if ($this->_debug === true) {
|
Chris@0
|
639 $line = $tokens[$i]['line'];
|
Chris@0
|
640 echo "Close JS object on line $line".PHP_EOL;
|
Chris@0
|
641 }
|
Chris@0
|
642
|
Chris@0
|
643 $scopeCloser = $checkToken;
|
Chris@0
|
644 if ($scopeCloser === null) {
|
Chris@0
|
645 $scopeCloser = $i;
|
Chris@0
|
646 } else {
|
Chris@0
|
647 array_pop($openScopes);
|
Chris@0
|
648 }
|
Chris@0
|
649
|
Chris@0
|
650 $parens = 0;
|
Chris@0
|
651 if (isset($tokens[$scopeCloser]['nested_parenthesis']) === true
|
Chris@0
|
652 && empty($tokens[$scopeCloser]['nested_parenthesis']) === false
|
Chris@0
|
653 ) {
|
Chris@0
|
654 end($tokens[$scopeCloser]['nested_parenthesis']);
|
Chris@0
|
655 $parens = key($tokens[$scopeCloser]['nested_parenthesis']);
|
Chris@0
|
656 if ($this->_debug === true) {
|
Chris@0
|
657 $line = $tokens[$parens]['line'];
|
Chris@0
|
658 echo "\t* token has nested parenthesis $parens on line $line *".PHP_EOL;
|
Chris@0
|
659 }
|
Chris@0
|
660 }
|
Chris@0
|
661
|
Chris@0
|
662 $condition = 0;
|
Chris@0
|
663 if (isset($tokens[$scopeCloser]['conditions']) === true
|
Chris@0
|
664 && empty($tokens[$scopeCloser]['conditions']) === false
|
Chris@0
|
665 ) {
|
Chris@0
|
666 end($tokens[$scopeCloser]['conditions']);
|
Chris@0
|
667 $condition = key($tokens[$scopeCloser]['conditions']);
|
Chris@0
|
668 if ($this->_debug === true) {
|
Chris@0
|
669 $line = $tokens[$condition]['line'];
|
Chris@0
|
670 $type = $tokens[$condition]['type'];
|
Chris@0
|
671 echo "\t* token is inside condition $condition ($type) on line $line *".PHP_EOL;
|
Chris@0
|
672 }
|
Chris@0
|
673 }
|
Chris@0
|
674
|
Chris@0
|
675 if ($parens > $condition) {
|
Chris@0
|
676 if ($this->_debug === true) {
|
Chris@0
|
677 echo "\t* using parenthesis *".PHP_EOL;
|
Chris@0
|
678 }
|
Chris@0
|
679
|
Chris@0
|
680 $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $parens, true);
|
Chris@0
|
681 $condition = 0;
|
Chris@0
|
682 } else if ($condition > 0) {
|
Chris@0
|
683 if ($this->_debug === true) {
|
Chris@0
|
684 echo "\t* using condition *".PHP_EOL;
|
Chris@0
|
685 }
|
Chris@0
|
686
|
Chris@0
|
687 $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $condition, true);
|
Chris@0
|
688 $parens = 0;
|
Chris@0
|
689 } else {
|
Chris@0
|
690 if ($this->_debug === true) {
|
Chris@0
|
691 $line = $tokens[$tokens[$scopeCloser]['bracket_opener']]['line'];
|
Chris@0
|
692 echo "\t* token is not in parenthesis or condition; using opener on line $line *".PHP_EOL;
|
Chris@0
|
693 }
|
Chris@0
|
694
|
Chris@0
|
695 $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $tokens[$scopeCloser]['bracket_opener'], true);
|
Chris@0
|
696 }//end if
|
Chris@0
|
697
|
Chris@0
|
698 $currentIndent = ($tokens[$first]['column'] - 1);
|
Chris@0
|
699 if (isset($adjustments[$first]) === true) {
|
Chris@0
|
700 $currentIndent += $adjustments[$first];
|
Chris@0
|
701 }
|
Chris@0
|
702
|
Chris@0
|
703 if ($parens > 0 || $condition > 0) {
|
Chris@0
|
704 $checkIndent = ($tokens[$first]['column'] - 1);
|
Chris@0
|
705 if (isset($adjustments[$first]) === true) {
|
Chris@0
|
706 $checkIndent += $adjustments[$first];
|
Chris@0
|
707 }
|
Chris@0
|
708
|
Chris@0
|
709 if ($condition > 0) {
|
Chris@0
|
710 $checkIndent += $this->indent;
|
Chris@0
|
711 $currentIndent += $this->indent;
|
Chris@0
|
712 $exact = true;
|
Chris@0
|
713 }
|
Chris@0
|
714 } else {
|
Chris@0
|
715 $checkIndent = $currentIndent;
|
Chris@0
|
716 }
|
Chris@0
|
717
|
Chris@0
|
718 // Make sure it is divisible by our expected indent.
|
Chris@0
|
719 $currentIndent = (int) (ceil($currentIndent / $this->indent) * $this->indent);
|
Chris@0
|
720 $checkIndent = (int) (ceil($checkIndent / $this->indent) * $this->indent);
|
Chris@0
|
721 $setIndents[$first] = $currentIndent;
|
Chris@0
|
722
|
Chris@0
|
723 if ($this->_debug === true) {
|
Chris@0
|
724 $type = $tokens[$first]['type'];
|
Chris@0
|
725 echo "\t=> checking indent of $checkIndent; main indent set to $currentIndent by token $first ($type)".PHP_EOL;
|
Chris@0
|
726 }
|
Chris@0
|
727 }//end if
|
Chris@0
|
728
|
Chris@0
|
729 if ($checkToken !== null
|
Chris@17
|
730 && isset(Tokens::$scopeOpeners[$tokens[$checkToken]['code']]) === true
|
Chris@0
|
731 && in_array($tokens[$checkToken]['code'], $this->nonIndentingScopes) === false
|
Chris@0
|
732 && isset($tokens[$checkToken]['scope_opener']) === true
|
Chris@0
|
733 ) {
|
Chris@0
|
734 $exact = true;
|
Chris@0
|
735
|
Chris@0
|
736 $lastOpener = null;
|
Chris@0
|
737 if (empty($openScopes) === false) {
|
Chris@0
|
738 end($openScopes);
|
Chris@0
|
739 $lastOpener = current($openScopes);
|
Chris@0
|
740 }
|
Chris@0
|
741
|
Chris@0
|
742 // A scope opener that shares a closer with another token (like multiple
|
Chris@0
|
743 // CASEs using the same BREAK) needs to reduce the indent level so its
|
Chris@0
|
744 // indent is checked correctly. It will then increase the indent again
|
Chris@0
|
745 // (as all openers do) after being checked.
|
Chris@0
|
746 if ($lastOpener !== null
|
Chris@0
|
747 && isset($tokens[$lastOpener]['scope_closer']) === true
|
Chris@0
|
748 && $tokens[$lastOpener]['level'] === $tokens[$checkToken]['level']
|
Chris@0
|
749 && $tokens[$lastOpener]['scope_closer'] === $tokens[$checkToken]['scope_closer']
|
Chris@0
|
750 ) {
|
Chris@0
|
751 $currentIndent -= $this->indent;
|
Chris@0
|
752 $setIndents[$lastOpener] = $currentIndent;
|
Chris@0
|
753 if ($this->_debug === true) {
|
Chris@0
|
754 $line = $tokens[$i]['line'];
|
Chris@0
|
755 $type = $tokens[$lastOpener]['type'];
|
Chris@0
|
756 echo "Shared closer found on line $line".PHP_EOL;
|
Chris@0
|
757 echo "\t=> indent set to $currentIndent by token $lastOpener ($type)".PHP_EOL;
|
Chris@0
|
758 }
|
Chris@0
|
759 }
|
Chris@0
|
760
|
Chris@0
|
761 if ($tokens[$checkToken]['code'] === T_CLOSURE
|
Chris@0
|
762 && $tokenIndent > $currentIndent
|
Chris@0
|
763 ) {
|
Chris@0
|
764 // The opener is indented more than needed, which is fine.
|
Chris@0
|
765 // But just check that it is divisible by our expected indent.
|
Chris@0
|
766 $checkIndent = (int) (ceil($tokenIndent / $this->indent) * $this->indent);
|
Chris@0
|
767 $exact = false;
|
Chris@0
|
768
|
Chris@0
|
769 if ($this->_debug === true) {
|
Chris@0
|
770 $line = $tokens[$i]['line'];
|
Chris@0
|
771 echo "Closure found on line $line".PHP_EOL;
|
Chris@0
|
772 echo "\t=> checking indent of $checkIndent; main indent remains at $currentIndent".PHP_EOL;
|
Chris@0
|
773 }
|
Chris@0
|
774 }
|
Chris@0
|
775 }//end if
|
Chris@0
|
776
|
Chris@0
|
777 // Method prefix indentation has to be exact or else if will break
|
Chris@0
|
778 // the rest of the function declaration, and potentially future ones.
|
Chris@0
|
779 if ($checkToken !== null
|
Chris@17
|
780 && isset(Tokens::$methodPrefixes[$tokens[$checkToken]['code']]) === true
|
Chris@0
|
781 && $tokens[($checkToken + 1)]['code'] !== T_DOUBLE_COLON
|
Chris@0
|
782 ) {
|
Chris@0
|
783 $exact = true;
|
Chris@0
|
784 }
|
Chris@0
|
785
|
Chris@0
|
786 // JS property indentation has to be exact or else if will break
|
Chris@0
|
787 // things like function and object indentation.
|
Chris@0
|
788 if ($checkToken !== null && $tokens[$checkToken]['code'] === T_PROPERTY) {
|
Chris@0
|
789 $exact = true;
|
Chris@0
|
790 }
|
Chris@0
|
791
|
Chris@0
|
792 // PHP tags needs to be indented to exact column positions
|
Chris@0
|
793 // so they don't cause problems with indent checks for the code
|
Chris@0
|
794 // within them, but they don't need to line up with the current indent.
|
Chris@0
|
795 if ($checkToken !== null
|
Chris@0
|
796 && ($tokens[$checkToken]['code'] === T_OPEN_TAG
|
Chris@0
|
797 || $tokens[$checkToken]['code'] === T_OPEN_TAG_WITH_ECHO
|
Chris@0
|
798 || $tokens[$checkToken]['code'] === T_CLOSE_TAG)
|
Chris@0
|
799 ) {
|
Chris@0
|
800 $exact = true;
|
Chris@0
|
801 $checkIndent = ($tokens[$checkToken]['column'] - 1);
|
Chris@0
|
802 $checkIndent = (int) (ceil($checkIndent / $this->indent) * $this->indent);
|
Chris@0
|
803 }
|
Chris@0
|
804
|
Chris@0
|
805 // Check the line indent.
|
Chris@0
|
806 if ($checkIndent === null) {
|
Chris@0
|
807 $checkIndent = $currentIndent;
|
Chris@0
|
808 }
|
Chris@0
|
809
|
Chris@0
|
810 // If the line starts with "->" we assume this is an indented chained
|
Chris@0
|
811 // method invocation, so we add one level of indentation.
|
Chris@0
|
812 if ($checkToken !== null && $tokens[$checkToken]['code'] === T_OBJECT_OPERATOR) {
|
Chris@0
|
813 $checkIndent += $this->indent;
|
Chris@0
|
814 }
|
Chris@0
|
815
|
Chris@0
|
816 // Comments starting with a star have an extra whitespace.
|
Chris@0
|
817 if ($checkToken !== null && $tokens[$checkToken]['code'] === T_COMMENT) {
|
Chris@0
|
818 $content = trim($tokens[$checkToken]['content']);
|
Chris@0
|
819 if ($content{0} === '*') {
|
Chris@0
|
820 $checkIndent += 1;
|
Chris@0
|
821 }
|
Chris@0
|
822 }
|
Chris@0
|
823
|
Chris@0
|
824 $adjusted = false;
|
Chris@0
|
825 if ($checkToken !== null
|
Chris@0
|
826 && isset($this->_ignoreIndentationTokens[$tokens[$checkToken]['code']]) === false
|
Chris@0
|
827 && (($tokenIndent !== $checkIndent && $exact === true)
|
Chris@0
|
828 || ($tokenIndent < $checkIndent && $exact === false))
|
Chris@0
|
829 ) {
|
Chris@0
|
830 if ($tokenIndent > $checkIndent) {
|
Chris@0
|
831 // Ignore multi line statements.
|
Chris@17
|
832 $before = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($checkToken - 1), null, true);
|
Chris@0
|
833 if ($before !== false && in_array(
|
Chris@0
|
834 $tokens[$before]['code'],
|
Chris@0
|
835 array(
|
Chris@0
|
836 T_SEMICOLON,
|
Chris@0
|
837 T_CLOSE_CURLY_BRACKET,
|
Chris@0
|
838 T_OPEN_CURLY_BRACKET,
|
Chris@0
|
839 T_COLON,
|
Chris@0
|
840 )
|
Chris@0
|
841 ) === false
|
Chris@0
|
842 ) {
|
Chris@0
|
843 continue;
|
Chris@0
|
844 }
|
Chris@0
|
845 }
|
Chris@0
|
846
|
Chris@0
|
847 // Skip array closing indentation errors, this is handled by the
|
Chris@0
|
848 // ArraySniff.
|
Chris@0
|
849 if (($tokens[$checkToken]['code'] === T_CLOSE_PARENTHESIS
|
Chris@0
|
850 && isset($tokens[$checkToken]['parenthesis_owner']) === true
|
Chris@0
|
851 && $tokens[$tokens[$checkToken]['parenthesis_owner']]['code'] === T_ARRAY)
|
Chris@0
|
852 || $tokens[$checkToken]['code'] === T_CLOSE_SHORT_ARRAY
|
Chris@0
|
853 ) {
|
Chris@0
|
854 continue;
|
Chris@0
|
855 }
|
Chris@0
|
856
|
Chris@0
|
857 $type = 'IncorrectExact';
|
Chris@0
|
858 $error = 'Line indented incorrectly; expected ';
|
Chris@0
|
859 if ($exact === false) {
|
Chris@0
|
860 $error .= 'at least ';
|
Chris@0
|
861 $type = 'Incorrect';
|
Chris@0
|
862 }
|
Chris@0
|
863
|
Chris@0
|
864 if ($this->tabIndent === true) {
|
Chris@0
|
865 $error .= '%s tabs, found %s';
|
Chris@0
|
866 $data = array(
|
Chris@0
|
867 floor($checkIndent / $this->_tabWidth),
|
Chris@0
|
868 floor($tokenIndent / $this->_tabWidth),
|
Chris@0
|
869 );
|
Chris@0
|
870 } else {
|
Chris@0
|
871 $error .= '%s spaces, found %s';
|
Chris@0
|
872 $data = array(
|
Chris@0
|
873 $checkIndent,
|
Chris@0
|
874 $tokenIndent,
|
Chris@0
|
875 );
|
Chris@0
|
876 }
|
Chris@0
|
877
|
Chris@0
|
878 if ($this->_debug === true) {
|
Chris@0
|
879 $line = $tokens[$checkToken]['line'];
|
Chris@0
|
880 $message = vsprintf($error, $data);
|
Chris@0
|
881 echo "[Line $line] $message".PHP_EOL;
|
Chris@0
|
882 }
|
Chris@0
|
883
|
Chris@0
|
884 $fix = $phpcsFile->addFixableError($error, $checkToken, $type, $data);
|
Chris@0
|
885 if ($fix === true || $this->_debug === true) {
|
Chris@0
|
886 $padding = '';
|
Chris@0
|
887 if ($this->tabIndent === true) {
|
Chris@0
|
888 $numTabs = floor($checkIndent / $this->_tabWidth);
|
Chris@0
|
889 if ($numTabs > 0) {
|
Chris@0
|
890 $numSpaces = ($checkIndent - ($numTabs * $this->_tabWidth));
|
Chris@0
|
891 $padding = str_repeat("\t", $numTabs).str_repeat(' ', $numSpaces);
|
Chris@0
|
892 }
|
Chris@0
|
893 } else if ($checkIndent > 0) {
|
Chris@0
|
894 $padding = str_repeat(' ', $checkIndent);
|
Chris@0
|
895 }
|
Chris@0
|
896
|
Chris@0
|
897 if ($checkToken === $i) {
|
Chris@0
|
898 $accepted = $phpcsFile->fixer->replaceToken($checkToken, $padding.$trimmed);
|
Chris@0
|
899 } else {
|
Chris@0
|
900 // Easier to just replace the entire indent.
|
Chris@0
|
901 $accepted = $phpcsFile->fixer->replaceToken(($checkToken - 1), $padding);
|
Chris@0
|
902 }
|
Chris@0
|
903
|
Chris@0
|
904 if ($accepted === true) {
|
Chris@0
|
905 $adjustments[$checkToken] = ($checkIndent - $tokenIndent);
|
Chris@0
|
906 if ($this->_debug === true) {
|
Chris@0
|
907 $line = $tokens[$checkToken]['line'];
|
Chris@0
|
908 $type = $tokens[$checkToken]['type'];
|
Chris@0
|
909 echo "\t=> Add adjustment of ".$adjustments[$checkToken]." for token $checkToken ($type) on line $line".PHP_EOL;
|
Chris@0
|
910 }
|
Chris@0
|
911 }
|
Chris@0
|
912 } else {
|
Chris@0
|
913 // Assume the change would be applied and continue
|
Chris@0
|
914 // checking indents under this assumption. This gives more
|
Chris@0
|
915 // technically accurate error messages.
|
Chris@0
|
916 $adjustments[$checkToken] = ($checkIndent - $tokenIndent);
|
Chris@0
|
917 }//end if
|
Chris@0
|
918 }//end if
|
Chris@0
|
919
|
Chris@0
|
920 if ($checkToken !== null) {
|
Chris@0
|
921 $i = $checkToken;
|
Chris@0
|
922 }
|
Chris@0
|
923
|
Chris@0
|
924 // Completely skip here/now docs as the indent is a part of the
|
Chris@0
|
925 // content itself.
|
Chris@0
|
926 if ($tokens[$i]['code'] === T_START_HEREDOC
|
Chris@0
|
927 || $tokens[$i]['code'] === T_START_NOWDOC
|
Chris@0
|
928 ) {
|
Chris@0
|
929 $i = $phpcsFile->findNext(array(T_END_HEREDOC, T_END_NOWDOC), ($i + 1));
|
Chris@0
|
930 continue;
|
Chris@0
|
931 }
|
Chris@0
|
932
|
Chris@0
|
933 // Completely skip multi-line strings as the indent is a part of the
|
Chris@0
|
934 // content itself.
|
Chris@0
|
935 if ($tokens[$i]['code'] === T_CONSTANT_ENCAPSED_STRING
|
Chris@0
|
936 || $tokens[$i]['code'] === T_DOUBLE_QUOTED_STRING
|
Chris@0
|
937 ) {
|
Chris@0
|
938 $i = $phpcsFile->findNext($tokens[$i]['code'], ($i + 1), null, true);
|
Chris@0
|
939 $i--;
|
Chris@0
|
940 continue;
|
Chris@0
|
941 }
|
Chris@0
|
942
|
Chris@0
|
943 // Completely skip doc comments as they tend to have complex
|
Chris@0
|
944 // indentation rules.
|
Chris@0
|
945 if ($tokens[$i]['code'] === T_DOC_COMMENT_OPEN_TAG) {
|
Chris@0
|
946 $i = $tokens[$i]['comment_closer'];
|
Chris@0
|
947 continue;
|
Chris@0
|
948 }
|
Chris@0
|
949
|
Chris@0
|
950 // Open tags reset the indent level.
|
Chris@0
|
951 if ($tokens[$i]['code'] === T_OPEN_TAG
|
Chris@0
|
952 || $tokens[$i]['code'] === T_OPEN_TAG_WITH_ECHO
|
Chris@0
|
953 ) {
|
Chris@0
|
954 if ($this->_debug === true) {
|
Chris@0
|
955 $line = $tokens[$i]['line'];
|
Chris@0
|
956 echo "Open PHP tag found on line $line".PHP_EOL;
|
Chris@0
|
957 }
|
Chris@0
|
958
|
Chris@0
|
959 if ($checkToken === null) {
|
Chris@0
|
960 $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $i, true);
|
Chris@0
|
961 $currentIndent = (strlen($tokens[$first]['content']) - strlen(ltrim($tokens[$first]['content'])));
|
Chris@0
|
962 } else {
|
Chris@0
|
963 $currentIndent = ($tokens[$i]['column'] - 1);
|
Chris@0
|
964 }
|
Chris@0
|
965
|
Chris@0
|
966 $lastOpenTag = $i;
|
Chris@0
|
967
|
Chris@0
|
968 if (isset($adjustments[$i]) === true) {
|
Chris@0
|
969 $currentIndent += $adjustments[$i];
|
Chris@0
|
970 }
|
Chris@0
|
971
|
Chris@0
|
972 // Make sure it is divisible by our expected indent.
|
Chris@0
|
973 $currentIndent = (int) (ceil($currentIndent / $this->indent) * $this->indent);
|
Chris@0
|
974 $setIndents[$i] = $currentIndent;
|
Chris@0
|
975
|
Chris@0
|
976 if ($this->_debug === true) {
|
Chris@0
|
977 $type = $tokens[$i]['type'];
|
Chris@0
|
978 echo "\t=> indent set to $currentIndent by token $i ($type)".PHP_EOL;
|
Chris@0
|
979 }
|
Chris@0
|
980
|
Chris@0
|
981 continue;
|
Chris@0
|
982 }//end if
|
Chris@0
|
983
|
Chris@0
|
984 // Close tags reset the indent level, unless they are closing a tag
|
Chris@0
|
985 // opened on the same line.
|
Chris@0
|
986 if ($tokens[$i]['code'] === T_CLOSE_TAG) {
|
Chris@0
|
987 if ($this->_debug === true) {
|
Chris@0
|
988 $line = $tokens[$i]['line'];
|
Chris@0
|
989 echo "Close PHP tag found on line $line".PHP_EOL;
|
Chris@0
|
990 }
|
Chris@0
|
991
|
Chris@0
|
992 if ($tokens[$lastOpenTag]['line'] !== $tokens[$i]['line']) {
|
Chris@0
|
993 $currentIndent = ($tokens[$i]['column'] - 1);
|
Chris@0
|
994 $lastCloseTag = $i;
|
Chris@0
|
995 } else {
|
Chris@0
|
996 if ($lastCloseTag === null) {
|
Chris@0
|
997 $currentIndent = 0;
|
Chris@0
|
998 } else {
|
Chris@0
|
999 $currentIndent = ($tokens[$lastCloseTag]['column'] - 1);
|
Chris@0
|
1000 }
|
Chris@0
|
1001 }
|
Chris@0
|
1002
|
Chris@0
|
1003 if (isset($adjustments[$i]) === true) {
|
Chris@0
|
1004 $currentIndent += $adjustments[$i];
|
Chris@0
|
1005 }
|
Chris@0
|
1006
|
Chris@0
|
1007 // Make sure it is divisible by our expected indent.
|
Chris@0
|
1008 $currentIndent = (int) (ceil($currentIndent / $this->indent) * $this->indent);
|
Chris@0
|
1009 $setIndents[$i] = $currentIndent;
|
Chris@0
|
1010
|
Chris@0
|
1011 if ($this->_debug === true) {
|
Chris@0
|
1012 $type = $tokens[$i]['type'];
|
Chris@0
|
1013 echo "\t=> indent set to $currentIndent by token $i ($type)".PHP_EOL;
|
Chris@0
|
1014 }
|
Chris@0
|
1015
|
Chris@0
|
1016 continue;
|
Chris@0
|
1017 }//end if
|
Chris@0
|
1018
|
Chris@0
|
1019 // Anon classes and functions set the indent based on their own indent level.
|
Chris@0
|
1020 if ($tokens[$i]['code'] === T_CLOSURE || $tokens[$i]['code'] === T_ANON_CLASS) {
|
Chris@0
|
1021 $closer = $tokens[$i]['scope_closer'];
|
Chris@0
|
1022 if ($tokens[$i]['line'] === $tokens[$closer]['line']) {
|
Chris@0
|
1023 if ($this->_debug === true) {
|
Chris@0
|
1024 $type = str_replace('_', ' ', strtolower(substr($tokens[$i]['type'], 2)));
|
Chris@0
|
1025 $line = $tokens[$i]['line'];
|
Chris@0
|
1026 echo "* ignoring single-line $type on line $line".PHP_EOL;
|
Chris@0
|
1027 }
|
Chris@0
|
1028
|
Chris@0
|
1029 $i = $closer;
|
Chris@0
|
1030 continue;
|
Chris@0
|
1031 }
|
Chris@0
|
1032
|
Chris@0
|
1033 if ($this->_debug === true) {
|
Chris@0
|
1034 $type = str_replace('_', ' ', strtolower(substr($tokens[$i]['type'], 2)));
|
Chris@0
|
1035 $line = $tokens[$i]['line'];
|
Chris@0
|
1036 echo "Open $type on line $line".PHP_EOL;
|
Chris@0
|
1037 }
|
Chris@0
|
1038
|
Chris@0
|
1039 $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $i, true);
|
Chris@0
|
1040 $currentIndent = (($tokens[$first]['column'] - 1) + $this->indent);
|
Chris@0
|
1041
|
Chris@0
|
1042 if (isset($adjustments[$first]) === true) {
|
Chris@0
|
1043 $currentIndent += $adjustments[$first];
|
Chris@0
|
1044 }
|
Chris@0
|
1045
|
Chris@0
|
1046 // Make sure it is divisible by our expected indent.
|
Chris@0
|
1047 $currentIndent = (int) (floor($currentIndent / $this->indent) * $this->indent);
|
Chris@0
|
1048 $i = $tokens[$i]['scope_opener'];
|
Chris@0
|
1049 $setIndents[$i] = $currentIndent;
|
Chris@0
|
1050
|
Chris@0
|
1051 if ($this->_debug === true) {
|
Chris@0
|
1052 $type = $tokens[$i]['type'];
|
Chris@0
|
1053 echo "\t=> indent set to $currentIndent by token $i ($type)".PHP_EOL;
|
Chris@0
|
1054 }
|
Chris@0
|
1055
|
Chris@0
|
1056 continue;
|
Chris@0
|
1057 }//end if
|
Chris@0
|
1058
|
Chris@0
|
1059 // Scope openers increase the indent level.
|
Chris@0
|
1060 if (isset($tokens[$i]['scope_condition']) === true
|
Chris@0
|
1061 && isset($tokens[$i]['scope_opener']) === true
|
Chris@0
|
1062 && $tokens[$i]['scope_opener'] === $i
|
Chris@0
|
1063 ) {
|
Chris@0
|
1064 $closer = $tokens[$i]['scope_closer'];
|
Chris@0
|
1065 if ($tokens[$i]['line'] === $tokens[$closer]['line']) {
|
Chris@0
|
1066 if ($this->_debug === true) {
|
Chris@0
|
1067 $line = $tokens[$i]['line'];
|
Chris@0
|
1068 $type = $tokens[$i]['type'];
|
Chris@0
|
1069 echo "* ignoring single-line $type on line $line".PHP_EOL;
|
Chris@0
|
1070 }
|
Chris@0
|
1071
|
Chris@0
|
1072 $i = $closer;
|
Chris@0
|
1073 continue;
|
Chris@0
|
1074 }
|
Chris@0
|
1075
|
Chris@0
|
1076 $condition = $tokens[$tokens[$i]['scope_condition']]['code'];
|
Chris@17
|
1077 if (isset(Tokens::$scopeOpeners[$condition]) === true
|
Chris@0
|
1078 && in_array($condition, $this->nonIndentingScopes) === false
|
Chris@0
|
1079 ) {
|
Chris@0
|
1080 if ($this->_debug === true) {
|
Chris@0
|
1081 $line = $tokens[$i]['line'];
|
Chris@0
|
1082 $type = $tokens[$tokens[$i]['scope_condition']]['type'];
|
Chris@0
|
1083 echo "Open scope ($type) on line $line".PHP_EOL;
|
Chris@0
|
1084 }
|
Chris@0
|
1085
|
Chris@0
|
1086 $currentIndent += $this->indent;
|
Chris@0
|
1087 $setIndents[$i] = $currentIndent;
|
Chris@0
|
1088 $openScopes[$tokens[$i]['scope_closer']] = $tokens[$i]['scope_condition'];
|
Chris@0
|
1089
|
Chris@0
|
1090 if ($this->_debug === true) {
|
Chris@0
|
1091 $type = $tokens[$i]['type'];
|
Chris@0
|
1092 echo "\t=> indent set to $currentIndent by token $i ($type)".PHP_EOL;
|
Chris@0
|
1093 }
|
Chris@0
|
1094
|
Chris@0
|
1095 continue;
|
Chris@0
|
1096 }
|
Chris@0
|
1097 }//end if
|
Chris@0
|
1098
|
Chris@0
|
1099 // JS objects set the indent level.
|
Chris@0
|
1100 if ($phpcsFile->tokenizerType === 'JS'
|
Chris@0
|
1101 && $tokens[$i]['code'] === T_OBJECT
|
Chris@0
|
1102 ) {
|
Chris@0
|
1103 $closer = $tokens[$i]['bracket_closer'];
|
Chris@0
|
1104 if ($tokens[$i]['line'] === $tokens[$closer]['line']) {
|
Chris@0
|
1105 if ($this->_debug === true) {
|
Chris@0
|
1106 $line = $tokens[$i]['line'];
|
Chris@0
|
1107 echo "* ignoring single-line JS object on line $line".PHP_EOL;
|
Chris@0
|
1108 }
|
Chris@0
|
1109
|
Chris@0
|
1110 $i = $closer;
|
Chris@0
|
1111 continue;
|
Chris@0
|
1112 }
|
Chris@0
|
1113
|
Chris@0
|
1114 if ($this->_debug === true) {
|
Chris@0
|
1115 $line = $tokens[$i]['line'];
|
Chris@0
|
1116 echo "Open JS object on line $line".PHP_EOL;
|
Chris@0
|
1117 }
|
Chris@0
|
1118
|
Chris@0
|
1119 $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $i, true);
|
Chris@0
|
1120 $currentIndent = (($tokens[$first]['column'] - 1) + $this->indent);
|
Chris@0
|
1121 if (isset($adjustments[$first]) === true) {
|
Chris@0
|
1122 $currentIndent += $adjustments[$first];
|
Chris@0
|
1123 }
|
Chris@0
|
1124
|
Chris@0
|
1125 // Make sure it is divisible by our expected indent.
|
Chris@0
|
1126 $currentIndent = (int) (ceil($currentIndent / $this->indent) * $this->indent);
|
Chris@0
|
1127 $setIndents[$first] = $currentIndent;
|
Chris@0
|
1128
|
Chris@0
|
1129 if ($this->_debug === true) {
|
Chris@0
|
1130 $type = $tokens[$first]['type'];
|
Chris@0
|
1131 echo "\t=> indent set to $currentIndent by token $first ($type)".PHP_EOL;
|
Chris@0
|
1132 }
|
Chris@0
|
1133
|
Chris@0
|
1134 continue;
|
Chris@0
|
1135 }//end if
|
Chris@0
|
1136
|
Chris@0
|
1137 // Closing an anon class or function.
|
Chris@0
|
1138 if (isset($tokens[$i]['scope_condition']) === true
|
Chris@0
|
1139 && $tokens[$i]['scope_closer'] === $i
|
Chris@0
|
1140 && ($tokens[$tokens[$i]['scope_condition']]['code'] === T_CLOSURE
|
Chris@0
|
1141 || $tokens[$tokens[$i]['scope_condition']]['code'] === T_ANON_CLASS)
|
Chris@0
|
1142 ) {
|
Chris@0
|
1143 if ($this->_debug === true) {
|
Chris@0
|
1144 $type = str_replace('_', ' ', strtolower(substr($tokens[$tokens[$i]['scope_condition']]['type'], 2)));
|
Chris@0
|
1145 $line = $tokens[$i]['line'];
|
Chris@0
|
1146 echo "Close $type on line $line".PHP_EOL;
|
Chris@0
|
1147 }
|
Chris@0
|
1148
|
Chris@0
|
1149 $prev = false;
|
Chris@0
|
1150
|
Chris@0
|
1151 $object = 0;
|
Chris@0
|
1152 if ($phpcsFile->tokenizerType === 'JS') {
|
Chris@0
|
1153 $conditions = $tokens[$i]['conditions'];
|
Chris@0
|
1154 krsort($conditions, SORT_NUMERIC);
|
Chris@0
|
1155 foreach ($conditions as $token => $condition) {
|
Chris@0
|
1156 if ($condition === T_OBJECT) {
|
Chris@0
|
1157 $object = $token;
|
Chris@0
|
1158 break;
|
Chris@0
|
1159 }
|
Chris@0
|
1160 }
|
Chris@0
|
1161
|
Chris@0
|
1162 if ($this->_debug === true && $object !== 0) {
|
Chris@0
|
1163 $line = $tokens[$object]['line'];
|
Chris@0
|
1164 echo "\t* token is inside JS object $object on line $line *".PHP_EOL;
|
Chris@0
|
1165 }
|
Chris@0
|
1166 }
|
Chris@0
|
1167
|
Chris@0
|
1168 $parens = 0;
|
Chris@0
|
1169 if (isset($tokens[$i]['nested_parenthesis']) === true
|
Chris@0
|
1170 && empty($tokens[$i]['nested_parenthesis']) === false
|
Chris@0
|
1171 ) {
|
Chris@0
|
1172 end($tokens[$i]['nested_parenthesis']);
|
Chris@0
|
1173 $parens = key($tokens[$i]['nested_parenthesis']);
|
Chris@0
|
1174 if ($this->_debug === true) {
|
Chris@0
|
1175 $line = $tokens[$parens]['line'];
|
Chris@0
|
1176 echo "\t* token has nested parenthesis $parens on line $line *".PHP_EOL;
|
Chris@0
|
1177 }
|
Chris@0
|
1178 }
|
Chris@0
|
1179
|
Chris@0
|
1180 $condition = 0;
|
Chris@0
|
1181 if (isset($tokens[$i]['conditions']) === true
|
Chris@0
|
1182 && empty($tokens[$i]['conditions']) === false
|
Chris@0
|
1183 ) {
|
Chris@0
|
1184 end($tokens[$i]['conditions']);
|
Chris@0
|
1185 $condition = key($tokens[$i]['conditions']);
|
Chris@0
|
1186 if ($this->_debug === true) {
|
Chris@0
|
1187 $line = $tokens[$condition]['line'];
|
Chris@0
|
1188 $type = $tokens[$condition]['type'];
|
Chris@0
|
1189 echo "\t* token is inside condition $condition ($type) on line $line *".PHP_EOL;
|
Chris@0
|
1190 }
|
Chris@0
|
1191 }
|
Chris@0
|
1192
|
Chris@0
|
1193 if ($parens > $object && $parens > $condition) {
|
Chris@0
|
1194 if ($this->_debug === true) {
|
Chris@0
|
1195 echo "\t* using parenthesis *".PHP_EOL;
|
Chris@0
|
1196 }
|
Chris@0
|
1197
|
Chris@17
|
1198 $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($parens - 1), null, true);
|
Chris@0
|
1199 $object = 0;
|
Chris@0
|
1200 $condition = 0;
|
Chris@0
|
1201 } else if ($object > 0 && $object >= $condition) {
|
Chris@0
|
1202 if ($this->_debug === true) {
|
Chris@0
|
1203 echo "\t* using object *".PHP_EOL;
|
Chris@0
|
1204 }
|
Chris@0
|
1205
|
Chris@0
|
1206 $prev = $object;
|
Chris@0
|
1207 $parens = 0;
|
Chris@0
|
1208 $condition = 0;
|
Chris@0
|
1209 } else if ($condition > 0) {
|
Chris@0
|
1210 if ($this->_debug === true) {
|
Chris@0
|
1211 echo "\t* using condition *".PHP_EOL;
|
Chris@0
|
1212 }
|
Chris@0
|
1213
|
Chris@0
|
1214 $prev = $condition;
|
Chris@0
|
1215 $object = 0;
|
Chris@0
|
1216 $parens = 0;
|
Chris@0
|
1217 }//end if
|
Chris@0
|
1218
|
Chris@0
|
1219 if ($prev === false) {
|
Chris@0
|
1220 $prev = $phpcsFile->findPrevious(array(T_EQUAL, T_RETURN), ($tokens[$i]['scope_condition'] - 1), null, false, null, true);
|
Chris@0
|
1221 if ($prev === false) {
|
Chris@0
|
1222 $prev = $i;
|
Chris@0
|
1223 if ($this->_debug === true) {
|
Chris@0
|
1224 echo "\t* could not find a previous T_EQUAL or T_RETURN token; will use current token *".PHP_EOL;
|
Chris@0
|
1225 }
|
Chris@0
|
1226 }
|
Chris@0
|
1227 }
|
Chris@0
|
1228
|
Chris@0
|
1229 if ($this->_debug === true) {
|
Chris@0
|
1230 $line = $tokens[$prev]['line'];
|
Chris@0
|
1231 $type = $tokens[$prev]['type'];
|
Chris@0
|
1232 echo "\t* previous token is $type on line $line *".PHP_EOL;
|
Chris@0
|
1233 }
|
Chris@0
|
1234
|
Chris@0
|
1235 $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $prev, true);
|
Chris@0
|
1236 if ($this->_debug === true) {
|
Chris@0
|
1237 $line = $tokens[$first]['line'];
|
Chris@0
|
1238 $type = $tokens[$first]['type'];
|
Chris@0
|
1239 echo "\t* first token on line $line is $first ($type) *".PHP_EOL;
|
Chris@0
|
1240 }
|
Chris@0
|
1241
|
Chris@0
|
1242 $prev = $phpcsFile->findStartOfStatement($first);
|
Chris@0
|
1243 if ($prev !== $first) {
|
Chris@0
|
1244 // This is not the start of the statement.
|
Chris@0
|
1245 if ($this->_debug === true) {
|
Chris@0
|
1246 $line = $tokens[$prev]['line'];
|
Chris@0
|
1247 $type = $tokens[$prev]['type'];
|
Chris@0
|
1248 echo "\t* amended previous is $type on line $line *".PHP_EOL;
|
Chris@0
|
1249 }
|
Chris@0
|
1250
|
Chris@0
|
1251 $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $prev, true);
|
Chris@0
|
1252 if ($this->_debug === true) {
|
Chris@0
|
1253 $line = $tokens[$first]['line'];
|
Chris@0
|
1254 $type = $tokens[$first]['type'];
|
Chris@0
|
1255 echo "\t* amended first token is $first ($type) on line $line *".PHP_EOL;
|
Chris@0
|
1256 }
|
Chris@0
|
1257 }
|
Chris@0
|
1258
|
Chris@0
|
1259 $currentIndent = ($tokens[$first]['column'] - 1);
|
Chris@0
|
1260 if ($object > 0 || $condition > 0) {
|
Chris@0
|
1261 $currentIndent += $this->indent;
|
Chris@0
|
1262 }
|
Chris@0
|
1263
|
Chris@0
|
1264 if (isset($tokens[$first]['scope_closer']) === true
|
Chris@0
|
1265 && $tokens[$first]['scope_closer'] === $first
|
Chris@0
|
1266 ) {
|
Chris@0
|
1267 if ($this->_debug === true) {
|
Chris@0
|
1268 echo "\t* first token is a scope closer *".PHP_EOL;
|
Chris@0
|
1269 }
|
Chris@0
|
1270
|
Chris@0
|
1271 if ($condition === 0 || $tokens[$condition]['scope_opener'] < $first) {
|
Chris@0
|
1272 $currentIndent = $setIndents[$first];
|
Chris@0
|
1273 } else if ($this->_debug === true) {
|
Chris@0
|
1274 echo "\t* ignoring scope closer *".PHP_EOL;
|
Chris@0
|
1275 }
|
Chris@0
|
1276 }
|
Chris@0
|
1277
|
Chris@0
|
1278 // Make sure it is divisible by our expected indent.
|
Chris@0
|
1279 $currentIndent = (int) (ceil($currentIndent / $this->indent) * $this->indent);
|
Chris@0
|
1280 $setIndents[$first] = $currentIndent;
|
Chris@0
|
1281
|
Chris@0
|
1282 if ($this->_debug === true) {
|
Chris@0
|
1283 $type = $tokens[$first]['type'];
|
Chris@0
|
1284 echo "\t=> indent set to $currentIndent by token $first ($type)".PHP_EOL;
|
Chris@0
|
1285 }
|
Chris@0
|
1286 }//end if
|
Chris@0
|
1287 }//end for
|
Chris@0
|
1288
|
Chris@0
|
1289 // Don't process the rest of the file.
|
Chris@0
|
1290 return $phpcsFile->numTokens;
|
Chris@0
|
1291
|
Chris@0
|
1292 }//end process()
|
Chris@0
|
1293
|
Chris@0
|
1294
|
Chris@0
|
1295 }//end class
|