Completed
Pull Request — develop (#1492)
by Zack
33:18 queued 12:17
created
PHPCompatibility/Sniffs/Syntax/NewArrayStringDereferencingSniff.php 1 patch
Indentation   +69 added lines, -69 removed lines patch added patch discarded remove patch
@@ -28,81 +28,81 @@
 block discarded – undo
28 28
  */
29 29
 class NewArrayStringDereferencingSniff extends Sniff
30 30
 {
31
-    /**
32
-     * Returns an array of tokens this test wants to listen for.
33
-     *
34
-     * @return array
35
-     */
36
-    public function register()
37
-    {
38
-        return array(
39
-            \T_ARRAY,
40
-            \T_OPEN_SHORT_ARRAY,
41
-            \T_CONSTANT_ENCAPSED_STRING,
42
-        );
43
-    }
31
+	/**
32
+	 * Returns an array of tokens this test wants to listen for.
33
+	 *
34
+	 * @return array
35
+	 */
36
+	public function register()
37
+	{
38
+		return array(
39
+			\T_ARRAY,
40
+			\T_OPEN_SHORT_ARRAY,
41
+			\T_CONSTANT_ENCAPSED_STRING,
42
+		);
43
+	}
44 44
 
45
-    /**
46
-     * Processes this test, when one of its tokens is encountered.
47
-     *
48
-     * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned.
49
-     * @param int                   $stackPtr  The position of the current token in
50
-     *                                         the stack passed in $tokens.
51
-     *
52
-     * @return void
53
-     */
54
-    public function process(File $phpcsFile, $stackPtr)
55
-    {
56
-        if ($this->supportsBelow('5.4') === false) {
57
-            return;
58
-        }
45
+	/**
46
+	 * Processes this test, when one of its tokens is encountered.
47
+	 *
48
+	 * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned.
49
+	 * @param int                   $stackPtr  The position of the current token in
50
+	 *                                         the stack passed in $tokens.
51
+	 *
52
+	 * @return void
53
+	 */
54
+	public function process(File $phpcsFile, $stackPtr)
55
+	{
56
+		if ($this->supportsBelow('5.4') === false) {
57
+			return;
58
+		}
59 59
 
60
-        $tokens = $phpcsFile->getTokens();
60
+		$tokens = $phpcsFile->getTokens();
61 61
 
62
-        switch ($tokens[$stackPtr]['code']) {
63
-            case \T_CONSTANT_ENCAPSED_STRING:
64
-                $type = 'string literals';
65
-                $end  = $stackPtr;
66
-                break;
62
+		switch ($tokens[$stackPtr]['code']) {
63
+			case \T_CONSTANT_ENCAPSED_STRING:
64
+				$type = 'string literals';
65
+				$end  = $stackPtr;
66
+				break;
67 67
 
68
-            case \T_ARRAY:
69
-                if (isset($tokens[$stackPtr]['parenthesis_closer']) === false) {
70
-                    // Live coding.
71
-                    return;
72
-                } else {
73
-                    $type = 'arrays';
74
-                    $end  = $tokens[$stackPtr]['parenthesis_closer'];
75
-                }
76
-                break;
68
+			case \T_ARRAY:
69
+				if (isset($tokens[$stackPtr]['parenthesis_closer']) === false) {
70
+					// Live coding.
71
+					return;
72
+				} else {
73
+					$type = 'arrays';
74
+					$end  = $tokens[$stackPtr]['parenthesis_closer'];
75
+				}
76
+				break;
77 77
 
78
-            case \T_OPEN_SHORT_ARRAY:
79
-                if (isset($tokens[$stackPtr]['bracket_closer']) === false) {
80
-                    // Live coding.
81
-                    return;
82
-                } else {
83
-                    $type = 'arrays';
84
-                    $end  = $tokens[$stackPtr]['bracket_closer'];
85
-                }
86
-                break;
87
-        }
78
+			case \T_OPEN_SHORT_ARRAY:
79
+				if (isset($tokens[$stackPtr]['bracket_closer']) === false) {
80
+					// Live coding.
81
+					return;
82
+				} else {
83
+					$type = 'arrays';
84
+					$end  = $tokens[$stackPtr]['bracket_closer'];
85
+				}
86
+				break;
87
+		}
88 88
 
89
-        if (isset($type, $end) === false) {
90
-            // Shouldn't happen, but for some reason did.
91
-            return;
92
-        }
89
+		if (isset($type, $end) === false) {
90
+			// Shouldn't happen, but for some reason did.
91
+			return;
92
+		}
93 93
 
94
-        $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($end + 1), null, true, null, true);
94
+		$nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($end + 1), null, true, null, true);
95 95
 
96
-        if ($nextNonEmpty !== false
97
-            && ($tokens[$nextNonEmpty]['type'] === 'T_OPEN_SQUARE_BRACKET'
98
-                || $tokens[$nextNonEmpty]['type'] === 'T_OPEN_SHORT_ARRAY') // Work around bug #1381 in PHPCS 2.8.1 and lower.
99
-        ) {
100
-            $phpcsFile->addError(
101
-                'Direct array dereferencing of %s is not present in PHP version 5.4 or earlier',
102
-                $nextNonEmpty,
103
-                'Found',
104
-                array($type)
105
-            );
106
-        }
107
-    }
96
+		if ($nextNonEmpty !== false
97
+			&& ($tokens[$nextNonEmpty]['type'] === 'T_OPEN_SQUARE_BRACKET'
98
+				|| $tokens[$nextNonEmpty]['type'] === 'T_OPEN_SHORT_ARRAY') // Work around bug #1381 in PHPCS 2.8.1 and lower.
99
+		) {
100
+			$phpcsFile->addError(
101
+				'Direct array dereferencing of %s is not present in PHP version 5.4 or earlier',
102
+				$nextNonEmpty,
103
+				'Found',
104
+				array($type)
105
+			);
106
+		}
107
+	}
108 108
 }
Please login to merge, or discard this patch.
php-compatibility/PHPCompatibility/Sniffs/Syntax/NewArrayUnpackingSniff.php 1 patch
Indentation   +106 added lines, -106 removed lines patch added patch discarded remove patch
@@ -26,112 +26,112 @@
 block discarded – undo
26 26
 class NewArrayUnpackingSniff extends Sniff
27 27
 {
28 28
 
29
-    /**
30
-     * Returns an array of tokens this test wants to listen for.
31
-     *
32
-     * @return array
33
-     */
34
-    public function register()
35
-    {
36
-        return array(
37
-            \T_ARRAY,
38
-            \T_OPEN_SHORT_ARRAY,
39
-        );
40
-    }
41
-
42
-    /**
43
-     * Processes this test, when one of its tokens is encountered.
44
-     *
45
-     * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned.
46
-     * @param int                   $stackPtr  The position of the current token in the
47
-     *                                         stack passed in $tokens.
48
-     *
49
-     * @return void
50
-     */
51
-    public function process(File $phpcsFile, $stackPtr)
52
-    {
53
-        if ($this->supportsBelow('7.3') === false) {
54
-            return;
55
-        }
56
-
57
-        $tokens = $phpcsFile->getTokens();
58
-
59
-        /*
29
+	/**
30
+	 * Returns an array of tokens this test wants to listen for.
31
+	 *
32
+	 * @return array
33
+	 */
34
+	public function register()
35
+	{
36
+		return array(
37
+			\T_ARRAY,
38
+			\T_OPEN_SHORT_ARRAY,
39
+		);
40
+	}
41
+
42
+	/**
43
+	 * Processes this test, when one of its tokens is encountered.
44
+	 *
45
+	 * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned.
46
+	 * @param int                   $stackPtr  The position of the current token in the
47
+	 *                                         stack passed in $tokens.
48
+	 *
49
+	 * @return void
50
+	 */
51
+	public function process(File $phpcsFile, $stackPtr)
52
+	{
53
+		if ($this->supportsBelow('7.3') === false) {
54
+			return;
55
+		}
56
+
57
+		$tokens = $phpcsFile->getTokens();
58
+
59
+		/*
60 60
          * Determine the array opener & closer.
61 61
          */
62
-        $closer = $phpcsFile->numTokens;
63
-        if ($tokens[$stackPtr]['code'] === \T_ARRAY) {
64
-            if (isset($tokens[$stackPtr]['parenthesis_opener']) === false) {
65
-                return;
66
-            }
67
-
68
-            $opener = $tokens[$stackPtr]['parenthesis_opener'];
69
-
70
-            if (isset($tokens[$opener]['parenthesis_closer'])) {
71
-                $closer = $tokens[$opener]['parenthesis_closer'];
72
-            }
73
-        } else {
74
-            // Short array syntax.
75
-            $opener = $stackPtr;
76
-
77
-            if (isset($tokens[$stackPtr]['bracket_closer'])) {
78
-                $closer = $tokens[$stackPtr]['bracket_closer'];
79
-            }
80
-        }
81
-
82
-        $nestingLevel = 0;
83
-        if (isset($tokens[($opener + 1)]['nested_parenthesis'])) {
84
-            $nestingLevel = count($tokens[($opener + 1)]['nested_parenthesis']);
85
-        }
86
-
87
-        for ($i = $opener; $i < $closer;) {
88
-            $i = $phpcsFile->findNext(array(\T_ELLIPSIS, \T_OPEN_SHORT_ARRAY, \T_ARRAY), ($i + 1), $closer);
89
-            if ($i === false) {
90
-                return;
91
-            }
92
-
93
-            if ($tokens[$i]['code'] === \T_OPEN_SHORT_ARRAY) {
94
-                if (isset($tokens[$i]['bracket_closer']) === false) {
95
-                    // Live coding, unfinished nested array, handle this when the array opener
96
-                    // of the nested array is passed.
97
-                    return;
98
-                }
99
-
100
-                // Skip over nested short arrays. These will be handled when the array opener
101
-                // of the nested array is passed.
102
-                $i = $tokens[$i]['bracket_closer'];
103
-                continue;
104
-            }
105
-
106
-            if ($tokens[$i]['code'] === \T_ARRAY) {
107
-                if (isset($tokens[$i]['parenthesis_closer']) === false) {
108
-                    // Live coding, unfinished nested array, handle this when the array opener
109
-                    // of the nested array is passed.
110
-                    return;
111
-                }
112
-
113
-                // Skip over nested long arrays. These will be handled when the array opener
114
-                // of the nested array is passed.
115
-                $i = $tokens[$i]['parenthesis_closer'];
116
-                continue;
117
-            }
118
-
119
-            // Ensure this is not function call variable unpacking.
120
-            if (isset($tokens[$i]['nested_parenthesis'])
121
-                && count($tokens[$i]['nested_parenthesis']) > $nestingLevel
122
-            ) {
123
-                continue;
124
-            }
125
-
126
-            // Ok, found one.
127
-            $nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($i + 1), null, true);
128
-            $snippet      = trim($phpcsFile->getTokensAsString($i, (($nextNonEmpty - $i) + 1)));
129
-            $phpcsFile->addError(
130
-                'Array unpacking within array declarations using the spread operator is not supported in PHP 7.3 or earlier. Found: %s',
131
-                $i,
132
-                'Found',
133
-                array($snippet)
134
-            );
135
-        }
136
-    }
62
+		$closer = $phpcsFile->numTokens;
63
+		if ($tokens[$stackPtr]['code'] === \T_ARRAY) {
64
+			if (isset($tokens[$stackPtr]['parenthesis_opener']) === false) {
65
+				return;
66
+			}
67
+
68
+			$opener = $tokens[$stackPtr]['parenthesis_opener'];
69
+
70
+			if (isset($tokens[$opener]['parenthesis_closer'])) {
71
+				$closer = $tokens[$opener]['parenthesis_closer'];
72
+			}
73
+		} else {
74
+			// Short array syntax.
75
+			$opener = $stackPtr;
76
+
77
+			if (isset($tokens[$stackPtr]['bracket_closer'])) {
78
+				$closer = $tokens[$stackPtr]['bracket_closer'];
79
+			}
80
+		}
81
+
82
+		$nestingLevel = 0;
83
+		if (isset($tokens[($opener + 1)]['nested_parenthesis'])) {
84
+			$nestingLevel = count($tokens[($opener + 1)]['nested_parenthesis']);
85
+		}
86
+
87
+		for ($i = $opener; $i < $closer;) {
88
+			$i = $phpcsFile->findNext(array(\T_ELLIPSIS, \T_OPEN_SHORT_ARRAY, \T_ARRAY), ($i + 1), $closer);
89
+			if ($i === false) {
90
+				return;
91
+			}
92
+
93
+			if ($tokens[$i]['code'] === \T_OPEN_SHORT_ARRAY) {
94
+				if (isset($tokens[$i]['bracket_closer']) === false) {
95
+					// Live coding, unfinished nested array, handle this when the array opener
96
+					// of the nested array is passed.
97
+					return;
98
+				}
99
+
100
+				// Skip over nested short arrays. These will be handled when the array opener
101
+				// of the nested array is passed.
102
+				$i = $tokens[$i]['bracket_closer'];
103
+				continue;
104
+			}
105
+
106
+			if ($tokens[$i]['code'] === \T_ARRAY) {
107
+				if (isset($tokens[$i]['parenthesis_closer']) === false) {
108
+					// Live coding, unfinished nested array, handle this when the array opener
109
+					// of the nested array is passed.
110
+					return;
111
+				}
112
+
113
+				// Skip over nested long arrays. These will be handled when the array opener
114
+				// of the nested array is passed.
115
+				$i = $tokens[$i]['parenthesis_closer'];
116
+				continue;
117
+			}
118
+
119
+			// Ensure this is not function call variable unpacking.
120
+			if (isset($tokens[$i]['nested_parenthesis'])
121
+				&& count($tokens[$i]['nested_parenthesis']) > $nestingLevel
122
+			) {
123
+				continue;
124
+			}
125
+
126
+			// Ok, found one.
127
+			$nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, ($i + 1), null, true);
128
+			$snippet      = trim($phpcsFile->getTokensAsString($i, (($nextNonEmpty - $i) + 1)));
129
+			$phpcsFile->addError(
130
+				'Array unpacking within array declarations using the spread operator is not supported in PHP 7.3 or earlier. Found: %s',
131
+				$i,
132
+				'Found',
133
+				array($snippet)
134
+			);
135
+		}
136
+	}
137 137
 }
