From 58d202fddc5597a1fa274ca3b64c352717818c4f Mon Sep 17 00:00:00 2001 From: Ondrej Mirtes Date: Mon, 19 Aug 2024 15:47:15 +0200 Subject: [PATCH] PHPStanDiagnoseExtension - show Composer packages with included config files --- conf/config.neon | 1 + src/Diagnose/PHPStanDiagnoseExtension.php | 56 +++++++++++++++++++++++ 2 files changed, 57 insertions(+) diff --git a/conf/config.neon b/conf/config.neon index c85cce945d..46f65b6fbb 100644 --- a/conf/config.neon +++ b/conf/config.neon @@ -2137,6 +2137,7 @@ services: class: PHPStan\Diagnose\PHPStanDiagnoseExtension arguments: composerAutoloaderProjectPaths: %composerAutoloaderProjectPaths% + allConfigFiles: %allConfigFiles% autowired: false # Error formatters diff --git a/src/Diagnose/PHPStanDiagnoseExtension.php b/src/Diagnose/PHPStanDiagnoseExtension.php index 0873b4f802..8a0834d278 100644 --- a/src/Diagnose/PHPStanDiagnoseExtension.php +++ b/src/Diagnose/PHPStanDiagnoseExtension.php @@ -5,13 +5,21 @@ use Phar; use PHPStan\Command\Output; use PHPStan\ExtensionInstaller\GeneratedConfig; +use PHPStan\File\FileHelper; use PHPStan\Internal\ComposerHelper; use PHPStan\Php\PhpVersion; +use function array_key_exists; +use function array_slice; use function class_exists; use function count; use function dirname; +use function explode; +use function implode; use function is_file; use function sprintf; +use function str_starts_with; +use function strlen; +use function substr; use const PHP_VERSION_ID; class PHPStanDiagnoseExtension implements DiagnoseExtension @@ -19,10 +27,13 @@ class PHPStanDiagnoseExtension implements DiagnoseExtension /** * @param string[] $composerAutoloaderProjectPaths + * @param string [] $allConfigFiles */ public function __construct( private PhpVersion $phpVersion, + private FileHelper $fileHelper, private array $composerAutoloaderProjectPaths, + private array $allConfigFiles, ) { } @@ -71,6 +82,51 @@ public function print(Output $output): void } $output->writeLineFormatted(''); + $thirdPartyIncludedConfigs = []; + foreach ($this->allConfigFiles as $configFile) { + $configFile = $this->fileHelper->normalizePath($configFile, '/'); + foreach ($this->composerAutoloaderProjectPaths as $composerAutoloaderProjectPath) { + $composerConfig = ComposerHelper::getComposerConfig($composerAutoloaderProjectPath); + if ($composerConfig === null) { + continue; + } + $vendorDir = $this->fileHelper->normalizePath(ComposerHelper::getVendorDirFromComposerConfig($composerAutoloaderProjectPath, $composerConfig), '/'); + if (!str_starts_with($configFile, $vendorDir)) { + continue; + } + + $installedPath = $vendorDir . '/composer/installed.php'; + if (!is_file($installedPath)) { + continue; + } + + $installed = require $installedPath; + + $trimmed = substr($configFile, strlen($vendorDir) + 1); + $parts = explode('/', $trimmed); + $package = implode('/', array_slice($parts, 0, 2)); + $configPath = implode('/', array_slice($parts, 2)); + if (!array_key_exists($package, $installed['versions'])) { + continue; + } + + $packageVersion = $installed['versions'][$package]['pretty_version'] ?? null; + if ($packageVersion === null) { + continue; + } + + $thirdPartyIncludedConfigs[] = [$package, $packageVersion, $configPath]; + } + } + + if (count($thirdPartyIncludedConfigs) > 0) { + $output->writeLineFormatted('Included configs from Composer packages:'); + foreach ($thirdPartyIncludedConfigs as [$package, $packageVersion, $configPath]) { + $output->writeLineFormatted(sprintf('%s (%s): %s', $package, $configPath, $packageVersion)); + } + $output->writeLineFormatted(''); + } + $composerAutoloaderProjectPathsCount = count($this->composerAutoloaderProjectPaths); $output->writeLineFormatted(sprintf( 'Discovered Composer project %s:',