Skip to content

Commit

Permalink
Do not always ask to report bug about an internal error
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed Jun 16, 2024
1 parent 0b95634 commit 3cd6416
Show file tree
Hide file tree
Showing 8 changed files with 57 additions and 16 deletions.
9 changes: 8 additions & 1 deletion src/Analyser/InternalError.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public function __construct(
private string $contextDescription,
private array $trace,
private ?string $traceAsString,
private bool $shouldReportBug,
)
{
}
Expand Down Expand Up @@ -71,12 +72,17 @@ public function getTraceAsString(): ?string
return $this->traceAsString;
}

public function shouldReportBug(): bool
{
return $this->shouldReportBug;
}

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

/**
Expand All @@ -90,6 +96,7 @@ public function jsonSerialize()
'contextDescription' => $this->contextDescription,
'trace' => $this->trace,
'traceAsString' => $this->traceAsString,
'shouldReportBug' => $this->shouldReportBug,
];
}

Expand Down
43 changes: 31 additions & 12 deletions src/Command/AnalyseCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
use Symfony\Component\Console\Output\StreamOutput;
use Throwable;
use function array_intersect;
use function array_key_exists;
use function array_keys;
use function array_map;
use function array_unique;
Expand Down Expand Up @@ -332,10 +333,11 @@ protected function execute(InputInterface $input, OutputInterface $output): int
$internalErrors = [];
foreach ($analysisResult->getInternalErrorObjects() as $internalError) {
$internalErrors[$internalError->getMessage()] = new InternalError(
sprintf('Internal error: %s', $internalError->getMessage()),
$internalError->getTraceAsString() !== null ? sprintf('Internal error: %s', $internalError->getMessage()) : $internalError->getMessage(),
$internalError->getContextDescription(),
$internalError->getTrace(),
$internalError->getTraceAsString(),
$internalError->shouldReportBug(),
);
}
foreach ($analysisResult->getFileSpecificErrors() as $fileSpecificError) {
Expand All @@ -344,39 +346,56 @@ protected function execute(InputInterface $input, OutputInterface $output): int
}

$message = $fileSpecificError->getMessage();
if ($fileSpecificError->getIdentifier() === 'phpstan.internal') {
$metadata = $fileSpecificError->getMetadata();
if (
$fileSpecificError->getIdentifier() === 'phpstan.internal'
&& array_key_exists(InternalError::STACK_TRACE_AS_STRING_METADATA_KEY, $metadata)
) {
$message = sprintf('Internal error: %s', $message);
}

$metadata = $fileSpecificError->getMetadata();
$internalErrors[$fileSpecificError->getMessage()] = new InternalError(
$message,
sprintf('analysing file %s', $fileSpecificError->getTraitFilePath() ?? $fileSpecificError->getFilePath()),
$metadata[InternalError::STACK_TRACE_METADATA_KEY] ?? [],
$metadata[InternalError::STACK_TRACE_AS_STRING_METADATA_KEY] ?? null,
true,
);
}

$internalErrors = array_values($internalErrors);
$bugReportUrl = 'https://github.com/phpstan/phpstan/issues/new?template=Bug_report.yaml';
foreach ($internalErrors as $i => $internalError) {
$message = sprintf('%s while %s', $internalError->getMessage(), $internalError->getContextDescription());
if (OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
$firstTraceItem = $internalError->getTrace()[0] ?? null;
$trace = '';
if ($firstTraceItem !== null && $firstTraceItem['file'] !== null && $firstTraceItem['line'] !== null) {
$trace = sprintf('## %s(%d)%s', $firstTraceItem['file'], $firstTraceItem['line'], "\n");
if ($internalError->getTraceAsString() !== null) {
if (OutputInterface::VERBOSITY_VERBOSE <= $output->getVerbosity()) {
$firstTraceItem = $internalError->getTrace()[0] ?? null;
$trace = '';
if ($firstTraceItem !== null && $firstTraceItem['file'] !== null && $firstTraceItem['line'] !== null) {
$trace = sprintf('## %s(%d)%s', $firstTraceItem['file'], $firstTraceItem['line'], "\n");
}
$trace .= $internalError->getTraceAsString();

if ($internalError->shouldReportBug()) {
$message .= sprintf('%sPost the following stack trace to %s: %s%s', "\n", $bugReportUrl, "\n", $trace);
} else {
$message .= sprintf('%s%s', "\n\n", $trace);
}
} else {
if ($internalError->shouldReportBug()) {
$message .= sprintf('%sRun PHPStan with -v option and post the stack trace to:%s%s%s', "\n\n", "\n", $bugReportUrl, "\n");
} else {
$message .= sprintf('%sRun PHPStan with -v option to see the stack trace', "\n");
}
}
$trace .= $internalError->getTraceAsString();
$message .= sprintf('%sPost the following stack trace to %s: %s%s', "\n\n", $bugReportUrl, "\n", $trace);
} else {
$message .= sprintf('%sRun PHPStan with -v option and post the stack trace to:%s%s', "\n", "\n", $bugReportUrl);
}

$internalErrors[$i] = new InternalError(
$message,
$internalError->getContextDescription(),
$internalError->getTrace(),
$internalError->getTraceAsString(),
$internalError->shouldReportBug(),
);
}

Expand Down
1 change: 1 addition & 0 deletions src/Command/FixerApplication.php
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,7 @@ private function analyse(
'running PHPStan Pro worker',
InternalError::prepareTrace($e),
$e->getTraceAsString(),
false,
)],
]]);
throw $e;
Expand Down
1 change: 1 addition & 0 deletions src/Command/FixerWorkerCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ function (array $errors, array $locallyIgnoredErrors, array $analysedFiles) use
'running analyser in PHPStan Pro worker',
[],
null,
false,
),
],
]]);
Expand Down
2 changes: 2 additions & 0 deletions src/Command/WorkerCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,7 @@ private function runWorker(
'communicating with main process in parallel worker',
InternalError::prepareTrace($error),
$error->getTraceAsString(),
true,
),
],
'filteredPhpErrors' => [],
Expand Down Expand Up @@ -235,6 +236,7 @@ private function runWorker(
sprintf('analysing file %s', $file),
InternalError::prepareTrace($t),
$t->getTraceAsString(),
true,
);
}
}
Expand Down
4 changes: 3 additions & 1 deletion src/Parallel/ParallelAnalyser.php
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ public function analyse(
'running parallel worker',
[],
null,
true,
);
$internalErrorsCount++;
}
Expand Down Expand Up @@ -149,6 +150,7 @@ public function analyse(
'communicating with parallel worker',
InternalError::prepareTrace($error),
$error->getTraceAsString(),
!$error instanceof ProcessTimedOutException,
);
$internalErrorsCount++;
$reachedInternalErrorsCountLimit = true;
Expand Down Expand Up @@ -299,7 +301,7 @@ public function analyse(
$memoryLimitMessage,
ini_get('memory_limit'),
'Increase your memory limit in php.ini or run PHPStan with --memory-limit CLI option.',
), 'running parallel worker', [], null);
), 'running parallel worker', [], null, false);
$internalErrorsCount++;
return;
}
Expand Down
3 changes: 1 addition & 2 deletions src/Parallel/Process.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@

namespace PHPStan\Parallel;

use Exception;
use PHPStan\ShouldNotHappenException;
use React\EventLoop\LoopInterface;
use React\EventLoop\TimerInterface;
Expand Down Expand Up @@ -112,7 +111,7 @@ public function request(array $data): void
$this->in->write($data);
$this->timer = $this->loop->addTimer($this->timeoutSeconds, function (): void {
$onError = $this->onError;
$onError(new Exception(sprintf('Child process timed out after %.1f seconds. Try making it longer with parallel.processTimeout setting.', $this->timeoutSeconds)));
$onError(new ProcessTimedOutException(sprintf('Child process timed out after %.1f seconds. Try making it longer with parallel.processTimeout setting.', $this->timeoutSeconds)));
});
}

Expand Down
10 changes: 10 additions & 0 deletions src/Parallel/ProcessTimedOutException.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php declare(strict_types = 1);

namespace PHPStan\Parallel;

use Exception;

class ProcessTimedOutException extends Exception
{

}

0 comments on commit 3cd6416

Please sign in to comment.