Please login to merge, or discard this patch.
PHPCompatibility/Sniffs/Operators/NewShortTernarySniff.php 1 patch
Indentation   +32 added lines, -32 removed lines patch added patch discarded remove patch
@@ -31,39 +31,39 @@
 block discarded – undo
31 31
 class NewShortTernarySniff extends Sniff
32 32
 {
33 33
 
34
-    /**
35
-     * Returns an array of tokens this test wants to listen for.
36
-     *
37
-     * @return array
38
-     */
39
-    public function register()
40
-    {
41
-        return array(\T_INLINE_THEN);
42
-    }
34
+	/**
35
+	 * Returns an array of tokens this test wants to listen for.
36
+	 *
37
+	 * @return array
38
+	 */
39
+	public function register()
40
+	{
41
+		return array(\T_INLINE_THEN);
42
+	}
43 43
 
44
-    /**
45
-     * Processes this test, 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 the
49
-     *                                         stack passed in $tokens.
50
-     *
51
-     * @return void
52
-     */
53
-    public function process(File $phpcsFile, $stackPtr)
54
-    {
55
-        if ($this->supportsBelow('5.2') === false) {
56
-            return;
57
-        }
44
+	/**
45
+	 * Processes this test, 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 the
49
+	 *                                         stack passed in $tokens.
50
+	 *
51
+	 * @return void
52
+	 */
53
+	public function process(File $phpcsFile, $stackPtr)
54
+	{
55
+		if ($this->supportsBelow('5.2') === false) {
56
+			return;
57
+		}
58 58
 
59
-        if ($this->isShortTernary($phpcsFile, $stackPtr) === false) {
60
-            return;
61
-        }
59
+		if ($this->isShortTernary($phpcsFile, $stackPtr) === false) {
60
+			return;
61
+		}
62 62
 
63
-        $phpcsFile->addError(
64
-            'Middle may not be omitted from ternary operators in PHP < 5.3',
65
-            $stackPtr,
66
-            'MiddleMissing'
67
-        );
68
-    }
63
+		$phpcsFile->addError(
64
+			'Middle may not be omitted from ternary operators in PHP < 5.3',
65
+			$stackPtr,
66
+			'MiddleMissing'
67
+		);
68
+	}
69 69
 }
Please login to merge, or discard this patch.
PHPCompatibility/Sniffs/Operators/ChangedConcatOperatorPrecedenceSniff.php 1 patch
Indentation   +161 added lines, -161 removed lines patch added patch discarded remove patch
@@ -35,165 +35,165 @@
 block discarded – undo
35 35
 class ChangedConcatOperatorPrecedenceSniff extends Sniff
36 36
 {
37 37
 
38
-    /**
39
-     * List of tokens with a lower operator precedence than concatenation in PHP >= 8.0.
40
-     *
41
-     * @since 9.2.0
42
-     *
43
-     * @var array
44
-     */
45
-    private $tokensWithLowerPrecedence = array(
46
-        'T_BITWISE_AND' => true,
47
-        'T_BITWISE_XOR' => true,
48
-        'T_BITWISE_OR'  => true,
49
-        'T_COALESCE'    => true,
50
-        'T_INLINE_THEN' => true,
51
-        'T_INLINE_ELSE' => true,
52
-        'T_YIELD_FROM'  => true,
53
-        'T_YIELD'       => true,
54
-    );
55
-
56
-
57
-    /**
58
-     * Returns an array of tokens this test wants to listen for.
59
-     *
60
-     * @since 9.2.0
61
-     *
62
-     * @return array
63
-     */
64
-    public function register()
65
-    {
66
-        return array(
67
-            \T_PLUS,
68
-            \T_MINUS,
69
-        );
70
-    }
71
-
72
-    /**
73
-     * Processes this test, when one of its tokens is encountered.
74
-     *
75
-     * @since 9.2.0
76
-     *
77
-     * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned.
78
-     * @param int                   $stackPtr  The position of the current token in the
79
-     *                                         stack passed in $tokens.
80
-     *
81
-     * @return void
82
-     */
83
-    public function process(File $phpcsFile, $stackPtr)
84
-    {
85
-        if ($this->supportsAbove('7.4') === false) {
86
-            return;
87
-        }
88
-
89
-        if ($this->isUnaryPlusMinus($phpcsFile, $stackPtr) === true) {
90
-            return;
91
-        }
92
-
93
-        $tokens = $phpcsFile->getTokens();
94
-
95
-        for ($i = ($stackPtr - 1); $stackPtr >= 0; $i--) {
96
-            if ($tokens[$i]['code'] === \T_STRING_CONCAT) {
97
-                // Found one.
98
-                break;
99
-            }
100
-
101
-            if ($tokens[$i]['code'] === \T_SEMICOLON
102
-                || $tokens[$i]['code'] === \T_OPEN_CURLY_BRACKET
103
-                || $tokens[$i]['code'] === \T_OPEN_TAG
104
-                || $tokens[$i]['code'] === \T_OPEN_TAG_WITH_ECHO
105
-                || $tokens[$i]['code'] === \T_COMMA
106
-                || $tokens[$i]['code'] === \T_COLON
107
-                || $tokens[$i]['code'] === \T_CASE
108
-            ) {
109
-                // If we reached any of the above tokens, we've reached the end of
110
-                // the statement without encountering a concatenation operator.
111
-                return;
112
-            }
113
-
114
-            if ($tokens[$i]['code'] === \T_OPEN_CURLY_BRACKET
115
-                && isset($tokens[$i]['bracket_closer'])
116
-                && $tokens[$i]['bracket_closer'] > $stackPtr
117
-            ) {
118
-                // No need to look any further, this is plus/minus within curly braces
119
-                // and we've reached the open curly.
120
-                return;
121
-            }
122
-
123
-            if ($tokens[$i]['code'] === \T_OPEN_PARENTHESIS
124
-                && isset($tokens[$i]['parenthesis_closer'])
125
-                && $tokens[$i]['parenthesis_closer'] > $stackPtr
126
-            ) {
127
-                // No need to look any further, this is plus/minus within parenthesis
128
-                // and we've reached the open parenthesis.
129
-                return;
130
-            }
131
-
132
-            if (($tokens[$i]['code'] === \T_OPEN_SHORT_ARRAY
133
-                || $tokens[$i]['code'] === \T_OPEN_SQUARE_BRACKET)
134
-                && isset($tokens[$i]['bracket_closer'])
135
-                && $tokens[$i]['bracket_closer'] > $stackPtr
136
-            ) {
137
-                // No need to look any further, this is plus/minus within a short array
138
-                // or array key square brackets and we've reached the opener.
139
-                return;
140
-            }
141
-
142
-            if ($tokens[$i]['code'] === \T_CLOSE_CURLY_BRACKET) {
143
-                if (isset($tokens[$i]['scope_owner'])) {
144
-                    // Different scope, we've passed the start of the statement.
145
-                    return;
146
-                }
147
-
148
-                if (isset($tokens[$i]['bracket_opener'])) {
149
-                    $i = $tokens[$i]['bracket_opener'];
150
-                }
151
-
152
-                continue;
153
-            }
154
-
155
-            if ($tokens[$i]['code'] === \T_CLOSE_PARENTHESIS
156
-                && isset($tokens[$i]['parenthesis_opener'])
157
-            ) {
158
-                // Skip over statements in parenthesis, including long arrays.
159
-                $i = $tokens[$i]['parenthesis_opener'];
160
-                continue;
161
-            }
162
-
163
-            if (($tokens[$i]['code'] === \T_CLOSE_SQUARE_BRACKET
164
-                || $tokens[$i]['code'] === \T_CLOSE_SHORT_ARRAY)
165
-                && isset($tokens[$i]['bracket_opener'])
166
-            ) {
167
-                // Skip over array keys and short arrays.
168
-                $i = $tokens[$i]['bracket_opener'];
169
-                continue;
170
-            }
171
-
172
-            // Check for chain being broken by a token with a lower precedence.
173
-            if (isset(Tokens::$booleanOperators[$tokens[$i]['code']]) === true
174
-                || isset(Tokens::$assignmentTokens[$tokens[$i]['code']]) === true
175
-            ) {
176
-                return;
177
-            }
178
-
179
-            if (isset($this->tokensWithLowerPrecedence[$tokens[$i]['type']]) === true) {
180
-                if ($tokens[$i]['code'] === \T_BITWISE_AND
181
-                    && $phpcsFile->isReference($i) === true
182
-                ) {
183
-                    continue;
184
-                }
185
-
186
-                return;
187
-            }
188
-        }
189
-
190
-        $message = 'Using an unparenthesized expression containing a "." before a "+" or "-" has been deprecated in PHP 7.4';
191
-        $isError = false;
192
-        if ($this->supportsAbove('8.0') === true) {
193
-            $message .= ' and removed in PHP 8.0';
194
-            $isError  = true;
195
-        }
196
-
197
-        $this->addMessage($phpcsFile, $message, $i, $isError);
198
-    }
38
+	/**
39
+	 * List of tokens with a lower operator precedence than concatenation in PHP >= 8.0.
40
+	 *
41
+	 * @since 9.2.0
42
+	 *
43
+	 * @var array
44
+	 */
45
+	private $tokensWithLowerPrecedence = array(
46
+		'T_BITWISE_AND' => true,
47
+		'T_BITWISE_XOR' => true,
48
+		'T_BITWISE_OR'  => true,
49
+		'T_COALESCE'    => true,
50
+		'T_INLINE_THEN' => true,
51
+		'T_INLINE_ELSE' => true,
52
+		'T_YIELD_FROM'  => true,
53
+		'T_YIELD'       => true,
54
+	);
55
+
56
+
57
+	/**
58
+	 * Returns an array of tokens this test wants to listen for.
59
+	 *
60
+	 * @since 9.2.0
61
+	 *
62
+	 * @return array
63
+	 */
64
+	public function register()
65
+	{
66
+		return array(
67
+			\T_PLUS,
68
+			\T_MINUS,
69
+		);
70
+	}
71
+
72
+	/**
73
+	 * Processes this test, when one of its tokens is encountered.
74
+	 *
75
+	 * @since 9.2.0
76
+	 *
77
+	 * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned.
78
+	 * @param int                   $stackPtr  The position of the current token in the
79
+	 *                                         stack passed in $tokens.
80
+	 *
81
+	 * @return void
82
+	 */
83
+	public function process(File $phpcsFile, $stackPtr)
84
+	{
85
+		if ($this->supportsAbove('7.4') === false) {
86
+			return;
87
+		}
88
+
89
+		if ($this->isUnaryPlusMinus($phpcsFile, $stackPtr) === true) {
90
+			return;
91
+		}
92
+
93
+		$tokens = $phpcsFile->getTokens();
94
+
95
+		for ($i = ($stackPtr - 1); $stackPtr >= 0; $i--) {
96
+			if ($tokens[$i]['code'] === \T_STRING_CONCAT) {
97
+				// Found one.
98
+				break;
99
+			}
100
+
101
+			if ($tokens[$i]['code'] === \T_SEMICOLON
102
+				|| $tokens[$i]['code'] === \T_OPEN_CURLY_BRACKET
103
+				|| $tokens[$i]['code'] === \T_OPEN_TAG
104
+				|| $tokens[$i]['code'] === \T_OPEN_TAG_WITH_ECHO
105
+				|| $tokens[$i]['code'] === \T_COMMA
106
+				|| $tokens[$i]['code'] === \T_COLON
107
+				|| $tokens[$i]['code'] === \T_CASE
108
+			) {
109
+				// If we reached any of the above tokens, we've reached the end of
110
+				// the statement without encountering a concatenation operator.
111
+				return;
112
+			}
113
+
114
+			if ($tokens[$i]['code'] === \T_OPEN_CURLY_BRACKET
115
+				&& isset($tokens[$i]['bracket_closer'])
116
+				&& $tokens[$i]['bracket_closer'] > $stackPtr
117
+			) {
118
+				// No need to look any further, this is plus/minus within curly braces
119
+				// and we've reached the open curly.
120
+				return;
121
+			}
122
+
123
+			if ($tokens[$i]['code'] === \T_OPEN_PARENTHESIS
124
+				&& isset($tokens[$i]['parenthesis_closer'])
125
+				&& $tokens[$i]['parenthesis_closer'] > $stackPtr
126
+			) {
127
+				// No need to look any further, this is plus/minus within parenthesis
128
+				// and we've reached the open parenthesis.
129
+				return;
130
+			}
131
+
132
+			if (($tokens[$i]['code'] === \T_OPEN_SHORT_ARRAY
133
+				|| $tokens[$i]['code'] === \T_OPEN_SQUARE_BRACKET)
134
+				&& isset($tokens[$i]['bracket_closer'])
135
+				&& $tokens[$i]['bracket_closer'] > $stackPtr
136
+			) {
137
+				// No need to look any further, this is plus/minus within a short array
138
+				// or array key square brackets and we've reached the opener.
139
+				return;
140
+			}
141
+
142
+			if ($tokens[$i]['code'] === \T_CLOSE_CURLY_BRACKET) {
143
+				if (isset($tokens[$i]['scope_owner'])) {
144
+					// Different scope, we've passed the start of the statement.
145
+					return;
146
+				}
147
+
148
+				if (isset($tokens[$i]['bracket_opener'])) {
149
+					$i = $tokens[$i]['bracket_opener'];
150
+				}
151
+
152
+				continue;
153
+			}
154
+
155
+			if ($tokens[$i]['code'] === \T_CLOSE_PARENTHESIS
156
+				&& isset($tokens[$i]['parenthesis_opener'])
157
+			) {
158
+				// Skip over statements in parenthesis, including long arrays.
159
+				$i = $tokens[$i]['parenthesis_opener'];
160
+				continue;
161
+			}
162
+
163
+			if (($tokens[$i]['code'] === \T_CLOSE_SQUARE_BRACKET
164
+				|| $tokens[$i]['code'] === \T_CLOSE_SHORT_ARRAY)
165
+				&& isset($tokens[$i]['bracket_opener'])
166
+			) {
167
+				// Skip over array keys and short arrays.
168
+				$i = $tokens[$i]['bracket_opener'];
169
+				continue;
170
+			}
171
+
172
+			// Check for chain being broken by a token with a lower precedence.
173
+			if (isset(Tokens::$booleanOperators[$tokens[$i]['code']]) === true
174
+				|| isset(Tokens::$assignmentTokens[$tokens[$i]['code']]) === true
175
+			) {
176
+				return;
177
+			}
178
+
179
+			if (isset($this->tokensWithLowerPrecedence[$tokens[$i]['type']]) === true) {
180
+				if ($tokens[$i]['code'] === \T_BITWISE_AND
181
+					&& $phpcsFile->isReference($i) === true
182
+				) {
183
+					continue;
184
+				}
185
+
186
+				return;
187
+			}
188
+		}
189
+
190
+		$message = 'Using an unparenthesized expression containing a "." before a "+" or "-" has been deprecated in PHP 7.4';
191
+		$isError = false;
192
+		if ($this->supportsAbove('8.0') === true) {
193
+			$message .= ' and removed in PHP 8.0';
194
+			$isError  = true;
195
+		}
196
+
197
+		$this->addMessage($phpcsFile, $message, $i, $isError);
198
+	}
199 199
 }
