GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Push — develop ( ebb7bf...0a5ff4 )
by Chris
02:41 queued 11s
created

Squiz_Sniffs_Arrays_ArrayDeclarationSniff::processSingleLineArray()   F

Complexity

Conditions 26
Paths 2964

Size

Total Lines 151
Code Lines 97

Duplication

Lines 103
Ratio 68.21 %

Importance

Changes 0
Metric Value
cc 26
eloc 97
nc 2964
nop 4
dl 103
loc 151
rs 2
c 0
b 0
f 0

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * A test to ensure that arrays conform to the array coding standard.
4
 *
5
 * PHP version 5
6
 *
7
 * @category  PHP
8
 * @package   PHP_CodeSniffer
9
 * @author    Greg Sherwood <[email protected]>
10
 * @author    Marc McIntyre <[email protected]>
11
 * @copyright 2006-2014 Squiz Pty Ltd (ABN 77 084 670 600)
12
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
13
 * @link      http://pear.php.net/package/PHP_CodeSniffer
14
 */
15
16
/**
17
 * A test to ensure that arrays conform to the array coding standard.
18
 *
19
 * @category  PHP
20
 * @package   PHP_CodeSniffer
21
 * @author    Greg Sherwood <[email protected]>
22
 * @author    Marc McIntyre <[email protected]>
23
 * @copyright 2006-2014 Squiz Pty Ltd (ABN 77 084 670 600)
24
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
25
 * @version   Release: @package_version@
26
 * @link      http://pear.php.net/package/PHP_CodeSniffer
27
 */
