Skip to content

Commit 50d6d43

Browse files
authored
Merge pull request #960 from PHPCSStandards/feature/runner-printprogress-minor-refactor
Runner::printProgress(): minor refactor
2 parents 8e82184 + 0632c4c commit 50d6d43

File tree

3 files changed

+485
-35
lines changed

3 files changed

+485
-35
lines changed

src/Runner.php

+28-35
Original file line numberDiff line numberDiff line change
@@ -856,9 +856,14 @@ public function printProgress(File $file, $numFiles, $numProcessed)
856856
return;
857857
}
858858

859+
$showColors = $this->config->colors;
860+
$colorOpen = '';
861+
$progressDot = '.';
862+
$colorClose = '';
863+
859864
// Show progress information.
860865
if ($file->ignored === true) {
861-
echo 'S';
866+
$progressDot = 'S';
862867
} else {
863868
$errors = $file->getErrorCount();
864869
$warnings = $file->getWarningCount();
@@ -870,27 +875,19 @@ public function printProgress(File $file, $numFiles, $numProcessed)
870875
// Files with unfixable errors or warnings are E (red).
871876
// Files with no errors or warnings are . (black).
872877
if ($fixable > 0) {
873-
if ($this->config->colors === true) {
874-
echo "\033[31m";
875-
}
878+
$progressDot = 'E';
876879

877-
echo 'E';
878-
879-
if ($this->config->colors === true) {
880-
echo "\033[0m";
880+
if ($showColors === true) {
881+
$colorOpen = "\033[31m";
882+
$colorClose = "\033[0m";
881883
}
882884
} else if ($fixed > 0) {
883-
if ($this->config->colors === true) {
884-
echo "\033[32m";
885-
}
885+
$progressDot = 'F';
886886

887-
echo 'F';
888-
889-
if ($this->config->colors === true) {
890-
echo "\033[0m";
887+
if ($showColors === true) {
888+
$colorOpen = "\033[32m";
889+
$colorClose = "\033[0m";
891890
}
892-
} else {
893-
echo '.';
894891
}//end if
895892
} else {
896893
// Files with errors are E (red).
@@ -899,39 +896,35 @@ public function printProgress(File $file, $numFiles, $numProcessed)
899896
// Files with fixable warnings are W (green).
900897
// Files with no errors or warnings are . (black).
901898
if ($errors > 0) {
902-
if ($this->config->colors === true) {
899+
$progressDot = 'E';
900+
901+
if ($showColors === true) {
903902
if ($fixable > 0) {
904-
echo "\033[32m";
903+
$colorOpen = "\033[32m";
905904
} else {
906-
echo "\033[31m";
905+
$colorOpen = "\033[31m";
907906
}
908-
}
909-
910-
echo 'E';
911907

912-
if ($this->config->colors === true) {
913-
echo "\033[0m";
908+
$colorClose = "\033[0m";
914909
}
915910
} else if ($warnings > 0) {
916-
if ($this->config->colors === true) {
911+
$progressDot = 'W';
912+
913+
if ($showColors === true) {
917914
if ($fixable > 0) {
918-
echo "\033[32m";
915+
$colorOpen = "\033[32m";
919916
} else {
920-
echo "\033[33m";
917+
$colorOpen = "\033[33m";
921918
}
922-
}
923919

924-
echo 'W';
925-
926-
if ($this->config->colors === true) {
927-
echo "\033[0m";
920+
$colorClose = "\033[0m";
928921
}
929-
} else {
930-
echo '.';
931922
}//end if
932923
}//end if
933924
}//end if
934925

926+
echo $colorOpen.$progressDot.$colorClose;
927+
935928
$numPerLine = 60;
936929
if ($numProcessed !== $numFiles && ($numProcessed % $numPerLine) !== 0) {
937930
return;
+222
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,222 @@
1+
<?php
2+
/**
3+
* Tests progress reporting in the Runner class.
4+
*
5+
* @copyright 2025 PHPCSStandards and contributors
6+
* @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
7+
*/
8+
9+
namespace PHP_CodeSniffer\Tests\Core\Runner;
10+
11+
use PHP_CodeSniffer\Files\DummyFile;
12+
use PHP_CodeSniffer\Ruleset;
13+
use PHP_CodeSniffer\Runner;
14+
use PHP_CodeSniffer\Tests\ConfigDouble;
15+
use PHPUnit\Framework\TestCase;
16+
17+
/**
18+
* Tests progress reporting.
19+
*
20+
* @covers \PHP_CodeSniffer\Runner::printProgress
21+
*/
22+
final class PrintProgressDotsTest extends TestCase
23+
{
24+
25+
26+
/**
27+
* Verify the correct progress indicator is used for a file in CS mode.
28+
*
29+
* @param bool $colors Whether to enable colors or not.
30+
* @param string $code Code snippet to process.
31+
* @param string $sniffs Comma-separated list of sniff(s) to run against the code snippet.
32+
* @param string $expected Expected output of the progress printer.
33+
*
34+
* @dataProvider dataProgressDotCs
35+
*
36+
* @return void
37+
*/
38+
public function testProgressDotCs($colors, $code, $sniffs, $expected)
39+
{
40+
if (PHP_CODESNIFFER_CBF === true) {
41+
$this->markTestSkipped('This test needs CS mode to run');
42+
}
43+
44+
$this->checkProgressDot($colors, $code, $sniffs, $expected);
45+
46+
}//end testProgressDotCs()
47+
48+
49+
/**
50+
* Data provider.
51+
*
52+
* @return array<string, array<string, bool|string>>
53+
*/
54+
public static function dataProgressDotCs()
55+
{
56+
return [
57+
'No colors: Dot: no errors, no warnings' => [
58+
'colors' => false,
59+
'code' => '<?php'."\n".'$var = false;'."\n",
60+
'sniff' => 'Generic.PHP.LowerCaseConstant',
61+
'expected' => '.',
62+
],
63+
'No colors: E: has error' => [
64+
'colors' => false,
65+
'code' => '<?php'."\n".'if ($a && $b || $c) {}'."\n",
66+
'sniff' => 'Generic.CodeAnalysis.RequireExplicitBooleanOperatorPrecedence',
67+
'expected' => 'E',
68+
],
69+
'No colors: W: has warning' => [
70+
'colors' => false,
71+
'code' => '<?php'."\n".'// TODO: something'."\n",
72+
'sniff' => 'Generic.Commenting.Todo',
73+
'expected' => 'W',
74+
],
75+
76+
'Colors: Dot: no errors, no warnings' => [
77+
'colors' => true,
78+
'code' => '<?php'."\n".'$var = false;'."\n",
79+
'sniff' => 'Generic.PHP.LowerCaseConstant',
80+
'expected' => '.',
81+
],
82+
'Colors: E: has error (red)' => [
83+
'colors' => true,
84+
'code' => '<?php'."\n".'if ($a && $b || $c) {}'."\n",
85+
'sniff' => 'Generic.CodeAnalysis.RequireExplicitBooleanOperatorPrecedence',
86+
'expected' => "\033[31m".'E'."\033[0m",
87+
],
88+
'Colors: E: has fixable error (green)' => [
89+
'colors' => true,
90+
'code' => '<?php'."\n".'$a = array();'."\n",
91+
'sniff' => 'Generic.Arrays.DisallowLongArraySyntax',
92+
'expected' => "\033[32m".'E'."\033[0m",
93+
],
94+
'Colors: W: has warning (yellow)' => [
95+
'colors' => true,
96+
'code' => '<?php'."\n".'// TODO: something'."\n",
97+
'sniff' => 'Generic.Commenting.Todo',
98+
'expected' => "\033[33m".'W'."\033[0m",
99+
],
100+
'Colors: W: has fixable warning (green)' => [
101+
'colors' => true,
102+
'code' => '<?php'."\n".'echo \'hello\';;'."\n",
103+
'sniff' => 'Generic.CodeAnalysis.EmptyPHPStatement',
104+
'expected' => "\033[32m".'W'."\033[0m",
105+
],
106+
];
107+
108+
}//end dataProgressDotCs()
109+
110+
111+
/**
112+
* Verify the correct progress indicator is used for a file in CBF mode.
113+
*
114+
* @param bool $colors Whether to enable colors or not.
115+
* @param string $code Code snippet to process.
116+
* @param string $sniffs Comma-separated list of sniff(s) to run against the code snippet.
117+
* @param string $expected Expected output of the progress printer.
118+
*
119+
* @dataProvider dataProgressDotCbf
120+
*
121+
* @group CBF
122+
*
123+
* @return void
124+
*/
125+
public function testProgressDotCbf($colors, $code, $sniffs, $expected)
126+
{
127+
if (PHP_CODESNIFFER_CBF === false) {
128+
$this->markTestSkipped('This test needs CBF mode to run');
129+
}
130+
131+
$this->checkProgressDot($colors, $code, $sniffs, $expected, true);
132+
133+
}//end testProgressDotCbf()
134+
135+
136+
/**
137+
* Data provider.
138+
*
139+
* @return array<string, array<string, bool|string>>
140+
*/
141+
public static function dataProgressDotCbf()
142+
{
143+
return [
144+
'No colors: Dot: no errors, no warnings' => [
145+
'colors' => false,
146+
'code' => '<?php'."\n".'$var = false;'."\n",
147+
'sniff' => 'Generic.PHP.LowerCaseConstant',
148+
'expected' => '.',
149+
],
150+
'No colors: F: fixes made' => [
151+
'colors' => false,
152+
'code' => '<?php'."\n".'$a = array();'."\n",
153+
'sniff' => 'Generic.Arrays.DisallowLongArraySyntax',
154+
'expected' => 'F',
155+
],
156+
'No colors: E: has fixer conflict' => [
157+
'colors' => false,
158+
'code' => '<?php'."\n".'$a = array();'."\n",
159+
'sniff' => 'Generic.Arrays.DisallowLongArraySyntax,Generic.Arrays.DisallowShortArraySyntax',
160+
'expected' => 'E',
161+
],
162+
163+
'Colors: Dot: no errors, no warnings (no color)' => [
164+
'colors' => true,
165+
'code' => '<?php'."\n".'$var = false;'."\n",
166+
'sniff' => 'Generic.PHP.LowerCaseConstant',
167+
'expected' => '.',
168+
],
169+
'Colors: F: fixes made (green)' => [
170+
'colors' => true,
171+
'code' => '<?php'."\n".'$a = array();'."\n",
172+
'sniff' => 'Generic.Arrays.DisallowLongArraySyntax',
173+
'expected' => "\033[32m".'F'."\033[0m",
174+
],
175+
'Colors: E: has fixer conflict (red)' => [
176+
'colors' => true,
177+
'code' => '<?php'."\n".'$a = array();'."\n",
178+
'sniff' => 'Generic.Arrays.DisallowLongArraySyntax,Generic.Arrays.DisallowShortArraySyntax',
179+
'expected' => "\033[31m".'E'."\033[0m",
180+
],
181+
];
182+
183+
}//end dataProgressDotCbf()
184+
185+
186+
/**
187+
* Verify the correct progress indicator is used for a file in CBF mode.
188+
*
189+
* @param bool $colors Whether to enable colors or not.
190+
* @param string $code Code snippet to process.
191+
* @param string $sniffs Comma-separated list of sniff(s) to run against the code snippet.
192+
* @param string $expected Expected output of the progress printer.
193+
* @param bool $enableFixer Whether to fix the code or not.
194+
*
195+
* @return void
196+
*/
197+
private function checkProgressDot($colors, $code, $sniffs, $expected, $enableFixer=false)
198+
{
199+
$this->expectOutputString($expected);
200+
201+
$config = new ConfigDouble(['-p']);
202+
$config->colors = $colors;
203+
$config->standards = ['Generic'];
204+
$config->sniffs = explode(',', $sniffs);
205+
$ruleset = new Ruleset($config);
206+
207+
$runner = new Runner();
208+
$runner->config = $config;
209+
210+
$file = new DummyFile($code, $ruleset, $config);
211+
$file->process();
212+
213+
if ($enableFixer === true) {
214+
$file->fixer->fixFile();
215+
}
216+
217+
$runner->printProgress($file, 2, 1);
218+
219+
}//end checkProgressDot()
220+
221+
222+
}//end class

0 commit comments

Comments
 (0)