diff --git a/.github/CONTRIBUTING.md b/.github/CONTRIBUTING.md index 03a5ae5b39..95f5dd7d4d 100644 --- a/.github/CONTRIBUTING.md +++ b/.github/CONTRIBUTING.md @@ -386,6 +386,13 @@ To run the tests specific to the use of `PHP_CODESNIFFER_CBF === true`: In such cases, the `PHP_CodeSniffer\Tests\Core\Config\AbstractRealConfigTestCase` should be used as the base test class. * Tests for the `Runner` class often can't create their own `Config` object in the tests, so run into the same issue. Those tests should use the `PHP_CodeSniffer\Tests\Core\Runner\AbstractRunnerTestCase` base class, which will ensure the Config is clean. +* Testing output sent to `stdErr` via the `StatusWriter` class is not possible by default using PHPUnit. + A work-around is available, however, as the `StatusWriter` is a "static class", that work-around involves static properties which need to be (re-)set between tests to ensure tests are pure. + So, to test output sent to `stdErr` via the `StatusWriter`, use the `PHP_CodeSniffer\Tests\Core\AbstractWriterTestCase` base class if your tests do not need their own `setUp()` and `tearDown()` methods. + If your tests **_do_** need their own `setUp()` and `tearDown()` methods, or would benefit more from using one of the other base TestCase classes, use the `PHP_CodeSniffer\Tests\Core\StatusWriterTestHelper` trait and call the appropriate setup/teardown helper methods from within your own `setUp()` and `tearDown()` methods. + Tests using the `AbstractWriterTestCase` class or the trait, also get access to the following test helpers for use when testing output sent to `stdErr`: `expectNoStdoutOutput()`, `assertStderrOutputSameString($expected)` and `assertStderrOutputMatchesRegex($regex)`. + Generally speaking, it is a good idea to always add a call to `expectNoStdoutOutput()` in any test using the `assertStderrOutput*()` assertions to make sure there is no output leaking to `stdOut`. + ### Submitting Your Pull Request diff --git a/requirements.php b/requirements.php index c15cd6524b..9b27e11f2d 100644 --- a/requirements.php +++ b/requirements.php @@ -33,7 +33,8 @@ function checkRequirements() // Check the PHP version. if (PHP_VERSION_ID < 70200) { - echo 'ERROR: PHP_CodeSniffer requires PHP version 7.2.0 or greater.'.PHP_EOL; + $error = 'ERROR: PHP_CodeSniffer requires PHP version 7.2.0 or greater.'.PHP_EOL; + fwrite(STDERR, $error); exit($exitCode); } @@ -64,7 +65,7 @@ function checkRequirements() } $error = 'ERROR: PHP_CodeSniffer requires the %s extensions to be enabled. Please enable %s.'.PHP_EOL; - printf($error, $required, $missing); + fwrite(STDERR, sprintf($error, $required, $missing)); exit($exitCode); } diff --git a/src/Files/File.php b/src/Files/File.php index 5a6f82b8ba..717e46aab6 100644 --- a/src/Files/File.php +++ b/src/Files/File.php @@ -17,6 +17,7 @@ use PHP_CodeSniffer\Tokenizers\PHP; use PHP_CodeSniffer\Util\Common; use PHP_CodeSniffer\Util\Tokens; +use PHP_CodeSniffer\Util\Writers\StatusWriter; class File { @@ -324,7 +325,7 @@ public function process() $this->fixer->startFile($this); if (PHP_CODESNIFFER_VERBOSITY > 2) { - echo "\t*** START TOKEN PROCESSING ***".PHP_EOL; + StatusWriter::write('*** START TOKEN PROCESSING ***', 1); } $foundCode = false; @@ -377,7 +378,7 @@ public function process() if (PHP_CODESNIFFER_VERBOSITY > 2) { $type = $token['type']; $content = Common::prepareForOutput($token['content']); - echo "\t\tProcess token $stackPtr: $type => $content".PHP_EOL; + StatusWriter::write("Process token $stackPtr: $type => $content", 2); } if ($token['code'] !== T_INLINE_HTML) { @@ -452,7 +453,7 @@ public function process() } if (PHP_CODESNIFFER_VERBOSITY > 2) { - echo "\t\t\tProcessing ".$this->activeListener.'... '; + StatusWriter::write('Processing '.$this->activeListener.'... ', 3, 0); } $ignoreTo = $this->ruleset->sniffs[$class]->process($this, $stackPtr); @@ -471,7 +472,7 @@ public function process() if (PHP_CODESNIFFER_VERBOSITY > 2) { $timeTaken = round(($timeTaken), 4); - echo "DONE in $timeTaken seconds".PHP_EOL; + StatusWriter::write("DONE in $timeTaken seconds"); } $this->activeListener = ''; @@ -493,15 +494,15 @@ public function process() } if (PHP_CODESNIFFER_VERBOSITY > 2) { - echo "\t*** END TOKEN PROCESSING ***".PHP_EOL; - echo "\t*** START SNIFF PROCESSING REPORT ***".PHP_EOL; + StatusWriter::write('*** END TOKEN PROCESSING ***', 1); + StatusWriter::write('*** START SNIFF PROCESSING REPORT ***', 1); arsort($this->listenerTimes, SORT_NUMERIC); foreach ($this->listenerTimes as $listener => $timeTaken) { - echo "\t$listener: ".round(($timeTaken), 4).' secs'.PHP_EOL; + StatusWriter::write("$listener: ".round(($timeTaken), 4).' secs', 1); } - echo "\t*** END SNIFF PROCESSING REPORT ***".PHP_EOL; + StatusWriter::write('*** END SNIFF PROCESSING REPORT ***', 1); } $this->fixedCount += $this->fixer->getFixCount(); @@ -528,10 +529,12 @@ public function parse() $this->ignored = true; $this->addWarning($e->getMessage(), null, 'Internal.Tokenizer.Exception'); if (PHP_CODESNIFFER_VERBOSITY > 0) { - echo '[tokenizer error]... '; + $newlines = 0; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo PHP_EOL; + $newlines = 1; } + + StatusWriter::write('[tokenizer error]... ', 0, $newlines); } return; @@ -560,10 +563,12 @@ public function parse() $numLines = $this->tokens[($this->numTokens - 1)]['line']; } - echo "[$this->numTokens tokens in $numLines lines]... "; + $newlines = 0; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo PHP_EOL; + $newlines = 1; } + + StatusWriter::write("[$this->numTokens tokens in $numLines lines]... ", 0, $newlines); } }//end parse() @@ -1043,7 +1048,7 @@ protected function addMessage($error, $message, $line, $column, $code, $data, $s && $fixable === true ) { @ob_end_clean(); - echo "\tE: [Line $line] $message ($sniffCode)".PHP_EOL; + StatusWriter::forceWrite("E: [Line $line] $message ($sniffCode)", 1); ob_start(); } diff --git a/src/Files/LocalFile.php b/src/Files/LocalFile.php index d937c2ad7c..140d6be910 100644 --- a/src/Files/LocalFile.php +++ b/src/Files/LocalFile.php @@ -13,6 +13,7 @@ use PHP_CodeSniffer\Ruleset; use PHP_CodeSniffer\Util\Cache; use PHP_CodeSniffer\Util\Common; +use PHP_CodeSniffer\Util\Writers\StatusWriter; class LocalFile extends File { @@ -113,7 +114,7 @@ public function process() if (PHP_CODESNIFFER_VERBOSITY > 0 || (PHP_CODESNIFFER_CBF === true && empty($this->config->files) === false) ) { - echo "[loaded from cache]... "; + StatusWriter::write('[loaded from cache]... ', 0, 0); } $this->numTokens = $cache['numTokens']; @@ -122,7 +123,7 @@ public function process() }//end if if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo PHP_EOL; + StatusWriter::writeNewline(); } parent::process(); diff --git a/src/Fixer.php b/src/Fixer.php index 093e4fce5d..709d193aa1 100644 --- a/src/Fixer.php +++ b/src/Fixer.php @@ -16,6 +16,7 @@ use PHP_CodeSniffer\Exceptions\RuntimeException; use PHP_CodeSniffer\Files\File; use PHP_CodeSniffer\Util\Common; +use PHP_CodeSniffer\Util\Writers\StatusWriter; class Fixer { @@ -149,6 +150,9 @@ public function fixFile() $this->enabled = true; + // Pause the StatusWriter to silence Tokenizer debug info about the file being retokenized for each loop. + StatusWriter::pause(); + $this->loops = 0; while ($this->loops < 50) { ob_start(); @@ -158,15 +162,15 @@ public function fixFile() if (PHP_CODESNIFFER_VERBOSITY > 2) { @ob_end_clean(); - echo '---START FILE CONTENT---'.PHP_EOL; + StatusWriter::forceWrite('---START FILE CONTENT---'); $lines = explode($this->currentFile->eolChar, $contents); $max = strlen(count($lines)); foreach ($lines as $lineNum => $line) { $lineNum++; - echo str_pad($lineNum, $max, ' ', STR_PAD_LEFT).'|'.$line.PHP_EOL; + StatusWriter::forceWrite(str_pad($lineNum, $max, ' ', STR_PAD_LEFT).'|'.$line); } - echo '--- END FILE CONTENT ---'.PHP_EOL; + StatusWriter::forceWrite('--- END FILE CONTENT ---'); ob_start(); } @@ -179,35 +183,40 @@ public function fixFile() $this->loops++; if (PHP_CODESNIFFER_CBF === true && PHP_CODESNIFFER_VERBOSITY > 0) { - echo "\r".str_repeat(' ', 80)."\r"; - echo "\t=> Fixing file: $this->numFixes/$fixable violations remaining [made $this->loops pass"; + StatusWriter::forceWrite("\r".str_repeat(' ', 80)."\r", 0, 0); + $statusMessage = "=> Fixing file: $this->numFixes/$fixable violations remaining [made $this->loops pass"; if ($this->loops > 1) { - echo 'es'; + $statusMessage .= 'es'; } - echo ']... '; + $statusMessage .= ']... '; + $newlines = 0; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo PHP_EOL; + $newlines = 1; } + + StatusWriter::forceWrite($statusMessage, 1, $newlines); } if ($this->numFixes === 0 && $this->inConflict === false) { // Nothing left to do. break; } else if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo "\t* fixed $this->numFixes violations, starting loop ".($this->loops + 1).' *'.PHP_EOL; + StatusWriter::forceWrite("* fixed $this->numFixes violations, starting loop ".($this->loops + 1).' *', 1); } }//end while $this->enabled = false; + StatusWriter::resume(); + if ($this->numFixes > 0) { if (PHP_CODESNIFFER_VERBOSITY > 1) { if (ob_get_level() > 0) { ob_end_clean(); } - echo "\t*** Reached maximum number of loops with $this->numFixes violations left unfixed ***".PHP_EOL; + StatusWriter::write("*** Reached maximum number of loops with $this->numFixes violations left unfixed ***", 1); ob_start(); } @@ -409,7 +418,7 @@ public function beginChangeset() $line = $bt[0]['line']; @ob_end_clean(); - echo "\t=> Changeset started by $sniff:$line".PHP_EOL; + StatusWriter::forceWrite("=> Changeset started by $sniff:$line", 1); ob_start(); } @@ -451,13 +460,13 @@ public function endChangeset() if (PHP_CODESNIFFER_VERBOSITY > 1) { @ob_end_clean(); - echo "\t=> Changeset failed to apply".PHP_EOL; + StatusWriter::forceWrite('=> Changeset failed to apply', 1); ob_start(); } } else if (PHP_CODESNIFFER_VERBOSITY > 1) { $fixes = count($this->changeset); @ob_end_clean(); - echo "\t=> Changeset ended: $fixes changes applied".PHP_EOL; + StatusWriter::forceWrite("=> Changeset ended: $fixes changes applied", 1); ob_start(); } @@ -493,8 +502,8 @@ public function rollbackChangeset() $numChanges = count($this->changeset); @ob_end_clean(); - echo "\t\tR: $sniff:$line rolled back the changeset ($numChanges changes)".PHP_EOL; - echo "\t=> Changeset rolled back".PHP_EOL; + StatusWriter::forceWrite("R: $sniff:$line rolled back the changeset ($numChanges changes)", 2); + StatusWriter::forceWrite('=> Changeset rolled back', 1); ob_start(); } @@ -521,14 +530,14 @@ public function replaceToken($stackPtr, $content) if ($this->inChangeset === false && isset($this->fixedTokens[$stackPtr]) === true ) { - $indent = "\t"; + $depth = 1; if (empty($this->changeset) === false) { - $indent .= "\t"; + $depth = 2; } if (PHP_CODESNIFFER_VERBOSITY > 1) { @ob_end_clean(); - echo "$indent* token $stackPtr has already been modified, skipping *".PHP_EOL; + StatusWriter::forceWrite("* token $stackPtr has already been modified, skipping *", $depth); ob_start(); } @@ -565,7 +574,7 @@ public function replaceToken($stackPtr, $content) if (PHP_CODESNIFFER_VERBOSITY > 1) { @ob_end_clean(); - echo "\t\tQ: $sniff:$line replaced token $stackPtr ($type on line $tokenLine) \"$oldContent\" => \"$newContent\"".PHP_EOL; + StatusWriter::forceWrite("Q: $sniff:$line replaced token $stackPtr ($type on line $tokenLine) \"$oldContent\" => \"$newContent\"", 2); ob_start(); } @@ -583,22 +592,22 @@ public function replaceToken($stackPtr, $content) && $this->oldTokenValues[$stackPtr]['loop'] === ($this->loops - 1) ) { if (PHP_CODESNIFFER_VERBOSITY > 1) { - $indent = "\t"; + $depth = 1; if (empty($this->changeset) === false) { - $indent .= "\t"; + $depth = 2; } $loop = $this->oldTokenValues[$stackPtr]['loop']; @ob_end_clean(); - echo "$indent**** $sniff:$line has possible conflict with another sniff on loop $loop; caused by the following change ****".PHP_EOL; - echo "$indent**** replaced token $stackPtr ($type on line $tokenLine) \"$oldContent\" => \"$newContent\" ****".PHP_EOL; + StatusWriter::forceWrite("**** $sniff:$line has possible conflict with another sniff on loop $loop; caused by the following change ****", $depth); + StatusWriter::forceWrite("**** replaced token $stackPtr ($type on line $tokenLine) \"$oldContent\" => \"$newContent\" ****", $depth); } if ($this->oldTokenValues[$stackPtr]['loop'] >= ($this->loops - 1)) { $this->inConflict = true; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo "$indent**** ignoring all changes until next loop ****".PHP_EOL; + StatusWriter::forceWrite('**** ignoring all changes until next loop ****', $depth); } } @@ -619,16 +628,18 @@ public function replaceToken($stackPtr, $content) $this->numFixes++; if (PHP_CODESNIFFER_VERBOSITY > 1) { - $indent = "\t"; + $statusMessage = "$sniff:$line replaced token $stackPtr ($type on line $tokenLine) \"$oldContent\" => \"$newContent\""; + $depth = 1; if (empty($this->changeset) === false) { - $indent .= "\tA: "; + $statusMessage = 'A: '.$statusMessage; + $depth = 2; } if (ob_get_level() > 0) { ob_end_clean(); } - echo "$indent$sniff:$line replaced token $stackPtr ($type on line $tokenLine) \"$oldContent\" => \"$newContent\"".PHP_EOL; + StatusWriter::forceWrite($statusMessage, $depth); ob_start(); } @@ -680,13 +691,15 @@ public function revertToken($stackPtr) $this->numFixes--; if (PHP_CODESNIFFER_VERBOSITY > 1) { - $indent = "\t"; + $statusMessage = "$sniff:$line reverted token $stackPtr ($type on line $tokenLine) \"$oldContent\" => \"$newContent\""; + $depth = 1; if (empty($this->changeset) === false) { - $indent .= "\tR: "; + $statusMessage = 'R: '.$statusMessage; + $depth = 2; } @ob_end_clean(); - echo "$indent$sniff:$line reverted token $stackPtr ($type on line $tokenLine) \"$oldContent\" => \"$newContent\"".PHP_EOL; + StatusWriter::forceWrite($statusMessage, $depth); ob_start(); } diff --git a/src/Reports/Cbf.php b/src/Reports/Cbf.php index 9f2ba84061..21662e7d1e 100644 --- a/src/Reports/Cbf.php +++ b/src/Reports/Cbf.php @@ -16,6 +16,7 @@ use PHP_CodeSniffer\Exceptions\DeepExitException; use PHP_CodeSniffer\Files\File; use PHP_CodeSniffer\Util\Timing; +use PHP_CodeSniffer\Util\Writers\StatusWriter; class Cbf implements Report { @@ -44,10 +45,12 @@ public function generateFileReport($report, File $phpcsFile, $showSources=false, if (PHP_CODESNIFFER_VERBOSITY > 0) { ob_end_clean(); $startTime = microtime(true); - echo "\t=> Fixing file: $errors/$errors violations remaining"; + $newlines = 0; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo PHP_EOL; + $newlines = 1; } + + StatusWriter::forceWrite("=> Fixing file: $errors/$errors violations remaining", 1, $newlines); } $fixed = $phpcsFile->fixer->fixFile(); @@ -67,18 +70,18 @@ public function generateFileReport($report, File $phpcsFile, $showSources=false, if (PHP_CODESNIFFER_VERBOSITY > 0) { if ($fixed === false) { - echo 'ERROR'; + StatusWriter::forceWrite('ERROR', 0, 0); } else { - echo 'DONE'; + StatusWriter::forceWrite('DONE', 0, 0); } $timeTaken = ((microtime(true) - $startTime) * 1000); if ($timeTaken < 1000) { $timeTaken = round($timeTaken); - echo " in {$timeTaken}ms".PHP_EOL; + StatusWriter::forceWrite(" in {$timeTaken}ms"); } else { $timeTaken = round(($timeTaken / 1000), 2); - echo " in $timeTaken secs".PHP_EOL; + StatusWriter::forceWrite(" in $timeTaken secs"); } } @@ -96,9 +99,9 @@ public function generateFileReport($report, File $phpcsFile, $showSources=false, if (PHP_CODESNIFFER_VERBOSITY > 0) { if ($newFilename === $report['filename']) { - echo "\t=> File was overwritten".PHP_EOL; + StatusWriter::forceWrite('=> File was overwritten', 1); } else { - echo "\t=> Fixed file written to ".basename($newFilename).PHP_EOL; + StatusWriter::forceWrite('=> Fixed file written to '.basename($newFilename), 1); } } } @@ -150,9 +153,11 @@ public function generate( if (empty($lines) === true) { if (($totalErrors + $totalWarnings) === 0) { - echo PHP_EOL.'No violations were found'.PHP_EOL; + StatusWriter::writeNewline(); + StatusWriter::write('No violations were found'); } else { - echo PHP_EOL.'No fixable errors were found'.PHP_EOL; + StatusWriter::writeNewline(); + StatusWriter::write('No fixable errors were found'); } return; diff --git a/src/Reports/Code.php b/src/Reports/Code.php index 18aaf1e144..20dda6faef 100644 --- a/src/Reports/Code.php +++ b/src/Reports/Code.php @@ -13,6 +13,7 @@ use PHP_CodeSniffer\Files\File; use PHP_CodeSniffer\Util\Common; use PHP_CodeSniffer\Util\Timing; +use PHP_CodeSniffer\Util\Writers\StatusWriter; class Code implements Report { @@ -48,9 +49,9 @@ public function generateFileReport($report, File $phpcsFile, $showSources=false, if (empty($tokens) === true) { if (PHP_CODESNIFFER_VERBOSITY === 1) { $startTime = microtime(true); - echo 'CODE report is parsing '.basename($file).' '; + StatusWriter::forceWrite('CODE report is parsing '.basename($file).' ', 0, 0); } else if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo "CODE report is forcing parse of $file".PHP_EOL; + StatusWriter::forceWrite("CODE report is forcing parse of $file"); } try { @@ -68,13 +69,11 @@ public function generateFileReport($report, File $phpcsFile, $showSources=false, $timeTaken = ((microtime(true) - $startTime) * 1000); if ($timeTaken < 1000) { $timeTaken = round($timeTaken); - echo "DONE in {$timeTaken}ms"; + StatusWriter::forceWrite("DONE in {$timeTaken}ms"); } else { $timeTaken = round(($timeTaken / 1000), 2); - echo "DONE in $timeTaken secs"; + StatusWriter::forceWrite("DONE in $timeTaken secs"); } - - echo PHP_EOL; } $tokens = $phpcsFile->getTokens(); diff --git a/src/Reports/Diff.php b/src/Reports/Diff.php index 9580b4e977..8ed45765ce 100644 --- a/src/Reports/Diff.php +++ b/src/Reports/Diff.php @@ -10,6 +10,7 @@ namespace PHP_CodeSniffer\Reports; use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Util\Writers\StatusWriter; class Diff implements Report { @@ -42,9 +43,9 @@ public function generateFileReport($report, File $phpcsFile, $showSources=false, if (empty($tokens) === true) { if (PHP_CODESNIFFER_VERBOSITY === 1) { $startTime = microtime(true); - echo 'DIFF report is parsing '.basename($report['filename']).' '; + StatusWriter::write('DIFF report is parsing '.basename($report['filename']).' ', 0, 0); } else if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo 'DIFF report is forcing parse of '.$report['filename'].PHP_EOL; + StatusWriter::write('DIFF report is forcing parse of '.$report['filename']); } $phpcsFile->parse(); @@ -53,13 +54,11 @@ public function generateFileReport($report, File $phpcsFile, $showSources=false, $timeTaken = ((microtime(true) - $startTime) * 1000); if ($timeTaken < 1000) { $timeTaken = round($timeTaken); - echo "DONE in {$timeTaken}ms"; + StatusWriter::write("DONE in {$timeTaken}ms"); } else { $timeTaken = round(($timeTaken / 1000), 2); - echo "DONE in $timeTaken secs"; + StatusWriter::write("DONE in $timeTaken secs"); } - - echo PHP_EOL; } $phpcsFile->fixer->startFile($phpcsFile); @@ -67,13 +66,13 @@ public function generateFileReport($report, File $phpcsFile, $showSources=false, if (PHP_CODESNIFFER_VERBOSITY > 1) { ob_end_clean(); - echo "\t*** START FILE FIXING ***".PHP_EOL; + StatusWriter::write('*** START FILE FIXING ***', 1); } $fixed = $phpcsFile->fixer->fixFile(); if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo "\t*** END FILE FIXING ***".PHP_EOL; + StatusWriter::write('*** END FILE FIXING ***', 1); ob_start(); } diff --git a/src/Ruleset.php b/src/Ruleset.php index f7dd8e1cf0..5e3f378893 100644 --- a/src/Ruleset.php +++ b/src/Ruleset.php @@ -17,6 +17,7 @@ use PHP_CodeSniffer\Util\Common; use PHP_CodeSniffer\Util\MessageCollector; use PHP_CodeSniffer\Util\Standards; +use PHP_CodeSniffer\Util\Writers\StatusWriter; use RecursiveDirectoryIterator; use RecursiveIteratorIterator; use ReflectionClass; @@ -218,10 +219,12 @@ public function __construct(Config $config) } if (PHP_CODESNIFFER_VERBOSITY === 1) { - echo "Registering sniffs in the $standardName standard... "; + $newlines = 0; if (count($config->standards) > 1 || PHP_CODESNIFFER_VERBOSITY > 2) { - echo PHP_EOL; + $newlines = 1; } + + StatusWriter::write("Registering sniffs in the $standardName standard... ", 0, $newlines); } $sniffs = array_merge($sniffs, $this->processRuleset($standard)); @@ -252,7 +255,7 @@ public function __construct(Config $config) $numSniffs = count($this->sniffs); if (PHP_CODESNIFFER_VERBOSITY === 1) { - echo "DONE ($numSniffs sniffs registered)".PHP_EOL; + StatusWriter::write("DONE ($numSniffs sniffs registered)"); } if ($numSniffs === 0) { @@ -461,9 +464,9 @@ public function showSniffDeprecations() $summaryLine = wordwrap($summaryLine, $reportWidth, PHP_EOL); if ($this->config->colors === true) { - echo "\033[33m".$summaryLine."\033[0m".PHP_EOL; + StatusWriter::write("\033[33m".$summaryLine."\033[0m"); } else { - echo $summaryLine.PHP_EOL; + StatusWriter::write($summaryLine); } $messages = implode(PHP_EOL, $messages); @@ -471,11 +474,12 @@ public function showSniffDeprecations() $messages = Common::stripColors($messages); } - echo str_repeat('-', min(($maxActualWidth + 4), $reportWidth)).PHP_EOL; - echo $messages; + StatusWriter::write(str_repeat('-', min(($maxActualWidth + 4), $reportWidth))); + StatusWriter::write($messages, 0, 0); $closer = wordwrap('Deprecated sniffs are still run, but will stop working at some point in the future.', $reportWidth, PHP_EOL); - echo PHP_EOL.PHP_EOL.$closer.PHP_EOL.PHP_EOL; + StatusWriter::writeNewline(2); + StatusWriter::write($closer, 0, 2); }//end showSniffDeprecations() @@ -527,8 +531,7 @@ public function processRuleset($rulesetPath, $depth=0) { $rulesetPath = Common::realpath($rulesetPath); if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", $depth); - echo 'Processing ruleset '.Common::stripBasepath($rulesetPath, $this->config->basepath).PHP_EOL; + StatusWriter::write('Processing ruleset '.Common::stripBasepath($rulesetPath, $this->config->basepath), $depth); } libxml_use_internal_errors(true); @@ -557,8 +560,7 @@ public function processRuleset($rulesetPath, $depth=0) $sniffDir = $rulesetDir.DIRECTORY_SEPARATOR.'Sniffs'; if (is_dir($sniffDir) === true) { if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", $depth); - echo "\tAdding sniff files from ".Common::stripBasepath($sniffDir, $this->config->basepath).' directory'.PHP_EOL; + StatusWriter::write('Adding sniff files from '.Common::stripBasepath($sniffDir, $this->config->basepath).' directory', ($depth + 1)); } $ownSniffs = $this->expandSniffDirectory($sniffDir, $depth); @@ -584,8 +586,7 @@ public function processRuleset($rulesetPath, $depth=0) include_once $autoloadPath; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", $depth); - echo "\t=> included autoloader $autoloadPath".PHP_EOL; + StatusWriter::write("=> included autoloader $autoloadPath", ($depth + 1)); } }//end foreach @@ -605,8 +606,7 @@ public function processRuleset($rulesetPath, $depth=0) ) { // Ignore this config. A higher level ruleset has already set a value for this directive. if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", $depth); - echo "\t=> ignoring config value ".$name.': '.(string) $config['value'].' => already changed by a higher level ruleset '.PHP_EOL; + StatusWriter::write('=> ignoring config value '.$name.': '.(string) $config['value'].' => already changed by a higher level ruleset ', ($depth + 1)); } continue; @@ -616,8 +616,7 @@ public function processRuleset($rulesetPath, $depth=0) $applied = $this->config->setConfigData($name, (string) $config['value'], true); if ($applied === true && PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", $depth); - echo "\t=> set config value ".$name.': '.(string) $config['value'].PHP_EOL; + StatusWriter::write('=> set config value '.$name.': '.(string) $config['value'], ($depth + 1)); } }//end foreach @@ -644,13 +643,12 @@ public function processRuleset($rulesetPath, $depth=0) ) { // Ignore this CLI flag. A higher level ruleset has already set a value for this setting. if (PHP_CODESNIFFER_VERBOSITY > 1) { - $statusMessage = str_repeat("\t", $depth); - $statusMessage .= "\t=> ignoring command line arg --".$name; + $statusMessage = '=> ignoring command line arg --'.$name; if (isset($arg['value']) === true) { $statusMessage .= '='.(string) $arg['value']; } - echo $statusMessage.' => already changed by a higher level ruleset '.PHP_EOL; + StatusWriter::write($statusMessage.' => already changed by a higher level ruleset ', ($depth + 1)); } continue; @@ -679,8 +677,7 @@ public function processRuleset($rulesetPath, $depth=0) ) { // Ignore this CLI flag. A higher level ruleset has already set a value for this setting. if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", $depth); - echo "\t=> ignoring command line flag -".$flag.' => already changed by a higher level ruleset '.PHP_EOL; + StatusWriter::write('=> ignoring command line flag -'.$flag.' => already changed by a higher level ruleset ', ($depth + 1)); } continue; @@ -702,8 +699,7 @@ public function processRuleset($rulesetPath, $depth=0) $cliArgs[] = $argString; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", $depth); - echo "\t=> set command line value $argString".PHP_EOL; + StatusWriter::write("=> set command line value $argString", ($depth + 1)); } }//end foreach @@ -715,8 +711,7 @@ public function processRuleset($rulesetPath, $depth=0) } if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", $depth); - echo "\tProcessing rule \"".$rule['ref'].'"'.PHP_EOL; + StatusWriter::write('Processing rule "'.$rule['ref'].'"', ($depth + 1)); } $expandedSniffs = $this->expandRulesetReference((string) $rule['ref'], $rulesetDir, $depth); @@ -737,10 +732,8 @@ public function processRuleset($rulesetPath, $depth=0) // it is being explicitly included again, so turn it back on. $this->ruleset[(string) $rule['ref']]['severity'] = 5; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", $depth); - echo "\t\t* disabling sniff exclusion for specific message code *".PHP_EOL; - echo str_repeat("\t", $depth); - echo "\t\t=> severity set to 5".PHP_EOL; + StatusWriter::write('* disabling sniff exclusion for specific message code *', ($depth + 2)); + StatusWriter::write('=> severity set to 5', ($depth + 2)); } } else if (empty($newSniffs) === false) { $newSniff = $newSniffs[0]; @@ -751,8 +744,7 @@ public function processRuleset($rulesetPath, $depth=0) $this->ruleset[$sniffCode]['severity'] = 0; $this->ruleset[(string) $rule['ref']]['severity'] = 5; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", $depth); - echo "\t\tExcluding sniff \"".$sniffCode.'" except for "'.$parts[3].'"'.PHP_EOL; + StatusWriter::write('Excluding sniff "'.$sniffCode.'" except for "'.$parts[3].'"', ($depth + 2)); } } }//end if @@ -762,9 +754,8 @@ public function processRuleset($rulesetPath, $depth=0) foreach ($rule->exclude as $exclude) { if (isset($exclude['name']) === false) { if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", $depth); - echo "\t\t* ignoring empty exclude rule *".PHP_EOL; - echo "\t\t\t=> ".$exclude->asXML().PHP_EOL; + StatusWriter::write('* ignoring empty exclude rule *', ($depth + 2)); + StatusWriter::write('=> '.$exclude->asXML(), ($depth + 3)); } continue; @@ -775,8 +766,7 @@ public function processRuleset($rulesetPath, $depth=0) } if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", $depth); - echo "\t\tExcluding rule \"".$exclude['name'].'"'.PHP_EOL; + StatusWriter::write('Excluding rule "'.$exclude['name'].'"', ($depth + 2)); } // Check if a single code is being excluded, which is a shortcut @@ -785,8 +775,7 @@ public function processRuleset($rulesetPath, $depth=0) if (count($parts) === 4) { $this->ruleset[(string) $exclude['name']]['severity'] = 0; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", $depth); - echo "\t\t=> severity set to 0".PHP_EOL; + StatusWriter::write('=> severity set to 0', ($depth + 2)); } } else { $excludedSniffs = array_merge( @@ -823,8 +812,7 @@ public function processRuleset($rulesetPath, $depth=0) $cliArgs[] = $argString; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", $depth); - echo "\t=> set PHP ini value $name to $value".PHP_EOL; + StatusWriter::write("=> set PHP ini value $name to $value", ($depth + 1)); } }//end foreach @@ -834,8 +822,7 @@ public function processRuleset($rulesetPath, $depth=0) $file = (string) $file; $cliArgs[] = $file; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", $depth); - echo "\t=> added \"$file\" to the file list".PHP_EOL; + StatusWriter::write("=> added \"$file\" to the file list", ($depth + 1)); } } } @@ -869,8 +856,7 @@ public function processRuleset($rulesetPath, $depth=0) $this->ignorePatterns[(string) $pattern] = (string) $pattern['type']; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", $depth); - echo "\t=> added global ".(string) $pattern['type'].' ignore pattern: '.(string) $pattern.PHP_EOL; + StatusWriter::write('=> added global '.(string) $pattern['type'].' ignore pattern: '.(string) $pattern, ($depth + 1)); } } @@ -880,8 +866,7 @@ public function processRuleset($rulesetPath, $depth=0) if (PHP_CODESNIFFER_VERBOSITY > 1) { $included = count($includedSniffs); $excluded = count($excludedSniffs); - echo str_repeat("\t", $depth); - echo "=> Ruleset processing complete; included $included sniffs and excluded $excluded".PHP_EOL; + StatusWriter::write("=> Ruleset processing complete; included $included sniffs and excluded $excluded", $depth); } // Merge our own sniff list with our externally included @@ -948,8 +933,7 @@ private function expandSniffDirectory($directory, $depth=0) } if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", $depth); - echo "\t\t=> ".Common::stripBasepath($path, $this->config->basepath).PHP_EOL; + StatusWriter::write('=> '.Common::stripBasepath($path, $this->config->basepath), ($depth + 2)); } $sniffs[] = $path; @@ -987,8 +971,7 @@ private function expandRulesetReference($ref, $rulesetDir, $depth=0) // hide and change internal messages. if (substr($ref, 0, 9) === 'Internal.') { if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", $depth); - echo "\t\t* ignoring internal sniff code *".PHP_EOL; + StatusWriter::write('* ignoring internal sniff code *', ($depth + 2)); } return []; @@ -1003,8 +986,7 @@ private function expandRulesetReference($ref, $rulesetDir, $depth=0) if ($realpath !== false) { $ref = $realpath; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", $depth); - echo "\t\t=> ".Common::stripBasepath($ref, $this->config->basepath).PHP_EOL; + StatusWriter::write('=> '.Common::stripBasepath($ref, $this->config->basepath), ($depth + 2)); } } } @@ -1016,8 +998,7 @@ private function expandRulesetReference($ref, $rulesetDir, $depth=0) if ($realpath !== false) { $ref = $realpath; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", $depth); - echo "\t\t=> ".Common::stripBasepath($ref, $this->config->basepath).PHP_EOL; + StatusWriter::write('=> '.Common::stripBasepath($ref, $this->config->basepath), ($depth + 2)); } } } @@ -1043,8 +1024,7 @@ private function expandRulesetReference($ref, $rulesetDir, $depth=0) if ($path !== null) { $ref = $path; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", $depth); - echo "\t\t=> ".Common::stripBasepath($ref, $this->config->basepath).PHP_EOL; + StatusWriter::write('=> '.Common::stripBasepath($ref, $this->config->basepath), ($depth + 2)); } } else if (is_dir($ref) === false) { // Work out the sniff path. @@ -1103,8 +1083,7 @@ private function expandRulesetReference($ref, $rulesetDir, $depth=0) } if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", $depth); - echo "\t\t=> ".Common::stripBasepath($ref, $this->config->basepath).PHP_EOL; + StatusWriter::write('=> '.Common::stripBasepath($ref, $this->config->basepath), ($depth + 2)); } }//end if }//end if @@ -1113,18 +1092,15 @@ private function expandRulesetReference($ref, $rulesetDir, $depth=0) if (is_file($ref.DIRECTORY_SEPARATOR.'ruleset.xml') === true) { // We are referencing an external coding standard. if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", $depth); - echo "\t\t* rule is referencing a standard using directory name; processing *".PHP_EOL; + StatusWriter::write('* rule is referencing a standard using directory name; processing *', ($depth + 2)); } return $this->processRuleset($ref.DIRECTORY_SEPARATOR.'ruleset.xml', ($depth + 2)); } else { // We are referencing a whole directory of sniffs. if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", $depth); - echo "\t\t* rule is referencing a directory of sniffs *".PHP_EOL; - echo str_repeat("\t", $depth); - echo "\t\tAdding sniff files from directory".PHP_EOL; + StatusWriter::write('* rule is referencing a directory of sniffs *', ($depth + 2)); + StatusWriter::write('Adding sniff files from directory', ($depth + 2)); } return $this->expandSniffDirectory($ref, ($depth + 1)); @@ -1141,8 +1117,7 @@ private function expandRulesetReference($ref, $rulesetDir, $depth=0) } else { // Assume an external ruleset.xml file. if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", $depth); - echo "\t\t* rule is referencing a standard using ruleset path; processing *".PHP_EOL; + StatusWriter::write('* rule is referencing a standard using ruleset path; processing *', ($depth + 2)); } return $this->processRuleset($ref, ($depth + 2)); @@ -1201,13 +1176,12 @@ private function processRule($rule, $newSniffs, $depth=0) $this->ruleset[$code]['severity'] = (int) $rule->severity; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", $depth); - echo "\t\t=> severity set to ".(int) $rule->severity; + $statusMessage = '=> severity set to '.(int) $rule->severity; if ($code !== $ref) { - echo " for $code"; + $statusMessage .= " for $code"; } - echo PHP_EOL; + StatusWriter::write($statusMessage, ($depth + 2)); } } @@ -1226,13 +1200,12 @@ private function processRule($rule, $newSniffs, $depth=0) } else { $this->ruleset[$code]['type'] = $type; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", $depth); - echo "\t\t=> message type set to ".(string) $rule->type; + $statusMessage = '=> message type set to '.(string) $rule->type; if ($code !== $ref) { - echo " for $code"; + $statusMessage .= " for $code"; } - echo PHP_EOL; + StatusWriter::write($statusMessage, ($depth + 2)); } } }//end if @@ -1247,13 +1220,12 @@ private function processRule($rule, $newSniffs, $depth=0) $this->ruleset[$code]['message'] = (string) $rule->message; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", $depth); - echo "\t\t=> message set to ".(string) $rule->message; + $statusMessage = '=> message set to '.(string) $rule->message; if ($code !== $ref) { - echo " for $code"; + $statusMessage .= " for $code"; } - echo PHP_EOL; + StatusWriter::write($statusMessage, ($depth + 2)); } } @@ -1328,13 +1300,12 @@ private function processRule($rule, $newSniffs, $depth=0) 'scope' => $propertyScope, ]; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", $depth); - echo "\t\t=> array property \"$name\" set to \"$printValue\""; + $statusMessage = "=> array property \"$name\" set to \"$printValue\""; if ($code !== $ref) { - echo " for $code"; + $statusMessage .= " for $code"; } - echo PHP_EOL; + StatusWriter::write($statusMessage, ($depth + 2)); } } else { $this->ruleset[$code]['properties'][$name] = [ @@ -1342,13 +1313,12 @@ private function processRule($rule, $newSniffs, $depth=0) 'scope' => $propertyScope, ]; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", $depth); - echo "\t\t=> property \"$name\" set to \"".(string) $prop['value'].'"'; + $statusMessage = "=> property \"$name\" set to \"".(string) $prop['value'].'"'; if ($code !== $ref) { - echo " for $code"; + $statusMessage .= " for $code"; } - echo PHP_EOL; + StatusWriter::write($statusMessage, ($depth + 2)); } }//end if }//end foreach @@ -1370,13 +1340,12 @@ private function processRule($rule, $newSniffs, $depth=0) $this->ignorePatterns[$code][(string) $pattern] = (string) $pattern['type']; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", $depth); - echo "\t\t=> added rule-specific ".(string) $pattern['type'].' ignore pattern'; + $statusMessage = '=> added rule-specific '.(string) $pattern['type'].' ignore pattern'; if ($code !== $ref) { - echo " for $code"; + $statusMessage .= " for $code"; } - echo ': '.(string) $pattern.PHP_EOL; + StatusWriter::write($statusMessage.': '.(string) $pattern, ($depth + 2)); } }//end foreach @@ -1396,13 +1365,12 @@ private function processRule($rule, $newSniffs, $depth=0) $this->includePatterns[$code][(string) $pattern] = (string) $pattern['type']; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", $depth); - echo "\t\t=> added rule-specific ".(string) $pattern['type'].' include pattern'; + $statusMessage = '=> added rule-specific '.(string) $pattern['type'].' include pattern'; if ($code !== $ref) { - echo " for $code"; + $statusMessage .= " for $code"; } - echo ': '.(string) $pattern.PHP_EOL; + StatusWriter::write($statusMessage.': '.(string) $pattern, ($depth + 2)); } }//end foreach }//end foreach @@ -1530,7 +1498,7 @@ public function registerSniffs($files, $restrictions, $exclusions) $listeners[$className] = $className; if (PHP_CODESNIFFER_VERBOSITY > 2) { - echo "Registered $className".PHP_EOL; + StatusWriter::write("Registered $className"); } }//end foreach diff --git a/src/Runner.php b/src/Runner.php index ab1d5f785d..580a8f408b 100644 --- a/src/Runner.php +++ b/src/Runner.php @@ -24,6 +24,7 @@ use PHP_CodeSniffer\Util\Standards; use PHP_CodeSniffer\Util\Timing; use PHP_CodeSniffer\Util\Tokens; +use PHP_CodeSniffer\Util\Writers\StatusWriter; class Runner { @@ -342,26 +343,26 @@ private function run() } if (PHP_CODESNIFFER_VERBOSITY > 0) { - echo 'Creating file list... '; + StatusWriter::write('Creating file list... ', 0, 0); } $todo = new FileList($this->config, $this->ruleset); if (PHP_CODESNIFFER_VERBOSITY > 0) { $numFiles = count($todo); - echo "DONE ($numFiles files in queue)".PHP_EOL; + StatusWriter::write("DONE ($numFiles files in queue)"); } if ($this->config->cache === true) { if (PHP_CODESNIFFER_VERBOSITY > 0) { - echo 'Loading cache... '; + StatusWriter::write('Loading cache... ', 0, 0); } Cache::load($this->ruleset, $this->config); if (PHP_CODESNIFFER_VERBOSITY > 0) { $size = Cache::getSize(); - echo "DONE ($size files in cache)".PHP_EOL; + StatusWriter::write("DONE ($size files in cache)"); } } }//end if @@ -391,7 +392,7 @@ private function run() $currDir = dirname($path); if ($lastDir !== $currDir) { if (PHP_CODESNIFFER_VERBOSITY > 0) { - echo 'Changing into directory '.Common::stripBasepath($currDir, $this->config->basepath).PHP_EOL; + StatusWriter::write('Changing into directory '.Common::stripBasepath($currDir, $this->config->basepath)); } $lastDir = $currDir; @@ -399,7 +400,7 @@ private function run() $this->processFile($file); } else if (PHP_CODESNIFFER_VERBOSITY > 0) { - echo 'Skipping '.basename($file->path).PHP_EOL; + StatusWriter::write('Skipping '.basename($file->path)); } $numProcessed++; @@ -457,7 +458,7 @@ private function run() $currDir = dirname($path); if ($lastDir !== $currDir) { if (PHP_CODESNIFFER_VERBOSITY > 0) { - echo 'Changing into directory '.Common::stripBasepath($currDir, $this->config->basepath).PHP_EOL; + StatusWriter::write('Changing into directory '.Common::stripBasepath($currDir, $this->config->basepath)); } $lastDir = $currDir; @@ -515,7 +516,7 @@ private function run() && $this->config->interactive === false && $this->config->showProgress === true ) { - echo PHP_EOL.PHP_EOL; + StatusWriter::writeNewline(2); } if ($this->config->cache === true) { @@ -584,10 +585,12 @@ public function processFile($file) { if (PHP_CODESNIFFER_VERBOSITY > 0) { $startTime = microtime(true); - echo 'Processing '.basename($file->path).' '; + $newlines = 0; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo PHP_EOL; + $newlines = 1; } + + StatusWriter::write('Processing '.basename($file->path).' ', 0, $newlines); } try { @@ -597,19 +600,19 @@ public function processFile($file) $timeTaken = ((microtime(true) - $startTime) * 1000); if ($timeTaken < 1000) { $timeTaken = round($timeTaken); - echo "DONE in {$timeTaken}ms"; + StatusWriter::write("DONE in {$timeTaken}ms", 0, 0); } else { $timeTaken = round(($timeTaken / 1000), 2); - echo "DONE in $timeTaken secs"; + StatusWriter::write("DONE in $timeTaken secs", 0, 0); } if (PHP_CODESNIFFER_CBF === true) { $errors = $file->getFixableCount(); - echo " ($errors fixable violations)".PHP_EOL; + StatusWriter::write(" ($errors fixable violations)"); } else { $errors = $file->getErrorCount(); $warnings = $file->getWarningCount(); - echo " ($errors errors, $warnings warnings)".PHP_EOL; + StatusWriter::write(" ($errors errors, $warnings warnings)"); } } } catch (Exception $e) { @@ -868,7 +871,7 @@ public function printProgress(File $file, $numFiles, $numProcessed) }//end if }//end if - echo $colorOpen.$progressDot.$colorClose; + StatusWriter::write($colorOpen.$progressDot.$colorClose, 0, 0); $numPerLine = 60; if ($numProcessed !== $numFiles && ($numProcessed % $numPerLine) !== 0) { @@ -884,7 +887,7 @@ public function printProgress(File $file, $numFiles, $numProcessed) $padding += ($numPerLine - ($numFiles - (floor($numFiles / $numPerLine) * $numPerLine))); } - echo str_repeat(' ', $padding)." $numProcessed / $numFiles ($percent%)".PHP_EOL; + StatusWriter::write(str_repeat(' ', $padding)." $numProcessed / $numFiles ($percent%)"); }//end printProgress() @@ -919,7 +922,7 @@ static function () use ( ) { $errorArray = error_get_last(); if (is_array($errorArray) === true && strpos($errorArray['message'], $memoryError) !== false) { - echo $errorMsg; + fwrite(STDERR, $errorMsg); } } ); diff --git a/src/Sniffs/AbstractPatternSniff.php b/src/Sniffs/AbstractPatternSniff.php index 78f3ffd377..30a3ce7355 100644 --- a/src/Sniffs/AbstractPatternSniff.php +++ b/src/Sniffs/AbstractPatternSniff.php @@ -13,6 +13,7 @@ use PHP_CodeSniffer\Files\File; use PHP_CodeSniffer\Tokenizers\PHP; use PHP_CodeSniffer\Util\Tokens; +use PHP_CodeSniffer\Util\Writers\StatusWriter; abstract class AbstractPatternSniff implements Sniff { @@ -909,9 +910,13 @@ private function createSkipPattern($pattern, $from) */ private function createTokenPattern($str) { + // Pause the StatusWriter to silence Tokenizer debug info about the patterns being parsed (which only confuses things). + StatusWriter::pause(); + // Don't add a space after the closing php tag as it will add a new // whitespace token. $tokenizer = new PHP('', null); + StatusWriter::resume(); // Remove the getTokens(); diff --git a/src/Standards/Generic/Sniffs/WhiteSpace/ScopeIndentSniff.php b/src/Standards/Generic/Sniffs/WhiteSpace/ScopeIndentSniff.php index 164fbe00cc..a1b9b3adb5 100644 --- a/src/Standards/Generic/Sniffs/WhiteSpace/ScopeIndentSniff.php +++ b/src/Standards/Generic/Sniffs/WhiteSpace/ScopeIndentSniff.php @@ -13,6 +13,7 @@ use PHP_CodeSniffer\Files\File; use PHP_CodeSniffer\Sniffs\Sniff; use PHP_CodeSniffer\Util\Tokens; +use PHP_CodeSniffer\Util\Writers\StatusWriter; class ScopeIndentSniff implements Sniff { @@ -151,7 +152,8 @@ public function process(File $phpcsFile, $stackPtr) if ($this->debug === true) { $line = $tokens[$stackPtr]['line']; - echo PHP_EOL."Start with token $stackPtr on line $line with indent $currentIndent".PHP_EOL; + StatusWriter::writeNewline(); + StatusWriter::write("Start with token $stackPtr on line $line with indent $currentIndent"); } if (empty($this->ignoreIndentation) === true) { @@ -205,7 +207,7 @@ public function process(File $phpcsFile, $stackPtr) $value = 'false'; } - echo "* token $i on line $line set exact flag to $value *".PHP_EOL; + StatusWriter::write("* token $i on line $line set exact flag to $value *"); } }//end if @@ -228,8 +230,8 @@ public function process(File $phpcsFile, $stackPtr) if ($this->debug === true) { $line = $tokens[$i]['line']; $type = $tokens[$disableExactEnd]['type']; - echo "Opening parenthesis found on line $line".PHP_EOL; - echo "\t=> disabling exact indent checking until $disableExactEnd ($type)".PHP_EOL; + StatusWriter::write("Opening parenthesis found on line $line"); + StatusWriter::write("=> disabling exact indent checking until $disableExactEnd ($type)", 1); } } @@ -269,7 +271,7 @@ public function process(File $phpcsFile, $stackPtr) if ($this->debug === true) { $line = $tokens[$i]['line']; - echo "Closing parenthesis found on line $line".PHP_EOL; + StatusWriter::write("Closing parenthesis found on line $line"); } $parenOpener = $tokens[$parenCloser]['parenthesis_opener']; @@ -283,7 +285,7 @@ public function process(File $phpcsFile, $stackPtr) $parens = key($parens); if ($this->debug === true) { $line = $tokens[$parens]['line']; - echo "\t* token has nested parenthesis $parens on line $line *".PHP_EOL; + StatusWriter::write("* token has nested parenthesis $parens on line $line *", 1); } } @@ -299,20 +301,20 @@ public function process(File $phpcsFile, $stackPtr) if ($this->debug === true) { $line = $tokens[$condition]['line']; $type = $tokens[$condition]['type']; - echo "\t* token is inside condition $condition ($type) on line $line *".PHP_EOL; + StatusWriter::write("* token is inside condition $condition ($type) on line $line *", 1); } } if ($parens > $condition) { if ($this->debug === true) { - echo "\t* using parenthesis *".PHP_EOL; + StatusWriter::write('* using parenthesis *', 1); } $parenOpener = $parens; $condition = 0; } else if ($condition > 0) { if ($this->debug === true) { - echo "\t* using condition *".PHP_EOL; + StatusWriter::write('* using condition *', 1); } $parenOpener = $condition; @@ -326,14 +328,14 @@ public function process(File $phpcsFile, $stackPtr) if ($condition > 0 && $lastOpenTagCondition === $condition) { if ($this->debug === true) { - echo "\t* open tag is inside condition; using open tag *".PHP_EOL; + StatusWriter::write('* open tag is inside condition; using open tag *', 1); } $first = $phpcsFile->findFirstOnLine([T_WHITESPACE, T_INLINE_HTML], $lastOpenTag, true); if ($this->debug === true) { $line = $tokens[$first]['line']; $type = $tokens[$first]['type']; - echo "\t* first token on line $line is $first ($type) *".PHP_EOL; + StatusWriter::write("* first token on line $line is $first ($type) *", 1); } $checkIndent = ($tokens[$first]['column'] - 1); @@ -345,7 +347,7 @@ public function process(File $phpcsFile, $stackPtr) if ($this->debug === true) { $type = $tokens[$lastOpenTag]['type']; - echo "\t=> checking indent of $checkIndent; main indent set to $currentIndent by token $lastOpenTag ($type)".PHP_EOL; + StatusWriter::write("=> checking indent of $checkIndent; main indent set to $currentIndent by token $lastOpenTag ($type)", 1); } } else if ($condition > 0 && isset($tokens[$condition]['scope_opener']) === true @@ -360,7 +362,7 @@ public function process(File $phpcsFile, $stackPtr) if ($this->debug === true) { $type = $tokens[$condition]['type']; - echo "\t=> checking indent of $checkIndent; main indent set to $currentIndent by token $condition ($type)".PHP_EOL; + StatusWriter::write("=> checking indent of $checkIndent; main indent set to $currentIndent by token $condition ($type)", 1); } } else { $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $parenOpener, true); @@ -373,7 +375,7 @@ public function process(File $phpcsFile, $stackPtr) if ($this->debug === true) { $line = $tokens[$first]['line']; $type = $tokens[$first]['type']; - echo "\t* first token on line $line is $first ($type) *".PHP_EOL; + StatusWriter::write("* first token on line $line is $first ($type) *", 1); } if ($first === $tokens[$parenCloser]['parenthesis_opener'] @@ -385,8 +387,8 @@ public function process(File $phpcsFile, $stackPtr) if ($this->debug === true) { $line = $tokens[$first]['line']; $type = $tokens[$first]['type']; - echo "\t* first token is the parenthesis opener *".PHP_EOL; - echo "\t* amended first token is $first ($type) on line $line *".PHP_EOL; + StatusWriter::write('* first token is the parenthesis opener *', 1); + StatusWriter::write("* amended first token is $first ($type) on line $line *", 1); } } @@ -396,7 +398,7 @@ public function process(File $phpcsFile, $stackPtr) if ($this->debug === true) { $line = $tokens[$prev]['line']; $type = $tokens[$prev]['type']; - echo "\t* previous is $type on line $line *".PHP_EOL; + StatusWriter::write("* previous is $type on line $line *", 1); } $first = $phpcsFile->findFirstOnLine([T_WHITESPACE, T_INLINE_HTML], $prev, true); @@ -410,7 +412,7 @@ public function process(File $phpcsFile, $stackPtr) if ($this->debug === true) { $line = $tokens[$first]['line']; $type = $tokens[$first]['type']; - echo "\t* amended first token is $first ($type) on line $line *".PHP_EOL; + StatusWriter::write("* amended first token is $first ($type) on line $line *", 1); } }//end if @@ -418,7 +420,7 @@ public function process(File $phpcsFile, $stackPtr) && $tokens[$first]['scope_closer'] === $first ) { if ($this->debug === true) { - echo "\t* first token is a scope closer *".PHP_EOL; + StatusWriter::write('* first token is a scope closer *', 1); } if (isset($tokens[$first]['scope_condition']) === true) { @@ -439,7 +441,7 @@ public function process(File $phpcsFile, $stackPtr) if ($this->debug === true) { $type = $tokens[$first]['type']; - echo "\t=> indent set to $currentIndent by token $first ($type)".PHP_EOL; + StatusWriter::write("=> indent set to $currentIndent by token $first ($type)", 1); } }//end if } else { @@ -454,12 +456,12 @@ public function process(File $phpcsFile, $stackPtr) if ($this->debug === true) { $type = $tokens[$first]['type']; - echo "\t=> checking indent of $checkIndent; main indent set to $currentIndent by token $first ($type)".PHP_EOL; + StatusWriter::write("=> checking indent of $checkIndent; main indent set to $currentIndent by token $first ($type)", 1); } }//end if }//end if } else if ($this->debug === true) { - echo "\t * ignoring single-line definition *".PHP_EOL; + StatusWriter::write(' * ignoring single-line definition *', 1); }//end if }//end if @@ -477,7 +479,7 @@ public function process(File $phpcsFile, $stackPtr) if ($this->debug === true) { $line = $tokens[$arrayCloser]['line']; - echo "Closing short array bracket found on line $line".PHP_EOL; + StatusWriter::write("Closing short array bracket found on line $line"); } $arrayOpener = $tokens[$arrayCloser]['bracket_opener']; @@ -488,7 +490,7 @@ public function process(File $phpcsFile, $stackPtr) if ($this->debug === true) { $line = $tokens[$first]['line']; $type = $tokens[$first]['type']; - echo "\t* first token on line $line is $first ($type) *".PHP_EOL; + StatusWriter::write("* first token on line $line is $first ($type) *", 1); } if ($first === $tokens[$arrayCloser]['bracket_opener']) { @@ -503,7 +505,7 @@ public function process(File $phpcsFile, $stackPtr) if ($this->debug === true) { $line = $tokens[$prev]['line']; $type = $tokens[$prev]['type']; - echo "\t* previous is $type on line $line *".PHP_EOL; + StatusWriter::write("* previous is $type on line $line *", 1); } $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $prev, true); @@ -512,7 +514,7 @@ public function process(File $phpcsFile, $stackPtr) if ($this->debug === true) { $line = $tokens[$first]['line']; $type = $tokens[$first]['type']; - echo "\t* amended first token is $first ($type) on line $line *".PHP_EOL; + StatusWriter::write("* amended first token is $first ($type) on line $line *", 1); } } else if ($tokens[$first]['code'] === T_WHITESPACE) { $first = $phpcsFile->findNext(T_WHITESPACE, ($first + 1), null, true); @@ -530,13 +532,13 @@ public function process(File $phpcsFile, $stackPtr) // been processed and set the indent level correctly, so // don't adjust it again. if ($this->debug === true) { - echo "\t* first token is a scope closer; ignoring closing short array bracket *".PHP_EOL; + StatusWriter::write('* first token is a scope closer; ignoring closing short array bracket *', 1); } if (isset($setIndents[$first]) === true) { $currentIndent = $setIndents[$first]; if ($this->debug === true) { - echo "\t=> indent reset to $currentIndent".PHP_EOL; + StatusWriter::write("=> indent reset to $currentIndent", 1); } } } else { @@ -551,11 +553,11 @@ public function process(File $phpcsFile, $stackPtr) if ($this->debug === true) { $type = $tokens[$first]['type']; - echo "\t=> checking indent of $checkIndent; main indent set to $currentIndent by token $first ($type)".PHP_EOL; + StatusWriter::write("=> checking indent of $checkIndent; main indent set to $currentIndent by token $first ($type)", 1); } }//end if } else if ($this->debug === true) { - echo "\t * ignoring single-line definition *".PHP_EOL; + StatusWriter::write(' * ignoring single-line definition *', 1); }//end if }//end if @@ -593,7 +595,7 @@ public function process(File $phpcsFile, $stackPtr) if ($this->debug === true) { $line = $tokens[$checkToken]['line']; $type = $tokens[$checkToken]['type']; - echo "Indent adjusted to $length for $type on line $line".PHP_EOL; + StatusWriter::write("Indent adjusted to $length for $type on line $line"); } $adjustments[$checkToken] = $adjustments[$first]; @@ -601,7 +603,7 @@ public function process(File $phpcsFile, $stackPtr) if ($this->debug === true) { $line = $tokens[$checkToken]['line']; $type = $tokens[$checkToken]['type']; - echo "\t=> add adjustment of ".$adjustments[$checkToken]." for token $checkToken ($type) on line $line".PHP_EOL; + StatusWriter::write('=> add adjustment of '.$adjustments[$checkToken]." for token $checkToken ($type) on line $line", 1); } }//end if }//end if @@ -625,7 +627,7 @@ public function process(File $phpcsFile, $stackPtr) $line = $tokens[$checkToken]['line']; } - echo "Close scope ($type) on line $line".PHP_EOL; + StatusWriter::write("Close scope ($type) on line $line"); } $scopeCloser = $checkToken; @@ -637,7 +639,7 @@ public function process(File $phpcsFile, $stackPtr) if ($this->debug === true && $conditionToken !== null) { $line = $tokens[$conditionToken]['line']; $type = $tokens[$conditionToken]['type']; - echo "\t=> removed open scope $conditionToken ($type) on line $line".PHP_EOL; + StatusWriter::write("=> removed open scope $conditionToken ($type) on line $line", 1); } if (isset($tokens[$scopeCloser]['scope_condition']) === true) { @@ -645,7 +647,7 @@ public function process(File $phpcsFile, $stackPtr) if ($this->debug === true) { $line = $tokens[$first]['line']; $type = $tokens[$first]['type']; - echo "\t* first token is $first ($type) on line $line *".PHP_EOL; + StatusWriter::write("* first token is $first ($type) on line $line *", 1); } while ($tokens[$first]['code'] === T_CONSTANT_ENCAPSED_STRING @@ -655,7 +657,7 @@ public function process(File $phpcsFile, $stackPtr) if ($this->debug === true) { $line = $tokens[$first]['line']; $type = $tokens[$first]['type']; - echo "\t* found multi-line string; amended first token is $first ($type) on line $line *".PHP_EOL; + StatusWriter::write("* found multi-line string; amended first token is $first ($type) on line $line *", 1); } } @@ -668,7 +670,7 @@ public function process(File $phpcsFile, $stackPtr) if ($this->debug === true) { $type = $tokens[$scopeCloser]['type']; - echo "\t=> indent set to $currentIndent by token $scopeCloser ($type)".PHP_EOL; + StatusWriter::write("=> indent set to $currentIndent by token $scopeCloser ($type)", 1); } // We only check the indent of scope closers if they are @@ -721,8 +723,8 @@ public function process(File $phpcsFile, $stackPtr) if ($this->debug === true) { $line = $tokens[$i]['line']; $type = $tokens[$lastOpener]['type']; - echo "Shared closer found on line $line".PHP_EOL; - echo "\t=> indent set to $currentIndent by token $lastOpener ($type)".PHP_EOL; + StatusWriter::write("Shared closer found on line $line"); + StatusWriter::write("=> indent set to $currentIndent by token $lastOpener ($type)", 1); } } @@ -736,8 +738,8 @@ public function process(File $phpcsFile, $stackPtr) if ($this->debug === true) { $line = $tokens[$i]['line']; - echo "Closure found on line $line".PHP_EOL; - echo "\t=> checking indent of $checkIndent; main indent remains at $currentIndent".PHP_EOL; + StatusWriter::write("Closure found on line $line"); + StatusWriter::write("=> checking indent of $checkIndent; main indent remains at $currentIndent", 1); } } }//end if @@ -770,7 +772,7 @@ public function process(File $phpcsFile, $stackPtr) if ($this->debug === true) { $line = $tokens[$checkToken]['line']; $type = $tokens[$checkToken]['type']; - echo "\t* method prefix ($type) found on line $line; indent set to exact *".PHP_EOL; + StatusWriter::write("* method prefix ($type) found on line $line; indent set to exact *", 1); } $exact = true; @@ -896,7 +898,7 @@ public function process(File $phpcsFile, $stackPtr) if ($this->debug === true) { $line = $tokens[$checkToken]['line']; $message = vsprintf($error, $data); - echo "[Line $line] $message".PHP_EOL; + StatusWriter::write("[Line $line] $message"); } // Assume the change would be applied and continue @@ -911,7 +913,7 @@ public function process(File $phpcsFile, $stackPtr) if ($accepted === true && $this->debug === true) { $line = $tokens[$checkToken]['line']; $type = $tokens[$checkToken]['type']; - echo "\t=> add adjustment of ".$adjustments[$checkToken]." for token $checkToken ($type) on line $line".PHP_EOL; + StatusWriter::write('=> add adjustment of '.$adjustments[$checkToken]." for token $checkToken ($type) on line $line", 1); } } }//end if @@ -928,11 +930,11 @@ public function process(File $phpcsFile, $stackPtr) $line = $tokens[$i]['line']; $type = $tokens[$disableExactEnd]['type']; $endLine = $tokens[$disableExactEnd]['line']; - echo "Opening short array bracket found on line $line".PHP_EOL; + StatusWriter::write("Opening short array bracket found on line $line"); if ($disableExactEnd === $tokens[$i]['bracket_closer']) { - echo "\t=> disabling exact indent checking until $disableExactEnd ($type) on line $endLine".PHP_EOL; + StatusWriter::write("=> disabling exact indent checking until $disableExactEnd ($type) on line $endLine", 1); } else { - echo "\t=> continuing to disable exact indent checking until $disableExactEnd ($type) on line $endLine".PHP_EOL; + StatusWriter::write("=> continuing to disable exact indent checking until $disableExactEnd ($type) on line $endLine", 1); } } } @@ -944,7 +946,7 @@ public function process(File $phpcsFile, $stackPtr) ) { if ($this->debug === true) { $line = $tokens[$i]['line']; - echo "Here/nowdoc found on line $line".PHP_EOL; + StatusWriter::write("Here/nowdoc found on line $line"); } $i = $phpcsFile->findNext([T_END_HEREDOC, T_END_NOWDOC], ($i + 1)); @@ -956,7 +958,7 @@ public function process(File $phpcsFile, $stackPtr) if ($this->debug === true) { $line = $tokens[$i]['line']; $type = $tokens[$i]['type']; - echo "\t* skipping to token $i ($type) on line $line *".PHP_EOL; + StatusWriter::write("* skipping to token $i ($type) on line $line *", 1); } continue; @@ -988,7 +990,7 @@ public function process(File $phpcsFile, $stackPtr) ) { if ($this->debug === true) { $line = $tokens[$i]['line']; - echo "Open PHP tag found on line $line".PHP_EOL; + StatusWriter::write("Open PHP tag found on line $line"); } if ($checkToken === null) { @@ -1010,7 +1012,7 @@ public function process(File $phpcsFile, $stackPtr) if ($this->debug === true) { $type = $tokens[$i]['type']; - echo "\t=> indent set to $currentIndent by token $i ($type)".PHP_EOL; + StatusWriter::write("=> indent set to $currentIndent by token $i ($type)", 1); } continue; @@ -1021,7 +1023,7 @@ public function process(File $phpcsFile, $stackPtr) if ($tokens[$i]['code'] === T_CLOSE_TAG) { if ($this->debug === true) { $line = $tokens[$i]['line']; - echo "Close PHP tag found on line $line".PHP_EOL; + StatusWriter::write("Close PHP tag found on line $line"); } if ($tokens[$lastOpenTag]['line'] !== $tokens[$i]['line']) { @@ -1045,7 +1047,7 @@ public function process(File $phpcsFile, $stackPtr) if ($this->debug === true) { $type = $tokens[$i]['type']; - echo "\t=> indent set to $currentIndent by token $i ($type)".PHP_EOL; + StatusWriter::write("=> indent set to $currentIndent by token $i ($type)", 1); } continue; @@ -1058,7 +1060,7 @@ public function process(File $phpcsFile, $stackPtr) if ($this->debug === true) { $type = str_replace('_', ' ', strtolower(substr($tokens[$i]['type'], 2))); $line = $tokens[$i]['line']; - echo "* ignoring single-line $type on line $line *".PHP_EOL; + StatusWriter::write("* ignoring single-line $type on line $line *"); } $i = $closer; @@ -1068,14 +1070,14 @@ public function process(File $phpcsFile, $stackPtr) if ($this->debug === true) { $type = str_replace('_', ' ', strtolower(substr($tokens[$i]['type'], 2))); $line = $tokens[$i]['line']; - echo "Open $type on line $line".PHP_EOL; + StatusWriter::write("Open $type on line $line"); } $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $i, true); if ($this->debug === true) { $line = $tokens[$first]['line']; $type = $tokens[$first]['type']; - echo "\t* first token is $first ($type) on line $line *".PHP_EOL; + StatusWriter::write("* first token is $first ($type) on line $line *", 1); } while ($tokens[$first]['code'] === T_CONSTANT_ENCAPSED_STRING @@ -1085,7 +1087,7 @@ public function process(File $phpcsFile, $stackPtr) if ($this->debug === true) { $line = $tokens[$first]['line']; $type = $tokens[$first]['type']; - echo "\t* found multi-line string; amended first token is $first ($type) on line $line *".PHP_EOL; + StatusWriter::write("* found multi-line string; amended first token is $first ($type) on line $line *", 1); } } @@ -1098,7 +1100,7 @@ public function process(File $phpcsFile, $stackPtr) $conditionToken = $tokens[$i]['scope_condition']; $conditionLine = $tokens[$conditionToken]['line']; $conditionType = $tokens[$conditionToken]['type']; - echo "\t=> added open scope $closerToken ($closerType) on line $closerLine, pointing to condition $conditionToken ($conditionType) on line $conditionLine".PHP_EOL; + StatusWriter::write("=> added open scope $closerToken ($closerType) on line $closerLine, pointing to condition $conditionToken ($conditionType) on line $conditionLine", 1); } if (isset($adjustments[$first]) === true) { @@ -1112,7 +1114,7 @@ public function process(File $phpcsFile, $stackPtr) if ($this->debug === true) { $type = $tokens[$i]['type']; - echo "\t=> indent set to $currentIndent by token $i ($type)".PHP_EOL; + StatusWriter::write("=> indent set to $currentIndent by token $i ($type)", 1); } continue; @@ -1128,7 +1130,7 @@ public function process(File $phpcsFile, $stackPtr) if ($this->debug === true) { $line = $tokens[$i]['line']; $type = $tokens[$i]['type']; - echo "* ignoring single-line $type on line $line *".PHP_EOL; + StatusWriter::write("* ignoring single-line $type on line $line *"); } $i = $closer; @@ -1139,7 +1141,7 @@ public function process(File $phpcsFile, $stackPtr) if ($condition === T_FN) { if ($this->debug === true) { $line = $tokens[$tokens[$i]['scope_condition']]['line']; - echo "* ignoring arrow function on line $line *".PHP_EOL; + StatusWriter::write("* ignoring arrow function on line $line *"); } $i = $closer; @@ -1152,7 +1154,7 @@ public function process(File $phpcsFile, $stackPtr) if ($this->debug === true) { $line = $tokens[$i]['line']; $type = $tokens[$tokens[$i]['scope_condition']]['type']; - echo "Open scope ($type) on line $line".PHP_EOL; + StatusWriter::write("Open scope ($type) on line $line"); } $currentIndent += $this->indent; @@ -1165,12 +1167,12 @@ public function process(File $phpcsFile, $stackPtr) $conditionToken = $tokens[$i]['scope_condition']; $conditionLine = $tokens[$conditionToken]['line']; $conditionType = $tokens[$conditionToken]['type']; - echo "\t=> added open scope $closerToken ($closerType) on line $closerLine, pointing to condition $conditionToken ($conditionType) on line $conditionLine".PHP_EOL; + StatusWriter::write("=> added open scope $closerToken ($closerType) on line $closerLine, pointing to condition $conditionToken ($conditionType) on line $conditionLine", 1); } if ($this->debug === true) { $type = $tokens[$i]['type']; - echo "\t=> indent set to $currentIndent by token $i ($type)".PHP_EOL; + StatusWriter::write("=> indent set to $currentIndent by token $i ($type)", 1); } continue; @@ -1189,7 +1191,7 @@ public function process(File $phpcsFile, $stackPtr) if ($this->debug === true) { $type = str_replace('_', ' ', strtolower(substr($tokens[$tokens[$i]['scope_condition']]['type'], 2))); $line = $tokens[$i]['line']; - echo "Close $type on line $line".PHP_EOL; + StatusWriter::write("Close $type on line $line"); } $prev = false; @@ -1203,7 +1205,7 @@ public function process(File $phpcsFile, $stackPtr) $parens = key($parens); if ($this->debug === true) { $line = $tokens[$parens]['line']; - echo "\t* token has nested parenthesis $parens on line $line *".PHP_EOL; + StatusWriter::write("* token has nested parenthesis $parens on line $line *", 1); } } @@ -1217,20 +1219,20 @@ public function process(File $phpcsFile, $stackPtr) if ($this->debug === true) { $line = $tokens[$condition]['line']; $type = $tokens[$condition]['type']; - echo "\t* token is inside condition $condition ($type) on line $line *".PHP_EOL; + StatusWriter::write("* token is inside condition $condition ($type) on line $line *", 1); } } if ($parens > $condition) { if ($this->debug === true) { - echo "\t* using parenthesis *".PHP_EOL; + StatusWriter::write('* using parenthesis *', 1); } $prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($parens - 1), null, true); $condition = 0; } else if ($condition > 0) { if ($this->debug === true) { - echo "\t* using condition *".PHP_EOL; + StatusWriter::write('* using condition *', 1); } $prev = $condition; @@ -1242,7 +1244,7 @@ public function process(File $phpcsFile, $stackPtr) if ($prev === false) { $prev = $i; if ($this->debug === true) { - echo "\t* could not find a previous T_EQUAL or T_RETURN token; will use current token *".PHP_EOL; + StatusWriter::write('* could not find a previous T_EQUAL or T_RETURN token; will use current token *', 1); } } } @@ -1250,14 +1252,14 @@ public function process(File $phpcsFile, $stackPtr) if ($this->debug === true) { $line = $tokens[$prev]['line']; $type = $tokens[$prev]['type']; - echo "\t* previous token is $type on line $line *".PHP_EOL; + StatusWriter::write("* previous token is $type on line $line *", 1); } $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $prev, true); if ($this->debug === true) { $line = $tokens[$first]['line']; $type = $tokens[$first]['type']; - echo "\t* first token on line $line is $first ($type) *".PHP_EOL; + StatusWriter::write("* first token on line $line is $first ($type) *", 1); } $prev = $phpcsFile->findStartOfStatement($first); @@ -1266,14 +1268,14 @@ public function process(File $phpcsFile, $stackPtr) if ($this->debug === true) { $line = $tokens[$prev]['line']; $type = $tokens[$prev]['type']; - echo "\t* amended previous is $type on line $line *".PHP_EOL; + StatusWriter::write("* amended previous is $type on line $line *", 1); } $first = $phpcsFile->findFirstOnLine(T_WHITESPACE, $prev, true); if ($this->debug === true) { $line = $tokens[$first]['line']; $type = $tokens[$first]['type']; - echo "\t* amended first token is $first ($type) on line $line *".PHP_EOL; + StatusWriter::write("* amended first token is $first ($type) on line $line *", 1); } } @@ -1286,13 +1288,13 @@ public function process(File $phpcsFile, $stackPtr) && $tokens[$first]['scope_closer'] === $first ) { if ($this->debug === true) { - echo "\t* first token is a scope closer *".PHP_EOL; + StatusWriter::write('* first token is a scope closer *', 1); } if ($condition === 0 || $tokens[$condition]['scope_opener'] < $first) { $currentIndent = $setIndents[$first]; } else if ($this->debug === true) { - echo "\t* ignoring scope closer *".PHP_EOL; + StatusWriter::write('* ignoring scope closer *', 1); } } @@ -1302,7 +1304,7 @@ public function process(File $phpcsFile, $stackPtr) if ($this->debug === true) { $type = $tokens[$first]['type']; - echo "\t=> indent set to $currentIndent by token $first ($type)".PHP_EOL; + StatusWriter::write("=> indent set to $currentIndent by token $first ($type)", 1); } }//end if }//end for @@ -1390,7 +1392,7 @@ protected function adjustIndent(File $phpcsFile, $stackPtr, $length, $change) $length = strlen($padding); $line = $tokens[$x]['line']; $type = $tokens[$x]['type']; - echo "\t=> Indent adjusted to $length for $type on line $line".PHP_EOL; + StatusWriter::write("=> Indent adjusted to $length for $type on line $line", 1); } }//end for }//end if diff --git a/src/Standards/Squiz/Sniffs/PHP/CommentedOutCodeSniff.php b/src/Standards/Squiz/Sniffs/PHP/CommentedOutCodeSniff.php index d9e78ba6c5..2213106060 100644 --- a/src/Standards/Squiz/Sniffs/PHP/CommentedOutCodeSniff.php +++ b/src/Standards/Squiz/Sniffs/PHP/CommentedOutCodeSniff.php @@ -14,6 +14,7 @@ use PHP_CodeSniffer\Sniffs\Sniff; use PHP_CodeSniffer\Tokenizers\PHP; use PHP_CodeSniffer\Util\Tokens; +use PHP_CodeSniffer\Util\Writers\StatusWriter; class CommentedOutCodeSniff implements Sniff { @@ -165,15 +166,22 @@ public function process(File $phpcsFile, $stackPtr) // of errors that don't mean anything, so ignore them. $oldErrors = ini_get('error_reporting'); ini_set('error_reporting', 0); + + // Pause the StatusWriter to silence Tokenizer debug info about the comments being parsed (which only confuses things). + StatusWriter::pause(); + try { $tokenizer = new PHP($content, $phpcsFile->config, $phpcsFile->eolChar); $stringTokens = $tokenizer->getTokens(); } catch (TokenizerException $e) { // We couldn't check the comment, so ignore it. + StatusWriter::resume(); ini_set('error_reporting', $oldErrors); return ($lastCommentBlockToken + 1); } + StatusWriter::resume(); + ini_set('error_reporting', $oldErrors); $numTokens = count($stringTokens); diff --git a/src/Tokenizers/Comment.php b/src/Tokenizers/Comment.php index e779c84a20..bac3111e28 100644 --- a/src/Tokenizers/Comment.php +++ b/src/Tokenizers/Comment.php @@ -10,6 +10,7 @@ namespace PHP_CodeSniffer\Tokenizers; use PHP_CodeSniffer\Util\Common; +use PHP_CodeSniffer\Util\Writers\StatusWriter; class Comment { @@ -27,7 +28,7 @@ class Comment public function tokenizeString($string, $eolChar, $stackPtr) { if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo "\t\t*** START COMMENT TOKENIZING ***".PHP_EOL; + StatusWriter::write('*** START COMMENT TOKENIZING ***', 2); } $tokens = []; @@ -61,7 +62,7 @@ public function tokenizeString($string, $eolChar, $stackPtr) if (PHP_CODESNIFFER_VERBOSITY > 1) { $content = Common::prepareForOutput($openTag); - echo "\t\tCreate comment token: T_DOC_COMMENT_OPEN_TAG => $content".PHP_EOL; + StatusWriter::write("Create comment token: T_DOC_COMMENT_OPEN_TAG => $content", 2); } /* @@ -105,7 +106,7 @@ public function tokenizeString($string, $eolChar, $stackPtr) $stackPtr++; if (PHP_CODESNIFFER_VERBOSITY > 1) { $content = Common::prepareForOutput($space['content']); - echo "\t\tCreate comment token: T_DOC_COMMENT_WHITESPACE => $content".PHP_EOL; + StatusWriter::write("Create comment token: T_DOC_COMMENT_WHITESPACE => $content", 2); } $char += strlen($space['content']); @@ -130,7 +131,7 @@ public function tokenizeString($string, $eolChar, $stackPtr) $stackPtr++; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo "\t\tCreate comment token: T_DOC_COMMENT_STAR => *".PHP_EOL; + StatusWriter::write('Create comment token: T_DOC_COMMENT_STAR => *', 2); } } @@ -141,7 +142,7 @@ public function tokenizeString($string, $eolChar, $stackPtr) if (PHP_CODESNIFFER_VERBOSITY > 1) { $content = Common::prepareForOutput($lineToken['content']); $type = $lineToken['type']; - echo "\t\tCreate comment token: $type => $content".PHP_EOL; + StatusWriter::write("Create comment token: $type => $content", 2); } if ($lineToken['code'] === T_DOC_COMMENT_TAG) { @@ -156,11 +157,11 @@ public function tokenizeString($string, $eolChar, $stackPtr) $tokens[$openPtr]['comment_closer'] = $stackPtr; if (PHP_CODESNIFFER_VERBOSITY > 1) { $content = Common::prepareForOutput($closeTag['content']); - echo "\t\tCreate comment token: T_DOC_COMMENT_CLOSE_TAG => $content".PHP_EOL; + StatusWriter::write("Create comment token: T_DOC_COMMENT_CLOSE_TAG => $content", 2); } if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo "\t\t*** END COMMENT TOKENIZING ***".PHP_EOL; + StatusWriter::write('*** END COMMENT TOKENIZING ***', 2); } return $tokens; diff --git a/src/Tokenizers/PHP.php b/src/Tokenizers/PHP.php index beff3e43d3..d40103c899 100644 --- a/src/Tokenizers/PHP.php +++ b/src/Tokenizers/PHP.php @@ -11,6 +11,7 @@ use PHP_CodeSniffer\Util\Common; use PHP_CodeSniffer\Util\Tokens; +use PHP_CodeSniffer\Util\Writers\StatusWriter; class PHP extends Tokenizer { @@ -516,7 +517,7 @@ class PHP extends Tokenizer protected function tokenize($string) { if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo "\t*** START PHP TOKENIZING ***".PHP_EOL; + StatusWriter::write('*** START PHP TOKENIZING ***', 1); $isWin = false; if (stripos(PHP_OS, 'WIN') === 0) { $isWin = true; @@ -555,14 +556,15 @@ protected function tokenize($string) $content = Common::prepareForOutput($token[0]); } - echo "\tProcess token "; + $statusMessage = 'Process token '; if ($tokenIsArray === true) { - echo "[$stackPtr]"; + $statusMessage .= "[$stackPtr]"; } else { - echo " $stackPtr "; + $statusMessage .= " $stackPtr "; } - echo ": $type => $content"; + $statusMessage .= ": $type => $content"; + StatusWriter::write($statusMessage, 1, 0); }//end if if ($newStackPtr > 0 @@ -586,9 +588,9 @@ protected function tokenize($string) $token[1] .= "\n"; if (PHP_CODESNIFFER_VERBOSITY > 1) { if ($isWin === true) { - echo '\n'; + StatusWriter::write('\n', 0, 0); } else { - echo "\033[30;1m\\n\033[0m"; + StatusWriter::write("\033[30;1m\\n\033[0m", 0, 0); } } @@ -603,7 +605,7 @@ protected function tokenize($string) }//end if if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo PHP_EOL; + StatusWriter::writeNewline(); } /* @@ -714,7 +716,7 @@ protected function tokenize($string) if ($preserveKeyword === false) { if (PHP_CODESNIFFER_VERBOSITY > 1) { $type = Tokens::tokenName($token[0]); - echo "\t\t* token $stackPtr changed from $type to T_STRING".PHP_EOL; + StatusWriter::write("* token $stackPtr changed from $type to T_STRING", 2); } $finalTokens[$newStackPtr] = [ @@ -858,7 +860,7 @@ protected function tokenize($string) $tokens[($stackPtr + 1)] = null; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo "\t\t* merged newline after comment into comment token $stackPtr".PHP_EOL; + StatusWriter::write("* merged newline after comment into comment token $stackPtr", 2); } } else { // This may be a whitespace token consisting of multiple new lines. @@ -874,7 +876,7 @@ protected function tokenize($string) } if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo "\t\t* stripped first newline after comment and added it to comment token $stackPtr".PHP_EOL; + StatusWriter::write("* stripped first newline after comment and added it to comment token $stackPtr", 2); } }//end if }//end if @@ -1090,8 +1092,8 @@ protected function tokenize($string) // a heredoc. if (PHP_CODESNIFFER_VERBOSITY > 1) { $type = $finalTokens[$newStackPtr]['type']; - echo "\t\t* failed to find the end of the here/nowdoc".PHP_EOL; - echo "\t\t* token $stackPtr changed from $type to T_STRING".PHP_EOL; + StatusWriter::write('* failed to find the end of the here/nowdoc', 2); + StatusWriter::write("* token $stackPtr changed from $type to T_STRING", 2); } $finalTokens[$newStackPtr]['code'] = T_STRING; @@ -1176,7 +1178,7 @@ protected function tokenize($string) $finalTokens[$newStackPtr] = $newToken; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo "\t\t* token $stackPtr changed from T_STRING to T_ENUM".PHP_EOL; + StatusWriter::write("* token $stackPtr changed from T_STRING to T_ENUM", 2); } $newStackPtr++; @@ -1235,7 +1237,7 @@ protected function tokenize($string) $finalTokens[$newStackPtr] = $newToken; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo "\t\t* token $stackPtr changed from T_CASE to T_ENUM_CASE".PHP_EOL; + StatusWriter::write("* token $stackPtr changed from T_CASE to T_ENUM_CASE", 2); } $newStackPtr++; @@ -1312,7 +1314,7 @@ protected function tokenize($string) if (PHP_CODESNIFFER_VERBOSITY > 1) { $type = Tokens::tokenName($token[0]); $content = Common::prepareForOutput($token[1]); - echo "\t\t* token $stackPtr split into individual tokens; was: $type => $content".PHP_EOL; + StatusWriter::write("* token $stackPtr split into individual tokens; was: $type => $content", 2); } continue; @@ -1355,7 +1357,7 @@ protected function tokenize($string) $tokens[$bracketCloser][1] = ']'; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo "\t\t* token $bracketCloser changed from T_CLOSE_SQUARE_BRACKET to T_ATTRIBUTE_END".PHP_EOL; + StatusWriter::write("* token $bracketCloser changed from T_CLOSE_SQUARE_BRACKET to T_ATTRIBUTE_END", 2); } $newStackPtr++; @@ -1411,7 +1413,7 @@ protected function tokenize($string) if (PHP_CODESNIFFER_VERBOSITY > 1) { $type = Tokens::tokenName($token[0]); - echo "\t\t* token $stackPtr changed from $type to T_PARAM_NAME".PHP_EOL; + StatusWriter::write("* token $stackPtr changed from $type to T_PARAM_NAME", 2); } continue; @@ -1521,7 +1523,7 @@ protected function tokenize($string) $token[0] = T_READONLY; if (PHP_CODESNIFFER_VERBOSITY > 1 && $type !== T_READONLY) { - echo "\t\t* token $stackPtr changed from $type to T_READONLY".PHP_EOL; + StatusWriter::write("* token $stackPtr changed from $type to T_READONLY", 2); } } else { $finalTokens[$newStackPtr] = [ @@ -1532,7 +1534,7 @@ protected function tokenize($string) $newStackPtr++; if (PHP_CODESNIFFER_VERBOSITY > 1 && $type !== T_STRING) { - echo "\t\t* token $stackPtr changed from $type to T_STRING".PHP_EOL; + StatusWriter::write("* token $stackPtr changed from $type to T_STRING", 2); } }//end if @@ -1567,8 +1569,8 @@ protected function tokenize($string) $newStackPtr++; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo "\t\t* token $lastNotEmptyToken (new stack) changed into T_YIELD_FROM; was: T_YIELD".PHP_EOL; - echo "\t\t* token $stackPtr changed into T_YIELD_FROM; was: T_STRING".PHP_EOL; + StatusWriter::write("* token $lastNotEmptyToken (new stack) changed into T_YIELD_FROM; was: T_YIELD", 2); + StatusWriter::write("* token $stackPtr changed into T_YIELD_FROM; was: T_STRING", 2); } continue; @@ -1620,7 +1622,7 @@ protected function tokenize($string) $newStackPtr++; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo "\t\t* token $stackPtr split into 'yield', one or more whitespace tokens and 'from'".PHP_EOL; + StatusWriter::write("* token $stackPtr split into 'yield', one or more whitespace tokens and 'from'", 2); } continue; @@ -1657,7 +1659,7 @@ protected function tokenize($string) $numTokens = count($tokens); if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo "\t\t* token $stackPtr split into parts (yield from with comment)".PHP_EOL; + StatusWriter::write("* token $stackPtr split into parts (yield from with comment)", 2); } unset($yieldFromSubtokens); @@ -1829,7 +1831,7 @@ protected function tokenize($string) $newToken['content'] = $token[1]; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo "\t\t* token $stackPtr changed from T_STRING to T_MATCH".PHP_EOL; + StatusWriter::write("* token $stackPtr changed from T_STRING to T_MATCH", 2); } $finalTokens[$newStackPtr] = $newToken; @@ -1843,7 +1845,7 @@ protected function tokenize($string) $newToken['content'] = $token[1]; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo "\t\t* token $stackPtr changed from T_MATCH to T_STRING".PHP_EOL; + StatusWriter::write("* token $stackPtr changed from T_MATCH to T_STRING", 2); } $finalTokens[$newStackPtr] = $newToken; @@ -1886,7 +1888,7 @@ protected function tokenize($string) // in PHP::processAdditional(). $tokens[$x][0] = T_MATCH_ARROW; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo "\t\t* token $x changed from T_DOUBLE_ARROW to T_MATCH_ARROW".PHP_EOL; + StatusWriter::write("* token $x changed from T_DOUBLE_ARROW to T_MATCH_ARROW", 2); } $newToken = []; @@ -1895,7 +1897,7 @@ protected function tokenize($string) $newToken['content'] = $token[1]; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo "\t\t* token $stackPtr changed from T_DEFAULT to T_MATCH_DEFAULT".PHP_EOL; + StatusWriter::write("* token $stackPtr changed from T_DEFAULT to T_MATCH_DEFAULT", 2); } $finalTokens[$newStackPtr] = $newToken; @@ -1918,7 +1920,7 @@ protected function tokenize($string) $newToken['type'] = 'T_NULLABLE'; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo "\t\t* token $stackPtr changed from ? to T_NULLABLE".PHP_EOL; + StatusWriter::write("* token $stackPtr changed from ? to T_NULLABLE", 2); } $finalTokens[$newStackPtr] = $newToken; @@ -1971,7 +1973,7 @@ protected function tokenize($string) || $tokenType === ':')) ) { if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo "\t\t* token $stackPtr changed from ? to T_INLINE_THEN".PHP_EOL; + StatusWriter::write("* token $stackPtr changed from ? to T_INLINE_THEN", 2); } $newToken['code'] = T_INLINE_THEN; @@ -2019,7 +2021,7 @@ protected function tokenize($string) $newToken['type'] = 'T_NULLABLE'; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo "\t\t* token $stackPtr changed from ? to T_NULLABLE".PHP_EOL; + StatusWriter::write("* token $stackPtr changed from ? to T_NULLABLE", 2); } break; @@ -2035,7 +2037,7 @@ protected function tokenize($string) || $tokenType === T_READONLY ) { if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo "\t\t* token $stackPtr changed from ? to T_NULLABLE".PHP_EOL; + StatusWriter::write("* token $stackPtr changed from ? to T_NULLABLE", 2); } $newToken['code'] = T_NULLABLE; @@ -2043,7 +2045,7 @@ protected function tokenize($string) break; } else if (in_array($tokenType, [T_DOUBLE_ARROW, T_OPEN_TAG, T_OPEN_TAG_WITH_ECHO, '=', '{', ';'], true) === true) { if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo "\t\t* token $stackPtr changed from ? to T_INLINE_THEN".PHP_EOL; + StatusWriter::write("* token $stackPtr changed from ? to T_INLINE_THEN", 2); } $newToken['code'] = T_INLINE_THEN; @@ -2102,7 +2104,7 @@ protected function tokenize($string) $tokens[$stackPtr][0] = T_FN; $token[0] = T_FN; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo "\t\t* token $stackPtr changed from T_STRING to T_FN".PHP_EOL; + StatusWriter::write("* token $stackPtr changed from T_STRING to T_FN", 2); } } @@ -2175,7 +2177,7 @@ function return types. We want to keep the parenthesis map clean, ]; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo "\t\t* token $x changed from ? to T_NULLABLE".PHP_EOL; + StatusWriter::write("* token $x changed from ? to T_NULLABLE", 2); } continue; @@ -2228,8 +2230,8 @@ function return types. We want to keep the parenthesis map clean, ]; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo "\t\t* token $stackPtr changed from T_STRING to T_GOTO_LABEL".PHP_EOL; - echo "\t\t* skipping T_COLON token ".($stackPtr + 1).PHP_EOL; + StatusWriter::write("* token $stackPtr changed from T_STRING to T_GOTO_LABEL", 2); + StatusWriter::write('* skipping T_COLON token '.($stackPtr + 1), 2); } $newStackPtr++; @@ -2389,7 +2391,7 @@ function return types. We want to keep the parenthesis map clean, if ($tokens[$i][0] === T_PARAM_NAME) { $isInlineIf = false; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo "\t\t* token is parameter label, not T_INLINE_ELSE".PHP_EOL; + StatusWriter::write('* token is parameter label, not T_INLINE_ELSE', 2); } } @@ -2436,7 +2438,7 @@ function return types. We want to keep the parenthesis map clean, if ($tokens[$i][0] === T_FUNCTION || $tokens[$i][0] === T_FN || $tokens[$i][0] === T_USE) { $isInlineIf = false; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo "\t\t* token is return type, not T_INLINE_ELSE".PHP_EOL; + StatusWriter::write('* token is return type, not T_INLINE_ELSE', 2); } } }//end if @@ -2452,7 +2454,7 @@ function return types. We want to keep the parenthesis map clean, ) { $isInlineIf = false; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo "\t\t* token is T_CASE or T_DEFAULT opener, not T_INLINE_ELSE".PHP_EOL; + StatusWriter::write('* token is T_CASE or T_DEFAULT opener, not T_INLINE_ELSE', 2); } break; @@ -2474,7 +2476,7 @@ function return types. We want to keep the parenthesis map clean, $newToken['type'] = 'T_INLINE_ELSE'; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo "\t\t* token changed from T_COLON to T_INLINE_ELSE".PHP_EOL; + StatusWriter::write('* token changed from T_COLON to T_INLINE_ELSE', 2); } } }//end if @@ -2534,7 +2536,7 @@ function return types. We want to keep the parenthesis map clean, }//end for if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo "\t*** END PHP TOKENIZING ***".PHP_EOL; + StatusWriter::write('*** END PHP TOKENIZING ***', 1); } return $finalTokens; @@ -2557,7 +2559,7 @@ function return types. We want to keep the parenthesis map clean, protected function processAdditional() { if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo "\t*** START ADDITIONAL PHP PROCESSING ***".PHP_EOL; + StatusWriter::write('*** START ADDITIONAL PHP PROCESSING ***', 1); } $this->createAttributesNestingMap(); @@ -2593,7 +2595,7 @@ protected function processAdditional() $this->tokens[$i]['type'] = 'T_CLOSURE'; if (PHP_CODESNIFFER_VERBOSITY > 1) { $line = $this->tokens[$i]['line']; - echo "\t* token $i on line $line changed from T_FUNCTION to T_CLOSURE".PHP_EOL; + StatusWriter::write("* token $i on line $line changed from T_FUNCTION to T_CLOSURE", 1); } for ($x = ($this->tokens[$i]['scope_opener'] + 1); $x < $this->tokens[$i]['scope_closer']; $x++) { @@ -2604,7 +2606,7 @@ protected function processAdditional() $this->tokens[$x]['conditions'][$i] = T_CLOSURE; if (PHP_CODESNIFFER_VERBOSITY > 1) { $type = $this->tokens[$x]['type']; - echo "\t\t* cleaned $x ($type) *".PHP_EOL; + StatusWriter::write("* cleaned $x ($type) *", 2); } } } @@ -2631,7 +2633,7 @@ protected function processAdditional() $this->tokens[$i]['type'] = 'T_ANON_CLASS'; if (PHP_CODESNIFFER_VERBOSITY > 1) { $line = $this->tokens[$i]['line']; - echo "\t* token $i on line $line changed from T_CLASS to T_ANON_CLASS".PHP_EOL; + StatusWriter::write("* token $i on line $line changed from T_CLASS to T_ANON_CLASS", 1); } if ($this->tokens[$x]['code'] === T_OPEN_PARENTHESIS @@ -2647,7 +2649,7 @@ protected function processAdditional() if (PHP_CODESNIFFER_VERBOSITY > 1) { $line = $this->tokens[$i]['line']; - echo "\t\t* added parenthesis keys to T_ANON_CLASS token $i on line $line".PHP_EOL; + StatusWriter::write("* added parenthesis keys to T_ANON_CLASS token $i on line $line", 2); } } @@ -2659,7 +2661,7 @@ protected function processAdditional() $this->tokens[$x]['conditions'][$i] = T_ANON_CLASS; if (PHP_CODESNIFFER_VERBOSITY > 1) { $type = $this->tokens[$x]['type']; - echo "\t\t* cleaned $x ($type) *".PHP_EOL; + StatusWriter::write("* cleaned $x ($type) *", 2); } } }//end if @@ -2818,11 +2820,11 @@ protected function processAdditional() if ($scopeCloser !== $numTokens) { if (PHP_CODESNIFFER_VERBOSITY > 1) { $line = $this->tokens[$i]['line']; - echo "\t=> token $i on line $line processed as arrow function".PHP_EOL; - echo "\t\t* scope opener set to $arrow *".PHP_EOL; - echo "\t\t* scope closer set to $scopeCloser *".PHP_EOL; - echo "\t\t* parenthesis opener set to $x *".PHP_EOL; - echo "\t\t* parenthesis closer set to $closer *".PHP_EOL; + StatusWriter::write("=> token $i on line $line processed as arrow function", 1); + StatusWriter::write("* scope opener set to $arrow *", 2); + StatusWriter::write("* scope closer set to $scopeCloser *", 2); + StatusWriter::write("* parenthesis opener set to $x *", 2); + StatusWriter::write("* parenthesis closer set to $closer *", 2); } $this->tokens[$i]['code'] = T_FN; @@ -2851,7 +2853,7 @@ protected function processAdditional() if (PHP_CODESNIFFER_VERBOSITY > 1) { $line = $this->tokens[$arrow]['line']; - echo "\t\t* token $arrow on line $line changed from T_DOUBLE_ARROW to T_FN_ARROW".PHP_EOL; + StatusWriter::write("* token $arrow on line $line changed from T_DOUBLE_ARROW to T_FN_ARROW", 2); } }//end if }//end if @@ -2861,8 +2863,8 @@ protected function processAdditional() if (isset($this->tokens[$i]['scope_closer']) === false) { if (PHP_CODESNIFFER_VERBOSITY > 1) { $line = $this->tokens[$i]['line']; - echo "\t=> token $i on line $line is not an arrow function".PHP_EOL; - echo "\t\t* token changed from T_FN to T_STRING".PHP_EOL; + StatusWriter::write("=> token $i on line $line is not an arrow function", 1); + StatusWriter::write('* token changed from T_FN to T_STRING', 2); } $this->tokens[$i]['code'] = T_STRING; @@ -2921,9 +2923,9 @@ protected function processAdditional() $this->tokens[$closer]['type'] = 'T_CLOSE_SHORT_ARRAY'; if (PHP_CODESNIFFER_VERBOSITY > 1) { $line = $this->tokens[$i]['line']; - echo "\t* token $i on line $line changed from T_OPEN_SQUARE_BRACKET to T_OPEN_SHORT_ARRAY".PHP_EOL; + StatusWriter::write("* token $i on line $line changed from T_OPEN_SQUARE_BRACKET to T_OPEN_SHORT_ARRAY", 1); $line = $this->tokens[$closer]['line']; - echo "\t* token $closer on line $line changed from T_CLOSE_SQUARE_BRACKET to T_CLOSE_SHORT_ARRAY".PHP_EOL; + StatusWriter::write("* token $closer on line $line changed from T_CLOSE_SQUARE_BRACKET to T_CLOSE_SHORT_ARRAY", 1); } } @@ -2935,7 +2937,7 @@ protected function processAdditional() $this->tokens[$i]['type'] = 'T_STRING'; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo "\t\t* token $i changed from T_MATCH to T_STRING".PHP_EOL; + StatusWriter::write("* token $i changed from T_MATCH to T_STRING", 2); } if (isset($this->tokens[$i]['parenthesis_opener'], $this->tokens[$i]['parenthesis_closer']) === true) { @@ -2952,7 +2954,7 @@ protected function processAdditional() ); if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo "\t\t* cleaned parenthesis of token $i *".PHP_EOL; + StatusWriter::write("* cleaned parenthesis of token $i *", 2); } } } else { @@ -2992,7 +2994,7 @@ protected function processAdditional() $this->tokens[$x]['type'] = 'T_MATCH_ARROW'; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo "\t\t* token $x changed from T_DOUBLE_ARROW to T_MATCH_ARROW".PHP_EOL; + StatusWriter::write("* token $x changed from T_DOUBLE_ARROW to T_MATCH_ARROW", 2); } } }//end for @@ -3127,7 +3129,7 @@ protected function processAdditional() if (PHP_CODESNIFFER_VERBOSITY > 1) { $line = $this->tokens[$x]['line']; - echo "\t* token $x on line $line changed back from T_STRING to T_STATIC".PHP_EOL; + StatusWriter::write("* token $x on line $line changed back from T_STRING to T_STATIC", 1); } } @@ -3307,7 +3309,7 @@ protected function processAdditional() if (PHP_CODESNIFFER_VERBOSITY > 1) { $line = $this->tokens[$x]['line']; - echo "\t* token $x on line $line changed from T_BITWISE_OR to T_TYPE_UNION".PHP_EOL; + StatusWriter::write("* token $x on line $line changed from T_BITWISE_OR to T_TYPE_UNION", 1); } } else if ($this->tokens[$x]['code'] === T_BITWISE_AND) { $this->tokens[$x]['code'] = T_TYPE_INTERSECTION; @@ -3315,7 +3317,7 @@ protected function processAdditional() if (PHP_CODESNIFFER_VERBOSITY > 1) { $line = $this->tokens[$x]['line']; - echo "\t* token $x on line $line changed from T_BITWISE_AND to T_TYPE_INTERSECTION".PHP_EOL; + StatusWriter::write("* token $x on line $line changed from T_BITWISE_AND to T_TYPE_INTERSECTION", 1); } } else if ($this->tokens[$x]['code'] === T_OPEN_PARENTHESIS) { $this->tokens[$x]['code'] = T_TYPE_OPEN_PARENTHESIS; @@ -3323,7 +3325,7 @@ protected function processAdditional() if (PHP_CODESNIFFER_VERBOSITY > 1) { $line = $this->tokens[$x]['line']; - echo "\t* token $x on line $line changed from T_OPEN_PARENTHESIS to T_TYPE_OPEN_PARENTHESIS".PHP_EOL; + StatusWriter::write("* token $x on line $line changed from T_OPEN_PARENTHESIS to T_TYPE_OPEN_PARENTHESIS", 1); } } else if ($this->tokens[$x]['code'] === T_CLOSE_PARENTHESIS) { $this->tokens[$x]['code'] = T_TYPE_CLOSE_PARENTHESIS; @@ -3331,7 +3333,7 @@ protected function processAdditional() if (PHP_CODESNIFFER_VERBOSITY > 1) { $line = $this->tokens[$x]['line']; - echo "\t* token $x on line $line changed from T_CLOSE_PARENTHESIS to T_TYPE_CLOSE_PARENTHESIS".PHP_EOL; + StatusWriter::write("* token $x on line $line changed from T_CLOSE_PARENTHESIS to T_TYPE_CLOSE_PARENTHESIS", 1); } }//end if }//end foreach @@ -3342,7 +3344,7 @@ protected function processAdditional() if (PHP_CODESNIFFER_VERBOSITY > 1) { $line = $this->tokens[$maybeNullable]['line']; - echo "\t* token $maybeNullable on line $line changed from T_INLINE_THEN to T_NULLABLE".PHP_EOL; + StatusWriter::write("* token $maybeNullable on line $line changed from T_INLINE_THEN to T_NULLABLE", 1); } } @@ -3360,7 +3362,7 @@ protected function processAdditional() if (PHP_CODESNIFFER_VERBOSITY > 1) { $line = $this->tokens[$i]['line']; - echo "\t* token $i on line $line changed from T_STATIC to T_STRING".PHP_EOL; + StatusWriter::write("* token $i on line $line changed from T_STATIC to T_STRING", 1); } } @@ -3382,7 +3384,7 @@ protected function processAdditional() if (PHP_CODESNIFFER_VERBOSITY > 1) { $line = $this->tokens[$i]['line']; $type = $this->tokens[$i]['type']; - echo "\t* token $i on line $line changed from $type to T_STRING".PHP_EOL; + StatusWriter::write("* token $i on line $line changed from $type to T_STRING", 1); } $this->tokens[$i]['code'] = T_STRING; @@ -3423,7 +3425,7 @@ protected function processAdditional() $oldType = $this->tokens[$scopeCloser]['type']; $newType = $this->tokens[$newCloser]['type']; $line = $this->tokens[$i]['line']; - echo "\t* token $i (T_CASE) on line $line closer changed from $scopeCloser ($oldType) to $newCloser ($newType)".PHP_EOL; + StatusWriter::write("* token $i (T_CASE) on line $line closer changed from $scopeCloser ($oldType) to $newCloser ($newType)", 1); } continue; @@ -3452,11 +3454,11 @@ protected function processAdditional() $oldType = $this->tokens[$scopeOpener]['type']; $newType = $this->tokens[$x]['type']; - echo "\t* token $i ($tokenType) on line $line opener changed from $scopeOpener ($oldType) to $x ($newType)".PHP_EOL; + StatusWriter::write("* token $i ($tokenType) on line $line opener changed from $scopeOpener ($oldType) to $x ($newType)", 1); $oldType = $this->tokens[$scopeCloser]['type']; $newType = $this->tokens[$newCloser]['type']; - echo "\t* token $i ($tokenType) on line $line closer changed from $scopeCloser ($oldType) to $newCloser ($newType)".PHP_EOL; + StatusWriter::write("* token $i ($tokenType) on line $line closer changed from $scopeCloser ($oldType) to $newCloser ($newType)", 1); } if ($this->tokens[$scopeOpener]['scope_condition'] === $i) { @@ -3486,7 +3488,7 @@ protected function processAdditional() $tokenType = $this->tokens[$y]['type']; $oldType = $this->tokens[$scopeCloser]['type']; $newType = $this->tokens[$newCloser]['type']; - echo "\t\t* token $y ($tokenType) on line $line closer changed from $scopeCloser ($oldType) to $newCloser ($newType)".PHP_EOL; + StatusWriter::write("* token $y ($tokenType) on line $line closer changed from $scopeCloser ($oldType) to $newCloser ($newType)", 2); } } } @@ -3522,8 +3524,8 @@ protected function processAdditional() $newConds = rtrim($newConds, ','); - echo "\t\t* cleaned $x ($type) *".PHP_EOL; - echo "\t\t\t=> conditions changed from $oldConds to $newConds".PHP_EOL; + StatusWriter::write("* cleaned $x ($type) *", 2); + StatusWriter::write("=> conditions changed from $oldConds to $newConds", 3); } break; @@ -3533,7 +3535,7 @@ protected function processAdditional() }//end for if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo "\t*** END ADDITIONAL PHP PROCESSING ***".PHP_EOL; + StatusWriter::write('*** END ADDITIONAL PHP PROCESSING ***', 1); } }//end processAdditional() diff --git a/src/Tokenizers/Tokenizer.php b/src/Tokenizers/Tokenizer.php index 61720c2560..929e5bda31 100644 --- a/src/Tokenizers/Tokenizer.php +++ b/src/Tokenizers/Tokenizer.php @@ -12,6 +12,7 @@ use PHP_CodeSniffer\Exceptions\TokenizerException; use PHP_CodeSniffer\Util\Common; use PHP_CodeSniffer\Util\Tokens; +use PHP_CodeSniffer\Util\Writers\StatusWriter; abstract class Tokenizer { @@ -620,7 +621,7 @@ public function replaceTabsInToken(&$token, $prefix=' ', $padding=' ', $tabWidth private function createTokenMap() { if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo "\t*** START TOKEN MAP ***".PHP_EOL; + StatusWriter::write('*** START TOKEN MAP ***', 1); } $squareOpeners = []; @@ -642,24 +643,21 @@ private function createTokenMap() $openOwner = $i; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", (count($openers) + 1)); - echo "=> Found parenthesis owner at $i".PHP_EOL; + StatusWriter::write("=> Found parenthesis owner at $i", (count($openers) + 1)); } } else if ($this->tokens[$i]['code'] === T_OPEN_PARENTHESIS) { $openers[] = $i; $this->tokens[$i]['parenthesis_opener'] = $i; if ($openOwner !== null) { if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", count($openers)); - echo "=> Found parenthesis opener at $i for $openOwner".PHP_EOL; + StatusWriter::write("=> Found parenthesis opener at $i for $openOwner", count($openers)); } $this->tokens[$openOwner]['parenthesis_opener'] = $i; $this->tokens[$i]['parenthesis_owner'] = $openOwner; $openOwner = null; } else if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", count($openers)); - echo "=> Found unowned parenthesis opener at $i".PHP_EOL; + StatusWriter::write("=> Found unowned parenthesis opener at $i", count($openers)); } } else if ($this->tokens[$i]['code'] === T_CLOSE_PARENTHESIS) { // Did we set an owner for this set of parenthesis? @@ -673,12 +671,10 @@ private function createTokenMap() $this->tokens[$i]['parenthesis_owner'] = $owner; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", (count($openers) + 1)); - echo "=> Found parenthesis closer at $i for $owner".PHP_EOL; + StatusWriter::write("=> Found parenthesis closer at $i for $owner", (count($openers) + 1)); } } else if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", (count($openers) + 1)); - echo "=> Found unowned parenthesis closer at $i for $opener".PHP_EOL; + StatusWriter::write("=> Found unowned parenthesis closer at $i for $opener", (count($openers) + 1)); } $this->tokens[$i]['parenthesis_opener'] = $opener; @@ -688,8 +684,7 @@ private function createTokenMap() } else if ($this->tokens[$i]['code'] === T_ATTRIBUTE) { $openers[] = $i; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", count($openers)); - echo "=> Found attribute opener at $i".PHP_EOL; + StatusWriter::write("=> Found attribute opener at $i", count($openers)); } $this->tokens[$i]['attribute_opener'] = $i; @@ -702,8 +697,7 @@ private function createTokenMap() $this->tokens[$opener]['attribute_closer'] = $i; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", (count($openers) + 1)); - echo "=> Found attribute closer at $i for $opener".PHP_EOL; + StatusWriter::write("=> Found attribute closer at $i for $opener", (count($openers) + 1)); } for ($x = ($opener + 1); $x <= $i; ++$x) { @@ -715,8 +709,7 @@ private function createTokenMap() $this->tokens[$x]['attribute_closer'] = $i; } } else if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", (count($openers) + 1)); - echo "=> Found unowned attribute closer at $i for $opener".PHP_EOL; + StatusWriter::write("=> Found unowned attribute closer at $i for $opener", (count($openers) + 1)); } }//end if }//end if @@ -730,9 +723,7 @@ private function createTokenMap() $squareOpeners[] = $i; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", count($squareOpeners)); - echo str_repeat("\t", count($curlyOpeners)); - echo "=> Found square bracket opener at $i".PHP_EOL; + StatusWriter::write("=> Found square bracket opener at $i", (count($squareOpeners) + count($curlyOpeners))); } break; case T_OPEN_CURLY_BRACKET: @@ -740,9 +731,7 @@ private function createTokenMap() $curlyOpeners[] = $i; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", count($squareOpeners)); - echo str_repeat("\t", count($curlyOpeners)); - echo "=> Found curly bracket opener at $i".PHP_EOL; + StatusWriter::write("=> Found curly bracket opener at $i", (count($squareOpeners) + count($curlyOpeners))); } } break; @@ -755,9 +744,7 @@ private function createTokenMap() $this->tokens[$opener]['bracket_closer'] = $i; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", count($squareOpeners)); - echo str_repeat("\t", count($curlyOpeners)); - echo "\t=> Found square bracket closer at $i for $opener".PHP_EOL; + StatusWriter::write("=> Found square bracket closer at $i for $opener", (count($squareOpeners) + count($curlyOpeners) + 1)); } } break; @@ -772,9 +759,7 @@ private function createTokenMap() $this->tokens[$opener]['bracket_closer'] = $i; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", count($squareOpeners)); - echo str_repeat("\t", count($curlyOpeners)); - echo "\t=> Found curly bracket closer at $i for $opener".PHP_EOL; + StatusWriter::write("=> Found curly bracket closer at $i for $opener", (count($squareOpeners) + count($curlyOpeners) + 1)); } } break; @@ -791,7 +776,7 @@ private function createTokenMap() } if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo "\t*** END TOKEN MAP ***".PHP_EOL; + StatusWriter::write('*** END TOKEN MAP ***', 1); } }//end createTokenMap() @@ -843,7 +828,7 @@ private function createParenthesisNestingMap() private function createScopeMap() { if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo "\t*** START SCOPE MAP ***".PHP_EOL; + StatusWriter::write('*** START SCOPE MAP ***', 1); } for ($i = 0; $i < $this->numTokens; $i++) { @@ -852,12 +837,12 @@ private function createScopeMap() if (PHP_CODESNIFFER_VERBOSITY > 1) { $type = $this->tokens[$i]['type']; $content = Common::prepareForOutput($this->tokens[$i]['content']); - echo "\tStart scope map at $i:$type => $content".PHP_EOL; + StatusWriter::write("Start scope map at $i:$type => $content", 1); } if (isset($this->tokens[$i]['scope_condition']) === true) { if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo "\t* already processed, skipping *".PHP_EOL; + StatusWriter::write('* already processed, skipping *', 1); } continue; @@ -868,7 +853,7 @@ private function createScopeMap() }//end for if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo "\t*** END SCOPE MAP ***".PHP_EOL; + StatusWriter::write('*** END SCOPE MAP ***', 1); } }//end createScopeMap() @@ -888,8 +873,7 @@ private function createScopeMap() private function recurseScopeMap($stackPtr, $depth=1, &$ignore=0) { if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", $depth); - echo "=> Begin scope map recursion at token $stackPtr with depth $depth".PHP_EOL; + StatusWriter::write("=> Begin scope map recursion at token $stackPtr with depth $depth", $depth); } $opener = null; @@ -915,17 +899,17 @@ private function recurseScopeMap($stackPtr, $depth=1, &$ignore=0) $line = $this->tokens[$i]['line']; $content = Common::prepareForOutput($this->tokens[$i]['content']); - echo str_repeat("\t", $depth); - echo "Process token $i on line $line ["; + $statusMessage = "Process token $i on line $line ["; if ($opener !== null) { - echo "opener:$opener;"; + $statusMessage .= "opener:$opener;"; } if ($ignore > 0) { - echo "ignore=$ignore;"; + $statusMessage .= "ignore=$ignore;"; } - echo "]: $type => $content".PHP_EOL; + $statusMessage .= "]: $type => $content"; + StatusWriter::write($statusMessage, $depth); }//end if // Very special case for IF statements in PHP that can be defined without @@ -941,14 +925,13 @@ private function recurseScopeMap($stackPtr, $depth=1, &$ignore=0) ) { if (PHP_CODESNIFFER_VERBOSITY > 1) { $type = $this->tokens[$stackPtr]['type']; - echo str_repeat("\t", $depth); if ($this->tokens[$i]['code'] === T_SEMICOLON) { $closerType = 'semicolon'; } else { $closerType = 'close tag'; } - echo "=> Found $closerType before scope opener for $stackPtr:$type, bailing".PHP_EOL; + StatusWriter::write("=> Found $closerType before scope opener for $stackPtr:$type, bailing", $depth); } return $i; @@ -965,8 +948,7 @@ private function recurseScopeMap($stackPtr, $depth=1, &$ignore=0) ) { if (PHP_CODESNIFFER_VERBOSITY > 1) { $type = $this->tokens[$stackPtr]['type']; - echo str_repeat("\t", $depth); - echo "=> Found curly brace closer before scope opener for $stackPtr:$type, bailing".PHP_EOL; + StatusWriter::write("=> Found curly brace closer before scope opener for $stackPtr:$type, bailing", $depth); } return ($i - 1); @@ -981,8 +963,7 @@ private function recurseScopeMap($stackPtr, $depth=1, &$ignore=0) // The last opening bracket must have been for a string // offset or alike, so let's ignore it. if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", $depth); - echo '* finished ignoring curly brace *'.PHP_EOL; + StatusWriter::write('* finished ignoring curly brace *', $depth); } $ignore--; @@ -995,8 +976,7 @@ private function recurseScopeMap($stackPtr, $depth=1, &$ignore=0) // a closer of T_IF when it should not. if (PHP_CODESNIFFER_VERBOSITY > 1) { $type = $this->tokens[$stackPtr]['type']; - echo str_repeat("\t", $depth); - echo "=> Ignoring non-curly scope closer for $stackPtr:$type".PHP_EOL; + StatusWriter::write("=> Ignoring non-curly scope closer for $stackPtr:$type", $depth); } } else { $scopeCloser = $i; @@ -1008,8 +988,7 @@ private function recurseScopeMap($stackPtr, $depth=1, &$ignore=0) if (PHP_CODESNIFFER_VERBOSITY > 1) { $type = $this->tokens[$stackPtr]['type']; $closerType = $this->tokens[$scopeCloser]['type']; - echo str_repeat("\t", $depth); - echo "=> Found scope closer ($scopeCloser:$closerType) for $stackPtr:$type".PHP_EOL; + StatusWriter::write("=> Found scope closer ($scopeCloser:$closerType) for $stackPtr:$type", $depth); } $validCloser = true; @@ -1018,8 +997,7 @@ private function recurseScopeMap($stackPtr, $depth=1, &$ignore=0) ) { // To be a closer, this token must have an opener. if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", $depth); - echo "* closer needs to be tested *".PHP_EOL; + StatusWriter::write('* closer needs to be tested *', $depth); } $i = self::recurseScopeMap($i, ($depth + 1), $ignore); @@ -1027,20 +1005,17 @@ private function recurseScopeMap($stackPtr, $depth=1, &$ignore=0) if (isset($this->tokens[$scopeCloser]['scope_opener']) === false) { $validCloser = false; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", $depth); - echo "* closer is not valid (no opener found) *".PHP_EOL; + StatusWriter::write('* closer is not valid (no opener found) *', $depth); } } else if ($this->tokens[$this->tokens[$scopeCloser]['scope_opener']]['code'] !== $this->tokens[$opener]['code']) { $validCloser = false; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", $depth); $type = $this->tokens[$this->tokens[$scopeCloser]['scope_opener']]['type']; $openerType = $this->tokens[$opener]['type']; - echo "* closer is not valid (mismatched opener type; $type != $openerType) *".PHP_EOL; + StatusWriter::write("* closer is not valid (mismatched opener type; $type != $openerType) *", $depth); } } else if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", $depth); - echo "* closer was valid *".PHP_EOL; + StatusWriter::write('* closer was valid *', $depth); } } else { // The closer was not processed, so we need to @@ -1103,15 +1078,13 @@ private function recurseScopeMap($stackPtr, $depth=1, &$ignore=0) // Probably a closure, so process it manually. if (PHP_CODESNIFFER_VERBOSITY > 1) { $type = $this->tokens[$stackPtr]['type']; - echo str_repeat("\t", $depth); - echo "=> Found function before scope opener for $stackPtr:$type, processing manually".PHP_EOL; + StatusWriter::write("=> Found function before scope opener for $stackPtr:$type, processing manually", $depth); } if (isset($this->tokens[$i]['scope_closer']) === true) { // We've already processed this closure. if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", $depth); - echo '* already processed, skipping *'.PHP_EOL; + StatusWriter::write('* already processed, skipping *', $depth); } $i = $this->tokens[$i]['scope_closer']; @@ -1127,15 +1100,13 @@ private function recurseScopeMap($stackPtr, $depth=1, &$ignore=0) // so process it manually. if (PHP_CODESNIFFER_VERBOSITY > 1) { $type = $this->tokens[$stackPtr]['type']; - echo str_repeat("\t", $depth); - echo "=> Found class before scope opener for $stackPtr:$type, processing manually".PHP_EOL; + StatusWriter::write("=> Found class before scope opener for $stackPtr:$type, processing manually", $depth); } if (isset($this->tokens[$i]['scope_closer']) === true) { // We've already processed this anon class. if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", $depth); - echo '* already processed, skipping *'.PHP_EOL; + StatusWriter::write('* already processed, skipping *', $depth); } $i = $this->tokens[$i]['scope_closer']; @@ -1150,8 +1121,7 @@ private function recurseScopeMap($stackPtr, $depth=1, &$ignore=0) // found our opener, so we are never going to find one. if (PHP_CODESNIFFER_VERBOSITY > 1) { $type = $this->tokens[$stackPtr]['type']; - echo str_repeat("\t", $depth); - echo "=> Found new opening condition before scope opener for $stackPtr:$type, "; + StatusWriter::write("=> Found new opening condition before scope opener for $stackPtr:$type, ", $depth, 0); } if (($this->tokens[$stackPtr]['code'] === T_IF @@ -1161,13 +1131,13 @@ private function recurseScopeMap($stackPtr, $depth=1, &$ignore=0) || $this->tokens[$i]['code'] === T_ELSEIF) ) { if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo "continuing".PHP_EOL; + StatusWriter::write('continuing'); } return ($i - 1); } else { if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo "backtracking".PHP_EOL; + StatusWriter::write('backtracking'); } return $stackPtr; @@ -1175,8 +1145,7 @@ private function recurseScopeMap($stackPtr, $depth=1, &$ignore=0) }//end if if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", $depth); - echo '* token is an opening condition *'.PHP_EOL; + StatusWriter::write('* token is an opening condition *', $depth); } $isShared = ($this->scopeOpeners[$tokenType]['shared'] === true); @@ -1184,8 +1153,7 @@ private function recurseScopeMap($stackPtr, $depth=1, &$ignore=0) if (isset($this->tokens[$i]['scope_condition']) === true) { // We've been here before. if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", $depth); - echo '* already processed, skipping *'.PHP_EOL; + StatusWriter::write('* already processed, skipping *', $depth); } if ($isShared === false @@ -1203,15 +1171,13 @@ private function recurseScopeMap($stackPtr, $depth=1, &$ignore=0) // scope opener which is the same type as us, and we don't // share openers, so we will never find one. if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", $depth); - echo '* it was another token\'s opener, bailing *'.PHP_EOL; + StatusWriter::write('* it was another token\'s opener, bailing *', $depth); } return $stackPtr; } else { if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", $depth); - echo '* searching for opener *'.PHP_EOL; + StatusWriter::write('* searching for opener *', $depth); } if (isset($this->scopeOpeners[$tokenType]['end'][T_CLOSE_CURLY_BRACKET]) === true) { @@ -1223,8 +1189,7 @@ private function recurseScopeMap($stackPtr, $depth=1, &$ignore=0) // because too many loops means we've run into trouble anyway. if ($depth > 50) { if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", $depth); - echo '* reached maximum nesting level; aborting *'.PHP_EOL; + StatusWriter::write('* reached maximum nesting level; aborting *', $depth); } throw new TokenizerException('Maximum nesting level reached; file could not be processed'); @@ -1260,8 +1225,7 @@ private function recurseScopeMap($stackPtr, $depth=1, &$ignore=0) // We found a curly brace inside the condition of the // current scope opener, so it must be a string offset. if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", $depth); - echo '* ignoring curly brace inside condition *'.PHP_EOL; + StatusWriter::write('* ignoring curly brace inside condition *', $depth); } $ignore++; @@ -1287,8 +1251,7 @@ private function recurseScopeMap($stackPtr, $depth=1, &$ignore=0) if (isset($disallowed[$this->tokens[$x]['code']]) === true) { if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", $depth); - echo '* ignoring curly brace *'.PHP_EOL; + StatusWriter::write('* ignoring curly brace *', $depth); } $ignore++; @@ -1312,15 +1275,13 @@ private function recurseScopeMap($stackPtr, $depth=1, &$ignore=0) // We found the a token that looks like the opener, but it's nested differently. if (PHP_CODESNIFFER_VERBOSITY > 1) { $type = $this->tokens[$i]['type']; - echo str_repeat("\t", $depth); - echo "* ignoring possible opener $i:$type as nested parenthesis don't match *".PHP_EOL; + StatusWriter::write("* ignoring possible opener $i:$type as nested parenthesis don't match *", $depth); } } else { // We found the opening scope token for $currType. if (PHP_CODESNIFFER_VERBOSITY > 1) { $type = $this->tokens[$stackPtr]['type']; - echo str_repeat("\t", $depth); - echo "=> Found scope opener for $stackPtr:$type".PHP_EOL; + StatusWriter::write("=> Found scope opener for $stackPtr:$type", $depth); } $opener = $i; @@ -1335,8 +1296,7 @@ private function recurseScopeMap($stackPtr, $depth=1, &$ignore=0) // found our opener, so we are never going to find one. if (PHP_CODESNIFFER_VERBOSITY > 1) { $type = $this->tokens[$stackPtr]['type']; - echo str_repeat("\t", $depth); - echo "=> Found end of statement before scope opener for $stackPtr:$type, continuing".PHP_EOL; + StatusWriter::write("=> Found end of statement before scope opener for $stackPtr:$type, continuing", $depth); } return ($i - 1); @@ -1360,16 +1320,14 @@ private function recurseScopeMap($stackPtr, $depth=1, &$ignore=0) // We want to ignore this so that we don't have an invalid scope // map. if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", $depth); - echo '* ignoring curly brace *'.PHP_EOL; + StatusWriter::write('* ignoring curly brace *', $depth); } $ignore++; } else if ($tokenType === T_CLOSE_CURLY_BRACKET && $ignore > 0) { // We found the end token for the opener we were ignoring. if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", $depth); - echo '* finished ignoring curly brace *'.PHP_EOL; + StatusWriter::write('* finished ignoring curly brace *', $depth); } $ignore--; @@ -1388,14 +1346,12 @@ private function recurseScopeMap($stackPtr, $depth=1, &$ignore=0) if (PHP_CODESNIFFER_VERBOSITY > 1) { $type = $this->tokens[$stackPtr]['type']; $lines = ($this->tokens[$i]['line'] - $startLine); - echo str_repeat("\t", $depth); - echo "=> Still looking for $stackPtr:$type scope opener after $lines lines".PHP_EOL; + StatusWriter::write("=> Still looking for $stackPtr:$type scope opener after $lines lines", $depth); } } else { if (PHP_CODESNIFFER_VERBOSITY > 1) { $type = $this->tokens[$stackPtr]['type']; - echo str_repeat("\t", $depth); - echo "=> Couldn't find scope opener for $stackPtr:$type, bailing".PHP_EOL; + StatusWriter::write("=> Couldn't find scope opener for $stackPtr:$type, bailing", $depth); } return $stackPtr; @@ -1409,8 +1365,7 @@ private function recurseScopeMap($stackPtr, $depth=1, &$ignore=0) if ($ignore > 0) { // We found the end token for the opener we were ignoring. if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", $depth); - echo '* finished ignoring curly brace *'.PHP_EOL; + StatusWriter::write('* finished ignoring curly brace *', $depth); } $ignore--; @@ -1421,8 +1376,7 @@ private function recurseScopeMap($stackPtr, $depth=1, &$ignore=0) // the closer. if (PHP_CODESNIFFER_VERBOSITY > 1) { $type = $this->tokens[$stackPtr]['type']; - echo str_repeat("\t", $depth); - echo "=> Found (unexpected) scope closer for $stackPtr:$type".PHP_EOL; + StatusWriter::write("=> Found (unexpected) scope closer for $stackPtr:$type", $depth); } foreach ([$stackPtr, $opener] as $token) { @@ -1455,7 +1409,7 @@ private function recurseScopeMap($stackPtr, $depth=1, &$ignore=0) private function createLevelMap() { if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo "\t*** START LEVEL MAP ***".PHP_EOL; + StatusWriter::write('*** START LEVEL MAP ***', 1); } $this->numTokens = count($this->tokens); @@ -1473,18 +1427,18 @@ private function createLevelMap() $content = Common::prepareForOutput($this->tokens[$i]['content']); - echo str_repeat("\t", ($level + 1)); - echo "Process token $i on line $line [col:$col;len:$len;lvl:$level;"; + $statusMessage = "Process token $i on line $line [col:$col;len:$len;lvl:$level;"; if (empty($conditions) !== true) { $conditionString = 'conds;'; foreach ($conditions as $condition) { $conditionString .= Tokens::tokenName($condition).','; } - echo rtrim($conditionString, ',').';'; + $statusMessage .= rtrim($conditionString, ',').';'; } - echo "]: $type => $content".PHP_EOL; + $statusMessage .= "]: $type => $content"; + StatusWriter::write($statusMessage, ($level + 1)); }//end if $this->tokens[$i]['level'] = $level; @@ -1496,8 +1450,7 @@ private function createLevelMap() $stackPtr = $this->tokens[$i]['scope_condition']; if (PHP_CODESNIFFER_VERBOSITY > 1) { $type = $this->tokens[$stackPtr]['type']; - echo str_repeat("\t", ($level + 1)); - echo "=> Found scope opener for $stackPtr:$type".PHP_EOL; + StatusWriter::write("=> Found scope opener for $stackPtr:$type", ($level + 1)); } $stackPtr = $this->tokens[$i]['scope_condition']; @@ -1526,8 +1479,7 @@ private function createLevelMap() $badToken = $opener; if (PHP_CODESNIFFER_VERBOSITY > 1) { $type = $this->tokens[$badToken]['type']; - echo str_repeat("\t", ($level + 1)); - echo "* shared closer, cleaning up $badToken:$type *".PHP_EOL; + StatusWriter::write("* shared closer, cleaning up $badToken:$type *", ($level + 1)); } for ($x = $this->tokens[$i]['scope_condition']; $x <= $i; $x++) { @@ -1552,43 +1504,36 @@ private function createLevelMap() $newConds = rtrim($newConds, ','); $newLevel = $this->tokens[$x]['level']; - echo str_repeat("\t", ($level + 1)); - echo "* cleaned $x:$type *".PHP_EOL; - echo str_repeat("\t", ($level + 2)); - echo "=> level changed from $oldLevel to $newLevel".PHP_EOL; - echo str_repeat("\t", ($level + 2)); - echo "=> conditions changed from $oldConds to $newConds".PHP_EOL; + StatusWriter::write("* cleaned $x:$type *", ($level + 1)); + StatusWriter::write("=> level changed from $oldLevel to $newLevel", ($level + 2)); + StatusWriter::write("=> conditions changed from $oldConds to $newConds", ($level + 2)); }//end if }//end for unset($conditions[$badToken]); if (PHP_CODESNIFFER_VERBOSITY > 1) { $type = $this->tokens[$badToken]['type']; - echo str_repeat("\t", ($level + 1)); - echo "* token $badToken:$type removed from conditions array *".PHP_EOL; + StatusWriter::write("* token $badToken:$type removed from conditions array *", ($level + 1)); } unset($openers[$lastOpener]); $level--; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", ($level + 2)); - echo '* level decreased *'.PHP_EOL; + StatusWriter::write('* level decreased *', ($level + 2)); } }//end if }//end if $level++; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", ($level + 1)); - echo '* level increased *'.PHP_EOL; + StatusWriter::write('* level increased *', ($level + 1)); } $conditions[$stackPtr] = $this->tokens[$stackPtr]['code']; if (PHP_CODESNIFFER_VERBOSITY > 1) { $type = $this->tokens[$stackPtr]['type']; - echo str_repeat("\t", ($level + 1)); - echo "* token $stackPtr:$type added to conditions array *".PHP_EOL; + StatusWriter::write("* token $stackPtr:$type added to conditions array *", ($level + 1)); } $lastOpener = $this->tokens[$i]['scope_opener']; @@ -1608,14 +1553,12 @@ private function createLevelMap() if (PHP_CODESNIFFER_VERBOSITY > 1) { $type = $this->tokens[$oldOpener]['type']; - echo str_repeat("\t", ($level + 1)); - echo "=> Found scope closer for $oldOpener:$type".PHP_EOL; + StatusWriter::write("=> Found scope closer for $oldOpener:$type", ($level + 1)); } $oldCondition = array_pop($conditions); if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", ($level + 1)); - echo '* token '.Tokens::tokenName($oldCondition).' removed from conditions array *'.PHP_EOL; + StatusWriter::write('* token '.Tokens::tokenName($oldCondition).' removed from conditions array *', ($level + 1)); } // Make sure this closer actually belongs to us. @@ -1628,8 +1571,7 @@ private function createLevelMap() if (PHP_CODESNIFFER_VERBOSITY > 1) { $type = Tokens::tokenName($oldCondition); - echo str_repeat("\t", ($level + 1)); - echo "* scope closer was bad, cleaning up $badToken:$type *".PHP_EOL; + StatusWriter::write("* scope closer was bad, cleaning up $badToken:$type *", ($level + 1)); } for ($x = ($oldOpener + 1); $x <= $i; $x++) { @@ -1654,12 +1596,9 @@ private function createLevelMap() $newConds = rtrim($newConds, ','); $newLevel = $this->tokens[$x]['level']; - echo str_repeat("\t", ($level + 1)); - echo "* cleaned $x:$type *".PHP_EOL; - echo str_repeat("\t", ($level + 2)); - echo "=> level changed from $oldLevel to $newLevel".PHP_EOL; - echo str_repeat("\t", ($level + 2)); - echo "=> conditions changed from $oldConds to $newConds".PHP_EOL; + StatusWriter::write("* cleaned $x:$type *", ($level + 1)); + StatusWriter::write("=> level changed from $oldLevel to $newLevel", ($level + 2)); + StatusWriter::write("=> conditions changed from $oldConds to $newConds", ($level + 2)); }//end if }//end for }//end if @@ -1667,8 +1606,7 @@ private function createLevelMap() $level--; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo str_repeat("\t", ($level + 2)); - echo '* level decreased *'.PHP_EOL; + StatusWriter::write('* level decreased *', ($level + 2)); } $this->tokens[$i]['level'] = $level; @@ -1680,7 +1618,7 @@ private function createLevelMap() }//end for if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo "\t*** END LEVEL MAP ***".PHP_EOL; + StatusWriter::write('*** END LEVEL MAP ***', 1); } }//end createLevelMap() diff --git a/src/Util/Cache.php b/src/Util/Cache.php index 408de96e7d..9d8d35d0b2 100644 --- a/src/Util/Cache.php +++ b/src/Util/Cache.php @@ -13,6 +13,7 @@ use PHP_CodeSniffer\Autoload; use PHP_CodeSniffer\Config; use PHP_CodeSniffer\Ruleset; +use PHP_CodeSniffer\Util\Writers\StatusWriter; use RecursiveCallbackFilterIterator; use RecursiveDirectoryIterator; use RecursiveIteratorIterator; @@ -50,7 +51,8 @@ public static function load(Ruleset $ruleset, Config $config) // At this point, the loaded class list contains the core PHPCS code // and all sniffs that have been loaded as part of the run. if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo PHP_EOL."\tGenerating loaded file list for code hash".PHP_EOL; + StatusWriter::writeNewline(); + StatusWriter::write('Generating loaded file list for code hash', 1); } $codeHashFiles = []; @@ -70,10 +72,10 @@ public static function load(Ruleset $ruleset, Config $config) } if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo "\t\t=> external file: $file".PHP_EOL; + StatusWriter::write("=> external file: $file", 2); } } else if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo "\t\t=> internal sniff: $file".PHP_EOL; + StatusWriter::write("=> internal sniff: $file", 2); } $codeHashFiles[] = $file; @@ -86,10 +88,10 @@ public static function load(Ruleset $ruleset, Config $config) foreach ($rulesets as $file) { if (substr($file, 0, $standardDirLen) !== $standardDir) { if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo "\t\t=> external ruleset: $file".PHP_EOL; + StatusWriter::write("=> external ruleset: $file", 2); } } else if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo "\t\t=> internal ruleset: $file".PHP_EOL; + StatusWriter::write("=> internal ruleset: $file", 2); } $codeHashFiles[] = $file; @@ -133,7 +135,7 @@ function ($file, $key, $iterator) { $iterator = new RecursiveIteratorIterator($filter); foreach ($iterator as $file) { if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo "\t\t=> core file: $file".PHP_EOL; + StatusWriter::write("=> core file: $file", 2); } $codeHashFiles[] = $file->getPathname(); @@ -168,12 +170,12 @@ function ($file, $key, $iterator) { $cacheHash = substr(sha1($configString), 0, 12); if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo "\tGenerating cache key data".PHP_EOL; + StatusWriter::write('Generating cache key data', 1); foreach ($configData as $key => $value) { if (is_array($value) === true) { - echo "\t\t=> $key:".PHP_EOL; + StatusWriter::write("=> $key:", 2); foreach ($value as $subKey => $subValue) { - echo "\t\t\t=> $subKey: $subValue".PHP_EOL; + StatusWriter::write("=> $subKey: $subValue", 3); } continue; @@ -183,10 +185,10 @@ function ($file, $key, $iterator) { $value = (int) $value; } - echo "\t\t=> $key: $value".PHP_EOL; + StatusWriter::write("=> $key: $value", 2); } - echo "\t\t=> cacheHash: $cacheHash".PHP_EOL; + StatusWriter::write("=> cacheHash: $cacheHash", 2); }//end if if ($config->cacheFile !== null) { @@ -196,7 +198,7 @@ function ($file, $key, $iterator) { // We can use this to locate an existing cache file, or to // determine where to create a new one. if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo "\tChecking possible cache file paths".PHP_EOL; + StatusWriter::write('Checking possible cache file paths', 1); } $paths = []; @@ -245,8 +247,8 @@ function ($file, $key, $iterator) { } if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo "\t\t=> $testFile".PHP_EOL; - echo "\t\t\t * based on shared location: $file *".PHP_EOL; + StatusWriter::write("=> $testFile", 2); + StatusWriter::write(" * based on shared location: $file *", 3); } if (file_exists($testFile) === true) { @@ -263,7 +265,7 @@ function ($file, $key, $iterator) { self::$path = $cacheFile; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo "\t=> Using cache file: ".self::$path.PHP_EOL; + StatusWriter::write('=> Using cache file: '.self::$path, 1); } if (file_exists(self::$path) === true) { @@ -273,11 +275,11 @@ function ($file, $key, $iterator) { if (self::$cache['config'] !== $configData) { self::$cache = []; if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo "\t* cache was invalid and has been cleared *".PHP_EOL; + StatusWriter::write('* cache was invalid and has been cleared *', 1); } } } else if (PHP_CODESNIFFER_VERBOSITY > 1) { - echo "\t* cache file does not exist *".PHP_EOL; + StatusWriter::write('* cache file does not exist *', 1); } self::$cache['config'] = $configData; diff --git a/src/Util/MessageCollector.php b/src/Util/MessageCollector.php index 92884ceecd..a334c3e563 100644 --- a/src/Util/MessageCollector.php +++ b/src/Util/MessageCollector.php @@ -23,6 +23,7 @@ use InvalidArgumentException; use PHP_CodeSniffer\Exceptions\RuntimeException; +use PHP_CodeSniffer\Util\Writers\StatusWriter; final class MessageCollector { @@ -161,12 +162,12 @@ public function display($order=self::ORDERBY_SEVERITY) $messages = $this->sortBySeverity($messageInfo); } - $allMessages = implode(PHP_EOL, $messages).PHP_EOL.PHP_EOL; + $allMessages = implode(PHP_EOL, $messages); if ($blocking === true) { - throw new RuntimeException($allMessages); + throw new RuntimeException($allMessages.PHP_EOL.PHP_EOL); } else { - echo $allMessages; + StatusWriter::write($allMessages, 0, 2); } }//end display() diff --git a/src/Util/Timing.php b/src/Util/Timing.php index 95f6810b3b..be3f299f08 100644 --- a/src/Util/Timing.php +++ b/src/Util/Timing.php @@ -9,6 +9,8 @@ namespace PHP_CodeSniffer\Util; +use PHP_CodeSniffer\Util\Writers\StatusWriter; + class Timing { @@ -123,7 +125,7 @@ public static function printRunTime($force=false) $duration = self::getHumanReadableDuration($duration); $mem = round((memory_get_peak_usage(true) / (1024 * 1024)), 2).'MB'; - echo "Time: $duration; Memory: $mem".PHP_EOL.PHP_EOL; + StatusWriter::write("Time: $duration; Memory: $mem"); self::$printed = true; diff --git a/src/Util/Writers/StatusWriter.php b/src/Util/Writers/StatusWriter.php new file mode 100644 index 0000000000..a52b634282 --- /dev/null +++ b/src/Util/Writers/StatusWriter.php @@ -0,0 +1,174 @@ + + * @author Juliette Reinders Folmer + * @copyright 2025 PHPCSStandards and contributors + * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence + */ + +namespace PHP_CodeSniffer\Util\Writers; + +final class StatusWriter +{ + + /** + * The stream to write to. + * + * @var resource + */ + private static $stream = STDERR; + + /** + * If TRUE, requests to print a status message will be ignored. + * + * @var boolean + */ + private static $paused = false; + + /** + * Number of open pause requests. + * + * If the writer is paused from different places, we only want to resume when all those places + * have given the okay for it. Let's call it "pause nesting". + * + * @var integer + */ + private static $pauseCount = 0; + + + /** + * Prints a status message to STDERR. + * + * If status messages have been paused, the message will be not be output. + * Use forceWrite() to forcibly print a message in this case. + * + * @param string $message The message to print. + * @param int $indent How many levels to indent the message. + * Tabs are used to indent status + * messages. + * @param int $newlines Number of new lines to add to the messages. + * Defaults to 1. Set to 0 to suppress adding a new line. + * + * @return void + */ + public static function write($message, $indent=0, $newlines=1) + { + if (self::$paused === true) { + return; + } + + self::forceWrite($message, $indent, $newlines); + + }//end write() + + + /** + * Prints a status message to STDERR, even if status messages have been paused. + * + * @param string $message The message to print. + * @param int $indent How many levels to indent the message. + * Tabs are used to indent status + * messages. + * @param int $newlines Number of new lines to add to the messages. + * Defaults to 1. Set to 0 to suppress adding a new line. + * + * @return void + */ + public static function forceWrite($message, $indent=0, $newlines=1) + { + if ($indent > 0) { + $message = str_repeat("\t", $indent).$message; + } + + if ($newlines > 0) { + $message .= str_repeat(PHP_EOL, $newlines); + } + + fwrite(self::$stream, $message); + + }//end forceWrite() + + + /** + * Prints a new line to STDERR. + * + * @param int $nr Number of new lines to print. + * Defaults to 1. + * + * @return void + */ + public static function writeNewline($nr=1) + { + self::write('', 0, $nr); + + }//end writeNewline() + + + /** + * Prints a new line to STDERR, even if status messages have been paused. + * + * @param int $nr Number of new lines to print. + * Defaults to 1. + * + * @return void + */ + public static function forceWriteNewline($nr=1) + { + self::forceWrite('', 0, $nr); + + }//end forceWriteNewline() + + + /** + * Pauses the printing of status messages. + * + * @return void + */ + public static function pause() + { + self::$paused = true; + ++self::$pauseCount; + + }//end pause() + + + /** + * Resumes the printing of status messages. + * + * @return void + */ + public static function resume() + { + if (self::$pauseCount > 0) { + --self::$pauseCount; + } + + if (self::$pauseCount === 0) { + self::$paused = false; + } + + }//end resume() + + + /** + * Check whether the StatusWriter is paused. + * + * @return bool + */ + public static function isPaused() + { + return self::$paused; + + }//end isPaused() + + +}//end class diff --git a/tests/Core/AbstractWriterTestCase.php b/tests/Core/AbstractWriterTestCase.php new file mode 100644 index 0000000000..0d0e67ff3e --- /dev/null +++ b/tests/Core/AbstractWriterTestCase.php @@ -0,0 +1,18 @@ +getPlainRuleset(); - $this->expectOutputString(''); + $this->expectNoStdoutOutput(); $this->invokeDisplayCachedMessages($ruleset); + $this->assertStderrOutputSameString(''); + }//end testDisplayCachedMessagesStaysSilentWithoutErrors() @@ -124,10 +128,12 @@ public function testNonBlockingErrorsGenerateOutput($messages, $expected) $ruleset = $this->getPlainRuleset(); $this->mockCachedMessages($ruleset, $messages); - $this->expectOutputString($expected); + $this->expectNoStdoutOutput(); $this->invokeDisplayCachedMessages($ruleset); + $this->assertStderrOutputSameString($expected); + }//end testNonBlockingErrorsGenerateOutput() @@ -212,10 +218,12 @@ public function testNonBlockingErrorsDoNotShowUnderSpecificCircumstances($config $ruleset = new Ruleset($config); $this->mockCachedMessages($ruleset, ['Deprecation notice' => MessageCollector::DEPRECATED]); - $this->expectOutputString(''); + $this->expectNoStdoutOutput(); $this->invokeDisplayCachedMessages($ruleset); + $this->assertStderrOutputSameString(''); + }//end testNonBlockingErrorsDoNotShowUnderSpecificCircumstances() diff --git a/tests/Core/Ruleset/ShowSniffDeprecationsTest.php b/tests/Core/Ruleset/ShowSniffDeprecationsTest.php index 1e72052840..712fa7d64b 100644 --- a/tests/Core/Ruleset/ShowSniffDeprecationsTest.php +++ b/tests/Core/Ruleset/ShowSniffDeprecationsTest.php @@ -12,6 +12,7 @@ use PHP_CodeSniffer\Ruleset; use PHP_CodeSniffer\Tests\ConfigDouble; use PHP_CodeSniffer\Tests\Core\Ruleset\AbstractRulesetTestCase; +use PHP_CodeSniffer\Tests\Core\StatusWriterTestHelper; /** * Tests PHPCS native handling of sniff deprecations. @@ -21,6 +22,7 @@ */ final class ShowSniffDeprecationsTest extends AbstractRulesetTestCase { + use StatusWriterTestHelper; /** @@ -85,10 +87,12 @@ public function testDeprecatedSniffsListDoesNotShow($standard, $additionalArgs=[ $config = new ConfigDouble($args); $ruleset = new Ruleset($config); - $this->expectOutputString(''); + $this->expectNoStdoutOutput(); $ruleset->showSniffDeprecations(); + $this->assertStderrOutputSameString(''); + }//end testDeprecatedSniffsListDoesNotShow() @@ -177,10 +181,12 @@ public function testDeprecatedSniffsListDoesNotShowWhenSelectedSniffsAreNotDepre $config = new ConfigDouble($cliArgs); $ruleset = new Ruleset($config); - $this->expectOutputString(''); + $this->expectNoStdoutOutput(); $ruleset->showSniffDeprecations(); + $this->assertStderrOutputSameString(''); + }//end testDeprecatedSniffsListDoesNotShowWhenSelectedSniffsAreNotDeprecated() @@ -208,10 +214,12 @@ public function testDeprecatedSniffsListDoesNotShowWhenAllDeprecatedSniffsAreExc $config = new ConfigDouble($cliArgs); $ruleset = new Ruleset($config); - $this->expectOutputString(''); + $this->expectNoStdoutOutput(); $ruleset->showSniffDeprecations(); + $this->assertStderrOutputSameString(''); + }//end testDeprecatedSniffsListDoesNotShowWhenAllDeprecatedSniffsAreExcluded() @@ -273,10 +281,12 @@ public function testDeprecatedSniffsWarning() $expected .= 'Deprecated sniffs are still run, but will stop working at some point in the'.PHP_EOL; $expected .= 'future.'.PHP_EOL.PHP_EOL; - $this->expectOutputString($expected); + $this->expectNoStdoutOutput(); $ruleset->showSniffDeprecations(); + $this->assertStderrOutputSameString($expected); + }//end testDeprecatedSniffsWarning() @@ -303,10 +313,12 @@ public function testReportWidthIsRespected($reportWidth, $expectedOutput) $config = new ConfigDouble(['.', "--standard=$standard", "--report-width=$reportWidth", '--no-colors']); $ruleset = new Ruleset($config); - $this->expectOutputString($expectedOutput); + $this->expectNoStdoutOutput(); $ruleset->showSniffDeprecations(); + $this->assertStderrOutputSameString($expectedOutput); + }//end testReportWidthIsRespected() @@ -417,10 +429,12 @@ public function testDeprecatedSniffsAreListedAlphabetically() $expected .= 'Deprecated sniffs are still run, but will stop working at some point in the'.PHP_EOL; $expected .= 'future.'.PHP_EOL.PHP_EOL; - $this->expectOutputString($expected); + $this->expectNoStdoutOutput(); $ruleset->showSniffDeprecations(); + $this->assertStderrOutputSameString($expected); + // Verify that the sniffs have been registered to run. $this->assertCount(2, $ruleset->sniffCodes, 'Incorrect number of sniff codes registered'); $this->assertArrayHasKey( diff --git a/tests/Core/Runner/PrintProgressDotsTest.php b/tests/Core/Runner/PrintProgressDotsTest.php index a195ed2815..c1184bad4b 100644 --- a/tests/Core/Runner/PrintProgressDotsTest.php +++ b/tests/Core/Runner/PrintProgressDotsTest.php @@ -12,6 +12,7 @@ use PHP_CodeSniffer\Ruleset; use PHP_CodeSniffer\Runner; use PHP_CodeSniffer\Tests\ConfigDouble; +use PHP_CodeSniffer\Tests\Core\StatusWriterTestHelper; use PHPUnit\Framework\TestCase; /** @@ -21,6 +22,7 @@ */ final class PrintProgressDotsTest extends TestCase { + use StatusWriterTestHelper; /** @@ -196,7 +198,7 @@ public static function dataProgressDotCbf() */ private function checkProgressDot($colors, $code, $sniffs, $expected, $enableFixer=false) { - $this->expectOutputString($expected); + $this->expectNoStdoutOutput(); $config = new ConfigDouble(['-p']); $config->colors = $colors; @@ -216,6 +218,8 @@ private function checkProgressDot($colors, $code, $sniffs, $expected, $enableFix $runner->printProgress($file, 2, 1); + $this->assertStderrOutputSameString($expected); + }//end checkProgressDot() diff --git a/tests/Core/Runner/PrintProgressTest.php b/tests/Core/Runner/PrintProgressTest.php index 82ab98fa7d..13991f1529 100644 --- a/tests/Core/Runner/PrintProgressTest.php +++ b/tests/Core/Runner/PrintProgressTest.php @@ -12,6 +12,7 @@ use PHP_CodeSniffer\Ruleset; use PHP_CodeSniffer\Runner; use PHP_CodeSniffer\Tests\ConfigDouble; +use PHP_CodeSniffer\Tests\Core\StatusWriterTestHelper; use PHPUnit\Framework\TestCase; /** @@ -21,6 +22,7 @@ */ final class PrintProgressTest extends TestCase { + use StatusWriterTestHelper; /** * Config instance for use in the tests. @@ -110,7 +112,7 @@ public static function tearDownAfterClass(): void */ public function testNoProgressIsShownWhenDisabled() { - $this->expectOutputString(''); + $this->expectNoStdoutOutput(); self::$config->showProgress = false; @@ -118,6 +120,8 @@ public function testNoProgressIsShownWhenDisabled() self::$runner->printProgress(self::$fileWithoutErrorsOrWarnings, 3, $i); } + $this->assertStderrOutputSameString(''); + }//end testNoProgressIsShownWhenDisabled() @@ -128,9 +132,9 @@ public function testNoProgressIsShownWhenDisabled() */ public function testProgressDotSkippedFiles() { - $nrOfFiles = 10; - $this->expectOutputString('.S.S.S.S.S 10 / 10 (100%)'.PHP_EOL); + $this->expectNoStdoutOutput(); + $nrOfFiles = 10; for ($i = 1; $i <= $nrOfFiles; $i++) { if (($i % 2) === 0) { self::$fileWithoutErrorsOrWarnings->ignored = true; @@ -141,6 +145,8 @@ public function testProgressDotSkippedFiles() self::$runner->printProgress(self::$fileWithoutErrorsOrWarnings, $nrOfFiles, $i); } + $this->assertStderrOutputSameString('.S.S.S.S.S 10 / 10 (100%)'.PHP_EOL); + }//end testProgressDotSkippedFiles() @@ -156,12 +162,14 @@ public function testProgressDotSkippedFiles() */ public function testEndOfLineSummary($nrOfFiles, $expected) { - $this->expectOutputString($expected); + $this->expectNoStdoutOutput(); for ($i = 1; $i <= $nrOfFiles; $i++) { self::$runner->printProgress(self::$fileWithoutErrorsOrWarnings, $nrOfFiles, $i); } + $this->assertStderrOutputSameString($expected); + }//end testEndOfLineSummary() diff --git a/tests/Core/StatusWriterTestHelper.php b/tests/Core/StatusWriterTestHelper.php new file mode 100644 index 0000000000..7ffecdf312 --- /dev/null +++ b/tests/Core/StatusWriterTestHelper.php @@ -0,0 +1,166 @@ +redirectStatusWriterOutputToStream(); + + }//end setUp() + + + /** + * Reset all static properties on the StatusWriter class. + * + * If the tearDown() method is overloaded, call the resetStatusWriterProperties() method from your own tearDown(). + * + * @return void + */ + protected function tearDown(): void + { + $this->resetStatusWriterProperties(); + + }//end tearDown() + + + /** + * Redirect the output from STDERR to memory. + * + * This method should typically be called from within the setUp() method of the test using this trait. + * + * @return void + */ + protected function redirectStatusWriterOutputToStream(): void + { + $stream = fopen('php://memory', 'rw'); + + if ($stream === false) { + return; + } + + $this->stream = $stream; + + $streamProperty = new ReflectionProperty(StatusWriter::class, 'stream'); + $streamProperty->setAccessible(true); + $streamProperty->setValue(null, $this->stream); + $streamProperty->setAccessible(false); + + }//end redirectStatusWriterOutputToStream() + + + /** + * Reset static property. + * + * This method should typically be called from within the tearDown() method of the test using this trait. + * + * @return void + */ + protected function resetStatusWriterStream(): void + { + // Reset the static property to its default. + $streamProperty = new ReflectionProperty(StatusWriter::class, 'stream'); + $streamProperty->setAccessible(true); + $streamProperty->setValue(null, STDERR); + $streamProperty->setAccessible(false); + + }//end resetStatusWriterStream() + + + /** + * Reset all static properties on the StatusWriter class. + * + * @return void + */ + protected function resetStatusWriterProperties(): void + { + while (StatusWriter::isPaused() === true) { + StatusWriter::resume(); + } + + $this->resetStatusWriterStream(); + + }//end resetStatusWriterProperties() + + + /** + * Assert that no output was sent to STDOUT. + * + * @return void + */ + public function expectNoStdoutOutput() + { + $this->expectOutputString(''); + + }//end expectNoStdoutOutput() + + + /** + * Verify output sent to STDERR is the same as expected output. + * + * @param string $expected The expected STDERR output. + * + * @return void + */ + public function assertStderrOutputSameString($expected) + { + fseek($this->stream, 0); + $output = stream_get_contents($this->stream); + + $this->assertIsString($output); + $this->assertSame($expected, $output); + + }//end assertStderrOutputSameString() + + + /** + * Verify output sent to STDERR complies with an expected regex pattern. + * + * @param string $regex The regular expression to use to verify the STDERR output complies with expectations. + * + * @return void + */ + public function assertStderrOutputMatchesRegex($regex) + { + fseek($this->stream, 0); + $output = stream_get_contents($this->stream); + + $this->assertIsString($output); + + if (method_exists($this, 'assertMatchesRegularExpression') === true) { + $this->assertMatchesRegularExpression($regex, $output); + } else { + // PHPUnit < 9.1.0. + $this->assertRegExp($regex, $output); + } + + }//end assertStderrOutputMatchesRegex() + + +}//end trait diff --git a/tests/Core/Util/MessageCollector/MessageCollectorTest.php b/tests/Core/Util/MessageCollector/MessageCollectorTest.php index 0f69967784..5ae16d5642 100644 --- a/tests/Core/Util/MessageCollector/MessageCollectorTest.php +++ b/tests/Core/Util/MessageCollector/MessageCollectorTest.php @@ -8,15 +8,15 @@ namespace PHP_CodeSniffer\Tests\Core\Util\MessageCollector; +use PHP_CodeSniffer\Tests\Core\AbstractWriterTestCase; use PHP_CodeSniffer\Util\MessageCollector; -use PHPUnit\Framework\TestCase; /** * Tests the message caching and display functionality. * * @covers \PHP_CodeSniffer\Util\MessageCollector */ -final class MessageCollectorTest extends TestCase +final class MessageCollectorTest extends AbstractWriterTestCase { @@ -196,10 +196,12 @@ public function testDisplayingNonBlockingMessages($messages, $expected) $msgCollector = new MessageCollector(); $this->createErrorCache($msgCollector, $messages); - $this->expectOutputString($expected); + $this->expectNoStdoutOutput(); $msgCollector->display(); + $this->assertStderrOutputSameString($expected); + }//end testDisplayingNonBlockingMessages() @@ -376,10 +378,13 @@ public function testNonUniqueMessagesWithDifferentErrorLevelAreAccepted() $expected = 'WARNING: Trying to add the same message twice'.PHP_EOL; $expected .= 'NOTICE: Trying to add the same message twice'.PHP_EOL.PHP_EOL; - $this->expectOutputString($expected); + + $this->expectNoStdoutOutput(); $msgCollector->display(); + $this->assertStderrOutputSameString($expected); + }//end testNonUniqueMessagesWithDifferentErrorLevelAreAccepted() @@ -400,10 +405,13 @@ public function testNonUniqueMessagesWithSameErrorLevelAreAccepted() $expected = 'NOTICE: Trying to add the same message twice'.PHP_EOL; $expected .= 'NOTICE: Trying to add the same message twice'.PHP_EOL.PHP_EOL; - $this->expectOutputString($expected); + + $this->expectNoStdoutOutput(); $msgCollector->display(); + $this->assertStderrOutputSameString($expected); + }//end testNonUniqueMessagesWithSameErrorLevelAreAccepted() @@ -428,11 +436,14 @@ public function testCallingDisplayTwiceWillNotShowMessagesTwice() $expected .= 'NOTICE: First notice'.PHP_EOL; $expected .= 'NOTICE: Third notice'.PHP_EOL; $expected .= 'DEPRECATED: Second deprecation'.PHP_EOL.PHP_EOL; - $this->expectOutputString($expected); + + $this->expectNoStdoutOutput(); $msgCollector->display(); $msgCollector->display(); + $this->assertStderrOutputSameString($expected); + }//end testCallingDisplayTwiceWillNotShowMessagesTwice() @@ -458,10 +469,12 @@ public function testDisplayOrderHandling($order, $expected) $msgCollector = new MessageCollector(); $this->createErrorCache($msgCollector, $messages); - $this->expectOutputString($expected); + $this->expectNoStdoutOutput(); $msgCollector->display($order); + $this->assertStderrOutputSameString($expected); + }//end testDisplayOrderHandling() diff --git a/tests/Core/Util/Timing/TimingTest.php b/tests/Core/Util/Timing/TimingTest.php index a8cf2d04e4..50e40c45f3 100644 --- a/tests/Core/Util/Timing/TimingTest.php +++ b/tests/Core/Util/Timing/TimingTest.php @@ -9,6 +9,7 @@ namespace PHP_CodeSniffer\Tests\Core\Util\Timing; +use PHP_CodeSniffer\Tests\Core\StatusWriterTestHelper; use PHP_CodeSniffer\Util\Timing; use PHPUnit\Framework\TestCase; @@ -26,6 +27,7 @@ */ final class TimingTest extends TestCase { + use StatusWriterTestHelper; /** @@ -65,9 +67,12 @@ public function testGetDurationWithStartReturnsMilliseconds() */ public function testTimeIsNotPrintedIfTimerWasNeverStarted() { - $this->expectOutputString(''); + $this->expectNoStdoutOutput(); + Timing::printRunTime(); + $this->assertStderrOutputSameString(''); + }//end testTimeIsNotPrintedIfTimerWasNeverStarted() @@ -78,9 +83,12 @@ public function testTimeIsNotPrintedIfTimerWasNeverStarted() */ public function testTimeIsNotPrintedIfTimerWasNeverStartedEvenWhenForced() { - $this->expectOutputString(''); + $this->expectNoStdoutOutput(); + Timing::printRunTime(true); + $this->assertStderrOutputSameString(''); + }//end testTimeIsNotPrintedIfTimerWasNeverStartedEvenWhenForced() @@ -91,7 +99,7 @@ public function testTimeIsNotPrintedIfTimerWasNeverStartedEvenWhenForced() */ public function testTimeIsPrintedOnlyOnce() { - $this->expectOutputRegex('`^Time: [0-9]+ms; Memory: [0-9\.]+MB'.PHP_EOL.PHP_EOL.'$`'); + $this->expectNoStdoutOutput(); Timing::startTiming(); usleep(2000); @@ -99,6 +107,9 @@ public function testTimeIsPrintedOnlyOnce() Timing::printRunTime(); Timing::printRunTime(); + $regex = '`^Time: [0-9]+ms; Memory: [0-9\.]+MB'.PHP_EOL.'$`'; + $this->assertStderrOutputMatchesRegex($regex); + }//end testTimeIsPrintedOnlyOnce() @@ -109,7 +120,7 @@ public function testTimeIsPrintedOnlyOnce() */ public function testTimeIsPrintedMultipleTimesOnlyIfForced() { - $this->expectOutputRegex('`^(Time: [0-9]+ms; Memory: [0-9\.]+MB'.PHP_EOL.PHP_EOL.'){3}$`'); + $this->expectNoStdoutOutput(); Timing::startTiming(); usleep(2000); @@ -117,6 +128,9 @@ public function testTimeIsPrintedMultipleTimesOnlyIfForced() Timing::printRunTime(true); Timing::printRunTime(true); + $regex = '`^(Time: [0-9]+ms; Memory: [0-9\.]+MB'.PHP_EOL.'){3}$`'; + $this->assertStderrOutputMatchesRegex($regex); + }//end testTimeIsPrintedMultipleTimesOnlyIfForced() diff --git a/tests/Core/Util/Writers/StatusWriterTest.php b/tests/Core/Util/Writers/StatusWriterTest.php new file mode 100644 index 0000000000..9a75939848 --- /dev/null +++ b/tests/Core/Util/Writers/StatusWriterTest.php @@ -0,0 +1,389 @@ +expectNoStdoutOutput(); + + StatusWriter::write($message); + + $this->assertStderrOutputSameString($expected); + + }//end testStatusSentToStdErr() + + + /** + * Data provider. + * + * @return array> + */ + public static function dataStatusSentToStdErr() + { + return [ + 'Default settings' => [ + 'message' => 'This message should end up in stdErr with no tab indent and 1 new line', + 'expected' => 'This message should end up in stdErr with no tab indent and 1 new line'.PHP_EOL, + ], + 'empty message prints new line' => [ + 'message' => '', + 'expected' => PHP_EOL, + ], + ]; + + }//end dataStatusSentToStdErr() + + + /** + * Perfunctory test to verify that the $indent and $newlines parameters are handled correctly. + * + * @param string $message The message to print. + * @param int $indent Indent setting to use for this test. + * @param int $newlines New lines setting to use for this test. + * @param string $expected Expected output. + * + * @dataProvider dataStatusSentToStdErrIndentNewlines + * + * @return void + */ + public function testStatusSentToStdErrIndentNewlines($message, $indent, $newlines, $expected) + { + $this->expectNoStdoutOutput(); + + StatusWriter::write($message, $indent, $newlines); + + $this->assertStderrOutputSameString($expected); + + }//end testStatusSentToStdErrIndentNewlines() + + + /** + * Data provider. + * + * @return array> + */ + public static function dataStatusSentToStdErrIndentNewlines() + { + return [ + 'Default settings' => [ + 'message' => 'This message should end up in stdErr with no tab indent and 1 new line', + 'indent' => 0, + 'newlines' => 1, + 'expected' => 'This message should end up in stdErr with no tab indent and 1 new line'.PHP_EOL, + ], + 'no indent, suppress new line' => [ + 'message' => 'This message should end up in stdErr with no tab indent and no new line', + 'indent' => 0, + 'newlines' => 0, + 'expected' => 'This message should end up in stdErr with no tab indent and no new line', + ], + '1 indent, default new line' => [ + 'message' => 'This message should end up in stdErr with one tab indent and 1 new line', + 'indent' => 1, + 'newlines' => 1, + 'expected' => "\tThis message should end up in stdErr with one tab indent and 1 new line".PHP_EOL, + ], + '2 indents, suppress new line' => [ + 'message' => 'This message should end up in stdErr with two tab indent and no new line', + 'indent' => 2, + 'newlines' => 0, + 'expected' => "\t\tThis message should end up in stdErr with two tab indent and no new line", + ], + '1 indent, double new line' => [ + 'message' => 'This message should end up in stdErr with one tab indent and 2 new lines', + 'indent' => 1, + 'newlines' => 2, + 'expected' => "\tThis message should end up in stdErr with one tab indent and 2 new lines".PHP_EOL.PHP_EOL, + ], + 'negative number of indents, negative number of new lines' => [ + 'message' => 'This message should end up in stdErr with no tab indent and no new line', + 'indent' => -10, + 'newlines' => -2, + 'expected' => 'This message should end up in stdErr with no tab indent and no new line', + ], + ]; + + }//end dataStatusSentToStdErrIndentNewlines() + + + /** + * Verify pausing the StatusWriter prevents output from being sent to stdErr. + * + * @return void + */ + public function testStatusDoesNotGetPrintedWhenPaused() + { + $this->expectNoStdoutOutput(); + + $message = 'This message should not be printed when the StatusWriter is paused'; + + $this->assertFalse(StatusWriter::isPaused()); + + StatusWriter::pause(); + $this->assertTrue(StatusWriter::isPaused()); + + StatusWriter::write($message); + + $this->assertStderrOutputSameString(''); + + }//end testStatusDoesNotGetPrintedWhenPaused() + + + /** + * Verify that output sent while paused is not sent to StdErr, while output sent once the StatusWriter + * is resumed, does get sent to StdErr. + * + * @return void + */ + public function testStatusDoesGetPrintedWhenPausedAndResumed() + { + $this->expectNoStdoutOutput(); + + $message = 'This message should not be printed when the StatusWriter is paused'; + + $this->assertFalse(StatusWriter::isPaused()); + + StatusWriter::pause(); + $this->assertTrue(StatusWriter::isPaused()); + + StatusWriter::write($message); + + StatusWriter::resume(); + $this->assertFalse(StatusWriter::isPaused()); + + $message = 'Once the StatusWriter is resumed, messages should be printed again'; + $expected = $message.PHP_EOL; + StatusWriter::write($message); + + $this->assertStderrOutputSameString($expected); + + }//end testStatusDoesGetPrintedWhenPausedAndResumed() + + + /** + * Verify that forceWrite() ignores whether the StatusWriter is paused. + * + * @return void + */ + public function testStatusDoesGetForcePrintedWhenPaused() + { + $this->expectNoStdoutOutput(); + + $message = 'This message should still be force printed when the StatusWriter is paused'; + $expected = $message.PHP_EOL; + + $this->assertFalse(StatusWriter::isPaused()); + + StatusWriter::pause(); + $this->assertTrue(StatusWriter::isPaused()); + + StatusWriter::forceWrite($message); + + $this->assertStderrOutputSameString($expected); + + }//end testStatusDoesGetForcePrintedWhenPaused() + + + /** + * Verify that forceWrite() ignores whether the StatusWriter is paused and resumed. + * + * @return void + */ + public function testStatusDoesGetForcePrintedWhenPausedAndResumed() + { + $this->expectNoStdoutOutput(); + + $messageA = 'This message should still be force printed when the StatusWriter is paused'; + $expected = $messageA.PHP_EOL; + + $messageB = 'This message should NOT be printed when the StatusWriter is paused'; + + $this->assertFalse(StatusWriter::isPaused()); + + StatusWriter::pause(); + $this->assertTrue(StatusWriter::isPaused()); + + StatusWriter::forceWrite($messageA); + StatusWriter::write($messageB); + + StatusWriter::resume(); + $this->assertFalse(StatusWriter::isPaused()); + + $messageC = 'Once the StatusWriter is resumed, messages should be printed again'; + $expected .= $messageC.PHP_EOL.$messageC.PHP_EOL; + + StatusWriter::write($messageC); + StatusWriter::forceWrite($messageC); + + $this->assertStderrOutputSameString($expected); + + }//end testStatusDoesGetForcePrintedWhenPausedAndResumed() + + + /** + * Verify sending new lines to StdErr. + * + * @return void + */ + public function testWriteNewline() + { + $this->expectNoStdoutOutput(); + + $this->assertFalse(StatusWriter::isPaused()); + + // Print new line. + StatusWriter::writeNewline(); + + StatusWriter::pause(); + $this->assertTrue(StatusWriter::isPaused()); + + // As the StatusWriter is paused, only the force printed new line should print, the other one should be ignored. + StatusWriter::writeNewline(); + StatusWriter::forceWriteNewline(); + + $this->assertStderrOutputSameString(PHP_EOL.PHP_EOL); + + }//end testWriteNewline() + + + /** + * Verify that the StatusWriter only resumes when all previous "pause" calls are rescinded. + * + * @return void + */ + public function testNestedPausing() + { + $this->expectNoStdoutOutput(); + + $message = 'This message should not be printed when the StatusWriter is paused'; + + $this->assertFalse(StatusWriter::isPaused()); + + // Pause 1. + StatusWriter::pause(); + $this->assertTrue(StatusWriter::isPaused()); + + StatusWriter::write($message); + + // Pause 2. + StatusWriter::pause(); + $this->assertTrue(StatusWriter::isPaused()); + + StatusWriter::write($message); + + // Pause 3. + StatusWriter::pause(); + $this->assertTrue(StatusWriter::isPaused()); + + StatusWriter::write($message); + + // Resume 3. + StatusWriter::resume(); + $this->assertTrue(StatusWriter::isPaused()); + + StatusWriter::write($message); + + // Resume 2. + StatusWriter::resume(); + $this->assertTrue(StatusWriter::isPaused()); + + StatusWriter::write($message); + + // Resume 1. + StatusWriter::resume(); + $this->assertFalse(StatusWriter::isPaused()); + + $message = 'Once the StatusWriter is resumed, messages should be printed again'; + $expected = $message.PHP_EOL; + StatusWriter::write($message); + + $this->assertStderrOutputSameString($expected); + + }//end testNestedPausing() + + + /** + * Verify that resuming more often than the StatusWriter is paused, won't block future pauses. + * + * @return void + */ + public function testResumingMoreOftenThanPaused() + { + $this->expectNoStdoutOutput(); + + $messageA = 'This message should not be printed when the StatusWriter is paused'; + $messageB = 'Once the StatusWriter is resumed, messages should be printed again'; + $expected = $messageB.PHP_EOL.$messageB.PHP_EOL; + + $this->assertFalse(StatusWriter::isPaused()); + + // Pause 1. + StatusWriter::pause(); + $this->assertTrue(StatusWriter::isPaused()); + + StatusWriter::write($messageA); + + // Pause 2. + StatusWriter::pause(); + $this->assertTrue(StatusWriter::isPaused()); + + StatusWriter::write($messageA); + + // Resume 2. + StatusWriter::resume(); + $this->assertTrue(StatusWriter::isPaused()); + + StatusWriter::write($messageA); + + // Resume 1. + StatusWriter::resume(); + $this->assertFalse(StatusWriter::isPaused()); + + StatusWriter::write($messageB); + + // Resume too much - this resume should not change the pause counter. + StatusWriter::resume(); + $this->assertFalse(StatusWriter::isPaused()); + + StatusWriter::write($messageB); + + // Pause after "resume too much", still pauses the StatusWriter. + StatusWriter::pause(); + $this->assertTrue(StatusWriter::isPaused()); + + StatusWriter::write($messageA); + + $this->assertStderrOutputSameString($expected); + + }//end testResumingMoreOftenThanPaused() + + +}//end class