PHP_CodeSniffer
[ class tree: PHP_CodeSniffer ] [ index: PHP_CodeSniffer ] [ all elements ]

Source for file ArrayDeclarationSniff.php

Documentation is available at ArrayDeclarationSniff.php

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

Documentation generated on Mon, 11 Mar 2019 15:27:14 -0400 by phpDocumentor 1.4.4. PEAR Logo Copyright © PHP Group 2004.