PageRenderTime 43ms CodeModel.GetById 15ms RepoModel.GetById 0ms app.codeStats 0ms

/share/pear/PHP/CodeSniffer/Standards_Backup/PEAR/Sniffs/Commenting/ClassCommentSniff.php

https://github.com/amumu/modev
PHP | 233 lines | 133 code | 31 blank | 69 comment | 25 complexity | f3c8e4e43daff3c9ebc5eb9a267a1789 MD5 | raw file
  1. <?php
  2. /**
  3. * Parses and verifies the doc comments for classes.
  4. *
  5. * PHP version 5
  6. *
  7. * @category PHP
  8. * @package PHP_CodeSniffer
  9. * @author Greg Sherwood <gsherwood@squiz.net>
  10. * @author Marc McIntyre <mmcintyre@squiz.net>
  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: ClassCommentSniff.php 270281 2008-12-02 02:38:34Z squiz $
  14. * @link http://pear.php.net/package/PHP_CodeSniffer
  15. */
  16. if (class_exists('PHP_CodeSniffer_CommentParser_ClassCommentParser', true) === false) {
  17. $error = 'Class PHP_CodeSniffer_CommentParser_ClassCommentParser not found';
  18. throw new PHP_CodeSniffer_Exception($error);
  19. }
  20. if (class_exists('PEAR_Sniffs_Commenting_FileCommentSniff', true) === false) {
  21. $error = 'Class PEAR_Sniffs_Commenting_FileCommentSniff not found';
  22. throw new PHP_CodeSniffer_Exception($error);
  23. }
  24. /**
  25. * Parses and verifies the doc comments for classes.
  26. *
  27. * Verifies that :
  28. * <ul>
  29. * <li>A doc comment exists.</li>
  30. * <li>There is a blank newline after the short description.</li>
  31. * <li>There is a blank newline between the long and short description.</li>
  32. * <li>There is a blank newline between the long description and tags.</li>
  33. * <li>Check the order of the tags.</li>
  34. * <li>Check the indentation of each tag.</li>
  35. * <li>Check required and optional tags and the format of their content.</li>
  36. * </ul>
  37. *
  38. * @category PHP
  39. * @package PHP_CodeSniffer
  40. * @author Greg Sherwood <gsherwood@squiz.net>
  41. * @author Marc McIntyre <mmcintyre@squiz.net>
  42. * @copyright 2006 Squiz Pty Ltd (ABN 77 084 670 600)
  43. * @license http://matrix.squiz.net/developer/tools/php_cs/licence BSD Licence
  44. * @version Release: 1.2.2
  45. * @link http://pear.php.net/package/PHP_CodeSniffer
  46. */
  47. class PEAR_Sniffs_Commenting_ClassCommentSniff extends PEAR_Sniffs_Commenting_FileCommentSniff
  48. {
  49. /**
  50. * Returns an array of tokens this test wants to listen for.
  51. *
  52. * @return array
  53. */
  54. public function register()
  55. {
  56. return array(
  57. T_CLASS,
  58. T_INTERFACE,
  59. );
  60. }//end register()
  61. /**
  62. * Processes this test, when one of its tokens is encountered.
  63. *
  64. * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
  65. * @param int $stackPtr The position of the current token
  66. * in the stack passed in $tokens.
  67. *
  68. * @return void
  69. */
  70. public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
  71. {
  72. $this->currentFile = $phpcsFile;
  73. $tokens = $phpcsFile->getTokens();
  74. $type = strtolower($tokens[$stackPtr]['content']);
  75. $find = array(
  76. T_ABSTRACT,
  77. T_WHITESPACE,
  78. T_FINAL,
  79. );
  80. // Extract the class comment docblock.
  81. $commentEnd = $phpcsFile->findPrevious($find, ($stackPtr - 1), null, true);
  82. if ($commentEnd !== false && $tokens[$commentEnd]['code'] === T_COMMENT) {
  83. $error = "You must use \"/**\" style comments for a $type comment";
  84. $phpcsFile->addError($error, $stackPtr);
  85. return;
  86. } else if ($commentEnd === false
  87. || $tokens[$commentEnd]['code'] !== T_DOC_COMMENT
  88. ) {
  89. $phpcsFile->addError("Missing $type doc comment", $stackPtr);
  90. return;
  91. }
  92. $commentStart = ($phpcsFile->findPrevious(T_DOC_COMMENT, ($commentEnd - 1), null, true) + 1);
  93. $commentNext = $phpcsFile->findPrevious(T_WHITESPACE, ($commentEnd + 1), $stackPtr, false, $phpcsFile->eolChar);
  94. // Distinguish file and class comment.
  95. $prevClassToken = $phpcsFile->findPrevious(T_CLASS, ($stackPtr - 1));
  96. if ($prevClassToken === false) {
  97. // This is the first class token in this file, need extra checks.
  98. $prevNonComment = $phpcsFile->findPrevious(T_DOC_COMMENT, ($commentStart - 1), null, true);
  99. if ($prevNonComment !== false) {
  100. $prevComment = $phpcsFile->findPrevious(T_DOC_COMMENT, ($prevNonComment - 1));
  101. if ($prevComment === false) {
  102. // There is only 1 doc comment between open tag and class token.
  103. $newlineToken = $phpcsFile->findNext(T_WHITESPACE, ($commentEnd + 1), $stackPtr, false, $phpcsFile->eolChar);
  104. if ($newlineToken !== false) {
  105. $newlineToken = $phpcsFile->findNext(
  106. T_WHITESPACE,
  107. ($newlineToken + 1),
  108. $stackPtr,
  109. false,
  110. $phpcsFile->eolChar
  111. );
  112. if ($newlineToken !== false) {
  113. // Blank line between the class and the doc block.
  114. // The doc block is most likely a file comment.
  115. $error = "Missing $type doc comment";
  116. $phpcsFile->addError($error, ($stackPtr + 1));
  117. return;
  118. }
  119. }//end if
  120. }//end if
  121. }//end if
  122. }//end if
  123. $comment = $phpcsFile->getTokensAsString(
  124. $commentStart,
  125. ($commentEnd - $commentStart + 1)
  126. );
  127. // Parse the class comment.docblock.
  128. try {
  129. $this->commentParser = new PHP_CodeSniffer_CommentParser_ClassCommentParser($comment, $phpcsFile);
  130. $this->commentParser->parse();
  131. } catch (PHP_CodeSniffer_CommentParser_ParserException $e) {
  132. $line = ($e->getLineWithinComment() + $commentStart);
  133. $phpcsFile->addError($e->getMessage(), $line);
  134. return;
  135. }
  136. $comment = $this->commentParser->getComment();
  137. if (is_null($comment) === true) {
  138. $error = ucfirst($type).' doc comment is empty';
  139. $phpcsFile->addError($error, $commentStart);
  140. return;
  141. }
  142. // No extra newline before short description.
  143. $short = $comment->getShortComment();
  144. $newlineCount = 0;
  145. $newlineSpan = strspn($short, $phpcsFile->eolChar);
  146. if ($short !== '' && $newlineSpan > 0) {
  147. $line = ($newlineSpan > 1) ? 'newlines' : 'newline';
  148. $error = "Extra $line found before $type comment short description";
  149. $phpcsFile->addError($error, ($commentStart + 1));
  150. }
  151. $newlineCount = (substr_count($short, $phpcsFile->eolChar) + 1);
  152. // Exactly one blank line between short and long description.
  153. $long = $comment->getLongComment();
  154. if (empty($long) === false) {
  155. $between = $comment->getWhiteSpaceBetween();
  156. $newlineBetween = substr_count($between, $phpcsFile->eolChar);
  157. if ($newlineBetween !== 2) {
  158. $error = "There must be exactly one blank line between descriptions in $type comments";
  159. $phpcsFile->addError($error, ($commentStart + $newlineCount + 1));
  160. }
  161. $newlineCount += $newlineBetween;
  162. }
  163. // Exactly one blank line before tags.
  164. $tags = $this->commentParser->getTagOrders();
  165. if (count($tags) > 1) {
  166. $newlineSpan = $comment->getNewlineAfter();
  167. if ($newlineSpan !== 2) {
  168. $error = "There must be exactly one blank line before the tags in $type comments";
  169. if ($long !== '') {
  170. $newlineCount += (substr_count($long, $phpcsFile->eolChar) - $newlineSpan + 1);
  171. }
  172. $phpcsFile->addError($error, ($commentStart + $newlineCount));
  173. $short = rtrim($short, $phpcsFile->eolChar.' ');
  174. }
  175. }
  176. // Check each tag.
  177. $this->processTags($commentStart, $commentEnd);
  178. }//end process()
  179. /**
  180. * Process the version tag.
  181. *
  182. * @param int $errorPos The line number where the error occurs.
  183. *
  184. * @return void
  185. */
  186. protected function processVersion($errorPos)
  187. {
  188. $version = $this->commentParser->getVersion();
  189. if ($version !== null) {
  190. $content = $version->getContent();
  191. $matches = array();
  192. if (empty($content) === true) {
  193. $error = 'Content missing for @version tag in doc comment';
  194. $this->currentFile->addError($error, $errorPos);
  195. } else if ((strstr($content, 'Release:') === false)) {
  196. $error = "Invalid version \"$content\" in doc comment; consider \"Release: <package_version>\" instead";
  197. $this->currentFile->addWarning($error, $errorPos);
  198. }
  199. }
  200. }//end processVersion()
  201. }//end class
  202. ?>