Skip to content

Commit 78508c3

Browse files
authored
Merge pull request #1175 from fredden/issue-1082/exit-code-when-fixing-stdin
[4.0] Fix exit code when phpcbf is processing STDIN
2 parents ceb3624 + 35098d7 commit 78508c3

File tree

5 files changed

+173
-19
lines changed

5 files changed

+173
-19
lines changed

src/Files/File.php

Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -153,22 +153,13 @@ class File
153153
protected $warningCount = 0;
154154

155155
/**
156-
* The original total number of errors that can be fixed (first run on a file).
156+
* The original total number of errors and warnings (first run on a file).
157157
*
158158
* {@internal This should be regarded as an immutable property.}
159159
*
160-
* @var integer
161-
*/
162-
private $fixableErrorCountFirstRun;
163-
164-
/**
165-
* The original total number of warnings that can be fixed (first run on a file).
166-
*
167-
* {@internal This should be regarded as an immutable property.}
168-
*
169-
* @var integer
160+
* @var array<string, int>
170161
*/
171-
private $fixableWarningCountFirstRun;
162+
private $firstRunCounts;
172163

173164
/**
174165
* The current total number of errors that can be fixed.
@@ -555,14 +546,18 @@ public function process()
555546
StatusWriter::write('*** END SNIFF PROCESSING REPORT ***', 1);
556547
}
557548

558-
if (isset($this->fixableErrorCountFirstRun, $this->fixableWarningCountFirstRun) === false) {
559-
$this->fixableErrorCountFirstRun = $this->fixableErrorCount;
560-
$this->fixableWarningCountFirstRun = $this->fixableWarningCount;
549+
if (isset($this->firstRunCounts) === false) {
550+
$this->firstRunCounts = [
551+
'error' => $this->errorCount,
552+
'warning' => $this->warningCount,
553+
'fixableError' => $this->fixableErrorCount,
554+
'fixableWarning' => $this->fixableWarningCount,
555+
];
561556
}
562557

563558
$this->fixedCount += $this->fixer->getFixCount();
564-
$this->fixedErrorCount = ($this->fixableErrorCountFirstRun - $this->fixableErrorCount);
565-
$this->fixedWarningCount = ($this->fixableWarningCountFirstRun - $this->fixableWarningCount);
559+
$this->fixedErrorCount = ($this->firstRunCounts['fixableError'] - $this->fixableErrorCount);
560+
$this->fixedWarningCount = ($this->firstRunCounts['fixableWarning'] - $this->fixableWarningCount);
566561

567562
}//end process()
568563

@@ -1217,6 +1212,22 @@ public function getFixedWarningCount()
12171212
}//end getFixedWarningCount()
12181213

12191214

1215+
/**
1216+
* Retrieve information about the first run.
1217+
*
1218+
* @param $type string
1219+
*
1220+
* @internal This method does not form part of any public API nor backwards compatibility guarantee.
1221+
*
1222+
* @return int
1223+
*/
1224+
public function getFirstRunCount(string $type):int
1225+
{
1226+
return $this->firstRunCounts[$type];
1227+
1228+
}//end getFirstRunCount()
1229+
1230+
12201231
/**
12211232
* Returns the list of ignored lines.
12221233
*

src/Reports/Cbf.php

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,17 @@
77
* report from the command line.
88
*
99
* @author Greg Sherwood <[email protected]>
10+
* @author Juliette Reinders Folmer <[email protected]>
1011
* @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600)
12+
* @copyright 2025 PHPCSStandards and contributors
1113
* @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
1214
*/
1315

1416
namespace PHP_CodeSniffer\Reports;
1517