28
class Squiz_Sniffs_Arrays_ArrayDeclarationSniff implements PHP_CodeSniffer_Sniff
29
{
30
31
32
    /**
33
     * Returns an array of tokens this test wants to listen for.
34
     *
35
     * @return array
36
     */
37
    public function register()
38
    {
39
        return array(
40
                T_ARRAY,
41
                T_OPEN_SHORT_ARRAY,
42
               );
43
44
    }//end register()
45
46
47
    /**
48
     * Processes this sniff, when one of its tokens is encountered.
49
     *
50
     * @param PHP_CodeSniffer_File $phpcsFile The current file being checked.
51
     * @param int                  $stackPtr  The position of the current token in
52
     *                                        the stack passed in $tokens.
53
     *
54
     * @return void
55
     */
56
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
57
    {
58
        $tokens = $phpcsFile->getTokens();
59
60
        if ($tokens[$stackPtr]['code'] === T_ARRAY) {
61
            $phpcsFile->recordMetric($stackPtr, 'Short array syntax used', 'no');
62
63
            // Array keyword should be lower case.
64
            if ($tokens[$stackPtr]['content'] !== strtolower($tokens[$stackPtr]['content'])) {
65
                if ($tokens[$stackPtr]['content'] === strtoupper($tokens[$stackPtr]['content'])) {
66
                    $phpcsFile->recordMetric($stackPtr, 'Array keyword case', 'upper');
67
                } else {
68
                    $phpcsFile->recordMetric($stackPtr, 'Array keyword case', 'mixed');
69
                }
70
71
                $error = 'Array keyword should be lower case; expected "array" but found "%s"';
72
                $data  = array($tokens[$stackPtr]['content']);
73
                $fix   = $phpcsFile->addFixableError($error, $stackPtr, 'NotLowerCase', $data);
74
                if ($fix === true) {
75
                    $phpcsFile->fixer->replaceToken($stackPtr, 'array');
76
                }
77
            } else {
78
                $phpcsFile->recordMetric($stackPtr, 'Array keyword case', 'lower');
79
            }
80
81
            $arrayStart = $tokens[$stackPtr]['parenthesis_opener'];
82
            if (isset($tokens[$arrayStart]['parenthesis_closer']) === false) {
83
                return;
84
            }
85
86
            $arrayEnd = $tokens[$arrayStart]['parenthesis_closer'];
87
88
            if ($arrayStart !== ($stackPtr + 1)) {
89
                $error = 'There must be no space between the "array" keyword and the opening parenthesis';
90
                $fix   = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceAfterKeyword');
91
92
                if ($fix === true) {
93
                    $phpcsFile->fixer->beginChangeset();
94
                    for ($i = ($stackPtr + 1); $i < $arrayStart; $i++) {
95
                        $phpcsFile->fixer->replaceToken($i, '');
96
                    }
97
98
                    $phpcsFile->fixer->endChangeset();
99
                }
100
            }
101
        } else {
102
            $phpcsFile->recordMetric($stackPtr, 'Short array syntax used', 'yes');
103
            $arrayStart = $stackPtr;
104
            $arrayEnd   = $tokens[$stackPtr]['bracket_closer'];
105
        }//end if
106
107
        // Check for empty arrays.
108
        $content = $phpcsFile->findNext(T_WHITESPACE, ($arrayStart + 1), ($arrayEnd + 1), true);
109
        if ($content === $arrayEnd) {
110
            // Empty array, but if the brackets aren't together, there's a problem.
111
            if (($arrayEnd - $arrayStart) !== 1) {
112
                $error = 'Empty array declaration must have no space between the parentheses';
113
                $fix   = $phpcsFile->addFixableError($error, $stackPtr, 'SpaceInEmptyArray');
114
115
                if ($fix === true) {
116
                    $phpcsFile->fixer->beginChangeset();
117
                    for ($i = ($arrayStart + 1); $i < $arrayEnd; $i++) {
118
                        $phpcsFile->fixer->replaceToken($i, '');
119
                    }
120
121
                    $phpcsFile->fixer->endChangeset();
122
                }
123
            }
124
125
            // We can return here because there is nothing else to check. All code
126
            // below can assume that the array is not empty.
127
            return;
128
        }
129
130
        if ($tokens[$arrayStart]['line'] === $tokens[$arrayEnd]['line']) {
131
            $this->processSingleLineArray($phpcsFile, $stackPtr, $arrayStart, $arrayEnd);
132
        } else {
133
            $this->processMultiLineArray($phpcsFile, $stackPtr, $arrayStart, $arrayEnd);
134
        }
135
136
    }//end process()
137
138
139
    /**
140
     * Processes a single-line array definition.
141
     *
142
     * @param PHP_CodeSniffer_File $phpcsFile  The current file being checked.
143
     * @param int                  $stackPtr   The position of the current token
144
     *                                         in the stack passed in $tokens.
145
     * @param int                  $arrayStart The token that starts the array definition.
146
     * @param int                  $arrayEnd   The token that ends the array definition.
147
     *
148
     * @return void
149
     */
150
    public function processSingleLineArray(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $arrayStart, $arrayEnd)
151
    {
152
        $tokens = $phpcsFile->getTokens();
153
154
        // Check if there are multiple values. If so, then it has to be multiple lines
155
        // unless it is contained inside a function call or condition.
156
        $valueCount = 0;
157
        $commas     = array();
158
        for ($i = ($arrayStart + 1); $i < $arrayEnd; $i++) {
159
            // Skip bracketed statements, like function calls.
160
            if ($tokens[$i]['code'] === T_OPEN_PARENTHESIS) {
161
                $i = $tokens[$i]['parenthesis_closer'];
162
                continue;
163
            }
164
165
            if ($tokens[$i]['code'] === T_COMMA) {
166
                // Before counting this comma, make sure we are not
167
                // at the end of the array.
168
                $next = $phpcsFile->findNext(T_WHITESPACE, ($i + 1), $arrayEnd, true);
169
                if ($next !== false) {
170
                    $valueCount++;
171
                    $commas[] = $i;
172
                } else {
173
                    // There is a comma at the end of a single line array.
174
                    $error = 'Comma not allowed after last value in single-line array declaration';
175
                    $fix   = $phpcsFile->addFixableError($error, $i, 'CommaAfterLast');
176
                    if ($fix === true) {
177
                        $phpcsFile->fixer->replaceToken($i, '');
178
                    }
179
                }
180
            }
181
        }//end for
182
183
        // Now check each of the double arrows (if any).
184
        $nextArrow = $arrayStart;
185
        while (($nextArrow = $phpcsFile->findNext(T_DOUBLE_ARROW, ($nextArrow + 1), $arrayEnd)) !== false) {
186
            if ($tokens[($nextArrow - 1)]['code'] !== T_WHITESPACE) {
187
                $content = $tokens[($nextArrow - 1)]['content'];
188
                $error   = 'Expected 1 space between "%s" and double arrow; 0 found';
189
                $data    = array($content);
190
                $fix     = $phpcsFile->addFixableError($error, $nextArrow, 'NoSpaceBeforeDoubleArrow', $data);
191
                if ($fix === true) {
192
                    $phpcsFile->fixer->addContentBefore($nextArrow, ' ');
193
                }
194
            } else {
195
                $spaceLength = $tokens[($nextArrow - 1)]['length'];
196
                if ($spaceLength !== 1) {
197
                    $content = $tokens[($nextArrow - 2)]['content'];
198
                    $error   = 'Expected 1 space between "%s" and double arrow; %s found';
199
                    $data    = array(
200
                                $content,
201
                                $spaceLength,
202
                               );
203
204
                    $fix = $phpcsFile->addFixableError($error, $nextArrow, 'SpaceBeforeDoubleArrow', $data);
205
                    if ($fix === true) {
206
                        $phpcsFile->fixer->replaceToken(($nextArrow - 1), ' ');
207
                    }
208
                }
209
            }//end if
210
211
            if ($tokens[($nextArrow + 1)]['code'] !== T_WHITESPACE) {
212
                $content = $tokens[($nextArrow + 1)]['content'];
213
                $error   = 'Expected 1 space between double arrow and "%s"; 0 found';
214
                $data    = array($content);
215
                $fix     = $phpcsFile->addFixableError($error, $nextArrow, 'NoSpaceAfterDoubleArrow', $data);
216
                if ($fix === true) {
217
                    $phpcsFile->fixer->addContent($nextArrow, ' ');
218
                }
219
            } else {
220
                $spaceLength = $tokens[($nextArrow + 1)]['length'];
221
                if ($spaceLength !== 1) {
222
                    $content = $tokens[($nextArrow + 2)]['content'];
223
                    $error   = 'Expected 1 space between double arrow and "%s"; %s found';
224
                    $data    = array(
225
                                $content,
226
                                $spaceLength,
227
                               );
228
229
                    $fix = $phpcsFile->addFixableError($error, $nextArrow, 'SpaceAfterDoubleArrow', $data);
230
                    if ($fix === true) {
231
                        $phpcsFile->fixer->replaceToken(($nextArrow + 1), ' ');
232
                    }
233
                }
234
            }//end if
235
        }//end while
236
237
        if ($valueCount > 0) {
238
            $conditionCheck = $phpcsFile->findPrevious(array(T_OPEN_PARENTHESIS, T_SEMICOLON), ($stackPtr - 1), null, false);
239
240
            if ($conditionCheck === false
241
                || $tokens[$conditionCheck]['line'] !== $tokens[$stackPtr]['line']
242
            ) {
243
                $error = 'Array with multiple values cannot be declared on a single line';
244
                $fix   = $phpcsFile->addFixableError($error, $stackPtr, 'SingleLineNotAllowed');
245
                if ($fix === true) {
246
                    $phpcsFile->fixer->beginChangeset();
247
                    $phpcsFile->fixer->addNewline($arrayStart);
248
                    $phpcsFile->fixer->addNewlineBefore($arrayEnd);
249
                    $phpcsFile->fixer->endChangeset();
250
                }
251
252
                return;
253
            }
254
255
            // We have a multiple value array that is inside a condition or
256
            // function. Check its spacing is correct.
257
            foreach ($commas as $comma) {
258
                if ($tokens[($comma + 1)]['code'] !== T_WHITESPACE) {
259
                    $content = $tokens[($comma + 1)]['content'];
260
                    $error   = 'Expected 1 space between comma and "%s"; 0 found';
261
                    $data    = array($content);
262
                    $fix     = $phpcsFile->addFixableError($error, $comma, 'NoSpaceAfterComma', $data);
263
                    if ($fix === true) {
264
                        $phpcsFile->fixer->addContent($comma, ' ');
265
                    }
266
                } else {
267
                    $spaceLength = $tokens[($comma + 1)]['length'];
268
                    if ($spaceLength !== 1) {
269
                        $content = $tokens[($comma + 2)]['content'];
270
                        $error   = 'Expected 1 space between comma and "%s"; %s found';
271
                        $data    = array(
272
                                    $content,
273
                                    $spaceLength,
274
                                   );
275
276
                        $fix = $phpcsFile->addFixableError($error, $comma, 'SpaceAfterComma', $data);
277
                        if ($fix === true) {
278
                            $phpcsFile->fixer->replaceToken(($comma + 1), ' ');
279
                        }
280
                    }
281
                }//end if
282
283
                if ($tokens[($comma - 1)]['code'] === T_WHITESPACE) {
284
                    $content     = $tokens[($comma - 2)]['content'];
285
                    $spaceLength = $tokens[($comma - 1)]['length'];
286
                    $error       = 'Expected 0 spaces between "%s" and comma; %s found';
287
                    $data        = array(
288
                                    $content,
289
                                    $spaceLength,
290
                                   );
291
292
                    $fix = $phpcsFile->addFixableError($error, $comma, 'SpaceBeforeComma', $data);
293
                    if ($fix === true) {
294
                        $phpcsFile->fixer->replaceToken(($comma - 1), '');
295
                    }
296
                }
297
            }//end foreach
298
        }//end if
299
300
    }//end processSingleLineArray()
301
302
303
    /**
304
     * Processes a multi-line array definition.
305
     *
306
     * @param PHP_CodeSniffer_File $phpcsFile  The current file being checked.
307
     * @param int                  $stackPtr   The position of the current token
308
     *                                         in the stack passed in $tokens.
309
     * @param int                  $arrayStart The token that starts the array definition.
310
     * @param int                  $arrayEnd   The token that ends the array definition.
311
     *
312
     * @return void
313
     */
314
    public function processMultiLineArray(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $arrayStart, $arrayEnd)
315
    {
316
        $tokens       = $phpcsFile->getTokens();
317
        $keywordStart = $tokens[$stackPtr]['column'];
318
319
        // Check the closing bracket is on a new line.
320
        $lastContent = $phpcsFile->findPrevious(T_WHITESPACE, ($arrayEnd - 1), $arrayStart, true);
321
        if ($tokens[$lastContent]['line'] === $tokens[$arrayEnd]['line']) {
322
            $error = 'Closing parenthesis of array declaration must be on a new line';
323
            $fix   = $phpcsFile->addFixableError($error, $arrayEnd, 'CloseBraceNewLine');
324
            if ($fix === true) {
325
                $phpcsFile->fixer->addNewlineBefore($arrayEnd);
326
            }
327
        } else if ($tokens[$arrayEnd]['column'] !== $keywordStart) {
328
            // Check the closing bracket is lined up under the "a" in array.
329
            $expected = ($keywordStart - 1);
330
            $found    = ($tokens[$arrayEnd]['column'] - 1);
331
            $error    = 'Closing parenthesis not aligned correctly; expected %s space(s) but found %s';
332
            $data     = array(
333
                         $expected,
334
                         $found,
335
                        );
336
337
            $fix = $phpcsFile->addFixableError($error, $arrayEnd, 'CloseBraceNotAligned', $data);
338
            if ($fix === true) {
339
                if ($found === 0) {
340
                    $phpcsFile->fixer->addContent(($arrayEnd - 1), str_repeat(' ', $expected));
341
                } else {
342
                    $phpcsFile->fixer->replaceToken(($arrayEnd - 1), str_repeat(' ', $expected));
343
                }
344
            }
345
        }//end if
346
347
        $keyUsed    = false;
348
        $singleUsed = false;
349
        $indices    = array();
350
        $maxLength  = 0;
351
352
        if ($tokens[$stackPtr]['code'] === T_ARRAY) {
353
            $lastToken = $tokens[$stackPtr]['parenthesis_opener'];
354
        } else {
355
            $lastToken = $stackPtr;
356
        }
357
358
        // Find all the double arrows that reside in this scope.
359
        for ($nextToken = ($stackPtr + 1); $nextToken < $arrayEnd; $nextToken++) {
360
            // Skip bracketed statements, like function calls.
361
            if ($tokens[$nextToken]['code'] === T_OPEN_PARENTHESIS
362
                && (isset($tokens[$nextToken]['parenthesis_owner']) === false
363
                || $tokens[$nextToken]['parenthesis_owner'] !== $stackPtr)
364
            ) {
365
                $nextToken = $tokens[$nextToken]['parenthesis_closer'];
366
                continue;
367
            }
368
369
            if ($tokens[$nextToken]['code'] === T_ARRAY
370
                || $tokens[$nextToken]['code'] === T_OPEN_SHORT_ARRAY
371
                || $tokens[$nextToken]['code'] === T_CLOSURE
372
            ) {
373
                // Let subsequent calls of this test handle nested arrays.
374
                if ($tokens[$lastToken]['code'] !== T_DOUBLE_ARROW) {
375
                    $indices[] = array('value' => $nextToken);
376
                    $lastToken = $nextToken;
377
                }
378
379
                if ($tokens[$nextToken]['code'] === T_ARRAY) {
380
                    $nextToken = $tokens[$tokens[$nextToken]['parenthesis_opener']]['parenthesis_closer'];
381
                } else if ($tokens[$nextToken]['code'] === T_OPEN_SHORT_ARRAY) {
382
                    $nextToken = $tokens[$nextToken]['bracket_closer'];
383
                } else {
384
                    // T_CLOSURE.
385
                    $nextToken = $tokens[$nextToken]['scope_closer'];
386
                }
387
388
                $nextToken = $phpcsFile->findNext(T_WHITESPACE, ($nextToken + 1), null, true);
389
                if ($tokens[$nextToken]['code'] !== T_COMMA) {
390
                    $nextToken--;
391
                } else {
392
                    $lastToken = $nextToken;
393
                }
394
395
                continue;
396
            }//end if
397
398
            if ($tokens[$nextToken]['code'] !== T_DOUBLE_ARROW
399
                && $tokens[$nextToken]['code'] !== T_COMMA
400
            ) {
401
                continue;
402
            }
403
404
            $currentEntry = array();
405
406
            if ($tokens[$nextToken]['code'] === T_COMMA) {
407
                $stackPtrCount = 0;
408
                if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) {
409
                    $stackPtrCount = count($tokens[$stackPtr]['nested_parenthesis']);
410
                }
411
412
                $commaCount = 0;
413
                if (isset($tokens[$nextToken]['nested_parenthesis']) === true) {
414
                    $commaCount = count($tokens[$nextToken]['nested_parenthesis']);
415
                    if ($tokens[$stackPtr]['code'] === T_ARRAY) {
416
                        // Remove parenthesis that are used to define the array.
417
                        $commaCount--;
418
                    }
419
                }
420
421
                if ($commaCount > $stackPtrCount) {
422
                    // This comma is inside more parenthesis than the ARRAY keyword,
423
                    // then there it is actually a comma used to separate arguments
424
                    // in a function call.
425
                    continue;
426
                }
427
428
                if ($keyUsed === true && $tokens[$lastToken]['code'] === T_COMMA) {
429
                    $error = 'No key specified for array entry; first entry specifies key';
430
                    $phpcsFile->addError($error, $nextToken, 'NoKeySpecified');
431
                    return;
432
                }
433
434
                if ($keyUsed === false) {
435
                    if ($tokens[($nextToken - 1)]['code'] === T_WHITESPACE) {
436
                        $content = $tokens[($nextToken - 2)]['content'];
437
                        if ($tokens[($nextToken - 1)]['content'] === $phpcsFile->eolChar) {
438
                            $spaceLength = 'newline';
439
                        } else {
440
                            $spaceLength = $tokens[($nextToken - 1)]['length'];
441
                        }
442
443
                        $error = 'Expected 0 spaces between "%s" and comma; %s found';
444
                        $data  = array(
445
                                  $content,
446
                                  $spaceLength,
447
                                 );
448
449
                        $fix = $phpcsFile->addFixableError($error, $nextToken, 'SpaceBeforeComma', $data);
450
                        if ($fix === true) {
451
                            $phpcsFile->fixer->replaceToken(($nextToken - 1), '');
452
                        }
453
                    }
454
455
                    $valueContent = $phpcsFile->findNext(
456
                        PHP_CodeSniffer_Tokens::$emptyTokens,
457
                        ($lastToken + 1),
458
                        $nextToken,
459
                        true
460
                    );
461
462
                    $indices[]  = array('value' => $valueContent);
463
                    $singleUsed = true;
464
                }//end if
465
466
                $lastToken = $nextToken;
467
                continue;
468
            }//end if
469
470
            if ($tokens[$nextToken]['code'] === T_DOUBLE_ARROW) {
471
                if ($singleUsed === true) {
472
                    $error = 'Key specified for array entry; first entry has no key';
473
                    $phpcsFile->addError($error, $nextToken, 'KeySpecified');
474
                    return;
475
                }
476
477
                $currentEntry['arrow'] = $nextToken;
478
                $keyUsed = true;
479
480
                // Find the start of index that uses this double arrow.
481
                $indexEnd   = $phpcsFile->findPrevious(T_WHITESPACE, ($nextToken - 1), $arrayStart, true);
482
                $indexStart = $phpcsFile->findStartOfStatement($indexEnd);
483
484
                if ($indexStart === $indexEnd) {
485
                    $currentEntry['index']         = $indexEnd;
486
                    $currentEntry['index_content'] = $tokens[$indexEnd]['content'];
487
                } else {
488
                    $currentEntry['index']         = $indexStart;
489
                    $currentEntry['index_content'] = $phpcsFile->getTokensAsString($indexStart, ($indexEnd - $indexStart + 1));
490
                }
491
492
                $indexLength = strlen($currentEntry['index_content']);
493
                if ($maxLength < $indexLength) {
494
                    $maxLength = $indexLength;
495
                }
496
497
                // Find the value of this index.
498
                $nextContent = $phpcsFile->findNext(
499
                    PHP_CodeSniffer_Tokens::$emptyTokens,
500
                    ($nextToken + 1),
501
                    $arrayEnd,
502
                    true
503
                );
504
505
                $currentEntry['value'] = $nextContent;
506
                $indices[] = $currentEntry;
507
                $lastToken = $nextToken;
508
            }//end if
509
        }//end for
510
511
        // Check for mutli-line arrays that should be single-line.
512
        $singleValue = false;
513
514
        if (empty($indices) === true) {
515
            $singleValue = true;
516
        } else if (count($indices) === 1 && $tokens[$lastToken]['code'] === T_COMMA) {
517
            // There may be another array value without a comma.
518
            $exclude     = PHP_CodeSniffer_Tokens::$emptyTokens;
519
            $exclude[]   = T_COMMA;
520
            $nextContent = $phpcsFile->findNext($exclude, ($indices[0]['value'] + 1), $arrayEnd, true);
521
            if ($nextContent === false) {
522
                $singleValue = true;
523
            }
524
        }
525
526
        if ($singleValue === true) {
527
            // Array cannot be empty, so this is a multi-line array with
528
            // a single value. It should be defined on single line.
529
            $error = 'Multi-line array contains a single value; use single-line array instead';
530
            $fix   = $phpcsFile->addFixableError($error, $stackPtr, 'MultiLineNotAllowed');
531
532
            if ($fix === true) {
533
                $phpcsFile->fixer->beginChangeset();
534
                for ($i = ($arrayStart + 1); $i < $arrayEnd; $i++) {
535
                    if ($tokens[$i]['code'] !== T_WHITESPACE) {
536
                        break;
537
                    }
538
539
                    $phpcsFile->fixer->replaceToken($i, '');
540
                }
541
542
                for ($i = ($arrayEnd - 1); $i > $arrayStart; $i--) {
543
                    if ($tokens[$i]['code'] !== T_WHITESPACE) {
544
                        break;
545
                    }
546
547
                    $phpcsFile->fixer->replaceToken($i, '');
548
                }
549
550
                $phpcsFile->fixer->endChangeset();
551
            }
552
553
            return;
554
        }//end if
555
556
        /*
557
            This section checks for arrays that don't specify keys.
558
559
            Arrays such as:
560
               array(
561
                'aaa',
562
                'bbb',
563
                'd',
564
               );
565
        */
566
567
        if ($keyUsed === false && empty($indices) === false) {
568
            $count     = count($indices);
569
            $lastIndex = $indices[($count - 1)]['value'];
570
571
            $trailingContent = $phpcsFile->findPrevious(
572
                PHP_CodeSniffer_Tokens::$emptyTokens,
573
                ($arrayEnd - 1),
574
                $lastIndex,
575
                true
576
            );
577
578
            if ($tokens[$trailingContent]['code'] !== T_COMMA) {
579
                $phpcsFile->recordMetric($stackPtr, 'Array end comma', 'no');
580
                $error = 'Comma required after last value in array declaration';
581
                $fix   = $phpcsFile->addFixableError($error, $trailingContent, 'NoCommaAfterLast');
582
                if ($fix === true) {
583
                    $phpcsFile->fixer->addContent($trailingContent, ',');
584
                }
585
            } else {
586
                $phpcsFile->recordMetric($stackPtr, 'Array end comma', 'yes');
587
            }
588
589
            $lastValueLine = false;
590
            foreach ($indices as $value) {
591
                if (empty($value['value']) === true) {
592
                    // Array was malformed and we couldn't figure out
593
                    // the array value correctly, so we have to ignore it.
594
                    // Other parts of this sniff will correct the error.
595
                    continue;
596
                }
597
598
                if ($lastValueLine !== false && $tokens[$value['value']]['line'] === $lastValueLine) {
599
                    $error = 'Each value in a multi-line array must be on a new line';
600
                    $fix   = $phpcsFile->addFixableError($error, $value['value'], 'ValueNoNewline');
601
                    if ($fix === true) {
602
                        if ($tokens[($value['value'] - 1)]['code'] === T_WHITESPACE) {
603
                            $phpcsFile->fixer->replaceToken(($value['value'] - 1), '');
604
                        }
605
606
                        $phpcsFile->fixer->addNewlineBefore($value['value']);
607
                    }
608
                } else if ($tokens[($value['value'] - 1)]['code'] === T_WHITESPACE) {
609
                    $expected = $keywordStart;
610
611
                    $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $value['value'], true);
612
                    $found = ($tokens[$first]['column'] - 1);
613
                    if ($found !== $expected) {
614
                        $error = 'Array value not aligned correctly; expected %s spaces but found %s';
615
                        $data  = array(
616
                                  $expected,
617
                                  $found,
618
                                 );
619
620
                        $fix = $phpcsFile->addFixableError($error, $value['value'], 'ValueNotAligned', $data);
621
                        if ($fix === true) {
622
                            if ($found === 0) {
623
                                $phpcsFile->fixer->addContent(($value['value'] - 1), str_repeat(' ', $expected));
624
                            } else {
625
                                $phpcsFile->fixer->replaceToken(($value['value'] - 1), str_repeat(' ', $expected));
626
                            }
627
                        }
628
                    }
629
                }//end if
630
631
                $lastValueLine = $tokens[$value['value']]['line'];
632
            }//end foreach
633
        }//end if
