Skip to content

Commit 4de2616

Browse files
author
Vincent Langlet
committed
✨ Add elseif, else, break rules
1 parent 5710c54 commit 4de2616

File tree

5 files changed

+196
-8
lines changed

5 files changed

+196
-8
lines changed
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
<?php
2+
3+
namespace Symfony3Custom\Sniffs\Formatting;
4+
5+
use PHP_CodeSniffer\Files\File;
6+
use PHP_CodeSniffer\Sniffs\Sniff;
7+
8+
/**
9+
* Checks whether there are else(if) or break statements after return or throw
10+
*/
11+
class ConditionalReturnOrThrowSniff implements Sniff
12+
{
13+
/**
14+
* @var array
15+
*/
16+
private $openers = [
17+
T_IF,
18+
T_CASE,
19+
];
20+
21+
/**
22+
* @var array
23+
*/
24+
private $conditions = [
25+
T_ELSEIF,
26+
T_ELSE,
27+
T_BREAK,
28+
];
29+
30+
/**
31+
* Registers the tokens that this sniff wants to listen for.
32+
*/
33+
public function register()
34+
{
35+
return [
36+
T_THROW,
37+
T_RETURN,
38+
];
39+
}
40+
41+
/**
42+
* Called when one of the token types that this sniff is listening for is found.
43+
*
44+
* @param File $phpcsFile The PHP_CodeSniffer file where the token was found.
45+
* @param int $stackPtr The position in the PHP_CodeSniffer file's token stack
46+
* where the token was found.
47+
*
48+
* @return void|int Optionally returns a stack pointer. The sniff will not be
49+
* called again on the current file until the returned stack
50+
* pointer is reached. Return (count($tokens) + 1) to skip
51+
* the rest of the file.
52+
*/
53+
public function process(File $phpcsFile, $stackPtr)
54+
{
55+
$tokens = $phpcsFile->getTokens();
56+
$opener = $phpcsFile->findPrevious($this->openers, $stackPtr);
57+
58+
if ($opener && $stackPtr <= $tokens[$opener]['scope_closer']) {
59+
$isClosure = $phpcsFile->findPrevious(T_CLOSURE, $stackPtr, $opener);
60+
61+
if (false !== $isClosure) {
62+
return;
63+
}
64+
65+
$condition = $phpcsFile->findNext($this->conditions, $stackPtr + 1);
66+
67+
if (false !== $condition) {
68+
$next = $phpcsFile->findNext($this->openers, $stackPtr + 1);
69+
70+
if (false !== $next) {
71+
$err = (isset($tokens[$condition]['scope_closer']) && isset($tokens[$next]['scope_opener']))
72+
? $tokens[$condition]['scope_closer'] < $tokens[$next]['scope_opener']
73+
: $tokens[$condition]['line'] <= $tokens[$next]['line'];
74+
} else {
75+
$err = false;
76+
}
77+
78+
if (false === $next || true === $err) {
79+
$phpcsFile->addError(
80+
'Do not use else, elseif, break after if and case conditions which return or throw something',
81+
$condition,
82+
'Invalid'
83+
);
84+
}
85+
}
86+
}
87+
}
88+
}
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
<?php
2+
3+
class Test
4+
{
5+
public function tester($dummy, $mergedOptions)
6+
{
7+
if (true === $dummy) {
8+
return null;
9+
}
10+
11+
if ('string' === $dummy) {
12+
if ('values' === $mergedOptions['some_default']) {
13+
return substr($dummy, 0, 5);
14+
}
15+
16+
return ucwords($dummy);
17+
}
18+
19+
if ('int' === $dummy) {
20+
if ('values' === $mergedOptions['some_default']) {
21+
return substr($dummy, 0, 5);
22+
} elseif (true) {
23+
return ucwords($dummy);
24+
}
25+
}
26+
27+
if ('a' === $dummy) {
28+
$mergedOptions['a'] = true;
29+
} else {
30+
$mergedOptions['a'] = false;
31+
}
32+
33+
if ('b' === $dummy) {
34+
$mergedOptions['a'] = true;
35+
36+
throw new Error();
37+
} else {
38+
$mergedOptions['a'] = false;
39+
}
40+
41+
switch (true) {
42+
case false:
43+
return null;
44+
break;
45+
default:
46+
break;
47+
}
48+
49+
if ('c' === $dummy) {
50+
$function = function () {
51+
return null;
52+
};
53+
} elseif ('d' === $dummy) {
54+
return null;
55+
}
56+
57+
return null;
58+
}
59+
}
60+
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
<?php
2+
3+
namespace Symfony3Custom\Tests\Formatting;
4+
5+
use PHP_CodeSniffer\Tests\Standards\AbstractSniffUnitTest;
6+
7+
/**
8+
* Unit test class for the ConditionalReturnOrThrow sniff.
9+
*
10+
* @group Symfony3Custom
11+
*/
12+
class ConditionalReturnOrThrowUnitTest extends AbstractSniffUnitTest
13+
{
14+
/**
15+
* Returns the lines where errors should occur.
16+
*
17+
* The key of the array should represent the line number and the value
18+
* should represent the number of errors that should occur on that line.
19+
*
20+
* @return array(int => int)
21+
*/
22+
public function getErrorList()
23+
{
24+
return array(
25+
22 => 1,
26+
37 => 1,
27+
44 => 1,
28+
);
29+
}
30+
31+
/**
32+
* Returns the lines where warnings should occur.
33+
*
34+
* The key of the array should represent the line number and the value
35+
* should represent the number of errors that should occur on that line.
36+
*
37+
* @return array(int => int)
38+
*/
39+
public function getWarningList()
40+
{
41+
return array();
42+
}
43+
}

docs/standards.md

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,10 @@ We imported the [PSR2 Standard](./standards/psr2.md) with these overrides:
2424
## From symfony
2525

2626
We mainly respect the [Symfony Standard](./standards/symfony.md) but
27-
28-
- We do not respect this rule:
27+
we do not respect this rule:
2928

3029
- Declare all the arguments on the same line as the method/function name, no matter how many arguments there are
3130

32-
- We do not currently check this rule:
33-
34-
- Do not use `else`, `elseif`, `break` after `if` and `case` conditions which return or throw something
35-
3631
## Others
3732
### Imported
3833
- Do not use `<?` to define a php file
@@ -124,7 +119,7 @@ We mainly respect the [Symfony Standard](./standards/symfony.md) but
124119
<rule ref="Symfony3Custom.Commenting.VariableComment"/>
125120
```
126121

127-
- USE keywords should be alphabetically sorted
122+
- `use` keywords should be alphabetically sorted
128123

129124
```
130125
<rule ref="Symfony3Custom.Namespaces.AlphabeticallySortedUse"/>

docs/standards/symfony.md

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,7 +108,9 @@ Not checked because of the limit of 120 characters per line
108108

109109
- Do not use `else`, `elseif`, `break` after `if` and `case` conditions which return or throw something
110110

111-
Not covered
111+
```
112+
<rule ref="Symfony3Custom.Formatting.ConditionalReturnOrThrowSniff" />
113+
```
112114

113115
- Do not use spaces around `[` offset accessor and before `]` offset accessor
114116

0 commit comments

Comments
 (0)