1<?php
2/**
3 * Parses and verifies the class doc comment.
4 *
5 * PHP version 5
6 *
7 * @category  PHP
8 * @package   PHP_CodeSniffer
9 * @author    Greg Sherwood <gsherwood@squiz.net>
10 * @copyright 2006-2014 Squiz Pty Ltd (ABN 77 084 670 600)
11 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
12 * @link      http://pear.php.net/package/PHP_CodeSniffer
13 */
14
15/**
16 * Parses and verifies the class doc comment.
17 *
18 * Verifies that :
19 * <ul>
20 *  <li>A class doc comment exists.</li>
21 *  <li>The comment uses the correct docblock style.</li>
22 *  <li>There are no blank lines after the class comment.</li>
23 *  <li>No tags are used in the docblock.</li>
24 * </ul>
25 *
26 * @category  PHP
27 * @package   PHP_CodeSniffer
28 * @author    Greg Sherwood <gsherwood@squiz.net>
29 * @copyright 2006-2014 Squiz Pty Ltd (ABN 77 084 670 600)
30 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
31 * @version   Release: @package_version@
32 * @link      http://pear.php.net/package/PHP_CodeSniffer
33 */
34class Squiz_Sniffs_Commenting_ClassCommentSniff implements PHP_CodeSniffer_Sniff
35{
36
37
38    /**
39     * Returns an array of tokens this test wants to listen for.
40     *
41     * @return array
42     */
43    public function register()
44    {
45        return array(T_CLASS);
46
47    }//end register()
48
49
50    /**
51     * Processes this test, when one of its tokens is encountered.
52     *
53     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
54     * @param int                  $stackPtr  The position of the current token
55     *                                        in the stack passed in $tokens.
56     *
57     * @return void
58     */
59    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
60    {
61        $tokens = $phpcsFile->getTokens();
62        $find   = PHP_CodeSniffer_Tokens::$methodPrefixes;
63        $find[] = T_WHITESPACE;
64
65        $commentEnd = $phpcsFile->findPrevious($find, ($stackPtr - 1), null, true);
66        if ($tokens[$commentEnd]['code'] !== T_DOC_COMMENT_CLOSE_TAG
67            && $tokens[$commentEnd]['code'] !== T_COMMENT
68        ) {
69            $phpcsFile->addError('Missing class doc comment', $stackPtr, 'Missing');
70            $phpcsFile->recordMetric($stackPtr, 'Class has doc comment', 'no');
71            return;
72        }
73
74        $phpcsFile->recordMetric($stackPtr, 'Class has doc comment', 'yes');
75
76        if ($tokens[$commentEnd]['code'] === T_COMMENT) {
77            $phpcsFile->addError('You must use "/**" style comments for a class comment', $stackPtr, 'WrongStyle');
78            return;
79        }
80
81        if ($tokens[$commentEnd]['line'] !== ($tokens[$stackPtr]['line'] - 1)) {
82            $error = 'There must be no blank lines after the class comment';
83            $phpcsFile->addError($error, $commentEnd, 'SpacingAfter');
84        }
85
86        $commentStart = $tokens[$commentEnd]['comment_opener'];
87        foreach ($tokens[$commentStart]['comment_tags'] as $tag) {
88            $error = '%s tag is not allowed in class comment';
89            $data  = array($tokens[$tag]['content']);
90            $phpcsFile->addWarning($error, $tag, 'TagNotAllowed', $data);
91        }
92
93    }//end process()
94
95
96}//end class
97