634
635
        /*
636
            Below the actual indentation of the array is checked.
637
            Errors will be thrown when a key is not aligned, when
638
            a double arrow is not aligned, and when a value is not
639
            aligned correctly.
640
            If an error is found in one of the above areas, then errors
641
            are not reported for the rest of the line to avoid reporting
642
            spaces and columns incorrectly. Often fixing the first
643
            problem will fix the other 2 anyway.
644
645
            For example:
646
647
            $a = array(
648
                  'index'  => '2',
649
                 );
650
651
            or
652
653
            $a = [
654
                  'index'  => '2',
655
                 ];
656
657
            In this array, the double arrow is indented too far, but this
658
            will also cause an error in the value's alignment. If the arrow were
659
            to be moved back one space however, then both errors would be fixed.
660
        */
661
662
        $numValues = count($indices);
663
664
        $indicesStart  = ($keywordStart + 1);
665
        $arrowStart    = ($indicesStart + $maxLength + 1);
666
        $valueStart    = ($arrowStart + 3);
667
        $indexLine     = $tokens[$stackPtr]['line'];
668
        $lastIndexLine = null;
669
        foreach ($indices as $index) {
670
            if (isset($index['index']) === false) {
671
                // Array value only.
672
                if ($tokens[$index['value']]['line'] === $tokens[$stackPtr]['line'] && $numValues > 1) {
673
                    $error = 'The first value in a multi-value array must be on a new line';
674
                    $fix   = $phpcsFile->addFixableError($error, $stackPtr, 'FirstValueNoNewline');
675
                    if ($fix === true) {
676
                        $phpcsFile->fixer->addNewlineBefore($index['value']);
677
                    }
678
                }
679
680
                continue;
681
            }
682
683
            $lastIndexLine = $indexLine;
684
            $indexLine     = $tokens[$index['index']]['line'];
685
686
            if ($indexLine === $tokens[$stackPtr]['line']) {
687
                $error = 'The first index in a multi-value array must be on a new line';
688
                $fix   = $phpcsFile->addFixableError($error, $index['index'], 'FirstIndexNoNewline');
689
                if ($fix === true) {
690
                    $phpcsFile->fixer->addNewlineBefore($index['index']);
691
                }
692
693
                continue;
694
            }
695
696
            if ($indexLine === $lastIndexLine) {
697
                $error = 'Each index in a multi-line array must be on a new line';
698
                $fix   = $phpcsFile->addFixableError($error, $index['index'], 'IndexNoNewline');
699
                if ($fix === true) {
700
                    if ($tokens[($index['index'] - 1)]['code'] === T_WHITESPACE) {
701
                        $phpcsFile->fixer->replaceToken(($index['index'] - 1), '');
702
                    }
703
704
                    $phpcsFile->fixer->addNewlineBefore($index['index']);
705
                }
706
707
                continue;
708
            }
709
710
            if ($tokens[$index['index']]['column'] !== $indicesStart) {
711
                $expected = ($indicesStart - 1);
712
                $found    = ($tokens[$index['index']]['column'] - 1);
713
                $error    = 'Array key not aligned correctly; expected %s spaces but found %s';
714
                $data     = array(
715
                             $expected,
716
                             $found,
717
                            );
718
719
                $fix = $phpcsFile->addFixableError($error, $index['index'], 'KeyNotAligned', $data);
720
                if ($fix === true) {
721
                    if ($found === 0) {
722
                        $phpcsFile->fixer->addContent(($index['index'] - 1), str_repeat(' ', $expected));
723
                    } else {
724
                        $phpcsFile->fixer->replaceToken(($index['index'] - 1), str_repeat(' ', $expected));
725
                    }
726
                }
727
728
                continue;
729
            }
730
731
            if ($tokens[$index['arrow']]['column'] !== $arrowStart) {
732
                $expected = ($arrowStart - (strlen($index['index_content']) + $tokens[$index['index']]['column']));
733
                $found    = ($tokens[$index['arrow']]['column'] - (strlen($index['index_content']) + $tokens[$index['index']]['column']));
734
                $error    = 'Array double arrow not aligned correctly; expected %s space(s) but found %s';
735
                $data     = array(
736
                             $expected,
737
                             $found,
738
                            );
739
740
                $fix = $phpcsFile->addFixableError($error, $index['arrow'], 'DoubleArrowNotAligned', $data);
741
                if ($fix === true) {
742
                    if ($found === 0) {
743
                        $phpcsFile->fixer->addContent(($index['arrow'] - 1), str_repeat(' ', $expected));
744
                    } else {
745
                        $phpcsFile->fixer->replaceToken(($index['arrow'] - 1), str_repeat(' ', $expected));
746
                    }
747
                }
748
749
                continue;
750
            }
751
752
            if ($tokens[$index['value']]['column'] !== $valueStart) {
753
                $expected = ($valueStart - ($tokens[$index['arrow']]['length'] + $tokens[$index['arrow']]['column']));
754
                $found    = ($tokens[$index['value']]['column'] - ($tokens[$index['arrow']]['length'] + $tokens[$index['arrow']]['column']));
755
                if ($found < 0) {
756
                    $found = 'newline';
757
                }
758
759
                $error = 'Array value not aligned correctly; expected %s space(s) but found %s';
760
                $data  = array(
761
                          $expected,
762
                          $found,
763
                         );
764
765
                $fix = $phpcsFile->addFixableError($error, $index['arrow'], 'ValueNotAligned', $data);
766
                if ($fix === true) {
767
                    if ($found === 'newline') {
768
                        $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($index['value'] - 1), null, true);
769
                        $phpcsFile->fixer->beginChangeset();
770
                        for ($i = ($prev + 1); $i < $index['value']; $i++) {
771
                            $phpcsFile->fixer->replaceToken($i, '');
772
                        }
773
774
                        $phpcsFile->fixer->replaceToken(($index['value'] - 1), str_repeat(' ', $expected));
775
                        $phpcsFile->fixer->endChangeset();
776
                    } else if ($found === 0) {
777
                        $phpcsFile->fixer->addContent(($index['value'] - 1), str_repeat(' ', $expected));
778
                    } else {
779
                        $phpcsFile->fixer->replaceToken(($index['value'] - 1), str_repeat(' ', $expected));
780
                    }
781
                }
782
            }//end if