1618
use PHP_CodeSniffer\Exceptions\DeepExitException;
1719
use PHP_CodeSniffer\Files\File;
20+
use PHP_CodeSniffer\Reporter;
1821
use PHP_CodeSniffer\Util\ExitCode;
1922
use PHP_CodeSniffer\Util\Timing;
2023
use PHP_CodeSniffer\Util\Writers\StatusWriter;
@@ -60,8 +63,12 @@ public function generateFileReport($report, File $phpcsFile, $showSources=false,
6063
// Replacing STDIN, so output current file to STDOUT
6164
// even if nothing was fixed. Exit here because we
6265
// can't process any more than 1 file in this setup.
63-
$fixedContent = $phpcsFile->fixer->getContents();
64-
throw new DeepExitException($fixedContent, ExitCode::OKAY);
66+
echo $phpcsFile->fixer->getContents();
67+
68+
// Fake a Reporter instance to allow for getting a proper exit code.
69+
$reporter = $this->createReporterInstance($phpcsFile);
70+
71+
throw new DeepExitException('', ExitCode::calculate($reporter));
6572
}
6673

6774
if ($errors === 0) {
@@ -246,4 +253,39 @@ public function generate(
246253
}//end generate()
247254

248255

256+
/**
257+
* Create a "fake" Reporter instance to allow for getting a proper exit code when scanning code provided via STDIN.
258+
*
259+
* @param \PHP_CodeSniffer\Files\File $phpcsFile The file being reported on.
260+
*
261+
* @return \PHP_CodeSniffer\Reporter
262+
*/
263+
private function createReporterInstance(File $phpcsFile)
264+
{
265+
$reporter = new class extends Reporter {
266+
267+
268+
/**
269+
* Overload the constructor as we don't need it.
270+
*/
271+
public function __construct()
272+
{
273+
}//end __construct()
274+
275+
276+
};
277+
278+
$reporter->totalFiles = 1;
279+
$reporter->totalErrors = $phpcsFile->getFirstRunCount('error');
280+
$reporter->totalWarnings = $phpcsFile->getFirstRunCount('warning');
281+
$reporter->totalFixableErrors = $phpcsFile->getFixableErrorCount();
282+
$reporter->totalFixableWarnings = $phpcsFile->getFixableWarningCount();
283+
$reporter->totalFixedErrors = $phpcsFile->getFixedErrorCount();
284+
$reporter->totalFixedWarnings = $phpcsFile->getFixedWarningCount();
285+
286+
return $reporter;
287+
288+
}//end createReporterInstance()
289+
290+
249291
}//end class
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
/**
4+
* Class containing a simple style error that phpcbf cannot fix, and another that it can fix.
5+
*
6+
* @copyright 2025 PHPCSStandards and contributors
7+
* @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
8+
*/
9+
10+
namespace PHP_CodeSniffer\Tests\EndToEnd\Fixtures;
11+
12+
// The brace on the following line should be on a line by itself. This can be fixed with phpcbf.
13+
class ClassWithTwoStyleErrors {
14+
} // This comment does not belong here, according to PSR12. This cannot be fixed with phpcbf.
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
/**
4+
* Class containing a simple style error that phpcbf cannot fix.
5+
*
6+
* @copyright 2025 PHPCSStandards and contributors
7+
* @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
8+
*/
9+
10+
namespace PHP_CodeSniffer\Tests\EndToEnd\Fixtures;
11+
12+
class ClassWithUnfixableStyleError
13+
{
14+
} // This comment does not belong here, according to PSR12.

