1313use PHPStan \Diagnose \DiagnoseExtension ;
1414use PHPStan \Diagnose \PHPStanDiagnoseExtension ;
1515use PHPStan \File \CouldNotWriteFileException ;
16+ use PHPStan \File \FileHelper ;
1617use PHPStan \File \FileReader ;
1718use PHPStan \File \FileWriter ;
1819use PHPStan \File \ParentDirectoryRelativePathHelper ;
3435use function array_key_exists ;
3536use function array_keys ;
3637use function array_map ;
38+ use function array_reverse ;
3739use function array_unique ;
3840use function array_values ;
3941use function count ;
5052use function pathinfo ;
5153use function rewind ;
5254use function sprintf ;
55+ use function str_contains ;
5356use function stream_get_contents ;
5457use function strlen ;
5558use function substr ;
5659use const PATHINFO_BASENAME ;
5760use const PATHINFO_EXTENSION ;
5861
62+ /**
63+ * @phpstan-import-type Trace from InternalError as InternalErrorTrace
64+ */
5965final class AnalyseCommand extends Command
6066{
6167
@@ -386,6 +392,8 @@ protected function execute(InputInterface $input, OutputInterface $output): int
386392
387393 $ internalErrorsTuples = array_values ($ internalErrorsTuples );
388394
395+ $ fileHelper = $ container ->getByType (FileHelper::class);
396+
389397 /**
390398 * Variable $internalErrors only contains non-file-specific "internal errors".
391399 */
@@ -396,7 +404,7 @@ protected function execute(InputInterface $input, OutputInterface $output): int
396404 }
397405
398406 $ internalErrors [] = new InternalError (
399- $ this ->getMessageFromInternalError ($ internalError , $ output ->getVerbosity ()),
407+ $ this ->getMessageFromInternalError ($ fileHelper , $ internalError , $ output ->getVerbosity ()),
400408 $ internalError ->getContextDescription (),
401409 $ internalError ->getTrace (),
402410 $ internalError ->getTraceAsString (),
@@ -530,10 +538,51 @@ private function createStreamOutput(): StreamOutput
530538 return new StreamOutput ($ resource );
531539 }
532540
533- private function getMessageFromInternalError (InternalError $ internalError , int $ verbosity ): string
541+ private function getMessageFromInternalError (FileHelper $ fileHelper , InternalError $ internalError , int $ verbosity ): string
534542 {
535- $ bugReportUrl = 'https://github.com/phpstan/phpstan/issues/new?template=Bug_report.yaml ' ;
536543 $ message = sprintf ('%s while %s ' , $ internalError ->getMessage (), $ internalError ->getContextDescription ());
544+ $ hasLarastan = false ;
545+ $ isLaravelLast = false ;
546+
547+ foreach (array_reverse ($ internalError ->getTrace ()) as $ traceItem ) {
548+ if ($ traceItem ['file ' ] === null ) {
549+ continue ;
550+ }
551+
552+ $ file = $ fileHelper ->normalizePath ($ traceItem ['file ' ], '/ ' );
553+
554+ if (str_contains ($ file , '/larastan/ ' )) {
555+ $ hasLarastan = true ;
556+ $ isLaravelLast = false ;
557+ continue ;
558+ }
559+
560+ if (!str_contains ($ file , '/laravel/framework/ ' )) {
561+ continue ;
562+ }
563+
564+ $ isLaravelLast = true ;
565+ }
566+ if ($ hasLarastan ) {
567+ if ($ isLaravelLast ) {
568+ $ message .= "\n" ;
569+ $ message .= "\n" . 'This message is coming from Laravel Framework itself. ' ;
570+ $ message .= "\n" . 'Larastan boots up your application in order to provide ' ;
571+ $ message .= "\n" . 'smarter static analysis of your codebase. ' ;
572+ $ message .= "\n" ;
573+ $ message .= "\n" . 'In order to do that, the environment you run PHPStan in ' ;
574+ $ message .= "\n" . 'must match the environment you run your application in. ' ;
575+ $ message .= "\n" ;
576+ $ message .= "\n" . 'Make sure you \'ve set your environment variables ' ;
577+ $ message .= "\n" . 'or the .env file correctly. ' ;
578+
579+ return $ message ;
580+ }
581+
582+ $ bugReportUrl = 'https://github.com/larastan/larastan/issues/new?template=bug-report.md ' ;
583+ } else {
584+ $ bugReportUrl = 'https://github.com/phpstan/phpstan/issues/new?template=Bug_report.yaml ' ;
585+ }
537586 if ($ internalError ->getTraceAsString () !== null ) {
538587 if (OutputInterface::VERBOSITY_VERBOSE <= $ verbosity ) {
539588 $ firstTraceItem = $ internalError ->getTrace ()[0 ] ?? null ;
0 commit comments