783
784
            // Check each line ends in a comma.
785
            $valueLine = $tokens[$index['value']]['line'];
786
            $nextComma = false;
787
            for ($i = $index['value']; $i < $arrayEnd; $i++) {
788
                // Skip bracketed statements, like function calls.
789
                if ($tokens[$i]['code'] === T_OPEN_PARENTHESIS) {
790
                    $i         = $tokens[$i]['parenthesis_closer'];
791
                    $valueLine = $tokens[$i]['line'];
792
                    continue;
793
                }
794
795
                if ($tokens[$i]['code'] === T_ARRAY) {
796
                    $i         = $tokens[$tokens[$i]['parenthesis_opener']]['parenthesis_closer'];
797
                    $valueLine = $tokens[$i]['line'];
798
                    continue;
799
                }
800
801
                // Skip to the end of multi-line strings.
802
                if (isset(PHP_CodeSniffer_Tokens::$stringTokens[$tokens[$i]['code']]) === true) {
803
                    $i = $phpcsFile->findNext($tokens[$i]['code'], ($i + 1), null, true);
804
                    $i--;
805
                    $valueLine = $tokens[$i]['line'];
806
                    continue;
807
                }
808
809
                if ($tokens[$i]['code'] === T_OPEN_SHORT_ARRAY) {
810
                    $i         = $tokens[$i]['bracket_closer'];
811
                    $valueLine = $tokens[$i]['line'];
812
                    continue;
813
                }
814
815
                if ($tokens[$i]['code'] === T_CLOSURE) {
816
                    $i         = $tokens[$i]['scope_closer'];
817
                    $valueLine = $tokens[$i]['line'];
818
                    continue;
819
                }
820
821
                if ($tokens[$i]['code'] === T_COMMA) {
822
                    $nextComma = $i;
823
                    break;
824
                }
825
            }//end for
