Completed
Pull Request — master (#581)
by Juliette
04:16 queued 02:14
created

ReservedFunctionNamesSniff::__construct()   B

Complexity

Conditions 4
Paths 8

Size

Total Lines 24
Code Lines 13

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 24
rs 8.6845
c 0
b 0
f 0
cc 4
eloc 13
nc 8
nop 0
1
<?php
2
/**
3
 * \PHPCompatibility\Sniffs\PHP\ReservedFunctionNamesSniff.
4
 *
5
 * @category PHP
6
 * @package  PHPCompatibility
7
 * @author   Juliette Reinders Folmer <[email protected]>
8
 */
9
10
namespace PHPCompatibility\Sniffs\PHP;
11
12
use PHPCompatibility\PHPCSHelper;
13
14
/**
15
 * \PHPCompatibility\Sniffs\PHP\ReservedFunctionNamesSniff.
16
 *
17
 * All function and method names starting with double underscore are reserved by PHP.
18
 *
19
 * {@internal Extends an upstream sniff to benefit from the properties contained therein.
20
 *            The properties are lists of valid PHP magic function and method names, which
21
 *            should be ignored for the purposes of this sniff.
22
 *            As this sniff is not PHP version specific, we don't need access to the utility
23
 *            methods in the PHPCompatibility\Sniff, so extending the upstream sniff is fine.
24
 *            As the upstream sniff checks the same (and more, but we don't need the rest),
25
 *            the logic in this sniff is largely the same as used upstream.
26
 *            Extending the upstream sniff instead of including it via the ruleset, however,
27
 *            prevents hard to debug issues of errors not being reported from the upstream sniff
28
 *            if this library is used in combination with other rulesets.}}
29
 *
30
 * @category PHP
31
 * @package  PHPCompatibility
32
 * @author   Juliette Reinders Folmer <[email protected]>
33
 */
34
class ReservedFunctionNamesSniff extends \Generic_Sniffs_NamingConventions_CamelCapsFunctionNameSniff
35
{
36
37
    /**
38
     * Overload the constructor to work round various PHPCS cross-version compatibility issues.
39
     */
40
    public function __construct()
41
    {
42
        $scopeTokens = array(T_CLASS, T_INTERFACE);
43
        if (defined('T_TRAIT')) {
44
            $scopeTokens[] = constant('T_TRAIT');
45
        }
46
        if (defined('T_ANON_CLASS')) {
47
            $scopeTokens[] = constant('T_ANON_CLASS');
48
        }
49
50
        // Call the grand-parent constructor directly.
51
        \PHP_CodeSniffer_Standards_AbstractScopeSniff::__construct($scopeTokens, array(T_FUNCTION), true);
52
53
        $phpcsVersion = PHPCSHelper::getVersion();
54
55
        if (version_compare($phpcsVersion, '2.0.0', '<') === true) {
56
            $this->magicMethods            = array_flip($this->magicMethods);
57
            $this->methodsDoubleUnderscore = array_flip($this->methodsDoubleUnderscore);
58
            $this->magicFunctions          = array_flip($this->magicFunctions);
59
        }
60
61
        // Make sure debuginfo is included in the array. Upstream only includes it since 2.5.1.
62
        $this->magicMethods['debuginfo'] = true;
63
    }
64
65
    /**
66
     * Processes the tokens within the scope.
67
     *
68
     * @param \PHP_CodeSniffer_File $phpcsFile The file being processed.
69
     * @param int                   $stackPtr  The position where this token was
70
     *                                         found.
71
     * @param int                   $currScope The position of the current scope.
72
     *
73
     * @return void
74
     */
75
    protected function processTokenWithinScope(\PHP_CodeSniffer_File $phpcsFile, $stackPtr, $currScope)
76
    {
77
        $tokens = $phpcsFile->getTokens();
78
79
        $methodName = $phpcsFile->getDeclarationName($stackPtr);
80
        if ($methodName === null) {
81
            // Ignore closures.
82
            return;
83
        }
84
85
        // Is this a magic method. i.e., is prefixed with "__" ?
86
        if (preg_match('|^__[^_]|', $methodName) > 0) {
87
            $magicPart = strtolower(substr($methodName, 2));
88
            if (isset($this->magicMethods[$magicPart]) === false
89
                && isset($this->methodsDoubleUnderscore[$magicPart]) === false
90
            ) {
91
                $className = '[anonymous class]';
92
                if (defined('T_ANON_CLASS') === false || $tokens[$currScope]['type'] !== 'T_ANON_CLASS') {
93
                    $className = $phpcsFile->getDeclarationName($currScope);
94
                }
95
96
                $phpcsFile->addWarning(
97
                    'Method name "%s" is discouraged; PHP has reserved all method names with a double underscore prefix for future use.',
98
                    $stackPtr,
99
                    'MethodDoubleUnderscore',
100
                    array($className.'::'.$methodName)
101
                );
102
            }
103
        }
104
    }
105
106
    /**
107
     * Processes the tokens outside the scope.
108
     *
109
     * @param \PHP_CodeSniffer_File $phpcsFile The file being processed.
110
     * @param int                   $stackPtr  The position where this token was
111
     *                                         found.
112
     *
113
     * @return void
114
     */
115
    protected function processTokenOutsideScope(\PHP_CodeSniffer_File $phpcsFile, $stackPtr)
116
    {
117
        $functionName = $phpcsFile->getDeclarationName($stackPtr);
118
        if ($functionName === null) {
119
            // Ignore closures.
120
            return;
121
        }
122
123
        // Is this a magic function. i.e., it is prefixed with "__".
124
        if (preg_match('|^__[^_]|', $functionName) > 0) {
125
            $magicPart = strtolower(substr($functionName, 2));
126
            if (isset($this->magicFunctions[$magicPart]) === false) {
127
                $phpcsFile->addWarning(
128
                    'Function name "%s" is discouraged; PHP has reserved all method names with a double underscore prefix for future use.',
129
                    $stackPtr,
130
                    'FunctionDoubleUnderscore',
131
                    array($functionName)
132
                );
133
            }
134
        }
135
    }
136
137
}//end class
138