Skip to content

Commit 700d107

Browse files
committed
Fixed YodaComparisonSniff for comparisons in arrays
1 parent 8e586ab commit 700d107

File tree

6 files changed

+105
-7
lines changed

6 files changed

+105
-7
lines changed

SlevomatCodingStandard/Sniffs/ControlStructures/YodaComparisonSniff.php

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,8 @@ public function process(\PHP_CodeSniffer_File $phpcsFile, $comparisonTokenPointe
101101
$tokens = $phpcsFile->getTokens();
102102
$leftSideTokens = $this->getLeftSideTokens($tokens, $comparisonTokenPointer);
103103
$rightSideTokens = $this->getRightSideTokens($tokens, $comparisonTokenPointer);
104-
$leftDynamism = $this->getDynamismForTokens($leftSideTokens);
105-
$rightDynamism = $this->getDynamismForTokens($rightSideTokens);
104+
$leftDynamism = $this->getDynamismForTokens($tokens, $leftSideTokens);
105+
$rightDynamism = $this->getDynamismForTokens($tokens, $rightSideTokens);
106106

107107
if ($leftDynamism === null || $rightDynamism === null) {
108108
return;
@@ -151,6 +151,7 @@ private function write(\PHP_CodeSniffer_File $phpcsFile, array $leftSideTokens,
151151
private function getLeftSideTokens(array $tokens, int $comparisonTokenPointer): array
152152
{
153153
$parenthesisDepth = 0;
154+
$shortArrayDepth = 0;
154155
$examinedTokenPointer = $comparisonTokenPointer;
155156
$sideTokens = [];
156157
$stopTokenCodes = $this->getStopTokenCodes();
@@ -161,6 +162,16 @@ private function getLeftSideTokens(array $tokens, int $comparisonTokenPointer):
161162
break;
162163
}
163164

165+
if ($examinedToken['code'] === T_CLOSE_SHORT_ARRAY) {
166+
$shortArrayDepth++;
167+
} elseif ($examinedToken['code'] === T_OPEN_SHORT_ARRAY) {
168+
if ($shortArrayDepth === 0) {
169+
break;
170+
}
171+
172+
$shortArrayDepth--;
173+
}
174+
164175
if ($examinedToken['code'] === T_CLOSE_PARENTHESIS) {
165176
$parenthesisDepth++;
166177
} elseif ($examinedToken['code'] === T_OPEN_PARENTHESIS) {
@@ -185,6 +196,7 @@ private function getLeftSideTokens(array $tokens, int $comparisonTokenPointer):
185196
private function getRightSideTokens(array $tokens, int $comparisonTokenPointer): array
186197
{
187198
$parenthesisDepth = 0;
199+
$shortArrayDepth = 0;
188200
$examinedTokenPointer = $comparisonTokenPointer;
189201
$sideTokens = [];
190202
$stopTokenCodes = $this->getStopTokenCodes();
@@ -195,6 +207,16 @@ private function getRightSideTokens(array $tokens, int $comparisonTokenPointer):
195207
break;
196208
}
197209

210+
if ($examinedToken['code'] === T_OPEN_SHORT_ARRAY) {
211+
$shortArrayDepth++;
212+
} elseif ($examinedToken['code'] === T_CLOSE_SHORT_ARRAY) {
213+
if ($shortArrayDepth === 0) {
214+
break;
215+
}
216+
217+
$shortArrayDepth--;
218+
}
219+
198220
if ($examinedToken['code'] === T_OPEN_PARENTHESIS) {
199221
$parenthesisDepth++;
200222
} elseif ($examinedToken['code'] === T_CLOSE_PARENTHESIS) {
@@ -212,24 +234,32 @@ private function getRightSideTokens(array $tokens, int $comparisonTokenPointer):
212234
}
213235

214236
/**
237+
* @param mixed[] $tokens
215238
* @param mixed[] $sideTokens
216239
* @return int|null
217240
*/
218-
private function getDynamismForTokens(array $sideTokens)
241+
private function getDynamismForTokens(array $tokens, array $sideTokens)
219242
{
220243
$sideTokens = array_values(array_filter($sideTokens, function (array $token): bool {
221244
return !in_array($token['code'], [T_WHITESPACE, T_COMMENT, T_DOC_COMMENT, T_NS_SEPARATOR, T_PLUS, T_MINUS, T_INT_CAST, T_DOUBLE_CAST, T_STRING_CAST, T_ARRAY_CAST, T_OBJECT_CAST, T_BOOL_CAST, T_UNSET_CAST], true);
222245
}));
223246

224247
$sideTokensCount = count($sideTokens);
225248

249+
$dynamism = $this->getTokenDynamism();
250+
226251
if ($sideTokensCount > 0) {
227252
if ($sideTokens[0]['code'] === T_VARIABLE) {
228253
// expression starts with a variable - wins over everything else
229254
return self::DYNAMISM_VARIABLE;
230255
} elseif ($sideTokens[$sideTokensCount - 1]['code'] === T_CLOSE_PARENTHESIS) {
231-
// function or method call
232-
return self::DYNAMISM_FUNCTION_CALL;
256+
if (isset($sideTokens[$sideTokensCount - 1]['parenthesis_owner']) && $tokens[$sideTokens[$sideTokensCount - 1]['parenthesis_owner']]['code'] === T_ARRAY) {
257+
// array()
258+
return $dynamism[T_ARRAY];
259+
} else {
260+
// function or method call
261+
return self::DYNAMISM_FUNCTION_CALL;
262+
}
233263
} elseif ($sideTokensCount === 1 && $sideTokens[0]['code'] === T_STRING) {
234264
// constant
235265
return self::DYNAMISM_CONSTANT;
@@ -246,7 +276,6 @@ private function getDynamismForTokens(array $sideTokens)
246276
}
247277
}
248278

249-
$dynamism = $this->getTokenDynamism();
250279
if (isset($sideTokens[0]) && isset($dynamism[$sideTokens[0]['code']])) {
251280
return $dynamism[$sideTokens[0]['code']];
252281
}

tests/Sniffs/ControlStructures/YodaComparisonSniffTest.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public function testCorrectFile()
1717
public function dataIncorrectFile(): array
1818
{
1919
$lineNumbers = [];
20-
foreach (range(3, 24) as $lineNumber) {
20+
foreach (range(3, 33) as $lineNumber) {
2121
$lineNumbers[$lineNumber] = [$lineNumber];
2222
}
2323

tests/Sniffs/ControlStructures/data/allYodaComparisons.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
false === $foo;
66
null === $foo;
77
[] === $foo;
8+
array() === $foo;
89
123 === BAR;
910
123 === Foo::BAR;
1011
123.0 === Foo::BAR;
@@ -20,5 +21,13 @@
2021
['test'] === Foo::BAR
2122
)) ? 123.0 === Foo::BAR
2223
: null === $foo;
24+
(BAR === foo() || (
25+
array('test') === Foo::BAR
26+
)) ? 123.0 === Foo::BAR
27+
: null === $foo;
2328
(int) FOO === $bar;
2429
FOO === (int) $bar;
30+
[self::ADMIN_EMAIL === $username ? self::ROLE_ADMIN : self::ROLE_CUSTOMER];
31+
array(self::ADMIN_EMAIL === $username ? self::ROLE_ADMIN : self::ROLE_CUSTOMER);
32+
[[] === $array];
33+
[array() === $array];

tests/Sniffs/ControlStructures/data/fixableYodaComparisons.fixed.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
$foo === false;
66
$foo === null;
77
$foo === [];
8+
$foo === array();
89
BAR === 123;
910
Foo::BAR === 123;
1011
Foo::BAR === 123.0;
@@ -18,6 +19,8 @@
1819
$foo === +1;
1920
(foo() === BAR|| (
2021
Foo::BAR === ['test'])) ? Foo::BAR === 123.0: $foo === null;
22+
(foo() === BAR|| (
23+
Foo::BAR === array('test'))) ? Foo::BAR === 123.0: $foo === null;
2124

2225
if (
2326
$foo($bar) === [Foo::BAR, Foo::BAZ] && (
@@ -26,6 +29,14 @@
2629
)
2730
) {
2831
}
32+
if (
33+
$foo($bar) === array(Foo::BAR, Foo::BAZ) && (
34+
$bar === true ||
35+
$bar === null
36+
)
37+
) {
38+
}
39+
2940
$x = $a ?? $b === 123;
3041

3142
switch ($c) {
@@ -35,3 +46,13 @@
3546

3647
$$a === $x;
3748
(int) $bar === FOO;
49+
50+
$x = [$username === self::ADMIN_EMAIL ? self::ROLE_ADMIN : self::ROLE_CUSTOMER];
51+
$x = [$username === self::ADMIN_EMAIL? self::ROLE_ADMIN : self::ROLE_CUSTOMER];
52+
$x = array($username === self::ADMIN_EMAIL ? self::ROLE_ADMIN : self::ROLE_CUSTOMER);
53+
$x = array($username === self::ADMIN_EMAIL? self::ROLE_ADMIN : self::ROLE_CUSTOMER);
54+
55+
$x = array($username === array()? true : false);
56+
$x = array($username === []? true : false);
57+
$x = [$username === array()? true : false];
58+
$x = [$username === []? true : false];

tests/Sniffs/ControlStructures/data/fixableYodaComparisons.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
false === $foo;
66
null === $foo;
77
[] === $foo;
8+
array() === $foo;
89
123 === BAR;
910
123 === Foo::BAR;
1011
123.0 === Foo::BAR;
@@ -20,6 +21,10 @@
2021
['test'] === Foo::BAR
2122
)) ? 123.0 === Foo::BAR
2223
: null === $foo;
24+
(BAR === foo() || (
25+
array('test') === Foo::BAR
26+
)) ? 123.0 === Foo::BAR
27+
: null === $foo;
2328

2429
if (
2530
$foo($bar) === [Foo::BAR, Foo::BAZ] && (
@@ -28,6 +33,14 @@
2833
)
2934
) {
3035
}
36+
if (
37+
$foo($bar) === array(Foo::BAR, Foo::BAZ) && (
38+
$bar === true ||
39+
$bar === null
40+
)
41+
) {
42+
}
43+
3144
$x = $a ?? 123 === $b;
3245

3346
switch ($c) {
@@ -37,3 +50,13 @@
3750

3851
$$a === $x;
3952
FOO === (int) $bar;
53+
54+
$x = [$username === self::ADMIN_EMAIL ? self::ROLE_ADMIN : self::ROLE_CUSTOMER];
55+
$x = [self::ADMIN_EMAIL === $username ? self::ROLE_ADMIN : self::ROLE_CUSTOMER];
56+
$x = array($username === self::ADMIN_EMAIL ? self::ROLE_ADMIN : self::ROLE_CUSTOMER);
57+
$x = array(self::ADMIN_EMAIL === $username ? self::ROLE_ADMIN : self::ROLE_CUSTOMER);
58+
59+
$x = array(array() === $username ? true : false);
60+
$x = array([] === $username ? true : false);
61+
$x = [array() === $username ? true : false];
62+
$x = [[] === $username ? true : false];

tests/Sniffs/ControlStructures/data/noYodaComparisons.php

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,9 @@
99
$foo === $this->foo();
1010
$this->foo() === $foo;
1111
[123] === [123];
12+
array(123) === array(123);
13+
[123] === array(123);
14+
array(123) === [123];
1215
BAR === 123;
1316
Foo::BAR === 123;
1417
Foo::BAR === 123.0;
@@ -31,6 +34,14 @@
3134
) {
3235
}
3336

37+
if (
38+
$foo($bar) === array(Foo::BAR, Foo::BAZ) && (
39+
$bar === true ||
40+
$bar === null
41+
)
42+
) {
43+
}
44+
3445
(int) $foo === $bar;
3546
$foo === (int) $bar;
3647
Foo::$bar === $foo;
@@ -51,3 +62,8 @@
5162
default:
5263
$timezone = 'UTC';
5364
}
65+
66+
[$username === self::ADMIN_EMAIL ? self::ROLE_ADMIN : self::ROLE_CUSTOMER];
67+
array($username === self::ADMIN_EMAIL ? self::ROLE_ADMIN : self::ROLE_CUSTOMER);
68+
[$array === []];
69+
[$array === array()];

0 commit comments

Comments
 (0)