Chris@0
|
1 <?php
|
Chris@0
|
2 /**
|
Chris@0
|
3 * Parses and verifies class property doc comments.
|
Chris@0
|
4 *
|
Chris@0
|
5 * @category PHP
|
Chris@0
|
6 * @package PHP_CodeSniffer
|
Chris@0
|
7 * @link http://pear.php.net/package/PHP_CodeSniffer
|
Chris@0
|
8 */
|
Chris@0
|
9
|
Chris@17
|
10 namespace Drupal\Sniffs\Commenting;
|
Chris@17
|
11
|
Chris@17
|
12 use Drupal\Sniffs\Commenting\FunctionCommentSniff;
|
Chris@17
|
13 use PHP_CodeSniffer\Files\File;
|
Chris@17
|
14 use PHP_CodeSniffer\Sniffs\AbstractVariableSniff;
|
Chris@17
|
15 use PHP_CodeSniffer\Util\Tokens;
|
Chris@17
|
16
|
Chris@0
|
17 /**
|
Chris@0
|
18 * Parses and verifies class property doc comments.
|
Chris@0
|
19 *
|
Chris@17
|
20 * Laregely copied from
|
Chris@17
|
21 * \PHP_CodeSniffer\Standards\Squiz\Sniffs\Commenting\VariableCommentSniff.
|
Chris@0
|
22 *
|
Chris@0
|
23 * @category PHP
|
Chris@0
|
24 * @package PHP_CodeSniffer
|
Chris@0
|
25 * @link http://pear.php.net/package/PHP_CodeSniffer
|
Chris@0
|
26 */
|
Chris@17
|
27 class VariableCommentSniff extends AbstractVariableSniff
|
Chris@0
|
28 {
|
Chris@0
|
29
|
Chris@0
|
30
|
Chris@0
|
31 /**
|
Chris@0
|
32 * Called to process class member vars.
|
Chris@0
|
33 *
|
Chris@17
|
34 * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned.
|
Chris@17
|
35 * @param int $stackPtr The position of the current token
|
Chris@17
|
36 * in the stack passed in $tokens.
|
Chris@0
|
37 *
|
Chris@0
|
38 * @return void
|
Chris@0
|
39 */
|
Chris@17
|
40 public function processMemberVar(File $phpcsFile, $stackPtr)
|
Chris@0
|
41 {
|
Chris@0
|
42 $tokens = $phpcsFile->getTokens();
|
Chris@0
|
43 $commentToken = array(
|
Chris@0
|
44 T_COMMENT,
|
Chris@0
|
45 T_DOC_COMMENT_CLOSE_TAG,
|
Chris@0
|
46 );
|
Chris@0
|
47
|
Chris@0
|
48 $commentEnd = $phpcsFile->findPrevious($commentToken, $stackPtr);
|
Chris@0
|
49 if ($commentEnd === false) {
|
Chris@0
|
50 return;
|
Chris@0
|
51 }
|
Chris@0
|
52
|
Chris@0
|
53 if ($tokens[$commentEnd]['code'] === T_COMMENT) {
|
Chris@0
|
54 $fix = $phpcsFile->addFixableError('You must use "/**" style comments for a member variable comment', $stackPtr, 'WrongStyle');
|
Chris@0
|
55 if ($fix === true) {
|
Chris@0
|
56 // Convert the comment into a doc comment.
|
Chris@0
|
57 $phpcsFile->fixer->beginChangeset();
|
Chris@0
|
58 $comment = '';
|
Chris@0
|
59 for ($i = $commentEnd; $tokens[$i]['code'] === T_COMMENT; $i--) {
|
Chris@0
|
60 $comment = ' *'.ltrim($tokens[$i]['content'], '/* ').$comment;
|
Chris@0
|
61 $phpcsFile->fixer->replaceToken($i, '');
|
Chris@0
|
62 }
|
Chris@0
|
63
|
Chris@0
|
64 $phpcsFile->fixer->replaceToken($commentEnd, "/**\n".rtrim($comment, "*/\n")."\n */\n");
|
Chris@0
|
65 $phpcsFile->fixer->endChangeset();
|
Chris@0
|
66 }
|
Chris@0
|
67
|
Chris@0
|
68 return;
|
Chris@0
|
69 } else if ($tokens[$commentEnd]['code'] !== T_DOC_COMMENT_CLOSE_TAG) {
|
Chris@0
|
70 return;
|
Chris@0
|
71 } else {
|
Chris@0
|
72 // Make sure the comment we have found belongs to us.
|
Chris@0
|
73 $commentFor = $phpcsFile->findNext(array(T_VARIABLE, T_CLASS, T_INTERFACE), ($commentEnd + 1));
|
Chris@0
|
74 if ($commentFor !== $stackPtr) {
|
Chris@0
|
75 return;
|
Chris@0
|
76 }
|
Chris@0
|
77 }//end if
|
Chris@0
|
78
|
Chris@0
|
79 $commentStart = $tokens[$commentEnd]['comment_opener'];
|
Chris@0
|
80
|
Chris@0
|
81 $commentContent = $phpcsFile->getTokensAsString($commentStart, ($commentEnd - $commentStart));
|
Chris@0
|
82 if (strpos($commentContent, '{@inheritdoc}') !== false) {
|
Chris@0
|
83 return;
|
Chris@0
|
84 }
|
Chris@0
|
85
|
Chris@0
|
86 $foundVar = null;
|
Chris@0
|
87 foreach ($tokens[$commentStart]['comment_tags'] as $tag) {
|
Chris@0
|
88 if ($tokens[$tag]['content'] === '@var') {
|
Chris@0
|
89 if ($foundVar !== null) {
|
Chris@0
|
90 $error = 'Only one @var tag is allowed in a member variable comment';
|
Chris@0
|
91 $phpcsFile->addError($error, $tag, 'DuplicateVar');
|
Chris@0
|
92 } else {
|
Chris@0
|
93 $foundVar = $tag;
|
Chris@0
|
94 }
|
Chris@0
|
95 } else if ($tokens[$tag]['content'] === '@see') {
|
Chris@0
|
96 // Make sure the tag isn't empty.
|
Chris@0
|
97 $string = $phpcsFile->findNext(T_DOC_COMMENT_STRING, $tag, $commentEnd);
|
Chris@0
|
98 if ($string === false || $tokens[$string]['line'] !== $tokens[$tag]['line']) {
|
Chris@0
|
99 $error = 'Content missing for @see tag in member variable comment';
|
Chris@0
|
100 $phpcsFile->addError($error, $tag, 'EmptySees');
|
Chris@0
|
101 }
|
Chris@0
|
102 }//end if
|
Chris@0
|
103 }//end foreach
|
Chris@0
|
104
|
Chris@0
|
105 // The @var tag is the only one we require.
|
Chris@0
|
106 if ($foundVar === null) {
|
Chris@0
|
107 $error = 'Missing @var tag in member variable comment';
|
Chris@0
|
108 $phpcsFile->addError($error, $commentEnd, 'MissingVar');
|
Chris@0
|
109 return;
|
Chris@0
|
110 }
|
Chris@0
|
111
|
Chris@0
|
112 $firstTag = $tokens[$commentStart]['comment_tags'][0];
|
Chris@0
|
113 if ($foundVar !== null && $tokens[$firstTag]['content'] !== '@var') {
|
Chris@0
|
114 $error = 'The @var tag must be the first tag in a member variable comment';
|
Chris@0
|
115 $phpcsFile->addError($error, $foundVar, 'VarOrder');
|
Chris@0
|
116 }
|
Chris@0
|
117
|
Chris@0
|
118 // Make sure the tag isn't empty and has the correct padding.
|
Chris@0
|
119 $string = $phpcsFile->findNext(T_DOC_COMMENT_STRING, $foundVar, $commentEnd);
|
Chris@0
|
120 if ($string === false || $tokens[$string]['line'] !== $tokens[$foundVar]['line']) {
|
Chris@0
|
121 $error = 'Content missing for @var tag in member variable comment';
|
Chris@0
|
122 $phpcsFile->addError($error, $foundVar, 'EmptyVar');
|
Chris@0
|
123 return;
|
Chris@0
|
124 }
|
Chris@0
|
125
|
Chris@0
|
126 $varType = $tokens[($foundVar + 2)]['content'];
|
Chris@0
|
127
|
Chris@0
|
128 // There may be multiple types separated by pipes.
|
Chris@0
|
129 $suggestedTypes = array();
|
Chris@0
|
130 foreach (explode('|', $varType) as $type) {
|
Chris@17
|
131 $suggestedTypes[] = FunctionCommentSniff::suggestType($type);
|
Chris@0
|
132 }
|
Chris@0
|
133
|
Chris@0
|
134 $suggestedType = implode('|', $suggestedTypes);
|
Chris@0
|
135
|
Chris@0
|
136 // Detect and auto-fix the common mistake that the variable name is
|
Chris@0
|
137 // appended to the type declaration.
|
Chris@0
|
138 $matches = array();
|
Chris@0
|
139 if (preg_match('/^([^\s]+)(\s+\$.+)$/', $varType, $matches) === 1) {
|
Chris@0
|
140 $error = 'Do not append variable name "%s" to the type declaration in a member variable comment';
|
Chris@0
|
141 $data = array(
|
Chris@0
|
142 trim($matches[2]),
|
Chris@0
|
143 );
|
Chris@0
|
144 $fix = $phpcsFile->addFixableError($error, ($foundVar + 2), 'InlineVariableName', $data);
|
Chris@0
|
145 if ($fix === true) {
|
Chris@0
|
146 $phpcsFile->fixer->replaceToken(($foundVar + 2), $matches[1]);
|
Chris@0
|
147 }
|
Chris@0
|
148 } else if ($varType !== $suggestedType) {
|
Chris@0
|
149 $error = 'Expected "%s" but found "%s" for @var tag in member variable comment';
|
Chris@0
|
150 $data = array(
|
Chris@0
|
151 $suggestedType,
|
Chris@0
|
152 $varType,
|
Chris@0
|
153 );
|
Chris@0
|
154 $fix = $phpcsFile->addFixableError($error, ($foundVar + 2), 'IncorrectVarType', $data);
|
Chris@0
|
155 if ($fix === true) {
|
Chris@0
|
156 $phpcsFile->fixer->replaceToken(($foundVar + 2), $suggestedType);
|
Chris@0
|
157 }
|
Chris@0
|
158 }//end if
|
Chris@0
|
159
|
Chris@0
|
160 }//end processMemberVar()
|
Chris@0
|
161
|
Chris@0
|
162
|
Chris@0
|
163 /**
|
Chris@0
|
164 * Called to process a normal variable.
|
Chris@0
|
165 *
|
Chris@0
|
166 * Not required for this sniff.
|
Chris@0
|
167 *
|
Chris@17
|
168 * @param \PHP_CodeSniffer\Files\File $phpcsFile The PHP_CodeSniffer file where this token was found.
|
Chris@17
|
169 * @param int $stackPtr The position where the double quoted
|
Chris@17
|
170 * string was found.
|
Chris@0
|
171 *
|
Chris@0
|
172 * @return void
|
Chris@0
|
173 */
|
Chris@17
|
174 protected function processVariable(File $phpcsFile, $stackPtr)
|
Chris@0
|
175 {
|
Chris@0
|
176
|
Chris@0
|
177 }//end processVariable()
|
Chris@0
|
178
|
Chris@0
|
179
|
Chris@0
|
180 /**
|
Chris@0
|
181 * Called to process variables found in double quoted strings.
|
Chris@0
|
182 *
|
Chris@0
|
183 * Not required for this sniff.
|
Chris@0
|
184 *
|
Chris@17
|
185 * @param \PHP_CodeSniffer\Files\File $phpcsFile The PHP_CodeSniffer file where this token was found.
|
Chris@17
|
186 * @param int $stackPtr The position where the double quoted
|
Chris@17
|
187 * string was found.
|
Chris@0
|
188 *
|
Chris@0
|
189 * @return void
|
Chris@0
|
190 */
|
Chris@17
|
191 protected function processVariableInString(File $phpcsFile, $stackPtr)
|
Chris@0
|
192 {
|
Chris@0
|
193
|
Chris@0
|
194 }//end processVariableInString()
|
Chris@0
|
195
|
Chris@0
|
196
|
Chris@0
|
197 }//end class
|