From 49be097913b851a8f57309238c418228bcefe042 Mon Sep 17 00:00:00 2001 From: Mikhail Trusov Date: Tue, 2 Dec 2025 20:43:06 +0300 Subject: [PATCH 1/5] Excluded clover.xml and auth.json from git --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index c9940b1..68f8fcf 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,5 @@ /coverage_report.xml /html_docs /phpunit.xml -/clover.xml \ No newline at end of file +/clover.xml +/auth.json From 040be823ac6bba16c3fdece70ae132b23c715dca Mon Sep 17 00:00:00 2001 From: Mikhail Trusov Date: Tue, 2 Dec 2025 20:50:12 +0300 Subject: [PATCH 2/5] Suppressed psalm and phpstan false warnings --- src/CodeMultiRunner.php | 4 +++- src/DTO/RunningProcessData.php | 4 ++++ src/DiffCodeMultiRunner.php | 4 +++- src/MultiRunner.php | 11 ++++++++++- 4 files changed, 20 insertions(+), 3 deletions(-) diff --git a/src/CodeMultiRunner.php b/src/CodeMultiRunner.php index 00032ff..d6ed383 100644 --- a/src/CodeMultiRunner.php +++ b/src/CodeMultiRunner.php @@ -65,7 +65,9 @@ public function __construct( $this->setupInterpreter($interpreter, $interpreterArgs); $this->setupCwdForCode($baseFolder); - + // phpcs:disable + /** @psalm-suppress PossiblyNullOperand */ + // phpcs:enable $this->mainScriptFullPath = $this->cwd . DIRECTORY_SEPARATOR . 'main' . $this->scriptFileExtension($interpreter); if (file_put_contents($this->mainScriptFullPath, $scriptText) === false) { diff --git a/src/DTO/RunningProcessData.php b/src/DTO/RunningProcessData.php index f024aef..18e4b57 100644 --- a/src/DTO/RunningProcessData.php +++ b/src/DTO/RunningProcessData.php @@ -11,6 +11,10 @@ /** * Just LocalDTO class for keeping data of each running process + * + * phpcs:disable + * @psalm-suppress MissingConstructor + * phpcs:enable */ class RunningProcessData { diff --git a/src/DiffCodeMultiRunner.php b/src/DiffCodeMultiRunner.php index d471aac..ee41b63 100644 --- a/src/DiffCodeMultiRunner.php +++ b/src/DiffCodeMultiRunner.php @@ -66,7 +66,9 @@ public function addProcess( if ($this->osCommandsWrapper->programExists($interpreter) !== 0) { throw new RuntimeException('Interpreter ' . $interpreter . ' not found'); } - + // phpcs:disable + /** @psalm-suppress PossiblyNullOperand */ + // phpcs:enable $mainScriptFullPath = $this->cwd . DIRECTORY_SEPARATOR . $processId . '_script' . $this->scriptFileExtension($interpreter); if (file_put_contents($mainScriptFullPath, $scriptText) === false) { diff --git a/src/MultiRunner.php b/src/MultiRunner.php index 67649d4..7183fa8 100644 --- a/src/MultiRunner.php +++ b/src/MultiRunner.php @@ -209,8 +209,14 @@ protected function getResultsAndCloseCompletedProcesses(int $timeLimit): array // Before we can get the status of a process // we should get the contents of stdout and stderr pipes // to avoid deadlocks if the process sends a lot of output. + // phpcs:disable + /** @psalm-suppress RedundantCondition, TypeDoesNotContainType */ + // phpcs:enable $processData->stdout = ($processData->stdout ?? '') . stream_get_contents($processData->pipes[self::STDOUT]); + // phpcs:disable + /** @psalm-suppress RedundantCondition, TypeDoesNotContainType */ + // phpcs:enable $processData->stderr = ($processData->stderr ?? '') . stream_get_contents($processData->pipes[self::STDERR]); $procStatus = proc_get_status($processData->process); @@ -339,7 +345,7 @@ protected function setupCwdForCode(?string $baseFolder): void set_error_handler( function ($errorSeverityNum, $message, $file, $line): bool { if (error_reporting()) { - // @noinspection PhpUnhandledExceptionInspection + /* @noinspection PhpUnhandledExceptionInspection */ throw new ErrorException($message, 0, $errorSeverityNum, $file, $line); } return true; @@ -533,6 +539,9 @@ protected function canProcessesRunViaPopen(): bool protected function closeProcess(string $processId, RunningProcessData $processData): int { foreach ($processData->pipes as $pipe) { + // phpcs:disable + /** @psalm-suppress RedundantConditionGivenDocblockType */ + // phpcs:enable if (is_resource($pipe)) { fclose($pipe); } From e48e48b31da5d998bcf54fe9b561b3de0c4030e8 Mon Sep 17 00:00:00 2001 From: Mikhail Trusov Date: Tue, 2 Dec 2025 20:51:50 +0300 Subject: [PATCH 3/5] Made the variable type clear for a static analysis tool --- src/Helpers/OsCommandsWrapper.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Helpers/OsCommandsWrapper.php b/src/Helpers/OsCommandsWrapper.php index 95b296a..eaed548 100644 --- a/src/Helpers/OsCommandsWrapper.php +++ b/src/Helpers/OsCommandsWrapper.php @@ -15,6 +15,7 @@ use RecursiveDirectoryIterator; use RecursiveIteratorIterator; use RuntimeException; +use SplFileInfo; /** * The class with methods to work with OS dependent functions. @@ -213,6 +214,9 @@ public function clearFolder(string $folder): void new RecursiveDirectoryIterator($folder, FilesystemIterator::SKIP_DOTS), RecursiveIteratorIterator::CHILD_FIRST ); + // phpcs:disable + /** @var SplFileInfo $file */ + // phpcs:enable foreach ($files as $file) { if ($file->isDir() === true) { rmdir($file->getPathName()); From 037ffdb0551e254212708b863caf3a0b5144f374 Mon Sep 17 00:00:00 2001 From: Mikhail Trusov Date: Sat, 13 Dec 2025 11:47:13 +0300 Subject: [PATCH 4/5] Suppressed some psalm warnings --- src/Helpers/OsCommandsWrapper.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Helpers/OsCommandsWrapper.php b/src/Helpers/OsCommandsWrapper.php index eaed548..777567a 100644 --- a/src/Helpers/OsCommandsWrapper.php +++ b/src/Helpers/OsCommandsWrapper.php @@ -157,6 +157,10 @@ public function escapeArgWin32(string $value): string case '\\': // Matching backslashes are escaped if quoted. return $match[0] . $match[0]; default: + // phpcs:disable + /** @psalm-suppress PossiblyFalseArgument */ + // phpcs:enable + // Because there is no way $match[0] can be false. throw new InvalidArgumentException( sprintf( "Invalid byte at offset %d: 0x%02X", @@ -174,7 +178,9 @@ public function escapeArgWin32(string $value): string ? new InvalidArgumentException("Invalid UTF-8 string") : new Error("PCRE error: " . preg_last_error()); } - + // phpcs:disable + /** @psalm-suppress RedundantCondition, TypeDoesNotContainType */ + // phpcs:enable return $quote // Only quote when needed. ? '"' . $escaped . '"' : $value; From a55eb4c95024b50c258dfbe87507c561523d796a Mon Sep 17 00:00:00 2001 From: Mikhail Trusov Date: Sat, 13 Dec 2025 11:51:14 +0300 Subject: [PATCH 5/5] Made some conditions more reliable and suppressed phpstan and psalm warnings --- src/MultiRunner.php | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/src/MultiRunner.php b/src/MultiRunner.php index 7183fa8..801ba79 100644 --- a/src/MultiRunner.php +++ b/src/MultiRunner.php @@ -311,8 +311,8 @@ public function __destruct() */ protected function checkAndNormalizeCWD(?string $cwd): ?string { - if (empty($cwd)) { - return $cwd; + if (is_null($cwd)) { + return null; } $cwdRealPath = realpath($cwd); if ($cwdRealPath === false) { @@ -515,11 +515,17 @@ protected function justRunAndForget(): void protected function canProcessesRunViaPopen(): bool { foreach ($this->processesQueue as $processParams) { - if ( - !empty($processParams->cwd) || - !empty($processParams->envVars) || - strpos($processParams->commandLine, '%') !== false - ) { + /* @phpstan-ignore booleanAnd.rightAlwaysTrue */ + if (isset($processParams->cwd) && is_string($processParams->cwd) && strlen(trim($processParams->cwd)) > 0) { + return false; + } + if (isset($processParams->envVars) && count($processParams->envVars) > 0) { + return false; + } + // phpcs:disable + /** @psalm-suppress RedundantCondition */ + // phpcs:enable + if (isset($processParams->commandLine) && strpos($processParams->commandLine, '%') !== false) { return false; } } @@ -571,7 +577,7 @@ protected function checkAndNormaliseProgram(string $program, ?string $cwd): stri if ($this->osCommandsWrapper->programExists($program) === 0) { return $program; } - if (!empty($cwd) && file_exists($cwd)) { + if (is_string($cwd) && strlen(trim($cwd)) > 0 && file_exists($cwd)) { $programInCwd = $cwd . DIRECTORY_SEPARATOR . $program; if ($this->osCommandsWrapper->programExists($programInCwd) === 0) { return $programInCwd; @@ -588,7 +594,7 @@ protected function checkAndNormaliseProgram(string $program, ?string $cwd): stri */ protected function clearAndDeleteCwd() { - if (!empty($this->cwd) && file_exists($this->cwd)) { + if (isset($this->cwd) && strlen(trim($this->cwd)) > 0 && file_exists($this->cwd)) { $this->osCommandsWrapper->removeDirRecursive($this->cwd); } }