Skip to content

Commit 4c06ebe

Browse files
committed
Merge branch 'feature/new-spread-operator-spacing-sniff' of https://github.com/jrfnl/PHP_CodeSniffer
2 parents fcca8b1 + 5c82a94 commit 4c06ebe

File tree

6 files changed

+384
-0
lines changed

6 files changed

+384
-0
lines changed

package.xml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -408,6 +408,7 @@ http://pear.php.net/dtd/package-2.0.xsd">
408408
<file baseinstalldir="PHP/CodeSniffer" name="DisallowSpaceIndentStandard.xml" role="php" />
409409
<file baseinstalldir="PHP/CodeSniffer" name="DisallowTabIndentStandard.xml" role="php" />
410410
<file baseinstalldir="PHP/CodeSniffer" name="ScopeIndentStandard.xml" role="php" />
411+
<file baseinstalldir="PHP/CodeSniffer" name="SpreadOperatorSpacingAfterStandard.xml" role="php" />
411412
</dir>
412413
</dir>
413414
<dir name="Sniffs">
@@ -515,6 +516,7 @@ http://pear.php.net/dtd/package-2.0.xsd">
515516
<file baseinstalldir="PHP/CodeSniffer" name="IncrementDecrementSpacingSniff.php" role="php" />
516517
<file baseinstalldir="PHP/CodeSniffer" name="LanguageConstructSpacingSniff.php" role="php" />
517518
<file baseinstalldir="PHP/CodeSniffer" name="ScopeIndentSniff.php" role="php" />
519+
<file baseinstalldir="PHP/CodeSniffer" name="SpreadOperatorSpacingAfterSniff.php" role="php" />
518520
</dir>
519521
</dir>
520522
<dir name="Tests">
@@ -834,6 +836,9 @@ http://pear.php.net/dtd/package-2.0.xsd">
834836
<file baseinstalldir="PHP/CodeSniffer" name="ScopeIndentUnitTest.3.inc.fixed" role="test" />
835837
<file baseinstalldir="PHP/CodeSniffer" name="ScopeIndentUnitTest.4.inc" role="test" />
836838
<file baseinstalldir="PHP/CodeSniffer" name="ScopeIndentUnitTest.php" role="test" />
839+
<file baseinstalldir="PHP/CodeSniffer" name="SpreadOperatorSpacingAfterUnitTest.inc" role="test" />
840+
<file baseinstalldir="PHP/CodeSniffer" name="SpreadOperatorSpacingAfterUnitTest.inc.fixed" role="test" />
841+
<file baseinstalldir="PHP/CodeSniffer" name="SpreadOperatorSpacingAfterUnitTest.php" role="test" />
837842
</dir>
838843
</dir>
839844
<file baseinstalldir="PHP/CodeSniffer" name="ruleset.xml" role="php" />
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
<documentation title="Spacing After Spread Operator">
2+
<standard>
3+
<![CDATA[
4+
There should be no space between the spread operator and the variable/function call it applies to.
5+
]]>
6+
</standard>
7+
<code_comparison>
8+
<code title="Valid: No space between the spread operator and the variable/function call it applies to.">
9+
<![CDATA[
10+
function foo(<em>&...$spread</em>) {
11+
bar(<em>...$spread</em>);
12+
13+
bar(
14+
[<em>...$foo</em>],
15+
<em>...array_values($keyedArray)</em>
16+
);
17+
}
18+
]]>
19+
</code>
20+
<code title="Invalid: space found between the spread operator and the variable/function call it applies to.">
21+
<![CDATA[
22+
function bar(<em>... </em>$spread) {
23+
bar(<em>...
24+
</em>$spread
25+
);
26+
27+
bar(
28+
[<em>... </em>$foo ],<em>.../*comment*/</em>array_values($keyedArray)
29+
);
30+
}
31+
]]>
32+
</code>
33+
</code_comparison>
34+
</documentation>
Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
<?php
2+
/**
3+
* Verifies spacing between the spread operator and the variable/function call it applies to.
4+
*
5+
* @author Juliette Reinders Folmer <phpcs_nospam@adviesenzo.nl>
6+
* @copyright 2019 Juliette Reinders Folmer. All rights reserved.
7+
* @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
8+
*/
9+
10+
namespace PHP_CodeSniffer\Standards\Generic\Sniffs\WhiteSpace;
11+
12+
use PHP_CodeSniffer\Sniffs\Sniff;
13+
use PHP_CodeSniffer\Files\File;
14+
use PHP_CodeSniffer\Util\Tokens;
15+
16+
class SpreadOperatorSpacingAfterSniff implements Sniff
17+
{
18+
19+
/**
20+
* The number of spaces desired after a spread token.
21+
*
22+
* @var integer
23+
*/
24+
public $spacing = 0;
25+
26+
/**
27+
* Allow newlines instead of spaces.
28+
*
29+
* @var boolean
30+
*/
31+
public $ignoreNewlines = false;
32+
33+
34+
/**
35+
* Returns an array of tokens this test wants to listen for.
36+
*
37+
* @return array
38+
*/
39+
public function register()
40+
{
41+
return [T_ELLIPSIS];
42+
43+
}//end register()
44+
45+
46+
/**
47+
* Processes this test, when one of its tokens is encountered.
48+
*
49+
* @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned.
50+
* @param int $stackPtr The position of the current token in
51+
* the stack passed in $tokens.
52+
*
53+
* @return void
54+
*/
55+
public function process(File $phpcsFile, $stackPtr)
56+
{
57+
$tokens = $phpcsFile->getTokens();
58+
$this->spacing = (int) $this->spacing;
59+
60+
$nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true);
61+
if ($nextNonEmpty === false) {
62+
return;
63+
}
64+
65+
if ($this->ignoreNewlines === true
66+
&& $tokens[$stackPtr]['line'] !== $tokens[$nextNonEmpty]['line']
67+
) {
68+
$phpcsFile->recordMetric($stackPtr, 'Spacing after spread operator', 'newline');
69+
return;
70+
}
71+
72+
if ($this->spacing === 0 && $nextNonEmpty === ($stackPtr + 1)) {
73+
$phpcsFile->recordMetric($stackPtr, 'Spacing after spread operator', 0);
74+
return;
75+
}
76+
77+
$nextNonWhitespace = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true);
78+
if ($nextNonEmpty !== $nextNonWhitespace) {
79+
$error = 'Expected %s space(s) after the spread operator; comment found';
80+
$data = [$this->spacing];
81+
$phpcsFile->addError($error, $stackPtr, 'CommentFound', $data);
82+
83+
if ($tokens[($stackPtr + 1)]['code'] === T_WHITESPACE) {
84+
$phpcsFile->recordMetric($stackPtr, 'Spacing after spread operator', $tokens[($stackPtr + 1)]['length']);
85+
} else {
86+
$phpcsFile->recordMetric($stackPtr, 'Spacing after spread operator', 0);
87+
}
88+
89+
return;
90+
}
91+
92+
$found = 0;
93+
if ($tokens[$stackPtr]['line'] !== $tokens[$nextNonEmpty]['line']) {
94+
$found = 'newline';
95+
} else if ($tokens[($stackPtr + 1)]['code'] === T_WHITESPACE) {
96+
$found = $tokens[($stackPtr + 1)]['length'];
97+
}
98+
99+
$phpcsFile->recordMetric($stackPtr, 'Spacing after spread operator', $found);
100+
101+
if ($found === $this->spacing) {
102+
return;
103+
}
104+
105+
$error = 'Expected %s space(s) after the spread operator; %s found';
106+
$data = [
107+
$this->spacing,
108+
$found,
109+
];
110+
111+
$errorCode = 'TooMuchSpace';
112+
if ($this->spacing !== 0) {
113+
if ($found === 0) {
114+
$errorCode = 'NoSpace';
115+
} else if ($found !== 'newline' && $found < $this->spacing) {
116+
$errorCode = 'TooLittleSpace';
117+
}
118+
}
119+
120+
$fix = $phpcsFile->addFixableError($error, $stackPtr, $errorCode, $data);
121+
122+
if ($fix === true) {
123+
$padding = str_repeat(' ', $this->spacing);
124+
if ($found === 0) {
125+
$phpcsFile->fixer->addContent($stackPtr, $padding);
126+
} else {
127+
$phpcsFile->fixer->beginChangeset();
128+
$start = ($stackPtr + 1);
129+
130+
if ($this->spacing > 0) {
131+
$phpcsFile->fixer->replaceToken($start, $padding);
132+
++$start;
133+
}
134+
135+
for ($i = $start; $i < $nextNonWhitespace; $i++) {
136+
$phpcsFile->fixer->replaceToken($i, '');
137+
}
138+
139+
$phpcsFile->fixer->endChangeset();
140+
}
141+
}
142+
143+
}//end process()
144+
145+
146+
}//end class
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
<?php
2+
3+
function foo( &...$spread ) {
4+
bar( ...$spread );
5+
6+
bar(
7+
[ ...$foo ],
8+
...array_values($keyedArray)
9+
);
10+
}
11+
12+
function bar( & ... $spread ) {
13+
bar(...
14+
15+
16+
$spread
17+
);
18+
19+
bar(
20+
[... $foo ],.../*comment*/array_values($keyedArray)
21+
);
22+
}
23+
24+
// phpcs:set Generic.WhiteSpace.SpreadOperatorSpacingAfter ignoreNewlines true
25+
bar(...
26+
$spread
27+
);
28+
// phpcs:set Generic.WhiteSpace.SpreadOperatorSpacingAfter ignoreNewlines false
29+
30+
// phpcs:set Generic.WhiteSpace.SpreadOperatorSpacingAfter spacing 1
31+
function foo( &... $spread ) {
32+
bar( ... $spread );
33+
34+
bar(
35+
[ ... $foo ],
36+
... array_values($keyedArray)
37+
);
38+
}
39+
40+
function bar( & ...$spread ) {
41+
bar(...
42+
$spread
43+
);
44+
45+
bar(
46+
[... $foo ],.../*comment*/array_values($keyedArray)
47+
);
48+
}
49+
50+
// phpcs:set Generic.WhiteSpace.SpreadOperatorSpacingAfter spacing 2
51+
function foo( &... $spread ) {
52+
bar( ... $spread );
53+
54+
bar(
55+
[ ... $foo ],
56+
... array_values($keyedArray)
57+
);
58+
}
59+
60+
function bar( & ... $spread ) {
61+
bar(...
62+
$spread
63+
);
64+
65+
bar(
66+
[... $foo ],.../*comment*/array_values($keyedArray)
67+
);
68+
}
69+
70+
// phpcs:set Generic.WhiteSpace.SpreadOperatorSpacingAfter spacing 0
71+
72+
// Intentional parse error. This has to be the last test in the file.
73+
function bar( ...
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<?php
2+
3+
function foo( &...$spread ) {
4+
bar( ...$spread );
5+
6+
bar(
7+
[ ...$foo ],
8+
...array_values($keyedArray)
9+
);
10+
}
11+
12+
function bar( & ...$spread ) {
13+
bar(...$spread
14+
);
15+
16+
bar(
17+
[...$foo ],.../*comment*/array_values($keyedArray)
18+
);
19+
}
20+
21+
// phpcs:set Generic.WhiteSpace.SpreadOperatorSpacingAfter ignoreNewlines true
22+
bar(...
23+
$spread
24+
);
25+
// phpcs:set Generic.WhiteSpace.SpreadOperatorSpacingAfter ignoreNewlines false
26+
27+
// phpcs:set Generic.WhiteSpace.SpreadOperatorSpacingAfter spacing 1
28+
function foo( &... $spread ) {
29+
bar( ... $spread );
30+
31+
bar(
32+
[ ... $foo ],
33+
... array_values($keyedArray)
34+
);
35+
}
36+
37+
function bar( & ... $spread ) {
38+
bar(... $spread
39+
);
40+
41+
bar(
42+
[... $foo ],.../*comment*/array_values($keyedArray)
43+
);
44+
}
45+
46+
// phpcs:set Generic.WhiteSpace.SpreadOperatorSpacingAfter spacing 2
47+
function foo( &... $spread ) {
48+
bar( ... $spread );
49+
50+
bar(
51+
[ ... $foo ],
52+
... array_values($keyedArray)
53+
);
54+
}
55+
56+
function bar( & ... $spread ) {
57+
bar(... $spread
58+
);
59+
60+
bar(
61+
[... $foo ],.../*comment*/array_values($keyedArray)
62+
);
63+
}
64+
65+
// phpcs:set Generic.WhiteSpace.SpreadOperatorSpacingAfter spacing 0
66+
67+
// Intentional parse error. This has to be the last test in the file.
68+
function bar( ...

0 commit comments

Comments
 (0)