Completed
Branch RELEASE (416965)
by
unknown
11:06 queued 12s
created
vendor/squizlabs/php_codesniffer/src/Reports/Info.php 2 patches
Spacing   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -30,7 +30,7 @@  discard block
 block discarded – undo
30 30
      *
31 31
      * @return bool
32 32
      */
33
-    public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80)
33
+    public function generateFileReport($report, File $phpcsFile, $showSources = false, $width = 80)
34 34
     {
35 35
         $metrics = $phpcsFile->getMetrics();
36 36
         foreach ($metrics as $metric => $data) {
@@ -66,10 +66,10 @@  discard block
 block discarded – undo
66 66
         $totalErrors,
67 67
         $totalWarnings,
68 68
         $totalFixable,
69
-        $showSources=false,
70
-        $width=80,
71
-        $interactive=false,
72
-        $toScreen=true
69
+        $showSources = false,
70
+        $width = 80,
71
+        $interactive = false,
72
+        $toScreen = true
73 73
     ) {
74 74
         $lines = explode(PHP_EOL, $cachedData);
75 75
         array_pop($lines);
Please login to merge, or discard this patch.
Indentation   +151 added lines, -151 removed lines patch added patch discarded remove patch
@@ -16,157 +16,157 @@
 block discarded – undo
16 16
 {
17 17
 
18 18
 
19
-    /**
20
-     * Generate a partial report for a single processed file.
21
-     *
22
-     * Function should return TRUE if it printed or stored data about the file
23
-     * and FALSE if it ignored the file. Returning TRUE indicates that the file and
24
-     * its data should be counted in the grand totals.
25
-     *
26
-     * @param array                 $report      Prepared report data.
27
-     * @param \PHP_CodeSniffer\File $phpcsFile   The file being reported on.
28
-     * @param bool                  $showSources Show sources?
29
-     * @param int                   $width       Maximum allowed line width.
30
-     *
31
-     * @return bool
32
-     */
33
-    public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80)
34
-    {
35
-        $metrics = $phpcsFile->getMetrics();
36
-        foreach ($metrics as $metric => $data) {
37
-            foreach ($data['values'] as $value => $count) {
38
-                echo "$metric>>$value>>$count".PHP_EOL;
39
-            }
40
-        }
41
-
42
-        return true;
43
-
44
-    }//end generateFileReport()
45
-
46
-
47
-    /**
48
-     * Prints the source of all errors and warnings.
49
-     *
50
-     * @param string $cachedData    Any partial report data that was returned from
51
-     *                              generateFileReport during the run.
52
-     * @param int    $totalFiles    Total number of files processed during the run.
53
-     * @param int    $totalErrors   Total number of errors found during the run.
54
-     * @param int    $totalWarnings Total number of warnings found during the run.
55
-     * @param int    $totalFixable  Total number of problems that can be fixed.
56
-     * @param bool   $showSources   Show sources?
57
-     * @param int    $width         Maximum allowed line width.
58
-     * @param bool   $interactive   Are we running in interactive mode?
59
-     * @param bool   $toScreen      Is the report being printed to screen?
60
-     *
61
-     * @return void
62
-     */
63
-    public function generate(
64
-        $cachedData,
65
-        $totalFiles,
66
-        $totalErrors,
67
-        $totalWarnings,
68
-        $totalFixable,
69
-        $showSources=false,
70
-        $width=80,
71
-        $interactive=false,
72
-        $toScreen=true
73
-    ) {
74
-        $lines = explode(PHP_EOL, $cachedData);
75
-        array_pop($lines);
76
-
77
-        if (empty($lines) === true) {
78
-            return;
79
-        }
80
-
81
-        $metrics = [];
82
-        foreach ($lines as $line) {
83
-            $parts  = explode('>>', $line);
84
-            $metric = $parts[0];
85
-            $value  = $parts[1];
86
-            $count  = $parts[2];
87
-            if (isset($metrics[$metric]) === false) {
88
-                $metrics[$metric] = [];
89
-            }
90
-
91
-            if (isset($metrics[$metric][$value]) === false) {
92
-                $metrics[$metric][$value] = $count;
93
-            } else {
94
-                $metrics[$metric][$value] += $count;
95
-            }
96
-        }
97
-
98
-        ksort($metrics);
99
-
100
-        echo PHP_EOL."\033[1m".'PHP CODE SNIFFER INFORMATION REPORT'."\033[0m".PHP_EOL;
101
-        echo str_repeat('-', 70).PHP_EOL;
102
-
103
-        foreach ($metrics as $metric => $values) {
104
-            if (count($values) === 1) {
105
-                $count = reset($values);
106
-                $value = key($values);
107
-
108
-                echo "$metric: \033[4m$value\033[0m [$count/$count, 100%]".PHP_EOL;
109
-            } else {
110
-                $totalCount = 0;
111
-                $valueWidth = 0;
112
-                foreach ($values as $value => $count) {
113
-                    $totalCount += $count;
114
-                    $valueWidth  = max($valueWidth, strlen($value));
115
-                }
116
-
117
-                // Length of the total string, plus however many
118
-                // thousands separators there are.
119
-                $countWidth = strlen($totalCount);
120
-                $thousandSeparatorCount = floor($countWidth / 3);
121
-                $countWidth            += $thousandSeparatorCount;
122
-
123
-                // Account for 'total' line.
124
-                $valueWidth = max(5, $valueWidth);
125
-
126
-                echo "$metric:".PHP_EOL;
127
-
128
-                ksort($values, SORT_NATURAL);
129
-                arsort($values);
130
-
131
-                $percentPrefixWidth = 0;
132
-                $percentWidth       = 6;
133
-                foreach ($values as $value => $count) {
134
-                    $percent       = round(($count / $totalCount * 100), 2);
135
-                    $percentPrefix = '';
136
-                    if ($percent === 0.00) {
137
-                        $percent            = 0.01;
138
-                        $percentPrefix      = '<';
139
-                        $percentPrefixWidth = 2;
140
-                        $percentWidth       = 4;
141
-                    }
142
-
143
-                    printf(
144
-                        "\t%-{$valueWidth}s => %{$countWidth}s (%{$percentPrefixWidth}s%{$percentWidth}.2f%%)".PHP_EOL,
145
-                        $value,
146
-                        number_format($count),
147
-                        $percentPrefix,
148
-                        $percent
149
-                    );
150
-                }
151
-
152
-                echo "\t".str_repeat('-', ($valueWidth + $countWidth + 15)).PHP_EOL;
153
-                printf(
154
-                    "\t%-{$valueWidth}s => %{$countWidth}s (100.00%%)".PHP_EOL,
155
-                    'total',
156
-                    number_format($totalCount)
157
-                );
158
-            }//end if
159
-
160
-            echo PHP_EOL;
161
-        }//end foreach
162
-
163
-        echo str_repeat('-', 70).PHP_EOL;
164
-
165
-        if ($toScreen === true && $interactive === false) {
166
-            Timing::printRunTime();
167
-        }
168
-
169
-    }//end generate()
19
+	/**
20
+	 * Generate a partial report for a single processed file.
21
+	 *
22
+	 * Function should return TRUE if it printed or stored data about the file
23
+	 * and FALSE if it ignored the file. Returning TRUE indicates that the file and
24
+	 * its data should be counted in the grand totals.
25
+	 *
26
+	 * @param array                 $report      Prepared report data.
27
+	 * @param \PHP_CodeSniffer\File $phpcsFile   The file being reported on.
28
+	 * @param bool                  $showSources Show sources?
29
+	 * @param int                   $width       Maximum allowed line width.
30
+	 *
31
+	 * @return bool
32
+	 */
33
+	public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80)
34
+	{
35
+		$metrics = $phpcsFile->getMetrics();
36
+		foreach ($metrics as $metric => $data) {
37
+			foreach ($data['values'] as $value => $count) {
38
+				echo "$metric>>$value>>$count".PHP_EOL;
39
+			}
40
+		}
41
+
42
+		return true;
43
+
44
+	}//end generateFileReport()
45
+
46
+
47
+	/**
48
+	 * Prints the source of all errors and warnings.
49
+	 *
50
+	 * @param string $cachedData    Any partial report data that was returned from
51
+	 *                              generateFileReport during the run.
52
+	 * @param int    $totalFiles    Total number of files processed during the run.
53
+	 * @param int    $totalErrors   Total number of errors found during the run.
54
+	 * @param int    $totalWarnings Total number of warnings found during the run.
55
+	 * @param int    $totalFixable  Total number of problems that can be fixed.
56
+	 * @param bool   $showSources   Show sources?
57
+	 * @param int    $width         Maximum allowed line width.
58
+	 * @param bool   $interactive   Are we running in interactive mode?
59
+	 * @param bool   $toScreen      Is the report being printed to screen?
60
+	 *
61
+	 * @return void
62
+	 */
63
+	public function generate(
64
+		$cachedData,
65
+		$totalFiles,
66
+		$totalErrors,
67
+		$totalWarnings,
68
+		$totalFixable,
69
+		$showSources=false,
70
+		$width=80,
71
+		$interactive=false,
72
+		$toScreen=true
73
+	) {
74
+		$lines = explode(PHP_EOL, $cachedData);
75
+		array_pop($lines);
76
+
77
+		if (empty($lines) === true) {
78
+			return;
79
+		}
80
+
81
+		$metrics = [];
82
+		foreach ($lines as $line) {
83
+			$parts  = explode('>>', $line);
84
+			$metric = $parts[0];
85
+			$value  = $parts[1];
86
+			$count  = $parts[2];
87
+			if (isset($metrics[$metric]) === false) {
88
+				$metrics[$metric] = [];
89
+			}
90
+
91
+			if (isset($metrics[$metric][$value]) === false) {
92
+				$metrics[$metric][$value] = $count;
93
+			} else {
94
+				$metrics[$metric][$value] += $count;
95
+			}
96
+		}
97
+
98
+		ksort($metrics);
99
+
100
+		echo PHP_EOL."\033[1m".'PHP CODE SNIFFER INFORMATION REPORT'."\033[0m".PHP_EOL;
101
+		echo str_repeat('-', 70).PHP_EOL;
102
+
103
+		foreach ($metrics as $metric => $values) {
104
+			if (count($values) === 1) {
105
+				$count = reset($values);
106
+				$value = key($values);
107
+
108
+				echo "$metric: \033[4m$value\033[0m [$count/$count, 100%]".PHP_EOL;
109
+			} else {
110
+				$totalCount = 0;
111
+				$valueWidth = 0;
112
+				foreach ($values as $value => $count) {
113
+					$totalCount += $count;
114
+					$valueWidth  = max($valueWidth, strlen($value));
115
+				}
116
+
117
+				// Length of the total string, plus however many
118
+				// thousands separators there are.
119
+				$countWidth = strlen($totalCount);
120
+				$thousandSeparatorCount = floor($countWidth / 3);
121
+				$countWidth            += $thousandSeparatorCount;
122
+
123
+				// Account for 'total' line.
124
+				$valueWidth = max(5, $valueWidth);
125
+
126
+				echo "$metric:".PHP_EOL;
127
+
128
+				ksort($values, SORT_NATURAL);
129
+				arsort($values);
130
+
131
+				$percentPrefixWidth = 0;
132
+				$percentWidth       = 6;
133
+				foreach ($values as $value => $count) {
134
+					$percent       = round(($count / $totalCount * 100), 2);
135
+					$percentPrefix = '';
136
+					if ($percent === 0.00) {
137
+						$percent            = 0.01;
138
+						$percentPrefix      = '<';
139
+						$percentPrefixWidth = 2;
140
+						$percentWidth       = 4;
141
+					}
142
+
143
+					printf(
144
+						"\t%-{$valueWidth}s => %{$countWidth}s (%{$percentPrefixWidth}s%{$percentWidth}.2f%%)".PHP_EOL,
145
+						$value,
146
+						number_format($count),
147
+						$percentPrefix,
148
+						$percent
149
+					);
150
+				}
151
+
152
+				echo "\t".str_repeat('-', ($valueWidth + $countWidth + 15)).PHP_EOL;
153
+				printf(
154
+					"\t%-{$valueWidth}s => %{$countWidth}s (100.00%%)".PHP_EOL,
155
+					'total',
156
+					number_format($totalCount)
157
+				);
158
+			}//end if
159
+
160
+			echo PHP_EOL;
161
+		}//end foreach
162
+
163
+		echo str_repeat('-', 70).PHP_EOL;
164
+
165
+		if ($toScreen === true && $interactive === false) {
166
+			Timing::printRunTime();
167
+		}
168
+
169
+	}//end generate()
170 170
 
171 171
 
172 172
 }//end class
Please login to merge, or discard this patch.
vendor/squizlabs/php_codesniffer/src/Reports/Diff.php 2 patches
Indentation   +110 added lines, -110 removed lines patch added patch discarded remove patch
@@ -16,116 +16,116 @@
 block discarded – undo
