Skip to content

Commit f22959b

Browse files
committed
Merge pull request #68 from guywithnose/master
Fix the Unnecessary String Concat Sniff
2 parents b4af94d + 5c3ecc2 commit f22959b

File tree

4 files changed

+153
-1
lines changed

4 files changed

+153
-1
lines changed
Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
<?php
2+
/**
3+
* Checks that two strings are not concatenated together; suggests
4+
* using one string instead.
5+
*
6+
* @package DWS
7+
* @subpackage Sniffs
8+
*/
9+
10+
/**
11+
* Checks that two strings are not concatenated together; suggests
12+
* using one string instead.
13+
*
14+
* @package DWS
15+
* @subpackage Sniffs
16+
*/
17+
final class DWS_Sniffs_Strings_UnnecessaryStringConcatSniff implements PHP_CodeSniffer_Sniff
18+
{
19+
/**
20+
* The limit that the length of a line should not exceed.
21+
*
22+
* @var int
23+
*/
24+
public $stringLimit = 144;
25+
26+
/**
27+
* A list of tokenizers this sniff supports.
28+
*
29+
* @var array
30+
*/
31+
public $supportedTokenizers = array('PHP', 'JS');
32+
33+
/**
34+
* Returns an array of tokens this test wants to listen for.
35+
*
36+
* @return array
37+
*/
38+
public function register()
39+
{
40+
return array(T_STRING_CONCAT, T_PLUS);
41+
}
42+
43+
/**
44+
* Processes this test, when one of its tokens is encountered.
45+
*
46+
* @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
47+
* @param int $stackPtr The position of the current token in the stack passed in $tokens.
48+
*
49+
* @return void
50+
*/
51+
public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
52+
{
53+
// Work out which type of file this is for.
54+
$tokens = $phpcsFile->getTokens();
55+
if ($tokens[$stackPtr]['code'] === T_STRING_CONCAT XOR $phpcsFile->tokenizerType === 'PHP') {
56+
return;
57+
}
58+
59+
//Find the surrounding non-whitespace characters
60+
$prev = $phpcsFile->findPrevious(T_WHITESPACE, $stackPtr - 1, null, true);
61+
$next = $phpcsFile->findNext(T_WHITESPACE, $stackPtr + 1, null, true);
62+
63+
$stringTokens = PHP_CodeSniffer_Tokens::$stringTokens;
64+
//See if the characters before and after the concatenation are quotes
65+
if (
66+
in_array($tokens[$prev]['code'], $stringTokens) !== true ||
67+
in_array($tokens[$next]['code'], $stringTokens) !== true
68+
) {
69+
return;
70+
}
71+
72+
//Make sure the combined string would not be too long for one line.
73+
if (strlen($tokens[$prev]['content']) + strlen($tokens[$next]['content']) + $tokens[$prev]['column'] > $this->stringLimit) {
74+
return;
75+
}
76+
77+
$error = 'String concat is not required here; use a single string instead';
78+
$phpcsFile->addError($error, $stackPtr, 'Found');
79+
}
80+
}

DWS/ruleset.xml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,6 @@
5656
<rule ref="Generic.PHP.NoSilencedErrors" />
5757
<rule ref="Squiz.Scope.StaticThisUsage" />
5858
<rule ref="Squiz.Strings.EchoedStrings" />
59-
<rule ref="Generic.Strings.UnnecessaryStringConcat" />
6059
<rule ref="Squiz.WhiteSpace.CastSpacing" />
6160
<rule ref="Generic.WhiteSpace.DisallowTabIndent" />
6261
<rule ref="Squiz.WhiteSpace.FunctionOpeningBraceSpace" />
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
<?php
2+
if ($foo === 3) {
3+
foreach ($bar as $thing) {
4+
$reallyLongVariableName = 'This is an error. We shoule not ' . 'concatenate if the string is not tooi long.';
5+
}
6+
}
7+
8+
if ($foo === 3) {
9+
foreach ($bar as $thing) {
10+
$reallyLongVariableName = 'This is an error because it is a line tha' . 't is over 144 characers. We really should never do this!!!!!!!!!!!!!!';
11+
}
12+
}
13+
14+
if ($foo === 3) {
15+
foreach ($bar as $thing) {
16+
$reallyLongVariableName = 'This is ok. The string is very long such' .
17+
' that if we kept it on one line it would be over 144 characters. So there is no problem concatenating here.';
18+
}
19+
}
20+
21+
if ($foo === 3) {
22+
foreach ($bar as $thing) {
23+
$reallyLongVariableName = 3 . 'We can still concatenate with numbers.';
24+
}
25+
}
26+
27+
if ($foo === 3) {
28+
foreach ($bar as $thing) {
29+
$reallyLongVariableName = 'We should have no reason to add ' +
30+
'strings in PHP, but since this is possible in javascript, it is a good idea yo test how PHPCS handles it. It should do fine!';
31+
}
32+
}
33+
34+
$foo = 'abc' . "{$foo}bar";
35+
36+
$foo = "{$foo}bar" . 'abc';
37+
38+
$foo = 'abc' . "{$foo}bar";
39+
40+
$foo = "{$foo}bar" .
41+
'abc and a bunch more characters to make this take up >144 when concatenated to the previous line';
42+
43+
$foo = 'abc and a bunch more characters to make this take up >144 when concatenated to the next line' .
44+
"{$foo}bar";
45+
46+
$foo = 'First line
47+
Second line' . 'additional';
48+
49+
$foo = 'First line
50+
Second line a bunch of characters to make this line take up <144 characters but enough that when concatenated with the previous line it is >144' .
51+
'additional';
52+
53+
$foo = 'First line
54+
Second line a bunch of characters to make this line take up >144 characters' .
55+
'additional';
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
<?php
2+
final class DWS_Sniffs_Strings_UnnecessaryStringConcatSniffTest extends AbstractSniffUnitTest
3+
{
4+
public function getErrorList()
5+
{
6+
return array(4 => 1, 34 => 1, 36 => 1, 38 => 1, 40 => 1, 43 => 1, 47 => 1, 54 => 1);
7+
}
8+
9+
public function getWarningList()
10+
{
11+
return array();
12+
}
13+
14+
protected function _getSniffName()
15+
{
16+
return 'DWS_Sniffs_Strings_UnnecessaryStringConcatSniff';
17+
}
18+
}

0 commit comments

Comments
 (0)