Please login to merge, or discard this patch.
PHPCompatibility/Sniffs/Operators/ForbiddenNegativeBitshiftSniff.php 1 patch
Indentation   +65 added lines, -65 removed lines patch added patch discarded remove patch
@@ -29,76 +29,76 @@
 block discarded – undo
29 29
  */
30 30
 class ForbiddenNegativeBitshiftSniff extends Sniff
31 31
 {
32
-    /**
33
-     * Potential end tokens for which the end pointer has to be set back by one.
34
-     *
35
-     * {@internal The PHPCS `findEndOfStatement()` method is not completely consistent
36
-     * in how it returns the statement end. This is just a simple way to bypass
37
-     * the inconsistency for our purposes.}}
38
-     *
39
-     * @var array
40
-     */
41
-    private $inclusiveStopPoints = array(
42
-        \T_COLON        => true,
43
-        \T_COMMA        => true,
44
-        \T_DOUBLE_ARROW => true,
45
-        \T_SEMICOLON    => true,
46
-    );
32
+	/**
33
+	 * Potential end tokens for which the end pointer has to be set back by one.
34
+	 *
35
+	 * {@internal The PHPCS `findEndOfStatement()` method is not completely consistent
36
+	 * in how it returns the statement end. This is just a simple way to bypass
37
+	 * the inconsistency for our purposes.}}
38
+	 *
39
+	 * @var array
40
+	 */
41
+	private $inclusiveStopPoints = array(
42
+		\T_COLON        => true,
43
+		\T_COMMA        => true,
44
+		\T_DOUBLE_ARROW => true,
45
+		\T_SEMICOLON    => true,
46
+	);
47 47
 
48
-    /**
49
-     * Returns an array of tokens this test wants to listen for.
50
-     *
51
-     * @return array
52
-     */
53
-    public function register()
54
-    {
55
-        return array(
56
-            \T_SL,
57
-            \T_SL_EQUAL,
58
-            \T_SR,
59
-            \T_SR_EQUAL,
60
-        );
61
-    }
48
+	/**
49
+	 * Returns an array of tokens this test wants to listen for.
50
+	 *
51
+	 * @return array
52
+	 */
53
+	public function register()
54
+	{
55
+		return array(
56
+			\T_SL,
57
+			\T_SL_EQUAL,
58
+			\T_SR,
59
+			\T_SR_EQUAL,
60
+		);
61
+	}
62 62
 
63
-    /**
64
-     * Processes this test, when one of its tokens is encountered.
65
-     *
66
-     * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned.
67
-     * @param int                   $stackPtr  The position of the current token
68
-     *                                         in the stack passed in $tokens.
69
-     *
70
-     * @return void
71
-     */
72
-    public function process(File $phpcsFile, $stackPtr)
73
-    {
74
-        if ($this->supportsAbove('7.0') === false) {
75
-            return;
76
-        }
63
+	/**
64
+	 * Processes this test, when one of its tokens is encountered.
65
+	 *
66
+	 * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned.
67
+	 * @param int                   $stackPtr  The position of the current token
68
+	 *                                         in the stack passed in $tokens.
69
+	 *
70
+	 * @return void
71
+	 */
72
+	public function process(File $phpcsFile, $stackPtr)
73
+	{
74
+		if ($this->supportsAbove('7.0') === false) {
75
+			return;
76
+		}
77 77
 
78
-        $tokens = $phpcsFile->getTokens();
78
+		$tokens = $phpcsFile->getTokens();
79 79
 
80
-        // Determine the start and end of the part of the statement we need to examine.
81
-        $start = ($stackPtr + 1);
82
-        $next  = $phpcsFile->findNext(Tokens::$emptyTokens, $start, null, true);
83
-        if ($next !== false && $tokens[$next]['code'] === \T_OPEN_PARENTHESIS) {
84
-            $start = ($next + 1);
85
-        }
80
+		// Determine the start and end of the part of the statement we need to examine.
81
+		$start = ($stackPtr + 1);
82
+		$next  = $phpcsFile->findNext(Tokens::$emptyTokens, $start, null, true);
83
+		if ($next !== false && $tokens[$next]['code'] === \T_OPEN_PARENTHESIS) {
84
+			$start = ($next + 1);
85
+		}
86 86
 
87
-        $end = PHPCSHelper::findEndOfStatement($phpcsFile, $start);
88
-        if (isset($this->inclusiveStopPoints[$tokens[$end]['code']]) === true) {
89
-            --$end;
90
-        }
87
+		$end = PHPCSHelper::findEndOfStatement($phpcsFile, $start);
88
+		if (isset($this->inclusiveStopPoints[$tokens[$end]['code']]) === true) {
89
+			--$end;
90
+		}
91 91
 
92
-        if ($this->isNegativeNumber($phpcsFile, $start, $end, true) !== true) {
93
-            // Not a negative number or undetermined.
94
-            return;
95
-        }
92
+		if ($this->isNegativeNumber($phpcsFile, $start, $end, true) !== true) {
93
+			// Not a negative number or undetermined.
94
+			return;
95
+		}
96 96
 
97
-        $phpcsFile->addError(
98
-            'Bitwise shifts by negative number will throw an ArithmeticError in PHP 7.0. Found: %s',
99
-            $stackPtr,
100
-            'Found',
101
-            array($phpcsFile->getTokensAsString($start, ($end - $start + 1)))
102
-        );
103
-    }
97
+		$phpcsFile->addError(
98
+			'Bitwise shifts by negative number will throw an ArithmeticError in PHP 7.0. Found: %s',
99
+			$stackPtr,
100
+			'Found',
101
+			array($phpcsFile->getTokensAsString($start, ($end - $start + 1)))
102
+		);
103
+	}
104 104
 }
Please login to merge, or discard this patch.
PHPCompatibility/Sniffs/Operators/RemovedTernaryAssociativitySniff.php 1 patch
Indentation   +123 added lines, -123 removed lines patch added patch discarded remove patch
@@ -30,127 +30,127 @@
 block discarded – undo
30 30
 class RemovedTernaryAssociativitySniff extends Sniff
