Skip to content

Commit 40814f8

Browse files
gsherwoodjrfnl
andcommitted
(Nearly) All status, debug, and progress output is now sent to STDERR instead of STDOUT
What with the `StatusWriter` class now being available, this commit starts using it in (nearly) all appropriate places. Notes: * The original implementation removed the output buffering from the `Fixer` class. While I would absolutely LOVE to get rid of that, my own manual tests of these changes showed that this led to undesired side-effects in the debug output, so I have not included that part of the original changeset for now, though I may re-attempt this at a later point in time. * As the fast majority of the output is "hidden" behind conditions involving the global `PHP_CODESNIFFER_VERBOSITY` constant, which is set to `0` in the test bootstrap, it is neigh impossible (at this time) to add tests to cover the changes in this commit. Then again, testing the debug output isn't something which should get the highest priority anyway and could be considered redundant. And while the changes in this commit have been made comprehensive based on the current codebase, there are still some situations where error output goes to `STDOUT` instead of `STDERR`. This is related to a) output buffering and b) the use of the `DeepExitException` to pass both error as well as requested output. I'm still investigating a solution to safely and reliably change this, but don't deem that solution ready for commit yet, though I'm hopeful that solution may still make it into 4.0. Includes updating the related tests to ensure that the output from the Timing class and the MessageCollector is send to `stdErr` and not to `stdOut`. I have "manually" tested the results of this change and have found it working, except for the edge case as annotated above. I'll happily share the test setup I've used for this so others can verify my findings. Fixes squizlabs/PHP_CodeSniffer 1612 Supersedes 3078 Co-authored-by: jrfnl <[email protected]>
1 parent 95e123e commit 40814f8

File tree

21 files changed

+532
-530
lines changed

21 files changed

+532
-530
lines changed

src/Files/File.php

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
use PHP_CodeSniffer\Tokenizers\PHP;
1818
use PHP_CodeSniffer\Util\Common;
1919
use PHP_CodeSniffer\Util\Tokens;
20+
use PHP_CodeSniffer\Util\Writers\StatusWriter;
2021

2122
class File
2223
{
@@ -324,7 +325,7 @@ public function process()
324325
$this->fixer->startFile($this);
325326

326327
if (PHP_CODESNIFFER_VERBOSITY > 2) {
327-
echo "\t*** START TOKEN PROCESSING ***".PHP_EOL;
328+
StatusWriter::write('*** START TOKEN PROCESSING ***', 1);
328329
}
329330

330331
$foundCode = false;
@@ -377,7 +378,7 @@ public function process()
377378
if (PHP_CODESNIFFER_VERBOSITY > 2) {
378379
$type = $token['type'];
379380
$content = Common::prepareForOutput($token['content']);
380-
echo "\t\tProcess token $stackPtr: $type => $content".PHP_EOL;
381+
StatusWriter::write("Process token $stackPtr: $type => $content", 2);
381382
}
382383

383384
if ($token['code'] !== T_INLINE_HTML) {
@@ -452,7 +453,7 @@ public function process()
452453
}
453454

454455
if (PHP_CODESNIFFER_VERBOSITY > 2) {
455-
echo "\t\t\tProcessing ".$this->activeListener.'... ';
456+
StatusWriter::write('Processing '.$this->activeListener.'... ', 3, 0);
456457
}
457458

458459
$ignoreTo = $this->ruleset->sniffs[$class]->process($this, $stackPtr);
@@ -471,7 +472,7 @@ public function process()
471472

472473
if (PHP_CODESNIFFER_VERBOSITY > 2) {
473474
$timeTaken = round(($timeTaken), 4);
474-
echo "DONE in $timeTaken seconds".PHP_EOL;
475+
StatusWriter::write("DONE in $timeTaken seconds");
475476
}
476477

477478
$this->activeListener = '';
@@ -493,15 +494,15 @@ public function process()
493494
}
494495

495496
if (PHP_CODESNIFFER_VERBOSITY > 2) {
496-
echo "\t*** END TOKEN PROCESSING ***".PHP_EOL;
497-
echo "\t*** START SNIFF PROCESSING REPORT ***".PHP_EOL;
497+
StatusWriter::write('*** END TOKEN PROCESSING ***', 1);
498+
StatusWriter::write('*** START SNIFF PROCESSING REPORT ***', 1);
498499

499500
arsort($this->listenerTimes, SORT_NUMERIC);
500501
foreach ($this->listenerTimes as $listener => $timeTaken) {
501-
echo "\t$listener: ".round(($timeTaken), 4).' secs'.PHP_EOL;
502+
StatusWriter::write("$listener: ".round(($timeTaken), 4).' secs', 1);
502503
}
503504

504-
echo "\t*** END SNIFF PROCESSING REPORT ***".PHP_EOL;
505+
StatusWriter::write('*** END SNIFF PROCESSING REPORT ***', 1);
505506
}
506507

