From bcb9c1bfb489adc59b88b6b2fe1391f8d22685bc Mon Sep 17 00:00:00 2001 From: =?utf8?q?Tim=20D=C3=BCsterhus?= Date: Fri, 4 Jan 2013 17:30:23 +0100 Subject: [PATCH] Check whether imports are correctly ordered Closes #987 --- .../Namespaces/SortedUseDeclarationSniff.php | 95 +++++++++++++++++++ .../Sniffs/Namespaces/UseDeclarationSniff.php | 1 - CodeSniff/WCF/ruleset.xml | 1 + .../LanguageMultilingualismForm.class.php | 4 +- .../acp/form/LanguageServerAddForm.class.php | 2 +- .../acp/form/LanguageServerEditForm.class.php | 2 +- .../files/lib/acp/form/StyleAddForm.class.php | 2 +- .../lib/acp/page/CacheListPage.class.php | 2 +- .../data/acl/option/ACLOptionAction.class.php | 2 +- .../application/ApplicationAction.class.php | 2 +- .../lib/data/category/CategoryNode.class.php | 2 +- .../data/category/CategoryNodeList.class.php | 2 +- .../files/lib/data/option/Option.class.php | 2 +- .../CategoryACLOptionCacheBuilder.class.php | 2 +- .../system/category/CategoryHandler.class.php | 4 +- .../system/version/VersionHandler.class.php | 4 +- 16 files changed, 112 insertions(+), 17 deletions(-) create mode 100644 CodeSniff/WCF/Sniffs/Namespaces/SortedUseDeclarationSniff.php diff --git a/CodeSniff/WCF/Sniffs/Namespaces/SortedUseDeclarationSniff.php b/CodeSniff/WCF/Sniffs/Namespaces/SortedUseDeclarationSniff.php new file mode 100644 index 0000000000..0f9281a9e9 --- /dev/null +++ b/CodeSniff/WCF/Sniffs/Namespaces/SortedUseDeclarationSniff.php @@ -0,0 +1,95 @@ + 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 + * @package com.woltlab.wcf + * @category Community Framework + */ +class WCF_Sniffs_Namespaces_SortedUseDeclarationSniff implements PHP_CodeSniffer_Sniff { + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() { + return array(T_OPEN_TAG); + } + + /** + * 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(); + + $classes = array(); + while (true) { + $stackPtr = $phpcsFile->findNext(T_USE, ($stackPtr + 1)); + if ($stackPtr === false) break; + + // Ignore USE keywords inside closures. + $next = $phpcsFile->findNext(T_WHITESPACE, ($stackPtr + 1), null, true); + if ($tokens[$next]['code'] === T_OPEN_PARENTHESIS) { + break; + } + $start = $phpcsFile->findNext(array(T_NS_SEPARATOR, T_STRING), ($stackPtr + 1)); + $end = $phpcsFile->findNext(array(T_NS_SEPARATOR, T_STRING), ($start + 1), null, true); + $class = ''; + for ($i = $start; $i < $end; $i++) { + $class .= $tokens[$i]['content']; + } + $classes[$stackPtr] = $class; + } + $previous = ''; + foreach ($classes as $stackPtr => $class) { + if ($previous !== '') { + if ($class == $previous) { + $error = 'Using class %s twice;'; + $data = array($class); + $phpcsFile->addError($error, $stackPtr, 'DuplicateUse', $data); + + } + else if (!$this->compare($previous, $class)) { + $error = 'Uses are misordered; check %s and %s'; + $data = array($previous, $class); + $phpcsFile->addError($error, $stackPtr, 'MisorderedUse', $data); + } + } + $previous = $class; + } + } + + public function compare($classA, $classB) { + if ($classA == $classB) return true; + + $classA = explode('\\', $classA); + $classB = explode('\\', $classB); + + for ($i = 0, $max = min(count($classA), count($classB)); $i < $max; $i++) { + if ($classA[$i] == $classB[$i]) { + unset($classA[$i], $classB[$i]); + } + } + $classA = array_values($classA); + $classB = array_values($classB); + + for ($i = 0, $max = min(count($classA), count($classB)); $i < $max; $i++) { + if (ucfirst($classB[$i]) == $classB[$i] && ucfirst($classA[$i]) != $classA[$i]) return true; + if (ucfirst($classB[$i]) != $classB[$i] && ucfirst($classA[$i]) == $classA[$i]) return false; + + if (strcasecmp($classA[$i], $classB[$i]) < 0) { + return true; + } + } + return false; + } +} diff --git a/CodeSniff/WCF/Sniffs/Namespaces/UseDeclarationSniff.php b/CodeSniff/WCF/Sniffs/Namespaces/UseDeclarationSniff.php index b5adfc3045..d9ba6632ed 100644 --- a/CodeSniff/WCF/Sniffs/Namespaces/UseDeclarationSniff.php +++ b/CodeSniff/WCF/Sniffs/Namespaces/UseDeclarationSniff.php @@ -17,7 +17,6 @@ class WCF_Sniffs_Namespaces_UseDeclarationSniff implements PHP_CodeSniffer_Sniff */ public function register() { return array(T_USE); - } /** diff --git a/CodeSniff/WCF/ruleset.xml b/CodeSniff/WCF/ruleset.xml index 4c1e73d580..4794a9cee0 100644 --- a/CodeSniff/WCF/ruleset.xml +++ b/CodeSniff/WCF/ruleset.xml @@ -32,6 +32,7 @@ + diff --git a/wcfsetup/install/files/lib/acp/form/LanguageMultilingualismForm.class.php b/wcfsetup/install/files/lib/acp/form/LanguageMultilingualismForm.class.php index 7c1e326fa3..1ee730f607 100644 --- a/wcfsetup/install/files/lib/acp/form/LanguageMultilingualismForm.class.php +++ b/wcfsetup/install/files/lib/acp/form/LanguageMultilingualismForm.class.php @@ -2,9 +2,9 @@ namespace wcf\acp\form; use wcf\data\language\LanguageEditor; use wcf\form\AbstractForm; -use wcf\system\language\LanguageFactory; -use wcf\system\exception\UserInputException; use wcf\system\cache\CacheHandler; +use wcf\system\exception\UserInputException; +use wcf\system\language\LanguageFactory; use wcf\system\WCF; use wcf\system\WCFACP; use wcf\util\ArrayUtil; diff --git a/wcfsetup/install/files/lib/acp/form/LanguageServerAddForm.class.php b/wcfsetup/install/files/lib/acp/form/LanguageServerAddForm.class.php index bde18715e5..1117c16e36 100644 --- a/wcfsetup/install/files/lib/acp/form/LanguageServerAddForm.class.php +++ b/wcfsetup/install/files/lib/acp/form/LanguageServerAddForm.class.php @@ -3,9 +3,9 @@ namespace wcf\acp\form; use wcf\data\language\server\LanguageServerAction; use wcf\data\package\update\server\PackageUpdateServer; use wcf\form\AbstractForm; +use wcf\system\exception\UserInputException; use wcf\system\WCF; use wcf\system\WCFACP; -use wcf\system\exception\UserInputException; use wcf\util\StringUtil; /** diff --git a/wcfsetup/install/files/lib/acp/form/LanguageServerEditForm.class.php b/wcfsetup/install/files/lib/acp/form/LanguageServerEditForm.class.php index 30f2981a13..2d34d060c7 100644 --- a/wcfsetup/install/files/lib/acp/form/LanguageServerEditForm.class.php +++ b/wcfsetup/install/files/lib/acp/form/LanguageServerEditForm.class.php @@ -3,8 +3,8 @@ namespace wcf\acp\form; use wcf\data\language\server\LanguageServer; use wcf\data\language\server\LanguageServerAction; use wcf\form\AbstractForm; -use wcf\system\WCF; use wcf\system\exception\IllegalLinkException; +use wcf\system\WCF; /** * Shows the language server edit form. diff --git a/wcfsetup/install/files/lib/acp/form/StyleAddForm.class.php b/wcfsetup/install/files/lib/acp/form/StyleAddForm.class.php index 3e76477890..9b188f295a 100644 --- a/wcfsetup/install/files/lib/acp/form/StyleAddForm.class.php +++ b/wcfsetup/install/files/lib/acp/form/StyleAddForm.class.php @@ -1,8 +1,8 @@