Skip to content

Commit 3643b52

Browse files
committed
Added custom AssignmentInsideConditionSniff
1 parent 7dd4af8 commit 3643b52

File tree

2 files changed

+203
-0
lines changed

2 files changed

+203
-0
lines changed
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
<?php declare(strict_types=1); # -*- coding: utf-8 -*-
2+
/*
3+
* This file is part of the php-coding-standards package.
4+
*
5+
* (c) Inpsyde GmbH
6+
*
7+
* For the full copyright and license information, please view the LICENSE
8+
* file that was distributed with this source code.
9+
*/
10+
11+
namespace Inpsyde\InpsydeCodingStandard\Sniffs\CodeQuality;
12+
13+
use Inpsyde\InpsydeCodingStandard\Helpers;
14+
use PHP_CodeSniffer\Files\File;
15+
use PHP_CodeSniffer\Sniffs\Sniff;
16+
use PHP_CodeSniffer\Util\Tokens;
17+
18+
/**
19+
* @package php-coding-standards
20+
* @license http://opensource.org/licenses/MIT MIT
21+
*/
22+
final class AssignmentInsideConditionSniff implements Sniff
23+
{
24+
/**
25+
* @return int[]
26+
*/
27+
public function register()
28+
{
29+
return [T_IF, T_ELSEIF];
30+
}
31+
32+
/**
33+
* @param File $file
34+
* @param int $position
35+
*/
36+
public function process(File $file, $position)
37+
{
38+
$tokens = $file->getTokens();
39+
$ifOpenerPosition = $tokens[$position]['parenthesis_opener'] ?? -1;
40+
$ifCloserPosition = $tokens[$position]['parenthesis_closer'] ?? -1;
41+
42+
if ($ifOpenerPosition < 0 || $ifCloserPosition <= ($ifOpenerPosition + 1)) {
43+
return;
44+
}
45+
46+
$insideIfAssignmentPositions = $this->findAssignmentPositions(
47+
$ifOpenerPosition,
48+
$ifCloserPosition,
49+
$file
50+
);
51+
52+
if (!$insideIfAssignmentPositions) {
53+
return;
54+
}
55+
56+
foreach ($insideIfAssignmentPositions as $insideIfAssignmentPosition) {
57+
if ($this->isAssignmentWrapped($insideIfAssignmentPosition, $ifOpenerPosition, $file)) {
58+
continue;
59+
}
60+
61+
$file->addWarning(
62+
'Please avoid assignments inside conditions, or at least wrap them in parenthesis.',
63+
$position,
64+
'Found'
65+
);
66+
}
67+
}
68+
69+
/**
70+
* @param int $ifOpenerPosition
71+
* @param int $ifCloserPosition
72+
* @param File $file
73+
* @return int[]
74+
*/
75+
private function findAssignmentPositions(
76+
int $ifOpenerPosition,
77+
int $ifCloserPosition,
78+
File $file
79+
): array {
80+
81+
$assignmentTokens = Helpers::filterTokensByType(
82+
$ifOpenerPosition + 1,
83+
$ifCloserPosition - 1,
84+
$file,
85+
...array_values(Tokens::$assignmentTokens)
86+
);
87+
88+
if (!$assignmentTokens) {
89+
return [];
90+
}
91+
92+
return array_keys($assignmentTokens);
93+
}
94+
95+
/**
96+
* @param int $insideIfAssignmentPosition
97+
* @param int $ifOpenerPosition
98+
* @param File $file
99+
* @return bool
100+
*/
101+
private function isAssignmentWrapped(
102+
int $insideIfAssignmentPosition,
103+
int $ifOpenerPosition,
104+
File $file
105+
) {
106+
$insideIfOpenParenthesisPosition = $file->findPrevious(
107+
T_OPEN_PARENTHESIS,
108+
$insideIfAssignmentPosition - 1,
109+
$ifOpenerPosition,
110+
false,
111+
null,
112+
true
113+
);
114+
115+
if ($insideIfOpenParenthesisPosition <= $ifOpenerPosition) {
116+
return false;
117+
}
118+
119+
$openParenthesisToken = $file->getTokens()[$insideIfOpenParenthesisPosition];
120+
$insideIfCloserParenthesisPosition = $openParenthesisToken['parenthesis_closer'] ?? -1;
121+
122+
if ($insideIfCloserParenthesisPosition < ($insideIfAssignmentPosition + 1)) {
123+
return false;
124+
}
125+
126+
$parenthesisInBetween = Helpers::filterTokensByType(
127+
$insideIfOpenParenthesisPosition + 1,
128+
$insideIfCloserParenthesisPosition - 1,
129+
$file,
130+
T_OPEN_PARENTHESIS,
131+
T_CLOSE_PARENTHESIS
132+
);
133+
134+
return !$parenthesisInBetween;
135+
}
136+
}
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
<?php
2+
// @phpcsSniff CodeQuality.AssignmentInsideCondition
3+
4+
if (($foo = 'x') || $foo += 'y' || ($foo = 'x')) {
5+
// @phpcsWarningOnPreviousLine
6+
return 1;
7+
}
8+
9+
if (($foo = 'x') && ($foo += 'y' && ($a = 'b')) || ($foo = 'z')) {
10+
// @phpcsWarningOnPreviousLine
11+
return 1;
12+
}
13+
14+
if ($foo = 'x') {
15+
// @phpcsWarningOnPreviousLine
16+
return 1;
17+
}
18+
19+
if (($foo = 'x') || ($foo = 'y') || ($foo = 'x')) {
20+
return 1;
21+
}
22+
23+
if (($foo = 'x')) {
24+
return 1;
25+
} elseif (($foo = 'y')) {
26+
return 2;
27+
} elseif ($foo = 'x') {
28+
// @phpcsWarningOnPreviousLine
29+
return 3;
30+
}
31+
32+
function inside_function() {
33+
34+
if (($foo = 'x')) {
35+
return 1;
36+
} elseif (($foo = 'y')) {
37+
return 2;
38+
} elseif ($foo = 'x') {
39+
// @phpcsWarningOnPreviousLine
40+
return 3;
41+
}
42+
43+
return 4;
44+
}
45+
46+
class OneClass {
47+
48+
function oneMethod() {
49+
50+
if (false) {
51+
return false;
52+
}
53+
54+
$foo = 1;
55+
56+
if (($foo = 5)) {
57+
return 1;
58+
} elseif (($foo |= 2)) {
59+
return 2;
60+
} elseif ($foo *= 0) {
61+
// @phpcsWarningOnPreviousLine
62+
return 3;
63+
}
64+
65+
return 4;
66+
}
67+
}

0 commit comments

Comments
 (0)