507508
$this->fixedCount += $this->fixer->getFixCount();
@@ -528,10 +529,12 @@ public function parse()
528529
$this->ignored = true;
529530
$this->addWarning($e->getMessage(), null, 'Internal.Tokenizer.Exception');
530531
if (PHP_CODESNIFFER_VERBOSITY > 0) {
531-
echo '[tokenizer error]... ';
532+
$newlines = 0;
532533
if (PHP_CODESNIFFER_VERBOSITY > 1) {
533-
echo PHP_EOL;
534+
$newlines = 1;
534535
}
536+
537+
StatusWriter::write('[tokenizer error]... ', 0, $newlines);
535538
}
536539

537540
return;
@@ -560,10 +563,12 @@ public function parse()
560563
$numLines = $this->tokens[($this->numTokens - 1)]['line'];
561564
}
562565

563-
echo "[$this->numTokens tokens in $numLines lines]... ";
566+
$newlines = 0;
564567
if (PHP_CODESNIFFER_VERBOSITY > 1) {
565-
echo PHP_EOL;
568+
$newlines = 1;
566569
}
570+
571+
StatusWriter::write("[$this->numTokens tokens in $numLines lines]... ", 0, $newlines);
567572
}
568573

569574
}//end parse()
@@ -1043,7 +1048,7 @@ protected function addMessage($error, $message, $line, $column, $code, $data, $s
10431048
&& $fixable === true
10441049
) {
10451050
@ob_end_clean();
1046-
echo "\tE: [Line $line] $message ($sniffCode)".PHP_EOL;
1051+
StatusWriter::forceWrite("E: [Line $line] $message ($sniffCode)", 1);
10471052
ob_start();
10481053
}
10491054

src/Files/LocalFile.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
use PHP_CodeSniffer\Ruleset;
1414
use PHP_CodeSniffer\Util\Cache;
1515
use PHP_CodeSniffer\Util\Common;
16+
use PHP_CodeSniffer\Util\Writers\StatusWriter;
1617

1718
class LocalFile extends File
1819
{
@@ -113,7 +114,7 @@ public function process()
113114
if (PHP_CODESNIFFER_VERBOSITY > 0
114115
|| (PHP_CODESNIFFER_CBF === true && empty($this->config->files) === false)
115116
) {
116-
echo "[loaded from cache]... ";
117+
StatusWriter::write('[loaded from cache]... ', 0, 0);
117118
}
118119

119120
$this->numTokens = $cache['numTokens'];
@@ -122,7 +123,7 @@ public function process()
122123
}//end if
123124

124125
if (PHP_CODESNIFFER_VERBOSITY > 1) {
125-
echo PHP_EOL;
126+
StatusWriter::writeNewline();
126127
}
127128

128129
parent::process();

src/Fixer.php

Lines changed: 43 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
use PHP_CodeSniffer\Exceptions\RuntimeException;
1717
use PHP_CodeSniffer\Files\File;
1818
use PHP_CodeSniffer\Util\Common;
19+
use PHP_CodeSniffer\Util\Writers\StatusWriter;
1920

