comparison vendor/squizlabs/php_codesniffer/src/Sniffs/AbstractArraySniff.php @ 17:129ea1e6d783

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