annotate vendor/squizlabs/php_codesniffer/src/Sniffs/AbstractArraySniff.php @ 19:fa3358dc1485 tip

Add ndrum files
author Chris Cannam
date Wed, 28 Aug 2019 13:14:47 +0100
parents af1871eacc83
children
rev   line source
Chris@17 1 <?php
Chris@17 2 /**
Chris@18 3 * Processes single and multi-line arrays.
Chris@17 4 *
Chris@17 5 * @author Greg Sherwood <gsherwood@squiz.net>
Chris@17 6 * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600)
Chris@17 7 * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
Chris@17 8 */
Chris@17 9
Chris@17 10 namespace PHP_CodeSniffer\Sniffs;
Chris@17 11
Chris@17 12 use PHP_CodeSniffer\Files\File;
Chris@17 13 use PHP_CodeSniffer\Util\Tokens;
Chris@17 14
Chris@17 15 abstract class AbstractArraySniff implements Sniff
Chris@17 16 {
Chris@17 17
Chris@17 18
Chris@17 19 /**
Chris@17 20 * Returns an array of tokens this test wants to listen for.
Chris@17 21 *
Chris@17 22 * @return array
Chris@17 23 */
Chris@17 24 final public function register()
Chris@17 25 {
Chris@17 26 return [
Chris@17 27 T_ARRAY,
Chris@17 28 T_OPEN_SHORT_ARRAY,
Chris@17 29 ];
Chris@17 30
Chris@17 31 }//end register()
Chris@17 32
Chris@17 33
Chris@17 34 /**
Chris@17 35 * Processes this sniff, when one of its tokens is encountered.
Chris@17 36 *
Chris@17 37 * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being checked.
Chris@17 38 * @param int $stackPtr The position of the current token in
Chris@17 39 * the stack passed in $tokens.
Chris@17 40 *
Chris@17 41 * @return void
Chris@17 42 */
Chris@17 43 public function process(File $phpcsFile, $stackPtr)
Chris@17 44 {
Chris@17 45 $tokens = $phpcsFile->getTokens();
Chris@17 46
Chris@17 47 if ($tokens[$stackPtr]['code'] === T_ARRAY) {
Chris@17 48 $phpcsFile->recordMetric($stackPtr, 'Short array syntax used', 'no');
Chris@17 49
Chris@17 50 $arrayStart = $tokens[$stackPtr]['parenthesis_opener'];
Chris@17 51 if (isset($tokens[$arrayStart]['parenthesis_closer']) === false) {
Chris@17 52 // Incomplete array.
Chris@17 53 return;
Chris@17 54 }
Chris@17 55
Chris@17 56 $arrayEnd = $tokens[$arrayStart]['parenthesis_closer'];
Chris@17 57 } else {
Chris@17 58 $phpcsFile->recordMetric($stackPtr, 'Short array syntax used', 'yes');
Chris@17 59 $arrayStart = $stackPtr;
Chris@17 60 $arrayEnd = $tokens[$stackPtr]['bracket_closer'];
Chris@17 61 }
Chris@17 62
Chris@17 63 $lastContent = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($arrayEnd - 1), null, true);
Chris@17 64 if ($tokens[$lastContent]['code'] === T_COMMA) {
Chris@17 65 // Last array item ends with a comma.
Chris@17 66 $phpcsFile->recordMetric($stackPtr, 'Array end comma', 'yes');
Chris@17 67 $lastArrayToken = $lastContent;
Chris@17 68 } else {
Chris@17 69 $phpcsFile->recordMetric($stackPtr, 'Array end comma', 'no');
Chris@17 70 $lastArrayToken = $arrayEnd;
Chris@17 71 }
Chris@17 72
Chris@17 73 if ($tokens[$stackPtr]['code'] === T_ARRAY) {
Chris@17 74 $lastToken = $tokens[$stackPtr]['parenthesis_opener'];
Chris@17 75 } else {
Chris@17 76 $lastToken = $stackPtr;
Chris@17 77 }
Chris@17 78
Chris@17 79 $keyUsed = false;
Chris@17 80 $indices = [];
Chris@17 81
Chris@17 82 for ($checkToken = ($stackPtr + 1); $checkToken <= $lastArrayToken; $checkToken++) {
Chris@17 83 // Skip bracketed statements, like function calls.
Chris@17 84 if ($tokens[$checkToken]['code'] === T_OPEN_PARENTHESIS
Chris@17 85 && (isset($tokens[$checkToken]['parenthesis_owner']) === false
Chris@17 86 || $tokens[$checkToken]['parenthesis_owner'] !== $stackPtr)
Chris@17 87 ) {
Chris@17 88 $checkToken = $tokens[$checkToken]['parenthesis_closer'];
Chris@17 89 continue;
Chris@17 90 }
Chris@17 91
Chris@17 92 if ($tokens[$checkToken]['code'] === T_ARRAY
Chris@17 93 || $tokens[$checkToken]['code'] === T_OPEN_SHORT_ARRAY
Chris@17 94 || $tokens[$checkToken]['code'] === T_CLOSURE
Chris@17 95 ) {
Chris@17 96 // Let subsequent calls of this test handle nested arrays.
Chris@17 97 if ($tokens[$lastToken]['code'] !== T_DOUBLE_ARROW) {
Chris@17 98 $indices[] = ['value_start' => $checkToken];
Chris@17 99 $lastToken = $checkToken;
Chris@17 100 }
Chris@17 101
Chris@17 102 if ($tokens[$checkToken]['code'] === T_ARRAY) {
Chris@17 103 $checkToken = $tokens[$tokens[$checkToken]['parenthesis_opener']]['parenthesis_closer'];
Chris@17 104 } else if ($tokens[$checkToken]['code'] === T_OPEN_SHORT_ARRAY) {
Chris@17 105 $checkToken = $tokens[$checkToken]['bracket_closer'];
Chris@17 106 } else {
Chris@17 107 // T_CLOSURE.
Chris@17 108 $checkToken = $tokens[$checkToken]['scope_closer'];
Chris@17 109 }
Chris@17 110
Chris@17 111 $checkToken = $phpcsFile->findNext(T_WHITESPACE, ($checkToken + 1), null, true);
Chris@17 112 $lastToken = $checkToken;
Chris@17 113 if ($tokens[$checkToken]['code'] !== T_COMMA) {
Chris@17 114 $checkToken--;
Chris@17 115 }
Chris@17 116
Chris@17 117 continue;
Chris@17 118 }//end if
Chris@17 119
Chris@17 120 if ($tokens[$checkToken]['code'] !== T_DOUBLE_ARROW
Chris@17 121 && $tokens[$checkToken]['code'] !== T_COMMA
Chris@17 122 && $checkToken !== $arrayEnd
Chris@17 123 ) {
Chris@17 124 continue;
Chris@17 125 }
Chris@17 126
Chris@17 127 if ($tokens[$checkToken]['code'] === T_COMMA
Chris@17 128 || $checkToken === $arrayEnd
Chris@17 129 ) {
Chris@17 130 $stackPtrCount = 0;
Chris@17 131 if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) {
Chris@17 132 $stackPtrCount = count($tokens[$stackPtr]['nested_parenthesis']);
Chris@17 133 }
Chris@17 134
Chris@17 135 $commaCount = 0;
Chris@17 136 if (isset($tokens[$checkToken]['nested_parenthesis']) === true) {
Chris@17 137 $commaCount = count($tokens[$checkToken]['nested_parenthesis']);
Chris@17 138 if ($tokens[$stackPtr]['code'] === T_ARRAY) {
Chris@17 139 // Remove parenthesis that are used to define the array.
Chris@17 140 $commaCount--;
Chris@17 141 }
Chris@17 142 }
Chris@17 143
Chris@17 144 if ($commaCount > $stackPtrCount) {
Chris@17 145 // This comma is inside more parenthesis than the ARRAY keyword,
Chris@17 146 // so it is actually a comma used to do things like
Chris@17 147 // separate arguments in a function call.
Chris@17 148 continue;
Chris@17 149 }
Chris@17 150
Chris@17 151 if ($keyUsed === false) {
Chris@17 152 $valueContent = $phpcsFile->findNext(
Chris@17 153 Tokens::$emptyTokens,
Chris@17 154 ($lastToken + 1),
Chris@17 155 $checkToken,
Chris@17 156 true
Chris@17 157 );
Chris@17 158
Chris@17 159 $indices[] = ['value_start' => $valueContent];
Chris@17 160 }
Chris@17 161
Chris@17 162 $lastToken = $checkToken;
Chris@17 163 $keyUsed = false;
Chris@17 164 continue;
Chris@17 165 }//end if
Chris@17 166
Chris@17 167 if ($tokens[$checkToken]['code'] === T_DOUBLE_ARROW) {
Chris@17 168 $keyUsed = true;
Chris@17 169
Chris@17 170 // Find the start of index that uses this double arrow.
Chris@17 171 $indexEnd = $phpcsFile->findPrevious(T_WHITESPACE, ($checkToken - 1), $arrayStart, true);
Chris@17 172 $indexStart = $phpcsFile->findStartOfStatement($indexEnd);
Chris@17 173
Chris@17 174 // Find the value of this index.
Chris@17 175 $nextContent = $phpcsFile->findNext(
Chris@17 176 Tokens::$emptyTokens,
Chris@17 177 ($checkToken + 1),
Chris@17 178 $arrayEnd,
Chris@17 179 true
Chris@17 180 );
Chris@17 181
Chris@17 182 $indices[] = [
Chris@17 183 'index_start' => $indexStart,
Chris@17 184 'index_end' => $indexEnd,
Chris@17 185 'arrow' => $checkToken,
Chris@17 186 'value_start' => $nextContent,
Chris@17 187 ];
Chris@17 188
Chris@17 189 $lastToken = $checkToken;
Chris@17 190 }//end if
Chris@17 191 }//end for
Chris@17 192
Chris@17 193 if ($tokens[$arrayStart]['line'] === $tokens[$arrayEnd]['line']) {
Chris@17 194 $this->processSingleLineArray($phpcsFile, $stackPtr, $arrayStart, $arrayEnd, $indices);
Chris@17 195 } else {
Chris@17 196 $this->processMultiLineArray($phpcsFile, $stackPtr, $arrayStart, $arrayEnd, $indices);
Chris@17 197 }
Chris@17 198
Chris@17 199 }//end process()
Chris@17 200
Chris@17 201
Chris@17 202 /**
Chris@17 203 * Processes a single-line array definition.
Chris@17 204 *
Chris@17 205 * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being checked.
Chris@17 206 * @param int $stackPtr The position of the current token
Chris@17 207 * in the stack passed in $tokens.
Chris@17 208 * @param int $arrayStart The token that starts the array definition.
Chris@17 209 * @param int $arrayEnd The token that ends the array definition.
Chris@17 210 * @param array $indices An array of token positions for the array keys,
Chris@17 211 * double arrows, and values.
Chris@17 212 *
Chris@17 213 * @return void
Chris@17 214 */
Chris@17 215 abstract protected function processSingleLineArray($phpcsFile, $stackPtr, $arrayStart, $arrayEnd, $indices);
Chris@17 216
Chris@17 217
Chris@17 218 /**
Chris@17 219 * Processes a multi-line array definition.
Chris@17 220 *
Chris@17 221 * @param \PHP_CodeSniffer\Files\File $phpcsFile The current file being checked.
Chris@17 222 * @param int $stackPtr The position of the current token
Chris@17 223 * in the stack passed in $tokens.
Chris@17 224 * @param int $arrayStart The token that starts the array definition.
Chris@17 225 * @param int $arrayEnd The token that ends the array definition.
Chris@17 226 * @param array $indices An array of token positions for the array keys,
Chris@17 227 * double arrows, and values.
Chris@17 228 *
Chris@17 229 * @return void
Chris@17 230 */
Chris@17 231 abstract protected function processMultiLineArray($phpcsFile, $stackPtr, $arrayStart, $arrayEnd, $indices);
Chris@17 232
Chris@17 233
Chris@17 234 }//end class