Skip to content

Commit 1ef22b8

Browse files
committed
Merge branch 'hotfix/array-indices' of https://github.com/michalbundyra/PHP_CodeSniffer
2 parents 6a3b033 + 45f70b2 commit 1ef22b8

File tree

4 files changed

+59
-123
lines changed

4 files changed

+59
-123
lines changed

src/Sniffs/AbstractArraySniff.php

Lines changed: 51 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -64,139 +64,33 @@ public function process(File $phpcsFile, $stackPtr)
6464
if ($tokens[$lastContent]['code'] === T_COMMA) {
6565
// Last array item ends with a comma.
6666
$phpcsFile->recordMetric($stackPtr, 'Array end comma', 'yes');
67-
$lastArrayToken = $lastContent;
6867
} else {
6968
$phpcsFile->recordMetric($stackPtr, 'Array end comma', 'no');
70-
$lastArrayToken = $arrayEnd;
7169
}
7270

73-
if ($tokens[$stackPtr]['code'] === T_ARRAY) {
74-
$lastToken = $tokens[$stackPtr]['parenthesis_opener'];
75-
} else {
76-
$lastToken = $stackPtr;
77-
}
78-
79-
$keyUsed = false;
8071
$indices = [];
8172

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-
}
73+
$current = $arrayStart;
74+
while (($next = $phpcsFile->findNext(Tokens::$emptyTokens, ($current + 1), $arrayEnd, true)) !== false) {
75+
$end = $this->getNext($phpcsFile, $next, $arrayEnd);
9176

92-
if ($tokens[$checkToken]['code'] === T_INLINE_THEN
93-
|| $tokens[$checkToken]['code'] === T_COALESCE
94-
) {
95-
$checkToken = $phpcsFile->findEndOfStatement($checkToken);
96-
continue;
97-
}
98-
99-
if ($tokens[$checkToken]['code'] === T_ARRAY
100-
|| $tokens[$checkToken]['code'] === T_OPEN_SHORT_ARRAY
101-
|| $tokens[$checkToken]['code'] === T_CLOSURE
102-
|| $tokens[$checkToken]['code'] === T_FN
103-
) {
104-
// Let subsequent calls of this test handle nested arrays.
105-
if ($tokens[$lastToken]['code'] !== T_DOUBLE_ARROW) {
106-
$indices[] = ['value_start' => $checkToken];
107-
$lastToken = $checkToken;
108-
}
109-
110-
if ($tokens[$checkToken]['code'] === T_ARRAY) {
111-
$checkToken = $tokens[$tokens[$checkToken]['parenthesis_opener']]['parenthesis_closer'];
112-
} else if ($tokens[$checkToken]['code'] === T_OPEN_SHORT_ARRAY) {
113-
$checkToken = $tokens[$checkToken]['bracket_closer'];
114-
} else {
115-
// T_CLOSURE.
116-
$checkToken = $tokens[$checkToken]['scope_closer'];
117-
}
118-
119-
$checkToken = $phpcsFile->findNext(T_WHITESPACE, ($checkToken + 1), null, true);
120-
$lastToken = $checkToken;
121-
if ($tokens[$checkToken]['code'] !== T_COMMA) {
122-
$checkToken--;
123-
}
124-
125-
continue;
126-
}//end if
127-
128-
if ($tokens[$checkToken]['code'] !== T_DOUBLE_ARROW
129-
&& $tokens[$checkToken]['code'] !== T_COMMA
130-
&& $checkToken !== $arrayEnd
131-
) {
132-
continue;
133-
}
134-
135-
if ($tokens[$checkToken]['code'] === T_COMMA
136-
|| $checkToken === $arrayEnd
137-
) {
138-
$stackPtrCount = 0;
139-
if (isset($tokens[$stackPtr]['nested_parenthesis']) === true) {
140-
$stackPtrCount = count($tokens[$stackPtr]['nested_parenthesis']);
141-
}
142-
143-
$commaCount = 0;
144-
if (isset($tokens[$checkToken]['nested_parenthesis']) === true) {
145-
$commaCount = count($tokens[$checkToken]['nested_parenthesis']);
146-
if ($tokens[$stackPtr]['code'] === T_ARRAY) {
147-
// Remove parenthesis that are used to define the array.
148-
$commaCount--;
149-
}
150-
}
151-
152-
if ($commaCount > $stackPtrCount) {
153-
// This comma is inside more parenthesis than the ARRAY keyword,
154-
// so it is actually a comma used to do things like
155-
// separate arguments in a function call.
156-
continue;
157-
}
158-
159-
if ($keyUsed === false) {
160-
$valueContent = $phpcsFile->findNext(
161-
Tokens::$emptyTokens,
162-
($lastToken + 1),
163-
$checkToken,
164-
true
165-
);
166-
167-
$indices[] = ['value_start' => $valueContent];
168-
}
169-
170-
$lastToken = $checkToken;
171-
$keyUsed = false;
172-
continue;
173-
}//end if
174-
175-
if ($tokens[$checkToken]['code'] === T_DOUBLE_ARROW) {
176-
$keyUsed = true;
177-
178-
// Find the start of index that uses this double arrow.
179-
$indexEnd = $phpcsFile->findPrevious(T_WHITESPACE, ($checkToken - 1), $arrayStart, true);
180-
$indexStart = $phpcsFile->findStartOfStatement($indexEnd);
181-
182-
// Find the value of this index.
183-
$nextContent = $phpcsFile->findNext(
184-
Tokens::$emptyTokens,
185-
($checkToken + 1),
186-
$arrayEnd,
187-
true
188-
);
77+
if ($tokens[$end]['code'] === T_DOUBLE_ARROW) {
78+
$indexEnd = $phpcsFile->findPrevious(T_WHITESPACE, ($end - 1), null, true);
79+
$valueStart = $phpcsFile->findNext(Tokens::$emptyTokens, ($end + 1), null, true);
18980

19081
$indices[] = [
191-
'index_start' => $indexStart,
82+
'index_start' => $next,
19283
'index_end' => $indexEnd,
193-
'arrow' => $checkToken,
194-
'value_start' => $nextContent,
84+
'arrow' => $end,
85+
'value_start' => $valueStart,
19586
];
87+
} else {
88+
$valueStart = $next;
89+
$indices[] = ['value_start' => $valueStart];
90+
}
19691

197-
$lastToken = $checkToken;
198-
}//end if
199-
}//end for
92+
$current = $this->getNext($phpcsFile, $valueStart, $arrayEnd);
93+
}
20094

