1<?php
2/**
3 * Parses and verifies the variable doc comment.
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-2014 Squiz Pty Ltd (ABN 77 084 670 600)
12 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
13 * @link      http://pear.php.net/package/PHP_CodeSniffer
14 */
15
16if (class_exists('PHP_CodeSniffer_Standards_AbstractVariableSniff', true) === false) {
17    throw new PHP_CodeSniffer_Exception('Class PHP_CodeSniffer_Standards_AbstractVariableSniff not found');
18}
19
20/**
21 * Parses and verifies the variable doc comment.
22 *
23 * @category  PHP
24 * @package   PHP_CodeSniffer
25 * @author    Greg Sherwood <gsherwood@squiz.net>
26 * @author    Marc McIntyre <mmcintyre@squiz.net>
27 * @copyright 2006-2014 Squiz Pty Ltd (ABN 77 084 670 600)
28 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
29 * @version   Release: @package_version@
30 * @link      http://pear.php.net/package/PHP_CodeSniffer
31 */
32
33class Squiz_Sniffs_Commenting_VariableCommentSniff extends PHP_CodeSniffer_Standards_AbstractVariableSniff
34{
35
36
37    /**
38     * Called to process class member vars.
39     *
40     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
41     * @param int                  $stackPtr  The position of the current token
42     *                                        in the stack passed in $tokens.
43     *
44     * @return void
45     */
46    public function processMemberVar(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
47    {
48        $tokens = $phpcsFile->getTokens();
49        $ignore = array(
50                   T_PUBLIC,
51                   T_PRIVATE,
52                   T_PROTECTED,
53                   T_VAR,
54                   T_STATIC,
55                   T_WHITESPACE,
56                  );
57
58        $commentEnd = $phpcsFile->findPrevious($ignore, ($stackPtr - 1), null, true);
59        if ($commentEnd === false
60            || ($tokens[$commentEnd]['code'] !== T_DOC_COMMENT_CLOSE_TAG
61            && $tokens[$commentEnd]['code'] !== T_COMMENT)
62        ) {
63            $phpcsFile->addError('Missing member variable doc comment', $stackPtr, 'Missing');
64            return;
65        }
66
67        if ($tokens[$commentEnd]['code'] === T_COMMENT) {
68            $phpcsFile->addError('You must use "/**" style comments for a member variable comment', $stackPtr, 'WrongStyle');
69            return;
70        }
71
72        $commentStart = $tokens[$commentEnd]['comment_opener'];
73
74        $foundVar = null;
75        foreach ($tokens[$commentStart]['comment_tags'] as $tag) {
76            if ($tokens[$tag]['content'] === '@var') {
77                if ($foundVar !== null) {
78                    $error = 'Only one @var tag is allowed in a member variable comment';
79                    $phpcsFile->addError($error, $tag, 'DuplicateVar');
80                } else {
81                    $foundVar = $tag;
82                }
83            } else if ($tokens[$tag]['content'] === '@see') {
84                // Make sure the tag isn't empty.
85                $string = $phpcsFile->findNext(T_DOC_COMMENT_STRING, $tag, $commentEnd);
86                if ($string === false || $tokens[$string]['line'] !== $tokens[$tag]['line']) {
87                    $error = 'Content missing for @see tag in member variable comment';
88                    $phpcsFile->addError($error, $tag, 'EmptySees');
89                }
90            } else {
91                $error = '%s tag is not allowed in member variable comment';
92                $data  = array($tokens[$tag]['content']);
93                $phpcsFile->addWarning($error, $tag, 'TagNotAllowed', $data);
94            }//end if
95        }//end foreach
96
97        // The @var tag is the only one we require.
98        if ($foundVar === null) {
99            $error = 'Missing @var tag in member variable comment';
100            $phpcsFile->addError($error, $commentEnd, 'MissingVar');
101            return;
102        }
103
104        $firstTag = $tokens[$commentStart]['comment_tags'][0];
105        if ($foundVar !== null && $tokens[$firstTag]['content'] !== '@var') {
106            $error = 'The @var tag must be the first tag in a member variable comment';
107            $phpcsFile->addError($error, $foundVar, 'VarOrder');
108        }
109
110        // Make sure the tag isn't empty and has the correct padding.
111        $string = $phpcsFile->findNext(T_DOC_COMMENT_STRING, $foundVar, $commentEnd);
112        if ($string === false || $tokens[$string]['line'] !== $tokens[$foundVar]['line']) {
113            $error = 'Content missing for @var tag in member variable comment';
114            $phpcsFile->addError($error, $foundVar, 'EmptyVar');
115            return;
116        }
117
118        $varType       = $tokens[($foundVar + 2)]['content'];
119        $suggestedType = PHP_CodeSniffer::suggestType($varType);
120        if ($varType !== $suggestedType) {
121            $error = 'Expected "%s" but found "%s" for @var tag in member variable comment';
122            $data  = array(
123                      $suggestedType,
124                      $varType,
125                     );
126
127            $fix = $phpcsFile->addFixableError($error, ($foundVar + 2), 'IncorrectVarType', $data);
128            if ($fix === true) {
129                $phpcsFile->fixer->replaceToken(($foundVar + 2), $suggestedType);
130            }
131        }
132
133    }//end processMemberVar()
134
135
136    /**
137     * Called to process a normal variable.
138     *
139     * Not required for this sniff.
140     *
141     * @param PHP_CodeSniffer_File $phpcsFile The PHP_CodeSniffer file where this token was found.
142     * @param int                  $stackPtr  The position where the double quoted
143     *                                        string was found.
144     *
145     * @return void
146     */
147    protected function processVariable(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
148    {
149
150    }//end processVariable()
151
152
153    /**
154     * Called to process variables found in double quoted strings.
155     *
156     * Not required for this sniff.
157     *
158     * @param PHP_CodeSniffer_File $phpcsFile The PHP_CodeSniffer file where this token was found.
159     * @param int                  $stackPtr  The position where the double quoted
160     *                                        string was found.
161     *
162     * @return void
163     */
164    protected function processVariableInString(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
165    {
166
167    }//end processVariableInString()
168
169
170}//end class
171