Completed
Branch dev (f99e72)
by
unknown
12:52 queued 05:01
created
vendor/squizlabs/php_codesniffer/src/Tokenizers/Comment.php 1 patch
Indentation   +238 added lines, -238 removed lines patch added patch discarded remove patch
@@ -15,263 +15,263 @@
 block discarded – undo
15 15
 {
16 16
 
17 17
 
18
-    /**
19
-     * Creates an array of tokens when given some PHP code.
20
-     *
21
-     * Starts by using token_get_all() but does a lot of extra processing
22
-     * to insert information about the context of the token.
23
-     *
24
-     * @param string $string   The string to tokenize.
25
-     * @param string $eolChar  The EOL character to use for splitting strings.
26
-     * @param int    $stackPtr The position of the first token in the file.
27
-     *
28
-     * @return array
29
-     */
30
-    public function tokenizeString($string, $eolChar, $stackPtr)
31
-    {
32
-        if (PHP_CODESNIFFER_VERBOSITY > 1) {
33
-            echo "\t\t*** START COMMENT TOKENIZING ***".PHP_EOL;
34
-        }
35
-
36
-        $tokens   = [];
37
-        $numChars = strlen($string);
38
-
39
-        /*
18
+	/**
19
+	 * Creates an array of tokens when given some PHP code.
20
+	 *
21
+	 * Starts by using token_get_all() but does a lot of extra processing
22
+	 * to insert information about the context of the token.
23
+	 *
24
+	 * @param string $string   The string to tokenize.
25
+	 * @param string $eolChar  The EOL character to use for splitting strings.
26
+	 * @param int    $stackPtr The position of the first token in the file.
27
+	 *
28
+	 * @return array
29
+	 */
30
+	public function tokenizeString($string, $eolChar, $stackPtr)
31
+	{
32
+		if (PHP_CODESNIFFER_VERBOSITY > 1) {
33
+			echo "\t\t*** START COMMENT TOKENIZING ***".PHP_EOL;
34
+		}
35
+
36
+		$tokens   = [];
37
+		$numChars = strlen($string);
38
+
39
+		/*
40 40
             Doc block comments start with /*, but typically contain an
41 41
             extra star when they are used for function and class comments.
42 42
         */
43 43
 
44
-        $char    = ($numChars - strlen(ltrim($string, '/*')));
45
-        $openTag = substr($string, 0, $char);
46
-        $string  = ltrim($string, '/*');
44
+		$char    = ($numChars - strlen(ltrim($string, '/*')));
45
+		$openTag = substr($string, 0, $char);
46
+		$string  = ltrim($string, '/*');
47 47
 
48
-        $tokens[$stackPtr] = [
49
-            'content'      => $openTag,
50
-            'code'         => T_DOC_COMMENT_OPEN_TAG,
51
-            'type'         => 'T_DOC_COMMENT_OPEN_TAG',
52
-            'comment_tags' => [],
53
-        ];
48
+		$tokens[$stackPtr] = [
49
+			'content'      => $openTag,
50
+			'code'         => T_DOC_COMMENT_OPEN_TAG,
51
+			'type'         => 'T_DOC_COMMENT_OPEN_TAG',
52
+			'comment_tags' => [],
53
+		];
54 54
 
55
-        $openPtr = $stackPtr;
56
-        $stackPtr++;
55
+		$openPtr = $stackPtr;
56
+		$stackPtr++;
57 57
 
58
-        if (PHP_CODESNIFFER_VERBOSITY > 1) {
59
-            $content = Util\Common::prepareForOutput($openTag);
60
-            echo "\t\tCreate comment token: T_DOC_COMMENT_OPEN_TAG => $content".PHP_EOL;
61
-        }
58
+		if (PHP_CODESNIFFER_VERBOSITY > 1) {
59
+			$content = Util\Common::prepareForOutput($openTag);
60
+			echo "\t\tCreate comment token: T_DOC_COMMENT_OPEN_TAG => $content".PHP_EOL;
61
+		}
62 62
 
63
-        /*
63
+		/*
64 64
             Strip off the close tag so it doesn't interfere with any
65 65
             of our comment line processing. The token will be added to the
66 66
             stack just before we return it.
67 67
         */
68 68
 
69
-        $closeTag = [
70
-            'content'        => substr($string, strlen(rtrim($string, '/*'))),
71
-            'code'           => T_DOC_COMMENT_CLOSE_TAG,
72
-            'type'           => 'T_DOC_COMMENT_CLOSE_TAG',
73
-            'comment_opener' => $openPtr,
74
-        ];
69
+		$closeTag = [
70
+			'content'        => substr($string, strlen(rtrim($string, '/*'))),
71
+			'code'           => T_DOC_COMMENT_CLOSE_TAG,
72
+			'type'           => 'T_DOC_COMMENT_CLOSE_TAG',
73
+			'comment_opener' => $openPtr,
74
+		];
75 75
 
76
-        if ($closeTag['content'] === false) {
77
-            $closeTag['content'] = '';
78
-        }
76
+		if ($closeTag['content'] === false) {
77
+			$closeTag['content'] = '';
78
+		}
79 79
 
80
-        $string = rtrim($string, '/*');
80
+		$string = rtrim($string, '/*');
81 81
 
82
-        /*
82
+		/*
83 83
             Process each line of the comment.
84 84
         */
85 85
 
86
-        $lines    = explode($eolChar, $string);
87
-        $numLines = count($lines);
88
-        foreach ($lines as $lineNum => $string) {
89
-            if ($lineNum !== ($numLines - 1)) {
90
-                $string .= $eolChar;
91
-            }
92
-
93
-            $char     = 0;
94
-            $numChars = strlen($string);
95
-
96
-            // We've started a new line, so process the indent.
97
-            $space = $this->collectWhitespace($string, $char, $numChars);
98
-            if ($space !== null) {
99
-                $tokens[$stackPtr] = $space;
100
-                $stackPtr++;
101
-                if (PHP_CODESNIFFER_VERBOSITY > 1) {
102
-                    $content = Util\Common::prepareForOutput($space['content']);
103
-                    echo "\t\tCreate comment token: T_DOC_COMMENT_WHITESPACE => $content".PHP_EOL;
104
-                }
105
-
106
-                $char += strlen($space['content']);
107
-                if ($char === $numChars) {
108
-                    break;
109
-                }
110
-            }
111
-
112
-            if ($string === '') {
113
-                continue;
114
-            }
115
-
116
-            if ($lineNum > 0 && $string[$char] === '*') {
117
-                // This is a function or class doc block line.
118
-                $char++;
119
-                $tokens[$stackPtr] = [
120
-                    'content' => '*',
121
-                    'code'    => T_DOC_COMMENT_STAR,
122
-                    'type'    => 'T_DOC_COMMENT_STAR',
123
-                ];
124
-
125
-                $stackPtr++;
126
-
127
-                if (PHP_CODESNIFFER_VERBOSITY > 1) {
128
-                    echo "\t\tCreate comment token: T_DOC_COMMENT_STAR => *".PHP_EOL;
129
-                }
130
-            }
131
-
132
-            // Now we are ready to process the actual content of the line.
133
-            $lineTokens = $this->processLine($string, $eolChar, $char, $numChars);
134
-            foreach ($lineTokens as $lineToken) {
135
-                $tokens[$stackPtr] = $lineToken;
136
-                if (PHP_CODESNIFFER_VERBOSITY > 1) {
137
-                    $content = Util\Common::prepareForOutput($lineToken['content']);
138
-                    $type    = $lineToken['type'];
139
-                    echo "\t\tCreate comment token: $type => $content".PHP_EOL;
140
-                }
141
-
142
-                if ($lineToken['code'] === T_DOC_COMMENT_TAG) {
143
-                    $tokens[$openPtr]['comment_tags'][] = $stackPtr;
144
-                }
145
-
146
-                $stackPtr++;
147
-            }
148
-        }//end foreach
149
-
150
-        $tokens[$stackPtr] = $closeTag;
151
-        $tokens[$openPtr]['comment_closer'] = $stackPtr;
152
-        if (PHP_CODESNIFFER_VERBOSITY > 1) {
153
-            $content = Util\Common::prepareForOutput($closeTag['content']);
154
-            echo "\t\tCreate comment token: T_DOC_COMMENT_CLOSE_TAG => $content".PHP_EOL;
155
-        }
156
-
157
-        if (PHP_CODESNIFFER_VERBOSITY > 1) {
158
-            echo "\t\t*** END COMMENT TOKENIZING ***".PHP_EOL;
159
-        }
160
-
161
-        return $tokens;
162
-
163
-    }//end tokenizeString()
164
-
165
-
166
-    /**
167
-     * Process a single line of a comment.
168
-     *
169
-     * @param string $string  The comment string being tokenized.
170
-     * @param string $eolChar The EOL character to use for splitting strings.
171
-     * @param int    $start   The position in the string to start processing.
172
-     * @param int    $end     The position in the string to end processing.
173
-     *
174
-     * @return array
175
-     */
176
-    private function processLine($string, $eolChar, $start, $end)
177
-    {
178
-        $tokens = [];
179
-
180
-        // Collect content padding.
181
-        $space = $this->collectWhitespace($string, $start, $end);
182
-        if ($space !== null) {
183
-            $tokens[] = $space;
184
-            $start   += strlen($space['content']);
185
-        }
186
-
187
-        if (isset($string[$start]) === false) {
188
-            return $tokens;
189
-        }
190
-
191
-        if ($string[$start] === '@') {
192
-            // The content up until the first whitespace is the tag name.
193
-            $matches = [];
194
-            preg_match('/@[^\s]+/', $string, $matches, 0, $start);
195
-            if (isset($matches[0]) === true
196
-                && substr(strtolower($matches[0]), 0, 7) !== '@phpcs:'
197
-            ) {
198
-                $tagName  = $matches[0];
199
-                $start   += strlen($tagName);
200
-                $tokens[] = [
201
-                    'content' => $tagName,
202
-                    'code'    => T_DOC_COMMENT_TAG,
203
-                    'type'    => 'T_DOC_COMMENT_TAG',
204
-                ];
205
-
206
-                // Then there will be some whitespace.
207
-                $space = $this->collectWhitespace($string, $start, $end);
208
-                if ($space !== null) {
209
-                    $tokens[] = $space;
210
-                    $start   += strlen($space['content']);
211
-                }
212
-            }
213
-        }//end if
214
-
215
-        // Process the rest of the line.
216
-        $eol = strpos($string, $eolChar, $start);
217
-        if ($eol === false) {
218
-            $eol = $end;
219
-        }
220
-
221
-        if ($eol > $start) {
222
-            $tokens[] = [
223
-                'content' => substr($string, $start, ($eol - $start)),
224
-                'code'    => T_DOC_COMMENT_STRING,
225
-                'type'    => 'T_DOC_COMMENT_STRING',
226
-            ];
227
-        }
228
-
229
-        if ($eol !== $end) {
230
-            $tokens[] = [
231
-                'content' => substr($string, $eol, strlen($eolChar)),
232
-                'code'    => T_DOC_COMMENT_WHITESPACE,
233
-                'type'    => 'T_DOC_COMMENT_WHITESPACE',
234
-            ];
235
-        }
236
-
237
-        return $tokens;
238
-
239
-    }//end processLine()
240
-
241
-
242
-    /**
243
-     * Collect consecutive whitespace into a single token.
244
-     *
245
-     * @param string $string The comment string being tokenized.
246
-     * @param int    $start  The position in the string to start processing.
247
-     * @param int    $end    The position in the string to end processing.
248
-     *
249
-     * @return array|null
250
-     */
251
-    private function collectWhitespace($string, $start, $end)
252
-    {
253
-        $space = '';
254
-        for ($start; $start < $end; $start++) {
255
-            if ($string[$start] !== ' ' && $string[$start] !== "\t") {
256
-                break;
257
-            }
258
-
259
-            $space .= $string[$start];
260
-        }
261
-
262
-        if ($space === '') {
263
-            return null;
264
-        }
265
-
266
-        $token = [
267
-            'content' => $space,
268
-            'code'    => T_DOC_COMMENT_WHITESPACE,
269
-            'type'    => 'T_DOC_COMMENT_WHITESPACE',
270
-        ];
271
-
272
-        return $token;
273
-
274
-    }//end collectWhitespace()
86
+		$lines    = explode($eolChar, $string);
87
+		$numLines = count($lines);
88
+		foreach ($lines as $lineNum => $string) {
89
+			if ($lineNum !== ($numLines - 1)) {
90
+				$string .= $eolChar;
91
+			}
92
+
93
+			$char     = 0;
94
+			$numChars = strlen($string);
95
+
96
+			// We've started a new line, so process the indent.
97
+			$space = $this->collectWhitespace($string, $char, $numChars);
98
+			if ($space !== null) {
99
+				$tokens[$stackPtr] = $space;
100
+				$stackPtr++;
101
+				if (PHP_CODESNIFFER_VERBOSITY > 1) {
102
+					$content = Util\Common::prepareForOutput($space['content']);
103
+					echo "\t\tCreate comment token: T_DOC_COMMENT_WHITESPACE => $content".PHP_EOL;
104
+				}
105
+
106
+				$char += strlen($space['content']);
107
+				if ($char === $numChars) {
108
+					break;
109
+				}
110
+			}
111
+
112
+			if ($string === '') {
113
+				continue;
114
+			}
115
+
116
+			if ($lineNum > 0 && $string[$char] === '*') {
117
+				// This is a function or class doc block line.
118
+				$char++;
119
+				$tokens[$stackPtr] = [
120
+					'content' => '*',
121
+					'code'    => T_DOC_COMMENT_STAR,
122
+					'type'    => 'T_DOC_COMMENT_STAR',
123
+				];
124
+
125
+				$stackPtr++;
126
+
127
+				if (PHP_CODESNIFFER_VERBOSITY > 1) {
128
+					echo "\t\tCreate comment token: T_DOC_COMMENT_STAR => *".PHP_EOL;
129
+				}
130
+			}
131
+
132
+			// Now we are ready to process the actual content of the line.
133
+			$lineTokens = $this->processLine($string, $eolChar, $char, $numChars);
134
+			foreach ($lineTokens as $lineToken) {
135
+				$tokens[$stackPtr] = $lineToken;
136
+				if (PHP_CODESNIFFER_VERBOSITY > 1) {
137
+					$content = Util\Common::prepareForOutput($lineToken['content']);
138
+					$type    = $lineToken['type'];
139
+					echo "\t\tCreate comment token: $type => $content".PHP_EOL;
140
+				}
141
+
142
+				if ($lineToken['code'] === T_DOC_COMMENT_TAG) {
143
+					$tokens[$openPtr]['comment_tags'][] = $stackPtr;
144
+				}
145
+
146
+				$stackPtr++;
147
+			}
148
+		}//end foreach
149
+
150
+		$tokens[$stackPtr] = $closeTag;
151
+		$tokens[$openPtr]['comment_closer'] = $stackPtr;
152
+		if (PHP_CODESNIFFER_VERBOSITY > 1) {
153
+			$content = Util\Common::prepareForOutput($closeTag['content']);
154
+			echo "\t\tCreate comment token: T_DOC_COMMENT_CLOSE_TAG => $content".PHP_EOL;
155
+		}
156
+
157
+		if (PHP_CODESNIFFER_VERBOSITY > 1) {
158
+			echo "\t\t*** END COMMENT TOKENIZING ***".PHP_EOL;
159
+		}
160
+
161
+		return $tokens;
162
+
163
+	}//end tokenizeString()
164
+
165
+
166
+	/**
167
+	 * Process a single line of a comment.
168
+	 *
169
+	 * @param string $string  The comment string being tokenized.
170
+	 * @param string $eolChar The EOL character to use for splitting strings.
171
+	 * @param int    $start   The position in the string to start processing.
172
+	 * @param int    $end     The position in the string to end processing.
173
+	 *
174
+	 * @return array
175
+	 */
176
+	private function processLine($string, $eolChar, $start, $end)
177
+	{
178
+		$tokens = [];
179
+
180
+		// Collect content padding.
181
+		$space = $this->collectWhitespace($string, $start, $end);
182
+		if ($space !== null) {
183
+			$tokens[] = $space;
184
+			$start   += strlen($space['content']);
185
+		}
186
+
187
+		if (isset($string[$start]) === false) {
188
+			return $tokens;
189
+		}
190
+
191
+		if ($string[$start] === '@') {
192
+			// The content up until the first whitespace is the tag name.
193
+			$matches = [];
194
+			preg_match('/@[^\s]+/', $string, $matches, 0, $start);
195
+			if (isset($matches[0]) === true
196
+				&& substr(strtolower($matches[0]), 0, 7) !== '@phpcs:'
197
+			) {
198
+				$tagName  = $matches[0];
199
+				$start   += strlen($tagName);
200
+				$tokens[] = [
201
+					'content' => $tagName,
202
+					'code'    => T_DOC_COMMENT_TAG,
203
+					'type'    => 'T_DOC_COMMENT_TAG',
204
+				];
205
+
206
+				// Then there will be some whitespace.
207
+				$space = $this->collectWhitespace($string, $start, $end);
208
+				if ($space !== null) {
209
+					$tokens[] = $space;
210
+					$start   += strlen($space['content']);
211
+				}
212
+			}
213
+		}//end if
214
+
215
+		// Process the rest of the line.
216
+		$eol = strpos($string, $eolChar, $start);
217
+		if ($eol === false) {
218
+			$eol = $end;
219
+		}
220
+
221
+		if ($eol > $start) {
222
+			$tokens[] = [
223
+				'content' => substr($string, $start, ($eol - $start)),
224
+				'code'    => T_DOC_COMMENT_STRING,
225
+				'type'    => 'T_DOC_COMMENT_STRING',
226
+			];
227
+		}
228
+
229
+		if ($eol !== $end) {
230
+			$tokens[] = [
231
+				'content' => substr($string, $eol, strlen($eolChar)),
232
+				'code'    => T_DOC_COMMENT_WHITESPACE,
233
+				'type'    => 'T_DOC_COMMENT_WHITESPACE',
234
+			];
235
+		}
236
+
237
+		return $tokens;
238
+
239
+	}//end processLine()
240
+
241
+
242
+	/**
243
+	 * Collect consecutive whitespace into a single token.
244
+	 *
245
+	 * @param string $string The comment string being tokenized.
246
+	 * @param int    $start  The position in the string to start processing.
247
+	 * @param int    $end    The position in the string to end processing.
248
+	 *
249
+	 * @return array|null
250
+	 */
251
+	private function collectWhitespace($string, $start, $end)
252
+	{
253
+		$space = '';
254
+		for ($start; $start < $end; $start++) {
255
+			if ($string[$start] !== ' ' && $string[$start] !== "\t") {
256
+				break;
257
+			}
258
+
259
+			$space .= $string[$start];
260
+		}
261
+
262
+		if ($space === '') {
263
+			return null;
264
+		}
265
+
266
+		$token = [
267
+			'content' => $space,
268
+			'code'    => T_DOC_COMMENT_WHITESPACE,
269
+			'type'    => 'T_DOC_COMMENT_WHITESPACE',
270
+		];
271
+
272
+		return $token;
273
+
274
+	}//end collectWhitespace()
275 275
 
276 276
 
277 277
 }//end class
