diff options
author | Michal Čihař <mcihar@suse.cz> | 2012-04-26 17:38:34 +0400 |
---|---|---|
committer | Michal Čihař <mcihar@suse.cz> | 2012-04-26 17:38:34 +0400 |
commit | 35711845494c6b02d1549488a99ff4ef937cd5bd (patch) | |
tree | fb5e32094a2cade42898c4891422dbb371554cf0 /PMAStandard/Sniffs/Commenting/ClassCommentSniff.php | |
parent | 76041ce9ca16ff9a5b3c7fe8e05b462a84912ae1 (diff) |
Include PEAR commenting rules
Diffstat (limited to 'PMAStandard/Sniffs/Commenting/ClassCommentSniff.php')
-rw-r--r-- | PMAStandard/Sniffs/Commenting/ClassCommentSniff.php | 233 |
1 files changed, 233 insertions, 0 deletions
diff --git a/PMAStandard/Sniffs/Commenting/ClassCommentSniff.php b/PMAStandard/Sniffs/Commenting/ClassCommentSniff.php new file mode 100644 index 0000000000..0a6249b70e --- /dev/null +++ b/PMAStandard/Sniffs/Commenting/ClassCommentSniff.php @@ -0,0 +1,233 @@ +<?php +/** + * Parses and verifies the doc comments for classes. + * + * PHP version 5 + * + * @category PHP + * @package PHP_CodeSniffer + * @author Greg Sherwood <gsherwood@squiz.net> + * @author Marc McIntyre <mmcintyre@squiz.net> + * @copyright 2006-2011 Squiz Pty Ltd (ABN 77 084 670 600) + * @license http://matrix.squiz.net/developer/tools/php_cs/licence BSD Licence + * @link http://pear.php.net/package/PHP_CodeSniffer + */ + +if (class_exists('PHP_CodeSniffer_CommentParser_ClassCommentParser', true) === false) { + $error = 'Class PHP_CodeSniffer_CommentParser_ClassCommentParser not found'; + throw new PHP_CodeSniffer_Exception($error); +} + +if (class_exists('PEAR_Sniffs_Commenting_FileCommentSniff', true) === false) { + $error = 'Class PEAR_Sniffs_Commenting_FileCommentSniff not found'; + throw new PHP_CodeSniffer_Exception($error); +} + +/** + * Parses and verifies the doc comments for classes. + * + * Verifies that : + * <ul> + * <li>A doc comment exists.</li> + * <li>There is a blank newline after the short description.</li> + * <li>There is a blank newline between the long and short description.</li> + * <li>There is a blank newline between the long description and tags.</li> + * <li>Check the order of the tags.</li> + * <li>Check the indentation of each tag.</li> + * <li>Check required and optional tags and the format of their content.</li> + * </ul> + * + * @category PHP + * @package PHP_CodeSniffer + * @author Greg Sherwood <gsherwood@squiz.net> + * @author Marc McIntyre <mmcintyre@squiz.net> + * @copyright 2006-2011 Squiz Pty Ltd (ABN 77 084 670 600) + * @license http://matrix.squiz.net/developer/tools/php_cs/licence BSD Licence + * @version Release: 1.3.3 + * @link http://pear.php.net/package/PHP_CodeSniffer + */ +class PEAR_Sniffs_Commenting_ClassCommentSniff extends PEAR_Sniffs_Commenting_FileCommentSniff +{ + + + /** + * Returns an array of tokens this test wants to listen for. + * + * @return array + */ + public function register() + { + return array( + T_CLASS, + T_INTERFACE, + ); + + }//end register() + + + /** + * 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) + { + $this->currentFile = $phpcsFile; + + $tokens = $phpcsFile->getTokens(); + $type = strtolower($tokens[$stackPtr]['content']); + $errorData = array($type); + $find = array( + T_ABSTRACT, + T_WHITESPACE, + T_FINAL, + ); + + // Extract the class comment docblock. + $commentEnd = $phpcsFile->findPrevious($find, ($stackPtr - 1), null, true); + + if ($commentEnd !== false && $tokens[$commentEnd]['code'] === T_COMMENT) { + $error = 'You must use "/**" style comments for a %s comment'; + $phpcsFile->addError($error, $stackPtr, 'WrongStyle', $errorData); + return; + } else if ($commentEnd === false + || $tokens[$commentEnd]['code'] !== T_DOC_COMMENT + ) { + $phpcsFile->addError('Missing %s doc comment', $stackPtr, 'Missing', $errorData); + return; + } + + $commentStart = ($phpcsFile->findPrevious(T_DOC_COMMENT, ($commentEnd - 1), null, true) + 1); + $commentNext = $phpcsFile->findPrevious(T_WHITESPACE, ($commentEnd + 1), $stackPtr, false, $phpcsFile->eolChar); + + // Distinguish file and class comment. + $prevClassToken = $phpcsFile->findPrevious(T_CLASS, ($stackPtr - 1)); + if ($prevClassToken === false) { + // This is the first class token in this file, need extra checks. + $prevNonComment = $phpcsFile->findPrevious(T_DOC_COMMENT, ($commentStart - 1), null, true); + if ($prevNonComment !== false) { + $prevComment = $phpcsFile->findPrevious(T_DOC_COMMENT, ($prevNonComment - 1)); + if ($prevComment === false) { + // There is only 1 doc comment between open tag and class token. + $newlineToken = $phpcsFile->findNext(T_WHITESPACE, ($commentEnd + 1), $stackPtr, false, $phpcsFile->eolChar); + if ($newlineToken !== false) { + $newlineToken = $phpcsFile->findNext( + T_WHITESPACE, + ($newlineToken + 1), + $stackPtr, + false, + $phpcsFile->eolChar + ); + + if ($newlineToken !== false) { + // Blank line between the class and the doc block. + // The doc block is most likely a file comment. + $error = 'Missing %s doc comment'; + $phpcsFile->addError($error, ($stackPtr + 1), 'Missing', $errorData); + return; + } + }//end if + }//end if + }//end if + }//end if + + $comment = $phpcsFile->getTokensAsString( + $commentStart, + ($commentEnd - $commentStart + 1) + ); + + // Parse the class comment.docblock. + try { + $this->commentParser = new PHP_CodeSniffer_CommentParser_ClassCommentParser($comment, $phpcsFile); + $this->commentParser->parse(); + } catch (PHP_CodeSniffer_CommentParser_ParserException $e) { + $line = ($e->getLineWithinComment() + $commentStart); + $phpcsFile->addError($e->getMessage(), $line, 'FailedParse'); + return; + } + + $comment = $this->commentParser->getComment(); + if (is_null($comment) === true) { + $error = 'Doc comment is empty for %s'; + $phpcsFile->addError($error, $commentStart, 'Empty', $errorData); + return; + } + + // No extra newline before short description. + $short = $comment->getShortComment(); + $newlineCount = 0; + $newlineSpan = strspn($short, $phpcsFile->eolChar); + if ($short !== '' && $newlineSpan > 0) { + $error = 'Extra newline(s) found before %s comment short description'; + $phpcsFile->addError($error, ($commentStart + 1), 'SpacingBeforeShort', $errorData); + } + + $newlineCount = (substr_count($short, $phpcsFile->eolChar) + 1); + + // Exactly one blank line between short and long description. + $long = $comment->getLongComment(); + if (empty($long) === false) { + $between = $comment->getWhiteSpaceBetween(); + $newlineBetween = substr_count($between, $phpcsFile->eolChar); + if ($newlineBetween !== 2) { + $error = 'There must be exactly one blank line between descriptions in %s comments'; + $phpcsFile->addError($error, ($commentStart + $newlineCount + 1), 'SpacingAfterShort', $errorData); + } + + $newlineCount += $newlineBetween; + } + + // Exactly one blank line before tags. + $tags = $this->commentParser->getTagOrders(); + if (count($tags) > 1) { + $newlineSpan = $comment->getNewlineAfter(); + if ($newlineSpan !== 2) { + $error = 'There must be exactly one blank line before the tags in %s comments'; + if ($long !== '') { + $newlineCount += (substr_count($long, $phpcsFile->eolChar) - $newlineSpan + 1); + } + + $phpcsFile->addError($error, ($commentStart + $newlineCount), 'SpacingBeforeTags', $errorData); + $short = rtrim($short, $phpcsFile->eolChar.' '); + } + } + + // Check each tag. + $this->processTags($commentStart, $commentEnd); + + }//end process() + + + /** + * Process the version tag. + * + * @param int $errorPos The line number where the error occurs. + * + * @return void + */ + protected function processVersion($errorPos) + { + $version = $this->commentParser->getVersion(); + if ($version !== null) { + $content = $version->getContent(); + $matches = array(); + if (empty($content) === true) { + $error = 'Content missing for @version tag in doc comment'; + $this->currentFile->addError($error, $errorPos, 'EmptyVersion'); + } else if ((strstr($content, 'Release:') === false)) { + $error = 'Invalid version "%s" in doc comment; consider "Release: <package_version>" instead'; + $data = array($content); + $this->currentFile->addWarning($error, $errorPos, 'InvalidVersion', $data); + } + } + + }//end processVersion() + + +}//end class + +?> |