16 16
 {
17 17
 
18 18
 
19
-    /**
20
-     * Generate a partial report for a single processed file.
21
-     *
22
-     * Function should return TRUE if it printed or stored data about the file
23
-     * and FALSE if it ignored the file. Returning TRUE indicates that the file and
24
-     * its data should be counted in the grand totals.
25
-     *
26
-     * @param array                 $report      Prepared report data.
27
-     * @param \PHP_CodeSniffer\File $phpcsFile   The file being reported on.
28
-     * @param bool                  $showSources Show sources?
29
-     * @param int                   $width       Maximum allowed line width.
30
-     *
31
-     * @return bool
32
-     */
33
-    public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80)
34
-    {
35
-        $errors = $phpcsFile->getFixableCount();
36
-        if ($errors === 0) {
37
-            return false;
38
-        }
39
-
40
-        $phpcsFile->disableCaching();
41
-        $tokens = $phpcsFile->getTokens();
42
-        if (empty($tokens) === true) {
43
-            if (PHP_CODESNIFFER_VERBOSITY === 1) {
44
-                $startTime = microtime(true);
45
-                echo 'DIFF report is parsing '.basename($report['filename']).' ';
46
-            } else if (PHP_CODESNIFFER_VERBOSITY > 1) {
47
-                echo 'DIFF report is forcing parse of '.$report['filename'].PHP_EOL;
48
-            }
49
-
50
-            $phpcsFile->parse();
51
-
52
-            if (PHP_CODESNIFFER_VERBOSITY === 1) {
53
-                $timeTaken = ((microtime(true) - $startTime) * 1000);
54
-                if ($timeTaken < 1000) {
55
-                    $timeTaken = round($timeTaken);
56
-                    echo "DONE in {$timeTaken}ms";
57
-                } else {
58
-                    $timeTaken = round(($timeTaken / 1000), 2);
59
-                    echo "DONE in $timeTaken secs";
60
-                }
61
-
62
-                echo PHP_EOL;
63
-            }
64
-
65
-            $phpcsFile->fixer->startFile($phpcsFile);
66
-        }//end if
67
-
68
-        if (PHP_CODESNIFFER_VERBOSITY > 1) {
69
-            ob_end_clean();
70
-            echo "\t*** START FILE FIXING ***".PHP_EOL;
71
-        }
72
-
73
-        $fixed = $phpcsFile->fixer->fixFile();
74
-
75
-        if (PHP_CODESNIFFER_VERBOSITY > 1) {
76
-            echo "\t*** END FILE FIXING ***".PHP_EOL;
77
-            ob_start();
78
-        }
79
-
80
-        if ($fixed === false) {
81
-            return false;
82
-        }
83
-
84
-        $diff = $phpcsFile->fixer->generateDiff();
85
-        if ($diff === '') {
86
-            // Nothing to print.
87
-            return false;
88
-        }
89
-
90
-        echo $diff.PHP_EOL;
91
-        return true;
92
-
93
-    }//end generateFileReport()
94
-
95
-
96
-    /**
97
-     * Prints all errors and warnings for each file processed.
98
-     *
99
-     * @param string $cachedData    Any partial report data that was returned from
100
-     *                              generateFileReport during the run.
101
-     * @param int    $totalFiles    Total number of files processed during the run.
102
-     * @param int    $totalErrors   Total number of errors found during the run.
103
-     * @param int    $totalWarnings Total number of warnings found during the run.
104
-     * @param int    $totalFixable  Total number of problems that can be fixed.
105
-     * @param bool   $showSources   Show sources?
106
-     * @param int    $width         Maximum allowed line width.
107
-     * @param bool   $interactive   Are we running in interactive mode?
108
-     * @param bool   $toScreen      Is the report being printed to screen?
109
-     *
110
-     * @return void
111
-     */
112
-    public function generate(
113
-        $cachedData,
114
-        $totalFiles,
115
-        $totalErrors,
116
-        $totalWarnings,
117
-        $totalFixable,
118
-        $showSources=false,
119
-        $width=80,
120
-        $interactive=false,
121
-        $toScreen=true
122
-    ) {
123
-        echo $cachedData;
124
-        if ($toScreen === true && $cachedData !== '') {
125
-            echo PHP_EOL;
126
-        }
127
-
128
-    }//end generate()
19
+	/**
20
+	 * Generate a partial report for a single processed file.
21
+	 *
22
+	 * Function should return TRUE if it printed or stored data about the file
23
+	 * and FALSE if it ignored the file. Returning TRUE indicates that the file and
24
+	 * its data should be counted in the grand totals.
25
+	 *
26
+	 * @param array                 $report      Prepared report data.
27
+	 * @param \PHP_CodeSniffer\File $phpcsFile   The file being reported on.
28
+	 * @param bool                  $showSources Show sources?
29
+	 * @param int                   $width       Maximum allowed line width.
30
+	 *
31
+	 * @return bool
32
+	 */
33
+	public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80)
34
+	{
35
+		$errors = $phpcsFile->getFixableCount();
36
+		if ($errors === 0) {
37
+			return false;
38
+		}
39
+
40
+		$phpcsFile->disableCaching();
41
+		$tokens = $phpcsFile->getTokens();
42
+		if (empty($tokens) === true) {
43
+			if (PHP_CODESNIFFER_VERBOSITY === 1) {
44
+				$startTime = microtime(true);
45
+				echo 'DIFF report is parsing '.basename($report['filename']).' ';
46
+			} else if (PHP_CODESNIFFER_VERBOSITY > 1) {
47
+				echo 'DIFF report is forcing parse of '.$report['filename'].PHP_EOL;
48
+			}
49
+
50
+			$phpcsFile->parse();
51
+
52
+			if (PHP_CODESNIFFER_VERBOSITY === 1) {
53
+				$timeTaken = ((microtime(true) - $startTime) * 1000);
54
+				if ($timeTaken < 1000) {
55
+					$timeTaken = round($timeTaken);
56
+					echo "DONE in {$timeTaken}ms";
57
+				} else {
58
+					$timeTaken = round(($timeTaken / 1000), 2);
59
+					echo "DONE in $timeTaken secs";
60
+				}
61
+
62
+				echo PHP_EOL;
63
+			}
64
+
65
+			$phpcsFile->fixer->startFile($phpcsFile);
66
+		}//end if
67
+
68
+		if (PHP_CODESNIFFER_VERBOSITY > 1) {
69
+			ob_end_clean();
70
+			echo "\t*** START FILE FIXING ***".PHP_EOL;
71
+		}
72
+
73
+		$fixed = $phpcsFile->fixer->fixFile();
74
+
75
+		if (PHP_CODESNIFFER_VERBOSITY > 1) {
76
+			echo "\t*** END FILE FIXING ***".PHP_EOL;
77
+			ob_start();
78
+		}
79
+
80
+		if ($fixed === false) {
81
+			return false;
82
+		}
83
+
84
+		$diff = $phpcsFile->fixer->generateDiff();
85
+		if ($diff === '') {
86
+			// Nothing to print.
87
+			return false;
88
+		}
89
+
90
+		echo $diff.PHP_EOL;
91
+		return true;
92
+
93
+	}//end generateFileReport()
94
+
95
+
96
+	/**
97
+	 * Prints all errors and warnings for each file processed.
98
+	 *
99
+	 * @param string $cachedData    Any partial report data that was returned from
100
+	 *                              generateFileReport during the run.
101
+	 * @param int    $totalFiles    Total number of files processed during the run.
102
+	 * @param int    $totalErrors   Total number of errors found during the run.
103
+	 * @param int    $totalWarnings Total number of warnings found during the run.
104
+	 * @param int    $totalFixable  Total number of problems that can be fixed.
105
+	 * @param bool   $showSources   Show sources?
106
+	 * @param int    $width         Maximum allowed line width.
107
+	 * @param bool   $interactive   Are we running in interactive mode?
108
+	 * @param bool   $toScreen      Is the report being printed to screen?
109
+	 *
110
+	 * @return void
111
+	 */
112
+	public function generate(
113
+		$cachedData,
114
+		$totalFiles,
115
+		$totalErrors,
116
+		$totalWarnings,
117
+		$totalFixable,
118
+		$showSources=false,
119
+		$width=80,
120
+		$interactive=false,
121
+		$toScreen=true
122
+	) {
123
+		echo $cachedData;
124
+		if ($toScreen === true && $cachedData !== '') {
125
+			echo PHP_EOL;
126
+		}
127
+
128
+	}//end generate()
129 129
 
130 130
 
131 131
 }//end class
Please login to merge, or discard this patch.
Spacing   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -30,7 +30,7 @@  discard block
 block discarded – undo
30 30
      *
31 31
      * @return bool
32 32
      */
