Skip to content

Commit e7b0cce

Browse files
committed
Generic.ControlStructures.DisallowYodaConditions now returns less false positives (ref #2653)
It now ignores empty parenthesis, and considers array definitions containing only variables to not be static.
1 parent f2b6798 commit e7b0cce

File tree

4 files changed

+112
-6
lines changed

4 files changed

+112
-6
lines changed

package.xml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ http://pear.php.net/dtd/package-2.0.xsd">
2626
</stability>
2727
<license uri="https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt">BSD 3-Clause License</license>
2828
<notes>
29+
- Generic.ControlStructures.DisallowYodaConditions now returns less false positives
30+
-- False positives were being returned for array comparisions, or when performing some function calls
2931
- Squiz.WhiteSpace.SemicolonSpacing.Incorrect error message now escapes newlines and tabs
3032
-- Provides a clearer error message as whitespace is now visible
3133
-- Also allows for better output for report types such as CSV and XML

src/Standards/Generic/Sniffs/ControlStructures/DisallowYodaConditionsSniff.php

Lines changed: 72 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,9 @@ public function process(File $phpcsFile, $stackPtr)
6262

6363
if ($tokens[$previousIndex]['code'] === T_CLOSE_SHORT_ARRAY) {
6464
$previousIndex = $tokens[$previousIndex]['bracket_opener'];
65+
if ($this->isArrayStatic($phpcsFile, $previousIndex) === false) {
66+
return;
67+
}
6568
}
6669

6770
$prevIndex = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($previousIndex - 1), null, true);
@@ -99,11 +102,22 @@ public function process(File $phpcsFile, $stackPtr)
99102
$tokens[$previousIndex]['parenthesis_opener']
100103
);
101104

102-
// If a variable exists it is not Yoda.
105+
// If a variable exists, it is not Yoda.
103106
if ($found !== false) {
104107
return;
105108
}
106-
}
109+
110+
// If there is nothing inside the parenthesis, it it not a Yoda.
111+
$opener = $tokens[$previousIndex]['parenthesis_opener'];
112+
$prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($previousIndex - 1), ($opener + 1), true);
113+
if ($prev === false) {
114+
return;
115+
}
116+
} else if ($tokens[$closeParenthesisIndex]['code'] === T_ARRAY
117+
&& $this->isArrayStatic($phpcsFile, $closeParenthesisIndex) === false
118+
) {
119+
return;
120+
}//end if
107121
}//end if
108122

109123
$phpcsFile->addError(
@@ -115,4 +129,60 @@ public function process(File $phpcsFile, $stackPtr)
115129
}//end process()
116130

117131

132+
/**
133+
* Determines if an array is a static definition.
134+
*
135+
* @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned.
136+
* @param int $arrayToken The position of the array token.
137+
*
138+
* @return bool
139+
*/
140+
public function isArrayStatic(File $phpcsFile, $arrayToken)
141+
{
142+
$tokens = $phpcsFile->getTokens();
143+
144+
$arrayEnd = null;
145+
if ($tokens[$arrayToken]['code'] === T_OPEN_SHORT_ARRAY) {
146+
$start = $arrayToken;
147+
$end = $tokens[$arrayToken]['bracket_closer'];
148+
} else if ($tokens[$arrayToken]['code'] === T_ARRAY) {
149+
$start = $tokens[$arrayToken]['parenthesis_opener'];
150+
$end = $tokens[$arrayToken]['parenthesis_closer'];
151+
} else {
152+
return true;
153+
}
154+
155+
$staticTokens = Tokens::$emptyTokens;
156+
$staticTokens += Tokens::$textStringTokens;
157+
$staticTokens += Tokens::$assignmentTokens;
158+
$staticTokens += Tokens::$equalityTokens;
159+
$staticTokens += Tokens::$comparisonTokens;
160+
$staticTokens += Tokens::$arithmeticTokens;
161+
$staticTokens += Tokens::$operators;
162+
$staticTokens += Tokens::$booleanOperators;
163+
$staticTokens += Tokens::$castTokens;
164+
$staticTokens += Tokens::$bracketTokens;
165+
$staticTokens += [
166+
T_DOUBLE_ARROW => T_DOUBLE_ARROW,
167+
T_COMMA => T_COMMA,
168+
T_TRUE => T_TRUE,
169+
T_FALSE => T_FALSE,
170+
];
171+
172+
for ($i = ($start + 1); $i < $end; $i++) {
173+
if (isset($tokens[$i]['scope_closer']) === true) {
174+
$i = $tokens[$i]['scope_closer'];
175+
continue;
176+
}
177+
178+
if (isset($staticTokens[$tokens[$i]['code']]) === false) {
179+
return false;
180+
}
181+
}
182+
183+
return true;
184+
185+
}//end isArrayStatic()
186+
187+
118188
}//end class

src/Standards/Generic/Tests/ControlStructures/DisallowYodaConditionsUnitTest.inc

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,3 +132,35 @@ if ((int) 5 > $var) {}
132132
if ((int) $var > (int) 5) {}
133133
if (true == function() { return false;}){}
134134
if (function() { return false;} == true){}
135+
136+
if (is_array($val)
137+
&& array($foo) === array($bar)
138+
&& [$foo] === [$bar]
139+
&& array('foo', 'bar') === array($foo, $bar)
140+
&& ['foo', 'bar'] === [$foo, $bar]
141+
&& array('foo' => true, 'bar' => false) === array(getContents())
142+
&& ['foo' => true, 'bar' => false] === array(getContents())
143+
&& array(getContents()) === ['foo' => true, 'bar' => false]
144+
) {
145+
}
146+
147+
if ($this->cfg['some_closure']() == 2) {
148+
}
149+
150+
if (is_array($val)
151+
&& array(get_class($val[0]), $val[1]) == array('someNamespace\\className', 'method')
152+
) {
153+
}
154+
155+
if (is_array($val)
156+
&& array('someNamespace\\className', 'method') == array(get_class($val[0]), $val[1])
157+
) {
158+
}
159+
160+
if ([function() { echo 'hi'; }] === [$foo]
161+
&& [$foo] === [function() { echo 'hi'; }]
162+
&& [function() { echo 'hi'; }, $bar] === [$foo]
163+
&& [$foo] === [function() { echo 'hi'; }, $bar]
164+
) {
165+
}
166+

src/Standards/Generic/Tests/ControlStructures/DisallowYodaConditionsUnitTest.php

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -48,15 +48,17 @@ public function getErrorList()
4848
97 => 3,
4949
98 => 3,
5050
105 => 1,
51-
119 => 1,
52-
120 => 1,
53-
122 => 1,
54-
123 => 1,
5551
128 => 1,
5652
129 => 2,
5753
130 => 1,
5854
131 => 1,
5955
133 => 1,
56+
139 => 1,
57+
140 => 1,
58+
141 => 1,
59+
142 => 1,
60+
156 => 1,
61+
160 => 1,
6062
];
6163

6264
}//end getErrorList()

0 commit comments

Comments
 (0)