Skip to content

Commit f093d00

Browse files
committed
Class standards for the Squiz coding standard
git-svn-id: http://svn.php.net/repository/pear/packages/PHP_CodeSniffer/trunk@225273 c90b9560-bf6c-de11-be94-00142212c4b1
1 parent 52676ac commit f093d00

12 files changed

+936
-0
lines changed
Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
<?php
2+
/**
3+
* Class Declaration Test.
4+
*
5+
* PHP version 5
6+
*
7+
* @category PHP
8+
* @package PHP_CodeSniffer
9+
* @author Greg Sherwood <[email protected]>
10+
* @author Marc McIntyre <[email protected]>
11+
* @copyright 2006 Squiz Pty Ltd (ABN 77 084 670 600)
12+
* @license http://matrix.squiz.net/developer/tools/php_cs/licence BSD Licence
13+
* @version CVS: $Id$
14+
* @link http://pear.php.net/package/PHP_CodeSniffer
15+
*/
16+
17+
require_once 'PHP/CodeSniffer/Sniff.php';
18+
19+
/**
20+
* Class Declaration Test.
21+
*
22+
* Checks the declaration of the class and its' inheritance is correct.
23+
*
24+
* @category PHP
25+
* @package PHP_CodeSniffer
26+
* @author Greg Sherwood <[email protected]>
27+
* @author Marc McIntyre <[email protected]>
28+
* @copyright 2006 Squiz Pty Ltd (ABN 77 084 670 600)
29+
* @license http://matrix.squiz.net/developer/tools/php_cs/licence BSD Licence
30+
* @version Release: @package_version@
31+
* @link http://pear.php.net/package/PHP_CodeSniffer
32+
*/
33+
class Squiz_Sniffs_Classes_ClassDeclarationSniff implements PHP_CodeSniffer_Sniff
34+
{
35+
36+
37+
/**
38+
* Returns an array of tokens this test wants to listen for.
39+
*
40+
* @return array
41+
*/
42+
public function register()
43+
{
44+
return array(
45+
T_CLASS,
46+
T_INTERFACE,
47+
);
48+
49+
}//end register()
50+
51+
52+
/**
53+
* Processes this test, when one of its tokens is encountered.
54+
*
55+
* @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
56+
* @param int $stackPtr The position of the current token in the
57+
* stack passed in $tokens.
58+
*
59+
* @return void
60+
*/
61+
public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
62+
{
63+
$tokens = $phpcsFile->getTokens();
64+
65+
/*
66+
First, check that this is the only class or interface in the file.
67+
*/
68+
69+
$nextClass = $phpcsFile->findNext(array(T_CLASS, T_INTERFACE), $stackPtr + 1);
70+
71+
if ($nextClass !== false) {
72+
// We have another, so an error is thrown.
73+
$error = 'Only one interface or class is allowed in a file.';
74+
$phpcsFile->addError($error, $nextClass);
75+
}
76+
77+
/*
78+
Checks the Opening brace is straight after the declaration.
79+
*/
80+
81+
$curlyBrace = $phpcsFile->findNext(array(T_OPEN_CURLY_BRACKET), $stackPtr, null, false);
82+
83+
$classLine = $tokens[$stackPtr]['line'];
84+
$braceLine = $tokens[$curlyBrace]['line'];
85+
if ($braceLine === $classLine) {
86+
$error = 'Opening brace of a ';
87+
$error .= $tokens[$stackPtr]['content'];
88+
$error .= ' must be on the line after the definition.';
89+
$phpcsFile->addError($error, $stackPtr);
90+
return;
91+
} else if ($braceLine > ($classLine + 1)) {
92+
$difference = ($braceLine - $classLine - 1);
93+
$difference .= ($difference === 1) ? ' empty line' : ' empty lines';
94+
$error = 'Opening brace of a ';
95+
$error .= $tokens[$stackPtr]['content'];
96+
$error .= ' should be on the line following a ';
97+
$error .= $tokens[$stackPtr]['content'];
98+
$error .= ' declaration. Found '.$difference.'.';
99+
$phpcsFile->addError($error, $curlyBrace);
100+
return;
101+
}
102+
103+
if ($tokens[$curlyBrace - 1]['content'] === "\n") {
104+
// Only a newline behind it.
105+
return;
106+
}
107+
108+
$blankSpace = substr($tokens[$curlyBrace - 1]['content'], strpos($tokens[$curlyBrace - 1]['content'], "\n"));
109+
$spaces = strlen($blankSpace);
110+
$spaces .= ($spaces === 1) ? ' space' : ' spaces';
111+
$error = 'Found '.$spaces.' before opening brace. Expected 0.';
112+
$phpcsFile->addError($error, $curlyBrace);
113+
114+
/*
115+
Check that each of the parent classes or interfaces specified
116+
are spaced correctly.
117+
*/
118+
119+
// We need to map out each of the possible tokens in the declaration.
120+
$keyword = $stackPtr;
121+
$openingBrace = $phpcsFile->findNext(T_OPEN_CURLY_BRACKET, $stackPtr);
122+
$className = $phpcsFile->findNext(T_STRING, $stackPtr);
123+
$extends = $phpcsFile->findNext(array(T_IMPLEMENTS, T_EXTENDS), $stackPtr, $openingBrace);
124+
$parents = array();
125+
126+
$nextParent = ($className + 1);
127+
while (($nextParent = $phpcsFile->findNext(T_STRING, $nextParent + 1, $openingBrace)) !== false) {
128+
$parents[] = $nextParent;
129+
}
130+
131+
/*
132+
Now check the spacing of each token.
133+
*/
134+
135+
$name = $tokens[$keyword]['content'];
136+
// Spacing of the keyword.
137+
$gap = $tokens[$stackPtr + 1]['content'];
138+
if (strlen($gap) !== 1) {
139+
$error = strlen($gap).' spaces found between "'.$name;
140+
$error .= '" keyword, and '.strtolower($name).' name. Expected 1.';
141+
$phpcsFile->addError($error, $stackPtr);
142+
}
143+
144+
// Check after the name.
145+
$gap = $tokens[$className + 1]['content'];
146+
if (strlen($gap) !== 1) {
147+
$error = strlen($gap).' spaces found after '.$name;
148+
$error .= 'name. Expected 1.';
149+
$phpcsFile->addError($error, $stackPtr);
150+
}
151+
152+
// Now check each of the parents.
153+
$parentCount = count($parents);
154+
for ($i = 0; $i < $parentCount; $i++) {
155+
if ($i === 0) {
156+
$spaceBefore = strlen($tokens[$parents[$i] - 1]['content']);
157+
if ($spaceBefore !== 1) {
158+
$error = $spaceBefore.' spaces found before ';
159+
$error .= '"'.$tokens[$parents[$i]]['content'].'". ';
160+
$error .= 'Expected 1.';
161+
$phpcsFile->addError($error, $stackPtr);
162+
}
163+
}
164+
165+
if ($tokens[$parents[$i] + 1]['code'] !== T_NONE) {
166+
if ($i !== ($parentCount - 1)) {
167+
$error = 'Space found between ';
168+
$error .= $tokens[$parents[$i]]['content'].' and comma.';
169+
}
170+
} else {
171+
if ($tokens[$parents[$i] + 2]['code'] !== T_WHITESPACE) {
172+
$content = $tokens[$parents[$i] + 2]['content'];
173+
$error = 'Space required before "'.$content.'".';
174+
$phpcsFile->addError($error, $stackPtr);
175+
} else {
176+
if ($i !== ($parentCount - 1)) {
177+
$space = strlen($tokens[$parents[$i] + 2]['content']);
178+
if ($space !== 1) {
179+
$content = $tokens[$parents[$i] + 3]['content'];
180+
$error = $space.' spaces found before ';
181+
$error .= '"'.$content.'"';
182+
$error .= '. Expected 1.';
183+
$phpcsFile->addError($error, $stackPtr);
184+
}
185+
}
186+
}
187+
}//end if
188+
}//end for
189+
190+
}//end process()
191+
192+
193+
}//end class
194+
195+
?>
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
<?php
2+
/**
3+
* Squiz_Sniffs_Classes_ClassFileNameSniff.
4+
*
5+
* PHP version 5
6+
*
7+
* @category PHP
8+
* @package PHP_CodeSniffer
9+
* @author Greg Sherwood <[email protected]>
10+
* @author Marc McIntyre <[email protected]>
11+
* @copyright 2006 Squiz Pty Ltd (ABN 77 084 670 600)
12+
* @license http://matrix.squiz.net/developer/tools/php_cs/licence BSD Licence
13+
* @version CVS: $Id$
14+
* @link http://pear.php.net/package/PHP_CodeSniffer
15+
*/
16+
17+
require_once 'PHP/CodeSniffer/Sniff.php';
18+
19+
/**
20+
* Squiz_Sniffs_Classes_ClassFileNameSniff.
21+
*
22+
* Tests that the file name and the name of the class contained within the file
23+
* match.
24+
*
25+
* @category PHP
26+
* @package PHP_CodeSniffer
27+
* @author Greg Sherwood <[email protected]>
28+
* @author Marc McIntyre <[email protected]>
29+
* @copyright 2006 Squiz Pty Ltd (ABN 77 084 670 600)
30+
* @license http://matrix.squiz.net/developer/tools/php_cs/licence BSD Licence
31+
* @version Release: @package_version@
32+
* @link http://pear.php.net/package/PHP_CodeSniffer
33+
*/
34+
class Squiz_Sniffs_Classes_ClassFileNameSniff implements PHP_CodeSniffer_Sniff
35+
{
36+
37+
38+
/**
39+
* Returns an array of tokens this test wants to listen for.
40+
*
41+
* @return array
42+
*/
43+
public function register()
44+
{
45+
return array(
46+
T_CLASS,
47+
T_INTERFACE,
48+
);
49+
50+
}//end register()
51+
52+
53+
/**
54+
* Processes this test, when one of its tokens is encountered.
55+
*
56+
* @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
57+
* @param int $stackPtr The position of the current token in the
58+
* stack passed in $tokens.
59+
*
60+
* @return void
61+
*/
62+
public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
63+
{
64+
$tokens = $phpcsFile->getTokens();
65+
$decName = $phpcsFile->findNext(T_STRING, $stackPtr);
66+
$fullPath = basename($phpcsFile->getFilename());
67+
$fileName = substr($fullPath, 0, strrpos($fullPath, '.'));
68+
69+
if ($tokens[$decName]['content'] !== $fileName) {
70+
$error = ucfirst($tokens[$stackPtr]['content']);
71+
$error .= ' name doesn\'t match filename. Expected ';
72+
$error .= '"'.$tokens[$stackPtr]['content'].' ';
73+
$error .= $fileName.'".';
74+
$phpcsFile->addError($error, $stackPtr);
75+
}
76+
77+
}//end process()
78+
79+
80+
}//end class
81+
82+
?>
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
<?php
2+
/**
3+
* Squiz_Sniffs_Classes_ClassFileNameSniff.
4+
*
5+
* PHP version 5
6+
*
7+
* @category PHP
8+
* @package PHP_CodeSniffer
9+
* @author Greg Sherwood <[email protected]>
10+
* @author Marc McIntyre <[email protected]>
11+
* @copyright 2006 Squiz Pty Ltd (ABN 77 084 670 600)
12+
* @license http://matrix.squiz.net/developer/tools/php_cs/licence BSD Licence
13+
* @version CVS: $Id$
14+
* @link http://pear.php.net/package/PHP_CodeSniffer
15+
*/
16+
17+
require_once 'PHP/CodeSniffer/Standards/AbstractScopeSniff.php';
18+
19+
/**
20+
* Tests self member references.
21+
*
22+
* Verifies that :
23+
* <ul>
24+
* <li>self:: is used instead of Self::</li>
25+
* <li>self:: is used for local static member reference</li>
26+
* <li>self:: is used instead of self ::</li>
27+
* </ul>
28+
*
29+
* @category PHP
30+
* @package PHP_CodeSniffer
31+
* @author Greg Sherwood <[email protected]>
32+
* @author Marc McIntyre <[email protected]>
33+
* @copyright 2006 Squiz Pty Ltd (ABN 77 084 670 600)
34+
* @license http://matrix.squiz.net/developer/tools/php_cs/licence BSD Licence
35+
* @version Release: @package_version@
36+
* @link http://pear.php.net/package/PHP_CodeSniffer
37+
*/
38+
class Squiz_Sniffs_Classes_SelfMemberReferenceSniff extends PHP_CodeSniffer_Standards_AbstractScopeSniff
39+
{
40+
41+
42+
/**
43+
* Constructs a Squiz_Sniffs_Classes_SelfMemberReferenceSniff.
44+
*/
45+
public function __construct()
46+
{
47+
parent::__construct(array(T_CLASS), array(T_DOUBLE_COLON));
48+
49+
}//end __construct()
50+
51+
52+
/**
53+
* Processes the function tokens within the class.
54+
*
55+
* @param PHP_CodeSniffer_File $phpcsFile The file where this token was found.
56+
* @param int $stackPtr The position where the token was found.
57+
* @param int $currScope The current scope opener token.
58+
*
59+
* @return void
60+
*/
61+
protected function processTokenWithinScope(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $currScope)
62+
{
63+
$tokens = $phpcsFile->getTokens();
64+
65+
$className = ($stackPtr - 1);
66+
if ($tokens[$className]['code'] === T_SELF) {
67+
if (strtolower($tokens[$className]['content']) !== $tokens[$className]['content']) {
68+
$error = 'Must use "self::" for local static member reference. (Found "'.$tokens[$className]['content'].'").';
69+
$phpcsFile->addError($error, $className);
70+
return;
71+
}
72+
} else if ($tokens[$className]['code'] === T_STRING) {
73+
// Make sure this another class ref.
74+
$declarationName = $phpcsFile->getDeclarationName($currScope);
75+
if ($declarationName === $tokens[$className]['content']) {
76+
$error = 'Must use "self::" for local static member reference.';
77+
$phpcsFile->addError($error, $className);
78+
return;
79+
}
80+
} else if ($tokens[$className]['code'] !== T_PARENT) {
81+
$error = 'Cannot have "'.$tokens[$className]['content'].'" between "::" and class name.';
82+
$phpcsFile->addError($error, $className);
83+
return;
84+
}
85+
86+
}//end processTokenWithinScope()
87+
88+
89+
}//end class
90+
91+
?>

0 commit comments

Comments
 (0)