Please login to merge, or discard this patch.
vendor/squizlabs/php_codesniffer/src/Sniffs/AbstractScopeSniff.php 2 patches
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -71,7 +71,7 @@
 block discarded – undo
71 71
     public function __construct(
72 72
         array $scopeTokens,
73 73
         array $tokens,
74
-        $listenOutside=false
74
+        $listenOutside = false
75 75
     ) {
76 76
         if (empty($scopeTokens) === true) {
77 77
             $error = 'The scope tokens list cannot be empty';
Please login to merge, or discard this patch.
Indentation   +154 added lines, -154 removed lines patch added patch discarded remove patch
@@ -32,160 +32,160 @@
 block discarded – undo
32 32
 abstract class AbstractScopeSniff implements Sniff
33 33
 {
34 34
 
35
-    /**
36
-     * The token types that this test wishes to listen to within the scope.
37
-     *
38
-     * @var array
39
-     */
40
-    private $tokens = [];
41
-
42
-    /**
43
-     * The type of scope opener tokens that this test wishes to listen to.
44
-     *
45
-     * @var string
46
-     */
47
-    private $scopeTokens = [];
48
-
49
-    /**
50
-     * True if this test should fire on tokens outside of the scope.
51
-     *
52
-     * @var boolean
53
-     */
54
-    private $listenOutside = false;
55
-
56
-
57
-    /**
58
-     * Constructs a new AbstractScopeTest.
59
-     *
60
-     * @param array   $scopeTokens   The type of scope the test wishes to listen to.
61
-     * @param array   $tokens        The tokens that the test wishes to listen to
62
-     *                               within the scope.
63
-     * @param boolean $listenOutside If true this test will also alert the
64
-     *                               extending class when a token is found outside
65
-     *                               the scope, by calling the
66
-     *                               processTokenOutsideScope method.
67
-     *
68
-     * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If the specified tokens arrays are empty
69
-     *                                                      or invalid.
70
-     */
71
-    public function __construct(
72
-        array $scopeTokens,
73
-        array $tokens,
74
-        $listenOutside=false
75
-    ) {
76
-        if (empty($scopeTokens) === true) {
77
-            $error = 'The scope tokens list cannot be empty';
78
-            throw new RuntimeException($error);
79
-        }
80
-
81
-        if (empty($tokens) === true) {
82
-            $error = 'The tokens list cannot be empty';
83
-            throw new RuntimeException($error);
84
-        }
85
-
86
-        $invalidScopeTokens = array_intersect($scopeTokens, $tokens);
87
-        if (empty($invalidScopeTokens) === false) {
88
-            $invalid = implode(', ', $invalidScopeTokens);
89
-            $error   = "Scope tokens [$invalid] can't be in the tokens array";
90
-            throw new RuntimeException($error);
91
-        }
92
-
93
-        $this->listenOutside = $listenOutside;
94
-        $this->scopeTokens   = array_flip($scopeTokens);
95
-        $this->tokens        = $tokens;
96
-
97
-    }//end __construct()
98
-
99
-
100
-    /**
101
-     * The method that is called to register the tokens this test wishes to
102
-     * listen to.
103
-     *
104
-     * DO NOT OVERRIDE THIS METHOD. Use the constructor of this class to register
105
-     * for the desired tokens and scope.
106
-     *
107
-     * @return int[]
108
-     * @see    __constructor()
109
-     */
110
-    final public function register()
111
-    {
112
-        return $this->tokens;
113
-
114
-    }//end register()
115
-
116
-
117
-    /**
118
-     * Processes the tokens that this test is listening for.
119
-     *
120
-     * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found.
121
-     * @param int                         $stackPtr  The position in the stack where this
122
-     *                                               token was found.
123
-     *
124
-     * @return void|int Optionally returns a stack pointer. The sniff will not be
125
-     *                  called again on the current file until the returned stack
126
-     *                  pointer is reached. Return ($phpcsFile->numTokens + 1) to skip
127
-     *                  the rest of the file.
128
-     * @see    processTokenWithinScope()
129
-     */
130
-    final public function process(File $phpcsFile, $stackPtr)
131
-    {
132
-        $tokens = $phpcsFile->getTokens();
133
-
134
-        $foundScope = false;
135
-        $skipTokens = [];
136
-        foreach ($tokens[$stackPtr]['conditions'] as $scope => $code) {
137
-            if (isset($this->scopeTokens[$code]) === true) {
138
-                $skipTokens[] = $this->processTokenWithinScope($phpcsFile, $stackPtr, $scope);
139
-                $foundScope   = true;
140
-            }
141
-        }
142
-
143
-        if ($this->listenOutside === true && $foundScope === false) {
144
-            $skipTokens[] = $this->processTokenOutsideScope($phpcsFile, $stackPtr);
145
-        }
146
-
147
-        if (empty($skipTokens) === false) {
148
-            return min($skipTokens);
149
-        }
150
-
151
-        return;
152
-
153
-    }//end process()
154
-
155
-
156
-    /**
157
-     * Processes a token that is found within the scope that this test is
158
-     * listening to.
159
-     *
160
-     * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found.
161
-     * @param int                         $stackPtr  The position in the stack where this
162
-     *                                               token was found.
163
-     * @param int                         $currScope The position in the tokens array that
164
-     *                                               opened the scope that this test is
165
-     *                                               listening for.
166
-     *
167
-     * @return void|int Optionally returns a stack pointer. The sniff will not be
168
-     *                  called again on the current file until the returned stack
169
-     *                  pointer is reached. Return ($phpcsFile->numTokens + 1) to skip
170
-     *                  the rest of the file.
171
-     */
172
-    abstract protected function processTokenWithinScope(File $phpcsFile, $stackPtr, $currScope);
173
-
174
-
175
-    /**
176
-     * Processes a token that is found outside the scope that this test is
177
-     * listening to.
178
-     *
179
-     * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found.
180
-     * @param int                         $stackPtr  The position in the stack where this
181
-     *                                               token was found.
182
-     *
183
-     * @return void|int Optionally returns a stack pointer. The sniff will not be
184
-     *                  called again on the current file until the returned stack
185
-     *                  pointer is reached. Return (count($tokens) + 1) to skip
186
-     *                  the rest of the file.
187
-     */
188
-    abstract protected function processTokenOutsideScope(File $phpcsFile, $stackPtr);
35
+	/**
36
+	 * The token types that this test wishes to listen to within the scope.
37
+	 *
38
+	 * @var array
39
+	 */
40
+	private $tokens = [];
41
+
42
+	/**
43
+	 * The type of scope opener tokens that this test wishes to listen to.
44
+	 *
45
+	 * @var string
46
+	 */
47
+	private $scopeTokens = [];
48
+
49
+	/**
50
+	 * True if this test should fire on tokens outside of the scope.
51
+	 *
52
+	 * @var boolean
53
+	 */
54
+	private $listenOutside = false;
55
+
56
+
57
+	/**
58
+	 * Constructs a new AbstractScopeTest.
59
+	 *
60
+	 * @param array   $scopeTokens   The type of scope the test wishes to listen to.
61
+	 * @param array   $tokens        The tokens that the test wishes to listen to
62
+	 *                               within the scope.
63
+	 * @param boolean $listenOutside If true this test will also alert the
64
+	 *                               extending class when a token is found outside
65
+	 *                               the scope, by calling the
66
+	 *                               processTokenOutsideScope method.
67
+	 *
68
+	 * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If the specified tokens arrays are empty
69
+	 *                                                      or invalid.
70
+	 */
71
+	public function __construct(
72
+		array $scopeTokens,
73
+		array $tokens,
74
+		$listenOutside=false
75
+	) {
76
+		if (empty($scopeTokens) === true) {
77
+			$error = 'The scope tokens list cannot be empty';
78
+			throw new RuntimeException($error);
79
+		}
80
+
81
+		if (empty($tokens) === true) {
82
+			$error = 'The tokens list cannot be empty';
83
+			throw new RuntimeException($error);
84
+		}
85
+
86
+		$invalidScopeTokens = array_intersect($scopeTokens, $tokens);
87
+		if (empty($invalidScopeTokens) === false) {
88
+			$invalid = implode(', ', $invalidScopeTokens);
89
+			$error   = "Scope tokens [$invalid] can't be in the tokens array";
90
+			throw new RuntimeException($error);
91
+		}
92
+
93
+		$this->listenOutside = $listenOutside;
94
+		$this->scopeTokens   = array_flip($scopeTokens);
95
+		$this->tokens        = $tokens;
96
+
97
+	}//end __construct()
98
+
99
+
100
+	/**
101
+	 * The method that is called to register the tokens this test wishes to
102
+	 * listen to.
103
+	 *
104
+	 * DO NOT OVERRIDE THIS METHOD. Use the constructor of this class to register
105
+	 * for the desired tokens and scope.
106
+	 *
107
+	 * @return int[]
108
+	 * @see    __constructor()
109
+	 */
110
+	final public function register()
111
+	{
112
+		return $this->tokens;
113
+
114
+	}//end register()
115
+
116
+
117
+	/**
118
+	 * Processes the tokens that this test is listening for.
119
+	 *
120
+	 * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found.
121
+	 * @param int                         $stackPtr  The position in the stack where this
122
+	 *                                               token was found.
123
+	 *
124
+	 * @return void|int Optionally returns a stack pointer. The sniff will not be
125
+	 *                  called again on the current file until the returned stack
126
+	 *                  pointer is reached. Return ($phpcsFile->numTokens + 1) to skip
127
+	 *                  the rest of the file.
128
+	 * @see    processTokenWithinScope()
129
+	 */
130
+	final public function process(File $phpcsFile, $stackPtr)
131
+	{
132
+		$tokens = $phpcsFile->getTokens();
133
+
134
+		$foundScope = false;
135
+		$skipTokens = [];
136
+		foreach ($tokens[$stackPtr]['conditions'] as $scope => $code) {
137
+			if (isset($this->scopeTokens[$code]) === true) {
138
+				$skipTokens[] = $this->processTokenWithinScope($phpcsFile, $stackPtr, $scope);
139
+				$foundScope   = true;
140
+			}
141
+		}
142
+
143
+		if ($this->listenOutside === true && $foundScope === false) {
144
+			$skipTokens[] = $this->processTokenOutsideScope($phpcsFile, $stackPtr);
145
+		}
146
+
147
+		if (empty($skipTokens) === false) {
148
+			return min($skipTokens);
149
+		}
150
+
151
+		return;
152
+
153
+	}//end process()
154
+
155
+
156
+	/**
157
+	 * Processes a token that is found within the scope that this test is
158
+	 * listening to.
159
+	 *
160
+	 * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found.
161
+	 * @param int                         $stackPtr  The position in the stack where this
162
+	 *                                               token was found.
163
+	 * @param int                         $currScope The position in the tokens array that
164
+	 *                                               opened the scope that this test is
165
+	 *                                               listening for.
166
+	 *
167
+	 * @return void|int Optionally returns a stack pointer. The sniff will not be
168
+	 *                  called again on the current file until the returned stack
169
+	 *                  pointer is reached. Return ($phpcsFile->numTokens + 1) to skip
170
+	 *                  the rest of the file.
171
+	 */
172
+	abstract protected function processTokenWithinScope(File $phpcsFile, $stackPtr, $currScope);
173
+
174
+
175
+	/**
176
+	 * Processes a token that is found outside the scope that this test is
177
+	 * listening to.
178
+	 *
179
+	 * @param \PHP_CodeSniffer\Files\File $phpcsFile The file where this token was found.
180
+	 * @param int                         $stackPtr  The position in the stack where this
181
+	 *                                               token was found.
182
+	 *
183
+	 * @return void|int Optionally returns a stack pointer. The sniff will not be
184
+	 *                  called again on the current file until the returned stack
185
+	 *                  pointer is reached. Return (count($tokens) + 1) to skip
186
+	 *                  the rest of the file.
187
+	 */
188
+	abstract protected function processTokenOutsideScope(File $phpcsFile, $stackPtr);
189 189
 
190 190
 
191 191
 }//end class
Please login to merge, or discard this patch.
vendor/squizlabs/php_codesniffer/src/Sniffs/AbstractPatternSniff.php 3 patches
Switch Indentation   +20 added lines, -20 removed lines patch added patch discarded remove patch
@@ -866,26 +866,26 @@
 block discarded – undo
866 866
         $nestedBraces      = 0;
867 867
         for ($start = $from; $start >= 0; $start--) {
868 868
             switch ($pattern[$start]) {
869
-            case '(':
870
-                if ($nestedParenthesis === 0) {
871
-                    $skip['to'] = 'parenthesis_closer';
872
-                }
873
-
874
-                $nestedParenthesis--;
875
-                break;
876
-            case '{':
877
-                if ($nestedBraces === 0) {
878
-                    $skip['to'] = 'scope_closer';
879
-                }
880
-
881
-                $nestedBraces--;
882
-                break;
883
-            case '}':
884
-                $nestedBraces++;
885
-                break;
886
-            case ')':
887
-                $nestedParenthesis++;
888
-                break;
869
+            	case '(':
870
+                	if ($nestedParenthesis === 0) {
871
+                    	$skip['to'] = 'parenthesis_closer';
872
+                	}
873
+
874
+                	$nestedParenthesis--;
875
+                	break;
876
+            	case '{':
877
+                	if ($nestedBraces === 0) {
878
+                    	$skip['to'] = 'scope_closer';
879
+                	}
880
+
881
+                	$nestedBraces--;
882
+                	break;
883
+            	case '}':
884
+                	$nestedBraces++;
885
+                	break;
886
+            	case ')':
887
+                	$nestedParenthesis++;
888
+                	break;
889 889
             }//end switch
890 890
 
891 891
             if (isset($skip['to']) === true) {
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -61,7 +61,7 @@
 block discarded – undo
61 61
      *
62 62
      * @param boolean $ignoreComments If true, comments will be ignored.
63 63
      */
64
-    public function __construct($ignoreComments=null)
64
+    public function __construct($ignoreComments = null)
65 65
     {
66 66
         // This is here for backwards compatibility.
67 67
         if ($ignoreComments !== null) {
Please login to merge, or discard this patch.
Indentation   +914 added lines, -914 removed lines patch added patch discarded remove patch
@@ -17,920 +17,920 @@
 block discarded – undo
17 17
 abstract class AbstractPatternSniff implements Sniff
18 18
 {
19 19
 
20
-    /**
21
-     * If true, comments will be ignored if they are found in the code.
22
-     *
23
-     * @var boolean
24
-     */
25
-    public $ignoreComments = false;
26
-
27
-    /**
28
-     * The current file being checked.
29
-     *
30
-     * @var string
31
-     */
32
-    protected $currFile = '';
33
-
34
-    /**
35
-     * The parsed patterns array.
36
-     *
37
-     * @var array
38
-     */
39
-    private $parsedPatterns = [];
40
-
41
-    /**
42
-     * Tokens that this sniff wishes to process outside of the patterns.
43
-     *
44
-     * @var int[]
45
-     * @see registerSupplementary()
46
-     * @see processSupplementary()
47
-     */
48
-    private $supplementaryTokens = [];
49
-
50
-    /**
51
-     * Positions in the stack where errors have occurred.
52
-     *
53
-     * @var array<int, bool>
54
-     */
55
-    private $errorPos = [];
56
-
57
-
58
-    /**
59
-     * Constructs a AbstractPatternSniff.
60
-     *
61
-     * @param boolean $ignoreComments If true, comments will be ignored.
62
-     */
63
-    public function __construct($ignoreComments=null)
64
-    {
65
-        // This is here for backwards compatibility.
66
-        if ($ignoreComments !== null) {
67
-            $this->ignoreComments = $ignoreComments;
68
-        }
69
-
70
-        $this->supplementaryTokens = $this->registerSupplementary();
71
-
72
-    }//end __construct()
73
-
74
-
75
-    /**
76
-     * Registers the tokens to listen to.
77
-     *
78
-     * Classes extending <i>AbstractPatternTest</i> should implement the
79
-     * <i>getPatterns()</i> method to register the patterns they wish to test.
80
-     *
81
-     * @return int[]
82
-     * @see    process()
83
-     */
84
-    final public function register()
85
-    {
86
-        $listenTypes = [];
87
-        $patterns    = $this->getPatterns();
88
-
89
-        foreach ($patterns as $pattern) {
90
-            $parsedPattern = $this->parse($pattern);
91
-
92
-            // Find a token position in the pattern that we can use
93
-            // for a listener token.
94
-            $pos           = $this->getListenerTokenPos($parsedPattern);
95
-            $tokenType     = $parsedPattern[$pos]['token'];
96
-            $listenTypes[] = $tokenType;
97
-
98
-            $patternArray = [
99
-                'listen_pos'   => $pos,
100
-                'pattern'      => $parsedPattern,
101
-                'pattern_code' => $pattern,
102
-            ];
103
-
104
-            if (isset($this->parsedPatterns[$tokenType]) === false) {
105
-                $this->parsedPatterns[$tokenType] = [];
106
-            }
107
-
108
-            $this->parsedPatterns[$tokenType][] = $patternArray;
109
-        }//end foreach
110
-
111
-        return array_unique(array_merge($listenTypes, $this->supplementaryTokens));
112
-
113
-    }//end register()
114
-
115
-
116
-    /**
117
-     * Returns the token types that the specified pattern is checking for.
118
-     *
119
-     * Returned array is in the format:
120
-     * <code>
121
-     *   array(
122
-     *      T_WHITESPACE => 0, // 0 is the position where the T_WHITESPACE token
123
-     *                         // should occur in the pattern.
124
-     *   );
125
-     * </code>
126
-     *
127
-     * @param array $pattern The parsed pattern to find the acquire the token
128
-     *                       types from.
129
-     *
130
-     * @return array<int, int>
131
-     */
132
-    private function getPatternTokenTypes($pattern)
133
-    {
134
-        $tokenTypes = [];
135
-        foreach ($pattern as $pos => $patternInfo) {
136
-            if ($patternInfo['type'] === 'token') {
137
-                if (isset($tokenTypes[$patternInfo['token']]) === false) {
138
-                    $tokenTypes[$patternInfo['token']] = $pos;
139
-                }
140
-            }
141
-        }
142
-
143
-        return $tokenTypes;
144
-
145
-    }//end getPatternTokenTypes()
146
-
147
-
148
-    /**
149
-     * Returns the position in the pattern that this test should register as
150
-     * a listener for the pattern.
151
-     *
152
-     * @param array $pattern The pattern to acquire the listener for.
153
-     *
154
-     * @return int The position in the pattern that this test should register
155
-     *             as the listener.
156
-     * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If we could not determine a token to listen for.
157
-     */
158
-    private function getListenerTokenPos($pattern)
159
-    {
160
-        $tokenTypes = $this->getPatternTokenTypes($pattern);
161
-        $tokenCodes = array_keys($tokenTypes);
162
-        $token      = Tokens::getHighestWeightedToken($tokenCodes);
163
-
164
-        // If we could not get a token.
165
-        if ($token === false) {
166
-            $error = 'Could not determine a token to listen for';
167
-            throw new RuntimeException($error);
168
-        }
169
-
170
-        return $tokenTypes[$token];
171
-
172
-    }//end getListenerTokenPos()
173
-
174
-
175
-    /**
176
-     * Processes the test.
177
-     *
178
-     * @param \PHP_CodeSniffer\Files\File $phpcsFile The PHP_CodeSniffer file where the
179
-     *                                               token occurred.
180
-     * @param int                         $stackPtr  The position in the tokens stack
181
-     *                                               where the listening token type
182
-     *                                               was found.
183
-     *
184
-     * @return void
185
-     * @see    register()
186
-     */
187
-    final public function process(File $phpcsFile, $stackPtr)
188
-    {
189
-        $file = $phpcsFile->getFilename();
190
-        if ($this->currFile !== $file) {
191
-            // We have changed files, so clean up.
192
-            $this->errorPos = [];
193
-            $this->currFile = $file;
194
-        }
195
-
196
-        $tokens = $phpcsFile->getTokens();
197
-
198
-        if (in_array($tokens[$stackPtr]['code'], $this->supplementaryTokens, true) === true) {
199
-            $this->processSupplementary($phpcsFile, $stackPtr);
200
-        }
201
-
202
-        $type = $tokens[$stackPtr]['code'];
203
-
204
-        // If the type is not set, then it must have been a token registered
205
-        // with registerSupplementary().
206
-        if (isset($this->parsedPatterns[$type]) === false) {
207
-            return;
208
-        }
209
-
210
-        $allErrors = [];
211
-
212
-        // Loop over each pattern that is listening to the current token type
213
-        // that we are processing.
214
-        foreach ($this->parsedPatterns[$type] as $patternInfo) {
215
-            // If processPattern returns false, then the pattern that we are
216
-            // checking the code with must not be designed to check that code.
217
-            $errors = $this->processPattern($patternInfo, $phpcsFile, $stackPtr);
218
-            if ($errors === false) {
219
-                // The pattern didn't match.
220
-                continue;
221
-            } else if (empty($errors) === true) {
222
-                // The pattern matched, but there were no errors.
223
-                break;
224
-            }
225
-
226
-            foreach ($errors as $stackPtr => $error) {
227
-                if (isset($this->errorPos[$stackPtr]) === false) {
228
-                    $this->errorPos[$stackPtr] = true;
229
-                    $allErrors[$stackPtr]      = $error;
230
-                }
231
-            }
232
-        }
233
-
234
-        foreach ($allErrors as $stackPtr => $error) {
235
-            $phpcsFile->addError($error, $stackPtr, 'Found');
236
-        }
237
-
238
-    }//end process()
239
-
240
-
241
-    /**
242
-     * Processes the pattern and verifies the code at $stackPtr.
243
-     *
244
-     * @param array                       $patternInfo Information about the pattern used
245
-     *                                                 for checking, which includes are
246
-     *                                                 parsed token representation of the
247
-     *                                                 pattern.
248
-     * @param \PHP_CodeSniffer\Files\File $phpcsFile   The PHP_CodeSniffer file where the
249
-     *                                                 token occurred.
250
-     * @param int                         $stackPtr    The position in the tokens stack where
251
-     *                                                 the listening token type was found.
252
-     *
253
-     * @return array
254
-     */
255
-    protected function processPattern($patternInfo, File $phpcsFile, $stackPtr)
256
-    {
257
-        $tokens      = $phpcsFile->getTokens();
258
-        $pattern     = $patternInfo['pattern'];
259
-        $patternCode = $patternInfo['pattern_code'];
260
-        $errors      = [];
261
-        $found       = '';
262
-
263
-        $ignoreTokens = [T_WHITESPACE => T_WHITESPACE];
264
-        if ($this->ignoreComments === true) {
265
-            $ignoreTokens += Tokens::$commentTokens;
266
-        }
267
-
268
-        $origStackPtr = $stackPtr;
269
-        $hasError     = false;
270
-
271
-        if ($patternInfo['listen_pos'] > 0) {
272
-            $stackPtr--;
273
-
274
-            for ($i = ($patternInfo['listen_pos'] - 1); $i >= 0; $i--) {
275
-                if ($pattern[$i]['type'] === 'token') {
276
-                    if ($pattern[$i]['token'] === T_WHITESPACE) {
277
-                        if ($tokens[$stackPtr]['code'] === T_WHITESPACE) {
278
-                            $found = $tokens[$stackPtr]['content'].$found;
279
-                        }
280
-
281
-                        // Only check the size of the whitespace if this is not
282
-                        // the first token. We don't care about the size of
283
-                        // leading whitespace, just that there is some.
284
-                        if ($i !== 0) {
285
-                            if ($tokens[$stackPtr]['content'] !== $pattern[$i]['value']) {
286
-                                $hasError = true;
287
-                            }
288
-                        }
289
-                    } else {
290
-                        // Check to see if this important token is the same as the
291
-                        // previous important token in the pattern. If it is not,
292
-                        // then the pattern cannot be for this piece of code.
293
-                        $prev = $phpcsFile->findPrevious(
294
-                            $ignoreTokens,
295
-                            $stackPtr,
296
-                            null,
297
-                            true
298
-                        );
299
-
300
-                        if ($prev === false
301
-                            || $tokens[$prev]['code'] !== $pattern[$i]['token']
302
-                        ) {
303
-                            return false;
304
-                        }
305
-
306
-                        // If we skipped past some whitespace tokens, then add them
307
-                        // to the found string.
308
-                        $tokenContent = $phpcsFile->getTokensAsString(
309
-                            ($prev + 1),
310
-                            ($stackPtr - $prev - 1)
311
-                        );
312
-
313
-                        $found = $tokens[$prev]['content'].$tokenContent.$found;
314
-
315
-                        if (isset($pattern[($i - 1)]) === true
316
-                            && $pattern[($i - 1)]['type'] === 'skip'
317
-                        ) {
318
-                            $stackPtr = $prev;
319
-                        } else {
320
-                            $stackPtr = ($prev - 1);
321
-                        }
322
-                    }//end if
323
-                } else if ($pattern[$i]['type'] === 'skip') {
324
-                    // Skip to next piece of relevant code.
325
-                    if ($pattern[$i]['to'] === 'parenthesis_closer') {
326
-                        $to = 'parenthesis_opener';
327
-                    } else {
328
-                        $to = 'scope_opener';
329
-                    }
330
-
331
-                    // Find the previous opener.
332
-                    $next = $phpcsFile->findPrevious(
333
-                        $ignoreTokens,
334
-                        $stackPtr,
335
-                        null,
336
-                        true
337
-                    );
338
-
339
-                    if ($next === false || isset($tokens[$next][$to]) === false) {
340
-                        // If there was not opener, then we must be
341
-                        // using the wrong pattern.
342
-                        return false;
343
-                    }
344
-
345
-                    if ($to === 'parenthesis_opener') {
346
-                        $found = '{'.$found;
347
-                    } else {
348
-                        $found = '('.$found;
349
-                    }
350
-
351
-                    $found = '...'.$found;
352
-
353
-                    // Skip to the opening token.
354
-                    $stackPtr = ($tokens[$next][$to] - 1);
355
-                } else if ($pattern[$i]['type'] === 'string') {
356
-                    $found = 'abc';
357
-                } else if ($pattern[$i]['type'] === 'newline') {
358
-                    if ($this->ignoreComments === true
359
-                        && isset(Tokens::$commentTokens[$tokens[$stackPtr]['code']]) === true
360
-                    ) {
361
-                        $startComment = $phpcsFile->findPrevious(
362
-                            Tokens::$commentTokens,
363
-                            ($stackPtr - 1),
364
-                            null,
365
-                            true
366
-                        );
367
-
368
-                        if ($tokens[$startComment]['line'] !== $tokens[($startComment + 1)]['line']) {
369
-                            $startComment++;
370
-                        }
371
-
372
-                        $tokenContent = $phpcsFile->getTokensAsString(
373
-                            $startComment,
374
-                            ($stackPtr - $startComment + 1)
375
-                        );
376
-
377
-                        $found    = $tokenContent.$found;
378
-                        $stackPtr = ($startComment - 1);
379
-                    }
380
-
381
-                    if ($tokens[$stackPtr]['code'] === T_WHITESPACE) {
382
-                        if ($tokens[$stackPtr]['content'] !== $phpcsFile->eolChar) {
383
-                            $found = $tokens[$stackPtr]['content'].$found;
384
-
385
-                            // This may just be an indent that comes after a newline
386
-                            // so check the token before to make sure. If it is a newline, we
387
-                            // can ignore the error here.
388
-                            if (($tokens[($stackPtr - 1)]['content'] !== $phpcsFile->eolChar)
389
-                                && ($this->ignoreComments === true
390
-                                && isset(Tokens::$commentTokens[$tokens[($stackPtr - 1)]['code']]) === false)
391
-                            ) {
392
-                                $hasError = true;
393
-                            } else {
394
-                                $stackPtr--;
395
-                            }
396
-                        } else {
397
-                            $found = 'EOL'.$found;
398
-                        }
399
-                    } else {
400
-                        $found    = $tokens[$stackPtr]['content'].$found;
401
-                        $hasError = true;
402
-                    }//end if
403
-
404
-                    if ($hasError === false && $pattern[($i - 1)]['type'] !== 'newline') {
405
-                        // Make sure they only have 1 newline.
406
-                        $prev = $phpcsFile->findPrevious($ignoreTokens, ($stackPtr - 1), null, true);
407
-                        if ($prev !== false && $tokens[$prev]['line'] !== $tokens[$stackPtr]['line']) {
408
-                            $hasError = true;
409
-                        }
410
-                    }
411
-                }//end if
412
-            }//end for
413
-        }//end if
414
-
415
-        $stackPtr          = $origStackPtr;
416
-        $lastAddedStackPtr = null;
417
-        $patternLen        = count($pattern);
418
-
419
-        for ($i = $patternInfo['listen_pos']; $i < $patternLen; $i++) {
420
-            if (isset($tokens[$stackPtr]) === false) {
421
-                break;
422
-            }
423
-
424
-            if ($pattern[$i]['type'] === 'token') {
425
-                if ($pattern[$i]['token'] === T_WHITESPACE) {
426
-                    if ($this->ignoreComments === true) {
427
-                        // If we are ignoring comments, check to see if this current
428
-                        // token is a comment. If so skip it.
429
-                        if (isset(Tokens::$commentTokens[$tokens[$stackPtr]['code']]) === true) {
430
-                            continue;
431
-                        }
432
-
433
-                        // If the next token is a comment, the we need to skip the
434
-                        // current token as we should allow a space before a
435
-                        // comment for readability.
436
-                        if (isset($tokens[($stackPtr + 1)]) === true
437
-                            && isset(Tokens::$commentTokens[$tokens[($stackPtr + 1)]['code']]) === true
438
-                        ) {
439
-                            continue;
440
-                        }
441
-                    }
442
-
443
-                    $tokenContent = '';
444
-                    if ($tokens[$stackPtr]['code'] === T_WHITESPACE) {
445
-                        if (isset($pattern[($i + 1)]) === false) {
446
-                            // This is the last token in the pattern, so just compare
447
-                            // the next token of content.
448
-                            $tokenContent = $tokens[$stackPtr]['content'];
449
-                        } else {
450
-                            // Get all the whitespace to the next token.
451
-                            $next = $phpcsFile->findNext(
452
-                                Tokens::$emptyTokens,
453
-                                $stackPtr,
454
-                                null,
455
-                                true
456
-                            );
457
-
458
-                            $tokenContent = $phpcsFile->getTokensAsString(
459
-                                $stackPtr,
460
-                                ($next - $stackPtr)
461
-                            );
462
-
463
-                            $lastAddedStackPtr = $stackPtr;
464
-                            $stackPtr          = $next;
465
-                        }//end if
466
-
467
-                        if ($stackPtr !== $lastAddedStackPtr) {
468
-                            $found .= $tokenContent;
469
-                        }
470
-                    } else {
471
-                        if ($stackPtr !== $lastAddedStackPtr) {
472
-                            $found            .= $tokens[$stackPtr]['content'];
473
-                            $lastAddedStackPtr = $stackPtr;
474
-                        }
475
-                    }//end if
476
-
477
-                    if (isset($pattern[($i + 1)]) === true
478
-                        && $pattern[($i + 1)]['type'] === 'skip'
479
-                    ) {
480
-                        // The next token is a skip token, so we just need to make
481
-                        // sure the whitespace we found has *at least* the
482
-                        // whitespace required.
483
-                        if (strpos($tokenContent, $pattern[$i]['value']) !== 0) {
484
-                            $hasError = true;
485
-                        }
486
-                    } else {
487
-                        if ($tokenContent !== $pattern[$i]['value']) {
488
-                            $hasError = true;
489
-                        }
490
-                    }
491
-                } else {
492
-                    // Check to see if this important token is the same as the
493
-                    // next important token in the pattern. If it is not, then
494
-                    // the pattern cannot be for this piece of code.
495
-                    $next = $phpcsFile->findNext(
496
-                        $ignoreTokens,
497
-                        $stackPtr,
498
-                        null,
499
-                        true
500
-                    );
501
-
502
-                    if ($next === false
503
-                        || $tokens[$next]['code'] !== $pattern[$i]['token']
504
-                    ) {
505
-                        // The next important token did not match the pattern.
506
-                        return false;
507
-                    }
508
-
509
-                    if ($lastAddedStackPtr !== null) {
510
-                        if (($tokens[$next]['code'] === T_OPEN_CURLY_BRACKET
511
-                            || $tokens[$next]['code'] === T_CLOSE_CURLY_BRACKET)
512
-                            && isset($tokens[$next]['scope_condition']) === true
513
-                            && $tokens[$next]['scope_condition'] > $lastAddedStackPtr
514
-                        ) {
515
-                            // This is a brace, but the owner of it is after the current
516
-                            // token, which means it does not belong to any token in
517
-                            // our pattern. This means the pattern is not for us.
518
-                            return false;
519
-                        }
520
-
521
-                        if (($tokens[$next]['code'] === T_OPEN_PARENTHESIS
522
-                            || $tokens[$next]['code'] === T_CLOSE_PARENTHESIS)
523
-                            && isset($tokens[$next]['parenthesis_owner']) === true
524
-                            && $tokens[$next]['parenthesis_owner'] > $lastAddedStackPtr
525
-                        ) {
526
-                            // This is a bracket, but the owner of it is after the current
527
-                            // token, which means it does not belong to any token in
528
-                            // our pattern. This means the pattern is not for us.
529
-                            return false;
530
-                        }
531
-                    }//end if
532
-
533
-                    // If we skipped past some whitespace tokens, then add them
534
-                    // to the found string.
535
-                    if (($next - $stackPtr) > 0) {
536
-                        $hasComment = false;
537
-                        for ($j = $stackPtr; $j < $next; $j++) {
538
-                            $found .= $tokens[$j]['content'];
539
-                            if (isset(Tokens::$commentTokens[$tokens[$j]['code']]) === true) {
540
-                                $hasComment = true;
541
-                            }
542
-                        }
543
-
544
-                        // If we are not ignoring comments, this additional
545
-                        // whitespace or comment is not allowed. If we are
546
-                        // ignoring comments, there needs to be at least one
547
-                        // comment for this to be allowed.
548
-                        if ($this->ignoreComments === false
549
-                            || ($this->ignoreComments === true
550
-                            && $hasComment === false)
551
-                        ) {
552
-                            $hasError = true;
553
-                        }
554
-
555
-                        // Even when ignoring comments, we are not allowed to include
556
-                        // newlines without the pattern specifying them, so
557
-                        // everything should be on the same line.
558
-                        if ($tokens[$next]['line'] !== $tokens[$stackPtr]['line']) {
559
-                            $hasError = true;
560
-                        }
561
-                    }//end if
562
-
563
-                    if ($next !== $lastAddedStackPtr) {
564
-                        $found            .= $tokens[$next]['content'];
565
-                        $lastAddedStackPtr = $next;
566
-                    }
567
-
568
-                    if (isset($pattern[($i + 1)]) === true
569
-                        && $pattern[($i + 1)]['type'] === 'skip'
570
-                    ) {
571
-                        $stackPtr = $next;
572
-                    } else {
573
-                        $stackPtr = ($next + 1);
574
-                    }
575
-                }//end if
576
-            } else if ($pattern[$i]['type'] === 'skip') {
577
-                if ($pattern[$i]['to'] === 'unknown') {
578
-                    $next = $phpcsFile->findNext(
579
-                        $pattern[($i + 1)]['token'],
580
-                        $stackPtr
581
-                    );
582
-
583
-                    if ($next === false) {
584
-                        // Couldn't find the next token, so we must
585
-                        // be using the wrong pattern.
586
-                        return false;
587
-                    }
588
-
589
-                    $found   .= '...';
590
-                    $stackPtr = $next;
591
-                } else {
592
-                    // Find the previous opener.
593
-                    $next = $phpcsFile->findPrevious(
594
-                        Tokens::$blockOpeners,
595
-                        $stackPtr
596
-                    );
597
-
598
-                    if ($next === false
599
-                        || isset($tokens[$next][$pattern[$i]['to']]) === false
600
-                    ) {
601
-                        // If there was not opener, then we must
602
-                        // be using the wrong pattern.
603
-                        return false;
604
-                    }
605
-
606
-                    $found .= '...';
607
-                    if ($pattern[$i]['to'] === 'parenthesis_closer') {
608
-                        $found .= ')';
609
-                    } else {
610
-                        $found .= '}';
611
-                    }
612
-
613
-                    // Skip to the closing token.
614
-                    $stackPtr = ($tokens[$next][$pattern[$i]['to']] + 1);
615
-                }//end if
616
-            } else if ($pattern[$i]['type'] === 'string') {
617
-                if ($tokens[$stackPtr]['code'] !== T_STRING) {
618
-                    $hasError = true;
619
-                }
620
-
621
-                if ($stackPtr !== $lastAddedStackPtr) {
622
-                    $found            .= 'abc';
623
-                    $lastAddedStackPtr = $stackPtr;
624
-                }
625
-
626
-                $stackPtr++;
627
-            } else if ($pattern[$i]['type'] === 'newline') {
628
-                // Find the next token that contains a newline character.
629
-                $newline = 0;
630
-                for ($j = $stackPtr; $j < $phpcsFile->numTokens; $j++) {
631
-                    if (strpos($tokens[$j]['content'], $phpcsFile->eolChar) !== false) {
632
-                        $newline = $j;
633
-                        break;
634
-                    }
635
-                }
636
-
637
-                if ($newline === 0) {
638
-                    // We didn't find a newline character in the rest of the file.
639
-                    $next     = ($phpcsFile->numTokens - 1);
640
-                    $hasError = true;
641
-                } else {
642
-                    if ($this->ignoreComments === false) {
643
-                        // The newline character cannot be part of a comment.
644
-                        if (isset(Tokens::$commentTokens[$tokens[$newline]['code']]) === true) {
645
-                            $hasError = true;
646
-                        }
647
-                    }
648
-
649
-                    if ($newline === $stackPtr) {
650
-                        $next = ($stackPtr + 1);
651
-                    } else {
652
-                        // Check that there were no significant tokens that we
653
-                        // skipped over to find our newline character.
654
-                        $next = $phpcsFile->findNext(
655
-                            $ignoreTokens,
656
-                            $stackPtr,
657
-                            null,
658
-                            true
659
-                        );
660
-
661
-                        if ($next < $newline) {
662
-                            // We skipped a non-ignored token.
663
-                            $hasError = true;
664
-                        } else {
665
-                            $next = ($newline + 1);
666
-                        }
667
-                    }
668
-                }//end if
669
-
670
-                if ($stackPtr !== $lastAddedStackPtr) {
671
-                    $found .= $phpcsFile->getTokensAsString(
672
-                        $stackPtr,
673
-                        ($next - $stackPtr)
674
-                    );
675
-
676
-                    $lastAddedStackPtr = ($next - 1);
677
-                }
678
-
679
-                $stackPtr = $next;
680
-            }//end if
681
-        }//end for
682
-
683
-        if ($hasError === true) {
684
-            $error = $this->prepareError($found, $patternCode);
685
-            $errors[$origStackPtr] = $error;
686
-        }
687
-
688
-        return $errors;
689
-
690
-    }//end processPattern()
691
-
692
-
693
-    /**
694
-     * Prepares an error for the specified patternCode.
695
-     *
696
-     * @param string $found       The actual found string in the code.
697
-     * @param string $patternCode The expected pattern code.
698
-     *
699
-     * @return string The error message.
700
-     */
701
-    protected function prepareError($found, $patternCode)
702
-    {
703
-        $found    = str_replace("\r\n", '\n', $found);
704
-        $found    = str_replace("\n", '\n', $found);
705
-        $found    = str_replace("\r", '\n', $found);
706
-        $found    = str_replace("\t", '\t', $found);
707
-        $found    = str_replace('EOL', '\n', $found);
708
-        $expected = str_replace('EOL', '\n', $patternCode);
709
-
710
-        $error = "Expected \"$expected\"; found \"$found\"";
711
-
712
-        return $error;
713
-
714
-    }//end prepareError()
715
-
716
-
717
-    /**
718
-     * Returns the patterns that should be checked.
719
-     *
720
-     * @return string[]
721
-     */
722
-    abstract protected function getPatterns();
723
-
724
-
725
-    /**
726
-     * Registers any supplementary tokens that this test might wish to process.
727
-     *
728
-     * A sniff may wish to register supplementary tests when it wishes to group
729
-     * an arbitrary validation that cannot be performed using a pattern, with
730
-     * other pattern tests.
731
-     *
732
-     * @return int[]
733
-     * @see    processSupplementary()
734
-     */
735
-    protected function registerSupplementary()
736
-    {
737
-        return [];
738
-
739
-    }//end registerSupplementary()
740
-
741
-
742
-     /**
743
-      * Processes any tokens registered with registerSupplementary().
744
-      *
745
-      * @param \PHP_CodeSniffer\Files\File $phpcsFile The PHP_CodeSniffer file where to
746
-      *                                               process the skip.
747
-      * @param int                         $stackPtr  The position in the tokens stack to
748
-      *                                               process.
749
-      *
750
-      * @return void
751
-      * @see    registerSupplementary()
752
-      */
753
-    protected function processSupplementary(File $phpcsFile, $stackPtr)
754
-    {
755
-
756
-    }//end processSupplementary()
757
-
758
-
759
-    /**
760
-     * Parses a pattern string into an array of pattern steps.
761
-     *
762
-     * @param string $pattern The pattern to parse.
763
-     *
764
-     * @return array The parsed pattern array.
765
-     * @see    createSkipPattern()
766
-     * @see    createTokenPattern()
767
-     */
768
-    private function parse($pattern)
769
-    {
770
-        $patterns   = [];
771
-        $length     = strlen($pattern);
772
-        $lastToken  = 0;
773
-        $firstToken = 0;
774
-
775
-        for ($i = 0; $i < $length; $i++) {
776
-            $specialPattern = false;
777
-            $isLastChar     = ($i === ($length - 1));
778
-            $oldFirstToken  = $firstToken;
779
-
780
-            if (substr($pattern, $i, 3) === '...') {
781
-                // It's a skip pattern. The skip pattern requires the
782
-                // content of the token in the "from" position and the token
783
-                // to skip to.
784
-                $specialPattern = $this->createSkipPattern($pattern, ($i - 1));
785
-                $lastToken      = ($i - $firstToken);
786
-                $firstToken     = ($i + 3);
787
-                $i += 2;
788
-
789
-                if ($specialPattern['to'] !== 'unknown') {
790
-                    $firstToken++;
791
-                }
792
-            } else if (substr($pattern, $i, 3) === 'abc') {
793
-                $specialPattern = ['type' => 'string'];
794
-                $lastToken      = ($i - $firstToken);
795
-                $firstToken     = ($i + 3);
796
-                $i += 2;
797
-            } else if (substr($pattern, $i, 3) === 'EOL') {
798
-                $specialPattern = ['type' => 'newline'];
799
-                $lastToken      = ($i - $firstToken);
800
-                $firstToken     = ($i + 3);
801
-                $i += 2;
802
-            }//end if
803
-
804
-            if ($specialPattern !== false || $isLastChar === true) {
805
-                // If we are at the end of the string, don't worry about a limit.
806
-                if ($isLastChar === true) {
807
-                    // Get the string from the end of the last skip pattern, if any,
808
-                    // to the end of the pattern string.
809
-                    $str = substr($pattern, $oldFirstToken);
810
-                } else {
811
-                    // Get the string from the end of the last special pattern,
812
-                    // if any, to the start of this special pattern.
813
-                    if ($lastToken === 0) {
814
-                        // Note that if the last special token was zero characters ago,
815
-                        // there will be nothing to process so we can skip this bit.
816
-                        // This happens if you have something like: EOL... in your pattern.
817
-                        $str = '';
818
-                    } else {
819
-                        $str = substr($pattern, $oldFirstToken, $lastToken);
820
-                    }
821
-                }
822
-
823
-                if ($str !== '') {
824
-                    $tokenPatterns = $this->createTokenPattern($str);
825
-                    foreach ($tokenPatterns as $tokenPattern) {
826
-                        $patterns[] = $tokenPattern;
827
-                    }
828
-                }
829
-
830
-                // Make sure we don't skip the last token.
831
-                if ($isLastChar === false && $i === ($length - 1)) {
832
-                    $i--;
833
-                }
834
-            }//end if
835
-
836
-            // Add the skip pattern *after* we have processed
837
-            // all the tokens from the end of the last skip pattern
838
-            // to the start of this skip pattern.
839
-            if ($specialPattern !== false) {
840
-                $patterns[] = $specialPattern;
841
-            }
842
-        }//end for
843
-
844
-        return $patterns;
845
-
846
-    }//end parse()
847
-
848
-
849
-    /**
850
-     * Creates a skip pattern.
851
-     *
852
-     * @param string $pattern The pattern being parsed.
853
-     * @param string $from    The token content that the skip pattern starts from.
854
-     *
855
-     * @return array The pattern step.
856
-     * @see    createTokenPattern()
857
-     * @see    parse()
858
-     */
859
-    private function createSkipPattern($pattern, $from)
860
-    {
861
-        $skip = ['type' => 'skip'];
862
-
863
-        $nestedParenthesis = 0;
864
-        $nestedBraces      = 0;
865
-        for ($start = $from; $start >= 0; $start--) {
866
-            switch ($pattern[$start]) {
867
-            case '(':
868
-                if ($nestedParenthesis === 0) {
869
-                    $skip['to'] = 'parenthesis_closer';
870
-                }
871
-
872
-                $nestedParenthesis--;
873
-                break;
874
-            case '{':
875
-                if ($nestedBraces === 0) {
876
-                    $skip['to'] = 'scope_closer';
877
-                }
878
-
879
-                $nestedBraces--;
880
-                break;
881
-            case '}':
882
-                $nestedBraces++;
883
-                break;
884
-            case ')':
885
-                $nestedParenthesis++;
886
-                break;
887
-            }//end switch
888
-
889
-            if (isset($skip['to']) === true) {
890
-                break;
891
-            }
892
-        }//end for
893
-
894
-        if (isset($skip['to']) === false) {
895
-            $skip['to'] = 'unknown';
896
-        }
897
-
898
-        return $skip;
899
-
900
-    }//end createSkipPattern()
901
-
902
-
903
-    /**
904
-     * Creates a token pattern.
905
-     *
906
-     * @param string $str The tokens string that the pattern should match.
907
-     *
908
-     * @return array The pattern step.
909
-     * @see    createSkipPattern()
910
-     * @see    parse()
911
-     */
912
-    private function createTokenPattern($str)
913
-    {
914
-        // Don't add a space after the closing php tag as it will add a new
915
-        // whitespace token.
916
-        $tokenizer = new PHP('<?php '.$str.'?>', null);
917
-
918
-        // Remove the <?php tag from the front and the end php tag from the back.
919
-        $tokens = $tokenizer->getTokens();
920
-        $tokens = array_slice($tokens, 1, (count($tokens) - 2));
921
-
922
-        $patterns = [];
923
-        foreach ($tokens as $patternInfo) {
924
-            $patterns[] = [
925
-                'type'  => 'token',
926
-                'token' => $patternInfo['code'],
927
-                'value' => $patternInfo['content'],
928
-            ];
929
-        }
930
-
931
-        return $patterns;
932
-
933
-    }//end createTokenPattern()
20
+	/**
21
+	 * If true, comments will be ignored if they are found in the code.
22
+	 *
23
+	 * @var boolean
24
+	 */
25
+	public $ignoreComments = false;
26
+
27
+	/**
28
+	 * The current file being checked.
29
+	 *
30
+	 * @var string
31
+	 */
32
+	protected $currFile = '';
33
+
34
+	/**
35
+	 * The parsed patterns array.
36
+	 *
37
+	 * @var array
38
+	 */
39
+	private $parsedPatterns = [];
40
+
41
+	/**
42
+	 * Tokens that this sniff wishes to process outside of the patterns.
43
+	 *
44
+	 * @var int[]
45
+	 * @see registerSupplementary()
46
+	 * @see processSupplementary()
47
+	 */
48
+	private $supplementaryTokens = [];
49
+
50
+	/**
51
+	 * Positions in the stack where errors have occurred.
52
+	 *
53
+	 * @var array<int, bool>
54
+	 */
55
+	private $errorPos = [];
56
+
57
+
58
+	/**
59
+	 * Constructs a AbstractPatternSniff.
60
+	 *
61
+	 * @param boolean $ignoreComments If true, comments will be ignored.
62
+	 */
63
+	public function __construct($ignoreComments=null)
64
+	{
65
+		// This is here for backwards compatibility.
66
+		if ($ignoreComments !== null) {
67
+			$this->ignoreComments = $ignoreComments;
68
+		}
69
+
70
+		$this->supplementaryTokens = $this->registerSupplementary();
71
+
72
+	}//end __construct()
73
+
74
+
75
+	/**
76
+	 * Registers the tokens to listen to.
77
+	 *
78
+	 * Classes extending <i>AbstractPatternTest</i> should implement the
79
+	 * <i>getPatterns()</i> method to register the patterns they wish to test.
80
+	 *
81
+	 * @return int[]
82
+	 * @see    process()
83
+	 */
84
+	final public function register()
85
+	{
86
+		$listenTypes = [];
87
+		$patterns    = $this->getPatterns();
88
+
89
+		foreach ($patterns as $pattern) {
90
+			$parsedPattern = $this->parse($pattern);
91
+
92
+			// Find a token position in the pattern that we can use
93
+			// for a listener token.
94
+			$pos           = $this->getListenerTokenPos($parsedPattern);
95
+			$tokenType     = $parsedPattern[$pos]['token'];
96
+			$listenTypes[] = $tokenType;
97
+
98
+			$patternArray = [
99
+				'listen_pos'   => $pos,
100
+				'pattern'      => $parsedPattern,
101
+				'pattern_code' => $pattern,
102
+			];
103
+
104
+			if (isset($this->parsedPatterns[$tokenType]) === false) {
105
+				$this->parsedPatterns[$tokenType] = [];
106
+			}
107
+
108
+			$this->parsedPatterns[$tokenType][] = $patternArray;
109
+		}//end foreach
110
+
111
+		return array_unique(array_merge($listenTypes, $this->supplementaryTokens));
112
+
113
+	}//end register()
114
+
115
+
116
+	/**
117
+	 * Returns the token types that the specified pattern is checking for.
118
+	 *
119
+	 * Returned array is in the format:
120
+	 * <code>
121
+	 *   array(
122
+	 *      T_WHITESPACE => 0, // 0 is the position where the T_WHITESPACE token
123
+	 *                         // should occur in the pattern.
124
+	 *   );
125
+	 * </code>
126
+	 *
127
+	 * @param array $pattern The parsed pattern to find the acquire the token
128
+	 *                       types from.
129
+	 *
130
+	 * @return array<int, int>
131
+	 */
132
+	private function getPatternTokenTypes($pattern)
133
+	{
134
+		$tokenTypes = [];
135
+		foreach ($pattern as $pos => $patternInfo) {
136
+			if ($patternInfo['type'] === 'token') {
137
+				if (isset($tokenTypes[$patternInfo['token']]) === false) {
138
+					$tokenTypes[$patternInfo['token']] = $pos;
139
+				}
140
+			}
141
+		}
142
+
143
+		return $tokenTypes;
144
+
145
+	}//end getPatternTokenTypes()
146
+
147
+
148
+	/**
149
+	 * Returns the position in the pattern that this test should register as
150
+	 * a listener for the pattern.
151
+	 *
152
+	 * @param array $pattern The pattern to acquire the listener for.
153
+	 *
154
+	 * @return int The position in the pattern that this test should register
155
+	 *             as the listener.
156
+	 * @throws \PHP_CodeSniffer\Exceptions\RuntimeException If we could not determine a token to listen for.
157
+	 */
158
+	private function getListenerTokenPos($pattern)
159
+	{
160
+		$tokenTypes = $this->getPatternTokenTypes($pattern);
161
+		$tokenCodes = array_keys($tokenTypes);
162
+		$token      = Tokens::getHighestWeightedToken($tokenCodes);
163
+
164
+		// If we could not get a token.
165
+		if ($token === false) {
166
+			$error = 'Could not determine a token to listen for';
167
+			throw new RuntimeException($error);
168
+		}
169
+
170
+		return $tokenTypes[$token];
171
+
172
+	}//end getListenerTokenPos()
173
+
174
+
175
+	/**
176
+	 * Processes the test.
177
+	 *
178
+	 * @param \PHP_CodeSniffer\Files\File $phpcsFile The PHP_CodeSniffer file where the
179
+	 *                                               token occurred.
180
+	 * @param int                         $stackPtr  The position in the tokens stack
181
+	 *                                               where the listening token type
182
+	 *                                               was found.
183
+	 *
184
+	 * @return void
185
+	 * @see    register()
186
+	 */
187
+	final public function process(File $phpcsFile, $stackPtr)
188
+	{
189
+		$file = $phpcsFile->getFilename();
190
+		if ($this->currFile !== $file) {
191
+			// We have changed files, so clean up.
192
+			$this->errorPos = [];
193
+			$this->currFile = $file;
194
+		}
195
+
196
+		$tokens = $phpcsFile->getTokens();
197
+
198
+		if (in_array($tokens[$stackPtr]['code'], $this->supplementaryTokens, true) === true) {
199
+			$this->processSupplementary($phpcsFile, $stackPtr);
200
+		}
201
+
202
+		$type = $tokens[$stackPtr]['code'];
203
+
204
+		// If the type is not set, then it must have been a token registered
205
+		// with registerSupplementary().
206
+		if (isset($this->parsedPatterns[$type]) === false) {
207
+			return;
208
+		}
209
+
210
+		$allErrors = [];
211
+
212
+		// Loop over each pattern that is listening to the current token type
213
+		// that we are processing.
214
+		foreach ($this->parsedPatterns[$type] as $patternInfo) {
215
+			// If processPattern returns false, then the pattern that we are
216
+			// checking the code with must not be designed to check that code.
217
+			$errors = $this->processPattern($patternInfo, $phpcsFile, $stackPtr);
218
+			if ($errors === false) {
219
+				// The pattern didn't match.
220
+				continue;
221
+			} else if (empty($errors) === true) {
222
+				// The pattern matched, but there were no errors.
223
+				break;
224
+			}
225
+
226
+			foreach ($errors as $stackPtr => $error) {
227
+				if (isset($this->errorPos[$stackPtr]) === false) {
228
+					$this->errorPos[$stackPtr] = true;
229
+					$allErrors[$stackPtr]      = $error;
230
+				}
231
+			}
232
+		}
233
+
234
+		foreach ($allErrors as $stackPtr => $error) {
235
+			$phpcsFile->addError($error, $stackPtr, 'Found');
236
+		}
237
+
238
+	}//end process()
239
+
240
+
241
+	/**
242
+	 * Processes the pattern and verifies the code at $stackPtr.
243
+	 *
244
+	 * @param array                       $patternInfo Information about the pattern used
245
+	 *                                                 for checking, which includes are
246
+	 *                                                 parsed token representation of the
247
+	 *                                                 pattern.
248
+	 * @param \PHP_CodeSniffer\Files\File $phpcsFile   The PHP_CodeSniffer file where the
249
+	 *                                                 token occurred.
250
+	 * @param int                         $stackPtr    The position in the tokens stack where
251
+	 *                                                 the listening token type was found.
252
+	 *
253
+	 * @return array
254
+	 */
255
+	protected function processPattern($patternInfo, File $phpcsFile, $stackPtr)
256
+	{
257
+		$tokens      = $phpcsFile->getTokens();
258
+		$pattern     = $patternInfo['pattern'];
259
+		$patternCode = $patternInfo['pattern_code'];
260
+		$errors      = [];
261
+		$found       = '';
262
+
263
+		$ignoreTokens = [T_WHITESPACE => T_WHITESPACE];
264
+		if ($this->ignoreComments === true) {
265
+			$ignoreTokens += Tokens::$commentTokens;
266
+		}
267
+
268
+		$origStackPtr = $stackPtr;
269
+		$hasError     = false;
270
+
271
+		if ($patternInfo['listen_pos'] > 0) {
272
+			$stackPtr--;
273
+
274
+			for ($i = ($patternInfo['listen_pos'] - 1); $i >= 0; $i--) {
275
+				if ($pattern[$i]['type'] === 'token') {
276
+					if ($pattern[$i]['token'] === T_WHITESPACE) {
277
+						if ($tokens[$stackPtr]['code'] === T_WHITESPACE) {
278
+							$found = $tokens[$stackPtr]['content'].$found;
279
+						}
280
+
281
+						// Only check the size of the whitespace if this is not
282
+						// the first token. We don't care about the size of
283
+						// leading whitespace, just that there is some.
284
+						if ($i !== 0) {
285
+							if ($tokens[$stackPtr]['content'] !== $pattern[$i]['value']) {
286
+								$hasError = true;
287
+							}
288
+						}
289
+					} else {
290
+						// Check to see if this important token is the same as the
291
+						// previous important token in the pattern. If it is not,
292
+						// then the pattern cannot be for this piece of code.
293
+						$prev = $phpcsFile->findPrevious(
294
+							$ignoreTokens,
295
+							$stackPtr,
296
+							null,
297
+							true
298
+						);
299
+
300
+						if ($prev === false
301
+							|| $tokens[$prev]['code'] !== $pattern[$i]['token']
302
+						) {
303
+							return false;
304
+						}
305
+
306
+						// If we skipped past some whitespace tokens, then add them
307
+						// to the found string.
308
+						$tokenContent = $phpcsFile->getTokensAsString(
309
+							($prev + 1),
310
+							($stackPtr - $prev - 1)
311
+						);
312
+
313
+						$found = $tokens[$prev]['content'].$tokenContent.$found;
314
+
315
+						if (isset($pattern[($i - 1)]) === true
316
+							&& $pattern[($i - 1)]['type'] === 'skip'
317
+						) {
318
+							$stackPtr = $prev;
319
+						} else {
320
+							$stackPtr = ($prev - 1);
321
+						}
322
+					}//end if
323
+				} else if ($pattern[$i]['type'] === 'skip') {
324
+					// Skip to next piece of relevant code.
325
+					if ($pattern[$i]['to'] === 'parenthesis_closer') {
326
+						$to = 'parenthesis_opener';
327
+					} else {
328
+						$to = 'scope_opener';
329
+					}
330
+
331
+					// Find the previous opener.
332
+					$next = $phpcsFile->findPrevious(
333
+						$ignoreTokens,
334
+						$stackPtr,
335
+						null,
336
+						true
337
+					);
338
+
339
+					if ($next === false || isset($tokens[$next][$to]) === false) {
340
+						// If there was not opener, then we must be
341
+						// using the wrong pattern.
342
+						return false;
343
+					}
344
+
345
+					if ($to === 'parenthesis_opener') {
346
+						$found = '{'.$found;
347
+					} else {
348
+						$found = '('.$found;
349
+					}
350
+
351
+					$found = '...'.$found;
352
+
353
+					// Skip to the opening token.
354
+					$stackPtr = ($tokens[$next][$to] - 1);
355
+				} else if ($pattern[$i]['type'] === 'string') {
356
+					$found = 'abc';
357
+				} else if ($pattern[$i]['type'] === 'newline') {
358
+					if ($this->ignoreComments === true
359
+						&& isset(Tokens::$commentTokens[$tokens[$stackPtr]['code']]) === true
360
+					) {
361
+						$startComment = $phpcsFile->findPrevious(
362
+							Tokens::$commentTokens,
363
+							($stackPtr - 1),
364
+							null,
365
+							true
366
+						);
367
+
368
+						if ($tokens[$startComment]['line'] !== $tokens[($startComment + 1)]['line']) {
369
+							$startComment++;
370
+						}
371
+
372
+						$tokenContent = $phpcsFile->getTokensAsString(
373
+							$startComment,
374
+							($stackPtr - $startComment + 1)
375
+						);
376
+
377
+						$found    = $tokenContent.$found;
378
+						$stackPtr = ($startComment - 1);
379
+					}
380
+
381
+					if ($tokens[$stackPtr]['code'] === T_WHITESPACE) {
382
+						if ($tokens[$stackPtr]['content'] !== $phpcsFile->eolChar) {
383
+							$found = $tokens[$stackPtr]['content'].$found;
384
+
385
+							// This may just be an indent that comes after a newline
386
+							// so check the token before to make sure. If it is a newline, we
387
+							// can ignore the error here.
388
+							if (($tokens[($stackPtr - 1)]['content'] !== $phpcsFile->eolChar)
389
+								&& ($this->ignoreComments === true
390
+								&& isset(Tokens::$commentTokens[$tokens[($stackPtr - 1)]['code']]) === false)
391
+							) {
392
+								$hasError = true;
393
+							} else {
394
+								$stackPtr--;
395
+							}
396
+						} else {
397
+							$found = 'EOL'.$found;
398
+						}
399
+					} else {
400
+						$found    = $tokens[$stackPtr]['content'].$found;
401
+						$hasError = true;
402
+					}//end if
403
+
404
+					if ($hasError === false && $pattern[($i - 1)]['type'] !== 'newline') {
405
+						// Make sure they only have 1 newline.
406
+						$prev = $phpcsFile->findPrevious($ignoreTokens, ($stackPtr - 1), null, true);
407
+						if ($prev !== false && $tokens[$prev]['line'] !== $tokens[$stackPtr]['line']) {
408
+							$hasError = true;
409
+						}
410
+					}
411
+				}//end if
412
+			}//end for
413
+		}//end if
414
+
415
+		$stackPtr          = $origStackPtr;
416
+		$lastAddedStackPtr = null;
417
+		$patternLen        = count($pattern);
418
+
419
+		for ($i = $patternInfo['listen_pos']; $i < $patternLen; $i++) {
420
+			if (isset($tokens[$stackPtr]) === false) {
421
+				break;
422
+			}
423
+
424
+			if ($pattern[$i]['type'] === 'token') {
425
+				if ($pattern[$i]['token'] === T_WHITESPACE) {
426
+					if ($this->ignoreComments === true) {
427
+						// If we are ignoring comments, check to see if this current
428
+						// token is a comment. If so skip it.
429
+						if (isset(Tokens::$commentTokens[$tokens[$stackPtr]['code']]) === true) {
430
+							continue;
431
+						}
432
+
433
+						// If the next token is a comment, the we need to skip the
434
+						// current token as we should allow a space before a
435
+						// comment for readability.
436
+						if (isset($tokens[($stackPtr + 1)]) === true
437
+							&& isset(Tokens::$commentTokens[$tokens[($stackPtr + 1)]['code']]) === true
438
+						) {
439
+							continue;
440
+						}
441
+					}
442
+
443
+					$tokenContent = '';
444
+					if ($tokens[$stackPtr]['code'] === T_WHITESPACE) {
445
+						if (isset($pattern[($i + 1)]) === false) {
446
+							// This is the last token in the pattern, so just compare
447
+							// the next token of content.
448
+							$tokenContent = $tokens[$stackPtr]['content'];
449
+						} else {
450
+							// Get all the whitespace to the next token.
451
+							$next = $phpcsFile->findNext(
452
+								Tokens::$emptyTokens,
453
+								$stackPtr,
454
+								null,
455
+								true
456
+							);
457
+
458
+							$tokenContent = $phpcsFile->getTokensAsString(
459
+								$stackPtr,
460
+								($next - $stackPtr)
461
+							);
462
+
463
+							$lastAddedStackPtr = $stackPtr;
464
+							$stackPtr          = $next;
465
+						}//end if
466
+
467
+						if ($stackPtr !== $lastAddedStackPtr) {
468
+							$found .= $tokenContent;
469
+						}
470
+					} else {
471
+						if ($stackPtr !== $lastAddedStackPtr) {
472
+							$found            .= $tokens[$stackPtr]['content'];
473
+							$lastAddedStackPtr = $stackPtr;
474
+						}
475
+					}//end if
476
+
477
+					if (isset($pattern[($i + 1)]) === true
478
+						&& $pattern[($i + 1)]['type'] === 'skip'
479
+					) {
480
+						// The next token is a skip token, so we just need to make
481
+						// sure the whitespace we found has *at least* the
482
+						// whitespace required.
483
+						if (strpos($tokenContent, $pattern[$i]['value']) !== 0) {
484
+							$hasError = true;
485
+						}
486
+					} else {
487
+						if ($tokenContent !== $pattern[$i]['value']) {
488
+							$hasError = true;
489
+						}
490
+					}
491
+				} else {
492
+					// Check to see if this important token is the same as the
493
+					// next important token in the pattern. If it is not, then
494
+					// the pattern cannot be for this piece of code.
495
+					$next = $phpcsFile->findNext(
496
+						$ignoreTokens,
497
+						$stackPtr,
498
+						null,
499
+						true
500
+					);
501
+
502
+					if ($next === false
503
+						|| $tokens[$next]['code'] !== $pattern[$i]['token']
504
+					) {
505
+						// The next important token did not match the pattern.
506
+						return false;
507
+					}
508
+
509
+					if ($lastAddedStackPtr !== null) {
510
+						if (($tokens[$next]['code'] === T_OPEN_CURLY_BRACKET
511
+							|| $tokens[$next]['code'] === T_CLOSE_CURLY_BRACKET)
512
+							&& isset($tokens[$next]['scope_condition']) === true
513
+							&& $tokens[$next]['scope_condition'] > $lastAddedStackPtr
514
+						) {
515
+							// This is a brace, but the owner of it is after the current
516
+							// token, which means it does not belong to any token in
517
+							// our pattern. This means the pattern is not for us.
518
+							return false;
519
+						}
520
+
521
+						if (($tokens[$next]['code'] === T_OPEN_PARENTHESIS
522
+							|| $tokens[$next]['code'] === T_CLOSE_PARENTHESIS)
523
+							&& isset($tokens[$next]['parenthesis_owner']) === true
524
+							&& $tokens[$next]['parenthesis_owner'] > $lastAddedStackPtr
525
+						) {
526
+							// This is a bracket, but the owner of it is after the current
527
+							// token, which means it does not belong to any token in
528
+							// our pattern. This means the pattern is not for us.
529
+							return false;
530
+						}
531
+					}//end if
532
+
533
+					// If we skipped past some whitespace tokens, then add them
534
+					// to the found string.
535
+					if (($next - $stackPtr) > 0) {
536
+						$hasComment = false;
537
+						for ($j = $stackPtr; $j < $next; $j++) {
538
+							$found .= $tokens[$j]['content'];
539
+							if (isset(Tokens::$commentTokens[$tokens[$j]['code']]) === true) {
540
+								$hasComment = true;
541
+							}
542
+						}
543
+
544
+						// If we are not ignoring comments, this additional
545
+						// whitespace or comment is not allowed. If we are
546
+						// ignoring comments, there needs to be at least one
547
+						// comment for this to be allowed.
548
+						if ($this->ignoreComments === false
549
+							|| ($this->ignoreComments === true
550
+							&& $hasComment === false)
551
+						) {
552
+							$hasError = true;
553
+						}
554
+
555
+						// Even when ignoring comments, we are not allowed to include
556
+						// newlines without the pattern specifying them, so
557
+						// everything should be on the same line.
558
+						if ($tokens[$next]['line'] !== $tokens[$stackPtr]['line']) {
559
+							$hasError = true;
560
+						}
561
+					}//end if
562
+
563
+					if ($next !== $lastAddedStackPtr) {
564
+						$found            .= $tokens[$next]['content'];
565
+						$lastAddedStackPtr = $next;
566
+					}
567
+
568
+					if (isset($pattern[($i + 1)]) === true
569
+						&& $pattern[($i + 1)]['type'] === 'skip'
570
+					) {
571
+						$stackPtr = $next;
572
+					} else {
573
+						$stackPtr = ($next + 1);
574
+					}
575
+				}//end if
576
+			} else if ($pattern[$i]['type'] === 'skip') {
577
+				if ($pattern[$i]['to'] === 'unknown') {
578
+					$next = $phpcsFile->findNext(
579
+						$pattern[($i + 1)]['token'],
580
+						$stackPtr
581
+					);
582
+
583
+					if ($next === false) {
584
+						// Couldn't find the next token, so we must
585
+						// be using the wrong pattern.
586
+						return false;
587
+					}
588
+
589
+					$found   .= '...';
590
+					$stackPtr = $next;
591
+				} else {
592
+					// Find the previous opener.
593
+					$next = $phpcsFile->findPrevious(
594
+						Tokens::$blockOpeners,
595
+						$stackPtr
596
+					);
597
+
598
+					if ($next === false
599
+						|| isset($tokens[$next][$pattern[$i]['to']]) === false
600
+					) {
601
+						// If there was not opener, then we must
602
+						// be using the wrong pattern.
603
+						return false;
604
+					}
605
+
606
+					$found .= '...';
607
+					if ($pattern[$i]['to'] === 'parenthesis_closer') {
608
+						$found .= ')';
609
+					} else {
610
+						$found .= '}';
611
+					}
612
+
613
+					// Skip to the closing token.
614
+					$stackPtr = ($tokens[$next][$pattern[$i]['to']] + 1);
615
+				}//end if
616
+			} else if ($pattern[$i]['type'] === 'string') {
617
+				if ($tokens[$stackPtr]['code'] !== T_STRING) {
618
+					$hasError = true;
619
+				}
620
+
621
+				if ($stackPtr !== $lastAddedStackPtr) {
622
+					$found            .= 'abc';
623
+					$lastAddedStackPtr = $stackPtr;
624
+				}
625
+
626
+				$stackPtr++;
627
+			} else if ($pattern[$i]['type'] === 'newline') {
628
+				// Find the next token that contains a newline character.
629
+				$newline = 0;
630
+				for ($j = $stackPtr; $j < $phpcsFile->numTokens; $j++) {
631
+					if (strpos($tokens[$j]['content'], $phpcsFile->eolChar) !== false) {
632
+						$newline = $j;
633
+						break;
634
+					}
635
+				}
636
+
637
+				if ($newline === 0) {
638
+					// We didn't find a newline character in the rest of the file.
639
+					$next     = ($phpcsFile->numTokens - 1);
640
+					$hasError = true;
641
+				} else {
642
+					if ($this->ignoreComments === false) {
643
+						// The newline character cannot be part of a comment.
644
+						if (isset(Tokens::$commentTokens[$tokens[$newline]['code']]) === true) {
645
+							$hasError = true;
646
+						}
647
+					}
648
+
649
+					if ($newline === $stackPtr) {
650
+						$next = ($stackPtr + 1);
651
+					} else {
652
+						// Check that there were no significant tokens that we
653
+						// skipped over to find our newline character.
654
+						$next = $phpcsFile->findNext(
655
+							$ignoreTokens,
656
+							$stackPtr,
657
+							null,
658
+							true
659
+						);
660
+
661
+						if ($next < $newline) {
662
+							// We skipped a non-ignored token.
663
+							$hasError = true;
664
+						} else {
665
+							$next = ($newline + 1);
666
+						}
667
+					}
668
+				}//end if
669
+
670
+				if ($stackPtr !== $lastAddedStackPtr) {
671
+					$found .= $phpcsFile->getTokensAsString(
672
+						$stackPtr,
673
+						($next - $stackPtr)
674
+					);
675
+
676
+					$lastAddedStackPtr = ($next - 1);
677
+				}
678
+
679
+				$stackPtr = $next;
680
+			}//end if
681
+		}//end for
682
+
683
+		if ($hasError === true) {
684
+			$error = $this->prepareError($found, $patternCode);
685
+			$errors[$origStackPtr] = $error;
686
+		}
687
+
688
+		return $errors;
689
+
690
+	}//end processPattern()
691
+
692
+
693
+	/**
694
+	 * Prepares an error for the specified patternCode.
695
+	 *
696
+	 * @param string $found       The actual found string in the code.
697
+	 * @param string $patternCode The expected pattern code.
698
+	 *
699
+	 * @return string The error message.
700
+	 */
701
+	protected function prepareError($found, $patternCode)
702
+	{
703
+		$found    = str_replace("\r\n", '\n', $found);
704
+		$found    = str_replace("\n", '\n', $found);
705
+		$found    = str_replace("\r", '\n', $found);
706
+		$found    = str_replace("\t", '\t', $found);
707
+		$found    = str_replace('EOL', '\n', $found);
708
+		$expected = str_replace('EOL', '\n', $patternCode);
709
+
710
+		$error = "Expected \"$expected\"; found \"$found\"";
711
+
712
+		return $error;
713
+
714
+	}//end prepareError()
715
+
716
+
717
+	/**
718
+	 * Returns the patterns that should be checked.
719
+	 *
720
+	 * @return string[]
721
+	 */
722
+	abstract protected function getPatterns();
723
+
724
+
725
+	/**
726
+	 * Registers any supplementary tokens that this test might wish to process.
727
+	 *
728
+	 * A sniff may wish to register supplementary tests when it wishes to group
729
+	 * an arbitrary validation that cannot be performed using a pattern, with
730
+	 * other pattern tests.
731
+	 *
732
+	 * @return int[]
733
+	 * @see    processSupplementary()
734
+	 */
735
+	protected function registerSupplementary()
736
+	{
737
+		return [];
738
+
739
+	}//end registerSupplementary()
740
+
741
+
742
+	 /**
743
+	  * Processes any tokens registered with registerSupplementary().
744
+	  *
745
+	  * @param \PHP_CodeSniffer\Files\File $phpcsFile The PHP_CodeSniffer file where to
746
+	  *                                               process the skip.
747
+	  * @param int                         $stackPtr  The position in the tokens stack to
748
+	  *                                               process.
749
+	  *
750
+	  * @return void
751
+	  * @see    registerSupplementary()
752
+	  */
753
+	protected function processSupplementary(File $phpcsFile, $stackPtr)
754
+	{
755
+
756
+	}//end processSupplementary()
757
+
758
+
759
+	/**
760
+	 * Parses a pattern string into an array of pattern steps.
761
+	 *
762
+	 * @param string $pattern The pattern to parse.
763
+	 *
764
+	 * @return array The parsed pattern array.
765
+	 * @see    createSkipPattern()
766
+	 * @see    createTokenPattern()
767
+	 */
768
+	private function parse($pattern)
769
+	{
770
+		$patterns   = [];
771
+		$length     = strlen($pattern);
772
+		$lastToken  = 0;
773
+		$firstToken = 0;
774
+
775
+		for ($i = 0; $i < $length; $i++) {
776
+			$specialPattern = false;
777
+			$isLastChar     = ($i === ($length - 1));
778
+			$oldFirstToken  = $firstToken;
779
+
780
+			if (substr($pattern, $i, 3) === '...') {
781
+				// It's a skip pattern. The skip pattern requires the
782
+				// content of the token in the "from" position and the token
783
+				// to skip to.
784
+				$specialPattern = $this->createSkipPattern($pattern, ($i - 1));
785
+				$lastToken      = ($i - $firstToken);
786
+				$firstToken     = ($i + 3);
787
+				$i += 2;
788
+
789
+				if ($specialPattern['to'] !== 'unknown') {
790
+					$firstToken++;
791
+				}
792
+			} else if (substr($pattern, $i, 3) === 'abc') {
793
+				$specialPattern = ['type' => 'string'];
794
+				$lastToken      = ($i - $firstToken);
795
+				$firstToken     = ($i + 3);
796
+				$i += 2;
797
+			} else if (substr($pattern, $i, 3) === 'EOL') {
798
+				$specialPattern = ['type' => 'newline'];
799
+				$lastToken      = ($i - $firstToken);
800
+				$firstToken     = ($i + 3);
801
+				$i += 2;
802
+			}//end if
803
+
804
+			if ($specialPattern !== false || $isLastChar === true) {
805
+				// If we are at the end of the string, don't worry about a limit.
806
+				if ($isLastChar === true) {
807
+					// Get the string from the end of the last skip pattern, if any,
808
+					// to the end of the pattern string.
809
+					$str = substr($pattern, $oldFirstToken);
810
+				} else {
811
+					// Get the string from the end of the last special pattern,
812
+					// if any, to the start of this special pattern.
813
+					if ($lastToken === 0) {
814
+						// Note that if the last special token was zero characters ago,
815
+						// there will be nothing to process so we can skip this bit.
816
+						// This happens if you have something like: EOL... in your pattern.
817
+						$str = '';
818
+					} else {
819
+						$str = substr($pattern, $oldFirstToken, $lastToken);
820
+					}
821
+				}
822
+
823
+				if ($str !== '') {
824
+					$tokenPatterns = $this->createTokenPattern($str);
825
+					foreach ($tokenPatterns as $tokenPattern) {
826
+						$patterns[] = $tokenPattern;
827
+					}
828
+				}
829
+
830
+				// Make sure we don't skip the last token.
831
+				if ($isLastChar === false && $i === ($length - 1)) {
832
+					$i--;
833
+				}
834
+			}//end if
835
+
836
+			// Add the skip pattern *after* we have processed
837
+			// all the tokens from the end of the last skip pattern
838
+			// to the start of this skip pattern.
839
+			if ($specialPattern !== false) {
840
+				$patterns[] = $specialPattern;
841
+			}
842
+		}//end for
843
+
844
+		return $patterns;
845
+
846
+	}//end parse()
847
+
848
+
849
+	/**
850
+	 * Creates a skip pattern.
851
+	 *
852
+	 * @param string $pattern The pattern being parsed.
853
+	 * @param string $from    The token content that the skip pattern starts from.
854
+	 *
855
+	 * @return array The pattern step.
856
+	 * @see    createTokenPattern()
857
+	 * @see    parse()
858
+	 */
859
+	private function createSkipPattern($pattern, $from)
860
+	{
861
+		$skip = ['type' => 'skip'];
862
+
863
+		$nestedParenthesis = 0;
864
+		$nestedBraces      = 0;
865
+		for ($start = $from; $start >= 0; $start--) {
866
+			switch ($pattern[$start]) {
867
+			case '(':
868
+				if ($nestedParenthesis === 0) {
869
+					$skip['to'] = 'parenthesis_closer';
870
+				}
871
+
872
+				$nestedParenthesis--;
873
+				break;
874
+			case '{':
875
+				if ($nestedBraces === 0) {
876
+					$skip['to'] = 'scope_closer';
877
+				}
878
+
879
+				$nestedBraces--;
880
+				break;
881
+			case '}':
882
+				$nestedBraces++;
883
+				break;
884
+			case ')':
885
+				$nestedParenthesis++;
886
+				break;
887
+			}//end switch
888
+
889
+			if (isset($skip['to']) === true) {
890
+				break;
891
+			}
892
+		}//end for
893
+
894
+		if (isset($skip['to']) === false) {
895
+			$skip['to'] = 'unknown';
896
+		}
897
+
898
+		return $skip;
899
+
900
+	}//end createSkipPattern()
901
+
902
+
903
+	/**
904
+	 * Creates a token pattern.
905
+	 *
906
+	 * @param string $str The tokens string that the pattern should match.
907
+	 *
908
+	 * @return array The pattern step.
909
+	 * @see    createSkipPattern()
910
+	 * @see    parse()
911
+	 */
912
+	private function createTokenPattern($str)
913
+	{
914
+		// Don't add a space after the closing php tag as it will add a new
915
+		// whitespace token.
916
+		$tokenizer = new PHP('<?php '.$str.'?>', null);
917
+
918
+		// Remove the <?php tag from the front and the end php tag from the back.
919
+		$tokens = $tokenizer->getTokens();
920
+		$tokens = array_slice($tokens, 1, (count($tokens) - 2));
921
+
922
+		$patterns = [];
923
+		foreach ($tokens as $patternInfo) {
924
+			$patterns[] = [
925
+				'type'  => 'token',
926
+				'token' => $patternInfo['code'],
927
+				'value' => $patternInfo['content'],
928
+			];
929
+		}
930
+
931
+		return $patterns;
932
+
933
+	}//end createTokenPattern()
934 934
 
935 935
 
936 936
 }//end class
Please login to merge, or discard this patch.
vendor/squizlabs/php_codesniffer/src/Generators/Generator.php 1 patch
Indentation   +94 added lines, -94 removed lines patch added patch discarded remove patch
@@ -19,100 +19,100 @@
 block discarded – undo
19 19
 abstract class Generator
20 20
 {
21 21
 
22
-    /**
23
-     * The ruleset used for the run.
24
-     *
25
-     * @var \PHP_CodeSniffer\Ruleset
26
-     */
27
-    public $ruleset = null;
28
-
29
-    /**
30
-     * XML documentation files used to produce the final output.
31
-     *
32
-     * @var string[]
33
-     */
34
-    public $docFiles = [];
35
-
36
-
37
-    /**
38
-     * Constructs a doc generator.
39
-     *
40
-     * @param \PHP_CodeSniffer\Ruleset $ruleset The ruleset used for the run.
41
-     *
42
-     * @see generate()
43
-     */
44
-    public function __construct(Ruleset $ruleset)
45
-    {
46
-        $this->ruleset = $ruleset;
47
-
48
-        foreach ($ruleset->sniffs as $className => $sniffClass) {
49
-            $file    = Autoload::getLoadedFileName($className);
50
-            $docFile = str_replace(
51
-                DIRECTORY_SEPARATOR.'Sniffs'.DIRECTORY_SEPARATOR,
52
-                DIRECTORY_SEPARATOR.'Docs'.DIRECTORY_SEPARATOR,
53
-                $file
54
-            );
55
-            $docFile = str_replace('Sniff.php', 'Standard.xml', $docFile);
56
-
57
-            if (is_file($docFile) === true) {
58
-                $this->docFiles[] = $docFile;
59
-            }
60
-        }
61
-
62
-    }//end __construct()
63
-
64
-
65
-    /**
66
-     * Retrieves the title of the sniff from the DOMNode supplied.
67
-     *
68
-     * @param \DOMNode $doc The DOMNode object for the sniff.
69
-     *                      It represents the "documentation" tag in the XML
70
-     *                      standard file.
71
-     *
72
-     * @return string
73
-     */
74
-    protected function getTitle(\DOMNode $doc)
75
-    {
76
-        return $doc->getAttribute('title');
77
-
78
-    }//end getTitle()
79
-
80
-
81
-    /**
82
-     * Generates the documentation for a standard.
83
-     *
84
-     * It's probably wise for doc generators to override this method so they
85
-     * have control over how the docs are produced. Otherwise, the processSniff
86
-     * method should be overridden to output content for each sniff.
87
-     *
88
-     * @return void
89
-     * @see    processSniff()
90
-     */
91
-    public function generate()
92
-    {
93
-        foreach ($this->docFiles as $file) {
94
-            $doc = new \DOMDocument();
95
-            $doc->load($file);
96
-            $documentation = $doc->getElementsByTagName('documentation')->item(0);
97
-            $this->processSniff($documentation);
98
-        }
99
-
100
-    }//end generate()
101
-
102
-
103
-    /**
104
-     * Process the documentation for a single sniff.
105
-     *
106
-     * Doc generators must implement this function to produce output.
107
-     *
108
-     * @param \DOMNode $doc The DOMNode object for the sniff.
109
-     *                      It represents the "documentation" tag in the XML
110
-     *                      standard file.
111
-     *
112
-     * @return void
113
-     * @see    generate()
114
-     */
115
-    abstract protected function processSniff(\DOMNode $doc);
22
+	/**
23
+	 * The ruleset used for the run.
24
+	 *
25
+	 * @var \PHP_CodeSniffer\Ruleset
26
+	 */
27
+	public $ruleset = null;
28
+
29
+	/**
30
+	 * XML documentation files used to produce the final output.
31
+	 *
32
+	 * @var string[]
33
+	 */
34
+	public $docFiles = [];
35
+
36
+
37
+	/**
38
+	 * Constructs a doc generator.
39
+	 *
40
+	 * @param \PHP_CodeSniffer\Ruleset $ruleset The ruleset used for the run.
41
+	 *
42
+	 * @see generate()
43
+	 */
44
+	public function __construct(Ruleset $ruleset)
45
+	{
46
+		$this->ruleset = $ruleset;
47
+
48
+		foreach ($ruleset->sniffs as $className => $sniffClass) {
49
+			$file    = Autoload::getLoadedFileName($className);
50
+			$docFile = str_replace(
51
+				DIRECTORY_SEPARATOR.'Sniffs'.DIRECTORY_SEPARATOR,
52
+				DIRECTORY_SEPARATOR.'Docs'.DIRECTORY_SEPARATOR,
53
+				$file
54
+			);
55
+			$docFile = str_replace('Sniff.php', 'Standard.xml', $docFile);
56
+
57
+			if (is_file($docFile) === true) {
58
+				$this->docFiles[] = $docFile;
59
+			}
60
+		}
61
+
62
+	}//end __construct()
63
+
64
+
65
+	/**
66
+	 * Retrieves the title of the sniff from the DOMNode supplied.
67
+	 *
68
+	 * @param \DOMNode $doc The DOMNode object for the sniff.
69
+	 *                      It represents the "documentation" tag in the XML
70
+	 *                      standard file.
71
+	 *
72
+	 * @return string
73
+	 */
74
+	protected function getTitle(\DOMNode $doc)
75
+	{
76
+		return $doc->getAttribute('title');
77
+
78
+	}//end getTitle()
79
+
80
+
81
+	/**
82
+	 * Generates the documentation for a standard.
83
+	 *
84
+	 * It's probably wise for doc generators to override this method so they
85
+	 * have control over how the docs are produced. Otherwise, the processSniff
86
+	 * method should be overridden to output content for each sniff.
87
+	 *
88
+	 * @return void
89
+	 * @see    processSniff()
90
+	 */
91
+	public function generate()
92
+	{
93
+		foreach ($this->docFiles as $file) {
94
+			$doc = new \DOMDocument();
95
+			$doc->load($file);
96
+			$documentation = $doc->getElementsByTagName('documentation')->item(0);
97
+			$this->processSniff($documentation);
98
+		}
99
+
100
+	}//end generate()
101
+
102
+
103
+	/**
104
+	 * Process the documentation for a single sniff.
105
+	 *
106
+	 * Doc generators must implement this function to produce output.
107
+	 *
108
+	 * @param \DOMNode $doc The DOMNode object for the sniff.
109
+	 *                      It represents the "documentation" tag in the XML
110
+	 *                      standard file.
111
+	 *
112
+	 * @return void
113
+	 * @see    generate()
114
+	 */
115
+	abstract protected function processSniff(\DOMNode $doc);
116 116
 
117 117
 
118 118
 }//end class
Please login to merge, or discard this patch.
vendor/squizlabs/php_codesniffer/src/Generators/HTML.php 1 patch
Indentation   +181 added lines, -181 removed lines patch added patch discarded remove patch
@@ -19,47 +19,47 @@  discard block
 block discarded – undo
19 19
 {
20 20
 
21 21
 
22
-    /**
23
-     * Generates the documentation for a standard.
24
-     *
25
-     * @return void
26
-     * @see    processSniff()
27
-     */
28
-    public function generate()
29
-    {
30
-        ob_start();
31
-        $this->printHeader();
32
-        $this->printToc();
33
-
34
-        foreach ($this->docFiles as $file) {
35
-            $doc = new \DOMDocument();
36
-            $doc->load($file);
37
-            $documentation = $doc->getElementsByTagName('documentation')->item(0);
38
-            $this->processSniff($documentation);
39
-        }
40
-
41
-        $this->printFooter();
42
-
43
-        $content = ob_get_contents();
44
-        ob_end_clean();
45
-
46
-        echo $content;
47
-
48
-    }//end generate()
49
-
50
-
51
-    /**
52
-     * Print the header of the HTML page.
53
-     *
54
-     * @return void
55
-     */
56
-    protected function printHeader()
57
-    {
58
-        $standard = $this->ruleset->name;
59
-        echo '<html>'.PHP_EOL;
60
-        echo ' <head>'.PHP_EOL;
61
-        echo "  <title>$standard Coding Standards</title>".PHP_EOL;
62
-        echo '  <style>
22
+	/**
23
+	 * Generates the documentation for a standard.
24
+	 *
25
+	 * @return void
26
+	 * @see    processSniff()
27
+	 */
28
+	public function generate()
29
+	{
30
+		ob_start();
31
+		$this->printHeader();
32
+		$this->printToc();
33
+
34
+		foreach ($this->docFiles as $file) {
35
+			$doc = new \DOMDocument();
36
+			$doc->load($file);
37
+			$documentation = $doc->getElementsByTagName('documentation')->item(0);
38
+			$this->processSniff($documentation);
39
+		}
40
+
41
+		$this->printFooter();
42
+
43
+		$content = ob_get_contents();
44
+		ob_end_clean();
45
+
46
+		echo $content;
47
+
48
+	}//end generate()
49
+
50
+
51
+	/**
52
+	 * Print the header of the HTML page.
53
+	 *
54
+	 * @return void
55
+	 */
56
+	protected function printHeader()
57
+	{
58
+		$standard = $this->ruleset->name;
59
+		echo '<html>'.PHP_EOL;
60
+		echo ' <head>'.PHP_EOL;
61
+		echo "  <title>$standard Coding Standards</title>".PHP_EOL;
62
+		echo '  <style>
63 63
                     body {
64 64
                         background-color: #FFFFFF;
65 65
                         font-size: 14px;
@@ -125,146 +125,146 @@  discard block
 block discarded – undo
125 125
                         color: #000000;
126 126
                     }
127 127
                 </style>'.PHP_EOL;
128
-        echo ' </head>'.PHP_EOL;
129
-        echo ' <body>'.PHP_EOL;
130
-        echo "  <h1>$standard Coding Standards</h1>".PHP_EOL;
131
-
132
-    }//end printHeader()
133
-
134
-
135
-    /**
136
-     * Print the table of contents for the standard.
137
-     *
138
-     * The TOC is just an unordered list of bookmarks to sniffs on the page.
139
-     *
140
-     * @return void
141
-     */
142
-    protected function printToc()
143
-    {
144
-        echo '  <h2>Table of Contents</h2>'.PHP_EOL;
145
-        echo '  <ul class="toc">'.PHP_EOL;
146
-
147
-        foreach ($this->docFiles as $file) {
148
-            $doc = new \DOMDocument();
149
-            $doc->load($file);
150
-            $documentation = $doc->getElementsByTagName('documentation')->item(0);
151
-            $title         = $this->getTitle($documentation);
152
-            echo '   <li><a href="#'.str_replace(' ', '-', $title)."\">$title</a></li>".PHP_EOL;
153
-        }
154
-
155
-        echo '  </ul>'.PHP_EOL;
156
-
157
-    }//end printToc()
158
-
159
-
160
-    /**
161
-     * Print the footer of the HTML page.
162
-     *
163
-     * @return void
164
-     */
165
-    protected function printFooter()
166
-    {
167
-        // Turn off errors so we don't get timezone warnings if people
168
-        // don't have their timezone set.
169
-        $errorLevel = error_reporting(0);
170
-        echo '  <div class="tag-line">';
171
-        echo 'Documentation generated on '.date('r');
172
-        echo ' by <a href="https://github.com/squizlabs/PHP_CodeSniffer">PHP_CodeSniffer '.Config::VERSION.'</a>';
173
-        echo '</div>'.PHP_EOL;
174
-        error_reporting($errorLevel);
175
-
176
-        echo ' </body>'.PHP_EOL;
177
-        echo '</html>'.PHP_EOL;
178
-
179
-    }//end printFooter()
180
-
181
-
182
-    /**
183
-     * Process the documentation for a single sniff.
184
-     *
185
-     * @param \DOMNode $doc The DOMNode object for the sniff.
186
-     *                      It represents the "documentation" tag in the XML
187
-     *                      standard file.
188
-     *
189
-     * @return void
190
-     */
191
-    public function processSniff(\DOMNode $doc)
192
-    {
193
-        $title = $this->getTitle($doc);
194
-        echo '  <a name="'.str_replace(' ', '-', $title).'" />'.PHP_EOL;
195
-        echo "  <h2>$title</h2>".PHP_EOL;
196
-
197
-        foreach ($doc->childNodes as $node) {
198
-            if ($node->nodeName === 'standard') {
199
-                $this->printTextBlock($node);
200
-            } else if ($node->nodeName === 'code_comparison') {
201
-                $this->printCodeComparisonBlock($node);
202
-            }
203
-        }
204
-
205
-    }//end processSniff()
206
-
207
-
208
-    /**
209
-     * Print a text block found in a standard.
210
-     *
211
-     * @param \DOMNode $node The DOMNode object for the text block.
212
-     *
213
-     * @return void
214
-     */
215
-    protected function printTextBlock(\DOMNode $node)
216
-    {
217
-        $content = trim($node->nodeValue);
218
-        $content = htmlspecialchars($content);
219
-
220
-        // Allow em tags only.
221
-        $content = str_replace('&lt;em&gt;', '<em>', $content);
222
-        $content = str_replace('&lt;/em&gt;', '</em>', $content);
223
-
224
-        echo "  <p class=\"text\">$content</p>".PHP_EOL;
225
-
226
-    }//end printTextBlock()
227
-
228
-
229
-    /**
230
-     * Print a code comparison block found in a standard.
231
-     *
232
-     * @param \DOMNode $node The DOMNode object for the code comparison block.
233
-     *
234
-     * @return void
235
-     */
236
-    protected function printCodeComparisonBlock(\DOMNode $node)
237
-    {
238
-        $codeBlocks = $node->getElementsByTagName('code');
239
-
240
-        $firstTitle = $codeBlocks->item(0)->getAttribute('title');
241
-        $first      = trim($codeBlocks->item(0)->nodeValue);
242
-        $first      = str_replace('<?php', '&lt;?php', $first);
243
-        $first      = str_replace("\n", '</br>', $first);
244
-        $first      = str_replace(' ', '&nbsp;', $first);
245
-        $first      = str_replace('<em>', '<span class="code-comparison-highlight">', $first);
246
-        $first      = str_replace('</em>', '</span>', $first);
247
-
248
-        $secondTitle = $codeBlocks->item(1)->getAttribute('title');
249
-        $second      = trim($codeBlocks->item(1)->nodeValue);
250
-        $second      = str_replace('<?php', '&lt;?php', $second);
251
-        $second      = str_replace("\n", '</br>', $second);
252
-        $second      = str_replace(' ', '&nbsp;', $second);
253
-        $second      = str_replace('<em>', '<span class="code-comparison-highlight">', $second);
254
-        $second      = str_replace('</em>', '</span>', $second);
255
-
256
-        echo '  <table class="code-comparison">'.PHP_EOL;
257
-        echo '   <tr>'.PHP_EOL;
258
-        echo "    <td class=\"code-comparison-title\">$firstTitle</td>".PHP_EOL;
259
-        echo "    <td class=\"code-comparison-title\">$secondTitle</td>".PHP_EOL;
260
-        echo '   </tr>'.PHP_EOL;
261
-        echo '   <tr>'.PHP_EOL;
262
-        echo "    <td class=\"code-comparison-code\">$first</td>".PHP_EOL;
263
-        echo "    <td class=\"code-comparison-code\">$second</td>".PHP_EOL;
264
-        echo '   </tr>'.PHP_EOL;
265
-        echo '  </table>'.PHP_EOL;
266
-
267
-    }//end printCodeComparisonBlock()
128
+		echo ' </head>'.PHP_EOL;
129
+		echo ' <body>'.PHP_EOL;
130
+		echo "  <h1>$standard Coding Standards</h1>".PHP_EOL;
131
+
132
+	}//end printHeader()
133
+
134
+
135
+	/**
136
+	 * Print the table of contents for the standard.
137
+	 *
138
+	 * The TOC is just an unordered list of bookmarks to sniffs on the page.
139
+	 *
140
+	 * @return void
141
+	 */
142
+	protected function printToc()
143
+	{
144
+		echo '  <h2>Table of Contents</h2>'.PHP_EOL;
145
+		echo '  <ul class="toc">'.PHP_EOL;
146
+
147
+		foreach ($this->docFiles as $file) {
148
+			$doc = new \DOMDocument();
149
+			$doc->load($file);
150
+			$documentation = $doc->getElementsByTagName('documentation')->item(0);
151
+			$title         = $this->getTitle($documentation);
152
+			echo '   <li><a href="#'.str_replace(' ', '-', $title)."\">$title</a></li>".PHP_EOL;
153
+		}
154
+
155
+		echo '  </ul>'.PHP_EOL;
156
+
157
+	}//end printToc()
158
+
159
+
160
+	/**
161
+	 * Print the footer of the HTML page.
162
+	 *
163
+	 * @return void
164
+	 */
165
+	protected function printFooter()
166
+	{
167
+		// Turn off errors so we don't get timezone warnings if people
168
+		// don't have their timezone set.
169
+		$errorLevel = error_reporting(0);
170
+		echo '  <div class="tag-line">';
171
+		echo 'Documentation generated on '.date('r');
172
+		echo ' by <a href="https://github.com/squizlabs/PHP_CodeSniffer">PHP_CodeSniffer '.Config::VERSION.'</a>';
173
+		echo '</div>'.PHP_EOL;
174
+		error_reporting($errorLevel);
175
+
176
+		echo ' </body>'.PHP_EOL;
177
+		echo '</html>'.PHP_EOL;
178
+
179
+	}//end printFooter()
180
+
181
+
182
+	/**
183
+	 * Process the documentation for a single sniff.
184
+	 *
185
+	 * @param \DOMNode $doc The DOMNode object for the sniff.
186
+	 *                      It represents the "documentation" tag in the XML
187
+	 *                      standard file.
188
+	 *
189
+	 * @return void
190
+	 */
191
+	public function processSniff(\DOMNode $doc)
192
+	{
193
+		$title = $this->getTitle($doc);
194
+		echo '  <a name="'.str_replace(' ', '-', $title).'" />'.PHP_EOL;
195
+		echo "  <h2>$title</h2>".PHP_EOL;
196
+
197
+		foreach ($doc->childNodes as $node) {
198
+			if ($node->nodeName === 'standard') {
199
+				$this->printTextBlock($node);
200
+			} else if ($node->nodeName === 'code_comparison') {
201
+				$this->printCodeComparisonBlock($node);
202
+			}
203
+		}
204
+
205
+	}//end processSniff()
206
+
207
+
208
+	/**
209
+	 * Print a text block found in a standard.
210
+	 *
211
+	 * @param \DOMNode $node The DOMNode object for the text block.
212
+	 *
213
+	 * @return void
214
+	 */
215
+	protected function printTextBlock(\DOMNode $node)
216
+	{
217
+		$content = trim($node->nodeValue);
218
+		$content = htmlspecialchars($content);
219
+
220
+		// Allow em tags only.
221
+		$content = str_replace('&lt;em&gt;', '<em>', $content);
222
+		$content = str_replace('&lt;/em&gt;', '</em>', $content);
223
+
224
+		echo "  <p class=\"text\">$content</p>".PHP_EOL;
225
+
226
+	}//end printTextBlock()
227
+
228
+
229
+	/**
230
+	 * Print a code comparison block found in a standard.
231
+	 *
232
+	 * @param \DOMNode $node The DOMNode object for the code comparison block.
233
+	 *
234
+	 * @return void
235
+	 */
236
+	protected function printCodeComparisonBlock(\DOMNode $node)
237
+	{
238
+		$codeBlocks = $node->getElementsByTagName('code');
239
+
240
+		$firstTitle = $codeBlocks->item(0)->getAttribute('title');
241
+		$first      = trim($codeBlocks->item(0)->nodeValue);
242
+		$first      = str_replace('<?php', '&lt;?php', $first);
243
+		$first      = str_replace("\n", '</br>', $first);
244
+		$first      = str_replace(' ', '&nbsp;', $first);
245
+		$first      = str_replace('<em>', '<span class="code-comparison-highlight">', $first);
246
+		$first      = str_replace('</em>', '</span>', $first);
247
+
248
+		$secondTitle = $codeBlocks->item(1)->getAttribute('title');
249
+		$second      = trim($codeBlocks->item(1)->nodeValue);
250
+		$second      = str_replace('<?php', '&lt;?php', $second);
251
+		$second      = str_replace("\n", '</br>', $second);
252
+		$second      = str_replace(' ', '&nbsp;', $second);
253
+		$second      = str_replace('<em>', '<span class="code-comparison-highlight">', $second);
254
+		$second      = str_replace('</em>', '</span>', $second);
255
+
256
+		echo '  <table class="code-comparison">'.PHP_EOL;
257
+		echo '   <tr>'.PHP_EOL;
258
+		echo "    <td class=\"code-comparison-title\">$firstTitle</td>".PHP_EOL;
259
+		echo "    <td class=\"code-comparison-title\">$secondTitle</td>".PHP_EOL;
260
+		echo '   </tr>'.PHP_EOL;
261
+		echo '   <tr>'.PHP_EOL;
262
+		echo "    <td class=\"code-comparison-code\">$first</td>".PHP_EOL;
263
+		echo "    <td class=\"code-comparison-code\">$second</td>".PHP_EOL;
264
+		echo '   </tr>'.PHP_EOL;
265
+		echo '  </table>'.PHP_EOL;
266
+
267
+	}//end printCodeComparisonBlock()
268 268
 
269 269
 
270 270
 }//end class
Please login to merge, or discard this patch.
vendor/squizlabs/php_codesniffer/tests/Standards/AllSniffs.php 2 patches
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -46,7 +46,7 @@
 block discarded – undo
46 46
 
47 47
         $suite = new TestSuite('PHP CodeSniffer Standards');
48 48
 
49
-        $isInstalled = !is_file(__DIR__.'/../../autoload.php');
49
+        $isInstalled = ! is_file(__DIR__.'/../../autoload.php');
50 50
 
51 51
         // Optionally allow for ignoring the tests for one or more standards.
52 52
         $ignoreTestsForStandards = getenv('PHPCS_IGNORE_TESTS');
Please login to merge, or discard this patch.
Indentation   +100 added lines, -100 removed lines patch added patch discarded remove patch
@@ -18,106 +18,106 @@
 block discarded – undo
18 18
 {
19 19
 
20 20
 
21
-    /**
22
-     * Prepare the test runner.
23
-     *
24
-     * @return void
25
-     */
26
-    public static function main()
27
-    {
28
-        TestRunner::run(self::suite());
29
-
30
-    }//end main()
31
-
32
-
33
-    /**
34
-     * Add all sniff unit tests into a test suite.
35
-     *
36
-     * Sniff unit tests are found by recursing through the 'Tests' directory
37
-     * of each installed coding standard.
38
-     *
39
-     * @return \PHPUnit\Framework\TestSuite
40
-     */
41
-    public static function suite()
42
-    {
43
-        $GLOBALS['PHP_CODESNIFFER_SNIFF_CODES']      = [];
44
-        $GLOBALS['PHP_CODESNIFFER_FIXABLE_CODES']    = [];
45
-        $GLOBALS['PHP_CODESNIFFER_SNIFF_CASE_FILES'] = [];
46
-
47
-        $suite = new TestSuite('PHP CodeSniffer Standards');
48
-
49
-        $isInstalled = !is_file(__DIR__.'/../../autoload.php');
50
-
51
-        // Optionally allow for ignoring the tests for one or more standards.
52
-        $ignoreTestsForStandards = getenv('PHPCS_IGNORE_TESTS');
53
-        if ($ignoreTestsForStandards === false) {
54
-            $ignoreTestsForStandards = [];
55
-        } else {
56
-            $ignoreTestsForStandards = explode(',', $ignoreTestsForStandards);
57
-        }
58
-
59
-        $installedStandards = self::getInstalledStandardDetails();
60
-
61
-        foreach ($installedStandards as $standard => $details) {
62
-            Autoload::addSearchPath($details['path'], $details['namespace']);
63
-
64
-            // If the test is running PEAR installed, the built-in standards
65
-            // are split into different directories; one for the sniffs and
66
-            // a different file system location for tests.
67
-            if ($isInstalled === true && is_dir(dirname($details['path']).DIRECTORY_SEPARATOR.'Generic') === true) {
68
-                $testPath = realpath(__DIR__.'/../../src/Standards/'.$standard);
69
-            } else {
70
-                $testPath = $details['path'];
71
-            }
72
-
73
-            if (in_array($standard, $ignoreTestsForStandards, true) === true) {
74
-                continue;
75
-            }
76
-
77
-            $testsDir = $testPath.DIRECTORY_SEPARATOR.'Tests'.DIRECTORY_SEPARATOR;
78
-            if (is_dir($testsDir) === false) {
79
-                // No tests for this standard.
80
-                continue;
81
-            }
82
-
83
-            $di = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($testsDir));
84
-
85
-            foreach ($di as $file) {
86
-                // Skip hidden files.
87
-                if (substr($file->getFilename(), 0, 1) === '.') {
88
-                    continue;
89
-                }
90
-
91
-                // Tests must have the extension 'php'.
92
-                $parts = explode('.', $file);
93
-                $ext   = array_pop($parts);
94
-                if ($ext !== 'php') {
95
-                    continue;
96
-                }
97
-
98
-                $className = Autoload::loadFile($file->getPathname());
99
-                $GLOBALS['PHP_CODESNIFFER_STANDARD_DIRS'][$className] = $details['path'];
100
-                $GLOBALS['PHP_CODESNIFFER_TEST_DIRS'][$className]     = $testsDir;
101
-                $suite->addTestSuite($className);
102
-            }
103
-        }//end foreach
104
-
105
-        return $suite;
106
-
107
-    }//end suite()
108
-
109
-
110
-    /**
111
-     * Get the details of all coding standards installed.
112
-     *
113
-     * @return array
114
-     * @see    Standards::getInstalledStandardDetails()
115
-     */
116
-    protected static function getInstalledStandardDetails()
117
-    {
118
-        return Standards::getInstalledStandardDetails(true);
119
-
120
-    }//end getInstalledStandardDetails()
21
+	/**
22
+	 * Prepare the test runner.
23
+	 *
24
+	 * @return void
25
+	 */
26
+	public static function main()
27
+	{
28
+		TestRunner::run(self::suite());
29
+
30
+	}//end main()
31
+
32
+
33
+	/**
34
+	 * Add all sniff unit tests into a test suite.
35
+	 *
36
+	 * Sniff unit tests are found by recursing through the 'Tests' directory
37
+	 * of each installed coding standard.
38
+	 *
39
+	 * @return \PHPUnit\Framework\TestSuite
40
+	 */
41
+	public static function suite()
42
+	{
43
+		$GLOBALS['PHP_CODESNIFFER_SNIFF_CODES']      = [];
44
+		$GLOBALS['PHP_CODESNIFFER_FIXABLE_CODES']    = [];
45
+		$GLOBALS['PHP_CODESNIFFER_SNIFF_CASE_FILES'] = [];
46
+
47
+		$suite = new TestSuite('PHP CodeSniffer Standards');
48
+
49
+		$isInstalled = !is_file(__DIR__.'/../../autoload.php');
50
+
51
+		// Optionally allow for ignoring the tests for one or more standards.
52
+		$ignoreTestsForStandards = getenv('PHPCS_IGNORE_TESTS');
53
+		if ($ignoreTestsForStandards === false) {
54
+			$ignoreTestsForStandards = [];
55
+		} else {
56
+			$ignoreTestsForStandards = explode(',', $ignoreTestsForStandards);
57
+		}
58
+
59
+		$installedStandards = self::getInstalledStandardDetails();
60
+
61
+		foreach ($installedStandards as $standard => $details) {
62
+			Autoload::addSearchPath($details['path'], $details['namespace']);
63
+
64
+			// If the test is running PEAR installed, the built-in standards
65
+			// are split into different directories; one for the sniffs and
66
+			// a different file system location for tests.
67
+			if ($isInstalled === true && is_dir(dirname($details['path']).DIRECTORY_SEPARATOR.'Generic') === true) {
68
+				$testPath = realpath(__DIR__.'/../../src/Standards/'.$standard);
69
+			} else {
70
+				$testPath = $details['path'];
71
+			}
72
+
73
+			if (in_array($standard, $ignoreTestsForStandards, true) === true) {
74
+				continue;
75
+			}
76
+
77
+			$testsDir = $testPath.DIRECTORY_SEPARATOR.'Tests'.DIRECTORY_SEPARATOR;
78
+			if (is_dir($testsDir) === false) {
79
+				// No tests for this standard.
80
+				continue;
81
+			}
82
+
83
+			$di = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($testsDir));
84
+
85
+			foreach ($di as $file) {
86
+				// Skip hidden files.
87
+				if (substr($file->getFilename(), 0, 1) === '.') {
88
+					continue;
89
+				}
90
+
91
+				// Tests must have the extension 'php'.
92
+				$parts = explode('.', $file);
93
+				$ext   = array_pop($parts);
94
+				if ($ext !== 'php') {
95
+					continue;
96
+				}
97
+
98
+				$className = Autoload::loadFile($file->getPathname());
99
+				$GLOBALS['PHP_CODESNIFFER_STANDARD_DIRS'][$className] = $details['path'];
100
+				$GLOBALS['PHP_CODESNIFFER_TEST_DIRS'][$className]     = $testsDir;
101
+				$suite->addTestSuite($className);
102
+			}
103
+		}//end foreach
104
+
105
+		return $suite;
106
+
107
+	}//end suite()
108
+
109
+
110
+	/**
111
+	 * Get the details of all coding standards installed.
112
+	 *
113
+	 * @return array
114
+	 * @see    Standards::getInstalledStandardDetails()
115
+	 */
116
+	protected static function getInstalledStandardDetails()
117
+	{
118
+		return Standards::getInstalledStandardDetails(true);
119
+
120
+	}//end getInstalledStandardDetails()
121 121
 
122 122
 
123 123
 }//end class
Please login to merge, or discard this patch.
vendor/squizlabs/php_codesniffer/tests/TestSuite7.php 2 patches
Indentation   +14 added lines, -14 removed lines patch added patch discarded remove patch
@@ -16,20 +16,20 @@
 block discarded – undo
16 16
 {
17 17
 
18 18
 
19
-    /**
20
-     * Runs the tests and collects their result in a TestResult.
21
-     *
22
-     * @param \PHPUnit\Framework\TestResult $result A test result.
23
-     *
24
-     * @return \PHPUnit\Framework\TestResult
25
-     */
26
-    public function run(TestResult $result=null): TestResult
27
-    {
28
-        $result = parent::run($result);
29
-        printPHPCodeSnifferTestOutput();
30
-        return $result;
31
-
32
-    }//end run()
19
+	/**
20
+	 * Runs the tests and collects their result in a TestResult.
21
+	 *
22
+	 * @param \PHPUnit\Framework\TestResult $result A test result.
23
+	 *
24
+	 * @return \PHPUnit\Framework\TestResult
25
+	 */
26
+	public function run(TestResult $result=null): TestResult
27
+	{
28
+		$result = parent::run($result);
29
+		printPHPCodeSnifferTestOutput();
30
+		return $result;
31
+
32
+	}//end run()
33 33
 
34 34
 
35 35
 }//end class
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -23,7 +23,7 @@
 block discarded – undo
23 23
      *
24 24
      * @return \PHPUnit\Framework\TestResult
25 25
      */
26
-    public function run(TestResult $result=null): TestResult
26
+    public function run(TestResult $result = null): TestResult
27 27
     {
28 28
         $result = parent::run($result);
29 29
         printPHPCodeSnifferTestOutput();
Please login to merge, or discard this patch.
vendor/squizlabs/php_codesniffer/tests/Core/IsCamelCapsTest.php 1 patch
Indentation   +114 added lines, -114 removed lines patch added patch discarded remove patch
@@ -16,120 +16,120 @@
 block discarded – undo
16 16
 {
17 17
 
18 18
 
19
-    /**
20
-     * Test valid public function/method names.
21
-     *
22
-     * @return void
23
-     */
24
-    public function testValidNotClassFormatPublic()
25
-    {
26
-        $this->assertTrue(Common::isCamelCaps('thisIsCamelCaps', false, true, true));
27
-        $this->assertTrue(Common::isCamelCaps('thisISCamelCaps', false, true, false));
28
-
29
-    }//end testValidNotClassFormatPublic()
30
-
31
-
32
-    /**
33
-     * Test invalid public function/method names.
34
-     *
35
-     * @return void
36
-     */
37
-    public function testInvalidNotClassFormatPublic()
38
-    {
39
-        $this->assertFalse(Common::isCamelCaps('_thisIsCamelCaps', false, true, true));
40
-        $this->assertFalse(Common::isCamelCaps('thisISCamelCaps', false, true, true));
41
-        $this->assertFalse(Common::isCamelCaps('ThisIsCamelCaps', false, true, true));
42
-
43
-        $this->assertFalse(Common::isCamelCaps('3thisIsCamelCaps', false, true, true));
44
-        $this->assertFalse(Common::isCamelCaps('*thisIsCamelCaps', false, true, true));
45
-        $this->assertFalse(Common::isCamelCaps('-thisIsCamelCaps', false, true, true));
46
-
47
-        $this->assertFalse(Common::isCamelCaps('this*IsCamelCaps', false, true, true));
48
-        $this->assertFalse(Common::isCamelCaps('this-IsCamelCaps', false, true, true));
49
-        $this->assertFalse(Common::isCamelCaps('this_IsCamelCaps', false, true, true));
50
-        $this->assertFalse(Common::isCamelCaps('this_is_camel_caps', false, true, true));
51
-
52
-    }//end testInvalidNotClassFormatPublic()
53
-
54
-
55
-    /**
56
-     * Test valid private method names.
57
-     *
58
-     * @return void
59
-     */
60
-    public function testValidNotClassFormatPrivate()
61
-    {
62
-        $this->assertTrue(Common::isCamelCaps('_thisIsCamelCaps', false, false, true));
63
-        $this->assertTrue(Common::isCamelCaps('_thisISCamelCaps', false, false, false));
64
-        $this->assertTrue(Common::isCamelCaps('_i18N', false, false, true));
65
-        $this->assertTrue(Common::isCamelCaps('_i18n', false, false, true));
66
-
67
-    }//end testValidNotClassFormatPrivate()
68
-
69
-
70
-    /**
71
-     * Test invalid private method names.
72
-     *
73
-     * @return void
74
-     */
75
-    public function testInvalidNotClassFormatPrivate()
76
-    {
77
-        $this->assertFalse(Common::isCamelCaps('thisIsCamelCaps', false, false, true));
78
-        $this->assertFalse(Common::isCamelCaps('_thisISCamelCaps', false, false, true));
79
-        $this->assertFalse(Common::isCamelCaps('_ThisIsCamelCaps', false, false, true));
80
-        $this->assertFalse(Common::isCamelCaps('__thisIsCamelCaps', false, false, true));
81
-        $this->assertFalse(Common::isCamelCaps('__thisISCamelCaps', false, false, false));
82
-
83
-        $this->assertFalse(Common::isCamelCaps('3thisIsCamelCaps', false, false, true));
84
-        $this->assertFalse(Common::isCamelCaps('*thisIsCamelCaps', false, false, true));
85
-        $this->assertFalse(Common::isCamelCaps('-thisIsCamelCaps', false, false, true));
86
-        $this->assertFalse(Common::isCamelCaps('_this_is_camel_caps', false, false, true));
87
-
88
-    }//end testInvalidNotClassFormatPrivate()
89
-
90
-
91
-    /**
92
-     * Test valid class names.
93
-     *
94
-     * @return void
95
-     */
96
-    public function testValidClassFormatPublic()
97
-    {
98
-        $this->assertTrue(Common::isCamelCaps('ThisIsCamelCaps', true, true, true));
99
-        $this->assertTrue(Common::isCamelCaps('ThisISCamelCaps', true, true, false));
100
-        $this->assertTrue(Common::isCamelCaps('This3IsCamelCaps', true, true, false));
101
-
102
-    }//end testValidClassFormatPublic()
103
-
104
-
105
-    /**
106
-     * Test invalid class names.
107
-     *
108
-     * @return void
109
-     */
110
-    public function testInvalidClassFormat()
111
-    {
112
-        $this->assertFalse(Common::isCamelCaps('thisIsCamelCaps', true));
113
-        $this->assertFalse(Common::isCamelCaps('This-IsCamelCaps', true));
114
-        $this->assertFalse(Common::isCamelCaps('This_Is_Camel_Caps', true));
115
-
116
-    }//end testInvalidClassFormat()
117
-
118
-
119
-    /**
120
-     * Test invalid class names with the private flag set.
121
-     *
122
-     * Note that the private flag is ignored if the class format
123
-     * flag is set, so these names are all invalid.
124
-     *
125
-     * @return void
126
-     */
127
-    public function testInvalidClassFormatPrivate()
128
-    {
129
-        $this->assertFalse(Common::isCamelCaps('_ThisIsCamelCaps', true, true));
130
-        $this->assertFalse(Common::isCamelCaps('_ThisIsCamelCaps', true, false));
131
-
132
-    }//end testInvalidClassFormatPrivate()
19
+	/**
20
+	 * Test valid public function/method names.
21
+	 *
22
+	 * @return void
23
+	 */
24
+	public function testValidNotClassFormatPublic()
25
+	{
26
+		$this->assertTrue(Common::isCamelCaps('thisIsCamelCaps', false, true, true));
27
+		$this->assertTrue(Common::isCamelCaps('thisISCamelCaps', false, true, false));
28
+
29
+	}//end testValidNotClassFormatPublic()
30
+
31
+
32
+	/**
33
+	 * Test invalid public function/method names.
34
+	 *
35
+	 * @return void
36
+	 */
37
+	public function testInvalidNotClassFormatPublic()
38
+	{
39
+		$this->assertFalse(Common::isCamelCaps('_thisIsCamelCaps', false, true, true));
40
+		$this->assertFalse(Common::isCamelCaps('thisISCamelCaps', false, true, true));
41
+		$this->assertFalse(Common::isCamelCaps('ThisIsCamelCaps', false, true, true));
42
+
43
+		$this->assertFalse(Common::isCamelCaps('3thisIsCamelCaps', false, true, true));
44
+		$this->assertFalse(Common::isCamelCaps('*thisIsCamelCaps', false, true, true));
45
+		$this->assertFalse(Common::isCamelCaps('-thisIsCamelCaps', false, true, true));
46
+
47
+		$this->assertFalse(Common::isCamelCaps('this*IsCamelCaps', false, true, true));
48
+		$this->assertFalse(Common::isCamelCaps('this-IsCamelCaps', false, true, true));
49
+		$this->assertFalse(Common::isCamelCaps('this_IsCamelCaps', false, true, true));
50
+		$this->assertFalse(Common::isCamelCaps('this_is_camel_caps', false, true, true));
51
+
52
+	}//end testInvalidNotClassFormatPublic()
53
+
54
+
55
+	/**
56
+	 * Test valid private method names.
57
+	 *
58
+	 * @return void
59
+	 */
60
+	public function testValidNotClassFormatPrivate()
61
+	{
62
+		$this->assertTrue(Common::isCamelCaps('_thisIsCamelCaps', false, false, true));
63
+		$this->assertTrue(Common::isCamelCaps('_thisISCamelCaps', false, false, false));
64
+		$this->assertTrue(Common::isCamelCaps('_i18N', false, false, true));
65
+		$this->assertTrue(Common::isCamelCaps('_i18n', false, false, true));
66
+
67
+	}//end testValidNotClassFormatPrivate()
68
+
69
+
70
+	/**
71
+	 * Test invalid private method names.
72
+	 *
73
+	 * @return void
74
+	 */
75
+	public function testInvalidNotClassFormatPrivate()
76
+	{
77
+		$this->assertFalse(Common::isCamelCaps('thisIsCamelCaps', false, false, true));
78
+		$this->assertFalse(Common::isCamelCaps('_thisISCamelCaps', false, false, true));
79
+		$this->assertFalse(Common::isCamelCaps('_ThisIsCamelCaps', false, false, true));
80
+		$this->assertFalse(Common::isCamelCaps('__thisIsCamelCaps', false, false, true));
81
+		$this->assertFalse(Common::isCamelCaps('__thisISCamelCaps', false, false, false));
82
+
83
+		$this->assertFalse(Common::isCamelCaps('3thisIsCamelCaps', false, false, true));
84
+		$this->assertFalse(Common::isCamelCaps('*thisIsCamelCaps', false, false, true));
85
+		$this->assertFalse(Common::isCamelCaps('-thisIsCamelCaps', false, false, true));
86
+		$this->assertFalse(Common::isCamelCaps('_this_is_camel_caps', false, false, true));
87
+
88
+	}//end testInvalidNotClassFormatPrivate()
89
+
90
+
91
+	/**
92
+	 * Test valid class names.
93
+	 *
94
+	 * @return void
95
+	 */
96
+	public function testValidClassFormatPublic()
97
+	{
98
+		$this->assertTrue(Common::isCamelCaps('ThisIsCamelCaps', true, true, true));
99
+		$this->assertTrue(Common::isCamelCaps('ThisISCamelCaps', true, true, false));
100
+		$this->assertTrue(Common::isCamelCaps('This3IsCamelCaps', true, true, false));
101
+
102
+	}//end testValidClassFormatPublic()
103
+
104
+
105
+	/**
106
+	 * Test invalid class names.
107
+	 *
108
+	 * @return void
109
+	 */
110
+	public function testInvalidClassFormat()
111
+	{
112
+		$this->assertFalse(Common::isCamelCaps('thisIsCamelCaps', true));
113
+		$this->assertFalse(Common::isCamelCaps('This-IsCamelCaps', true));
114
+		$this->assertFalse(Common::isCamelCaps('This_Is_Camel_Caps', true));
115
+
116
+	}//end testInvalidClassFormat()
117
+
118
+
119
+	/**
120
+	 * Test invalid class names with the private flag set.
121
+	 *
122
+	 * Note that the private flag is ignored if the class format
123
+	 * flag is set, so these names are all invalid.
124
+	 *
125
+	 * @return void
126
+	 */
127
+	public function testInvalidClassFormatPrivate()
128
+	{
129
+		$this->assertFalse(Common::isCamelCaps('_ThisIsCamelCaps', true, true));
130
+		$this->assertFalse(Common::isCamelCaps('_ThisIsCamelCaps', true, false));
131
+
132
+	}//end testInvalidClassFormatPrivate()
133 133
 
134 134
 
135 135
 }//end class
Please login to merge, or discard this patch.
vendor/squizlabs/php_codesniffer/tests/TestSuite.php 2 patches
Indentation   +14 added lines, -14 removed lines patch added patch discarded remove patch
@@ -16,20 +16,20 @@
 block discarded – undo
16 16
 {
17 17
 
18 18
 
19
-    /**
20
-     * Runs the tests and collects their result in a TestResult.
21
-     *
22
-     * @param \PHPUnit\Framework\TestResult $result A test result.
23
-     *
24
-     * @return \PHPUnit\Framework\TestResult
25
-     */
26
-    public function run(TestResult $result=null)
27
-    {
28
-        $result = parent::run($result);
29
-        printPHPCodeSnifferTestOutput();
30
-        return $result;
31
-
32
-    }//end run()
19
+	/**
20
+	 * Runs the tests and collects their result in a TestResult.
21
+	 *
22
+	 * @param \PHPUnit\Framework\TestResult $result A test result.
23
+	 *
24
+	 * @return \PHPUnit\Framework\TestResult
25
+	 */
26
+	public function run(TestResult $result=null)
27
+	{
28
+		$result = parent::run($result);
29
+		printPHPCodeSnifferTestOutput();
30
+		return $result;
31
+
32
+	}//end run()
33 33
 
34 34
 
35 35
 }//end class
Please login to merge, or discard this patch.
Spacing   +1 added lines, -1 removed lines patch added patch discarded remove patch
@@ -23,7 +23,7 @@
 block discarded – undo
23 23
      *
24 24
      * @return \PHPUnit\Framework\TestResult
25 25
      */
26
-    public function run(TestResult $result=null)
26
+    public function run(TestResult $result = null)
27 27
     {
28 28
         $result = parent::run($result);
29 29
         printPHPCodeSnifferTestOutput();
Please login to merge, or discard this patch.