Skip to content

Commit ed6ae4e

Browse files
committed
Adding PMD sniffs
git-svn-id: http://svn.php.net/repository/pear/packages/PHP_CodeSniffer/trunk@252356 c90b9560-bf6c-de11-be94-00142212c4b1
1 parent c76c689 commit ed6ae4e

25 files changed

+1872
-26
lines changed
Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
<?php
2+
/**
3+
* This file is part of the CodeAnalysis addon for PHP_CodeSniffer.
4+
*
5+
* PHP version 5
6+
*
7+
* @category PHP
8+
* @package PHP_CodeSniffer
9+
* @author Greg Sherwood <[email protected]>
10+
* @author Manuel Pichler <[email protected]>
11+
* @copyright 2007-2008 Manuel Pichler. All rights reserved.
12+
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
13+
* @version CVS: $Id$
14+
* @link http://pear.php.net/package/PHP_CodeSniffer
15+
*/
16+
17+
/**
18+
* This sniff class detected empty statement.
19+
*
20+
* This sniff implements the common algorithm for empty statement body detection.
21+
* A body is considered as empty if it is completely empty or it only contains
22+
* whitespace characters and|or comments.
23+
*
24+
* <code>
25+
* stmt {
26+
* // foo
27+
* }
28+
* stmt (conditions) {
29+
* // foo
30+
* }
31+
* </code>
32+
*
33+
* Statements covered by this sniff are <b>catch</b>, <b>do</b>, <b>else</b>,
34+
* <b>elsif</b>, <b>for</b>, <b>foreach<b>, <b>if</b>, <b>switch</b>, <b>try</b>
35+
* and <b>while</b>.
36+
*
37+
* @category PHP
38+
* @package PHP_CodeSniffer
39+
* @author Manuel Pichler <[email protected]>
40+
* @copyright 2007-2008 Manuel Pichler. All rights reserved.
41+
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
42+
* @version Release: @package_version@
43+
* @link http://pear.php.net/package/PHP_CodeSniffer
44+
*/
45+
class Generic_Sniffs_CodeAnalysis_EmptyStatementSniff implements PHP_CodeSniffer_Sniff
46+
{
47+
48+
/**
49+
* List of block tokens that this sniff covers.
50+
*
51+
* The key of this hash identifies the required token while the boolean
52+
* value says mark an error or mark a warning.
53+
*
54+
* @type array<boolean>
55+
* @var array(integer=>boolean) $_tokens
56+
*/
57+
private $_tokens = array(
58+
T_CATCH => true,
59+
T_DO => false,
60+
T_ELSE => false,
61+
T_ELSEIF => false,
62+
T_FOR => false,
63+
T_FOREACH => false,
64+
T_IF => false,
65+
T_SWITCH => false,
66+
T_TRY => false,
67+
T_WHILE => false,
68+
);
69+
70+
71+
/**
72+
* Registers the tokens that this sniff wants to listen for.
73+
*
74+
* @return array(integer)
75+
*/
76+
public function register()
77+
{
78+
return array_keys($this->_tokens);
79+
80+
}//end register()
81+
82+
83+
/**
84+
* Processes this test, when one of its tokens is encountered.
85+
*
86+
* @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
87+
* @param int $stackPtr The position of the current token
88+
* in the stack passed in $tokens.
89+
*
90+
* @return void
91+
*/
92+
public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
93+
{
94+
$tokens = $phpcsFile->getTokens();
95+
$token = $tokens[$stackPtr];
96+
97+
// Skip for-statements without body.
98+
if (isset($token['scope_opener']) === false) {
99+
return;
100+
}
101+
102+
$next = ++$token['scope_opener'];
103+
$end = --$token['scope_closer'];
104+
105+
$emptyBody = true;
106+
for (; $next <= $end; ++$next) {
107+
if (in_array($tokens[$next]['code'], PHP_CodeSniffer_Tokens::$emptyTokens) === false) {
108+
$emptyBody = false;
109+
break;
110+
}
111+
}
112+
113+
if ($emptyBody === true) {
114+
// Get token identifier.
115+
$name = $phpcsFile->getTokensAsString($stackPtr, 1);
116+
$error = sprintf('Empty %s statement detected', strtoupper($name));
117+
if ($this->_tokens[$token['code']] === true) {
118+
$phpcsFile->addError($error, $stackPtr);
119+
} else {
120+
$phpcsFile->addWarning($error, $stackPtr);
121+
}
122+
}
123+
124+
}//end process()
125+
126+
127+
}//end class
128+
129+
?>
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
<?php
2+
/**
3+
* This file is part of the CodeAnalysis addon for PHP_CodeSniffer.
4+
*
5+
* PHP version 5
6+
*
7+
* @category PHP
8+
* @package PHP_CodeSniffer
9+
* @author Greg Sherwood <[email protected]>
10+
* @author Manuel Pichler <[email protected]>
11+
* @copyright 2007-2008 Manuel Pichler. All rights reserved.
12+
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
13+
* @version CVS: $Id$
14+
* @link http://pear.php.net/package/PHP_CodeSniffer
15+
*/
16+
17+
/**
18+
* Detects for-loops that can be simplified to a while-loop.
19+
*
20+
* This rule is based on the PMD rule catalog. Detects for-loops that can be
21+
* simplified as a while-loop.
22+
*
23+
* <code>
24+
* class Foo
25+
* {
26+
* public function bar($x)
27+
* {
28+
* for (;true;) true; // No Init or Update part, may as well be: while (true)
29+
* }
30+
* }
31+
* </code>
32+
*
33+
* @category PHP
34+
* @package PHP_CodeSniffer
35+
* @author Manuel Pichler <[email protected]>
36+
* @copyright 2007-2008 Manuel Pichler. All rights reserved.
37+
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
38+
* @version Release: @package_version@
39+
* @link http://pear.php.net/package/PHP_CodeSniffer
40+
*/
41+
class Generic_Sniffs_CodeAnalysis_ForLoopShouldBeWhileLoopSniff implements PHP_CodeSniffer_Sniff
42+
{
43+
44+
45+
/**
46+
* Registers the tokens that this sniff wants to listen for.
47+
*
48+
* @return array(integer)
49+
*/
50+
public function register()
51+
{
52+
return array(T_FOR);
53+
54+
}//end register()
55+
56+
57+
/**
58+
* Processes this test, when one of its tokens is encountered.
59+
*
60+
* @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
61+
* @param int $stackPtr The position of the current token
62+
* in the stack passed in $tokens.
63+
*
64+
* @return void
65+
*/
66+
public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
67+
{
68+
$tokens = $phpcsFile->getTokens();
69+
$token = $tokens[$stackPtr];
70+
71+
// Skip invalid statement.
72+
if (isset($token['parenthesis_opener']) === false) {
73+
return;
74+
}
75+
76+
$next = ++$token['parenthesis_opener'];
77+
$end = --$token['parenthesis_closer'];
78+
79+
$parts = array(0, 0, 0);
80+
$index = 0;
81+
82+
for (; $next <= $end; ++$next) {
83+
$code = $tokens[$next]['code'];
84+
if ($code === T_SEMICOLON) {
85+
++$index;
86+
} else if (in_array($code, PHP_CodeSniffer_Tokens::$emptyTokens) === false) {
87+
++$parts[$index];
88+
}
89+
}
90+
91+
if ($parts[0] === 0 && $parts[2] === 0 && $parts[1] > 0) {
92+
$error = 'This FOR loop can be simplified to a WHILE loop';
93+
$phpcsFile->addWarning($error, $stackPtr);
94+
}
95+
96+
}//end process()
97+
98+
99+
}//end class
100+
101+
?>
Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
<?php
2+
/**
3+
* This file is part of the CodeAnalysis addon for PHP_CodeSniffer.
4+
*
5+
* PHP version 5
6+
*
7+
* @category PHP
8+
* @package PHP_CodeSniffer
9+
* @author Greg Sherwood <[email protected]>
10+
* @author Manuel Pichler <[email protected]>
11+
* @copyright 2007-2008 Manuel Pichler. All rights reserved.
12+
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
13+
* @version CVS: $Id$
14+
* @link http://pear.php.net/package/PHP_CodeSniffer
15+
*/
16+
17+
/**
18+
* Detects for-loops that use a function call in the test expression.
19+
*
20+
* This rule is based on the PMD rule catalog. Detects for-loops that use a
21+
* function call in the test expression.
22+
*
23+
* <code>
24+
* class Foo
25+
* {
26+
* public function bar($x)
27+
* {
28+
* $a = array(1, 2, 3, 4);
29+
* for ($i = 0; $i < count($a); $i++) {
30+
* $a[$i] *= $i;
31+
* }
32+
* }
33+
* }
34+
* </code>
35+
*
36+
* @category PHP
37+
* @package PHP_CodeSniffer
38+
* @author Manuel Pichler <[email protected]>
39+
* @copyright 2007-2008 Manuel Pichler. All rights reserved.
40+
* @license http://www.opensource.org/licenses/bsd-license.php BSD License
41+
* @version Release: @package_version@
42+
* @link http://pear.php.net/package/PHP_CodeSniffer
43+
*/
44+
class Generic_Sniffs_CodeAnalysis_ForLoopWithTestFunctionCallSniff implements PHP_CodeSniffer_Sniff
45+
{
46+
47+
48+
/**
49+
* Registers the tokens that this sniff wants to listen for.
50+
*
51+
* @return array(integer)
52+
*/
53+
public function register()
54+
{
55+
return array(T_FOR);
56+
57+
}//end register()
58+
59+
60+
/**
61+
* Processes this test, when one of its tokens is encountered.
62+
*
63+
* @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
64+
* @param int $stackPtr The position of the current token
65+
* in the stack passed in $tokens.
66+
*
67+
* @return void
68+
*/
69+
public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
70+
{
71+
$tokens = $phpcsFile->getTokens();
72+
$token = $tokens[$stackPtr];
73+
74+
// Skip invalid statement.
75+
if (isset($token['parenthesis_opener']) === false) {
76+
return;
77+
}
78+
79+
$next = ++$token['parenthesis_opener'];
80+
$end = --$token['parenthesis_closer'];
81+
82+
$position = 0;
83+
84+
for (; $next <= $end; ++$next) {
85+
$code = $tokens[$next]['code'];
86+
if ($code === T_SEMICOLON) {
87+
++$position;
88+
}
89+
90+
if ($position < 1) {
91+
continue;
92+
} else if ($position > 1) {
93+
break;
94+
} else if ($code !== T_VARIABLE && $code !== T_STRING) {
95+
continue;
96+
}
97+
98+
// Find next non empty token, if it is a open curly brace we have a
99+
// function call.
100+
$index = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$emptyTokens, ($next + 1), null, true);
101+
102+
if ($tokens[$index]['code'] === T_OPEN_PARENTHESIS) {
103+
$error = 'Avoid function calls in a FOR loop test part';
104+
$phpcsFile->addWarning($error, $stackPtr);
105+
break;
106+
}
107+
}//end for
108+
109+
}//end process()
110+
111+
112+
}//end class
113+
114+
?>

0 commit comments

Comments
 (0)