tests/EndToEnd/exit_code_test.sh

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
#!/usr/bin/env bash
2+
3+
function tear_down() {
4+
rm -f tests/EndToEnd/Fixtures/*.fixed
5+
}
6+
7+
function test_phpcs_exit_code_clean_file() {
8+
bin/phpcs --standard=tests/EndToEnd/Fixtures/endtoend.xml.dist tests/EndToEnd/Fixtures/ClassOneWithoutStyleError.inc
9+
assert_exit_code 0
10+
}
11+
function test_phpcs_exit_code_clean_stdin() {
12+
bin/phpcs --standard=tests/EndToEnd/Fixtures/endtoend.xml.dist < tests/EndToEnd/Fixtures/ClassOneWithoutStyleError.inc
13+
assert_exit_code 0
14+
}
15+
function test_phpcbf_exit_code_clean_file() {
16+
bin/phpcbf --suffix=.fixed --standard=tests/EndToEnd/Fixtures/endtoend.xml.dist tests/EndToEnd/Fixtures/ClassOneWithoutStyleError.inc
17+
assert_exit_code 0
18+
}
19+
function test_phpcbf_exit_code_clean_stdin() {
20+
bin/phpcbf --suffix=.fixed --standard=tests/EndToEnd/Fixtures/endtoend.xml.dist < tests/EndToEnd/Fixtures/ClassOneWithoutStyleError.inc
21+
assert_exit_code 0
22+
}
23+
24+
function test_phpcs_exit_code_fixable_file() {
25+
bin/phpcs --standard=tests/EndToEnd/Fixtures/endtoend.xml.dist tests/EndToEnd/Fixtures/ClassWithStyleError.inc
26+
assert_exit_code 1
27+
}
28+
function test_phpcs_exit_code_fixable_stdin() {
29+
bin/phpcs --standard=tests/EndToEnd/Fixtures/endtoend.xml.dist < tests/EndToEnd/Fixtures/ClassWithStyleError.inc
30+
assert_exit_code 1
31+
}
32+
function test_phpcbf_exit_code_fixable_file() {
33+
bin/phpcbf --suffix=.fixed --standard=tests/EndToEnd/Fixtures/endtoend.xml.dist tests/EndToEnd/Fixtures/ClassWithStyleError.inc
34+
assert_exit_code 0
35+
}
36+
function test_phpcbf_exit_code_fixable_stdin() {
37+
bin/phpcbf --suffix=.fixed --standard=tests/EndToEnd/Fixtures/endtoend.xml.dist < tests/EndToEnd/Fixtures/ClassWithStyleError.inc
38+
assert_exit_code 0
39+
}
40+
41+
function test_phpcs_exit_code_non_fixable_file() {
42+
bin/phpcs --standard=tests/EndToEnd/Fixtures/endtoend.xml.dist tests/EndToEnd/Fixtures/ClassWithUnfixableStyleError.inc
43+
assert_exit_code 2
44+
}
45+
function test_phpcs_exit_code_non_fixable_stdin() {
46+
bin/phpcs --standard=tests/EndToEnd/Fixtures/endtoend.xml.dist < tests/EndToEnd/Fixtures/ClassWithUnfixableStyleError.inc
47+
assert_exit_code 2
48+
}
49+
function test_phpcbf_exit_code_non_fixable_file() {
50+
bin/phpcbf --suffix=.fixed --standard=tests/EndToEnd/Fixtures/endtoend.xml.dist tests/EndToEnd/Fixtures/ClassWithUnfixableStyleError.inc
51+
assert_exit_code 2
52+
}
53+
function test_phpcbf_exit_code_non_fixable_stdin() {
54+
bin/phpcbf --suffix=.fixed --standard=tests/EndToEnd/Fixtures/endtoend.xml.dist < tests/EndToEnd/Fixtures/ClassWithUnfixableStyleError.inc
55+
assert_exit_code 2
56+
}
57+
58+
function test_phpcs_exit_code_fixable_and_non_fixable_file() {
59+
bin/phpcs --standard=tests/EndToEnd/Fixtures/endtoend.xml.dist tests/EndToEnd/Fixtures/ClassWithTwoStyleErrors.inc
60+
assert_exit_code 3
61+
}
62+
function test_phpcs_exit_code_fixable_and_non_fixable_stdin() {
63+
bin/phpcs --standard=tests/EndToEnd/Fixtures/endtoend.xml.dist < tests/EndToEnd/Fixtures/ClassWithTwoStyleErrors.inc
64+
assert_exit_code 3
65+
}
66+
function test_phpcbf_exit_code_fixable_and_non_fixable_file() {
67+
bin/phpcbf --suffix=.fixed --standard=tests/EndToEnd/Fixtures/endtoend.xml.dist tests/EndToEnd/Fixtures/ClassWithTwoStyleErrors.inc
68+
assert_exit_code 2
69+
}
70+
function test_phpcbf_exit_code_fixable_and_non_fixable_stdin() {
71+
bin/phpcbf --suffix=.fixed --standard=tests/EndToEnd/Fixtures/endtoend.xml.dist < tests/EndToEnd/Fixtures/ClassWithTwoStyleErrors.inc
72+
assert_exit_code 2
73+
}

0 commit comments

Comments
 (0)