From 475a18ce8e0e14e340d7a0939906fffa6dd28e8d Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Wed, 11 Sep 2024 11:29:08 +0200 Subject: [PATCH] Special internal error message for Larastan+Laravel --- src/Command/AnalyseCommand.php | 55 ++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 3 deletions(-) diff --git a/src/Command/AnalyseCommand.php b/src/Command/AnalyseCommand.php index 4e9d20c150..a112f22235 100644 --- a/src/Command/AnalyseCommand.php +++ b/src/Command/AnalyseCommand.php @@ -13,6 +13,7 @@ use PHPStan\Diagnose\DiagnoseExtension; use PHPStan\Diagnose\PHPStanDiagnoseExtension; use PHPStan\File\CouldNotWriteFileException; +use PHPStan\File\FileHelper; use PHPStan\File\FileReader; use PHPStan\File\FileWriter; use PHPStan\File\ParentDirectoryRelativePathHelper; @@ -34,6 +35,7 @@ use function array_key_exists; use function array_keys; use function array_map; +use function array_reverse; use function array_unique; use function array_values; use function count; @@ -50,12 +52,16 @@ use function pathinfo; use function rewind; use function sprintf; +use function str_contains; use function stream_get_contents; use function strlen; use function substr; use const PATHINFO_BASENAME; use const PATHINFO_EXTENSION; +/** + * @phpstan-import-type Trace from InternalError as InternalErrorTrace + */ final class AnalyseCommand extends Command { @@ -386,6 +392,8 @@ protected function execute(InputInterface $input, OutputInterface $output): int $internalErrorsTuples = array_values($internalErrorsTuples); + $fileHelper = $container->getByType(FileHelper::class); + /** * Variable $internalErrors only contains non-file-specific "internal errors". */ @@ -396,7 +404,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int } $internalErrors[] = new InternalError( - $this->getMessageFromInternalError($internalError, $output->getVerbosity()), + $this->getMessageFromInternalError($fileHelper, $internalError, $output->getVerbosity()), $internalError->getContextDescription(), $internalError->getTrace(), $internalError->getTraceAsString(), @@ -530,10 +538,51 @@ private function createStreamOutput(): StreamOutput return new StreamOutput($resource); } - private function getMessageFromInternalError(InternalError $internalError, int $verbosity): string + private function getMessageFromInternalError(FileHelper $fileHelper, InternalError $internalError, int $verbosity): string { - $bugReportUrl = 'https://github.com/phpstan/phpstan/issues/new?template=Bug_report.yaml'; $message = sprintf('%s while %s', $internalError->getMessage(), $internalError->getContextDescription()); + $hasLarastan = false; + $isLaravelLast = false; + + foreach (array_reverse($internalError->getTrace()) as $traceItem) { + if ($traceItem['file'] === null) { + continue; + } + + $file = $fileHelper->normalizePath($traceItem['file'], '/'); + + if (str_contains($file, '/larastan/')) { + $hasLarastan = true; + $isLaravelLast = false; + continue; + } + + if (!str_contains($file, '/laravel/framework/')) { + continue; + } + + $isLaravelLast = true; + } + if ($hasLarastan) { + if ($isLaravelLast) { + $message .= "\n"; + $message .= "\n" . 'This message is coming from Laravel Framework itself.'; + $message .= "\n" . 'Larastan boots up your application in order to provide'; + $message .= "\n" . 'smarter static analysis of your codebase.'; + $message .= "\n"; + $message .= "\n" . 'In order to do that, the environment you run PHPStan in'; + $message .= "\n" . 'must match the environment you run your application in.'; + $message .= "\n"; + $message .= "\n" . 'Make sure you\'ve set your environment variables'; + $message .= "\n" . 'or the .env file correctly.'; + + return $message; + } + + $bugReportUrl = 'https://github.com/larastan/larastan/issues/new?template=bug-report.md'; + } else { + $bugReportUrl = 'https://github.com/phpstan/phpstan/issues/new?template=Bug_report.yaml'; + } if ($internalError->getTraceAsString() !== null) { if (OutputInterface::VERBOSITY_VERBOSE <= $verbosity) { $firstTraceItem = $internalError->getTrace()[0] ?? null;