20195
if ($tokens[$arrayStart]['line'] === $tokens[$arrayEnd]['line']) {
20296
$this->processSingleLineArray($phpcsFile, $stackPtr, $arrayStart, $arrayEnd, $indices);
@@ -207,6 +101,42 @@ public function process(File $phpcsFile, $stackPtr)
207101
}//end process()
208102

209103

104+
/**
105+
* Find next separator in array - either: comma or double arrow.
106+
*
107+
* @param File $phpcsFile The current file being checked.
108+
* @param int $ptr The position of current token.
109+
* @param int $arrayEnd The token that ends the array definition.
110+
*
111+
* @return int
112+
*/
113+
private function getNext(File $phpcsFile, $ptr, $arrayEnd)
114+
{
115+
$tokens = $phpcsFile->getTokens();
116+
117+
while ($ptr < $arrayEnd) {
118+
if (isset($tokens[$ptr]['scope_closer']) === true) {
119+
$ptr = $tokens[$ptr]['scope_closer'];
120+
} else if (isset($tokens[$ptr]['parenthesis_closer']) === true) {
121+
$ptr = $tokens[$ptr]['parenthesis_closer'];
122+
} else if (isset($tokens[$ptr]['bracket_closer']) === true) {
123+
$ptr = $tokens[$ptr]['bracket_closer'];
124+
}
125+
126+
if ($tokens[$ptr]['code'] === T_COMMA
127+
|| $tokens[$ptr]['code'] === T_DOUBLE_ARROW
128+
) {
129+
return $ptr;
130+
}
131+
132+
++$ptr;
133+
}
134+
135+
return $ptr;
136+
137+
}//end getNext()
138+
139+
210140
/**
211141
* Processes a single-line array definition.
212142
*

src/Standards/Generic/Tests/Arrays/ArrayIndentUnitTest.inc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ $array = [
5959
['two'],
6060
'fn' =>
6161
fn ($x) => yield 'k' => $x,
62+
$a ?? $b,
63+
$c ? $d : $e,
6264
];
6365

6466
// phpcs:set Generic.Arrays.ArrayIndent indent 2

src/Standards/Generic/Tests/Arrays/ArrayIndentUnitTest.inc.fixed

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,8 @@ $array = [
6060
['two'],
6161
'fn' =>
6262
fn ($x) => yield 'k' => $x,
63+
$a ?? $b,
64+
$c ? $d : $e,
6365
];
6466

6567
// phpcs:set Generic.Arrays.ArrayIndent indent 2

src/Standards/Generic/Tests/Arrays/ArrayIndentUnitTest.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,12 @@ public function getErrorList()
3333
31 => 1,
3434
33 => 1,
3535
41 => 1,
36-
67 => 1,
37-
68 => 1,
36+
62 => 1,
37+
63 => 1,
3838
69 => 1,
3939
70 => 1,
40+
71 => 1,
41+
72 => 1,
4042
];
4143

4244
}//end getErrorList()

0 commit comments

Comments
 (0)