31 31
 {
32 32
 
33
-    /**
34
-     * List of tokens with a lower operator precedence than ternary.
35
-     *
36
-     * @since 9.2.0
37
-     *
38
-     * @var array
39
-     */
40
-    private $tokensWithLowerPrecedence = array(
41
-        'T_YIELD_FROM'  => true,
42
-        'T_YIELD'       => true,
43
-        'T_LOGICAL_AND' => true,
44
-        'T_LOGICAL_OR'  => true,
45
-        'T_LOGICAL_XOR' => true,
46
-    );
47
-
48
-
49
-    /**
50
-     * Returns an array of tokens this test wants to listen for.
51
-     *
52
-     * @since 9.2.0
53
-     *
54
-     * @return array
55
-     */
56
-    public function register()
57
-    {
58
-        return array(\T_INLINE_THEN);
59
-    }
60
-
61
-    /**
62
-     * Processes this test, when one of its tokens is encountered.
63
-     *
64
-     * @since 9.2.0
65
-     *
66
-     * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned.
67
-     * @param int                   $stackPtr  The position of the current token
68
-     *                                         in the stack passed in $tokens.
69
-     *
70
-     * @return void
71
-     */
72
-    public function process(File $phpcsFile, $stackPtr)
73
-    {
74
-        if ($this->supportsAbove('7.4') === false) {
75
-            return;
76
-        }
77
-
78
-        $tokens         = $phpcsFile->getTokens();
79
-        $endOfStatement = PHPCSHelper::findEndOfStatement($phpcsFile, $stackPtr);
80
-        if ($tokens[$endOfStatement]['code'] !== \T_SEMICOLON
81
-            && $tokens[$endOfStatement]['code'] !== \T_COLON
82
-            && $tokens[$endOfStatement]['code'] !== \T_COMMA
83
-            && $tokens[$endOfStatement]['code'] !== \T_DOUBLE_ARROW
84
-            && $tokens[$endOfStatement]['code'] !== \T_OPEN_TAG
85
-            && $tokens[$endOfStatement]['code'] !== \T_CLOSE_TAG
86
-        ) {
87
-            // End of statement is last non-empty before close brace, so make sure we examine that token too.
88
-            ++$endOfStatement;
89
-        }
90
-
91
-        $ternaryCount      = 0;
92
-        $elseCount         = 0;
93
-        $shortTernaryCount = 0;
94
-
95
-        // Start at $stackPtr so we don't need duplicate code for short ternary determination.
96
-        for ($i = $stackPtr; $i < $endOfStatement; $i++) {
97
-            if (($tokens[$i]['code'] === \T_OPEN_SHORT_ARRAY
98
-                || $tokens[$i]['code'] === \T_OPEN_SQUARE_BRACKET
99
-                || $tokens[$i]['code'] === \T_OPEN_CURLY_BRACKET)
100
-                && isset($tokens[$i]['bracket_closer'])
101
-            ) {
102
-                // Skip over short arrays, array access keys and curlies.
103
-                $i = $tokens[$i]['bracket_closer'];
104
-                continue;
105
-            }
106
-
107
-            if ($tokens[$i]['code'] === \T_OPEN_PARENTHESIS
108
-                && isset($tokens[$i]['parenthesis_closer'])
109
-            ) {
110
-                // Skip over anything between parentheses.
111
-                $i = $tokens[$i]['parenthesis_closer'];
112
-                continue;
113
-            }
114
-
115
-            // Check for operators with lower operator precedence.
116
-            if (isset(Tokens::$assignmentTokens[$tokens[$i]['code']])
117
-                || isset($this->tokensWithLowerPrecedence[$tokens[$i]['code']])
118
-            ) {
119
-                break;
120
-            }
121
-
122
-            if ($tokens[$i]['code'] === \T_INLINE_THEN) {
123
-                ++$ternaryCount;
124
-
125
-                if ($this->isShortTernary($phpcsFile, $i) === true) {
126
-                    ++$shortTernaryCount;
127
-                }
128
-
129
-                continue;
130
-            }
131
-
132
-            if ($tokens[$i]['code'] === \T_INLINE_ELSE) {
133
-                if (($ternaryCount - $elseCount) >= 2) {
134
-                    // This is the `else` for a ternary in the middle part of a previous ternary.
135
-                    --$ternaryCount;
136
-                } else {
137
-                    ++$elseCount;
138
-                }
139
-                continue;
140
-            }
141
-        }
142
-
143
-        if ($ternaryCount > 1 && $ternaryCount === $elseCount && $ternaryCount > $shortTernaryCount) {
144
-            $message = 'The left-associativity of the ternary operator has been deprecated in PHP 7.4';
145
-            $isError = false;
146
-            if ($this->supportsAbove('8.0') === true) {
147
-                $message .= ' and removed in PHP 8.0';
148
-                $isError  = true;
149
-            }
150
-
151
-            $message .= '. Multiple consecutive ternaries detected. Use parenthesis to clarify the order in which the operations should be executed';
152
-
153
-            $this->addMessage($phpcsFile, $message, $stackPtr, $isError);
154
-        }
155
-    }
33
+	/**
34
+	 * List of tokens with a lower operator precedence than ternary.
35
+	 *
36
+	 * @since 9.2.0
37
+	 *
38
+	 * @var array
39
+	 */
40
+	private $tokensWithLowerPrecedence = array(
41
+		'T_YIELD_FROM'  => true,
42
+		'T_YIELD'       => true,
43
+		'T_LOGICAL_AND' => true,
44
+		'T_LOGICAL_OR'  => true,
45
+		'T_LOGICAL_XOR' => true,
46
+	);
47
+
48
+
49
+	/**
50
+	 * Returns an array of tokens this test wants to listen for.
51
+	 *
52
+	 * @since 9.2.0
53
+	 *
54
+	 * @return array
55
+	 */
56
+	public function register()
57
+	{
58
+		return array(\T_INLINE_THEN);
59
+	}
60
+
61
+	/**
62
+	 * Processes this test, when one of its tokens is encountered.
63
+	 *
64
+	 * @since 9.2.0
65
+	 *
66
+	 * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned.
67
+	 * @param int                   $stackPtr  The position of the current token
68
+	 *                                         in the stack passed in $tokens.
69
+	 *
70
+	 * @return void
71
+	 */
72
+	public function process(File $phpcsFile, $stackPtr)
73
+	{
74
+		if ($this->supportsAbove('7.4') === false) {
75
+			return;
76
+		}
77
+
78
+		$tokens         = $phpcsFile->getTokens();
79
+		$endOfStatement = PHPCSHelper::findEndOfStatement($phpcsFile, $stackPtr);
80
+		if ($tokens[$endOfStatement]['code'] !== \T_SEMICOLON
81
+			&& $tokens[$endOfStatement]['code'] !== \T_COLON
82
+			&& $tokens[$endOfStatement]['code'] !== \T_COMMA
83
+			&& $tokens[$endOfStatement]['code'] !== \T_DOUBLE_ARROW
84
+			&& $tokens[$endOfStatement]['code'] !== \T_OPEN_TAG
85
+			&& $tokens[$endOfStatement]['code'] !== \T_CLOSE_TAG
86
+		) {
87
+			// End of statement is last non-empty before close brace, so make sure we examine that token too.
88
+			++$endOfStatement;
89
+		}
90
+
91
+		$ternaryCount      = 0;
92
+		$elseCount         = 0;
93
+		$shortTernaryCount = 0;
94
+
95
+		// Start at $stackPtr so we don't need duplicate code for short ternary determination.
96
+		for ($i = $stackPtr; $i < $endOfStatement; $i++) {
97
+			if (($tokens[$i]['code'] === \T_OPEN_SHORT_ARRAY
98
+				|| $tokens[$i]['code'] === \T_OPEN_SQUARE_BRACKET
99
+				|| $tokens[$i]['code'] === \T_OPEN_CURLY_BRACKET)
100
+				&& isset($tokens[$i]['bracket_closer'])
101
+			) {
102
+				// Skip over short arrays, array access keys and curlies.
103
+				$i = $tokens[$i]['bracket_closer'];
104
+				continue;
105
+			}
106
+
107
+			if ($tokens[$i]['code'] === \T_OPEN_PARENTHESIS
108
+				&& isset($tokens[$i]['parenthesis_closer'])
109
+			) {
110
+				// Skip over anything between parentheses.
111
+				$i = $tokens[$i]['parenthesis_closer'];
112
+				continue;
113
+			}
114
+
115
+			// Check for operators with lower operator precedence.
116
+			if (isset(Tokens::$assignmentTokens[$tokens[$i]['code']])
117
+				|| isset($this->tokensWithLowerPrecedence[$tokens[$i]['code']])
118
+			) {
119
+				break;
120
+			}
121
+
122
+			if ($tokens[$i]['code'] === \T_INLINE_THEN) {
123
+				++$ternaryCount;
124
+
125
+				if ($this->isShortTernary($phpcsFile, $i) === true) {
126
+					++$shortTernaryCount;
127
+				}
128
+
129
+				continue;
130
+			}
131
+
132
+			if ($tokens[$i]['code'] === \T_INLINE_ELSE) {
133
+				if (($ternaryCount - $elseCount) >= 2) {
134
+					// This is the `else` for a ternary in the middle part of a previous ternary.
135
+					--$ternaryCount;
136
+				} else {
137
+					++$elseCount;
138
+				}
139
+				continue;
140
+			}
141
+		}
142
+
143
+		if ($ternaryCount > 1 && $ternaryCount === $elseCount && $ternaryCount > $shortTernaryCount) {
144
+			$message = 'The left-associativity of the ternary operator has been deprecated in PHP 7.4';
145
+			$isError = false;
146
+			if ($this->supportsAbove('8.0') === true) {
147
+				$message .= ' and removed in PHP 8.0';
148
+				$isError  = true;
149
+			}
150
+
151
+			$message .= '. Multiple consecutive ternaries detected. Use parenthesis to clarify the order in which the operations should be executed';
152
+
153
+			$this->addMessage($phpcsFile, $message, $stackPtr, $isError);
154
+		}
155
+	}
156 156
 }
Please login to merge, or discard this patch.
php-compatibility/PHPCompatibility/Sniffs/Operators/NewOperatorsSniff.php 1 patch
Indentation   +239 added lines, -239 removed lines patch added patch discarded remove patch
@@ -24,271 +24,271 @@
 block discarded – undo
24 24
 class NewOperatorsSniff extends AbstractNewFeatureSniff
