~ubuntu-branches/ubuntu/utopic/php-codesniffer/utopic-proposed

« back to all changes in this revision

Viewing changes to PHP_CodeSniffer-1.5.0RC2/CodeSniffer/Standards/Squiz/Sniffs/Commenting/VariableCommentSniff.php

  • Committer: Package Import Robot
  • Author(s): David Prévot
  • Date: 2014-07-21 14:42:41 UTC
  • mfrom: (1.1.4)
  • Revision ID: package-import@ubuntu.com-20140721144241-g4orlcuk4jzn9mhs
Tags: 1.5.3-1
* Team upload
* Focus on stable release
* Update copyright
* Bump standards version to 3.9.5
* Update Homepage
* Use ${phppear:…} instead of hardcoding them
* Run tests in dh_auto_test
* Update patch with gbp pq
* Simplify configuration installation
* Edit package.xml to move script
* Add DEP-8 tests

Show diffs side-by-side

added added

removed removed

Lines of Context:
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-2012 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
 
 
16
 
if (class_exists('PHP_CodeSniffer_Standards_AbstractVariableSniff', true) === false) {
17
 
    throw new PHP_CodeSniffer_Exception('Class PHP_CodeSniffer_Standards_AbstractVariableSniff not found');
18
 
}
19
 
 
20
 
if (class_exists('PHP_CodeSniffer_CommentParser_MemberCommentParser', true) === false) {
21
 
    throw new PHP_CodeSniffer_Exception('Class PHP_CodeSniffer_CommentParser_MemberCommentParser not found');
22
 
}
23
 
 
24
 
/**
25
 
 * Parses and verifies the variable doc comment.
26
 
 *
27
 
 * Verifies that :
28
 
 * <ul>
29
 
 *  <li>A variable doc comment exists.</li>
30
 
 *  <li>Short description ends with a full stop.</li>
31
 
 *  <li>There is a blank line after the short description.</li>
32
 
 *  <li>There is a blank line between the description and the tags.</li>
33
 
 *  <li>Check the order, indentation and content of each tag.</li>
34
 
 * </ul>
35
 
 *
36
 
 * @category  PHP
37
 
 * @package   PHP_CodeSniffer
38
 
 * @author    Greg Sherwood <gsherwood@squiz.net>
39
 
 * @author    Marc McIntyre <mmcintyre@squiz.net>
40
 
 * @copyright 2006-2012 Squiz Pty Ltd (ABN 77 084 670 600)
41
 
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
42
 
 * @version   Release: 1.5.0RC2
43
 
 * @link      http://pear.php.net/package/PHP_CodeSniffer
44
 
 */
45
 
 
46
 
class Squiz_Sniffs_Commenting_VariableCommentSniff extends PHP_CodeSniffer_Standards_AbstractVariableSniff
47
 