2021
class Fixer
2122
{
@@ -149,6 +150,9 @@ public function fixFile()
149150

150151
$this->enabled = true;
151152

153+
// Pause the StatusWriter to silence Tokenizer debug info about the file being retokenized for each loop.
154+
StatusWriter::pause();
155+
152156
$this->loops = 0;
153157
while ($this->loops < 50) {
154158
ob_start();
@@ -158,15 +162,15 @@ public function fixFile()
158162

159163
if (PHP_CODESNIFFER_VERBOSITY > 2) {
160164
@ob_end_clean();
161-
echo '---START FILE CONTENT---'.PHP_EOL;
165+
StatusWriter::forceWrite('---START FILE CONTENT---');
162166
$lines = explode($this->currentFile->eolChar, $contents);
163167
$max = strlen(count($lines));
164168
foreach ($lines as $lineNum => $line) {
165169
$lineNum++;
166-
echo str_pad($lineNum, $max, ' ', STR_PAD_LEFT).'|'.$line.PHP_EOL;
170+
StatusWriter::forceWrite(str_pad($lineNum, $max, ' ', STR_PAD_LEFT).'|'.$line);
167171
}
168172

169-
echo '--- END FILE CONTENT ---'.PHP_EOL;
173+
StatusWriter::forceWrite('--- END FILE CONTENT ---');
170174
ob_start();
171175
}
172176

@@ -179,35 +183,40 @@ public function fixFile()
179183
$this->loops++;
180184

181185
if (PHP_CODESNIFFER_CBF === true && PHP_CODESNIFFER_VERBOSITY > 0) {
182-
echo "\r".str_repeat(' ', 80)."\r";
183-
echo "\t=> Fixing file: $this->numFixes/$fixable violations remaining [made $this->loops pass";
186+
StatusWriter::forceWrite("\r".str_repeat(' ', 80)."\r", 0, 0);
187+
$statusMessage = "=> Fixing file: $this->numFixes/$fixable violations remaining [made $this->loops pass";
184188
if ($this->loops > 1) {
185-
echo 'es';
189+
$statusMessage .= 'es';
186190
}
187191

188-
echo ']... ';
192+
$statusMessage .= ']... ';
193+
$newlines = 0;
189194
if (PHP_CODESNIFFER_VERBOSITY > 1) {
190-
echo PHP_EOL;
195+
$newlines = 1;
191196
}
197+
198+
StatusWriter::forceWrite($statusMessage, 1, $newlines);
192199
}
193200

194201
if ($this->numFixes === 0 && $this->inConflict === false) {
195202
// Nothing left to do.
196203
break;
197204
} else if (PHP_CODESNIFFER_VERBOSITY > 1) {
198-
echo "\t* fixed $this->numFixes violations, starting loop ".($this->loops + 1).' *'.PHP_EOL;
205+
StatusWriter::forceWrite("* fixed $this->numFixes violations, starting loop ".($this->loops + 1).' *', 1);
199206
}
200207
}//end while
201208

202209
$this->enabled = false;
203210

211+
StatusWriter::resume();
212+
204213
if ($this->numFixes > 0) {
205214
if (PHP_CODESNIFFER_VERBOSITY > 1) {
206215
if (ob_get_level() > 0) {
207216
ob_end_clean();
208217
}
209218

210-
echo "\t*** Reached maximum number of loops with $this->numFixes violations left unfixed ***".PHP_EOL;
219+
StatusWriter::write("*** Reached maximum number of loops with $this->numFixes violations left unfixed ***", 1);
211220
ob_start();
212221
}
213222

@@ -409,7 +418,7 @@ public function beginChangeset()
409418
$line = $bt[0]['line'];
410419

411420
@ob_end_clean();
412-
echo "\t=> Changeset started by $sniff:$line".PHP_EOL;
421+
StatusWriter::forceWrite("=> Changeset started by $sniff:$line", 1);
413422
ob_start();
414423
}
415424

@@ -451,13 +460,13 @@ public function endChangeset()
451460

452461
if (PHP_CODESNIFFER_VERBOSITY > 1) {
453462
@ob_end_clean();
454-
echo "\t=> Changeset failed to apply".PHP_EOL;
463+
StatusWriter::forceWrite('=> Changeset failed to apply', 1);
455464
ob_start();
456465
}
457466
} else if (PHP_CODESNIFFER_VERBOSITY > 1) {
458467
$fixes = count($this->changeset);
459468
@ob_end_clean();
460-
echo "\t=> Changeset ended: $fixes changes applied".PHP_EOL;
469+
StatusWriter::forceWrite("=> Changeset ended: $fixes changes applied", 1);
461470
ob_start();
462471
}
463472

@@ -493,8 +502,8 @@ public function rollbackChangeset()
493502
$numChanges = count($this->changeset);
494503

495504
@ob_end_clean();
496-
echo "\t\tR: $sniff:$line rolled back the changeset ($numChanges changes)".PHP_EOL;
497-
echo "\t=> Changeset rolled back".PHP_EOL;
505+
StatusWriter::forceWrite("R: $sniff:$line rolled back the changeset ($numChanges changes)", 2);
506+
StatusWriter::forceWrite('=> Changeset rolled back', 1);
498507
ob_start();
499508
}
500509