25 25
 {
26 26
 
27
-    /**
28
-     * A list of new operators, not present in older versions.
29
-     *
30
-     * The array lists : version number with false (not present) or true (present).
31
-     * If's sufficient to list the first version where the keyword appears.
32
-     *
33
-     * @var array(string => array(string => int|string|null))
34
-     */
35
-    protected $newOperators = array(
36
-        'T_POW' => array(
37
-            '5.5' => false,
38
-            '5.6' => true,
39
-            'description' => 'power operator (**)',
40
-        ), // Identified in PHP < 5.6 icw PHPCS < 2.4.0 as T_MULTIPLY + T_MULTIPLY.
41
-        'T_POW_EQUAL' => array(
42
-            '5.5' => false,
43
-            '5.6' => true,
44
-            'description' => 'power assignment operator (**=)',
45
-        ), // Identified in PHP < 5.6 icw PHPCS < 2.6.0 as T_MULTIPLY + T_MUL_EQUAL.
46
-        'T_SPACESHIP' => array(
47
-            '5.6' => false,
48
-            '7.0' => true,
49
-            'description' => 'spaceship operator (<=>)',
50
-        ), // Identified in PHP < 7.0 icw PHPCS < 2.5.1 as T_IS_SMALLER_OR_EQUAL + T_GREATER_THAN.
51
-        'T_COALESCE' => array(
52
-            '5.6' => false,
53
-            '7.0' => true,
54
-            'description' => 'null coalescing operator (??)',
55
-        ), // Identified in PHP < 7.0 icw PHPCS < 2.6.2 as T_INLINE_THEN + T_INLINE_THEN.
56
-        /*
27
+	/**
28
+	 * A list of new operators, not present in older versions.
29
+	 *
30
+	 * The array lists : version number with false (not present) or true (present).
31
+	 * If's sufficient to list the first version where the keyword appears.
32
+	 *
33
+	 * @var array(string => array(string => int|string|null))
34
+	 */
35
+	protected $newOperators = array(
36
+		'T_POW' => array(
37
+			'5.5' => false,
38
+			'5.6' => true,
39
+			'description' => 'power operator (**)',
40
+		), // Identified in PHP < 5.6 icw PHPCS < 2.4.0 as T_MULTIPLY + T_MULTIPLY.
41
+		'T_POW_EQUAL' => array(
42
+			'5.5' => false,
43
+			'5.6' => true,
44
+			'description' => 'power assignment operator (**=)',
45
+		), // Identified in PHP < 5.6 icw PHPCS < 2.6.0 as T_MULTIPLY + T_MUL_EQUAL.
46
+		'T_SPACESHIP' => array(
47
+			'5.6' => false,
48
+			'7.0' => true,
49
+			'description' => 'spaceship operator (<=>)',
50
+		), // Identified in PHP < 7.0 icw PHPCS < 2.5.1 as T_IS_SMALLER_OR_EQUAL + T_GREATER_THAN.
51
+		'T_COALESCE' => array(
52
+			'5.6' => false,
53
+			'7.0' => true,
54
+			'description' => 'null coalescing operator (??)',
55
+		), // Identified in PHP < 7.0 icw PHPCS < 2.6.2 as T_INLINE_THEN + T_INLINE_THEN.
56
+		/*
57 57
          * Was slated for 7.2, but still not implemented. PHPCS however does already tokenize it.
58 58
          * @link https://wiki.php.net/rfc/null_coalesce_equal_operator
59 59
          */
60
-        'T_COALESCE_EQUAL' => array(
61
-            '7.3' => false,
62
-            '7.4' => true,
63
-            'description' => 'null coalesce equal operator (??=)',
64
-        ), // Identified in PHP < 7.0 icw PHPCS < 2.6.2 as T_INLINE_THEN + T_INLINE_THEN + T_EQUAL and between PHPCS 2.6.2 and PHPCS 2.8.1 as T_COALESCE + T_EQUAL.
65
-    );
60
+		'T_COALESCE_EQUAL' => array(
61
+			'7.3' => false,
62
+			'7.4' => true,
63
+			'description' => 'null coalesce equal operator (??=)',
64
+		), // Identified in PHP < 7.0 icw PHPCS < 2.6.2 as T_INLINE_THEN + T_INLINE_THEN + T_EQUAL and between PHPCS 2.6.2 and PHPCS 2.8.1 as T_COALESCE + T_EQUAL.
65
+	);
66 66
 
67 67
 
68
-    /**
69
-     * A list of new operators which are not recognized in older PHPCS versions.
70
-     *
71
-     * The array lists an alternative token to listen for.
72
-     *
73
-     * @var array(string => int)
74
-     */
75
-    protected $newOperatorsPHPCSCompat = array(
76
-        'T_POW'            => \T_MULTIPLY,
77
-        'T_POW_EQUAL'      => \T_MUL_EQUAL,
78
-        'T_SPACESHIP'      => \T_GREATER_THAN,
79
-        'T_COALESCE'       => \T_INLINE_THEN,
80
-        'T_COALESCE_EQUAL' => \T_EQUAL,
81
-    );
68
+	/**
69
+	 * A list of new operators which are not recognized in older PHPCS versions.
70
+	 *
71
+	 * The array lists an alternative token to listen for.
72
+	 *
73
+	 * @var array(string => int)
74
+	 */
75
+	protected $newOperatorsPHPCSCompat = array(
76
+		'T_POW'            => \T_MULTIPLY,
77
+		'T_POW_EQUAL'      => \T_MUL_EQUAL,
78
+		'T_SPACESHIP'      => \T_GREATER_THAN,
79
+		'T_COALESCE'       => \T_INLINE_THEN,
80
+		'T_COALESCE_EQUAL' => \T_EQUAL,
81
+	);
82 82
 
83
-    /**
84
-     * Token translation table for older PHPCS versions.
85
-     *
86
-     * The 'before' index lists the token which would have to be directly before the
87
-     * token found for it to be one of the new operators.
88
-     * The 'real_token' index indicates which operator was found in that case.
89
-     *
90
-     * If the token combination has multi-layer complexity, such as is the case
91
-     * with T_COALESCE(_EQUAL), a 'callback' index is added instead pointing to a
92
-     * separate function which can determine whether this is the targetted token across
93
-     * PHP and PHPCS versions.
94
-     *
95
-     * {@internal 'before' was chosen rather than 'after' as that allowed for a 1-on-1
96
-     * translation list with the current tokens.}}
97
-     *
98
-     * @var array(string => array(string => string))
99
-     */
100
-    protected $PHPCSCompatTranslate = array(
101
-        'T_MULTIPLY' => array(
102
-            'before'     => 'T_MULTIPLY',
103
-            'real_token' => 'T_POW',
104
-        ),
105
-        'T_MUL_EQUAL' => array(
106
-            'before'     => 'T_MULTIPLY',
107
-            'real_token' => 'T_POW_EQUAL',
108
-        ),
109
-        'T_GREATER_THAN' => array(
110
-            'before'     => 'T_IS_SMALLER_OR_EQUAL',
111
-            'real_token' => 'T_SPACESHIP',
112
-        ),
113
-        'T_INLINE_THEN' => array(
114
-            'callback'   => 'isTCoalesce',
115
-            'real_token' => 'T_COALESCE',
116
-        ),
117
-        'T_EQUAL' => array(
118
-            'callback'   => 'isTCoalesceEqual',
119
-            'real_token' => 'T_COALESCE_EQUAL',
120
-        ),
121
-    );
83
+	/**
84
+	 * Token translation table for older PHPCS versions.
85
+	 *
86
+	 * The 'before' index lists the token which would have to be directly before the
87
+	 * token found for it to be one of the new operators.
88
+	 * The 'real_token' index indicates which operator was found in that case.
89
+	 *
90
+	 * If the token combination has multi-layer complexity, such as is the case
91
+	 * with T_COALESCE(_EQUAL), a 'callback' index is added instead pointing to a
92
+	 * separate function which can determine whether this is the targetted token across
93
+	 * PHP and PHPCS versions.
94
+	 *
95
+	 * {@internal 'before' was chosen rather than 'after' as that allowed for a 1-on-1
96
+	 * translation list with the current tokens.}}
97
+	 *
98
+	 * @var array(string => array(string => string))
99
+	 */
100
+	protected $PHPCSCompatTranslate = array(
101
+		'T_MULTIPLY' => array(
102
+			'before'     => 'T_MULTIPLY',
103
+			'real_token' => 'T_POW',
104
+		),
105
+		'T_MUL_EQUAL' => array(
106
+			'before'     => 'T_MULTIPLY',
107
+			'real_token' => 'T_POW_EQUAL',
108
+		),
109
+		'T_GREATER_THAN' => array(
110
+			'before'     => 'T_IS_SMALLER_OR_EQUAL',
111
+			'real_token' => 'T_SPACESHIP',
112
+		),
113
+		'T_INLINE_THEN' => array(
114
+			'callback'   => 'isTCoalesce',
115
+			'real_token' => 'T_COALESCE',
116
+		),
117
+		'T_EQUAL' => array(
118
+			'callback'   => 'isTCoalesceEqual',
119
+			'real_token' => 'T_COALESCE_EQUAL',
120
+		),
121
+	);
122 122
 
123
-    /**
124
-     * Returns an array of tokens this test wants to listen for.
125
-     *
126
-     * @return array
127
-     */
128
-    public function register()
129
-    {
130
-        $tokens = array();
131
-        foreach ($this->newOperators as $token => $versions) {
132
-            if (\defined($token)) {
133
-                $tokens[] = constant($token);
134
-            } elseif (isset($this->newOperatorsPHPCSCompat[$token])) {
135
-                $tokens[] = $this->newOperatorsPHPCSCompat[$token];
136
-            }
137
-        }
138
-        return $tokens;
139
-    }
123
+	/**
124
+	 * Returns an array of tokens this test wants to listen for.
125
+	 *
126
+	 * @return array
127
+	 */
128
+	public function register()
129
+	{
130
+		$tokens = array();
131
+		foreach ($this->newOperators as $token => $versions) {
132
+			if (\defined($token)) {
133
+				$tokens[] = constant($token);
134
+			} elseif (isset($this->newOperatorsPHPCSCompat[$token])) {
135
+				$tokens[] = $this->newOperatorsPHPCSCompat[$token];
136
+			}
137
+		}
138
+		return $tokens;
139
+	}
140 140
 
141 141
 
142
-    /**
143
-     * Processes this test, when one of its tokens is encountered.
144
-     *
145
-     * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned.
146
-     * @param int                   $stackPtr  The position of the current token in
147
-     *                                         the stack passed in $tokens.
148
-     *
149
-     * @return void
150
-     */
151
-    public function process(File $phpcsFile, $stackPtr)
152
-    {
153
-        $tokens    = $phpcsFile->getTokens();
154
-        $tokenType = $tokens[$stackPtr]['type'];
142
+	/**
143
+	 * Processes this test, when one of its tokens is encountered.
144
+	 *
145
+	 * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned.
146
+	 * @param int                   $stackPtr  The position of the current token in
147
+	 *                                         the stack passed in $tokens.
148
+	 *
149
+	 * @return void
150
+	 */
151
+	public function process(File $phpcsFile, $stackPtr)
152
+	{
153
+		$tokens    = $phpcsFile->getTokens();
154
+		$tokenType = $tokens[$stackPtr]['type'];
155 155
 
156
-        // Translate older PHPCS token combis for new operators to the actual operator.
157
-        if (isset($this->newOperators[$tokenType]) === false) {
158
-            if (isset($this->PHPCSCompatTranslate[$tokenType])
159
-                && ((isset($this->PHPCSCompatTranslate[$tokenType]['before'], $tokens[$stackPtr - 1]) === true
160
-                    && $tokens[$stackPtr - 1]['type'] === $this->PHPCSCompatTranslate[$tokenType]['before'])
161
-                || (isset($this->PHPCSCompatTranslate[$tokenType]['callback']) === true
162
-                    && \call_user_func(array($this, $this->PHPCSCompatTranslate[$tokenType]['callback']), $tokens, $stackPtr) === true))
163
-            ) {
164
-                $tokenType = $this->PHPCSCompatTranslate[$tokenType]['real_token'];
165
-            }
166
-        } elseif ($tokenType === 'T_COALESCE') {
167
-            // Make sure that T_COALESCE is not confused with T_COALESCE_EQUAL.
168
-            if (isset($tokens[($stackPtr + 1)]) !== false && $tokens[($stackPtr + 1)]['code'] === \T_EQUAL) {
169
-                // Ignore as will be dealt with via the T_EQUAL token.
170
-                return;
171
-            }
172
-        }
156
+		// Translate older PHPCS token combis for new operators to the actual operator.
157
+		if (isset($this->newOperators[$tokenType]) === false) {
158
+			if (isset($this->PHPCSCompatTranslate[$tokenType])
159
+				&& ((isset($this->PHPCSCompatTranslate[$tokenType]['before'], $tokens[$stackPtr - 1]) === true
160
+					&& $tokens[$stackPtr - 1]['type'] === $this->PHPCSCompatTranslate[$tokenType]['before'])
161
+				|| (isset($this->PHPCSCompatTranslate[$tokenType]['callback']) === true
162
+					&& \call_user_func(array($this, $this->PHPCSCompatTranslate[$tokenType]['callback']), $tokens, $stackPtr) === true))
163
+			) {
164
+				$tokenType = $this->PHPCSCompatTranslate[$tokenType]['real_token'];
165
+			}
166
+		} elseif ($tokenType === 'T_COALESCE') {
167
+			// Make sure that T_COALESCE is not confused with T_COALESCE_EQUAL.
168
+			if (isset($tokens[($stackPtr + 1)]) !== false && $tokens[($stackPtr + 1)]['code'] === \T_EQUAL) {
169
+				// Ignore as will be dealt with via the T_EQUAL token.
170
+				return;
171
+			}
172
+		}
173 173
 
174
-        // If the translation did not yield one of the tokens we are looking for, bow out.
175
-        if (isset($this->newOperators[$tokenType]) === false) {
176
-            return;
177
-        }
174
+		// If the translation did not yield one of the tokens we are looking for, bow out.
175
+		if (isset($this->newOperators[$tokenType]) === false) {
176
+			return;
177
+		}
178 178
 
179
-        $itemInfo = array(
180
-            'name' => $tokenType,
181
-        );
182
-        $this->handleFeature($phpcsFile, $stackPtr, $itemInfo);
183
-    }
179
+		$itemInfo = array(
180
+			'name' => $tokenType,
181
+		);
182
+		$this->handleFeature($phpcsFile, $stackPtr, $itemInfo);
183
+	}
184 184
 
185 185
 
186
-    /**
187
-     * Get the relevant sub-array for a specific item from a multi-dimensional array.
188
-     *
189
-     * @param array $itemInfo Base information about the item.
190
-     *
191
-     * @return array Version and other information about the item.
192
-     */
193
-    public function getItemArray(array $itemInfo)
194
-    {
195
-        return $this->newOperators[$itemInfo['name']];
196
-    }
186
+	/**
187
+	 * Get the relevant sub-array for a specific item from a multi-dimensional array.
188
+	 *
189
+	 * @param array $itemInfo Base information about the item.
190
+	 *
191
+	 * @return array Version and other information about the item.
192
+	 */
193
+	public function getItemArray(array $itemInfo)
194
+	{
195
+		return $this->newOperators[$itemInfo['name']];
196
+	}
197 197
 
198 198
 
199
-    /**
200
-     * Get an array of the non-PHP-version array keys used in a sub-array.
201
-     *
202
-     * @return array
203
-     */
204
-    protected function getNonVersionArrayKeys()
205
-    {
206
-        return array('description');
207
-    }
199
+	/**
200
+	 * Get an array of the non-PHP-version array keys used in a sub-array.
201
+	 *
202
+	 * @return array
203
+	 */
204
+	protected function getNonVersionArrayKeys()
205
+	{
206
+		return array('description');
207
+	}
208 208
 
209 209
 
210
-    /**
211
-     * Retrieve the relevant detail (version) information for use in an error message.
212
-     *
213
-     * @param array $itemArray Version and other information about the item.
214
-     * @param array $itemInfo  Base information about the item.
215
-     *
216
-     * @return array
217
-     */
218
-    public function getErrorInfo(array $itemArray, array $itemInfo)
219
-    {
220
-        $errorInfo                = parent::getErrorInfo($itemArray, $itemInfo);
221
-        $errorInfo['description'] = $itemArray['description'];
210
+	/**
211
+	 * Retrieve the relevant detail (version) information for use in an error message.
212
+	 *
213
+	 * @param array $itemArray Version and other information about the item.
214
+	 * @param array $itemInfo  Base information about the item.
215
+	 *
216
+	 * @return array
217
+	 */
218
+	public function getErrorInfo(array $itemArray, array $itemInfo)
219
+	{
220
+		$errorInfo                = parent::getErrorInfo($itemArray, $itemInfo);
221
+		$errorInfo['description'] = $itemArray['description'];
222 222
 
223
-        return $errorInfo;
224
-    }
223
+		return $errorInfo;
224
+	}
225 225
 
226 226
 
227
-    /**
228
-     * Allow for concrete child classes to filter the error data before it's passed to PHPCS.
229
-     *
230
-     * @param array $data      The error data array which was created.
231
-     * @param array $itemInfo  Base information about the item this error message applies to.
232
-     * @param array $errorInfo Detail information about an item this error message applies to.
233
-     *
234
-     * @return array
235
-     */
236
-    protected function filterErrorData(array $data, array $itemInfo, array $errorInfo)
237
-    {
238
-        $data[0] = $errorInfo['description'];
239
-        return $data;
240
-    }
227
+	/**
228
+	 * Allow for concrete child classes to filter the error data before it's passed to PHPCS.
229
+	 *
230
+	 * @param array $data      The error data array which was created.
231
+	 * @param array $itemInfo  Base information about the item this error message applies to.
232
+	 * @param array $errorInfo Detail information about an item this error message applies to.
233
+	 *
234
+	 * @return array
235
+	 */
236
+	protected function filterErrorData(array $data, array $itemInfo, array $errorInfo)
237
+	{
238
+		$data[0] = $errorInfo['description'];
239
+		return $data;
240
+	}
241 241
 
242 242
 
243
-    /**
244
-     * Callback function to determine whether a T_EQUAL token is really a T_COALESCE_EQUAL token.
245
-     *
246
-     * @param array $tokens   The token stack.
247
-     * @param int   $stackPtr The current position in the token stack.
248
-     *
249
-     * @return bool
250
-     */
251
-    private function isTCoalesceEqual($tokens, $stackPtr)
252
-    {
253
-        if ($tokens[$stackPtr]['code'] !== \T_EQUAL || isset($tokens[($stackPtr - 1)]) === false) {
254
-            // Function called for wrong token or token has no predecesor.
255
-            return false;
256
-        }
243
+	/**
244
+	 * Callback function to determine whether a T_EQUAL token is really a T_COALESCE_EQUAL token.
245
+	 *
246
+	 * @param array $tokens   The token stack.
247
+	 * @param int   $stackPtr The current position in the token stack.
248
+	 *
249
+	 * @return bool
250
+	 */
251
+	private function isTCoalesceEqual($tokens, $stackPtr)
252
+	{
253
+		if ($tokens[$stackPtr]['code'] !== \T_EQUAL || isset($tokens[($stackPtr - 1)]) === false) {
254
+			// Function called for wrong token or token has no predecesor.
255
+			return false;
256
+		}
257 257
 
258
-        if ($tokens[($stackPtr - 1)]['type'] === 'T_COALESCE') {
259
-            return true;
260
-        }
261
-        if ($tokens[($stackPtr - 1)]['type'] === 'T_INLINE_THEN'
262
-            && (isset($tokens[($stackPtr - 2)]) && $tokens[($stackPtr - 2)]['type'] === 'T_INLINE_THEN')
263
-        ) {
264
-            return true;
265
-        }
258
+		if ($tokens[($stackPtr - 1)]['type'] === 'T_COALESCE') {
259
+			return true;
260
+		}
261
+		if ($tokens[($stackPtr - 1)]['type'] === 'T_INLINE_THEN'
262
+			&& (isset($tokens[($stackPtr - 2)]) && $tokens[($stackPtr - 2)]['type'] === 'T_INLINE_THEN')
263
+		) {
264
+			return true;
265
+		}
266 266
 
267
-        return false;
268
-    }
267
+		return false;
268
+	}
269 269
 
270
-    /**
271
-     * Callback function to determine whether a T_INLINE_THEN token is really a T_COALESCE token.
272
-     *
273
-     * @param array $tokens   The token stack.
274
-     * @param int   $stackPtr The current position in the token stack.
275
-     *
276
-     * @return bool
277
-     */
278
-    private function isTCoalesce($tokens, $stackPtr)
279
-    {
280
-        if ($tokens[$stackPtr]['code'] !== \T_INLINE_THEN || isset($tokens[($stackPtr - 1)]) === false) {
281
-            // Function called for wrong token or token has no predecesor.
282
-            return false;
283
-        }
270
+	/**
271
+	 * Callback function to determine whether a T_INLINE_THEN token is really a T_COALESCE token.
272
+	 *
273
+	 * @param array $tokens   The token stack.
274
+	 * @param int   $stackPtr The current position in the token stack.
275
+	 *
276
+	 * @return bool
277
+	 */
278
+	private function isTCoalesce($tokens, $stackPtr)
279
+	{
280
+		if ($tokens[$stackPtr]['code'] !== \T_INLINE_THEN || isset($tokens[($stackPtr - 1)]) === false) {
281
+			// Function called for wrong token or token has no predecesor.
282
+			return false;
283
+		}
284 284
 
285
-        if ($tokens[($stackPtr - 1)]['code'] === \T_INLINE_THEN) {
286
-            // Make sure not to confuse it with the T_COALESCE_EQUAL token.
287
-            if (isset($tokens[($stackPtr + 1)]) === false || $tokens[($stackPtr + 1)]['code'] !== \T_EQUAL) {
288
-                return true;
289
-            }
290
-        }
285
+		if ($tokens[($stackPtr - 1)]['code'] === \T_INLINE_THEN) {
286
+			// Make sure not to confuse it with the T_COALESCE_EQUAL token.
287
+			if (isset($tokens[($stackPtr + 1)]) === false || $tokens[($stackPtr + 1)]['code'] !== \T_EQUAL) {
288
+				return true;
289
+			}
290
+		}
291 291
 
292
-        return false;
293
-    }
292
+		return false;
293
+	}
294 294
 }
