<?php
/**
* Processes single and multi-line arrays.
*
* @author Greg Sherwood <gsherwood@squiz.net>
* @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600)
* @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
*/
namespace PHP_CodeSniffer\Sniffs;
use PHP_CodeSniffer\Files\File;
use PHP_CodeSniffer\Util\Tokens;
abstract class AbstractArraySniff implements Sniff
{
/**
* Returns an array of tokens this test wants to listen for.
*
* @return array
*/
final public function register()
{
return [
T_ARRAY,
T_OPEN_SHORT_ARRAY,
];
}//end register()
/**
* Processes this sniff, when one of its tokens is encountered.
*
* @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being checked.
* @param int $stackPtr The position of the current token in
* the stack passed in $tokens.
*
* @return void
*/
public function process(File $phpcsFile, $stackPtr)
{
$tokens = $phpcsFile->getTokens();
if ($tokens[$stackPtr]['code'] === T_ARRAY) {
$phpcsFile->recordMetric($stackPtr, 'Short array syntax used', 'no');
$arrayStart = $tokens[$stackPtr]['parenthesis_opener'];
if (isset($tokens[$arrayStart]['parenthesis_closer']) === false) {
// Incomplete array.
return;
}
$arrayEnd = $tokens[$arrayStart]['parenthesis_closer'];
} else {
$phpcsFile->recordMetric($stackPtr, 'Short array syntax used', 'yes');
$arrayStart = $stackPtr;
$arrayEnd = $tokens[$stackPtr]['bracket_closer'];
}
$lastContent = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($arrayEnd - 1), null, true);
if ($tokens[$lastContent]['code'] === T_COMMA) {
// Last array item ends with a comma.
$phpcsFile->recordMetric($stackPtr, 'Array end comma', 'yes');
} else {
$phpcsFile->recordMetric($stackPtr, 'Array end comma', 'no');
}
$indices = [];
$current = $arrayStart;
while (($next = $phpcsFile->findNext(Tokens::$emptyTokens, ($current + 1), $arrayEnd, true)) !== false) {
$end = $this->getNext($phpcsFile, $next, $arrayEnd);
if ($tokens[$end]['code'] === T_DOUBLE_ARROW) {
$indexEnd = $phpcsFile->findPrevious(T_WHITESPACE, ($end - 1), null, true);
$valueStart = $phpcsFile->findNext(Tokens::$emptyTokens, ($end + 1), null, true);
$indices[] = [
'index_start' => $next,
'index_end' => $indexEnd,
'arrow' => $end,
'value_start' => $valueStart,
];
} else {
$valueStart = $next;
$indices[] = ['value_start' => $valueStart];
}
$current = $this->getNext($phpcsFile, $valueStart, $arrayEnd);
}
if ($tokens[$arrayStart]['line'] === $tokens[$arrayEnd]['line']) {
$this->processSingleLineArray($phpcsFile, $stackPtr, $arrayStart, $arrayEnd, $indices);
} else {
$this->processMultiLineArray($phpcsFile, $stackPtr, $arrayStart, $arrayEnd, $indices);
}
}//end process()
/**
* Find next separator in array - either: comma or double arrow.
*
* @param File $phpcsFile The current file being checked.
* @param int $ptr The position of current token.
* @param int $arrayEnd The token that ends the array definition.
*
* @return int
*/
private function getNext(File $phpcsFile, $ptr, $arrayEnd)
{
$tokens = $phpcsFile->getTokens();
while ($ptr < $arrayEnd) {
if (isset($tokens[$ptr]['scope_closer']) === true) {
$ptr = $tokens[$ptr]['scope_closer'];
} else if (isset($tokens[$ptr]['parenthesis_closer']) === true) {
$ptr = $tokens[$ptr]['parenthesis_closer'];
} else if (isset($tokens[$ptr]['bracket_closer']) === true) {
$ptr = $tokens[$ptr]['bracket_closer'];
}
if ($tokens[$ptr]['code'] === T_COMMA
|| $tokens[$ptr]['code'] === T_DOUBLE_ARROW
) {
return $ptr;
}
++$ptr;
}
return $ptr;
}//end getNext()
/**
* Processes a single-line array definition.
*
* @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being checked.
* @param int $stackPtr The position of the current token
* in the stack passed in $tokens.
* @param int $arrayStart The token that starts the array definition.
* @param int $arrayEnd The token that ends the array definition.
* @param array $indices An array of token positions for the array keys,
* double arrows, and values.
*
* @return void
*/
abstract protected function processSingleLineArray($phpcsFile, $stackPtr, $arrayStart, $arrayEnd, $indices);
/**
* Processes a multi-line array definition.
*
* @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being checked.
* @param int $stackPtr The position of the current token
* in the stack passed in $tokens.
* @param int $arrayStart The token that starts the array definition.
* @param int $arrayEnd The token that ends the array definition.
* @param array $indices An array of token positions for the array keys,
* double arrows, and values.
*
* @return void
*/
abstract protected function processMultiLineArray($phpcsFile, $stackPtr, $arrayStart, $arrayEnd, $indices);
}//end class