{
48
 
 
49
 
    /**
50
 
     * The header comment parser for the current file.
51
 
     *
52
 
     * @var PHP_CodeSniffer_Comment_Parser_ClassCommentParser
53
 
     */
54
 
    protected $commentParser = null;
55
 
 
56
 
 
57
 
    /**
58
 
     * Called to process class member vars.
59
 
     *
60
 
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
61
 
     * @param int                  $stackPtr  The position of the current token
62
 
     *                                        in the stack passed in $tokens.
63
 
     *
64
 
     * @return void
65
 
     */
66
 
    public function processMemberVar(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
67
 
    {
68
 
        $this->currentFile = $phpcsFile;
69
 
        $tokens            = $phpcsFile->getTokens();
70
 
        $commentToken      = array(
71
 
                              T_COMMENT,
72
 
                              T_DOC_COMMENT,
73
 
                             );
74
 
 
75
 
        // Extract the var comment docblock.
76
 
        $commentEnd = $phpcsFile->findPrevious($commentToken, ($stackPtr - 3));
77
 
        if ($commentEnd !== false && $tokens[$commentEnd]['code'] === T_COMMENT) {
78
 
            $phpcsFile->addError('You must use "/**" style comments for a variable comment', $stackPtr, 'WrongStyle');
79
 
            return;
80
 
        } else if ($commentEnd === false || $tokens[$commentEnd]['code'] !== T_DOC_COMMENT) {
81
 
            $phpcsFile->addError('Missing variable doc comment', $stackPtr, 'Missing');
82
 
            return;
83
 
        } else {
84
 
            // Make sure the comment we have found belongs to us.
85
 
            $commentFor = $phpcsFile->findNext(array(T_VARIABLE, T_CLASS, T_INTERFACE), ($commentEnd + 1));
86
 
            if ($commentFor !== $stackPtr) {
87
 
                $phpcsFile->addError('Missing variable doc comment', $stackPtr, 'Missing');
88
 
                return;
89
 
            }
90
 
        }
91
 
 
92
 
        $commentStart  = ($phpcsFile->findPrevious(T_DOC_COMMENT, ($commentEnd - 1), null, true) + 1);
93
 
        $commentString = $phpcsFile->getTokensAsString($commentStart, ($commentEnd - $commentStart + 1));
94
 
 
95
 
        // Parse the header comment docblock.
96
 
        try {
97
 
            $this->commentParser = new PHP_CodeSniffer_CommentParser_MemberCommentParser($commentString, $phpcsFile);
98
 
            $this->commentParser->parse();
99
 
        } catch (PHP_CodeSniffer_CommentParser_ParserException $e) {
100
 
            $line = ($e->getLineWithinComment() + $commentStart);
101
 
            $phpcsFile->addError($e->getMessage(), $line, 'ErrorParsing');
102
 
            return;
103
 
        }
104
 
 
105
 
        $comment = $this->commentParser->getComment();
106
 
        if (is_null($comment) === true) {
107
 
            $error = 'Variable doc comment is empty';
108
 
            $phpcsFile->addError($error, $commentStart, 'Empty');
109
 
            return;
110
 
        }
111
 
 
112
 
        // The first line of the comment should just be the /** code.
113
 
        $eolPos    = strpos($commentString, $phpcsFile->eolChar);
114
 
        $firstLine = substr($commentString, 0, $eolPos);
115
 
        if ($firstLine !== '/**') {
116
 
            $error = 'The open comment tag must be the only content on the line';
117
 
            $phpcsFile->addError($error, $commentStart, 'ContentAfterOpen');
118
 
        }
119
 
 
120
 
        // Check for a comment description.
121
 
        $short = $comment->getShortComment();
122
 
        $long  = '';
123
 
        if (trim($short) === '') {
124
 
            $error = 'Missing short description in variable doc comment';
125
 
            $phpcsFile->addError($error, $commentStart, 'MissingShort');
126
 
            $newlineCount = 1;
127
 
        } else {
128
 
            // No extra newline before short description.
129
 
            $newlineCount = 0;
130
 
            $newlineSpan  = strspn($short, $phpcsFile->eolChar);
131
 
            if ($short !== '' && $newlineSpan > 0) {
132
 
                $error = 'Extra newline(s) found before variable comment short description';
133
 
                $phpcsFile->addError($error, ($commentStart + 1), 'SpacingBeforeShort');
134
 
            }
135
 
 
136
 
            $newlineCount = (substr_count($short, $phpcsFile->eolChar) + 1);
137
 
 
138
 
            // Exactly one blank line between short and long description.
139
 
            $long = $comment->getLongComment();
140
 
            if (empty($long) === false) {
141
 
                $between        = $comment->getWhiteSpaceBetween();
142
 
                $newlineBetween = substr_count($between, $phpcsFile->eolChar);
143
 
                if ($newlineBetween !== 2) {
144
 
                    $error = 'There must be exactly one blank line between descriptions in variable comment';
145
 
                    $phpcsFile->addError($error, ($commentStart + $newlineCount + 1), 'SpacingBetween');
146
 
                }
147
 
 
148
 
                $newlineCount += $newlineBetween;
149
 
 
150
 
                $testLong = trim($long);
151
 
                if (preg_match('|\p{Lu}|u', $testLong[0]) === 0) {
152
 
                    $error = 'Variable comment long description must start with a capital letter';
153
 
                    $phpcsFile->addError($error, ($commentStart + $newlineCount), 'LongNotCapital');
154
 
                }
155
 
            }//end if
156
 
 
157
 
            // Short description must be single line and end with a full stop.
158
 
            $testShort = trim($short);
159
 
            $lastChar  = $testShort[(strlen($testShort) - 1)];
160
 
            if (substr_count($testShort, $phpcsFile->eolChar) !== 0) {
161
 
                $error = 'Variable comment short description must be on a single line';
162
 
                $phpcsFile->addError($error, ($commentStart + 1), 'ShortSingleLine');
163
 
            }
164
 
 
165
 
            if (preg_match('|\p{Lu}|u', $testShort[0]) === 0) {
166
 
                $error = 'Variable comment short description must start with a capital letter';
167
 
                $phpcsFile->addError($error, ($commentStart + 1), 'ShortNotCapital');
168
 
            }
169
 
 
170
 
            if ($lastChar !== '.') {
171
 
                $error = 'Variable comment short description must end with a full stop';
172
 
                $phpcsFile->addError($error, ($commentStart + 1), 'ShortFullStop');
173
 
            }
174
 
        }//end if
175
 
 
176
 
        // Exactly one blank line before tags.
177
 
        $tags = $this->commentParser->getTagOrders();
178
 
        if (count($tags) > 1) {
179
 
            $newlineSpan = $comment->getNewlineAfter();
180
 
            if ($newlineSpan !== 2) {
181
 
                $error = 'There must be exactly one blank line before the tags in variable comment';
182
 
                if ($long !== '') {
183
 
                    $newlineCount += (substr_count($long, $phpcsFile->eolChar) - $newlineSpan + 1);
184
 
                }
185
 
 
186
 
                $phpcsFile->addError($error, ($commentStart + $newlineCount), 'SpacingBeforeTags');
187
 
                $short = rtrim($short, $phpcsFile->eolChar.' ');
188
 
            }
189
 
        }
190
 
 
191
 
        // Check for unknown/deprecated tags.
192
 
        $unknownTags = $this->commentParser->getUnknown();
193
 
        foreach ($unknownTags as $errorTag) {
194
 
            // Unknown tags are not parsed, do not process further.
195
 
            $error = '@%s tag is not allowed in variable comment';
196
 
            $data  = array($errorTag['tag']);
197
 
            $phpcsFile->addWarning($error, ($commentStart + $errorTag['line']), 'TagNotAllowed', $data);
198
 
        }
199
 
 
200
 
        // Check each tag.
201
 
        $this->processVar($commentStart, $commentEnd);
202
 
        $this->processSees($commentStart);
203
 
 
204
 
        // The last content should be a newline and the content before
205
 
        // that should not be blank. If there is more blank space
206
 
        // then they have additional blank lines at the end of the comment.
207
 
        $words   = $this->commentParser->getWords();
208
 
        $lastPos = (count($words) - 1);
209
 
        if (trim($words[($lastPos - 1)]) !== ''
210
 
            || strpos($words[($lastPos - 1)], $this->currentFile->eolChar) === false
211
 
            || trim($words[($lastPos - 2)]) === ''
212
 
        ) {
213
 
            $error = 'Additional blank lines found at end of variable comment';
214
 
            $this->currentFile->addError($error, $commentEnd, 'SpacingAfter');
215
 
        }
216
 
 
217
 
    }//end processMemberVar()
218
 
 
219
 
 
220
 
    /**
221
 
     * Process the var tag.
222
 
     *
223
 
     * @param int $commentStart The position in the stack where the comment started.
224
 
     * @param int $commentEnd   The position in the stack where the comment ended.
225
 
     *
226
 
     * @return void
227
 
     */
228
 
    protected function processVar($commentStart, $commentEnd)
229
 
    {
230
 
        $var = $this->commentParser->getVar();
231
 
 
232
 
        if ($var !== null) {
233
 
            $errorPos = ($commentStart + $var->getLine());
234
 
            $index    = array_keys($this->commentParser->getTagOrders(), 'var');
235
 
 
236
 
            if (count($index) > 1) {
237
 
                $error = 'Only 1 @var tag is allowed in variable comment';
238
 
                $this->currentFile->addError($error, $errorPos, 'DuplicateVar');
239
 
                return;
240
 
            }
241
 
 
242
 
            if ($index[0] !== 1) {
243
 
                $error = 'The @var tag must be the first tag in a variable comment';
244
 
                $this->currentFile->addError($error, $errorPos, 'VarOrder');
245
 
            }
246
 
 
247
 
            $content = $var->getContent();
248
 
            if (empty($content) === true) {
249
 
                $error = 'Var type missing for @var tag in variable comment';
250
 
                $this->currentFile->addError($error, $errorPos, 'MissingVarType');
251
 
                return;
252
 
            } else {
253
 
                $suggestedType = PHP_CodeSniffer::suggestType($content);
254
 
                if ($content !== $suggestedType) {
255
 
                    $error = 'Expected "%s"; found "%s" for @var tag in variable comment';
256
 
                    $data  = array(
257
 
                              $suggestedType,
258
 
                              $content,
259
 
                             );
260
 
                    $this->currentFile->addError($error, $errorPos, 'IncorrectVarType', $data);
261
 
                }
262
 
            }
263
 
 
264
 
            $spacing = substr_count($var->getWhitespaceBeforeContent(), ' ');
265
 
            if ($spacing !== 1) {
266
 
                $error = '@var tag indented incorrectly; expected 1 space but found %s';
267
 
                $data  = array($spacing);
268
 
                $this->currentFile->addError($error, $errorPos, 'VarIndent', $data);
269
 
            }
270
 
        } else {
271
 
            $error = 'Missing @var tag in variable comment';
272
 
            $this->currentFile->addError($error, $commentEnd, 'MissingVar');
273
 
        }//end if
274
 
 
275
 
    }//end processVar()
276
 
 
277
 
 
278
 
    /**
279
 
     * Process the see tags.
280
 
     *
281
 
     * @param int $commentStart The position in the stack where the comment started.
282
 
     *
283
 
     * @return void
284
 
     */
285
 
    protected function processSees($commentStart)
286
 
    {
287
 
        $sees = $this->commentParser->getSees();
288
 
        if (empty($sees) === false) {
289
 
            foreach ($sees as $see) {
290
 
                $errorPos = ($commentStart + $see->getLine());
291
 
                $content  = $see->getContent();
292
 
                if (empty($content) === true) {
293
 
                    $error = 'Content missing for @see tag in variable comment';
294
 
                    $this->currentFile->addError($error, $errorPos, 'EmptySees');
295
 
                    continue;
296
 
                }
297
 
 
298
 
                $spacing = substr_count($see->getWhitespaceBeforeContent(), ' ');
299
 
                if ($spacing !== 1) {
300
 
                    $error = '@see tag indented incorrectly; expected 1 spaces but found %s';
301
 
                    $data  = array($spacing);
302
 
                    $this->currentFile->addError($error, $errorPos, 'SeesIndent', $data);
303
 
                }
304
 
            }
305
 
        }
306
 
 
307
 
    }//end processSees()
308
 
 
309
 
 
310
 
    /**
311
 
     * Called to process a normal variable.
312
 
     *
313
 
     * Not required for this sniff.
314
 
     *
315
 
     * @param PHP_CodeSniffer_File $phpcsFile The PHP_CodeSniffer file where this token was found.
316
 
     * @param int                  $stackPtr  The position where the double quoted
317
 
     *                                        string was found.
318
 
     *
319
 
     * @return void
320
 
     */
321
 
    protected function processVariable(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
322
 
    {
323
 
 
324
 
    }//end processVariable()
325
 
 
326
 
 
327
 
    /**
328
 
     * Called to process variables found in double quoted strings.
329
 
     *
330
 
     * Not required for this sniff.
331
 
     *
332
 
     * @param PHP_CodeSniffer_File $phpcsFile The PHP_CodeSniffer file where this token was found.
333
 
     * @param int                  $stackPtr  The position where the double quoted
334
 
     *                                        string was found.
335
 
     *
336
 
     * @return void
337
 
     */
338
 
    protected function processVariableInString(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
339
 
    {
340
 
 
341
 
    }//end processVariableInString()
342
 
 
343
 
 
344
 
}//end class
345
 
?>