@@ -521,14 +530,14 @@ public function replaceToken($stackPtr, $content)
521530
if ($this->inChangeset === false
522531
&& isset($this->fixedTokens[$stackPtr]) === true
523532
) {
524-
$indent = "\t";
533+
$depth = 1;
525534
if (empty($this->changeset) === false) {
526-
$indent .= "\t";
535+
$depth = 2;
527536
}
528537

529538
if (PHP_CODESNIFFER_VERBOSITY > 1) {
530539
@ob_end_clean();
531-
echo "$indent* token $stackPtr has already been modified, skipping *".PHP_EOL;
540+
StatusWriter::forceWrite("* token $stackPtr has already been modified, skipping *", $depth);
532541
ob_start();
533542
}
534543

@@ -565,7 +574,7 @@ public function replaceToken($stackPtr, $content)
565574

566575
if (PHP_CODESNIFFER_VERBOSITY > 1) {
567576
@ob_end_clean();
568-
echo "\t\tQ: $sniff:$line replaced token $stackPtr ($type on line $tokenLine) \"$oldContent\" => \"$newContent\"".PHP_EOL;
577+
StatusWriter::forceWrite("Q: $sniff:$line replaced token $stackPtr ($type on line $tokenLine) \"$oldContent\" => \"$newContent\"", 2);
569578
ob_start();
570579
}
571580

@@ -583,22 +592,22 @@ public function replaceToken($stackPtr, $content)
583592
&& $this->oldTokenValues[$stackPtr]['loop'] === ($this->loops - 1)
584593
) {
585594
if (PHP_CODESNIFFER_VERBOSITY > 1) {
586-
$indent = "\t";
595+
$depth = 1;
587596
if (empty($this->changeset) === false) {
588-
$indent .= "\t";
597+
$depth = 2;
589598
}
590599

591600
$loop = $this->oldTokenValues[$stackPtr]['loop'];
592601

593602
@ob_end_clean();
594-
echo "$indent**** $sniff:$line has possible conflict with another sniff on loop $loop; caused by the following change ****".PHP_EOL;
595-
echo "$indent**** replaced token $stackPtr ($type on line $tokenLine) \"$oldContent\" => \"$newContent\" ****".PHP_EOL;
603+
StatusWriter::forceWrite("**** $sniff:$line has possible conflict with another sniff on loop $loop; caused by the following change ****", $depth);
604+
StatusWriter::forceWrite("**** replaced token $stackPtr ($type on line $tokenLine) \"$oldContent\" => \"$newContent\" ****", $depth);
596605
}
597606

598607
if ($this->oldTokenValues[$stackPtr]['loop'] >= ($this->loops - 1)) {
599608
$this->inConflict = true;
600609
if (PHP_CODESNIFFER_VERBOSITY > 1) {
601-
echo "$indent**** ignoring all changes until next loop ****".PHP_EOL;
610+
StatusWriter::forceWrite('**** ignoring all changes until next loop ****', $depth);
602611
}
603612
}
604613

@@ -619,16 +628,18 @@ public function replaceToken($stackPtr, $content)
619628
$this->numFixes++;
620629

621630
if (PHP_CODESNIFFER_VERBOSITY > 1) {
622-
$indent = "\t";
631+
$statusMessage = "$sniff:$line replaced token $stackPtr ($type on line $tokenLine) \"$oldContent\" => \"$newContent\"";
632+
$depth = 1;
623633
if (empty($this->changeset) === false) {
624-
$indent .= "\tA: ";
634+
$statusMessage = 'A: '.$statusMessage;
635+
$depth = 2;
625636
}
626637

627638
if (ob_get_level() > 0) {
628639
ob_end_clean();
629640
}
630641

631-
echo "$indent$sniff:$line replaced token $stackPtr ($type on line $tokenLine) \"$oldContent\" => \"$newContent\"".PHP_EOL;
642+
StatusWriter::forceWrite($statusMessage, $depth);
632643
ob_start();
633644
}
634645

@@ -680,13 +691,15 @@ public function revertToken($stackPtr)
680691
$this->numFixes--;
681692

682693
if (PHP_CODESNIFFER_VERBOSITY > 1) {
683-
$indent = "\t";
694+
$statusMessage = "$sniff:$line reverted token $stackPtr ($type on line $tokenLine) \"$oldContent\" => \"$newContent\"";
695+
$depth = 1;
684696
if (empty($this->changeset) === false) {
685-
$indent .= "\tR: ";
697+
$statusMessage = 'R: '.$statusMessage;
698+
$depth = 2;
686699
}
687700

688701
@ob_end_clean();
689-
echo "$indent$sniff:$line reverted token $stackPtr ($type on line $tokenLine) \"$oldContent\" => \"$newContent\"".PHP_EOL;
702+
StatusWriter::forceWrite($statusMessage, $depth);
690703
ob_start();
691704
}
692705

0 commit comments

Comments
 (0)