826
827
            if ($nextComma === false || ($tokens[$nextComma]['line'] !== $valueLine)) {
828
                $error = 'Each line in an array declaration must end in a comma';
829
                $fix   = $phpcsFile->addFixableError($error, $index['value'], 'NoComma');
830
831
                if ($fix === true) {
832
                    // Find the end of the line and put a comma there.
833
                    for ($i = ($index['value'] + 1); $i < $arrayEnd; $i++) {
834
                        if ($tokens[$i]['line'] > $valueLine) {
835
                            break;
836
                        }
837
                    }
838
839
                    $phpcsFile->fixer->addContentBefore(($i - 1), ',');
840
                }
841
            }
842
843
            // Check that there is no space before the comma.
844
            if ($nextComma !== false && $tokens[($nextComma - 1)]['code'] === T_WHITESPACE) {
845
                $content     = $tokens[($nextComma - 2)]['content'];
846
                $spaceLength = $tokens[($nextComma - 1)]['length'];
847
                $error       = 'Expected 0 spaces between "%s" and comma; %s found';
848
                $data        = array(
849
                                $content,
850
                                $spaceLength,
851
                               );
852
853
                $fix = $phpcsFile->addFixableError($error, $nextComma, 'SpaceBeforeComma', $data);
854
                if ($fix === true) {
855
                    $phpcsFile->fixer->replaceToken(($nextComma - 1), '');
856
                }
857
            }
858
        }//end foreach
859
860
    }//end processMultiLineArray()
861
862
863
}//end class
864