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

« back to all changes in this revision

Viewing changes to PHP_CodeSniffer-1.5.4/CodeSniffer/Standards/PSR1/Sniffs/Files/SideEffectsSniff.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
 
 * PSR1_Sniffs_Files_SideEffectsSniff.
4
 
 *
5
 
 * PHP version 5
6
 
 *
7
 
 * @category  PHP
8
 
 * @package   PHP_CodeSniffer
9
 
 * @author    Greg Sherwood <gsherwood@squiz.net>
10
 
 * @copyright 2006-2014 Squiz Pty Ltd (ABN 77 084 670 600)
11
 
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
12
 
 * @link      http://pear.php.net/package/PHP_CodeSniffer
13
 
 */
14
 
 
15
 
/**
16
 
 * PSR1_Sniffs_Files_SideEffectsSniff.
17
 
 *
18
 
 * Ensures a file declare new symbols and causes no other side effects, or executes
19
 
 * logic with side effects, but not both.
20
 
 *
21
 
 * @category  PHP
22
 
 * @package   PHP_CodeSniffer
23
 
 * @author    Greg Sherwood <gsherwood@squiz.net>
24
 
 * @copyright 2006-2014 Squiz Pty Ltd (ABN 77 084 670 600)
25
 
 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
26
 
 * @version   Release: 1.5.4
27
 
 * @link      http://pear.php.net/package/PHP_CodeSniffer
28
 
 */
29
 
class PSR1_Sniffs_Files_SideEffectsSniff implements PHP_CodeSniffer_Sniff
30
 
