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