~ubuntu-branches/ubuntu/vivid/php-codesniffer/vivid

« back to all changes in this revision

Viewing changes to PHP_CodeSniffer-1.5.5/CodeSniffer/Standards/Squiz/Sniffs/Commenting/FunctionCommentThrowTagSniff.php

  • Committer: Package Import Robot
  • Author(s): David Prévot, Greg Sherwood, Alexey, Emily, David Prévot
  • Date: 2014-09-26 13:44:35 UTC
  • mfrom: (1.1.6)
  • Revision ID: package-import@ubuntu.com-20140926134435-wvjq16miqq4d60y0
Tags: 1.5.5-1
[ Greg Sherwood ]
* Improved closure support in Generic ScopeIndentSniff
* Improved indented PHP tag support in Generic ScopeIndentSniff
* Standards can now be located within hidden directories
 (further fix for bug #20323)
* Fixed bug #20373 : Inline comment sniff tab handling way
* Fixed bug #20378 : Report appended to existing file if no errors
  found in run
* Fixed bug #20381 : Invalid "Comment closer must be on a new line"
* PHP tokenizer no longer converts class/function names to special
  tokens types
* Fixed bug #20386 : Squiz.Commenting.ClassComment.SpacingBefore
  thrown if first block comment
* Squiz and PEAR FunctionCommentSnif now support _()
* PEAR ValidFunctionNameSniff no longer throws an error for _()
* Fixed bug #248 : FunctionCommentSniff expects ampersand on param name
* Fixed bug #248 in Squiz sniff as well
* Fixed bug #265 : False positives with type hints in ForbiddenFunctionsSniff
* Prepare for 1.5.5 release

[ Alexey ]
* Allowed single undersored methods and functions

[ Emily ]
* Added var_dump to discouraged functions sniff

[ David Prévot ]
* Revert "Add XS-Testsuite still needed for ci.d.n"
* Add self to uploaders
* Bump standards version to 3.9.6

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<?php
 
2
/**
 
3
 * Verifies that a @throws tag exists for a function that throws exceptions.
 
4
 * Verifies the number of @throws tags and the number of throw tokens matches.
 
5
 * Verifies the exception type.
 
6
 *
 
7
 * PHP version 5
 
8
 *
 
9
 * @category  PHP
 
10
 * @package   PHP_CodeSniffer
 
11
 * @author    Greg Sherwood <gsherwood@squiz.net>
 
12
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 
13
 * @copyright 2006-2014 Squiz Pty Ltd (ABN 77 084 670 600)
 
14
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 
15
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 
16
 */
 
17
 
 
18
if (class_exists('PHP_CodeSniffer_Standards_AbstractScopeSniff', true) === false) {
 
19
    $error = 'Class PHP_CodeSniffer_Standards_AbstractScopeSniff not found';
 
20
    throw new PHP_CodeSniffer_Exception($error);
 
21
}
 
22
 
 
23
/**
 
24
 * Verifies that a @throws tag exists for a function that throws exceptions.
 
25
 * Verifies the number of @throws tags and the number of throw tokens matches.
 
26
 * Verifies the exception type.
 
27
 *
 
28
 * @category  PHP
 
29
 * @package   PHP_CodeSniffer
 
30
 * @author    Greg Sherwood <gsherwood@squiz.net>
 
31
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 
32
 * @copyright 2006-2014 Squiz Pty Ltd (ABN 77 084 670 600)
 
33
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
 
34
 * @version   Release: 1.5.5
 
35
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 
36
 */
 
37
class Squiz_Sniffs_Commenting_FunctionCommentThrowTagSniff extends PHP_CodeSniffer_Standards_AbstractScopeSniff
 
38
{
 
39
 
 
40
 
 
41
    /**
 
42
     * Constructs a Squiz_Sniffs_Commenting_FunctionCommentThrowTagSniff.
 
43
     */
 
44
    public function __construct()
 
45
    {
 
46
        parent::__construct(array(T_FUNCTION), array(T_THROW));
 
47
 
 
48
    }//end __construct()
 
49
 
 
50
 
 
51
    /**
 
52
     * Processes the function tokens within the class.
 
53
     *
 
54
     * @param PHP_CodeSniffer_File $phpcsFile The file where this token was found.
 
55
     * @param int                  $stackPtr  The position where the token was found.
 
56
     * @param int                  $currScope The current scope opener token.
 
57
     *
 
58
     * @return void
 
59
     */
 
60
    protected function processTokenWithinScope(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $currScope)
 
61
    {
 
62
        // Is this the first throw token within the current function scope?
 
63
        // If so, we have to validate other throw tokens within the same scope.
 
64
        $previousThrow = $phpcsFile->findPrevious(T_THROW, ($stackPtr - 1), $currScope);
 
65
        if ($previousThrow !== false) {
 
66
            return;
 
67
        }
 
68
 
 
69
        $tokens = $phpcsFile->getTokens();
 
70
 
 
71
        $find = array(
 
72
                 T_COMMENT,
 
73
                 T_DOC_COMMENT,
 
74
                 T_CLASS,
 
75
                 T_FUNCTION,
 
76
                 T_OPEN_TAG,
 
77
                );
 
78
 
 
79
        $commentEnd = $phpcsFile->findPrevious($find, ($currScope - 1));
 
80
 
 
81
        if ($commentEnd === false) {
 
82
            return;
 
83
        }
 
84
 
 
85
        if ($tokens[$commentEnd]['code'] !== T_DOC_COMMENT) {
 
86
            // Function doesn't have a comment. Let someone else warn about that.
 
87
            return;
 
88
        }
 
89
 
 
90
        $commentStart = ($phpcsFile->findPrevious(T_DOC_COMMENT, ($commentEnd - 1), null, true) + 1);
 
91
        $comment      = $phpcsFile->getTokensAsString($commentStart, ($commentEnd - $commentStart + 1));
 
92
 
 
93
        try {
 
94
            $this->commentParser = new PHP_CodeSniffer_CommentParser_FunctionCommentParser($comment, $phpcsFile);
 
95
            $this->commentParser->parse();
 
96
        } catch (PHP_CodeSniffer_CommentParser_ParserException $e) {
 
97
            $line = ($e->getLineWithinComment() + $commentStart);
 
98
            $phpcsFile->addError($e->getMessage(), $line, 'FailedParse');
 
99
            return;
 
100
        }
 
101
 
 
102
        // Find the position where the current function scope ends.
 
103
        $currScopeEnd = 0;
 
104
        if (isset($tokens[$currScope]['scope_closer']) === true) {
 
105
            $currScopeEnd = $tokens[$currScope]['scope_closer'];
 
106
        }
 
107
 
 
108
        // Find all the exception type token within the current scope.
 
109
        $throwTokens = array();
 
110
        $currPos     = $stackPtr;
 
111
        if ($currScopeEnd !== 0) {
 
112
            while ($currPos < $currScopeEnd && $currPos !== false) {
 
113
 
 
114
                /*
 
115
                    If we can't find a NEW, we are probably throwing
 
116
                    a variable, so we ignore it, but they still need to
 
117
                    provide at least one @throws tag, even through we
 
118
                    don't know the exception class.
 
119
                */
 
120
 
 
121
                $nextToken = $phpcsFile->findNext(T_WHITESPACE, ($currPos + 1), null, true);
 
122
                if ($tokens[$nextToken]['code'] === T_NEW) {
 
123
                    $currException = $phpcsFile->findNext(
 
124
                        array(
 
125
                         T_NS_SEPARATOR,
 
126
                         T_STRING,
 
127
                        ),
 
128
                        $currPos,
 
129
                        $currScopeEnd,
 
130
                        false,
 
131
                        null,
 
132
                        true
 
133
                    );
 
134
 
 
135
                    if ($currException !== false) {
 
136
                        $endException = $phpcsFile->findNext(
 
137
                            array(
 
138
                             T_NS_SEPARATOR,
 
139
                             T_STRING,
 
140
                            ),
 
141
                            ($currException + 1),
 
142
                            $currScopeEnd,
 
143
                            true,
 
144
                            null,
 
145
                            true
 
146
                        );
 
147
 
 
148
                        if ($endException === false) {
 
149
                            $throwTokens[] = $tokens[$currException]['content'];
 
150
                        } else {
 
151
                            $throwTokens[] = $phpcsFile->getTokensAsString($currException, ($endException - $currException));
 
152
                        }
 
153
                    }//end if
 
154
                }//end if
 
155
 
 
156
                $currPos = $phpcsFile->findNext(T_THROW, ($currPos + 1), $currScopeEnd);
 
157
            }//end while
 
158
        }//end if
 
159
 
 
160
        // Only need one @throws tag for each type of exception thrown.
 
161
        $throwTokens = array_unique($throwTokens);
 
162
        sort($throwTokens);
 
163
 
 
164
        $throws = $this->commentParser->getThrows();
 
165
        if (empty($throws) === true) {
 
166
            $error = 'Missing @throws tag in function comment';
 
167
            $phpcsFile->addError($error, $commentEnd, 'Missing');
 
168
        } else if (empty($throwTokens) === true) {
 
169
            // If token count is zero, it means that only variables are being
 
170
            // thrown, so we need at least one @throws tag (checked above).
 
171
            // Nothing more to do.
 
172
            return;
 
173
        } else {
 
174
            $throwTags  = array();
 
175
            $lineNumber = array();
 
176
            foreach ($throws as $throw) {
 
177
                $throwTags[]                    = $throw->getValue();
 
178
                $lineNumber[$throw->getValue()] = $throw->getLine();
 
179
            }
 
180
 
 
181
            $throwTags = array_unique($throwTags);
 
182
            sort($throwTags);
 
183
 
 
184
            // Make sure @throws tag count matches throw token count.
 
185
            $tokenCount = count($throwTokens);
 
186
            $tagCount   = count($throwTags);
 
187
            if ($tokenCount !== $tagCount) {
 
188
                $error = 'Expected %s @throws tag(s) in function comment; %s found';
 
189
                $data  = array(
 
190
                          $tokenCount,
 
191
                          $tagCount,
 
192
                         );
 
193
                $phpcsFile->addError($error, $commentEnd, 'WrongNumber', $data);
 
194
                return;
 
195
            } else {
 
196
                // Exception type in @throws tag must be thrown in the function.
 
197
                foreach ($throwTags as $i => $throwTag) {
 
198
                    $errorPos = ($commentStart + $lineNumber[$throwTag]);
 
199
                    if (empty($throwTag) === false && $throwTag !== $throwTokens[$i]) {
 
200
                        $error = 'Expected "%s" but found "%s" for @throws tag exception';
 
201
                        $data  = array(
 
202
                                  $throwTokens[$i],
 
203
                                  $throwTag,
 
204
                                 );
 
205
                        $phpcsFile->addError($error, $errorPos, 'WrongType', $data);
 
206
                    }
 
207
                }
 
208
            }
 
209
        }//end if
 
210
 
 
211
    }//end processTokenWithinScope()
 
212
 
 
213
 
 
214
}//end class
 
215
?>