33
-    public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80)
33
+    public function generateFileReport($report, File $phpcsFile, $showSources = false, $width = 80)
34 34
     {
35 35
         $errors = $phpcsFile->getFixableCount();
36 36
         if ($errors === 0) {
@@ -115,10 +115,10 @@  discard block
 block discarded – undo
115 115
         $totalErrors,
116 116
         $totalWarnings,
117 117
         $totalFixable,
118
-        $showSources=false,
119
-        $width=80,
120
-        $interactive=false,
121
-        $toScreen=true
118
+        $showSources = false,
119
+        $width = 80,
120
+        $interactive = false,
121
+        $toScreen = true
122 122
     ) {
123 123
         echo $cachedData;
124 124
         if ($toScreen === true && $cachedData !== '') {
Please login to merge, or discard this patch.
vendor/squizlabs/php_codesniffer/src/Reports/VersionControl.php 3 patches
Indentation   +355 added lines, -355 removed lines patch added patch discarded remove patch
@@ -16,361 +16,361 @@
 block discarded – undo
16 16
 abstract class VersionControl implements Report
17 17
 {
18 18
 
19
-    /**
20
-     * The name of the report we want in the output.
21
-     *
22
-     * @var string
23
-     */
24
-    protected $reportName = 'VERSION CONTROL';
25
-
26
-
27
-    /**
28
-     * Generate a partial report for a single processed file.
29
-     *
30
-     * Function should return TRUE if it printed or stored data about the file
31
-     * and FALSE if it ignored the file. Returning TRUE indicates that the file and
32
-     * its data should be counted in the grand totals.
33
-     *
34
-     * @param array                 $report      Prepared report data.
35
-     * @param \PHP_CodeSniffer\File $phpcsFile   The file being reported on.
36
-     * @param bool                  $showSources Show sources?
37
-     * @param int                   $width       Maximum allowed line width.
38
-     *
39
-     * @return bool
40
-     */
41
-    public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80)
42
-    {
43
-        $blames = $this->getBlameContent($report['filename']);
44
-
45
-        $authorCache = [];
46
-        $praiseCache = [];
47
-        $sourceCache = [];
48
-
49
-        foreach ($report['messages'] as $line => $lineErrors) {
50
-            $author = 'Unknown';
51
-            if (isset($blames[($line - 1)]) === true) {
52
-                $blameAuthor = $this->getAuthor($blames[($line - 1)]);
53
-                if ($blameAuthor !== false) {
54
-                    $author = $blameAuthor;
55
-                }
56
-            }
57
-
58
-            if (isset($authorCache[$author]) === false) {
59
-                $authorCache[$author] = 0;
60
-                $praiseCache[$author] = [
61
-                    'good' => 0,
62
-                    'bad'  => 0,
63
-                ];
64
-            }
65
-
66
-            $praiseCache[$author]['bad']++;
67
-
68
-            foreach ($lineErrors as $column => $colErrors) {
69
-                foreach ($colErrors as $error) {
70
-                    $authorCache[$author]++;
71
-
72
-                    if ($showSources === true) {
73
-                        $source = $error['source'];
74
-                        if (isset($sourceCache[$author][$source]) === false) {
75
-                            $sourceCache[$author][$source] = [
76
-                                'count'   => 1,
77
-                                'fixable' => $error['fixable'],
78
-                            ];
79
-                        } else {
80
-                            $sourceCache[$author][$source]['count']++;
81
-                        }
82
-                    }
83
-                }
84
-            }
85
-
86
-            unset($blames[($line - 1)]);
87
-        }//end foreach
88
-
89
-        // Now go through and give the authors some credit for
90
-        // all the lines that do not have errors.
91
-        foreach ($blames as $line) {
92
-            $author = $this->getAuthor($line);
93
-            if ($author === false) {
94
-                $author = 'Unknown';
95
-            }
96
-
97
-            if (isset($authorCache[$author]) === false) {
98
-                // This author doesn't have any errors.
99
-                if (PHP_CODESNIFFER_VERBOSITY === 0) {
100
-                    continue;
101
-                }
102
-
103
-                $authorCache[$author] = 0;
104
-                $praiseCache[$author] = [
105
-                    'good' => 0,
106
-                    'bad'  => 0,
107
-                ];
108
-            }
109
-
110
-            $praiseCache[$author]['good']++;
111
-        }//end foreach
112
-
113
-        foreach ($authorCache as $author => $errors) {
114
-            echo "AUTHOR>>$author>>$errors".PHP_EOL;
115
-        }
116
-
117
-        foreach ($praiseCache as $author => $praise) {
118
-            echo "PRAISE>>$author>>".$praise['good'].'>>'.$praise['bad'].PHP_EOL;
119
-        }
120
-
121
-        foreach ($sourceCache as $author => $sources) {
122
-            foreach ($sources as $source => $sourceData) {
123
-                $count   = $sourceData['count'];
124
-                $fixable = (int) $sourceData['fixable'];
125
-                echo "SOURCE>>$author>>$source>>$count>>$fixable".PHP_EOL;
126
-            }
127
-        }
128
-
129
-        return true;
130
-
131
-    }//end generateFileReport()
132
-
133
-
134
-    /**
135
-     * Prints the author of all errors and warnings, as given by "version control blame".
136
-     *
137
-     * @param string $cachedData    Any partial report data that was returned from
138
-     *                              generateFileReport during the run.
139
-     * @param int    $totalFiles    Total number of files processed during the run.
140
-     * @param int    $totalErrors   Total number of errors found during the run.
141
-     * @param int    $totalWarnings Total number of warnings found during the run.
142
-     * @param int    $totalFixable  Total number of problems that can be fixed.
143
-     * @param bool   $showSources   Show sources?
144
-     * @param int    $width         Maximum allowed line width.
145
-     * @param bool   $interactive   Are we running in interactive mode?
146
-     * @param bool   $toScreen      Is the report being printed to screen?
147
-     *
148
-     * @return void
149
-     */
150
-    public function generate(
151
-        $cachedData,
152
-        $totalFiles,
153
-        $totalErrors,
154
-        $totalWarnings,
155
-        $totalFixable,
156
-        $showSources=false,
157
-        $width=80,
158
-        $interactive=false,
159
-        $toScreen=true
160
-    ) {
161
-        $errorsShown = ($totalErrors + $totalWarnings);
162
-        if ($errorsShown === 0) {
163
-            // Nothing to show.
164
-            return;
165
-        }
166
-
167
-        $lines = explode(PHP_EOL, $cachedData);
168
-        array_pop($lines);
169
-
170
-        if (empty($lines) === true) {
171
-            return;
172
-        }
173
-
174
-        $authorCache = [];
175
-        $praiseCache = [];
176
-        $sourceCache = [];
177
-
178
-        foreach ($lines as $line) {
179
-            $parts = explode('>>', $line);
180
-            switch ($parts[0]) {
181
-            case 'AUTHOR':
182
-                if (isset($authorCache[$parts[1]]) === false) {
183
-                    $authorCache[$parts[1]] = $parts[2];
184
-                } else {
185
-                    $authorCache[$parts[1]] += $parts[2];
186
-                }
187
-                break;
188
-            case 'PRAISE':
189
-                if (isset($praiseCache[$parts[1]]) === false) {
190
-                    $praiseCache[$parts[1]] = [
191
-                        'good' => $parts[2],
192
-                        'bad'  => $parts[3],
193
-                    ];
194
-                } else {
195
-                    $praiseCache[$parts[1]]['good'] += $parts[2];
196
-                    $praiseCache[$parts[1]]['bad']  += $parts[3];
197
-                }
198
-                break;
199
-            case 'SOURCE':
200
-                if (isset($praiseCache[$parts[1]]) === false) {
201
-                    $praiseCache[$parts[1]] = [];
202
-                }
203
-
204
-                if (isset($sourceCache[$parts[1]][$parts[2]]) === false) {
205
-                    $sourceCache[$parts[1]][$parts[2]] = [
206
-                        'count'   => $parts[3],
207
-                        'fixable' => (bool) $parts[4],
208
-                    ];
209
-                } else {
210
-                    $sourceCache[$parts[1]][$parts[2]]['count'] += $parts[3];
211
-                }
212
-                break;
213
-            default:
214
-                break;
215
-            }//end switch
216
-        }//end foreach
217
-
218
-        // Make sure the report width isn't too big.
219
-        $maxLength = 0;
220
-        foreach ($authorCache as $author => $count) {
221
-            $maxLength = max($maxLength, strlen($author));
222
-            if ($showSources === true && isset($sourceCache[$author]) === true) {
223
-                foreach ($sourceCache[$author] as $source => $sourceData) {
224
-                    if ($source === 'count') {
225
-                        continue;
226
-                    }
227
-
228
-                    $maxLength = max($maxLength, (strlen($source) + 9));
229
-                }
230
-            }
231
-        }
232
-
233
-        $width = min($width, ($maxLength + 30));
234
-        $width = max($width, 70);
235
-        arsort($authorCache);
236
-
237
-        echo PHP_EOL."\033[1m".'PHP CODE SNIFFER '.$this->reportName.' BLAME SUMMARY'."\033[0m".PHP_EOL;
238
-        echo str_repeat('-', $width).PHP_EOL."\033[1m";
239
-        if ($showSources === true) {
240
-            echo 'AUTHOR   SOURCE'.str_repeat(' ', ($width - 43)).'(Author %) (Overall %) COUNT'.PHP_EOL;
241
-            echo str_repeat('-', $width).PHP_EOL;
242
-        } else {
243
-            echo 'AUTHOR'.str_repeat(' ', ($width - 34)).'(Author %) (Overall %) COUNT'.PHP_EOL;
244
-            echo str_repeat('-', $width).PHP_EOL;
245
-        }
246
-
247
-        echo "\033[0m";
248
-
249
-        if ($showSources === true) {
250
-            $maxSniffWidth = ($width - 15);
251
-
252
-            if ($totalFixable > 0) {
253
-                $maxSniffWidth -= 4;
254
-            }
255
-        }
256
-
257
-        $fixableSources = 0;
258
-
259
-        foreach ($authorCache as $author => $count) {
260
-            if ($praiseCache[$author]['good'] === 0) {
261
-                $percent = 0;
262
-            } else {
263
-                $total   = ($praiseCache[$author]['bad'] + $praiseCache[$author]['good']);
264
-                $percent = round(($praiseCache[$author]['bad'] / $total * 100), 2);
265
-            }
266
-
267
-            $overallPercent = '('.round((($count / $errorsShown) * 100), 2).')';
268
-            $authorPercent  = '('.$percent.')';
269
-            $line           = str_repeat(' ', (6 - strlen($count))).$count;
270
-            $line           = str_repeat(' ', (12 - strlen($overallPercent))).$overallPercent.$line;
271
-            $line           = str_repeat(' ', (11 - strlen($authorPercent))).$authorPercent.$line;
272
-            $line           = $author.str_repeat(' ', ($width - strlen($author) - strlen($line))).$line;
273
-
274
-            if ($showSources === true) {
275
-                $line = "\033[1m$line\033[0m";
276
-            }
277
-
278
-            echo $line.PHP_EOL;
279
-
280
-            if ($showSources === true && isset($sourceCache[$author]) === true) {
281
-                $errors = $sourceCache[$author];
282
-                asort($errors);
283
-                $errors = array_reverse($errors);
284
-
285
-                foreach ($errors as $source => $sourceData) {
286
-                    if ($source === 'count') {
287
-                        continue;
288
-                    }
289
-
290
-                    $count = $sourceData['count'];
291
-
292
-                    $srcLength = strlen($source);
293
-                    if ($srcLength > $maxSniffWidth) {
294
-                        $source = substr($source, 0, $maxSniffWidth);
295
-                    }
296
-
297
-                    $line = str_repeat(' ', (5 - strlen($count))).$count;
298
-
299
-                    echo '         ';
300
-                    if ($totalFixable > 0) {
301
-                        echo '[';
302
-                        if ($sourceData['fixable'] === true) {
303
-                            echo 'x';
304
-                            $fixableSources++;
305
-                        } else {
306
-                            echo ' ';
307
-                        }
308
-
309
-                        echo '] ';
310
-                    }
311
-
312
-                    echo $source;
313
-                    if ($totalFixable > 0) {
314
-                        echo str_repeat(' ', ($width - 18 - strlen($source)));
315
-                    } else {
316
-                        echo str_repeat(' ', ($width - 14 - strlen($source)));
317
-                    }
318
-
319
-                    echo $line.PHP_EOL;
320
-                }//end foreach
321
-            }//end if
322
-        }//end foreach
323
-
324
-        echo str_repeat('-', $width).PHP_EOL;
325
-        echo "\033[1m".'A TOTAL OF '.$errorsShown.' SNIFF VIOLATION';
326
-        if ($errorsShown !== 1) {
327
-            echo 'S';
328
-        }
329
-
330
-        echo ' WERE COMMITTED BY '.count($authorCache).' AUTHOR';
331
-        if (count($authorCache) !== 1) {
332
-            echo 'S';
333
-        }
334
-
335
-        echo "\033[0m";
336
-
337
-        if ($totalFixable > 0) {
338
-            if ($showSources === true) {
339
-                echo PHP_EOL.str_repeat('-', $width).PHP_EOL;
340
-                echo "\033[1mPHPCBF CAN FIX THE $fixableSources MARKED SOURCES AUTOMATICALLY ($totalFixable VIOLATIONS IN TOTAL)\033[0m";
341
-            } else {
342
-                echo PHP_EOL.str_repeat('-', $width).PHP_EOL;
343
-                echo "\033[1mPHPCBF CAN FIX $totalFixable OF THESE SNIFF VIOLATIONS AUTOMATICALLY\033[0m";
344
-            }
345
-        }
346
-
347
-        echo PHP_EOL.str_repeat('-', $width).PHP_EOL.PHP_EOL;
348
-
349
-        if ($toScreen === true && $interactive === false) {
350
-            Timing::printRunTime();
351
-        }
352
-
353
-    }//end generate()
354
-
355
-
356
-    /**
357
-     * Extract the author from a blame line.
358
-     *
359
-     * @param string $line Line to parse.
360
-     *
361
-     * @return mixed string or false if impossible to recover.
362
-     */
363
-    abstract protected function getAuthor($line);
364
-
365
-
366
-    /**
367
-     * Gets the blame output.
368
-     *
369
-     * @param string $filename File to blame.
370
-     *
371
-     * @return array
372
-     */
373
-    abstract protected function getBlameContent($filename);
19
+	/**
20
+	 * The name of the report we want in the output.
21
+	 *
22
+	 * @var string
23
+	 */
24
+	protected $reportName = 'VERSION CONTROL';
25
+
26
+
27
+	/**
28
+	 * Generate a partial report for a single processed file.
29
+	 *
30
+	 * Function should return TRUE if it printed or stored data about the file
31
+	 * and FALSE if it ignored the file. Returning TRUE indicates that the file and
32
+	 * its data should be counted in the grand totals.
33
+	 *
34
+	 * @param array                 $report      Prepared report data.
35
+	 * @param \PHP_CodeSniffer\File $phpcsFile   The file being reported on.
36
+	 * @param bool                  $showSources Show sources?
37
+	 * @param int                   $width       Maximum allowed line width.
38
+	 *
39
+	 * @return bool
40
+	 */
41
+	public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80)
42
+	{
43
+		$blames = $this->getBlameContent($report['filename']);
44
+
45
+		$authorCache = [];
46
+		$praiseCache = [];
47
+		$sourceCache = [];
48
+
49
+		foreach ($report['messages'] as $line => $lineErrors) {
50
+			$author = 'Unknown';
51
+			if (isset($blames[($line - 1)]) === true) {
52
+				$blameAuthor = $this->getAuthor($blames[($line - 1)]);
53
+				if ($blameAuthor !== false) {
54
+					$author = $blameAuthor;
55
+				}
56
+			}
57
+
58
+			if (isset($authorCache[$author]) === false) {
59
+				$authorCache[$author] = 0;
60
+				$praiseCache[$author] = [
61
+					'good' => 0,
62
+					'bad'  => 0,
63
+				];
64
+			}
65
+
66
+			$praiseCache[$author]['bad']++;
67
+
68
+			foreach ($lineErrors as $column => $colErrors) {
69
+				foreach ($colErrors as $error) {
70
+					$authorCache[$author]++;
71
+
72
+					if ($showSources === true) {
73
+						$source = $error['source'];
74
+						if (isset($sourceCache[$author][$source]) === false) {
75
+							$sourceCache[$author][$source] = [
76
+								'count'   => 1,
77
+								'fixable' => $error['fixable'],
78
+							];
79
+						} else {
80
+							$sourceCache[$author][$source]['count']++;
81
+						}
82
+					}
83
+				}
84
+			}
85
+
86
+			unset($blames[($line - 1)]);
87
+		}//end foreach
88
+
89
+		// Now go through and give the authors some credit for
90
+		// all the lines that do not have errors.
91
+		foreach ($blames as $line) {
92
+			$author = $this->getAuthor($line);
93
+			if ($author === false) {
94
+				$author = 'Unknown';
95
+			}
96
+
97
+			if (isset($authorCache[$author]) === false) {
98
+				// This author doesn't have any errors.
99
+				if (PHP_CODESNIFFER_VERBOSITY === 0) {
100
+					continue;
101
+				}
102
+
103
+				$authorCache[$author] = 0;
104
+				$praiseCache[$author] = [
105
+					'good' => 0,
106
+					'bad'  => 0,
107
+				];
108
+			}
109
+
110
+			$praiseCache[$author]['good']++;
111
+		}//end foreach
112
+
113
+		foreach ($authorCache as $author => $errors) {
114
+			echo "AUTHOR>>$author>>$errors".PHP_EOL;
115
+		}
116
+
117
+		foreach ($praiseCache as $author => $praise) {
118
+			echo "PRAISE>>$author>>".$praise['good'].'>>'.$praise['bad'].PHP_EOL;
119
+		}
120
+
121
+		foreach ($sourceCache as $author => $sources) {
122
+			foreach ($sources as $source => $sourceData) {
123
+				$count   = $sourceData['count'];
124
+				$fixable = (int) $sourceData['fixable'];
125
+				echo "SOURCE>>$author>>$source>>$count>>$fixable".PHP_EOL;
126
+			}
127
+		}
128
+
129
+		return true;
130
+
131
+	}//end generateFileReport()
132
+
133
+
134
+	/**
135
+	 * Prints the author of all errors and warnings, as given by "version control blame".
136
+	 *
137
+	 * @param string $cachedData    Any partial report data that was returned from
138
+	 *                              generateFileReport during the run.
139
+	 * @param int    $totalFiles    Total number of files processed during the run.
140
+	 * @param int    $totalErrors   Total number of errors found during the run.
141
+	 * @param int    $totalWarnings Total number of warnings found during the run.
142
+	 * @param int    $totalFixable  Total number of problems that can be fixed.
143
+	 * @param bool   $showSources   Show sources?
144
+	 * @param int    $width         Maximum allowed line width.
145
+	 * @param bool   $interactive   Are we running in interactive mode?
146
+	 * @param bool   $toScreen      Is the report being printed to screen?
147
+	 *
148
+	 * @return void
149
+	 */
150
+	public function generate(
151
+		$cachedData,
152
+		$totalFiles,
153
+		$totalErrors,
154
+		$totalWarnings,
155
+		$totalFixable,
156
+		$showSources=false,
157
+		$width=80,
158
+		$interactive=false,
159
+		$toScreen=true
160
+	) {
161
+		$errorsShown = ($totalErrors + $totalWarnings);
162
+		if ($errorsShown === 0) {
163
+			// Nothing to show.
164
+			return;
165
+		}
166
+
167
+		$lines = explode(PHP_EOL, $cachedData);
168
+		array_pop($lines);
169
+
170
+		if (empty($lines) === true) {
171
+			return;
172
+		}
173
+
174
+		$authorCache = [];
175
+		$praiseCache = [];
176
+		$sourceCache = [];
177
+
178
+		foreach ($lines as $line) {
179
+			$parts = explode('>>', $line);
180
+			switch ($parts[0]) {
181
+			case 'AUTHOR':
182
+				if (isset($authorCache[$parts[1]]) === false) {
183
+					$authorCache[$parts[1]] = $parts[2];
184
+				} else {
185
+					$authorCache[$parts[1]] += $parts[2];
186
+				}
187
+				break;
188
+			case 'PRAISE':
189
+				if (isset($praiseCache[$parts[1]]) === false) {
190
+					$praiseCache[$parts[1]] = [
191
+						'good' => $parts[2],
192
+						'bad'  => $parts[3],
193
+					];
194
+				} else {
195
+					$praiseCache[$parts[1]]['good'] += $parts[2];
196
+					$praiseCache[$parts[1]]['bad']  += $parts[3];
197
+				}
198
+				break;
199
+			case 'SOURCE':
200
+				if (isset($praiseCache[$parts[1]]) === false) {
201
+					$praiseCache[$parts[1]] = [];
202
+				}
203
+
204
+				if (isset($sourceCache[$parts[1]][$parts[2]]) === false) {
205
+					$sourceCache[$parts[1]][$parts[2]] = [
206
+						'count'   => $parts[3],
207
+						'fixable' => (bool) $parts[4],
208
+					];
209
+				} else {
210
+					$sourceCache[$parts[1]][$parts[2]]['count'] += $parts[3];
211
+				}
212
+				break;
213
+			default:
214
+				break;
215
+			}//end switch
216
+		}//end foreach
217
+
218
+		// Make sure the report width isn't too big.
219
+		$maxLength = 0;
220
+		foreach ($authorCache as $author => $count) {
221
+			$maxLength = max($maxLength, strlen($author));
222
+			if ($showSources === true && isset($sourceCache[$author]) === true) {
223
+				foreach ($sourceCache[$author] as $source => $sourceData) {
224
+					if ($source === 'count') {
225
+						continue;
226
+					}
227
+
228
+					$maxLength = max($maxLength, (strlen($source) + 9));
229
+				}
230
+			}
231
+		}
232
+
233
+		$width = min($width, ($maxLength + 30));
234
+		$width = max($width, 70);
235
+		arsort($authorCache);
236
+
237
+		echo PHP_EOL."\033[1m".'PHP CODE SNIFFER '.$this->reportName.' BLAME SUMMARY'."\033[0m".PHP_EOL;
238
+		echo str_repeat('-', $width).PHP_EOL."\033[1m";
239
+		if ($showSources === true) {
240
+			echo 'AUTHOR   SOURCE'.str_repeat(' ', ($width - 43)).'(Author %) (Overall %) COUNT'.PHP_EOL;
241
+			echo str_repeat('-', $width).PHP_EOL;
242
+		} else {
243
+			echo 'AUTHOR'.str_repeat(' ', ($width - 34)).'(Author %) (Overall %) COUNT'.PHP_EOL;
244
+			echo str_repeat('-', $width).PHP_EOL;
245
+		}
246
+
247
+		echo "\033[0m";
248
+
249
+		if ($showSources === true) {
250
+			$maxSniffWidth = ($width - 15);
251
+
252
+			if ($totalFixable > 0) {
253
+				$maxSniffWidth -= 4;
254
+			}
255
+		}
256
+
257
+		$fixableSources = 0;
258
+
259
+		foreach ($authorCache as $author => $count) {
260
+			if ($praiseCache[$author]['good'] === 0) {
261
+				$percent = 0;
262
+			} else {
263
+				$total   = ($praiseCache[$author]['bad'] + $praiseCache[$author]['good']);
264
+				$percent = round(($praiseCache[$author]['bad'] / $total * 100), 2);
265
+			}
266
+
267
+			$overallPercent = '('.round((($count / $errorsShown) * 100), 2).')';
268
+			$authorPercent  = '('.$percent.')';
269
+			$line           = str_repeat(' ', (6 - strlen($count))).$count;
270
+			$line           = str_repeat(' ', (12 - strlen($overallPercent))).$overallPercent.$line;
271
+			$line           = str_repeat(' ', (11 - strlen($authorPercent))).$authorPercent.$line;
272
+			$line           = $author.str_repeat(' ', ($width - strlen($author) - strlen($line))).$line;
273
+
274
+			if ($showSources === true) {
275
+				$line = "\033[1m$line\033[0m";
276
+			}
277
+
278
+			echo $line.PHP_EOL;
279
+
280
+			if ($showSources === true && isset($sourceCache[$author]) === true) {
281
+				$errors = $sourceCache[$author];
282
+				asort($errors);
283
+				$errors = array_reverse($errors);
284
+
285
+				foreach ($errors as $source => $sourceData) {
286
+					if ($source === 'count') {
287
+						continue;
288
+					}
289
+
290
+					$count = $sourceData['count'];
291
+
292
+					$srcLength = strlen($source);
293
+					if ($srcLength > $maxSniffWidth) {
294
+						$source = substr($source, 0, $maxSniffWidth);
295
+					}
296
+
297
+					$line = str_repeat(' ', (5 - strlen($count))).$count;
298
+
299
+					echo '         ';
300
+					if ($totalFixable > 0) {
301
+						echo '[';
302
+						if ($sourceData['fixable'] === true) {
303
+							echo 'x';
304
+							$fixableSources++;
305
+						} else {
306
+							echo ' ';
307
+						}
308
+
309
+						echo '] ';
310
+					}
311
+
312
+					echo $source;
313
+					if ($totalFixable > 0) {
314
+						echo str_repeat(' ', ($width - 18 - strlen($source)));
315
+					} else {
316
+						echo str_repeat(' ', ($width - 14 - strlen($source)));
317
+					}
318
+
319
+					echo $line.PHP_EOL;
320
+				}//end foreach
321
+			}//end if
322
+		}//end foreach
323
+
324
+		echo str_repeat('-', $width).PHP_EOL;
325
+		echo "\033[1m".'A TOTAL OF '.$errorsShown.' SNIFF VIOLATION';
326
+		if ($errorsShown !== 1) {
327
+			echo 'S';
328
+		}
329
+
330
+		echo ' WERE COMMITTED BY '.count($authorCache).' AUTHOR';
331
+		if (count($authorCache) !== 1) {
332
+			echo 'S';
333
+		}
334
+
335
+		echo "\033[0m";
336
+
337
+		if ($totalFixable > 0) {
338
+			if ($showSources === true) {
339
+				echo PHP_EOL.str_repeat('-', $width).PHP_EOL;
340
+				echo "\033[1mPHPCBF CAN FIX THE $fixableSources MARKED SOURCES AUTOMATICALLY ($totalFixable VIOLATIONS IN TOTAL)\033[0m";
341
+			} else {
342
+				echo PHP_EOL.str_repeat('-', $width).PHP_EOL;
343
+				echo "\033[1mPHPCBF CAN FIX $totalFixable OF THESE SNIFF VIOLATIONS AUTOMATICALLY\033[0m";
344
+			}
345
+		}
346
+
347
+		echo PHP_EOL.str_repeat('-', $width).PHP_EOL.PHP_EOL;
348
+
349
+		if ($toScreen === true && $interactive === false) {
350
+			Timing::printRunTime();
351
+		}
352
+
353
+	}//end generate()
354
+
355
+
356
+	/**
357
+	 * Extract the author from a blame line.
358
+	 *
359
+	 * @param string $line Line to parse.
360
+	 *
361
+	 * @return mixed string or false if impossible to recover.
362
+	 */
363
+	abstract protected function getAuthor($line);
364
+
365
+
366
+	/**
367
+	 * Gets the blame output.
368
+	 *
369
+	 * @param string $filename File to blame.
370
+	 *
371
+	 * @return array
372
+	 */
373
+	abstract protected function getBlameContent($filename);
374 374
 
375 375
 
376 376
 }//end class
Please login to merge, or discard this patch.
Switch Indentation   +34 added lines, -34 removed lines patch added patch discarded remove patch
@@ -178,40 +178,40 @@
 block discarded – undo
178 178
         foreach ($lines as $line) {
179 179
             $parts = explode('>>', $line);
180 180
             switch ($parts[0]) {
181
-            case 'AUTHOR':
182
-                if (isset($authorCache[$parts[1]]) === false) {
183
-                    $authorCache[$parts[1]] = $parts[2];
184
-                } else {
185
-                    $authorCache[$parts[1]] += $parts[2];
186
-                }
187
-                break;
188
-            case 'PRAISE':
189
-                if (isset($praiseCache[$parts[1]]) === false) {
190
-                    $praiseCache[$parts[1]] = [
191
-                        'good' => $parts[2],
192
-                        'bad'  => $parts[3],
193
-                    ];
194
-                } else {
195
-                    $praiseCache[$parts[1]]['good'] += $parts[2];
196
-                    $praiseCache[$parts[1]]['bad']  += $parts[3];
197
-                }
198
-                break;
199
-            case 'SOURCE':
200
-                if (isset($praiseCache[$parts[1]]) === false) {
201
-                    $praiseCache[$parts[1]] = [];
202
-                }
203
-
204
-                if (isset($sourceCache[$parts[1]][$parts[2]]) === false) {
205
-                    $sourceCache[$parts[1]][$parts[2]] = [
206
-                        'count'   => $parts[3],
207
-                        'fixable' => (bool) $parts[4],
208
-                    ];
209
-                } else {
210
-                    $sourceCache[$parts[1]][$parts[2]]['count'] += $parts[3];
211
-                }
212
-                break;
213
-            default:
214
-                break;
181
+            	case 'AUTHOR':
182
+                	if (isset($authorCache[$parts[1]]) === false) {
183
+                    	$authorCache[$parts[1]] = $parts[2];
184
+                	} else {
185
+                    	$authorCache[$parts[1]] += $parts[2];
186
+                	}
187
+                	break;
188
+            	case 'PRAISE':
189
+                	if (isset($praiseCache[$parts[1]]) === false) {
190
+                    	$praiseCache[$parts[1]] = [
191
+                        	'good' => $parts[2],
192
+                        	'bad'  => $parts[3],
193
+                    	];
194
+                	} else {
195
+                    	$praiseCache[$parts[1]]['good'] += $parts[2];
196
+                    	$praiseCache[$parts[1]]['bad']  += $parts[3];
197
+                	}
198
+                	break;
199
+            	case 'SOURCE':
200
+                	if (isset($praiseCache[$parts[1]]) === false) {
201
+                    	$praiseCache[$parts[1]] = [];
202
+                	}
203
+
204
+                	if (isset($sourceCache[$parts[1]][$parts[2]]) === false) {
205
+                    	$sourceCache[$parts[1]][$parts[2]] = [
206
+                        	'count'   => $parts[3],
207
+                        	'fixable' => (bool) $parts[4],
208
+                    	];
209
+                	} else {
210
+                    	$sourceCache[$parts[1]][$parts[2]]['count'] += $parts[3];
211
+                	}
212
+                	break;
213
+            	default:
214
+                	break;
215 215
             }//end switch
216 216
         }//end foreach
217 217
 
Please login to merge, or discard this patch.
Spacing   +5 added lines, -5 removed lines patch added patch discarded remove patch
@@ -38,7 +38,7 @@  discard block
 block discarded – undo
38 38
      *
39 39
      * @return bool
40 40
      */
41
-    public function generateFileReport($report, File $phpcsFile, $showSources=false, $width=80)
41
+    public function generateFileReport($report, File $phpcsFile, $showSources = false, $width = 80)
42 42
     {
43 43
         $blames = $this->getBlameContent($report['filename']);
44 44
 
@@ -153,10 +153,10 @@  discard block
 block discarded – undo
153 153
         $totalErrors,
154 154
         $totalWarnings,
155 155
         $totalFixable,
156
-        $showSources=false,
157
-        $width=80,
158
-        $interactive=false,
159
-        $toScreen=true
156
+        $showSources = false,
157
+        $width = 80,
158
+        $interactive = false,
159
+        $toScreen = true
160 160
     ) {
161 161
         $errorsShown = ($totalErrors + $totalWarnings);
162 162
         if ($errorsShown === 0) {
Please login to merge, or discard this patch.
vendor/squizlabs/php_codesniffer/src/Fixer.php 3 patches
Switch Indentation   +8 added lines, -8 removed lines patch added patch discarded remove patch
@@ -269,14 +269,14 @@
 block discarded – undo
269 269
         foreach ($diffLines as $line) {
270 270
             if (isset($line[0]) === true) {
271 271
                 switch ($line[0]) {
272
-                case '-':
273
-                    $diff[] = "\033[31m$line\033[0m";
274
-                    break;
275
-                case '+':
276
-                    $diff[] = "\033[32m$line\033[0m";
277
-                    break;
278
-                default:
279
-                    $diff[] = $line;
272
+                	case '-':
273
+                    	$diff[] = "\033[31m$line\033[0m";
274
+                    	break;
275
+                	case '+':
276
+                    	$diff[] = "\033[32m$line\033[0m";
277
+                    	break;
278
+                	default:
279
+                    	$diff[] = $line;
280 280
                 }
281 281
             }
282 282
         }
Please login to merge, or discard this patch.
Spacing   +2 added lines, -2 removed lines patch added patch discarded remove patch
@@ -224,7 +224,7 @@  discard block
 block discarded – undo
224 224
      *
225 225
      * @return string
226 226
      */
227
-    public function generateDiff($filePath=null, $colors=true)
227
+    public function generateDiff($filePath = null, $colors = true)
228 228
     {
229 229
         if ($filePath === null) {
230 230
             $filePath = $this->currentFile->getFilename();
@@ -643,7 +643,7 @@  discard block
 block discarded – undo
643 643
      *
644 644
      * @return bool If the change was accepted.
645 645
      */
646
-    public function substrToken($stackPtr, $start, $length=null)
646
+    public function substrToken($stackPtr, $start, $length = null)
647 647
     {
648 648
         $current = $this->getTokenContent($stackPtr);
649 649
 
Please login to merge, or discard this patch.
Indentation   +783 added lines, -783 removed lines patch added patch discarded remove patch
@@ -18,789 +18,789 @@
 block discarded – undo
18 18
 class Fixer
19 19
 {
20 20
 
21
-    /**
22
-     * Is the fixer enabled and fixing a file?
23
-     *
24
-     * Sniffs should check this value to ensure they are not
25
-     * doing extra processing to prepare for a fix when fixing is
26
-     * not required.
27
-     *
28
-     * @var boolean
29
-     */
30
-    public $enabled = false;
31
-
32
-    /**
33
-     * The number of times we have looped over a file.
34
-     *
35
-     * @var integer
36
-     */
37
-    public $loops = 0;
38
-
39
-    /**
40
-     * The file being fixed.
41
-     *
42
-     * @var \PHP_CodeSniffer\Files\File
43
-     */
44
-    private $currentFile = null;
45
-
46
-    /**
47
-     * The list of tokens that make up the file contents.
48
-     *
49
-     * This is a simplified list which just contains the token content and nothing
50
-     * else. This is the array that is updated as fixes are made, not the file's
51
-     * token array. Imploding this array will give you the file content back.
52
-     *
53
-     * @var array<int, string>
54
-     */
55
-    private $tokens = [];
56
-
57
-    /**
58
-     * A list of tokens that have already been fixed.
59
-     *
60
-     * We don't allow the same token to be fixed more than once each time
61
-     * through a file as this can easily cause conflicts between sniffs.
62
-     *
63
-     * @var int[]
64
-     */
65
-    private $fixedTokens = [];
66
-
67
-    /**
68
-     * The last value of each fixed token.
69
-     *
70
-     * If a token is being "fixed" back to its last value, the fix is
71
-     * probably conflicting with another.
72
-     *
73
-     * @var array<int, string>
74
-     */
75
-    private $oldTokenValues = [];
76
-
77
-    /**
78
-     * A list of tokens that have been fixed during a changeset.
79
-     *
80
-     * All changes in changeset must be able to be applied, or else
81
-     * the entire changeset is rejected.
82
-     *
83
-     * @var array
84
-     */
85
-    private $changeset = [];
86
-
87
-    /**
88
-     * Is there an open changeset.
89
-     *
90
-     * @var boolean
91
-     */
92
-    private $inChangeset = false;
93
-
94
-    /**
95
-     * Is the current fixing loop in conflict?
96
-     *
97
-     * @var boolean
98
-     */
99
-    private $inConflict = false;
100
-
101
-    /**
102
-     * The number of fixes that have been performed.
103
-     *
104
-     * @var integer
105
-     */
106
-    private $numFixes = 0;
107
-
108
-
109
-    /**
110
-     * Starts fixing a new file.
111
-     *
112
-     * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being fixed.
113
-     *
114
-     * @return void
115
-     */
116
-    public function startFile(File $phpcsFile)
117
-    {
118
-        $this->currentFile = $phpcsFile;
119
-        $this->numFixes    = 0;
120
-        $this->fixedTokens = [];
121
-
122
-        $tokens       = $phpcsFile->getTokens();
123
-        $this->tokens = [];
124
-        foreach ($tokens as $index => $token) {
125
-            if (isset($token['orig_content']) === true) {
126
-                $this->tokens[$index] = $token['orig_content'];
127
-            } else {
128
-                $this->tokens[$index] = $token['content'];
129
-            }
130
-        }
131
-
132
-    }//end startFile()
133
-
134
-
135
-    /**
136
-     * Attempt to fix the file by processing it until no fixes are made.
137
-     *
138
-     * @return boolean
139
-     */
140
-    public function fixFile()
141
-    {
142
-        $fixable = $this->currentFile->getFixableCount();
143
-        if ($fixable === 0) {
144
-            // Nothing to fix.
145
-            return false;
146
-        }
147
-
148
-        $this->enabled = true;
149
-
150
-        $this->loops = 0;
151
-        while ($this->loops < 50) {
152
-            ob_start();
153
-
154
-            // Only needed once file content has changed.
155
-            $contents = $this->getContents();
156
-
157
-            if (PHP_CODESNIFFER_VERBOSITY > 2) {
158
-                @ob_end_clean();
159
-                echo '---START FILE CONTENT---'.PHP_EOL;
160
-                $lines = explode($this->currentFile->eolChar, $contents);
161
-                $max   = strlen(count($lines));
162
-                foreach ($lines as $lineNum => $line) {
163
-                    $lineNum++;
164
-                    echo str_pad($lineNum, $max, ' ', STR_PAD_LEFT).'|'.$line.PHP_EOL;
165
-                }
166
-
167
-                echo '--- END FILE CONTENT ---'.PHP_EOL;
168
-                ob_start();
169
-            }
170
-
171
-            $this->inConflict = false;
172
-            $this->currentFile->ruleset->populateTokenListeners();
173
-            $this->currentFile->setContent($contents);
174
-            $this->currentFile->process();
175
-            ob_end_clean();
176
-
177
-            $this->loops++;
178
-
179
-            if (PHP_CODESNIFFER_CBF === true && PHP_CODESNIFFER_VERBOSITY > 0) {
180
-                echo "\r".str_repeat(' ', 80)."\r";
181
-                echo "\t=> Fixing file: $this->numFixes/$fixable violations remaining [made $this->loops pass";
182
-                if ($this->loops > 1) {
183
-                    echo 'es';
184
-                }
185
-
186
-                echo ']... ';
187
-                if (PHP_CODESNIFFER_VERBOSITY > 1) {
188
-                    echo PHP_EOL;
189
-                }
190
-            }
191
-
192
-            if ($this->numFixes === 0 && $this->inConflict === false) {
193
-                // Nothing left to do.
194
-                break;
195
-            } else if (PHP_CODESNIFFER_VERBOSITY > 1) {
196
-                echo "\t* fixed $this->numFixes violations, starting loop ".($this->loops + 1).' *'.PHP_EOL;
197
-            }
198
-        }//end while
199
-
200
-        $this->enabled = false;
201
-
202
-        if ($this->numFixes > 0) {
203
-            if (PHP_CODESNIFFER_VERBOSITY > 1) {
204
-                if (ob_get_level() > 0) {
205
-                    ob_end_clean();
206
-                }
207
-
208
-                echo "\t*** Reached maximum number of loops with $this->numFixes violations left unfixed ***".PHP_EOL;
209
-                ob_start();
210
-            }
211
-
212
-            return false;
213
-        }
214
-
215
-        return true;
216
-
217
-    }//end fixFile()
218
-
219
-
220
-    /**
221
-     * Generates a text diff of the original file and the new content.
222
-     *
223
-     * @param string  $filePath Optional file path to diff the file against.
224
-     *                          If not specified, the original version of the
225
-     *                          file will be used.
226
-     * @param boolean $colors   Print coloured output or not.
227
-     *
228
-     * @return string
229
-     */
230
-    public function generateDiff($filePath=null, $colors=true)
231
-    {
232
-        if ($filePath === null) {
233
-            $filePath = $this->currentFile->getFilename();
234
-        }
235
-
236
-        $cwd = getcwd().DIRECTORY_SEPARATOR;
237
-        if (strpos($filePath, $cwd) === 0) {
238
-            $filename = substr($filePath, strlen($cwd));
239
-        } else {
240
-            $filename = $filePath;
241
-        }
242
-
243
-        $contents = $this->getContents();
244
-
245
-        $tempName  = tempnam(sys_get_temp_dir(), 'phpcs-fixer');
246
-        $fixedFile = fopen($tempName, 'w');
247
-        fwrite($fixedFile, $contents);
248
-
249
-        // We must use something like shell_exec() because whitespace at the end
250
-        // of lines is critical to diff files.
251
-        $filename = escapeshellarg($filename);
252
-        $cmd      = "diff -u -L$filename -LPHP_CodeSniffer $filename \"$tempName\"";
253
-
254
-        $diff = shell_exec($cmd);
255
-
256
-        fclose($fixedFile);
257
-        if (is_file($tempName) === true) {
258
-            unlink($tempName);
259
-        }
260
-
261
-        if ($diff === null) {
262
-            return '';
263
-        }
264
-
265
-        if ($colors === false) {
266
-            return $diff;
267
-        }
268
-
269
-        $diffLines = explode(PHP_EOL, $diff);
270
-        if (count($diffLines) === 1) {
271
-            // Seems to be required for cygwin.
272
-            $diffLines = explode("\n", $diff);
273
-        }
274
-
275
-        $diff = [];
276
-        foreach ($diffLines as $line) {
277
-            if (isset($line[0]) === true) {
278
-                switch ($line[0]) {
279
-                case '-':
280
-                    $diff[] = "\033[31m$line\033[0m";
281
-                    break;
282
-                case '+':
283
-                    $diff[] = "\033[32m$line\033[0m";
284
-                    break;
285
-                default:
286
-                    $diff[] = $line;
287
-                }
288
-            }
289
-        }
290
-
291
-        $diff = implode(PHP_EOL, $diff);
292
-
293
-        return $diff;
294
-
295
-    }//end generateDiff()
296
-
297
-
298
-    /**
299
-     * Get a count of fixes that have been performed on the file.
300
-     *
301
-     * This value is reset every time a new file is started, or an existing
302
-     * file is restarted.
303
-     *
304
-     * @return int
305
-     */
306
-    public function getFixCount()
307
-    {
308
-        return $this->numFixes;
309
-
310
-    }//end getFixCount()
311
-
312
-
313
-    /**
314
-     * Get the current content of the file, as a string.
315
-     *
316
-     * @return string
317
-     */
318
-    public function getContents()
319
-    {
320
-        $contents = implode($this->tokens);
321
-        return $contents;
322
-
323
-    }//end getContents()
324
-
325
-
326
-    /**
327
-     * Get the current fixed content of a token.
328
-     *
329
-     * This function takes changesets into account so should be used
330
-     * instead of directly accessing the token array.
331
-     *
332
-     * @param int $stackPtr The position of the token in the token stack.
333
-     *
334
-     * @return string
335
-     */
336
-    public function getTokenContent($stackPtr)
337
-    {
338
-        if ($this->inChangeset === true
339
-            && isset($this->changeset[$stackPtr]) === true
340
-        ) {
341
-            return $this->changeset[$stackPtr];
342
-        } else {
343
-            return $this->tokens[$stackPtr];
344
-        }
345
-
346
-    }//end getTokenContent()
347
-
348
-
349
-    /**
350
-     * Start recording actions for a changeset.
351
-     *
352
-     * @return void
353
-     */
354
-    public function beginChangeset()
355
-    {
356
-        if ($this->inConflict === true) {
357
-            return false;
358
-        }
359
-
360
-        if (PHP_CODESNIFFER_VERBOSITY > 1) {
361
-            $bt = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
362
-            if ($bt[1]['class'] === __CLASS__) {
363
-                $sniff = 'Fixer';
364
-            } else {
365
-                $sniff = Util\Common::getSniffCode($bt[1]['class']);
366
-            }
367
-
368
-            $line = $bt[0]['line'];
369
-
370
-            @ob_end_clean();
371
-            echo "\t=> Changeset started by $sniff:$line".PHP_EOL;
372
-            ob_start();
373
-        }
374
-
375
-        $this->changeset   = [];
376
-        $this->inChangeset = true;
377
-
378
-    }//end beginChangeset()
379
-
380
-
381
-    /**
382
-     * Stop recording actions for a changeset, and apply logged changes.
383
-     *
384
-     * @return boolean
385
-     */
386
-    public function endChangeset()
387
-    {
388
-        if ($this->inConflict === true) {
389
-            return false;
390
-        }
391
-
392
-        $this->inChangeset = false;
393
-
394
-        $success = true;
395
-        $applied = [];
396
-        foreach ($this->changeset as $stackPtr => $content) {
397
-            $success = $this->replaceToken($stackPtr, $content);
398
-            if ($success === false) {
399
-                break;
400
-            } else {
401
-                $applied[] = $stackPtr;
402
-            }
403
-        }
404
-
405
-        if ($success === false) {
406
-            // Rolling back all changes.
407
-            foreach ($applied as $stackPtr) {
408
-                $this->revertToken($stackPtr);
409
-            }
410
-
411
-            if (PHP_CODESNIFFER_VERBOSITY > 1) {
412
-                @ob_end_clean();
413
-                echo "\t=> Changeset failed to apply".PHP_EOL;
414
-                ob_start();
415
-            }
416
-        } else if (PHP_CODESNIFFER_VERBOSITY > 1) {
417
-            $fixes = count($this->changeset);
418
-            @ob_end_clean();
419
-            echo "\t=> Changeset ended: $fixes changes applied".PHP_EOL;
420
-            ob_start();
421
-        }
422
-
423
-        $this->changeset = [];
424
-        return true;
425
-
426
-    }//end endChangeset()
427
-
428
-
429
-    /**
430
-     * Stop recording actions for a changeset, and discard logged changes.
431
-     *
432
-     * @return void
433
-     */
434
-    public function rollbackChangeset()
435
-    {
436
-        $this->inChangeset = false;
437
-        $this->inConflict  = false;
438
-
439
-        if (empty($this->changeset) === false) {
440
-            if (PHP_CODESNIFFER_VERBOSITY > 1) {
441
-                $bt = debug_backtrace();
442
-                if ($bt[1]['class'] === 'PHP_CodeSniffer\Fixer') {
443
-                    $sniff = $bt[2]['class'];
444
-                    $line  = $bt[1]['line'];
445
-                } else {
446
-                    $sniff = $bt[1]['class'];
447
-                    $line  = $bt[0]['line'];
448
-                }
449
-
450
-                $sniff = Util\Common::getSniffCode($sniff);
451
-
452
-                $numChanges = count($this->changeset);
453
-
454
-                @ob_end_clean();
455
-                echo "\t\tR: $sniff:$line rolled back the changeset ($numChanges changes)".PHP_EOL;
456
-                echo "\t=> Changeset rolled back".PHP_EOL;
457
-                ob_start();
458
-            }
459
-
460
-            $this->changeset = [];
461
-        }//end if
462
-
463
-    }//end rollbackChangeset()
464
-
465
-
466
-    /**
467
-     * Replace the entire contents of a token.
468
-     *
469
-     * @param int    $stackPtr The position of the token in the token stack.
470
-     * @param string $content  The new content of the token.
471
-     *
472
-     * @return bool If the change was accepted.
473
-     */
474
-    public function replaceToken($stackPtr, $content)
475
-    {
476
-        if ($this->inConflict === true) {
477
-            return false;
478
-        }
479
-
480
-        if ($this->inChangeset === false
481
-            && isset($this->fixedTokens[$stackPtr]) === true
482
-        ) {
483
-            $indent = "\t";
484
-            if (empty($this->changeset) === false) {
485
-                $indent .= "\t";
486
-            }
487
-
488
-            if (PHP_CODESNIFFER_VERBOSITY > 1) {
489
-                @ob_end_clean();
490
-                echo "$indent* token $stackPtr has already been modified, skipping *".PHP_EOL;
491
-                ob_start();
492
-            }
493
-
494
-            return false;
495
-        }
496
-
497
-        if (PHP_CODESNIFFER_VERBOSITY > 1) {
498
-            $bt = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
499
-            if ($bt[1]['class'] === 'PHP_CodeSniffer\Fixer') {
500
-                $sniff = $bt[2]['class'];
501
-                $line  = $bt[1]['line'];
502
-            } else {
503
-                $sniff = $bt[1]['class'];
504
-                $line  = $bt[0]['line'];
505
-            }
506
-
507
-            $sniff = Util\Common::getSniffCode($sniff);
508
-
509
-            $tokens     = $this->currentFile->getTokens();
510
-            $type       = $tokens[$stackPtr]['type'];
511
-            $tokenLine  = $tokens[$stackPtr]['line'];
512
-            $oldContent = Common::prepareForOutput($this->tokens[$stackPtr]);
513
-            $newContent = Common::prepareForOutput($content);
514
-            if (trim($this->tokens[$stackPtr]) === '' && isset($this->tokens[($stackPtr + 1)]) === true) {
515
-                // Add some context for whitespace only changes.
516
-                $append      = Common::prepareForOutput($this->tokens[($stackPtr + 1)]);
517
-                $oldContent .= $append;
518
-                $newContent .= $append;
519
-            }
520
-        }//end if
521
-
522
-        if ($this->inChangeset === true) {
523
-            $this->changeset[$stackPtr] = $content;
524
-
525
-            if (PHP_CODESNIFFER_VERBOSITY > 1) {
526
-                @ob_end_clean();
527
-                echo "\t\tQ: $sniff:$line replaced token $stackPtr ($type on line $tokenLine) \"$oldContent\" => \"$newContent\"".PHP_EOL;
528
-                ob_start();
529
-            }
530
-
531
-            return true;
532
-        }
533
-
534
-        if (isset($this->oldTokenValues[$stackPtr]) === false) {
535
-            $this->oldTokenValues[$stackPtr] = [
536
-                'curr' => $content,
537
-                'prev' => $this->tokens[$stackPtr],
538
-                'loop' => $this->loops,
539
-            ];
540
-        } else {
541
-            if ($this->oldTokenValues[$stackPtr]['prev'] === $content
542
-                && $this->oldTokenValues[$stackPtr]['loop'] === ($this->loops - 1)
543
-            ) {
544
-                if (PHP_CODESNIFFER_VERBOSITY > 1) {
545
-                    $indent = "\t";
546
-                    if (empty($this->changeset) === false) {
547
-                        $indent .= "\t";
548
-                    }
549
-
550
-                    $loop = $this->oldTokenValues[$stackPtr]['loop'];
551
-
552
-                    @ob_end_clean();
553
-                    echo "$indent**** $sniff:$line has possible conflict with another sniff on loop $loop; caused by the following change ****".PHP_EOL;
554
-                    echo "$indent**** replaced token $stackPtr ($type on line $tokenLine) \"$oldContent\" => \"$newContent\" ****".PHP_EOL;
555
-                }
556
-
557
-                if ($this->oldTokenValues[$stackPtr]['loop'] >= ($this->loops - 1)) {
558
-                    $this->inConflict = true;
559
-                    if (PHP_CODESNIFFER_VERBOSITY > 1) {
560
-                        echo "$indent**** ignoring all changes until next loop ****".PHP_EOL;
561
-                    }
562
-                }
563
-
564
-                if (PHP_CODESNIFFER_VERBOSITY > 1) {
565
-                    ob_start();
566
-                }
567
-
568
-                return false;
569
-            }//end if
570
-
571
-            $this->oldTokenValues[$stackPtr]['prev'] = $this->oldTokenValues[$stackPtr]['curr'];
572
-            $this->oldTokenValues[$stackPtr]['curr'] = $content;
573
-            $this->oldTokenValues[$stackPtr]['loop'] = $this->loops;
574
-        }//end if
575
-
576
-        $this->fixedTokens[$stackPtr] = $this->tokens[$stackPtr];
577
-        $this->tokens[$stackPtr]      = $content;
578
-        $this->numFixes++;
579
-
580
-        if (PHP_CODESNIFFER_VERBOSITY > 1) {
581
-            $indent = "\t";
582
-            if (empty($this->changeset) === false) {
583
-                $indent .= "\tA: ";
584
-            }
585
-
586
-            if (ob_get_level() > 0) {
587
-                ob_end_clean();
588
-            }
589
-
590
-            echo "$indent$sniff:$line replaced token $stackPtr ($type on line $tokenLine) \"$oldContent\" => \"$newContent\"".PHP_EOL;
591
-            ob_start();
592
-        }
593
-
594
-        return true;
595
-
596
-    }//end replaceToken()
597
-
598
-
599
-    /**
600
-     * Reverts the previous fix made to a token.
601
-     *
602
-     * @param int $stackPtr The position of the token in the token stack.
603
-     *
604
-     * @return bool If a change was reverted.
605
-     */
606
-    public function revertToken($stackPtr)
607
-    {
608
-        if (isset($this->fixedTokens[$stackPtr]) === false) {
609
-            return false;
610
-        }
611
-
612
-        if (PHP_CODESNIFFER_VERBOSITY > 1) {
613
-            $bt = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
614
-            if ($bt[1]['class'] === 'PHP_CodeSniffer\Fixer') {
615
-                $sniff = $bt[2]['class'];
616
-                $line  = $bt[1]['line'];
617
-            } else {
618
-                $sniff = $bt[1]['class'];
619
-                $line  = $bt[0]['line'];
620
-            }
621
-
622
-            $sniff = Util\Common::getSniffCode($sniff);
623
-
624
-            $tokens     = $this->currentFile->getTokens();
625
-            $type       = $tokens[$stackPtr]['type'];
626
-            $tokenLine  = $tokens[$stackPtr]['line'];
627
-            $oldContent = Common::prepareForOutput($this->tokens[$stackPtr]);
628
-            $newContent = Common::prepareForOutput($this->fixedTokens[$stackPtr]);
629
-            if (trim($this->tokens[$stackPtr]) === '' && isset($tokens[($stackPtr + 1)]) === true) {
630
-                // Add some context for whitespace only changes.
631
-                $append      = Common::prepareForOutput($this->tokens[($stackPtr + 1)]);
632
-                $oldContent .= $append;
633
-                $newContent .= $append;
634
-            }
635
-        }//end if
636
-
637
-        $this->tokens[$stackPtr] = $this->fixedTokens[$stackPtr];
638
-        unset($this->fixedTokens[$stackPtr]);
639
-        $this->numFixes--;
640
-
641
-        if (PHP_CODESNIFFER_VERBOSITY > 1) {
642
-            $indent = "\t";
643
-            if (empty($this->changeset) === false) {
644
-                $indent .= "\tR: ";
645
-            }
646
-
647
-            @ob_end_clean();
648
-            echo "$indent$sniff:$line reverted token $stackPtr ($type on line $tokenLine) \"$oldContent\" => \"$newContent\"".PHP_EOL;
649
-            ob_start();
650
-        }
651
-
652
-        return true;
653
-
654
-    }//end revertToken()
655
-
656
-
657
-    /**
658
-     * Replace the content of a token with a part of its current content.
659
-     *
660
-     * @param int $stackPtr The position of the token in the token stack.
661
-     * @param int $start    The first character to keep.
662
-     * @param int $length   The number of characters to keep. If NULL, the content of
663
-     *                      the token from $start to the end of the content is kept.
664
-     *
665
-     * @return bool If the change was accepted.
666
-     */
667
-    public function substrToken($stackPtr, $start, $length=null)
668
-    {
669
-        $current = $this->getTokenContent($stackPtr);
670
-
671
-        if ($length === null) {
672
-            $newContent = substr($current, $start);
673
-        } else {
674
-            $newContent = substr($current, $start, $length);
675
-        }
676
-
677
-        return $this->replaceToken($stackPtr, $newContent);
678
-
679
-    }//end substrToken()
680
-
681
-
682
-    /**
683
-     * Adds a newline to end of a token's content.
684
-     *
685
-     * @param int $stackPtr The position of the token in the token stack.
686
-     *
687
-     * @return bool If the change was accepted.
688
-     */
689
-    public function addNewline($stackPtr)
690
-    {
691
-        $current = $this->getTokenContent($stackPtr);
692
-        return $this->replaceToken($stackPtr, $current.$this->currentFile->eolChar);
693
-
694
-    }//end addNewline()
695
-
696
-
697
-    /**
698
-     * Adds a newline to the start of a token's content.
699
-     *
700
-     * @param int $stackPtr The position of the token in the token stack.
701
-     *
702
-     * @return bool If the change was accepted.
703
-     */
704
-    public function addNewlineBefore($stackPtr)
705
-    {
706
-        $current = $this->getTokenContent($stackPtr);
707
-        return $this->replaceToken($stackPtr, $this->currentFile->eolChar.$current);
708
-
709
-    }//end addNewlineBefore()
710
-
711
-
712
-    /**
713
-     * Adds content to the end of a token's current content.
714
-     *
715
-     * @param int    $stackPtr The position of the token in the token stack.
716
-     * @param string $content  The content to add.
717
-     *
718
-     * @return bool If the change was accepted.
719
-     */
720
-    public function addContent($stackPtr, $content)
721
-    {
722
-        $current = $this->getTokenContent($stackPtr);
723
-        return $this->replaceToken($stackPtr, $current.$content);
724
-
725
-    }//end addContent()
726
-
727
-
728
-    /**
729
-     * Adds content to the start of a token's current content.
730
-     *
731
-     * @param int    $stackPtr The position of the token in the token stack.
732
-     * @param string $content  The content to add.
733
-     *
734
-     * @return bool If the change was accepted.
735
-     */
736
-    public function addContentBefore($stackPtr, $content)
737
-    {
738
-        $current = $this->getTokenContent($stackPtr);
739
-        return $this->replaceToken($stackPtr, $content.$current);
740
-
741
-    }//end addContentBefore()
742
-
743
-
744
-    /**
745
-     * Adjust the indent of a code block.
746
-     *
747
-     * @param int $start  The position of the token in the token stack
748
-     *                    to start adjusting the indent from.
749
-     * @param int $end    The position of the token in the token stack
750
-     *                    to end adjusting the indent.
751
-     * @param int $change The number of spaces to adjust the indent by
752
-     *                    (positive or negative).
753
-     *
754
-     * @return void
755
-     */
756
-    public function changeCodeBlockIndent($start, $end, $change)
757
-    {
758
-        $tokens = $this->currentFile->getTokens();
759
-
760
-        $baseIndent = '';
761
-        if ($change > 0) {
762
-            $baseIndent = str_repeat(' ', $change);
763
-        }
764
-
765
-        $useChangeset = false;
766
-        if ($this->inChangeset === false) {
767
-            $this->beginChangeset();
768
-            $useChangeset = true;
769
-        }
770
-
771
-        for ($i = $start; $i <= $end; $i++) {
772
-            if ($tokens[$i]['column'] !== 1
773
-                || $tokens[($i + 1)]['line'] !== $tokens[$i]['line']
774
-            ) {
775
-                continue;
776
-            }
777
-
778
-            $length = 0;
779
-            if ($tokens[$i]['code'] === T_WHITESPACE
780
-                || $tokens[$i]['code'] === T_DOC_COMMENT_WHITESPACE
781
-            ) {
782
-                $length = $tokens[$i]['length'];
783
-
784
-                $padding = ($length + $change);
785
-                if ($padding > 0) {
786
-                    $padding = str_repeat(' ', $padding);
787
-                } else {
788
-                    $padding = '';
789
-                }
790
-
791
-                $newContent = $padding.ltrim($tokens[$i]['content']);
792
-            } else {
793
-                $newContent = $baseIndent.$tokens[$i]['content'];
794
-            }
795
-
796
-            $this->replaceToken($i, $newContent);
797
-        }//end for
798
-
799
-        if ($useChangeset === true) {
800
-            $this->endChangeset();
801
-        }
802
-
803
-    }//end changeCodeBlockIndent()
21
+	/**
22
+	 * Is the fixer enabled and fixing a file?
23
+	 *
24
+	 * Sniffs should check this value to ensure they are not
25
+	 * doing extra processing to prepare for a fix when fixing is
26
+	 * not required.
27
+	 *
28
+	 * @var boolean
29
+	 */
30
+	public $enabled = false;
31
+
32
+	/**
33
+	 * The number of times we have looped over a file.
34
+	 *
35
+	 * @var integer
36
+	 */
37
+	public $loops = 0;
38
+
39
+	/**
40
+	 * The file being fixed.
41
+	 *
42
+	 * @var \PHP_CodeSniffer\Files\File
43
+	 */
44
+	private $currentFile = null;
45
+
46
+	/**
47
+	 * The list of tokens that make up the file contents.
48
+	 *
49
+	 * This is a simplified list which just contains the token content and nothing
50
+	 * else. This is the array that is updated as fixes are made, not the file's
51
+	 * token array. Imploding this array will give you the file content back.
52
+	 *
53
+	 * @var array<int, string>
54
+	 */
55
+	private $tokens = [];
56
+
57
+	/**
58
+	 * A list of tokens that have already been fixed.
59
+	 *
60
+	 * We don't allow the same token to be fixed more than once each time
61
+	 * through a file as this can easily cause conflicts between sniffs.
62
+	 *
63
+	 * @var int[]
64
+	 */
65
+	private $fixedTokens = [];
66
+
67
+	/**
68
+	 * The last value of each fixed token.
69
+	 *
70
+	 * If a token is being "fixed" back to its last value, the fix is
71
+	 * probably conflicting with another.
72
+	 *
73
+	 * @var array<int, string>
74
+	 */
75
+	private $oldTokenValues = [];
76
+
77
+	/**
78
+	 * A list of tokens that have been fixed during a changeset.
79
+	 *
80
+	 * All changes in changeset must be able to be applied, or else
81
+	 * the entire changeset is rejected.
82
+	 *
83
+	 * @var array
84
+	 */
85
+	private $changeset = [];
86
+
87
+	/**
88
+	 * Is there an open changeset.
89
+	 *
90
+	 * @var boolean
91
+	 */
92
+	private $inChangeset = false;
93
+
94
+	/**
95
+	 * Is the current fixing loop in conflict?
96
+	 *
97
+	 * @var boolean
98
+	 */
99
+	private $inConflict = false;
100
+
101
+	/**
102
+	 * The number of fixes that have been performed.
103
+	 *
104
+	 * @var integer
105
+	 */
106
+	private $numFixes = 0;
107
+
108
+
109
+	/**
110
+	 * Starts fixing a new file.
111
+	 *
112
+	 * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being fixed.
113
+	 *
114
+	 * @return void
115
+	 */
116
+	public function startFile(File $phpcsFile)
117
+	{
118
+		$this->currentFile = $phpcsFile;
119
+		$this->numFixes    = 0;
120
+		$this->fixedTokens = [];
121
+
122
+		$tokens       = $phpcsFile->getTokens();
123
+		$this->tokens = [];
124
+		foreach ($tokens as $index => $token) {
125
+			if (isset($token['orig_content']) === true) {
126
+				$this->tokens[$index] = $token['orig_content'];
127
+			} else {
128
+				$this->tokens[$index] = $token['content'];
129
+			}
130
+		}
131
+
132
+	}//end startFile()
133
+
134
+
135
+	/**
136
+	 * Attempt to fix the file by processing it until no fixes are made.
137
+	 *
138
+	 * @return boolean
139
+	 */
140
+	public function fixFile()
141
+	{
142
+		$fixable = $this->currentFile->getFixableCount();
143
+		if ($fixable === 0) {
144
+			// Nothing to fix.
145
+			return false;
146
+		}
147
+
148
+		$this->enabled = true;
149
+
150
+		$this->loops = 0;
151
+		while ($this->loops < 50) {
152
+			ob_start();
153
+
154
+			// Only needed once file content has changed.
155
+			$contents = $this->getContents();
156
+
157
+			if (PHP_CODESNIFFER_VERBOSITY > 2) {
158
+				@ob_end_clean();
159
+				echo '---START FILE CONTENT---'.PHP_EOL;
160
+				$lines = explode($this->currentFile->eolChar, $contents);
161
+				$max   = strlen(count($lines));
162
+				foreach ($lines as $lineNum => $line) {
163
+					$lineNum++;
164
+					echo str_pad($lineNum, $max, ' ', STR_PAD_LEFT).'|'.$line.PHP_EOL;
165
+				}
166
+
167
+				echo '--- END FILE CONTENT ---'.PHP_EOL;
168
+				ob_start();
169
+			}
170
+
171
+			$this->inConflict = false;
172
+			$this->currentFile->ruleset->populateTokenListeners();
173
+			$this->currentFile->setContent($contents);
174
+			$this->currentFile->process();
175
+			ob_end_clean();
176
+
177
+			$this->loops++;
178
+
179
+			if (PHP_CODESNIFFER_CBF === true && PHP_CODESNIFFER_VERBOSITY > 0) {
180
+				echo "\r".str_repeat(' ', 80)."\r";
181
+				echo "\t=> Fixing file: $this->numFixes/$fixable violations remaining [made $this->loops pass";
182
+				if ($this->loops > 1) {
183
+					echo 'es';
184
+				}
185
+
186
+				echo ']... ';
187
+				if (PHP_CODESNIFFER_VERBOSITY > 1) {
188
+					echo PHP_EOL;
189
+				}
190
+			}
191
+
192
+			if ($this->numFixes === 0 && $this->inConflict === false) {
193
+				// Nothing left to do.
194
+				break;
195
+			} else if (PHP_CODESNIFFER_VERBOSITY > 1) {
196
+				echo "\t* fixed $this->numFixes violations, starting loop ".($this->loops + 1).' *'.PHP_EOL;
197
+			}
198
+		}//end while
199
+
200
+		$this->enabled = false;
201
+
202
+		if ($this->numFixes > 0) {
203
+			if (PHP_CODESNIFFER_VERBOSITY > 1) {
204
+				if (ob_get_level() > 0) {
205
+					ob_end_clean();
206
+				}
207
+
208
+				echo "\t*** Reached maximum number of loops with $this->numFixes violations left unfixed ***".PHP_EOL;
209
+				ob_start();
210
+			}
211
+
212
+			return false;
213
+		}
214
+
215
+		return true;
216
+
217
+	}//end fixFile()
218
+
219
+
220
+	/**
221
+	 * Generates a text diff of the original file and the new content.
222
+	 *
223
+	 * @param string  $filePath Optional file path to diff the file against.
224
+	 *                          If not specified, the original version of the
225
+	 *                          file will be used.
226
+	 * @param boolean $colors   Print coloured output or not.
227
+	 *
228
+	 * @return string
229
+	 */
230
+	public function generateDiff($filePath=null, $colors=true)
231
+	{
232
+		if ($filePath === null) {
233
+			$filePath = $this->currentFile->getFilename();
234
+		}
235
+
236
+		$cwd = getcwd().DIRECTORY_SEPARATOR;
237
+		if (strpos($filePath, $cwd) === 0) {
238
+			$filename = substr($filePath, strlen($cwd));
239
+		} else {
240
+			$filename = $filePath;
241
+		}
242
+
243
+		$contents = $this->getContents();
244
+
245
+		$tempName  = tempnam(sys_get_temp_dir(), 'phpcs-fixer');
246
+		$fixedFile = fopen($tempName, 'w');
247
+		fwrite($fixedFile, $contents);
248
+
249
+		// We must use something like shell_exec() because whitespace at the end
250
+		// of lines is critical to diff files.
251
+		$filename = escapeshellarg($filename);
252
+		$cmd      = "diff -u -L$filename -LPHP_CodeSniffer $filename \"$tempName\"";
253
+
254
+		$diff = shell_exec($cmd);
255
+
256
+		fclose($fixedFile);
257
+		if (is_file($tempName) === true) {
258
+			unlink($tempName);
259
+		}
260
+
261
+		if ($diff === null) {
262
+			return '';
263
+		}
264
+
265
+		if ($colors === false) {
266
+			return $diff;
267
+		}
268
+
269
+		$diffLines = explode(PHP_EOL, $diff);
270
+		if (count($diffLines) === 1) {
271
+			// Seems to be required for cygwin.
272
+			$diffLines = explode("\n", $diff);
273
+		}
274
+
275
+		$diff = [];
276
+		foreach ($diffLines as $line) {
277
+			if (isset($line[0]) === true) {
278
+				switch ($line[0]) {
279
+				case '-':
280
+					$diff[] = "\033[31m$line\033[0m";
281
+					break;
282
+				case '+':
283
+					$diff[] = "\033[32m$line\033[0m";
284
+					break;
285
+				default:
286
+					$diff[] = $line;
287
+				}
288
+			}
289
+		}
290
+
291
+		$diff = implode(PHP_EOL, $diff);
292
+
293
+		return $diff;
294
+
295
+	}//end generateDiff()
296
+
297
+
298
+	/**
299
+	 * Get a count of fixes that have been performed on the file.
300
+	 *
301
+	 * This value is reset every time a new file is started, or an existing
302
+	 * file is restarted.
303
+	 *
304
+	 * @return int
305
+	 */
306
+	public function getFixCount()
307
+	{
308
+		return $this->numFixes;
309
+
310
+	}//end getFixCount()
311
+
312
+
313
+	/**
314
+	 * Get the current content of the file, as a string.
315
+	 *
316
+	 * @return string
317
+	 */
318
+	public function getContents()
319
+	{
320
+		$contents = implode($this->tokens);
321
+		return $contents;
322
+
323
+	}//end getContents()
324
+
325
+
326
+	/**
327
+	 * Get the current fixed content of a token.
328
+	 *
329
+	 * This function takes changesets into account so should be used
330
+	 * instead of directly accessing the token array.
331
+	 *
332
+	 * @param int $stackPtr The position of the token in the token stack.
333
+	 *
334
+	 * @return string
335
+	 */
336
+	public function getTokenContent($stackPtr)
337
+	{
338
+		if ($this->inChangeset === true
339
+			&& isset($this->changeset[$stackPtr]) === true
340
+		) {
341
+			return $this->changeset[$stackPtr];
342
+		} else {
343
+			return $this->tokens[$stackPtr];
344
+		}
345
+
346
+	}//end getTokenContent()
347
+
348
+
349
+	/**
350
+	 * Start recording actions for a changeset.
351
+	 *
352
+	 * @return void
353
+	 */
354
+	public function beginChangeset()
355
+	{
356
+		if ($this->inConflict === true) {
357
+			return false;
358
+		}
359
+
360
+		if (PHP_CODESNIFFER_VERBOSITY > 1) {
361
+			$bt = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
362
+			if ($bt[1]['class'] === __CLASS__) {
363
+				$sniff = 'Fixer';
364
+			} else {
365
+				$sniff = Util\Common::getSniffCode($bt[1]['class']);
366
+			}
367
+
368
+			$line = $bt[0]['line'];
369
+
370
+			@ob_end_clean();
371
+			echo "\t=> Changeset started by $sniff:$line".PHP_EOL;
372
+			ob_start();
373
+		}
374
+
375
+		$this->changeset   = [];
376
+		$this->inChangeset = true;
377
+
378
+	}//end beginChangeset()
379
+
380
+
381
+	/**
382
+	 * Stop recording actions for a changeset, and apply logged changes.
383
+	 *
384
+	 * @return boolean
385
+	 */
386
+	public function endChangeset()
387
+	{
388
+		if ($this->inConflict === true) {
389
+			return false;
390
+		}
391
+
392
+		$this->inChangeset = false;
393
+
394
+		$success = true;
395
+		$applied = [];
396
+		foreach ($this->changeset as $stackPtr => $content) {
397
+			$success = $this->replaceToken($stackPtr, $content);
398
+			if ($success === false) {
399
+				break;
400
+			} else {
401
+				$applied[] = $stackPtr;
402
+			}
403
+		}
404
+
405
+		if ($success === false) {
406
+			// Rolling back all changes.
407
+			foreach ($applied as $stackPtr) {
408
+				$this->revertToken($stackPtr);
409
+			}
410
+
411
+			if (PHP_CODESNIFFER_VERBOSITY > 1) {
412
+				@ob_end_clean();
413
+				echo "\t=> Changeset failed to apply".PHP_EOL;
414
+				ob_start();
415
+			}
416
+		} else if (PHP_CODESNIFFER_VERBOSITY > 1) {
417
+			$fixes = count($this->changeset);
418
+			@ob_end_clean();
419
+			echo "\t=> Changeset ended: $fixes changes applied".PHP_EOL;
420
+			ob_start();
421
+		}
422
+
423
+		$this->changeset = [];
424
+		return true;
425
+
426
+	}//end endChangeset()
427
+
428
+
429
+	/**
430
+	 * Stop recording actions for a changeset, and discard logged changes.
431
+	 *
432
+	 * @return void
433
+	 */
434
+	public function rollbackChangeset()
435
+	{
436
+		$this->inChangeset = false;
437
+		$this->inConflict  = false;
438
+
439
+		if (empty($this->changeset) === false) {
440
+			if (PHP_CODESNIFFER_VERBOSITY > 1) {
441
+				$bt = debug_backtrace();
442
+				if ($bt[1]['class'] === 'PHP_CodeSniffer\Fixer') {
443
+					$sniff = $bt[2]['class'];
444
+					$line  = $bt[1]['line'];
445
+				} else {
446
+					$sniff = $bt[1]['class'];
447
+					$line  = $bt[0]['line'];
448
+				}
449
+
450
+				$sniff = Util\Common::getSniffCode($sniff);
451
+
452
+				$numChanges = count($this->changeset);
453
+
454
+				@ob_end_clean();
455
+				echo "\t\tR: $sniff:$line rolled back the changeset ($numChanges changes)".PHP_EOL;
456
+				echo "\t=> Changeset rolled back".PHP_EOL;
457
+				ob_start();
458
+			}
459
+
460
+			$this->changeset = [];
461
+		}//end if
462
+
463
+	}//end rollbackChangeset()
464
+
465
+
466
+	/**
467
+	 * Replace the entire contents of a token.
468
+	 *
469
+	 * @param int    $stackPtr The position of the token in the token stack.
470
+	 * @param string $content  The new content of the token.
471
+	 *
472
+	 * @return bool If the change was accepted.
473
+	 */
474
+	public function replaceToken($stackPtr, $content)
475
+	{
476
+		if ($this->inConflict === true) {
477
+			return false;
478
+		}
479
+
480
+		if ($this->inChangeset === false
481
+			&& isset($this->fixedTokens[$stackPtr]) === true
482
+		) {
483
+			$indent = "\t";
484
+			if (empty($this->changeset) === false) {
485
+				$indent .= "\t";
486
+			}
487
+
488
+			if (PHP_CODESNIFFER_VERBOSITY > 1) {
489
+				@ob_end_clean();
490
+				echo "$indent* token $stackPtr has already been modified, skipping *".PHP_EOL;
491
+				ob_start();
492
+			}
493
+
494
+			return false;
495
+		}
496
+
497
+		if (PHP_CODESNIFFER_VERBOSITY > 1) {
498
+			$bt = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
499
+			if ($bt[1]['class'] === 'PHP_CodeSniffer\Fixer') {
500
+				$sniff = $bt[2]['class'];
501
+				$line  = $bt[1]['line'];
502
+			} else {
503
+				$sniff = $bt[1]['class'];
504
+				$line  = $bt[0]['line'];
505
+			}
506
+
507
+			$sniff = Util\Common::getSniffCode($sniff);
508
+
509
+			$tokens     = $this->currentFile->getTokens();
510
+			$type       = $tokens[$stackPtr]['type'];
511
+			$tokenLine  = $tokens[$stackPtr]['line'];
512
+			$oldContent = Common::prepareForOutput($this->tokens[$stackPtr]);
513
+			$newContent = Common::prepareForOutput($content);
514
+			if (trim($this->tokens[$stackPtr]) === '' && isset($this->tokens[($stackPtr + 1)]) === true) {
515
+				// Add some context for whitespace only changes.
516
+				$append      = Common::prepareForOutput($this->tokens[($stackPtr + 1)]);
517
+				$oldContent .= $append;
518
+				$newContent .= $append;
519
+			}
520
+		}//end if
521
+
522
+		if ($this->inChangeset === true) {
523
+			$this->changeset[$stackPtr] = $content;
524
+
525
+			if (PHP_CODESNIFFER_VERBOSITY > 1) {
526
+				@ob_end_clean();
527
+				echo "\t\tQ: $sniff:$line replaced token $stackPtr ($type on line $tokenLine) \"$oldContent\" => \"$newContent\"".PHP_EOL;
528
+				ob_start();
529
+			}
530
+
531
+			return true;
532
+		}
533
+
534
+		if (isset($this->oldTokenValues[$stackPtr]) === false) {
535
+			$this->oldTokenValues[$stackPtr] = [
536
+				'curr' => $content,
537
+				'prev' => $this->tokens[$stackPtr],
538
+				'loop' => $this->loops,
539
+			];
540
+		} else {
541
+			if ($this->oldTokenValues[$stackPtr]['prev'] === $content
542
+				&& $this->oldTokenValues[$stackPtr]['loop'] === ($this->loops - 1)
543
+			) {
544
+				if (PHP_CODESNIFFER_VERBOSITY > 1) {
545
+					$indent = "\t";
546
+					if (empty($this->changeset) === false) {
547
+						$indent .= "\t";
548
+					}
549
+
550
+					$loop = $this->oldTokenValues[$stackPtr]['loop'];
551
+
552
+					@ob_end_clean();
553
+					echo "$indent**** $sniff:$line has possible conflict with another sniff on loop $loop; caused by the following change ****".PHP_EOL;
554
+					echo "$indent**** replaced token $stackPtr ($type on line $tokenLine) \"$oldContent\" => \"$newContent\" ****".PHP_EOL;
555
+				}
556
+
557
+				if ($this->oldTokenValues[$stackPtr]['loop'] >= ($this->loops - 1)) {
558
+					$this->inConflict = true;
559
+					if (PHP_CODESNIFFER_VERBOSITY > 1) {
560
+						echo "$indent**** ignoring all changes until next loop ****".PHP_EOL;
561
+					}
562
+				}
563
+
564
+				if (PHP_CODESNIFFER_VERBOSITY > 1) {
565
+					ob_start();
566
+				}
567
+
568
+				return false;
569
+			}//end if
570
+
571
+			$this->oldTokenValues[$stackPtr]['prev'] = $this->oldTokenValues[$stackPtr]['curr'];
572
+			$this->oldTokenValues[$stackPtr]['curr'] = $content;
573
+			$this->oldTokenValues[$stackPtr]['loop'] = $this->loops;
574
+		}//end if
575
+
576
+		$this->fixedTokens[$stackPtr] = $this->tokens[$stackPtr];
577
+		$this->tokens[$stackPtr]      = $content;
578
+		$this->numFixes++;
579
+
580
+		if (PHP_CODESNIFFER_VERBOSITY > 1) {
581
+			$indent = "\t";
582
+			if (empty($this->changeset) === false) {
583
+				$indent .= "\tA: ";
584
+			}
585
+
586
+			if (ob_get_level() > 0) {
587
+				ob_end_clean();
588
+			}
589
+
590
+			echo "$indent$sniff:$line replaced token $stackPtr ($type on line $tokenLine) \"$oldContent\" => \"$newContent\"".PHP_EOL;
591
+			ob_start();
592
+		}
593
+
594
+		return true;
595
+
596
+	}//end replaceToken()
597
+
598
+
599
+	/**
600
+	 * Reverts the previous fix made to a token.
601
+	 *
602
+	 * @param int $stackPtr The position of the token in the token stack.
603
+	 *
604
+	 * @return bool If a change was reverted.
605
+	 */
606
+	public function revertToken($stackPtr)
607
+	{
608
+		if (isset($this->fixedTokens[$stackPtr]) === false) {
609
+			return false;
610
+		}
611
+
612
+		if (PHP_CODESNIFFER_VERBOSITY > 1) {
613
+			$bt = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
614
+			if ($bt[1]['class'] === 'PHP_CodeSniffer\Fixer') {
615
+				$sniff = $bt[2]['class'];
616
+				$line  = $bt[1]['line'];
617
+			} else {
618
+				$sniff = $bt[1]['class'];
619
+				$line  = $bt[0]['line'];
620
+			}
621
+
622
+			$sniff = Util\Common::getSniffCode($sniff);
623
+
624
+			$tokens     = $this->currentFile->getTokens();
625
+			$type       = $tokens[$stackPtr]['type'];
626
+			$tokenLine  = $tokens[$stackPtr]['line'];
627
+			$oldContent = Common::prepareForOutput($this->tokens[$stackPtr]);
628
+			$newContent = Common::prepareForOutput($this->fixedTokens[$stackPtr]);
629
+			if (trim($this->tokens[$stackPtr]) === '' && isset($tokens[($stackPtr + 1)]) === true) {
630
+				// Add some context for whitespace only changes.
631
+				$append      = Common::prepareForOutput($this->tokens[($stackPtr + 1)]);
632
+				$oldContent .= $append;
633
+				$newContent .= $append;
634
+			}
635
+		}//end if
636
+
637
+		$this->tokens[$stackPtr] = $this->fixedTokens[$stackPtr];
638
+		unset($this->fixedTokens[$stackPtr]);
639
+		$this->numFixes--;
640
+
641
+		if (PHP_CODESNIFFER_VERBOSITY > 1) {
642
+			$indent = "\t";
643
+			if (empty($this->changeset) === false) {
644
+				$indent .= "\tR: ";
645
+			}
646
+
647
+			@ob_end_clean();
648
+			echo "$indent$sniff:$line reverted token $stackPtr ($type on line $tokenLine) \"$oldContent\" => \"$newContent\"".PHP_EOL;
649
+			ob_start();
650
+		}
651
+
652
+		return true;
653
+
654
+	}//end revertToken()
655
+
656
+
657
+	/**
658
+	 * Replace the content of a token with a part of its current content.
659
+	 *
660
+	 * @param int $stackPtr The position of the token in the token stack.
661
+	 * @param int $start    The first character to keep.
662
+	 * @param int $length   The number of characters to keep. If NULL, the content of
663
+	 *                      the token from $start to the end of the content is kept.
664
+	 *
665
+	 * @return bool If the change was accepted.
666
+	 */
667
+	public function substrToken($stackPtr, $start, $length=null)
668
+	{
669
+		$current = $this->getTokenContent($stackPtr);
670
+
671
+		if ($length === null) {
672
+			$newContent = substr($current, $start);
673
+		} else {
674
+			$newContent = substr($current, $start, $length);
675
+		}
676
+
677
+		return $this->replaceToken($stackPtr, $newContent);
678
+
679
+	}//end substrToken()
680
+
681
+
682
+	/**
683
+	 * Adds a newline to end of a token's content.
684
+	 *
685
+	 * @param int $stackPtr The position of the token in the token stack.
686
+	 *
687
+	 * @return bool If the change was accepted.
688
+	 */
689
+	public function addNewline($stackPtr)
690
+	{
691
+		$current = $this->getTokenContent($stackPtr);
692
+		return $this->replaceToken($stackPtr, $current.$this->currentFile->eolChar);
693
+
694
+	}//end addNewline()
695
+
696
+
697
+	/**
698
+	 * Adds a newline to the start of a token's content.
699
+	 *
700
+	 * @param int $stackPtr The position of the token in the token stack.
701
+	 *
702
+	 * @return bool If the change was accepted.
703
+	 */
704
+	public function addNewlineBefore($stackPtr)
705
+	{
706
+		$current = $this->getTokenContent($stackPtr);
707
+		return $this->replaceToken($stackPtr, $this->currentFile->eolChar.$current);
708
+
709
+	}//end addNewlineBefore()
710
+
711
+
712
+	/**
713
+	 * Adds content to the end of a token's current content.
714
+	 *
715
+	 * @param int    $stackPtr The position of the token in the token stack.
716
+	 * @param string $content  The content to add.
717
+	 *
718
+	 * @return bool If the change was accepted.
719
+	 */
720
+	public function addContent($stackPtr, $content)
721
+	{
722
+		$current = $this->getTokenContent($stackPtr);
723
+		return $this->replaceToken($stackPtr, $current.$content);
724
+
725
+	}//end addContent()
726
+
727
+
728
+	/**
729
+	 * Adds content to the start of a token's current content.
730
+	 *
731
+	 * @param int    $stackPtr The position of the token in the token stack.
732
+	 * @param string $content  The content to add.
733
+	 *
734
+	 * @return bool If the change was accepted.
735
+	 */
736
+	public function addContentBefore($stackPtr, $content)
737
+	{
738
+		$current = $this->getTokenContent($stackPtr);
739
+		return $this->replaceToken($stackPtr, $content.$current);
740
+
741
+	}//end addContentBefore()
742
+
743
+
744
+	/**
745
+	 * Adjust the indent of a code block.
746
+	 *
747
+	 * @param int $start  The position of the token in the token stack
748
+	 *                    to start adjusting the indent from.
749
+	 * @param int $end    The position of the token in the token stack
750
+	 *                    to end adjusting the indent.
751
+	 * @param int $change The number of spaces to adjust the indent by
752
+	 *                    (positive or negative).
753
+	 *
754
+	 * @return void
755
+	 */
756
+	public function changeCodeBlockIndent($start, $end, $change)
757
+	{
758
+		$tokens = $this->currentFile->getTokens();
759
+
760
+		$baseIndent = '';
761
+		if ($change > 0) {
762
+			$baseIndent = str_repeat(' ', $change);
763
+		}
764
+
765
+		$useChangeset = false;
766
+		if ($this->inChangeset === false) {
767
+			$this->beginChangeset();
768
+			$useChangeset = true;
769
+		}
770
+
771
+		for ($i = $start; $i <= $end; $i++) {
772
+			if ($tokens[$i]['column'] !== 1
773
+				|| $tokens[($i + 1)]['line'] !== $tokens[$i]['line']
774
+			) {
775
+				continue;
776
+			}
777
+
778
+			$length = 0;
779
+			if ($tokens[$i]['code'] === T_WHITESPACE
780
+				|| $tokens[$i]['code'] === T_DOC_COMMENT_WHITESPACE
781
+			) {
782
+				$length = $tokens[$i]['length'];
783
+
784
+				$padding = ($length + $change);
785
+				if ($padding > 0) {
786
+					$padding = str_repeat(' ', $padding);
787
+				} else {
788
+					$padding = '';
789
+				}
790
+
791
+				$newContent = $padding.ltrim($tokens[$i]['content']);
792
+			} else {
793
+				$newContent = $baseIndent.$tokens[$i]['content'];
794
+			}
795
+
796
+			$this->replaceToken($i, $newContent);
797
+		}//end for
798
+
799
+		if ($useChangeset === true) {
800
+			$this->endChangeset();
801
+		}
802
+
803
+	}//end changeCodeBlockIndent()
804 804
 
805 805
 
806 806
 }//end class
Please login to merge, or discard this patch.
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.