Please login to merge, or discard this patch.
php-compatibility/PHPCompatibility/Sniffs/Upgrade/LowPHPCSSniff.php 1 patch
Indentation   +110 added lines, -110 removed lines patch added patch discarded remove patch
@@ -34,96 +34,96 @@  discard block
 block discarded – undo
34 34
  */
35 35
 class LowPHPCSSniff extends Sniff
36 36
 {
37
-    /**
38
-     * The minimum supported PHPCS version.
39
-     *
40
-     * Users on PHPCS versions below this will see an ERROR message.
41
-     *
42
-     * @var string
43
-     */
44
-    protected $minSupportedVersion = '2.3.0';
45
-
46
-    /**
47
-     * The minimum recommended PHPCS version.
48
-     *
49
-     * Users on PHPCS versions below this will see a WARNING.
50
-     *
51
-     * @var string
52
-     */
53
-    protected $minRecommendedVersion = '2.6.0';
54
-
55
-    /**
56
-     * Keep track of whether this sniff needs to actually run.
57
-     *
58
-     * This will be set to `false` when either a high enough PHPCS
59
-     * version is detected or once the error/warning has been thrown,
60
-     * to make sure that the notice will only be thrown once per run.
61
-     *
62
-     * @var bool
63
-     */
64
-    private $examine = true;
65
-
66
-
67
-    /**
68
-     * Returns an array of tokens this test wants to listen for.
69
-     *
70
-     * @return array
71
-     */
72
-    public function register()
73
-    {
74
-        return array(
75
-            \T_OPEN_TAG,
76
-        );
77
-    }
78
-
79
-    /**
80
-     * Processes this test, when one of its tokens is encountered.
81
-     *
82
-     * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned.
83
-     * @param int                   $stackPtr  The position of the current token in the
84
-     *                                         stack passed in $tokens.
85
-     *
86
-     * @return int|void Integer stack pointer to skip forward or void to continue
87
-     *                  normal file processing.
88
-     */
89
-    public function process(File $phpcsFile, $stackPtr)
90
-    {
91
-        // Don't do anything if the warning has already been thrown or is not necessary.
92
-        if ($this->examine === false) {
93
-            return ($phpcsFile->numTokens + 1);
94
-        }
95
-
96
-        $phpcsVersion = PHPCSHelper::getVersion();
97
-
98
-        // Don't do anything if the PHPCS version used is above the minimum recommended version.
99
-        if (version_compare($phpcsVersion, $this->minRecommendedVersion, '>=')) {
100
-            $this->examine = false;
101
-            return ($phpcsFile->numTokens + 1);
102
-        }
103
-
104
-        if (version_compare($phpcsVersion, $this->minSupportedVersion, '<')) {
105
-            $isError      = true;
106
-            $message      = "IMPORTANT: Please be advised that the minimum PHP_CodeSniffer version the PHPCompatibility standard supports is %s. You are currently using PHP_CodeSniffer %s. Please upgrade your PHP_CodeSniffer installation. The recommended version of PHP_CodeSniffer for PHPCompatibility is %s or higher.";
107
-            $errorCode    = 'Unsupported_' . $this->stringToErrorCode($this->minSupportedVersion);
108
-            $replacements = array(
109
-                $this->minSupportedVersion,
110
-                $phpcsVersion,
111
-                $this->minRecommendedVersion,
112
-                $errorCode,
113
-            );
114
-        } else {
115
-            $isError      = false;
116
-            $message      = "IMPORTANT: Please be advised that for the most reliable PHPCompatibility results, PHP_CodeSniffer %s or higher should be used. Support for lower versions will be dropped in the foreseeable future. You are currently using PHP_CodeSniffer %s. Please upgrade your PHP_CodeSniffer installation to version %s or higher.";
117
-            $errorCode    = 'BelowRecommended_' . $this->stringToErrorCode($this->minRecommendedVersion);
118
-            $replacements = array(
119
-                $this->minRecommendedVersion,
120
-                $phpcsVersion,
121
-                $this->minRecommendedVersion,
122
-                $errorCode,
123
-            );
124
-        }
125
-
126
-        /*
37
+	/**
38
+	 * The minimum supported PHPCS version.
39
+	 *
40
+	 * Users on PHPCS versions below this will see an ERROR message.
41
+	 *
42
+	 * @var string
43
+	 */
44
+	protected $minSupportedVersion = '2.3.0';
45
+
46
+	/**
47
+	 * The minimum recommended PHPCS version.
48
+	 *
49
+	 * Users on PHPCS versions below this will see a WARNING.
50
+	 *
51
+	 * @var string
52
+	 */
53
+	protected $minRecommendedVersion = '2.6.0';
54
+
55
+	/**
56
+	 * Keep track of whether this sniff needs to actually run.
57
+	 *
58
+	 * This will be set to `false` when either a high enough PHPCS
59
+	 * version is detected or once the error/warning has been thrown,
60
+	 * to make sure that the notice will only be thrown once per run.
61
+	 *
62
+	 * @var bool
63
+	 */
64
+	private $examine = true;
65
+
66
+
67
+	/**
68
+	 * Returns an array of tokens this test wants to listen for.
69
+	 *
70
+	 * @return array
71
+	 */
72
+	public function register()
73
+	{
74
+		return array(
75
+			\T_OPEN_TAG,
76
+		);
77
+	}
78
+
79
+	/**
80
+	 * Processes this test, when one of its tokens is encountered.
81
+	 *
82
+	 * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned.
83
+	 * @param int                   $stackPtr  The position of the current token in the
84
+	 *                                         stack passed in $tokens.
85
+	 *
86
+	 * @return int|void Integer stack pointer to skip forward or void to continue
87
+	 *                  normal file processing.
88
+	 */
89
+	public function process(File $phpcsFile, $stackPtr)
90
+	{
91
+		// Don't do anything if the warning has already been thrown or is not necessary.
92
+		if ($this->examine === false) {
93
+			return ($phpcsFile->numTokens + 1);
94
+		}
95
+
96
+		$phpcsVersion = PHPCSHelper::getVersion();
97
+
98
+		// Don't do anything if the PHPCS version used is above the minimum recommended version.
99
+		if (version_compare($phpcsVersion, $this->minRecommendedVersion, '>=')) {
100
+			$this->examine = false;
101
+			return ($phpcsFile->numTokens + 1);
102
+		}
103
+
104
+		if (version_compare($phpcsVersion, $this->minSupportedVersion, '<')) {
105
+			$isError      = true;
106
+			$message      = "IMPORTANT: Please be advised that the minimum PHP_CodeSniffer version the PHPCompatibility standard supports is %s. You are currently using PHP_CodeSniffer %s. Please upgrade your PHP_CodeSniffer installation. The recommended version of PHP_CodeSniffer for PHPCompatibility is %s or higher.";
107
+			$errorCode    = 'Unsupported_' . $this->stringToErrorCode($this->minSupportedVersion);
108
+			$replacements = array(
109
+				$this->minSupportedVersion,
110
+				$phpcsVersion,
111
+				$this->minRecommendedVersion,
112
+				$errorCode,
113
+			);
114
+		} else {
115
+			$isError      = false;
116
+			$message      = "IMPORTANT: Please be advised that for the most reliable PHPCompatibility results, PHP_CodeSniffer %s or higher should be used. Support for lower versions will be dropped in the foreseeable future. You are currently using PHP_CodeSniffer %s. Please upgrade your PHP_CodeSniffer installation to version %s or higher.";
117
+			$errorCode    = 'BelowRecommended_' . $this->stringToErrorCode($this->minRecommendedVersion);
118
+			$replacements = array(
119
+				$this->minRecommendedVersion,
120
+				$phpcsVersion,
121
+				$this->minRecommendedVersion,
122
+				$errorCode,
123
+			);
124
+		}
125
+
126
+		/*
127 127
          * Figure out the report width to determine how long the delimiter lines should be.
128 128
          *
129 129
          * This is not an exact calculation as there are a number of unknowns at the time the
@@ -149,24 +149,24 @@  discard block
 block discarded – undo
149 149
          * If/when the upstream PR has been merged and the minimum supported/recommended version
150 150
          * of PHPCompatibility would go beyond that, the below code should be adjusted.}}
151 151
          */
152
-        $reportWidth = PHPCSHelper::getCommandLineData($phpcsFile, 'reportWidth');
153
-        $showSources = PHPCSHelper::getCommandLineData($phpcsFile, 'showSources');
154
-        if ($showSources === true && version_compare($phpcsVersion, '2.3.0', '>=')) {
155
-            $reportWidth += 6;
156
-        }
157
-
158
-        $messageWidth  = ($reportWidth - 15); // 15 is length of " # | WARNING | ".
159
-        $delimiterLine = str_repeat('-', ($messageWidth));
160
-        $disableNotice = 'To disable this notice, add --exclude=PHPCompatibility.Upgrade.LowPHPCS to your command or add <exclude name="PHPCompatibility.Upgrade.LowPHPCS.%s"/> to your custom ruleset. ';
161
-        $thankYou      = 'Thank you for using PHPCompatibility!';
162
-
163
-        $message .= ' ' . $delimiterLine;
164
-        $message .= ' ' . $disableNotice;
165
-        $message .= ' ' . $delimiterLine;
166
-        $message .= ' ' . $thankYou;
167
-
168
-        $this->addMessage($phpcsFile, $message, 0, $isError, $errorCode, $replacements);
169
-
170
-        $this->examine = false;
171
-    }
152
+		$reportWidth = PHPCSHelper::getCommandLineData($phpcsFile, 'reportWidth');
153
+		$showSources = PHPCSHelper::getCommandLineData($phpcsFile, 'showSources');
154
+		if ($showSources === true && version_compare($phpcsVersion, '2.3.0', '>=')) {
155
+			$reportWidth += 6;
156
+		}
157
+
158
+		$messageWidth  = ($reportWidth - 15); // 15 is length of " # | WARNING | ".
159
+		$delimiterLine = str_repeat('-', ($messageWidth));
160
+		$disableNotice = 'To disable this notice, add --exclude=PHPCompatibility.Upgrade.LowPHPCS to your command or add <exclude name="PHPCompatibility.Upgrade.LowPHPCS.%s"/> to your custom ruleset. ';
161
+		$thankYou      = 'Thank you for using PHPCompatibility!';
162
+
163
+		$message .= ' ' . $delimiterLine;
164
+		$message .= ' ' . $disableNotice;
165
+		$message .= ' ' . $delimiterLine;
166
+		$message .= ' ' . $thankYou;
167
+
168
+		$this->addMessage($phpcsFile, $message, 0, $isError, $errorCode, $replacements);
169
+
170
+		$this->examine = false;
171
+	}
172 172
 }
Please login to merge, or discard this patch.
PHPCompatibility/Sniffs/Variables/ForbiddenThisUseContextsSniff.php 1 patch
Indentation   +356 added lines, -356 removed lines patch added patch discarded remove patch
@@ -50,375 +50,375 @@
 block discarded – undo
50 50
 class ForbiddenThisUseContextsSniff extends Sniff
