@@ -325,53 +325,35 @@ public function processMultiLineArray(File $phpcsFile, $stackPtr, $arrayStart, $
325325
326326 // Find all the double arrows that reside in this scope.
327327 for ($ nextToken = ($ stackPtr + 1 ); $ nextToken < $ arrayEnd ; $ nextToken ++) {
328- // Skip bracketed statements, like function calls.
329- if (T_OPEN_PARENTHESIS === $ tokens [$ nextToken ]['code ' ]
330- && (false === isset ($ tokens [$ nextToken ]['parenthesis_owner ' ])
331- || $ tokens [$ nextToken ]['parenthesis_owner ' ] !== $ stackPtr )
332- ) {
333- $ nextToken = $ tokens [$ nextToken ]['parenthesis_closer ' ];
334- continue ;
335- }
336-
337- if (T_ARRAY === $ tokens [$ nextToken ]['code ' ]
338- || T_OPEN_SHORT_ARRAY === $ tokens [$ nextToken ]['code ' ]
339- || T_CLOSURE === $ tokens [$ nextToken ]['code ' ]
340- ) {
341- // Let subsequent calls of this test handle nested arrays.
342- if (T_DOUBLE_ARROW !== $ tokens [$ lastToken ]['code ' ]) {
343- $ indices [] = ['value ' => $ nextToken ];
344- $ lastToken = $ nextToken ;
345- }
346-
347- if (T_ARRAY === $ tokens [$ nextToken ]['code ' ]) {
328+ // Skip array or function calls
329+ switch ($ tokens [$ nextToken ]['code ' ]) {
330+ case T_ARRAY :
348331 $ nextToken = $ tokens [$ tokens [$ nextToken ]['parenthesis_opener ' ]]['parenthesis_closer ' ];
349- } elseif (T_OPEN_SHORT_ARRAY === $ tokens [$ nextToken ]['code ' ]) {
332+ continue ;
333+ case T_OPEN_SHORT_ARRAY :
350334 $ nextToken = $ tokens [$ nextToken ]['bracket_closer ' ];
351- } else {
352- // T_CLOSURE.
335+ continue ;
336+ case T_CLOSURE :
353337 $ nextToken = $ tokens [$ nextToken ]['scope_closer ' ];
354- }
355-
356- $ nextToken = $ phpcsFile ->findNext (T_WHITESPACE , ($ nextToken + 1 ), null , true );
357- if (T_COMMA !== $ tokens [$ nextToken ]['code ' ]) {
358- $ nextToken --;
359- } else {
360- $ lastToken = $ nextToken ;
361- }
362-
363- continue ;
338+ continue ;
339+ case T_OPEN_PARENTHESIS :
340+ $ parenthesisOwner = $ tokens [$ nextToken ]['parenthesis_owner ' ];
341+ if (false === isset ($ parenthesisOwner ) || $ parenthesisOwner !== $ stackPtr ) {
342+ $ nextToken = $ tokens [$ nextToken ]['parenthesis_closer ' ];
343+ continue ;
344+ }
345+ break ;
364346 }
365347
366- if (T_DOUBLE_ARROW !== $ tokens [$ nextToken ]['code ' ]
367- && T_COMMA !== $ tokens [ $ nextToken ][ ' code ' ]
348+ if (! in_array ( $ tokens [$ nextToken ]['code ' ], [ T_DOUBLE_ARROW , T_COMMA ])
349+ && $ nextToken !== $ arrayEnd - 1
368350 ) {
369351 continue ;
370352 }
371353
372354 $ currentEntry = [];
373355
374- if (T_COMMA === $ tokens [$ nextToken ]['code ' ]) {
356+ if (T_COMMA === $ tokens [$ nextToken ]['code ' ] || $ nextToken === $ arrayEnd - 1 ) {
375357 $ stackPtrCount = 0 ;
376358 if (true === isset ($ tokens [$ stackPtr ]['nested_parenthesis ' ])) {
377359 $ stackPtrCount = count ($ tokens [$ stackPtr ]['nested_parenthesis ' ]);
@@ -393,43 +375,41 @@ public function processMultiLineArray(File $phpcsFile, $stackPtr, $arrayStart, $
393375 continue ;
394376 }
395377
396- if ( true === $ keyUsed && T_COMMA === $ tokens [ $ lastToken ][ ' code ' ]) {
397- $ error = ' No key specified for array entry; first entry specifies key ' ;
398- $ phpcsFile -> addError ( $ error , $ nextToken , ' NoKeySpecified ' );
399-
400- return ;
401- }
378+ $ valueContent = $ phpcsFile -> findNext (
379+ Tokens:: $ emptyTokens ,
380+ ( $ lastToken + 1 ),
381+ $ nextToken ,
382+ true
383+ );
402384
403- if (false === $ keyUsed ) {
404- if (T_WHITESPACE === $ tokens [($ nextToken - 1 )]['code ' ]) {
405- $ content = $ tokens [($ nextToken - 2 )]['content ' ];
406- if ($ tokens [($ nextToken - 1 )]['content ' ] === $ phpcsFile ->eolChar ) {
407- $ spaceLength = 'newline ' ;
408- } else {
409- $ spaceLength = $ tokens [($ nextToken - 1 )]['length ' ];
410- }
385+ if (false !== $ valueContent && T_DOUBLE_ARROW !== $ tokens [$ lastToken ]['code ' ]) {
386+ if (true === $ keyUsed ) {
387+ $ error = 'No key specified for array entry; first entry specifies key ' ;
388+ $ phpcsFile ->addError ($ error , $ nextToken , 'NoKeySpecified ' );
389+ } else {
390+ $ singleUsed = true ;
391+ }
411392
412- $ error = 'Expected 0 spaces between "%s" and comma; %s found ' ;
413- $ data = [
414- $ content ,
415- $ spaceLength ,
416- ];
393+ $ indices [] = ['value ' => $ valueContent ];
394+ }
417395
418- $ fix = $ phpcsFile ->addFixableError ($ error , $ nextToken , 'SpaceBeforeComma ' , $ data );
419- if (true === $ fix ) {
420- $ phpcsFile ->fixer ->replaceToken (($ nextToken - 1 ), '' );
421- }
396+ if (T_COMMA === $ tokens [$ nextToken ]['code ' ]
397+ && T_WHITESPACE === $ tokens [($ nextToken - 1 )]['code ' ]
398+ ) {
399+ $ content = $ tokens [($ nextToken - 2 )]['content ' ];
400+ if ($ tokens [($ nextToken - 1 )]['content ' ] === $ phpcsFile ->eolChar ) {
401+ $ spaceLength = 'newline ' ;
402+ } else {
403+ $ spaceLength = $ tokens [($ nextToken - 1 )]['length ' ];
422404 }
423405
424- $ valueContent = $ phpcsFile ->findNext (
425- Tokens::$ emptyTokens ,
426- ($ lastToken + 1 ),
427- $ nextToken ,
428- true
429- );
406+ $ error = 'Expected 0 spaces between "%s" and comma; %s found ' ;
407+ $ data = [$ content , $ spaceLength ];
430408
431- $ indices [] = ['value ' => $ valueContent ];
432- $ singleUsed = true ;
409+ $ fix = $ phpcsFile ->addFixableError ($ error , $ nextToken , 'SpaceBeforeComma ' , $ data );
410+ if (true === $ fix ) {
411+ $ phpcsFile ->fixer ->replaceToken (($ nextToken - 1 ), '' );
412+ }
433413 }
434414
435415 $ lastToken = $ nextToken ;
@@ -440,12 +420,11 @@ public function processMultiLineArray(File $phpcsFile, $stackPtr, $arrayStart, $
440420 if (true === $ singleUsed ) {
441421 $ error = 'Key specified for array entry; first entry has no key ' ;
442422 $ phpcsFile ->addError ($ error , $ nextToken , 'KeySpecified ' );
443-
444- return ;
423+ } else {
424+ $ keyUsed = true ;
445425 }
446426
447427 $ currentEntry ['arrow ' ] = $ nextToken ;
448- $ keyUsed = true ;
449428
450429 // Find the start of index that uses this double arrow.
451430 $ indexEnd = $ phpcsFile ->findPrevious (T_WHITESPACE , ($ nextToken - 1 ), $ arrayStart , true );
@@ -481,18 +460,7 @@ public function processMultiLineArray(File $phpcsFile, $stackPtr, $arrayStart, $
481460 }
482461 }
483462
484- /*
485- This section checks for arrays that don't specify keys.
486-
487- Arrays such as:
488- array(
489- 'aaa',
490- 'bbb',
491- 'd',
492- );
493- */
494-
495- if (false === $ keyUsed && false === empty ($ indices )) {
463+ if (false === empty ($ indices )) {
496464 $ count = count ($ indices );
497465 $ lastIndex = $ indices [($ count - 1 )]['value ' ];
498466
@@ -514,15 +482,22 @@ public function processMultiLineArray(File $phpcsFile, $stackPtr, $arrayStart, $
514482 $ phpcsFile ->recordMetric ($ stackPtr , 'Array end comma ' , 'yes ' );
515483 }
516484
517- $ lastValueLine = false ;
485+ $ lastValueLine = $ stackPtr ;
518486 foreach ($ indices as $ value ) {
487+ if (false === empty ($ value ['arrow ' ])) {
488+ // Array value with arrow are checked later cause there is more checks.
489+ continue ;
490+ }
491+
519492 if (true === empty ($ value ['value ' ])) {
520- // Array was malformed and we couldn't figure out
521- // the array value correctly, so we have to ignore it.
493+ // Array was malformed, so we have to ignore it.
522494 // Other parts of this sniff will correct the error.
523495 continue ;
524496 }
525497
498+ $ lastValue = $ phpcsFile ->findPrevious (T_COMMA , $ value ['value ' ] - 1 , $ lastValueLine );
499+ $ lastValueLine = $ lastValue ? $ tokens [$ lastValue ]['line ' ] : false ;
500+
526501 if (false !== $ lastValueLine && $ tokens [$ value ['value ' ]]['line ' ] === $ lastValueLine ) {
527502 $ error = 'Each value in a multi-line array must be on a new line ' ;
528503 $ fix = $ phpcsFile ->addFixableError ($ error , $ value ['value ' ], 'ValueNoNewline ' );
@@ -552,8 +527,6 @@ public function processMultiLineArray(File $phpcsFile, $stackPtr, $arrayStart, $
552527 }
553528 }
554529 }
555-
556- $ lastValueLine = $ tokens [$ value ['value ' ]]['line ' ];
557530 }
558531 }
559532
@@ -583,14 +556,12 @@ public function processMultiLineArray(File $phpcsFile, $stackPtr, $arrayStart, $
583556 will also cause an error in the value's alignment. If the arrow were
584557 to be moved back one space however, then both errors would be fixed.
585558 */
586-
587559 $ numValues = count ($ indices );
588560
589561 $ indicesStart = ($ currentIndent + $ this ->indent + 1 );
590562 $ arrowStart = ($ indicesStart + $ maxLength + 1 );
591563 $ valueStart = ($ arrowStart + 3 );
592- $ indexLine = $ tokens [$ stackPtr ]['line ' ];
593- $ lastIndexLine = null ;
564+ $ lastIndexLine = $ tokens [$ stackPtr ]['line ' ];
594565 foreach ($ indices as $ index ) {
595566 if (isset ($ index ['index ' ]) === false ) {
596567 // Array value only.
@@ -605,7 +576,8 @@ public function processMultiLineArray(File $phpcsFile, $stackPtr, $arrayStart, $
605576 continue ;
606577 }
607578
608- $ lastIndexLine = $ indexLine ;
579+ $ lastIndex = $ phpcsFile ->findPrevious (T_COMMA , $ index ['index ' ] - 1 , $ lastIndexLine );
580+ $ lastIndexLine = $ lastIndex ? $ tokens [$ lastIndex ]['line ' ] : false ;
609581 $ indexLine = $ tokens [$ index ['index ' ]]['line ' ];
610582
611583 if ($ indexLine === $ tokens [$ stackPtr ]['line ' ]) {
@@ -652,16 +624,17 @@ public function processMultiLineArray(File $phpcsFile, $stackPtr, $arrayStart, $
652624 }
653625
654626 if ($ tokens [$ index ['arrow ' ]]['column ' ] !== $ arrowStart ) {
655- $ expected = ($ arrowStart - (mb_strlen ($ index ['index_content ' ]) + $ tokens [$ index ['index ' ]]['column ' ]));
627+ $ expected = ($ arrowStart
628+ - (mb_strlen ($ index ['index_content ' ]) + $ tokens [$ index ['index ' ]]['column ' ]));
656629 $ found = $ tokens [$ index ['arrow ' ]]['column ' ]
657630 - (mb_strlen ($ index ['index_content ' ]) + $ tokens [$ index ['index ' ]]['column ' ]);
658631
659632 if ($ found < 0 ) {
660633 $ found = 'newline ' ;
661634 }
662635
663- $ error = 'Array double arrow not aligned correctly; expected %s space(s) but found %s ' ;
664- $ data = [$ expected , $ found ];
636+ $ error = 'Array double arrow not aligned correctly; expected %s space(s) but found %s ' ;
637+ $ data = [$ expected , $ found ];
665638
666639 if ('newline ' !== $ found || false === $ this ->ignoreNewLines ) {
667640 $ fix = $ phpcsFile ->addFixableError ($ error , $ index ['arrow ' ], 'DoubleArrowNotAligned ' , $ data );
@@ -697,10 +670,7 @@ public function processMultiLineArray(File $phpcsFile, $stackPtr, $arrayStart, $
697670
698671 if ('newline ' !== $ found || false === $ this ->ignoreNewLines ) {
699672 $ error = 'Array value not aligned correctly; expected %s space(s) but found %s ' ;
700- $ data = [
701- $ expected ,
702- $ found ,
703- ];
673+ $ data = [$ expected , $ found ];
704674
705675 $ fix = $ phpcsFile ->addFixableError ($ error , $ index ['arrow ' ], 'ValueNotAligned ' , $ data );
706676 if (true === $ fix ) {
@@ -721,78 +691,6 @@ public function processMultiLineArray(File $phpcsFile, $stackPtr, $arrayStart, $
721691 }
722692 }
723693 }
724-
725- // Check each line ends in a comma.
726- $ valueLine = $ tokens [$ index ['value ' ]]['line ' ];
727- $ nextComma = false ;
728- for ($ i = $ index ['value ' ]; $ i < $ arrayEnd ; $ i ++) {
729- // Skip bracketed statements, like function calls.
730- if (T_OPEN_PARENTHESIS === $ tokens [$ i ]['code ' ]) {
731- $ i = $ tokens [$ i ]['parenthesis_closer ' ];
732- $ valueLine = $ tokens [$ i ]['line ' ];
733- continue ;
734- }
735-
736- if (T_ARRAY === $ tokens [$ i ]['code ' ]) {
737- $ i = $ tokens [$ tokens [$ i ]['parenthesis_opener ' ]]['parenthesis_closer ' ];
738- $ valueLine = $ tokens [$ i ]['line ' ];
739- continue ;
740- }
741-
742- // Skip to the end of multi-line strings.
743- if (isset (Tokens::$ stringTokens [$ tokens [$ i ]['code ' ]]) === true ) {
744- $ i = $ phpcsFile ->findNext ($ tokens [$ i ]['code ' ], ($ i + 1 ), null , true );
745- $ i --;
746- $ valueLine = $ tokens [$ i ]['line ' ];
747- continue ;
748- }
749-
750- if (T_OPEN_SHORT_ARRAY === $ tokens [$ i ]['code ' ]) {
751- $ i = $ tokens [$ i ]['bracket_closer ' ];
752- $ valueLine = $ tokens [$ i ]['line ' ];
753- continue ;
754- }
755-
756- if (T_CLOSURE === $ tokens [$ i ]['code ' ]) {
757- $ i = $ tokens [$ i ]['scope_closer ' ];
758- $ valueLine = $ tokens [$ i ]['line ' ];
759- continue ;
760- }
761-
762- if (T_COMMA === $ tokens [$ i ]['code ' ]) {
763- $ nextComma = $ i ;
764- break ;
765- }
766- }
767-
768- if (false === $ nextComma || ($ tokens [$ nextComma ]['line ' ] !== $ valueLine )) {
769- $ error = 'Each line in an array declaration must end in a comma ' ;
770- $ fix = $ phpcsFile ->addFixableError ($ error , $ index ['value ' ], 'NoComma ' );
771-
772- if (true === $ fix ) {
773- // Find the end of the line and put a comma there.
774- for ($ i = ($ index ['value ' ] + 1 ); $ i < $ arrayEnd ; $ i ++) {
775- if ($ tokens [$ i ]['line ' ] > $ valueLine ) {
776- break ;
777- }
778- }
779-
780- $ phpcsFile ->fixer ->addContentBefore (($ i - 1 ), ', ' );
781- }
782- }
783-
784- // Check that there is no space before the comma.
785- if (false !== $ nextComma && T_WHITESPACE === $ tokens [($ nextComma - 1 )]['code ' ]) {
786- $ content = $ tokens [($ nextComma - 2 )]['content ' ];
787- $ spaceLength = $ tokens [($ nextComma - 1 )]['length ' ];
788- $ error = 'Expected 0 spaces between "%s" and comma; %s found ' ;
789- $ data = [$ content , $ spaceLength ];
790-
791- $ fix = $ phpcsFile ->addFixableError ($ error , $ nextComma , 'SpaceBeforeComma ' , $ data );
792- if (true === $ fix ) {
793- $ phpcsFile ->fixer ->replaceToken (($ nextComma - 1 ), '' );
794- }
795- }
796694 }
797695 }
798696}
0 commit comments