{
31
 
 
32
 
    /**
33
 
     * Returns an array of tokens this test wants to listen for.
34
 
     *
35
 
     * @return array
36
 
     */
37
 
    public function register()
38
 
    {
39
 
        return array(T_OPEN_TAG);
40
 
 
41
 
    }//end register()
42
 
 
43
 
 
44
 
    /**
45
 
     * Processes this sniff, when one of its tokens is encountered.
46
 
     *
47
 
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
48
 
     * @param int                  $stackPtr  The position of the current token in
49
 
     *                                        the token stack.
50
 
     *
51
 
     * @return void
52
 
     */
53
 
    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
54
 
    {
55
 
        // We are only interested if this is the first open tag.
56
 
        if ($stackPtr !== 0) {
57
 
            if ($phpcsFile->findPrevious(T_OPEN_TAG, ($stackPtr - 1)) !== false) {
58
 
                return;
59
 
            }
60
 
        }
61
 
 
62
 
        $tokens = $phpcsFile->getTokens();
63
 
        $result = $this->_searchForConflict($phpcsFile, 0, ($phpcsFile->numTokens - 1), $tokens);
64
 
 
65
 
        if ($result['symbol'] !== null && $result['effect'] !== null) {
66
 
            $error = 'A file should declare new symbols (classes, functions, constants, etc.) and cause no other side effects, or it should execute logic with side effects, but should not do both. The first symbol is defined on line %s and the first side effect is on line %s.';
67
 
            $data  = array(
68
 
                      $tokens[$result['symbol']]['line'],
69
 
                      $tokens[$result['effect']]['line'],
70
 
                     );
71
 
            $phpcsFile->addWarning($error, 0, 'FoundWithSymbols', $data);
72
 
        }
73
 
 
74
 
    }//end process()
75
 
 
76
 
 
77
 
    /**
78
 
     * Searches for symbol declarations and side effects.
79
 
     *
80
 
     * Returns the positions of both the first symbol declared and the first
81
 
     * side effect in the file. A NULL value for either indicates nothing was
82
 
     * found.
83
 
     *
84
 
     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
85
 
     * @param int                  $start     The token to start searching from.
86
 
     * @param int                  $end       The token to search to.
87
 
     * @param array                $tokens    The stack of tokens that make up
88
 
     *                                        the file.
89
 
     *
90
 
     * @return array
91
 
     */
92
 
    private function _searchForConflict(PHP_CodeSniffer_File $phpcsFile, $start, $end, $tokens)
93
 
    {
94
 
        $symbols = array(
95
 
                    T_CLASS,
96
 
                    T_INTERFACE,
97
 
                    T_TRAIT,
98
 
                    T_FUNCTION,
99
 
                   );
100
 
 
101
 
        $conditions = array(
102
 
                       T_IF,
103
 
                       T_ELSE,
104
 
                       T_ELSEIF,
105
 
                      );
106
 
 
107
 
        $firstSymbol = null;
108
 
        $firstEffect = null;
109
 
        for ($i = $start; $i <= $end; $i++) {
110
 
            // Ignore whitespace and comments.
111
 
            if (in_array($tokens[$i]['code'], PHP_CodeSniffer_Tokens::$emptyTokens) === true) {
112
 
                continue;
113
 
            }
114
 
 
115
 
            // Ignore PHP tags.
116
 
            if ($tokens[$i]['code'] === T_OPEN_TAG
117
 
                || $tokens[$i]['code'] === T_CLOSE_TAG
118
 
            ) {
119
 
                continue;
120
 
            }
121
 
 
122
 
            // Ignore entire namespace, const and use statements.
123
 
            if ($tokens[$i]['code'] === T_NAMESPACE) {
124
 
                $next = $phpcsFile->findNext(array(T_SEMICOLON, T_OPEN_CURLY_BRACKET), ($i + 1));
125
 
                if ($next === false) {
126
 
                    $next = $i++;
127
 
                } else if ($tokens[$next]['code'] === T_OPEN_CURLY_BRACKET) {
128
 
                    $next = $tokens[$next]['bracket_closer'];
129
 
                }
130
 
 
131
 
                $i = $next;
132
 
                continue;
133
 
            } else if ($tokens[$i]['code'] === T_USE
134
 
                || $tokens[$i]['code'] === T_CONST
135
 
            ) {
136
 
                $semicolon = $phpcsFile->findNext(T_SEMICOLON, ($i + 1));
137
 
                if ($semicolon !== false) {
138
 
                    $i = $semicolon;
139
 
                }
140
 
 
141
 
                continue;
142
 
            }
143
 
 
144
 
            // Ignore function/class prefixes.
145
 
            if (in_array($tokens[$i]['code'], PHP_CodeSniffer_Tokens::$methodPrefixes) === true) {
146
 
                continue;
147
 
            }
148
 
 
149
 
            // Detect and skip over symbols.
150
 
            if (in_array($tokens[$i]['code'], $symbols) === true
151
 
                && isset($tokens[$i]['scope_closer']) === true
152
 
            ) {
153
 
                if ($firstSymbol === null) {
154
 
                    $firstSymbol = $i;
155
 
                }
156
 
 
157
 
                $i = $tokens[$i]['scope_closer'];
158
 
                continue;
159
 
            } else if ($tokens[$i]['code'] === T_STRING
160
 
                && strtolower($tokens[$i]['content']) === 'define'
161
 
            ) {
162
 
                $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($i - 1), null, true);
163
 
                if ($tokens[$prev]['code'] !== T_OBJECT_OPERATOR) {
164
 
                    if ($firstSymbol === null) {
165
 
                        $firstSymbol = $i;
166
 
                    }
167
 
 
168
 
                    $i = $phpcsFile->findNext(T_SEMICOLON, ($i + 1));
169
 
                    continue;
170
 
                }
171
 
            }
172
 
 
173
 
            // Conditional statements are allowed in symbol files as long as the
174
 
            // contents is only a symbol definition. So don't count these as effects
175
 
            // in this case.
176
 
            if (in_array($tokens[$i]['code'], $conditions) === true) {
177
 
                if (isset($tokens[$i]['scope_opener']) === false) {
178
 
                    // Probably an "else if", so just ignore.
179
 
                    continue;
180
 
                }
181
 
 
182
 
                $result = $this->_searchForConflict(
183
 
                    $phpcsFile,
184
 
                    ($tokens[$i]['scope_opener'] + 1),
185
 
                    ($tokens[$i]['scope_closer'] - 1),
186
 
                    $tokens
187
 
                );
188
 
 
189
 
                if ($result['symbol'] !== null) {
190
 
                    if ($firstSymbol === null) {
191
 
                        $firstSymbol = $result['symbol'];
192
 
                    }
193
 
 
194
 
                    if ($result['effect'] !== null) {
195
 
                        // Found a conflict.
196
 
                        $firstEffect = $result['effect'];
197
 
                        break;
198
 
                    }
199
 
                }
200
 
 
201
 
                if ($firstEffect === null) {
202
 
                    $firstEffect = $result['effect'];
203
 
                }
204
 
 
205
 
                $i = $tokens[$i]['scope_closer'];
206
 
                continue;
207
 
            }//end if
208
 
 
209
 
            if ($firstEffect === null) {
210
 
                $firstEffect = $i;
211
 
            }
212
 
 
213
 
            if ($firstSymbol !== null) {
214
 
                // We have a conflict we have to report, so no point continuing.
215
 
                break;
216
 
            }
217
 
        }//end for
218
 
 
219
 
        return array(
220
 
                'symbol' => $firstSymbol,
221
 
                'effect' => $firstEffect,
222
 
               );
223
 
 
224
 
    }//end _searchForConflict()
225
 
 
226
 
 
227
 
}//end class
228
 
 
229
 
?>