51 51
 {
52 52
 
53
-    /**
54
-     * OO scope tokens.
55
-     *
56
-     * Duplicate of Tokens::$ooScopeTokens array in PHPCS which was added in 3.1.0.
57
-     *
58
-     * @since 9.1.0
59
-     *
60
-     * @var array
61
-     */
62
-    private $ooScopeTokens = array(
63
-        'T_CLASS'     => \T_CLASS,
64
-        'T_INTERFACE' => \T_INTERFACE,
65
-        'T_TRAIT'     => \T_TRAIT,
66
-    );
67
-
68
-    /**
69
-     * Scopes to skip over when examining the contents of functions.
70
-     *
71
-     * @since 9.1.0
72
-     *
73
-     * @var array
74
-     */
75
-    private $skipOverScopes = array(
76
-        'T_FUNCTION' => true,
77
-        'T_CLOSURE'  => true,
78
-    );
79
-
80
-    /**
81
-     * Valid uses of $this in plain functions or methods outside object context.
82
-     *
83
-     * @since 9.1.0
84
-     *
85
-     * @var array
86
-     */
87
-    private $validUseOutsideObject = array(
88
-        \T_ISSET => true,
89
-        \T_EMPTY => true,
90
-    );
91
-
92
-    /**
93
-     * Returns an array of tokens this test wants to listen for.
94
-     *
95
-     * @since 9.1.0
96
-     *
97
-     * @return array
98
-     */
99
-    public function register()
100
-    {
101
-        if (\defined('T_ANON_CLASS')) {
102
-            $this->ooScopeTokens['T_ANON_CLASS'] = \T_ANON_CLASS;
103
-        }
104
-
105
-        $this->skipOverScopes += $this->ooScopeTokens;
106
-
107
-        return array(
108
-            \T_FUNCTION,
109
-            \T_CLOSURE,
110
-            \T_GLOBAL,
111
-            \T_CATCH,
112
-            \T_FOREACH,
113
-            \T_UNSET,
114
-        );
115
-    }
116
-
117
-    /**
118
-     * Processes this test, when one of its tokens is encountered.
119
-     *
120
-     * @since 9.1.0
121
-     *
122
-     * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned.
123
-     * @param int                   $stackPtr  The position of the current token in
124
-     *                                         the stack passed in $tokens.
125
-     *
126
-     * @return void
127
-     */
128
-    public function process(File $phpcsFile, $stackPtr)
129
-    {
130
-        if ($this->supportsAbove('7.1') === false) {
131
-            return;
132
-        }
133
-
134
-        $tokens = $phpcsFile->getTokens();
135
-
136
-        switch ($tokens[$stackPtr]['code']) {
137
-            case \T_FUNCTION:
138
-                $this->isThisUsedAsParameter($phpcsFile, $stackPtr);
139
-                $this->isThisUsedOutsideObjectContext($phpcsFile, $stackPtr);
140
-                break;
141
-
142
-            case \T_CLOSURE:
143
-                $this->isThisUsedAsParameter($phpcsFile, $stackPtr);
144
-                break;
145
-
146
-            case \T_GLOBAL:
147
-                /*
53
+	/**
54
+	 * OO scope tokens.
55
+	 *
56
+	 * Duplicate of Tokens::$ooScopeTokens array in PHPCS which was added in 3.1.0.
57
+	 *
58
+	 * @since 9.1.0
59
+	 *
60
+	 * @var array
61
+	 */
62
+	private $ooScopeTokens = array(
63
+		'T_CLASS'     => \T_CLASS,
64
+		'T_INTERFACE' => \T_INTERFACE,
65
+		'T_TRAIT'     => \T_TRAIT,
66
+	);
67
+
68
+	/**
69
+	 * Scopes to skip over when examining the contents of functions.
70
+	 *
71
+	 * @since 9.1.0
72
+	 *
73
+	 * @var array
74
+	 */
75
+	private $skipOverScopes = array(
76
+		'T_FUNCTION' => true,
77
+		'T_CLOSURE'  => true,
78
+	);
79
+
80
+	/**
81
+	 * Valid uses of $this in plain functions or methods outside object context.
82
+	 *
83
+	 * @since 9.1.0
84
+	 *
85
+	 * @var array
86
+	 */
87
+	private $validUseOutsideObject = array(
88
+		\T_ISSET => true,
89
+		\T_EMPTY => true,
90
+	);
91
+
92
+	/**
93
+	 * Returns an array of tokens this test wants to listen for.
94
+	 *
95
+	 * @since 9.1.0
96
+	 *
97
+	 * @return array
98
+	 */
99
+	public function register()
100
+	{
101
+		if (\defined('T_ANON_CLASS')) {
102
+			$this->ooScopeTokens['T_ANON_CLASS'] = \T_ANON_CLASS;
103
+		}
104
+
105
+		$this->skipOverScopes += $this->ooScopeTokens;
106
+
107
+		return array(
108
+			\T_FUNCTION,
109
+			\T_CLOSURE,
110
+			\T_GLOBAL,
111
+			\T_CATCH,
112
+			\T_FOREACH,
113
+			\T_UNSET,
114
+		);
115
+	}
116
+
117
+	/**
118
+	 * Processes this test, when one of its tokens is encountered.
119
+	 *
120
+	 * @since 9.1.0
121
+	 *
122
+	 * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned.
123
+	 * @param int                   $stackPtr  The position of the current token in
124
+	 *                                         the stack passed in $tokens.
125
+	 *
126
+	 * @return void
127
+	 */
128
+	public function process(File $phpcsFile, $stackPtr)
129
+	{
130
+		if ($this->supportsAbove('7.1') === false) {
131
+			return;
132
+		}
133
+
134
+		$tokens = $phpcsFile->getTokens();
135
+
136
+		switch ($tokens[$stackPtr]['code']) {
137
+			case \T_FUNCTION:
138
+				$this->isThisUsedAsParameter($phpcsFile, $stackPtr);
139
+				$this->isThisUsedOutsideObjectContext($phpcsFile, $stackPtr);
140
+				break;
141
+
142
+			case \T_CLOSURE:
143
+				$this->isThisUsedAsParameter($phpcsFile, $stackPtr);
144
+				break;
145
+
146
+			case \T_GLOBAL:
147
+				/*
148 148
                  * $this can no longer be imported using the `global` keyword.
149 149
                  * This worked in PHP 7.0, though in PHP 5.x, it would throw a
150 150
                  * fatal "Cannot re-assign $this" error.
151 151
                  */
152
-                $endOfStatement = $phpcsFile->findNext(array(\T_SEMICOLON, \T_CLOSE_TAG), ($stackPtr + 1));
153
-                if ($endOfStatement === false) {
154
-                    // No semi-colon - live coding.
155
-                    return;
156
-                }
157
-
158
-                for ($i = ($stackPtr + 1); $i < $endOfStatement; $i++) {
159
-                    if ($tokens[$i]['code'] !== \T_VARIABLE || $tokens[$i]['content'] !== '$this') {
160
-                        continue;
161
-                    }
162
-
163
-                    $phpcsFile->addError(
164
-                        '"$this" can no longer be used with the "global" keyword since PHP 7.1.',
165
-                        $i,
166
-                        'Global'
167
-                    );
168
-                }
169
-
170
-                break;
171
-
172
-            case \T_CATCH:
173
-                /*
152
+				$endOfStatement = $phpcsFile->findNext(array(\T_SEMICOLON, \T_CLOSE_TAG), ($stackPtr + 1));
153
+				if ($endOfStatement === false) {
154
+					// No semi-colon - live coding.
155
+					return;
156
+				}
157
+
158
+				for ($i = ($stackPtr + 1); $i < $endOfStatement; $i++) {
159
+					if ($tokens[$i]['code'] !== \T_VARIABLE || $tokens[$i]['content'] !== '$this') {
160
+						continue;
161
+					}
162
+
163
+					$phpcsFile->addError(
164
+						'"$this" can no longer be used with the "global" keyword since PHP 7.1.',
165
+						$i,
166
+						'Global'
167
+					);
168
+				}
169
+
170
+				break;
171
+
172
+			case \T_CATCH:
173
+				/*
174 174
                  * $this can no longer be used as a catch variable.
175 175
                  */
176
-                if (isset($tokens[$stackPtr]['parenthesis_opener'], $tokens[$stackPtr]['parenthesis_closer']) === false) {
177
-                    return;
178
-                }
179
-
180
-                $varPtr = $phpcsFile->findNext(
181
-                    \T_VARIABLE,
182
-                    ($tokens[$stackPtr]['parenthesis_opener'] + 1),
183
-                    $tokens[$stackPtr]['parenthesis_closer']
184
-                );
185
-
186
-                if ($varPtr === false || $tokens[$varPtr]['content'] !== '$this') {
187
-                    return;
188
-                }
189
-
190
-                $phpcsFile->addError(
191
-                    '"$this" can no longer be used as a catch variable since PHP 7.1.',
192
-                    $varPtr,
193
-                    'Catch'
194
-                );
195
-
196
-                break;
197
-
198
-            case \T_FOREACH:
199
-                /*
176
+				if (isset($tokens[$stackPtr]['parenthesis_opener'], $tokens[$stackPtr]['parenthesis_closer']) === false) {
177
+					return;
178
+				}
179
+
180
+				$varPtr = $phpcsFile->findNext(
181
+					\T_VARIABLE,
182
+					($tokens[$stackPtr]['parenthesis_opener'] + 1),
183
+					$tokens[$stackPtr]['parenthesis_closer']
184
+				);
185
+
186
+				if ($varPtr === false || $tokens[$varPtr]['content'] !== '$this') {
187
+					return;
188
+				}
189
+
190
+				$phpcsFile->addError(
191
+					'"$this" can no longer be used as a catch variable since PHP 7.1.',
192
+					$varPtr,
193
+					'Catch'
194
+				);
195
+
196
+				break;
197
+
198
+			case \T_FOREACH:
199
+				/*
200 200
                  * $this can no longer be used as a foreach *value* variable.
201 201
                  * This worked in PHP 7.0, though in PHP 5.x, it would throw a
202 202
                  * fatal "Cannot re-assign $this" error.
203 203
                  */
204
-                if (isset($tokens[$stackPtr]['parenthesis_opener'], $tokens[$stackPtr]['parenthesis_closer']) === false) {
205
-                    return;
206
-                }
207
-
208
-                $stopPtr = $phpcsFile->findPrevious(
209
-                    array(\T_AS, \T_DOUBLE_ARROW),
210
-                    ($tokens[$stackPtr]['parenthesis_closer'] - 1),
211
-                    $tokens[$stackPtr]['parenthesis_opener']
212
-                );
213
-                if ($stopPtr === false) {
214
-                    return;
215
-                }
216
-
217
-                $valueVarPtr = $phpcsFile->findNext(
218
-                    \T_VARIABLE,
219
-                    ($stopPtr + 1),
220
-                    $tokens[$stackPtr]['parenthesis_closer']
221
-                );
222
-                if ($valueVarPtr === false || $tokens[$valueVarPtr]['content'] !== '$this') {
223
-                    return;
224
-                }
225
-
226
-                $afterThis = $phpcsFile->findNext(
227
-                    Tokens::$emptyTokens,
228
-                    ($valueVarPtr + 1),
229
-                    $tokens[$stackPtr]['parenthesis_closer'],
230
-                    true
231
-                );
232
-
233
-                if ($afterThis !== false
234
-                    && ($tokens[$afterThis]['code'] === \T_OBJECT_OPERATOR
235
-                        || $tokens[$afterThis]['code'] === \T_DOUBLE_COLON)
236
-                ) {
237
-                    return;
238
-                }
239
-
240
-                $phpcsFile->addError(
241
-                    '"$this" can no longer be used as value variable in a foreach control structure since PHP 7.1.',
242
-                    $valueVarPtr,
243
-                    'ForeachValueVar'
244
-                );
245
-
246
-                break;
247
-
248
-            case \T_UNSET:
249
-                /*
204
+				if (isset($tokens[$stackPtr]['parenthesis_opener'], $tokens[$stackPtr]['parenthesis_closer']) === false) {
205
+					return;
206
+				}
207
+
208
+				$stopPtr = $phpcsFile->findPrevious(
209
+					array(\T_AS, \T_DOUBLE_ARROW),
210
+					($tokens[$stackPtr]['parenthesis_closer'] - 1),
211
+					$tokens[$stackPtr]['parenthesis_opener']
212
+				);
213
+				if ($stopPtr === false) {
214
+					return;
215
+				}
216
+
217
+				$valueVarPtr = $phpcsFile->findNext(
218
+					\T_VARIABLE,
219
+					($stopPtr + 1),
220
+					$tokens[$stackPtr]['parenthesis_closer']
221
+				);
222
+				if ($valueVarPtr === false || $tokens[$valueVarPtr]['content'] !== '$this') {
223
+					return;
224
+				}
225
+
226
+				$afterThis = $phpcsFile->findNext(
227
+					Tokens::$emptyTokens,
228
+					($valueVarPtr + 1),
229
+					$tokens[$stackPtr]['parenthesis_closer'],
230
+					true
231
+				);
232
+
233
+				if ($afterThis !== false
234
+					&& ($tokens[$afterThis]['code'] === \T_OBJECT_OPERATOR
235
+						|| $tokens[$afterThis]['code'] === \T_DOUBLE_COLON)
236
+				) {
237
+					return;
238
+				}
239
+
240
+				$phpcsFile->addError(
241
+					'"$this" can no longer be used as value variable in a foreach control structure since PHP 7.1.',
242
+					$valueVarPtr,
243
+					'ForeachValueVar'
244
+				);
245
+
246
+				break;
247
+
248
+			case \T_UNSET:
249
+				/*
250 250
                  * $this can no longer be unset.
251 251
                  */
252
-                $openParenthesis = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true);
253
-                if ($openParenthesis === false
254
-                    || $tokens[$openParenthesis]['code'] !== \T_OPEN_PARENTHESIS
255
-                    || isset($tokens[$openParenthesis]['parenthesis_closer']) === false
256
-                ) {
257
-                    return;
258
-                }
259
-
260
-                for ($i = ($openParenthesis + 1); $i < $tokens[$openParenthesis]['parenthesis_closer']; $i++) {
261
-                    if ($tokens[$i]['code'] !== \T_VARIABLE || $tokens[$i]['content'] !== '$this') {
262
-                        continue;
263
-                    }
264
-
265
-                    $afterThis = $phpcsFile->findNext(
266
-                        Tokens::$emptyTokens,
267
-                        ($i + 1),
268
-                        $tokens[$openParenthesis]['parenthesis_closer'],
269
-                        true
270
-                    );
271
-
272
-                    if ($afterThis !== false
273
-                        && ($tokens[$afterThis]['code'] === \T_OBJECT_OPERATOR
274
-                            || $tokens[$afterThis]['code'] === \T_DOUBLE_COLON
275
-                            || $tokens[$afterThis]['code'] === \T_OPEN_SQUARE_BRACKET)
276
-                    ) {
277
-                        $i = $afterThis;
278
-                        continue;
279
-                    }
280
-
281
-                    $phpcsFile->addError(
282
-                        '"$this" can no longer be unset since PHP 7.1.',
283
-                        $i,
284
-                        'Unset'
285
-                    );
286
-                }
287
-
288
-                break;
289
-        }
290
-    }
291
-
292
-    /**
293
-     * Check if $this is used as a parameter in a function declaration.
294
-     *
295
-     * $this can no longer be used as a parameter in a *global* function.
296
-     * Use as a parameter in a method was already an error prior to PHP 7.1.
297
-     *
298
-     * @since 9.1.0
299
-     *
300
-     * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned.
301
-     * @param int                   $stackPtr  The position of the current token in
302
-     *                                         the stack passed in $tokens.
303
-     *
304
-     * @return void
305
-     */
306
-    protected function isThisUsedAsParameter(File $phpcsFile, $stackPtr)
307
-    {
308
-        if ($this->validDirectScope($phpcsFile, $stackPtr, $this->ooScopeTokens) !== false) {
309
-            return;
310
-        }
311
-
312
-        $params = PHPCSHelper::getMethodParameters($phpcsFile, $stackPtr);
313
-        if (empty($params)) {
314
-            return;
315
-        }
316
-
317
-        $tokens = $phpcsFile->getTokens();
318
-
319
-        foreach ($params as $param) {
320
-            if ($param['name'] !== '$this') {
321
-                continue;
322
-            }
323
-
324
-            if ($tokens[$stackPtr]['code'] === \T_FUNCTION) {
325
-                $phpcsFile->addError(
326
-                    '"$this" can no longer be used as a parameter since PHP 7.1.',
327
-                    $param['token'],
328
-                    'FunctionParam'
329
-                );
330
-            } else {
331
-                $phpcsFile->addError(
332
-                    '"$this" can no longer be used as a closure parameter since PHP 7.0.7.',
333
-                    $param['token'],
334
-                    'ClosureParam'
335
-                );
336
-            }
337
-        }
338
-    }
339
-
340
-    /**
341
-     * Check if $this is used in a plain function or method.
342
-     *
343
-     * Prior to PHP 7.1, this would result in an "undefined variable" notice
344
-     * and execution would continue with $this regarded as `null`.
345
-     * As of PHP 7.1, this throws an exception.
346
-     *
347
-     * Note: use within isset() and empty() to check object context is still allowed.
348
-     * Note: $this can still be used within a closure.
349
-     *
350
-     * @since 9.1.0
351
-     *
352
-     * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned.
353
-     * @param int                   $stackPtr  The position of the current token in
354
-     *                                         the stack passed in $tokens.
355
-     *
356
-     * @return void
357
-     */
358
-    protected function isThisUsedOutsideObjectContext(File $phpcsFile, $stackPtr)
359
-    {
360
-        $tokens = $phpcsFile->getTokens();
361
-
362
-        if (isset($tokens[$stackPtr]['scope_opener'], $tokens[$stackPtr]['scope_closer']) === false) {
363
-            return;
364
-        }
365
-
366
-        if ($this->validDirectScope($phpcsFile, $stackPtr, $this->ooScopeTokens) !== false) {
367
-            $methodProps = $phpcsFile->getMethodProperties($stackPtr);
368
-            if ($methodProps['is_static'] === false) {
369
-                return;
370
-            } else {
371
-                $methodName = $phpcsFile->getDeclarationName($stackPtr);
372
-                if ($methodName === '__call') {
373
-                    /*
252
+				$openParenthesis = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true);
253
+				if ($openParenthesis === false
254
+					|| $tokens[$openParenthesis]['code'] !== \T_OPEN_PARENTHESIS
255
+					|| isset($tokens[$openParenthesis]['parenthesis_closer']) === false
256
+				) {
257
+					return;
258
+				}
259
+
260
+				for ($i = ($openParenthesis + 1); $i < $tokens[$openParenthesis]['parenthesis_closer']; $i++) {
261
+					if ($tokens[$i]['code'] !== \T_VARIABLE || $tokens[$i]['content'] !== '$this') {
262
+						continue;
263
+					}
264
+
265
+					$afterThis = $phpcsFile->findNext(
266
+						Tokens::$emptyTokens,
267
+						($i + 1),
268
+						$tokens[$openParenthesis]['parenthesis_closer'],
269
+						true
270
+					);
271
+
272
+					if ($afterThis !== false
273
+						&& ($tokens[$afterThis]['code'] === \T_OBJECT_OPERATOR
274
+							|| $tokens[$afterThis]['code'] === \T_DOUBLE_COLON
275
+							|| $tokens[$afterThis]['code'] === \T_OPEN_SQUARE_BRACKET)
276
+					) {
277
+						$i = $afterThis;
278
+						continue;
279
+					}
280
+
281
+					$phpcsFile->addError(
282
+						'"$this" can no longer be unset since PHP 7.1.',
283
+						$i,
284
+						'Unset'
285
+					);
286
+				}
287
+
288
+				break;
289
+		}
290
+	}
291
+
292
+	/**
293
+	 * Check if $this is used as a parameter in a function declaration.
294
+	 *
295
+	 * $this can no longer be used as a parameter in a *global* function.
296
+	 * Use as a parameter in a method was already an error prior to PHP 7.1.
297
+	 *
298
+	 * @since 9.1.0
299
+	 *
300
+	 * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned.
301
+	 * @param int                   $stackPtr  The position of the current token in
302
+	 *                                         the stack passed in $tokens.
303
+	 *
304
+	 * @return void
305
+	 */
306
+	protected function isThisUsedAsParameter(File $phpcsFile, $stackPtr)
307
+	{
308
+		if ($this->validDirectScope($phpcsFile, $stackPtr, $this->ooScopeTokens) !== false) {
309
+			return;
310
+		}
311
+
312
+		$params = PHPCSHelper::getMethodParameters($phpcsFile, $stackPtr);
313
+		if (empty($params)) {
314
+			return;
315
+		}
316
+
317
+		$tokens = $phpcsFile->getTokens();
318
+
319
+		foreach ($params as $param) {
320
+			if ($param['name'] !== '$this') {
321
+				continue;
322
+			}
323
+
324
+			if ($tokens[$stackPtr]['code'] === \T_FUNCTION) {
325
+				$phpcsFile->addError(
326
+					'"$this" can no longer be used as a parameter since PHP 7.1.',
327
+					$param['token'],
328
+					'FunctionParam'
329
+				);
330
+			} else {
331
+				$phpcsFile->addError(
332
+					'"$this" can no longer be used as a closure parameter since PHP 7.0.7.',
333
+					$param['token'],
334
+					'ClosureParam'
335
+				);
336
+			}
337
+		}
338
+	}
339
+
340
+	/**
341
+	 * Check if $this is used in a plain function or method.
342
+	 *
343
+	 * Prior to PHP 7.1, this would result in an "undefined variable" notice
344
+	 * and execution would continue with $this regarded as `null`.
345
+	 * As of PHP 7.1, this throws an exception.
346
+	 *
347
+	 * Note: use within isset() and empty() to check object context is still allowed.
348
+	 * Note: $this can still be used within a closure.
349
+	 *
350
+	 * @since 9.1.0
351
+	 *
352
+	 * @param \PHP_CodeSniffer_File $phpcsFile The file being scanned.
353
+	 * @param int                   $stackPtr  The position of the current token in
354
+	 *                                         the stack passed in $tokens.
355
+	 *
356
+	 * @return void
357
+	 */
358
+	protected function isThisUsedOutsideObjectContext(File $phpcsFile, $stackPtr)
359
+	{
360
+		$tokens = $phpcsFile->getTokens();
361
+
362
+		if (isset($tokens[$stackPtr]['scope_opener'], $tokens[$stackPtr]['scope_closer']) === false) {
363
+			return;
364
+		}
365
+
366
+		if ($this->validDirectScope($phpcsFile, $stackPtr, $this->ooScopeTokens) !== false) {
367
+			$methodProps = $phpcsFile->getMethodProperties($stackPtr);
368
+			if ($methodProps['is_static'] === false) {
369
+				return;
370
+			} else {
371
+				$methodName = $phpcsFile->getDeclarationName($stackPtr);
372
+				if ($methodName === '__call') {
373
+					/*
374 374
                      * This is an exception.
375 375
                      * @link https://wiki.php.net/rfc/this_var#always_show_true_this_value_in_magic_method_call
376 376
                      */
377
-                    return;
378
-                }
379
-            }
380
-        }
381
-
382
-        for ($i = ($tokens[$stackPtr]['scope_opener'] + 1); $i < $tokens[$stackPtr]['scope_closer']; $i++) {
383
-            if (isset($this->skipOverScopes[$tokens[$i]['type']])) {
384
-                if (isset($tokens[$i]['scope_closer']) === false) {
385
-                    // Live coding or parse error, will only lead to inaccurate results.
386
-                    return;
387
-                }
388
-
389
-                // Skip over nested structures.
390
-                $i = $tokens[$i]['scope_closer'];
391
-                continue;
392
-            }
393
-
394
-            if ($tokens[$i]['code'] !== \T_VARIABLE || $tokens[$i]['content'] !== '$this') {
395
-                continue;
396
-            }
397
-
398
-            if (isset($tokens[$i]['nested_parenthesis']) === true) {
399
-                $nestedParenthesis     = $tokens[$i]['nested_parenthesis'];
400
-                $nestedOpenParenthesis = array_keys($nestedParenthesis);
401
-                $lastOpenParenthesis   = array_pop($nestedOpenParenthesis);
402
-
403
-                $previousNonEmpty = $phpcsFile->findPrevious(
404
-                    Tokens::$emptyTokens,
405
-                    ($lastOpenParenthesis - 1),
406
-                    null,
407
-                    true,
408
-                    null,
409
-                    true
410
-                );
411
-
412
-                if (isset($this->validUseOutsideObject[$tokens[$previousNonEmpty]['code']])) {
413
-                    continue;
414
-                }
415
-            }
416
-
417
-            $phpcsFile->addError(
418
-                '"$this" can no longer be used in a plain function or method since PHP 7.1.',
419
-                $i,
420
-                'OutsideObjectContext'
421
-            );
422
-        }
423
-    }
377
+					return;
378
+				}
379
+			}
380
+		}
381
+
382
+		for ($i = ($tokens[$stackPtr]['scope_opener'] + 1); $i < $tokens[$stackPtr]['scope_closer']; $i++) {
383
+			if (isset($this->skipOverScopes[$tokens[$i]['type']])) {
384
+				if (isset($tokens[$i]['scope_closer']) === false) {
385
+					// Live coding or parse error, will only lead to inaccurate results.
386
+					return;
387
+				}
388
+
389
+				// Skip over nested structures.
390
+				$i = $tokens[$i]['scope_closer'];
391
+				continue;
392
+			}
393
+
394
+			if ($tokens[$i]['code'] !== \T_VARIABLE || $tokens[$i]['content'] !== '$this') {
395
+				continue;
396
+			}
397
+
398
+			if (isset($tokens[$i]['nested_parenthesis']) === true) {
399
+				$nestedParenthesis     = $tokens[$i]['nested_parenthesis'];
400
+				$nestedOpenParenthesis = array_keys($nestedParenthesis);
401
+				$lastOpenParenthesis   = array_pop($nestedOpenParenthesis);
402
+
403
+				$previousNonEmpty = $phpcsFile->findPrevious(
404
+					Tokens::$emptyTokens,
405
+					($lastOpenParenthesis - 1),
406
+					null,
407
+					true,
408
+					null,
409
+					true
410
+				);
411
+
412
+				if (isset($this->validUseOutsideObject[$tokens[$previousNonEmpty]['code']])) {
413
+					continue;
414
+				}
415
+			}
416
+
417
+			$phpcsFile->addError(
418
+				'"$this" can no longer be used in a plain function or method since PHP 7.1.',
419
+				$i,
420
+				'OutsideObjectContext'
421
+			);
422
+		}
423
+	}
424 424
 }
Please login to merge, or discard this patch.