Validate declaration of use
authorTim Düsterhus <duesterhus@woltlab.com>
Fri, 4 Jan 2013 15:03:24 +0000 (16:03 +0100)
committerTim Düsterhus <duesterhus@woltlab.com>
Fri, 4 Jan 2013 15:03:24 +0000 (16:03 +0100)
CodeSniff/WCF/Sniffs/Namespaces/UseDeclarationSniff.php [new file with mode: 0644]
CodeSniff/WCF/ruleset.xml

diff --git a/CodeSniff/WCF/Sniffs/Namespaces/UseDeclarationSniff.php b/CodeSniff/WCF/Sniffs/Namespaces/UseDeclarationSniff.php
new file mode 100644 (file)
index 0000000..38c47fc
--- /dev/null
@@ -0,0 +1,85 @@
+<?php
+/**
+ * This sniff is based on Squiz_Sniffs_Classes_ClassFileNameSniff. Originally written
+ * by Greg Sherwood <gsherwood@squiz.net> and released under the terms of the BSD Licence.
+ * See: https://github.com/squizlabs/PHP_CodeSniffer/blob/master/CodeSniffer/Standards/PSR2/Sniffs/Namespaces/UseDeclarationSniff.php
+ * 
+ * @author     Tim Duesterhus
+ * @license    BSD Licence <https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt>
+ * @package    com.woltlab.wcf
+ * @category   Community Framework
+ */
+class WCF_Sniffs_Namespaces_UseDeclarationSniff implements PHP_CodeSniffer_Sniff {
+       /**
+        * Returns an array of tokens this test wants to listen for.
+        *
+        * @return array
+        */
+       public function register() {
+               return array(T_USE);
+
+       }
+
+       /**
+        * Processes this test, when one of its tokens is encountered.
+        *
+        * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
+        * @param int                             $stackPtr  The position of the current token in
+        *                                                                              the stack passed in $tokens.
+        *
+        * @return void
+        */
+       public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) {
+               $tokens = $phpcsFile->getTokens();
+               
+               // Ignore USE keywords inside closures.
+               $next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true);
+               if ($tokens[$next]['code'] === T_OPEN_PARENTHESIS) {
+                       return;
+               }
+               
+               // Only one USE declaration allowed per statement.
+               $next = $phpcsFile->findNext(array(T_COMMA, T_SEMICOLON), ($stackPtr + 1));
+               if ($tokens[$next]['code'] === T_COMMA) {
+                       $error = 'There must be one USE keyword per declaration';
+                       $phpcsFile->addError($error, $stackPtr, 'MultipleDeclarations');
+               }
+               
+               // Leading NS_SEPARATOR must be omitted
+               $next = $phpcsFile->findNext(array(T_NS_SEPARATOR, T_STRING), ($stackPtr + 1));
+               if ($tokens[$next]['code'] === T_NS_SEPARATOR) {
+                       $error = 'Leading backslash must be omitted.';
+                       $phpcsFile->addError($error, $stackPtr, 'LeadingNSSeparator');
+               }
+               
+               // Make sure this USE comes after the first namespace declaration.
+               $prev = $phpcsFile->findPrevious(T_NAMESPACE, ($stackPtr - 1));
+               if ($prev !== false) {
+                       $first = $phpcsFile->findNext(T_NAMESPACE, 1);
+                       if ($prev !== $first) {
+                               $error = 'USE declarations must go after the first namespace declaration';
+                               $phpcsFile->addError($error, $stackPtr, 'UseAfterNamespace');
+                       }
+               }
+               
+               // Only interested in the last USE statement from here onwards.
+               $nextUse = $phpcsFile->findNext(T_USE, ($stackPtr + 1));
+               if ($nextUse !== false) {
+                       return;
+               }
+               
+               $end  = $phpcsFile->findNext(T_SEMICOLON, ($stackPtr + 1));
+               $next = $phpcsFile->findNext(T_WHITESPACE, ($end + 1), null, true);
+               $diff = ($tokens[$next]['line'] - $tokens[$end]['line'] - 1);
+               if ($diff !== 1) {
+                       if ($diff < 0) {
+                               $diff = 0;
+                       }
+                       
+                       $error = 'There must be one blank line after the last USE statement; %s found;';
+                       $data  = array($diff);
+                       $phpcsFile->addError($error, $stackPtr, 'SpaceAfterLastUse', $data);
+               }
+       
+       }
+}
index 4bd6de83d82b4f7e4a8e52b2110fb7bdc146fac6..8d6a7820ce22ca4a9a955e29236ff4469d855f6b 100644 (file)
@@ -31,6 +31,7 @@
        <rule ref="Squiz.PHP.ForbiddenFunctions" />
        <rule ref="WCF.Classes.ClassFileName" />
        <rule ref="WCF.ControlStructures.ControlSignature" />
+       <rule ref="WCF.Namespaces.UseDeclaration" />
        <rule ref="WCF.WhiteSpace.SuperfluousWhitespace" />
        <rule ref="Zend.Files.ClosingTag" />