From b872aebe587dec22bcea1ef8559875195374d4f1 Mon Sep 17 00:00:00 2001 From: jrfnl Date: Fri, 8 Aug 2025 19:46:03 +0100 Subject: [PATCH 1/5] Use the new exit codes when scanning code from STDIN --- src/Reports/Cbf.php | 46 +++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/src/Reports/Cbf.php b/src/Reports/Cbf.php index 823ed14a57..5a157b6e77 100644 --- a/src/Reports/Cbf.php +++ b/src/Reports/Cbf.php @@ -7,7 +7,9 @@ * report from the command line. * * @author Greg Sherwood + * @author Juliette Reinders Folmer * @copyright 2006-2015 Squiz Pty Ltd (ABN 77 084 670 600) + * @copyright 2025 PHPCSStandards and contributors * @license https://github.com/PHPCSStandards/PHP_CodeSniffer/blob/master/licence.txt BSD Licence */ @@ -15,6 +17,7 @@ use PHP_CodeSniffer\Exceptions\DeepExitException; use PHP_CodeSniffer\Files\File; +use PHP_CodeSniffer\Reporter; use PHP_CodeSniffer\Util\ExitCode; use PHP_CodeSniffer\Util\Timing; use PHP_CodeSniffer\Util\Writers\StatusWriter; @@ -60,8 +63,12 @@ public function generateFileReport($report, File $phpcsFile, $showSources=false, // Replacing STDIN, so output current file to STDOUT // even if nothing was fixed. Exit here because we // can't process any more than 1 file in this setup. - $fixedContent = $phpcsFile->fixer->getContents(); - throw new DeepExitException($fixedContent, ExitCode::OKAY); + echo $phpcsFile->fixer->getContents(); + + // Fake a Reporter instance to allow for getting a proper exit code. + $reporter = $this->createReporterInstance($phpcsFile); + + throw new DeepExitException('', ExitCode::calculate($reporter)); } if ($errors === 0) { @@ -246,4 +253,39 @@ public function generate( }//end generate() + /** + * Create a "fake" Reporter instance to allow for getting a proper exit code when scanning code provided via STDIN. + * + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being reported on. + * + * @return \PHP_CodeSniffer\Reporter + */ + private function createReporterInstance(File $phpcsFile) + { + $reporter = new class extends Reporter { + + + /** + * Overload the constructor as we don't need it. + */ + public function __construct() + { + }//end __construct() + + + }; + + $reporter->totalFiles = 1; + $reporter->totalErrors = $phpcsFile->getErrorCount(); + $reporter->totalWarnings = $phpcsFile->getWarningCount(); + $reporter->totalFixableErrors = $phpcsFile->getFixableErrorCount(); + $reporter->totalFixableWarnings = $phpcsFile->getFixableWarningCount(); + $reporter->totalFixedErrors = $phpcsFile->getFixedErrorCount(); + $reporter->totalFixedWarnings = $phpcsFile->getFixedWarningCount(); + + return $reporter; + + }//end createReporterInstance() + + }//end class From 4f225c4333f11109faa2327e08deace5a480ac24 Mon Sep 17 00:00:00 2001 From: Dan Wallis Date: Fri, 8 Aug 2025 20:19:16 +0100 Subject: [PATCH 2/5] Fix exit code when phpcbf is processing STDIN --- src/Files/File.php | 45 ++++++++++++++++++++++++++++----------------- src/Reports/Cbf.php | 4 ++-- 2 files changed, 30 insertions(+), 19 deletions(-) diff --git a/src/Files/File.php b/src/Files/File.php index c8201f903c..0399df52e4 100644 --- a/src/Files/File.php +++ b/src/Files/File.php @@ -153,22 +153,13 @@ class File protected $warningCount = 0; /** - * The original total number of errors that can be fixed (first run on a file). + * The original total number of errors and warnings (first run on a file). * * {@internal This should be regarded as an immutable property.} * - * @var integer - */ - private $fixableErrorCountFirstRun; - - /** - * The original total number of warnings that can be fixed (first run on a file). - * - * {@internal This should be regarded as an immutable property.} - * - * @var integer + * @var array */ - private $fixableWarningCountFirstRun; + private $firstRunCounts; /** * The current total number of errors that can be fixed. @@ -555,14 +546,18 @@ public function process() StatusWriter::write('*** END SNIFF PROCESSING REPORT ***', 1); } - if (isset($this->fixableErrorCountFirstRun, $this->fixableWarningCountFirstRun) === false) { - $this->fixableErrorCountFirstRun = $this->fixableErrorCount; - $this->fixableWarningCountFirstRun = $this->fixableWarningCount; + if (isset($this->firstRunCounts) === false) { + $this->firstRunCounts = [ + 'error' => $this->errorCount, + 'warning' => $this->warningCount, + 'fixableError' => $this->fixableErrorCount, + 'fixableWarning' => $this->fixableWarningCount, + ]; } $this->fixedCount += $this->fixer->getFixCount(); - $this->fixedErrorCount = ($this->fixableErrorCountFirstRun - $this->fixableErrorCount); - $this->fixedWarningCount = ($this->fixableWarningCountFirstRun - $this->fixableWarningCount); + $this->fixedErrorCount = ($this->firstRunCounts['fixableError'] - $this->fixableErrorCount); + $this->fixedWarningCount = ($this->firstRunCounts['fixableWarning'] - $this->fixableWarningCount); }//end process() @@ -1217,6 +1212,22 @@ public function getFixedWarningCount() }//end getFixedWarningCount() + /** + * Retrieve information about the first run. + * + * @param $type string + * + * @internal This method does not form part of any public API nor backwards compatibility guarantee. + * + * @return int + */ + public function getFirstRunCount(string $type):int + { + return $this->firstRunCounts[$type]; + + }//end getFirstRunCount() + + /** * Returns the list of ignored lines. * diff --git a/src/Reports/Cbf.php b/src/Reports/Cbf.php index 5a157b6e77..e3369dd898 100644 --- a/src/Reports/Cbf.php +++ b/src/Reports/Cbf.php @@ -276,8 +276,8 @@ public function __construct() }; $reporter->totalFiles = 1; - $reporter->totalErrors = $phpcsFile->getErrorCount(); - $reporter->totalWarnings = $phpcsFile->getWarningCount(); + $reporter->totalErrors = $phpcsFile->getFirstRunCount('error'); + $reporter->totalWarnings = $phpcsFile->getFirstRunCount('warning'); $reporter->totalFixableErrors = $phpcsFile->getFixableErrorCount(); $reporter->totalFixableWarnings = $phpcsFile->getFixableWarningCount(); $reporter->totalFixedErrors = $phpcsFile->getFixedErrorCount(); From 7bfebccb81aae927f398802107e6e0c071fd92b3 Mon Sep 17 00:00:00 2001 From: Dan Wallis Date: Thu, 21 Aug 2025 20:47:18 +0100 Subject: [PATCH 3/5] Add tests to cover exit codes for phpcs & phpcbf This also includes tests for when files are supplied via STDIN. --- .../Fixtures/ClassWithTwoStyleErrors.inc | 14 ++++++++ .../Fixtures/ClassWithUnfixableStyleError.inc | 14 ++++++++ tests/EndToEnd/phpcbf_test.sh | 36 +++++++++++++++++++ tests/EndToEnd/phpcs_test.sh | 36 +++++++++++++++++++ 4 files changed, 100 insertions(+) create mode 100644 tests/EndToEnd/Fixtures/ClassWithTwoStyleErrors.inc create mode 100644 tests/EndToEnd/Fixtures/ClassWithUnfixableStyleError.inc diff --git a/tests/EndToEnd/Fixtures/ClassWithTwoStyleErrors.inc b/tests/EndToEnd/Fixtures/ClassWithTwoStyleErrors.inc new file mode 100644 index 0000000000..ab4faecdc0 --- /dev/null +++ b/tests/EndToEnd/Fixtures/ClassWithTwoStyleErrors.inc @@ -0,0 +1,14 @@ + Date: Fri, 29 Aug 2025 17:57:11 +0100 Subject: [PATCH 4/5] Move exit code tests to a file of their own --- tests/EndToEnd/exit_code_test.sh | 73 ++++++++++++++++++++++++++++++++ tests/EndToEnd/phpcbf_test.sh | 36 ---------------- tests/EndToEnd/phpcs_test.sh | 36 ---------------- 3 files changed, 73 insertions(+), 72 deletions(-) create mode 100644 tests/EndToEnd/exit_code_test.sh diff --git a/tests/EndToEnd/exit_code_test.sh b/tests/EndToEnd/exit_code_test.sh new file mode 100644 index 0000000000..ced50e0a2f --- /dev/null +++ b/tests/EndToEnd/exit_code_test.sh @@ -0,0 +1,73 @@ +#!/usr/bin/env bash + +function tear_down() { + rm -f tests/EndToEnd/Fixtures/*.fixed +} + +function test_phpcs_exit_code_clean_file() { + bin/phpcs --standard=tests/EndToEnd/Fixtures/endtoend.xml.dist tests/EndToEnd/Fixtures/ClassOneWithoutStyleError.inc + assert_exit_code 0 +} +function test_phpcs_exit_code_clean_stdin() { + bin/phpcs --standard=tests/EndToEnd/Fixtures/endtoend.xml.dist < tests/EndToEnd/Fixtures/ClassOneWithoutStyleError.inc + assert_exit_code 0 +} +function test_phpcbf_exit_code_clean_file() { + bin/phpcbf --suffix=.fixed --standard=tests/EndToEnd/Fixtures/endtoend.xml.dist tests/EndToEnd/Fixtures/ClassOneWithoutStyleError.inc + assert_exit_code 0 +} +function test_phpcbf_exit_code_clean_stdin() { + bin/phpcbf --suffix=.fixed --standard=tests/EndToEnd/Fixtures/endtoend.xml.dist < tests/EndToEnd/Fixtures/ClassOneWithoutStyleError.inc + assert_exit_code 0 +} + +function test_phpcs_exit_code_fixable_file() { + bin/phpcs --standard=tests/EndToEnd/Fixtures/endtoend.xml.dist tests/EndToEnd/Fixtures/ClassWithStyleError.inc + assert_exit_code 1 +} +function test_phpcs_exit_code_fixable_stdin() { + bin/phpcs --standard=tests/EndToEnd/Fixtures/endtoend.xml.dist < tests/EndToEnd/Fixtures/ClassWithStyleError.inc + assert_exit_code 1 +} +function test_phpcbf_exit_code_fixable_file() { + bin/phpcbf --suffix=.fixed --standard=tests/EndToEnd/Fixtures/endtoend.xml.dist tests/EndToEnd/Fixtures/ClassWithStyleError.inc + assert_exit_code 0 +} +function test_phpcbf_exit_code_fixable_stdin() { + bin/phpcbf --suffix=.fixed --standard=tests/EndToEnd/Fixtures/endtoend.xml.dist < tests/EndToEnd/Fixtures/ClassWithStyleError.inc + assert_exit_code 0 +} + +function test_phpcs_exit_code_non_fixable_file() { + bin/phpcs --standard=tests/EndToEnd/Fixtures/endtoend.xml.dist tests/EndToEnd/Fixtures/ClassWithUnfixableStyleError.inc + assert_exit_code 2 +} +function test_phpcs_exit_code_non_fixable_stdin() { + bin/phpcs --standard=tests/EndToEnd/Fixtures/endtoend.xml.dist < tests/EndToEnd/Fixtures/ClassWithUnfixableStyleError.inc + assert_exit_code 2 +} +function test_phpcbf_exit_code_non_fixable_file() { + bin/phpcbf --suffix=.fixed --standard=tests/EndToEnd/Fixtures/endtoend.xml.dist tests/EndToEnd/Fixtures/ClassWithUnfixableStyleError.inc + assert_exit_code 2 +} +function test_phpcbf_exit_code_non_fixable_stdin() { + bin/phpcbf --suffix=.fixed --standard=tests/EndToEnd/Fixtures/endtoend.xml.dist < tests/EndToEnd/Fixtures/ClassWithUnfixableStyleError.inc + assert_exit_code 2 +} + +function test_phpcs_exit_code_fixable_and_non_fixable_file() { + bin/phpcs --standard=tests/EndToEnd/Fixtures/endtoend.xml.dist tests/EndToEnd/Fixtures/ClassWithTwoStyleErrors.inc + assert_exit_code 3 +} +function test_phpcs_exit_code_fixable_and_non_fixable_stdin() { + bin/phpcs --standard=tests/EndToEnd/Fixtures/endtoend.xml.dist < tests/EndToEnd/Fixtures/ClassWithTwoStyleErrors.inc + assert_exit_code 3 +} +function test_phpcbf_exit_code_fixable_and_non_fixable_file() { + bin/phpcbf --suffix=.fixed --standard=tests/EndToEnd/Fixtures/endtoend.xml.dist tests/EndToEnd/Fixtures/ClassWithTwoStyleErrors.inc + assert_exit_code 2 +} +function test_phpcbf_exit_code_fixable_and_non_fixable_stdin() { + bin/phpcbf --suffix=.fixed --standard=tests/EndToEnd/Fixtures/endtoend.xml.dist < tests/EndToEnd/Fixtures/ClassWithTwoStyleErrors.inc + assert_exit_code 2 +} diff --git a/tests/EndToEnd/phpcbf_test.sh b/tests/EndToEnd/phpcbf_test.sh index 8f2644b0fe..d71669a241 100644 --- a/tests/EndToEnd/phpcbf_test.sh +++ b/tests/EndToEnd/phpcbf_test.sh @@ -43,39 +43,3 @@ function test_phpcbf_bug_1112() { assert_successful_code "$(bash -ic 'bash --init-file <(echo "echo \"Subprocess\"") -c "bin/phpcbf --no-cache --parallel=2 --standard=tests/EndToEnd/Fixtures/endtoend.xml.dist tests/EndToEnd/Fixtures/ClassOneWithoutStyleError.inc tests/EndToEnd/Fixtures/ClassTwoWithoutStyleError.inc"')" fi } - -function test_phpcbf_exit_code_clean() { - bin/phpcbf --suffix=.fixed --standard=tests/EndToEnd/Fixtures/endtoend.xml.dist tests/EndToEnd/Fixtures/ClassOneWithoutStyleError.inc - assert_exit_code 0 - - # Same result via STDIN - bin/phpcbf --suffix=.fixed --standard=tests/EndToEnd/Fixtures/endtoend.xml.dist < tests/EndToEnd/Fixtures/ClassOneWithoutStyleError.inc - assert_exit_code 0 -} - -function test_phpcbf_exit_code_fixable() { - bin/phpcbf --suffix=.fixed --standard=tests/EndToEnd/Fixtures/endtoend.xml.dist tests/EndToEnd/Fixtures/ClassWithStyleError.inc - assert_exit_code 0 - - # Same result via STDIN - bin/phpcbf --suffix=.fixed --standard=tests/EndToEnd/Fixtures/endtoend.xml.dist < tests/EndToEnd/Fixtures/ClassWithStyleError.inc - assert_exit_code 0 -} - -function test_phpcbf_exit_code_non_fixable() { - bin/phpcbf --suffix=.fixed --standard=tests/EndToEnd/Fixtures/endtoend.xml.dist tests/EndToEnd/Fixtures/ClassWithUnfixableStyleError.inc - assert_exit_code 2 - - # Same result via STDIN - bin/phpcbf --suffix=.fixed --standard=tests/EndToEnd/Fixtures/endtoend.xml.dist < tests/EndToEnd/Fixtures/ClassWithUnfixableStyleError.inc - assert_exit_code 2 -} - -function test_phpcbf_exit_code_fixable_and_non_fixable() { - bin/phpcbf --suffix=.fixed --standard=tests/EndToEnd/Fixtures/endtoend.xml.dist tests/EndToEnd/Fixtures/ClassWithTwoStyleErrors.inc - assert_exit_code 2 - - # Same result via STDIN - bin/phpcbf --suffix=.fixed --standard=tests/EndToEnd/Fixtures/endtoend.xml.dist < tests/EndToEnd/Fixtures/ClassWithTwoStyleErrors.inc - assert_exit_code 2 -} diff --git a/tests/EndToEnd/phpcs_test.sh b/tests/EndToEnd/phpcs_test.sh index d6cef89d8e..dcc643b03b 100644 --- a/tests/EndToEnd/phpcs_test.sh +++ b/tests/EndToEnd/phpcs_test.sh @@ -26,39 +26,3 @@ function test_phpcs_bug_1112() { assert_successful_code "$(bash -ic 'bash --init-file <(echo "echo \"Subprocess\"") -c "bin/phpcs --no-cache --parallel=2 --standard=tests/EndToEnd/Fixtures/endtoend.xml.dist tests/EndToEnd/Fixtures/ClassOneWithoutStyleError.inc tests/EndToEnd/Fixtures/ClassTwoWithoutStyleError.inc"')" fi } - -function test_phpcs_exit_code_clean() { - bin/phpcs --standard=tests/EndToEnd/Fixtures/endtoend.xml.dist tests/EndToEnd/Fixtures/ClassOneWithoutStyleError.inc - assert_exit_code 0 - - # Same result via STDIN - bin/phpcs --standard=tests/EndToEnd/Fixtures/endtoend.xml.dist < tests/EndToEnd/Fixtures/ClassOneWithoutStyleError.inc - assert_exit_code 0 -} - -function test_phpcs_exit_code_fixable() { - bin/phpcs --standard=tests/EndToEnd/Fixtures/endtoend.xml.dist tests/EndToEnd/Fixtures/ClassWithStyleError.inc - assert_exit_code 1 - - # Same result via STDIN - bin/phpcs --standard=tests/EndToEnd/Fixtures/endtoend.xml.dist < tests/EndToEnd/Fixtures/ClassWithStyleError.inc - assert_exit_code 1 -} - -function test_phpcs_exit_code_non_fixable() { - bin/phpcs --standard=tests/EndToEnd/Fixtures/endtoend.xml.dist tests/EndToEnd/Fixtures/ClassWithUnfixableStyleError.inc - assert_exit_code 2 - - # Same result via STDIN - bin/phpcs --standard=tests/EndToEnd/Fixtures/endtoend.xml.dist < tests/EndToEnd/Fixtures/ClassWithUnfixableStyleError.inc - assert_exit_code 2 -} - -function test_phpcs_exit_code_fixable_and_non_fixable() { - bin/phpcs --standard=tests/EndToEnd/Fixtures/endtoend.xml.dist tests/EndToEnd/Fixtures/ClassWithTwoStyleErrors.inc - assert_exit_code 3 - - # Same result via STDIN - bin/phpcs --standard=tests/EndToEnd/Fixtures/endtoend.xml.dist < tests/EndToEnd/Fixtures/ClassWithTwoStyleErrors.inc - assert_exit_code 3 -} From 87c0b23786a088dd3be8506418f7aa602d72a8ab Mon Sep 17 00:00:00 2001 From: Dan Wallis Date: Fri, 29 Aug 2025 18:00:12 +0100 Subject: [PATCH 5/5] Change comment flavour from '#' to '//' --- tests/EndToEnd/Fixtures/ClassWithTwoStyleErrors.inc | 4 ++-- tests/EndToEnd/Fixtures/ClassWithUnfixableStyleError.inc | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/EndToEnd/Fixtures/ClassWithTwoStyleErrors.inc b/tests/EndToEnd/Fixtures/ClassWithTwoStyleErrors.inc index ab4faecdc0..710248a733 100644 --- a/tests/EndToEnd/Fixtures/ClassWithTwoStyleErrors.inc +++ b/tests/EndToEnd/Fixtures/ClassWithTwoStyleErrors.inc @@ -9,6 +9,6 @@ namespace PHP_CodeSniffer\Tests\EndToEnd\Fixtures; -# The brace on the following line should be on a line by itself. This can be fixed with phpcbf. +// The brace on the following line should be on a line by itself. This can be fixed with phpcbf. class ClassWithTwoStyleErrors { -} # This comment does not belong here, according to PSR12. This cannot be fixed with phpcbf. +} // This comment does not belong here, according to PSR12. This cannot be fixed with phpcbf. diff --git a/tests/EndToEnd/Fixtures/ClassWithUnfixableStyleError.inc b/tests/EndToEnd/Fixtures/ClassWithUnfixableStyleError.inc index e8e3a5ef24..bf20814d8b 100644 --- a/tests/EndToEnd/Fixtures/ClassWithUnfixableStyleError.inc +++ b/tests/EndToEnd/Fixtures/ClassWithUnfixableStyleError.inc @@ -11,4 +11,4 @@ namespace PHP_CodeSniffer\Tests\EndToEnd\Fixtures; class ClassWithUnfixableStyleError { -} # This comment does not belong here, according to PSR12. +} // This comment does not belong here, according to PSR12.