Skip to content

Commit 7cd03f0

Browse files
committed
Internal errors as structured objects
1 parent e45ba45 commit 7cd03f0

File tree

8 files changed

+78
-20
lines changed

8 files changed

+78
-20
lines changed

src/Analyser/AnalyserResult.php

+2-2
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ class AnalyserResult
2323
* @param array<string, LinesToIgnore> $linesToIgnore
2424
* @param array<string, LinesToIgnore> $unmatchedLineIgnores
2525
* @param list<CollectedData> $collectedData
26-
* @param list<string> $internalErrors
26+
* @param list<InternalError> $internalErrors
2727
* @param array<string, array<string>>|null $dependencies
2828
* @param array<string, array<RootExportedNode>> $exportedNodes
2929
*/
@@ -117,7 +117,7 @@ public function getUnmatchedLineIgnores(): array
117117
}
118118

119119
/**
120-
* @return list<string>
120+
* @return list<InternalError>
121121
*/
122122
public function getInternalErrors(): array
123123
{

src/Analyser/InternalError.php

+41
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php declare(strict_types = 1);
2+
3+
namespace PHPStan\Analyser;
4+
5+
use JsonSerializable;
6+
use ReturnTypeWillChange;
7+
8+
class InternalError implements JsonSerializable
9+
{
10+
11+
public function __construct(
12+
private string $message,
13+
)
14+
{
15+
}
16+
17+
public function getMessage(): string
18+
{
19+
return $this->message;
20+
}
21+
22+
/**
23+
* @param mixed[] $json
24+
*/
25+
public static function decode(array $json): self
26+
{
27+
return new self($json['message']);
28+
}
29+
30+
/**
31+
* @return mixed
32+
*/
33+
#[ReturnTypeWillChange]
34+
public function jsonSerialize()
35+
{
36+
return [
37+
'message' => $this->message,
38+
];
39+
}
40+
41+
}

src/Command/AnalyseApplication.php

+3-1
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,14 @@
55
use PHPStan\Analyser\AnalyserResult;
66
use PHPStan\Analyser\AnalyserResultFinalizer;
77
use PHPStan\Analyser\Ignore\IgnoredErrorHelper;
8+
use PHPStan\Analyser\InternalError;
89
use PHPStan\Analyser\ResultCache\ResultCacheManagerFactory;
910
use PHPStan\Internal\BytesHelper;
1011
use PHPStan\PhpDoc\StubFilesProvider;
1112
use PHPStan\PhpDoc\StubValidator;
1213
use PHPStan\ShouldNotHappenException;
1314
use Symfony\Component\Console\Input\InputInterface;
15+
use function array_map;
1416
use function array_merge;
1517
use function count;
1618
use function is_file;
@@ -148,7 +150,7 @@ public function analyse(
148150
if ($analyserResult->hasReachedInternalErrorsCountLimit()) {
149151
$notFileSpecificErrors[] = sprintf('Reached internal errors count limit of %d, exiting...', $this->internalErrorsCountLimit);
150152
}
151-
$notFileSpecificErrors = array_merge($notFileSpecificErrors, $internalErrors);
153+
$notFileSpecificErrors = array_merge($notFileSpecificErrors, array_map(static fn (InternalError $internalError) => $internalError->getMessage(), $internalErrors));
152154
}
153155

154156
return new AnalysisResult(

src/Command/AnalysisResult.php

+4-2
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33
namespace PHPStan\Command;
44

55
use PHPStan\Analyser\Error;
6+
use PHPStan\Analyser\InternalError;
67
use PHPStan\Collectors\CollectedData;
8+
use function array_map;
79
use function count;
810
use function usort;
911

@@ -17,7 +19,7 @@ class AnalysisResult
1719
/**
1820
* @param list<Error> $fileSpecificErrors
1921
* @param list<string> $notFileSpecificErrors
20-
* @param list<string> $internalErrors
22+
* @param list<InternalError> $internalErrors
2123
* @param list<string> $warnings
2224
* @param list<CollectedData> $collectedData
2325
* @param array<string, string> $changedProjectExtensionFilesOutsideOfAnalysedPaths
@@ -83,7 +85,7 @@ public function getNotFileSpecificErrors(): array
8385
*/
8486
public function getInternalErrors(): array
8587
{
86-
return $this->internalErrors;
88+
return array_map(static fn (InternalError $internalError) => $internalError->getMessage(), $this->internalErrors);
8789
}
8890

8991
/**

src/Command/WorkerCommand.php

+16-2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
use Clue\React\NDJson\Decoder;
66
use Clue\React\NDJson\Encoder;
77
use PHPStan\Analyser\FileAnalyser;
8+
use PHPStan\Analyser\InternalError;
89
use PHPStan\Analyser\NodeScopeResolver;
910
use PHPStan\Collectors\Registry as CollectorRegistry;
1011
use PHPStan\DependencyInjection\Container;
@@ -162,8 +163,19 @@ private function runWorker(
162163
$out->write([
163164
'action' => 'result',
164165
'result' => [
165-
'errors' => [$error->getMessage()],
166+
'errors' => [],
167+
'internalErrors' => [
168+
new InternalError($error->getMessage()),
169+
],
170+
'filteredPhpErrors' => [],
171+
'allPhpErrors' => [],
172+
'locallyIgnoredErrors' => [],
173+
'linesToIgnore' => [],
174+
'unmatchedLineIgnores' => [],
175+
'collectedData' => [],
176+
'memoryUsage' => memory_get_peak_usage(true),
166177
'dependencies' => [],
178+
'exportedNodes' => [],
167179
'files' => [],
168180
'internalErrorsCount' => 1,
169181
],
@@ -183,6 +195,7 @@ private function runWorker(
183195
$internalErrorsCount = 0;
184196
$files = $json['files'];
185197
$errors = [];
198+
$internalErrors = [];
186199
$filteredPhpErrors = [];
187200
$allPhpErrors = [];
188201
$locallyIgnoredErrors = [];
@@ -224,14 +237,15 @@ private function runWorker(
224237
$internalErrorMessage .= sprintf('%sRun PHPStan with -v option and post the stack trace to:%s%s', "\n", "\n", $bugReportUrl);
225238
}
226239

227-
$errors[] = $internalErrorMessage;
240+
$internalErrors[] = new InternalError($internalErrorMessage);
228241
}
229242
}
230243

231244
$out->write([
232245
'action' => 'result',
233246
'result' => [
234247
'errors' => $errors,
248+
'internalErrors' => $internalErrors,
235249
'filteredPhpErrors' => $filteredPhpErrors,
236250
'allPhpErrors' => $allPhpErrors,
237251
'locallyIgnoredErrors' => $locallyIgnoredErrors,

src/Parallel/ParallelAnalyser.php

+9-11
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use Nette\Utils\Random;
99
use PHPStan\Analyser\AnalyserResult;
1010
use PHPStan\Analyser\Error;
11+
use PHPStan\Analyser\InternalError;
1112
use PHPStan\Collectors\CollectedData;
1213
use PHPStan\Dependency\RootExportedNode;
1314
use PHPStan\Process\ProcessHelper;
@@ -25,7 +26,6 @@
2526
use function count;
2627
use function defined;
2728
use function ini_get;
28-
use function is_string;
2929
use function max;
3030
use function memory_get_usage;
3131
use function parse_url;
@@ -90,7 +90,7 @@ public function analyse(
9090
$server = new TcpServer('127.0.0.1:0', $loop);
9191
$this->processPool = new ProcessPool($server, static function () use ($deferred, &$jobs, &$internalErrors, &$internalErrorsCount, &$reachedInternalErrorsCountLimit, &$errors, &$filteredPhpErrors, &$allPhpErrors, &$locallyIgnoredErrors, &$linesToIgnore, &$unmatchedLineIgnores, &$collectedData, &$dependencies, &$exportedNodes, &$peakMemoryUsages): void {
9292
if (count($jobs) > 0 && $internalErrorsCount === 0) {
93-
$internalErrors[] = 'Some parallel worker jobs have not finished.';
93+
$internalErrors[] = new InternalError('Some parallel worker jobs have not finished.');
9494
$internalErrorsCount++;
9595
}
9696

@@ -139,7 +139,7 @@ public function analyse(
139139
$serverPort = parse_url($serverAddress, PHP_URL_PORT);
140140

141141
$handleError = function (Throwable $error) use (&$internalErrors, &$internalErrorsCount, &$reachedInternalErrorsCountLimit): void {
142-
$internalErrors[] = sprintf('Internal error: ' . $error->getMessage());
142+
$internalErrors[] = new InternalError($error->getMessage());
143143
$internalErrorsCount++;
144144
$reachedInternalErrorsCountLimit = true;
145145
$this->processPool->quitAll();
@@ -168,13 +168,11 @@ public function analyse(
168168
$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 {
169169
$fileErrors = [];
170170
foreach ($json['errors'] as $jsonError) {
171-
if (is_string($jsonError)) {
172-
$internalErrors[] = sprintf('Internal error: %s', $jsonError);
173-
continue;
174-
}
175-
176171
$fileErrors[] = Error::decode($jsonError);
177172
}
173+
foreach ($json['internalErrors'] as $internalJsonError) {
174+
$internalErrors[] = InternalError::decode($internalJsonError);
175+
}
178176

179177
foreach ($json['filteredPhpErrors'] as $filteredPhpError) {
180178
$filteredPhpErrors[] = Error::decode($filteredPhpError);
@@ -280,13 +278,13 @@ public function analyse(
280278
$memoryLimitMessage = 'PHPStan process crashed because it reached configured PHP memory limit';
281279
if (str_contains($output, $memoryLimitMessage)) {
282280
foreach ($internalErrors as $internalError) {
283-
if (!str_contains($internalError, $memoryLimitMessage)) {
281+
if (!str_contains($internalError->getMessage(), $memoryLimitMessage)) {
284282
continue;
285283
}
286284

287285
return;
288286
}
289-
$internalErrors[] = sprintf(sprintf(
287+
$internalErrors[] = new InternalError(sprintf(
290288
"<error>Child process error</error>: %s: %s\n%s\n",
291289
$memoryLimitMessage,
292290
ini_get('memory_limit'),
@@ -296,7 +294,7 @@ public function analyse(
296294
return;
297295
}
298296

299-
$internalErrors[] = sprintf('<error>Child process error</error> (exit code %d): %s', $exitCode, $output);
297+
$internalErrors[] = new InternalError(sprintf('<error>Child process error</error> (exit code %d): %s', $exitCode, $output));
300298
$internalErrorsCount++;
301299
});
302300
$this->processPool->attachProcess($processIdentifier, $process);

src/Testing/RuleTestCase.php

+2-1
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use PHPStan\Analyser\AnalyserResultFinalizer;
88
use PHPStan\Analyser\Error;
99
use PHPStan\Analyser\FileAnalyser;
10+
use PHPStan\Analyser\InternalError;
1011
use PHPStan\Analyser\LocalIgnoresProcessor;
1112
use PHPStan\Analyser\NodeScopeResolver;
1213
use PHPStan\Analyser\RuleErrorTransformer;
@@ -176,7 +177,7 @@ public function gatherAnalyserErrors(array $files): array
176177
true,
177178
);
178179
if (count($analyserResult->getInternalErrors()) > 0) {
179-
$this->fail(implode("\n", $analyserResult->getInternalErrors()));
180+
$this->fail(implode("\n", array_map(static fn (InternalError $internalError) => $internalError->getMessage(), $analyserResult->getInternalErrors())));
180181
}
181182

182183
if ($this->shouldFailOnPhpErrors() && count($analyserResult->getAllPhpErrors()) > 0) {

tests/PHPStan/Analyser/AnalyserTest.php

+1-1
Original file line numberDiff line numberDiff line change
@@ -670,7 +670,7 @@ private function runAnalyser(
670670

671671
return array_merge(
672672
$errors,
673-
$analyserResult->getInternalErrors(),
673+
array_map(static fn (InternalError $internalError) => $internalError->getMessage(), $analyserResult->getInternalErrors()),
674674
);
675675
}
676676

0 commit comments

Comments
 (0)