Completed
Push — feature/new-reserved-function-... ( 62e1e9...c1f55a )
by Juliette
01:36
created

processTokenWithinScope()   C

Complexity

Conditions 7
Paths 5

Size

Total Lines 30
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 30
rs 6.7272
c 0
b 0
f 0
cc 7
eloc 17
nc 5
nop 3
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
    /**
67
     * Processes the tokens within the scope.
68
     *
69
     * @param \PHP_CodeSniffer_File $phpcsFile The file being processed.
70
     * @param int                   $stackPtr  The position where this token was
71
     *                                         found.
72
     * @param int                   $currScope The position of the current scope.
73
     *
74
     * @return void
75
     */
76
    protected function processTokenWithinScope(\PHP_CodeSniffer_File $phpcsFile, $stackPtr, $currScope)
77
    {
78
        $tokens = $phpcsFile->getTokens();
79
80
        $methodName = $phpcsFile->getDeclarationName($stackPtr);
81
        if ($methodName === null) {
82
            // Ignore closures.
83
            return;
84
        }
85
86
        // Is this a magic method. i.e., is prefixed with "__" ?
87
        if (preg_match('|^__[^_]|', $methodName) > 0) {
88
            $magicPart = strtolower(substr($methodName, 2));
89
            if (isset($this->magicMethods[$magicPart]) === false
90
                && isset($this->methodsDoubleUnderscore[$magicPart]) === false
91
            ) {
92
                $className = '[anonymous class]';
93
                if (defined('T_ANON_CLASS') === false || $tokens[$currScope]['type'] !== 'T_ANON_CLASS') {
94
                    $className = $phpcsFile->getDeclarationName($currScope);
95
                }
96
97
                $phpcsFile->addWarning(
98
                    'Method name "%s" is discouraged; PHP has reserved all method names with a double underscore prefix for future use.',
99
                    $stackPtr,
100
                    'MethodDoubleUnderscore',
101
                    array($className.'::'.$methodName)
102
                );
103
            }
104
        }
105
    }
106
107
    /**
108
     * Processes the tokens outside the scope.
109
     *
110
     * @param \PHP_CodeSniffer_File $phpcsFile The file being processed.
111
     * @param int                   $stackPtr  The position where this token was
112
     *                                         found.
113
     *
114
     * @return void
115
     */
116
    protected function processTokenOutsideScope(\PHP_CodeSniffer_File $phpcsFile, $stackPtr)
117
    {
118
        $functionName = $phpcsFile->getDeclarationName($stackPtr);
119
        if ($functionName === null) {
120
            // Ignore closures.
121
            return;
122
        }
123
124
        // Is this a magic function. i.e., it is prefixed with "__".
125
        if (preg_match('|^__[^_]|', $functionName) > 0) {
126
            $magicPart = strtolower(substr($functionName, 2));
127
            if (isset($this->magicFunctions[$magicPart]) === false) {
128
                $phpcsFile->addWarning(
129
                    'Function name "%s" is discouraged; PHP has reserved all method names with a double underscore prefix for future use.',
130
                    $stackPtr,
131
                    'FunctionDoubleUnderscore',
132
                    array($functionName)
133
                );
134
            }
135
        }
136
    }
137
138
}//end class
139