Skip to content

Commit

Permalink
Internal errors as structured objects
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed Jun 12, 2024
1 parent e45ba45 commit 7cd03f0
Show file tree
Hide file tree
Showing 8 changed files with 78 additions and 20 deletions.
4 changes: 2 additions & 2 deletions src/Analyser/AnalyserResult.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ class AnalyserResult
* @param array<string, LinesToIgnore> $linesToIgnore
* @param array<string, LinesToIgnore> $unmatchedLineIgnores
* @param list<CollectedData> $collectedData
* @param list<string> $internalErrors
* @param list<InternalError> $internalErrors
* @param array<string, array<string>>|null $dependencies
* @param array<string, array<RootExportedNode>> $exportedNodes
*/
Expand Down Expand Up @@ -117,7 +117,7 @@ public function getUnmatchedLineIgnores(): array
}

/**
* @return list<string>
* @return list<InternalError>
*/
public function getInternalErrors(): array
{
Expand Down
41 changes: 41 additions & 0 deletions src/Analyser/InternalError.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
<?php declare(strict_types = 1);

namespace PHPStan\Analyser;

use JsonSerializable;
use ReturnTypeWillChange;

class InternalError implements JsonSerializable
{

public function __construct(
private string $message,
)
{
}

public function getMessage(): string
{
return $this->message;
}

/**
* @param mixed[] $json
*/
public static function decode(array $json): self
{
return new self($json['message']);
}

/**
* @return mixed
*/
#[ReturnTypeWillChange]
public function jsonSerialize()
{
return [
'message' => $this->message,
];
}

}
4 changes: 3 additions & 1 deletion src/Command/AnalyseApplication.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,14 @@
use PHPStan\Analyser\AnalyserResult;
use PHPStan\Analyser\AnalyserResultFinalizer;
use PHPStan\Analyser\Ignore\IgnoredErrorHelper;
use PHPStan\Analyser\InternalError;
use PHPStan\Analyser\ResultCache\ResultCacheManagerFactory;
use PHPStan\Internal\BytesHelper;
use PHPStan\PhpDoc\StubFilesProvider;
use PHPStan\PhpDoc\StubValidator;
use PHPStan\ShouldNotHappenException;
use Symfony\Component\Console\Input\InputInterface;
use function array_map;
use function array_merge;
use function count;
use function is_file;
Expand Down Expand Up @@ -148,7 +150,7 @@ public function analyse(
if ($analyserResult->hasReachedInternalErrorsCountLimit()) {
$notFileSpecificErrors[] = sprintf('Reached internal errors count limit of %d, exiting...', $this->internalErrorsCountLimit);
}
$notFileSpecificErrors = array_merge($notFileSpecificErrors, $internalErrors);
$notFileSpecificErrors = array_merge($notFileSpecificErrors, array_map(static fn (InternalError $internalError) => $internalError->getMessage(), $internalErrors));
}

return new AnalysisResult(
Expand Down
6 changes: 4 additions & 2 deletions src/Command/AnalysisResult.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
namespace PHPStan\Command;

use PHPStan\Analyser\Error;
use PHPStan\Analyser\InternalError;
use PHPStan\Collectors\CollectedData;
use function array_map;
use function count;
use function usort;

Expand All @@ -17,7 +19,7 @@ class AnalysisResult
/**
* @param list<Error> $fileSpecificErrors
* @param list<string> $notFileSpecificErrors
* @param list<string> $internalErrors
* @param list<InternalError> $internalErrors
* @param list<string> $warnings
* @param list<CollectedData> $collectedData
* @param array<string, string> $changedProjectExtensionFilesOutsideOfAnalysedPaths
Expand Down Expand Up @@ -83,7 +85,7 @@ public function getNotFileSpecificErrors(): array
*/
public function getInternalErrors(): array
{
return $this->internalErrors;
return array_map(static fn (InternalError $internalError) => $internalError->getMessage(), $this->internalErrors);
}

/**
Expand Down
18 changes: 16 additions & 2 deletions src/Command/WorkerCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
use Clue\React\NDJson\Decoder;
use Clue\React\NDJson\Encoder;
use PHPStan\Analyser\FileAnalyser;
use PHPStan\Analyser\InternalError;
use PHPStan\Analyser\NodeScopeResolver;
use PHPStan\Collectors\Registry as CollectorRegistry;
use PHPStan\DependencyInjection\Container;
Expand Down Expand Up @@ -162,8 +163,19 @@ private function runWorker(
$out->write([
'action' => 'result',
'result' => [
'errors' => [$error->getMessage()],
'errors' => [],
'internalErrors' => [
new InternalError($error->getMessage()),
],
'filteredPhpErrors' => [],
'allPhpErrors' => [],
'locallyIgnoredErrors' => [],
'linesToIgnore' => [],
'unmatchedLineIgnores' => [],
'collectedData' => [],
'memoryUsage' => memory_get_peak_usage(true),
'dependencies' => [],
'exportedNodes' => [],
'files' => [],
'internalErrorsCount' => 1,
],
Expand All @@ -183,6 +195,7 @@ private function runWorker(
$internalErrorsCount = 0;
$files = $json['files'];
$errors = [];
$internalErrors = [];
$filteredPhpErrors = [];
$allPhpErrors = [];
$locallyIgnoredErrors = [];
Expand Down Expand Up @@ -224,14 +237,15 @@ private function runWorker(
$internalErrorMessage .= sprintf('%sRun PHPStan with -v option and post the stack trace to:%s%s', "\n", "\n", $bugReportUrl);
}

$errors[] = $internalErrorMessage;
$internalErrors[] = new InternalError($internalErrorMessage);
}
}

$out->write([
'action' => 'result',
'result' => [
'errors' => $errors,
'internalErrors' => $internalErrors,
'filteredPhpErrors' => $filteredPhpErrors,
'allPhpErrors' => $allPhpErrors,
'locallyIgnoredErrors' => $locallyIgnoredErrors,
Expand Down
20 changes: 9 additions & 11 deletions src/Parallel/ParallelAnalyser.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
use Nette\Utils\Random;
use PHPStan\Analyser\AnalyserResult;
use PHPStan\Analyser\Error;
use PHPStan\Analyser\InternalError;
use PHPStan\Collectors\CollectedData;
use PHPStan\Dependency\RootExportedNode;
use PHPStan\Process\ProcessHelper;
Expand All @@ -25,7 +26,6 @@
use function count;
use function defined;
use function ini_get;
use function is_string;
use function max;
use function memory_get_usage;
use function parse_url;
Expand Down Expand Up @@ -90,7 +90,7 @@ public function analyse(
$server = new TcpServer('127.0.0.1:0', $loop);
$this->processPool = new ProcessPool($server, static function () use ($deferred, &$jobs, &$internalErrors, &$internalErrorsCount, &$reachedInternalErrorsCountLimit, &$errors, &$filteredPhpErrors, &$allPhpErrors, &$locallyIgnoredErrors, &$linesToIgnore, &$unmatchedLineIgnores, &$collectedData, &$dependencies, &$exportedNodes, &$peakMemoryUsages): void {
if (count($jobs) > 0 && $internalErrorsCount === 0) {
$internalErrors[] = 'Some parallel worker jobs have not finished.';
$internalErrors[] = new InternalError('Some parallel worker jobs have not finished.');
$internalErrorsCount++;
}

Expand Down Expand Up @@ -139,7 +139,7 @@ public function analyse(
$serverPort = parse_url($serverAddress, PHP_URL_PORT);

$handleError = function (Throwable $error) use (&$internalErrors, &$internalErrorsCount, &$reachedInternalErrorsCountLimit): void {
$internalErrors[] = sprintf('Internal error: ' . $error->getMessage());
$internalErrors[] = new InternalError($error->getMessage());
$internalErrorsCount++;
$reachedInternalErrorsCountLimit = true;
$this->processPool->quitAll();
Expand Down Expand Up @@ -168,13 +168,11 @@ public function analyse(
$process->start(function (array $json) use ($process, &$internalErrors, &$errors, &$filteredPhpErrors, &$allPhpErrors, &$locallyIgnoredErrors, &$linesToIgnore, &$unmatchedLineIgnores, &$collectedData, &$dependencies, &$exportedNodes, &$peakMemoryUsages, &$jobs, $postFileCallback, &$internalErrorsCount, &$reachedInternalErrorsCountLimit, $processIdentifier, $onFileAnalysisHandler): void {
$fileErrors = [];
foreach ($json['errors'] as $jsonError) {
if (is_string($jsonError)) {
$internalErrors[] = sprintf('Internal error: %s', $jsonError);
continue;
}

$fileErrors[] = Error::decode($jsonError);
}
foreach ($json['internalErrors'] as $internalJsonError) {
$internalErrors[] = InternalError::decode($internalJsonError);
}

foreach ($json['filteredPhpErrors'] as $filteredPhpError) {
$filteredPhpErrors[] = Error::decode($filteredPhpError);
Expand Down Expand Up @@ -280,13 +278,13 @@ public function analyse(
$memoryLimitMessage = 'PHPStan process crashed because it reached configured PHP memory limit';
if (str_contains($output, $memoryLimitMessage)) {
foreach ($internalErrors as $internalError) {
if (!str_contains($internalError, $memoryLimitMessage)) {
if (!str_contains($internalError->getMessage(), $memoryLimitMessage)) {
continue;
}

return;
}
$internalErrors[] = sprintf(sprintf(
$internalErrors[] = new InternalError(sprintf(
"<error>Child process error</error>: %s: %s\n%s\n",
$memoryLimitMessage,
ini_get('memory_limit'),
Expand All @@ -296,7 +294,7 @@ public function analyse(
return;
}

$internalErrors[] = sprintf('<error>Child process error</error> (exit code %d): %s', $exitCode, $output);
$internalErrors[] = new InternalError(sprintf('<error>Child process error</error> (exit code %d): %s', $exitCode, $output));
$internalErrorsCount++;
});
$this->processPool->attachProcess($processIdentifier, $process);
Expand Down
3 changes: 2 additions & 1 deletion src/Testing/RuleTestCase.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use PHPStan\Analyser\AnalyserResultFinalizer;
use PHPStan\Analyser\Error;
use PHPStan\Analyser\FileAnalyser;
use PHPStan\Analyser\InternalError;
use PHPStan\Analyser\LocalIgnoresProcessor;
use PHPStan\Analyser\NodeScopeResolver;
use PHPStan\Analyser\RuleErrorTransformer;
Expand Down Expand Up @@ -176,7 +177,7 @@ public function gatherAnalyserErrors(array $files): array
true,
);
if (count($analyserResult->getInternalErrors()) > 0) {
$this->fail(implode("\n", $analyserResult->getInternalErrors()));
$this->fail(implode("\n", array_map(static fn (InternalError $internalError) => $internalError->getMessage(), $analyserResult->getInternalErrors())));
}

if ($this->shouldFailOnPhpErrors() && count($analyserResult->getAllPhpErrors()) > 0) {
Expand Down
2 changes: 1 addition & 1 deletion tests/PHPStan/Analyser/AnalyserTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -670,7 +670,7 @@ private function runAnalyser(

return array_merge(
$errors,
$analyserResult->getInternalErrors(),
array_map(static fn (InternalError $internalError) => $internalError->getMessage(), $analyserResult->getInternalErrors()),
);
}

Expand Down

0 comments on commit 7cd03f0

Please sign in to comment.