diff options
Diffstat (limited to 'build/code_sniffer/phpbb/Sniffs')
-rw-r--r-- | build/code_sniffer/phpbb/Sniffs/Commenting/FileCommentSniff.php | 222 | ||||
-rw-r--r-- | build/code_sniffer/phpbb/Sniffs/Namespaces/UnusedUseSniff.php | 234 |
2 files changed, 456 insertions, 0 deletions
diff --git a/build/code_sniffer/phpbb/Sniffs/Commenting/FileCommentSniff.php b/build/code_sniffer/phpbb/Sniffs/Commenting/FileCommentSniff.php new file mode 100644 index 0000000000..8337cf02ee --- /dev/null +++ b/build/code_sniffer/phpbb/Sniffs/Commenting/FileCommentSniff.php @@ -0,0 +1,222 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +/** +* Checks that each PHP source file contains a valid header as defined by the +* phpBB Coding Guidelines. +* +* @package code_sniffer +* @author Manuel Pichler <mapi@phpundercontrol.org> +*/ +class phpbb_Sniffs_Commenting_FileCommentSniff 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 null + */ + public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) + { + // We are only interested in the first file comment. + if ($stackPtr !== 0) + { + if ($phpcsFile->findPrevious(T_OPEN_TAG, $stackPtr - 1) !== false) + { + return; + } + } + + // Fetch next non whitespace token + $tokens = $phpcsFile->getTokens(); + $start = $phpcsFile->findNext(T_WHITESPACE, $stackPtr + 1, null, true); + + // Skip empty files + if ($tokens[$start]['code'] === T_CLOSE_TAG) + { + return; + } + // Mark as error if this is not a doc comment + else if ($start === false || $tokens[$start]['code'] !== T_DOC_COMMENT) + { + $phpcsFile->addError('Missing required file doc comment.', $stackPtr); + return; + } + + // Find comment end token + $end = $phpcsFile->findNext(T_DOC_COMMENT, $start + 1, null, true) - 1; + + // If there is no end, skip processing here + if ($end === false) + { + return; + } + + // List of found comment tags + $tags = array(); + + // check comment lines without the first(/**) an last(*/) line + for ($i = $start + 1, $c = $end - 1; $i <= $c; ++$i) + { + $line = $tokens[$i]['content']; + + // Check that each line starts with a '*' + if (substr($line, 0, 1) !== '*' && substr($line, 0, 2) !== ' *') + { + $message = 'The file doc comment should not be indented.'; + $phpcsFile->addWarning($message, $i); + } + else if (preg_match('/^[ ]?\*\s+@([\w]+)\s+(.*)$/', $line, $match) !== 0) + { + if (!isset($tags[$match[1]])) + { + $tags[$match[1]] = array(); + } + + $tags[$match[1]][] = array($match[2], $i); + } + } + + // Check that the first and last line is empty + if (trim($tokens[$start + 1]['content']) !== '*') + { + $message = 'The first file comment line should be empty.'; + $phpcsFile->addWarning($message, ($start + 1)); + } + if (trim($tokens[$end - 1]['content']) !== '*') + { + $message = 'The last file comment line should be empty.'; + $phpcsFile->addWarning($message, $end - 1); + } + + //$this->processPackage($phpcsFile, $start, $tags); + //$this->processVersion($phpcsFile, $start, $tags); + $this->processCopyright($phpcsFile, $start, $tags); + $this->processLicense($phpcsFile, $start, $tags); + } + + /** + * Checks that the tags array contains a valid package tag + * + * @param PHP_CodeSniffer_File $phpcsFile The context source file instance. + * @param integer The stack pointer for the first comment token. + * @param array(string=>array) $tags The found file doc comment tags. + * + * @return null + */ + protected function processPackage(PHP_CodeSniffer_File $phpcsFile, $ptr, $tags) + { + if (!isset($tags['package'])) + { + $message = 'Missing require @package tag in file doc comment.'; + $phpcsFile->addError($message, $ptr); + } + else if (preg_match('/^([\w]+)$/', $tags['package'][0]) === 0) + { + $message = 'Invalid content found for @package tag.'; + $phpcsFile->addWarning($message, $tags['package'][1]); + } + } + + /** + * Checks that the tags array contains a valid version tag + * + * @param PHP_CodeSniffer_File $phpcsFile The context source file instance. + * @param integer The stack pointer for the first comment token. + * @param array(string=>array) $tags The found file doc comment tags. + * + * @return null + */ + protected function processVersion(PHP_CodeSniffer_File $phpcsFile, $ptr, $tags) + { + if (!isset($tags['version'])) + { + $message = 'Missing require @version tag in file doc comment.'; + $phpcsFile->addError($message, $ptr); + } + else if (preg_match('/^\$Id:[^\$]+\$$/', $tags['version'][0]) === 0) + { + $message = 'Invalid content found for @version tag, use "$Id: $".'; + $phpcsFile->addError($message, $tags['version'][1]); + } + } + + /** + * Checks that the tags array contains a valid copyright tag + * + * @param PHP_CodeSniffer_File $phpcsFile The context source file instance. + * @param integer The stack pointer for the first comment token. + * @param array(string=>array) $tags The found file doc comment tags. + * + * @return null + */ + protected function processCopyright(PHP_CodeSniffer_File $phpcsFile, $ptr, $tags) + { + $copyright = '(c) phpBB Limited <https://www.phpbb.com>'; + + if (!isset($tags['copyright'])) + { + $message = 'Missing require @copyright tag in file doc comment.'; + $phpcsFile->addError($message, $ptr); + } + else if ($tags['copyright'][0][0] !== $copyright) + { + $message = 'Invalid content found for the first @copyright tag, use "' . $copyright . '".'; + $phpcsFile->addError($message, $tags['copyright'][0][1]); + } + } + + /** + * Checks that the tags array contains a valid license tag + * + * @param PHP_CodeSniffer_File $phpcsFile The context source file instance. + * @param integer The stack pointer for the first comment token. + * @param array(string=>array) $tags The found file doc comment tags. + * + * @return null + */ + protected function processLicense(PHP_CodeSniffer_File $phpcsFile, $ptr, $tags) + { + $license = 'GNU General Public License, version 2 (GPL-2.0)'; + + if (!isset($tags['license'])) + { + $message = 'Missing require @license tag in file doc comment.'; + $phpcsFile->addError($message, $ptr); + } + else if (sizeof($tags['license']) !== 1) + { + $message = 'It must be only one @license tag in file doc comment.'; + $phpcsFile->addError($message, $ptr); + } + else if (trim($tags['license'][0][0]) !== $license) + { + $message = 'Invalid content found for @license tag, use ' + . '"' . $license . '".'; + $phpcsFile->addError($message, $tags['license'][0][1]); + } + } +} diff --git a/build/code_sniffer/phpbb/Sniffs/Namespaces/UnusedUseSniff.php b/build/code_sniffer/phpbb/Sniffs/Namespaces/UnusedUseSniff.php new file mode 100644 index 0000000000..18cb8ba82e --- /dev/null +++ b/build/code_sniffer/phpbb/Sniffs/Namespaces/UnusedUseSniff.php @@ -0,0 +1,234 @@ +<?php +/** +* +* This file is part of the phpBB Forum Software package. +* +* @copyright (c) phpBB Limited <https://www.phpbb.com> +* @license GNU General Public License, version 2 (GPL-2.0) +* +* For full copyright and license information, please see +* the docs/CREDITS.txt file. +* +*/ + +/** +* Checks that each use statement is used. +*/ +class phpbb_Sniffs_Namespaces_UnusedUseSniff implements PHP_CodeSniffer_Sniff +{ + /** + * {@inheritdoc} + */ + public function register() + { + return array(T_USE); + } + + protected function check($phpcsFile, $found_name, $full_name, $short_name, $line) + { + + if ($found_name === $full_name) + { + $error = 'Either use statement or full name must be used.'; + $phpcsFile->addError($error, $line, 'FullName'); + } + + if ($found_name === $short_name) + { + return true; + } + + return false; + } + + /** + * {@inheritdoc} + */ + public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr) + { + if ($this->should_ignore_use($phpcsFile, $stackPtr) === true) + { + return; + } + + $tokens = $phpcsFile->getTokens(); + + $class_name_start = $phpcsFile->findNext(array(T_NS_SEPARATOR, T_STRING), ($stackPtr + 1)); + + $find = array( + T_NS_SEPARATOR, + T_STRING, + T_WHITESPACE, + ); + + $class_name_end = $phpcsFile->findNext($find, ($stackPtr + 1), null, true); + + $aliasing_as_position = $phpcsFile->findNext(T_AS, $class_name_end, null, false, null, true); + if ($aliasing_as_position !== false) + { + $alias_position = $phpcsFile->findNext(T_STRING, $aliasing_as_position, null, false, null, true); + $class_name_short = $tokens[$alias_position]['content']; + $class_name_full = $phpcsFile->getTokensAsString($class_name_start, ($class_name_end - $class_name_start - 1)); + } + else + { + $class_name_full = $phpcsFile->getTokensAsString($class_name_start, ($class_name_end - $class_name_start)); + $class_name_short = $tokens[$class_name_end - 1]['content']; + } + + $ok = false; + + // Checks in simple statements (new, instanceof and extends) + foreach (array(T_INSTANCEOF, T_NEW, T_EXTENDS) as $keyword) + { + $old_simple_statement = $stackPtr; + while (($simple_statement = $phpcsFile->findNext($keyword, ($old_simple_statement + 1))) !== false) + { + $old_simple_statement = $simple_statement; + + $simple_class_name_start = $phpcsFile->findNext(array(T_NS_SEPARATOR, T_STRING), ($simple_statement + 1)); + $simple_class_name_end = $phpcsFile->findNext($find, ($simple_statement + 1), null, true); + + $simple_class_name = trim($phpcsFile->getTokensAsString($simple_class_name_start, ($simple_class_name_end - $simple_class_name_start))); + + $ok = $this->check($phpcsFile, $simple_class_name, $class_name_full, $class_name_short, $simple_statement) ? true : $ok; + } + } + + // Checks paamayim nekudotayim + $old_paamayim_nekudotayim = $stackPtr; + while (($paamayim_nekudotayim = $phpcsFile->findNext(T_PAAMAYIM_NEKUDOTAYIM, ($old_paamayim_nekudotayim + 1))) !== false) + { + $old_paamayim_nekudotayim = $paamayim_nekudotayim; + + $paamayim_nekudotayim_class_name_start = $phpcsFile->findPrevious($find, $paamayim_nekudotayim - 1, null, true); + $paamayim_nekudotayim_class_name_end = $paamayim_nekudotayim - 1; + + $paamayim_nekudotayim_class_name = trim($phpcsFile->getTokensAsString($paamayim_nekudotayim_class_name_start + 1, ($paamayim_nekudotayim_class_name_end - $paamayim_nekudotayim_class_name_start))); + + $ok = $this->check($phpcsFile, $paamayim_nekudotayim_class_name, $class_name_full, $class_name_short, $paamayim_nekudotayim) ? true : $ok; + } + + // Checks in implements + $old_implements = $stackPtr; + while (($implements = $phpcsFile->findNext(T_IMPLEMENTS, ($old_implements + 1))) !== false) + { + $old_implements = $implements; + + $old_implemented_class = $implements; + while (($implemented_class = $phpcsFile->findNext(T_STRING, ($old_implemented_class + 1), null, false, null, true)) !== false) + { + $old_implemented_class = $implemented_class; + + $implements_class_name_start = $phpcsFile->findNext(array(T_NS_SEPARATOR, T_STRING), ($implemented_class - 1)); + $implements_class_name_end = $phpcsFile->findNext($find, ($implemented_class - 1), null, true); + + $implements_class_name = trim($phpcsFile->getTokensAsString($implements_class_name_start, ($implements_class_name_end - $implements_class_name_start))); + + $ok = $this->check($phpcsFile, $implements_class_name, $class_name_full, $class_name_short, $implements) ? true : $ok; + } + } + + // Checks in type hinting + $old_function_declaration = $stackPtr; + while (($function_declaration = $phpcsFile->findNext(T_FUNCTION, ($old_function_declaration + 1))) !== false) + { + $old_function_declaration = $function_declaration; + + // Check docblocks + $find = array( + T_COMMENT, + T_DOC_COMMENT, + T_CLASS, + T_FUNCTION, + T_OPEN_TAG, + ); + + $comment_end = $phpcsFile->findPrevious($find, ($function_declaration - 1)); + if ($comment_end !== false) + { + if (!$tokens[$comment_end]['code'] !== T_DOC_COMMENT) + { + $comment_start = ($phpcsFile->findPrevious(T_DOC_COMMENT, ($comment_end - 1), null, true) + 1); + $comment = $phpcsFile->getTokensAsString($comment_start, ($comment_end - $comment_start + 1)); + + try + { + $comment_parser = new PHP_CodeSniffer_CommentParser_FunctionCommentParser($comment, $phpcsFile); + $comment_parser->parse(); + + // Check @param + foreach ($comment_parser->getParams() as $param) { + $type = $param->getType(); + $types = explode('|', str_replace('[]', '', $type)); + foreach ($types as $type) + { + $ok = $this->check($phpcsFile, $type, $class_name_full, $class_name_short, $param->getLine() + $comment_start) ? true : $ok; + } + } + + // Check @return + $return = $comment_parser->getReturn(); + if ($return !== null) + { + $type = $return->getValue(); + $types = explode('|', str_replace('[]', '', $type)); + foreach ($types as $type) + { + $ok = $this->check($phpcsFile, $type, $class_name_full, $class_name_short, $return->getLine() + $comment_start) ? true : $ok; + } + } + } + catch (PHP_CodeSniffer_CommentParser_ParserException $e) + { + $line = ($e->getLineWithinComment() + $comment_start); + $phpcsFile->addError($e->getMessage(), $line, 'FailedParse'); + } + } + } + + // Check type hint + $params = $phpcsFile->getMethodParameters($function_declaration); + foreach ($params as $param) + { + $ok = $this->check($phpcsFile, $param['type_hint'], $class_name_full, $class_name_short, $function_declaration) ? true : $ok; + } + } + + if (!$ok) + { + $error = 'There must not be unused USE statements.'; + $phpcsFile->addError($error, $stackPtr, 'Unused'); + } + } + + /** + * Check if this use statement is part of the namespace block. + * + * @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 bool + */ + private function should_ignore_use(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 true; + } + + // Ignore USE keywords for traits. + if ($phpcsFile->hasCondition($stackPtr, array(T_CLASS, T_TRAIT)) === true) + { + return true; + } + + return false; + + } +} |