extension-installer icon indicating copy to clipboard operation
extension-installer copied to clipboard

Automatic PHPStan extension loading in rector

Open staabm opened this issue 10 months ago • 9 comments

Feature request

In https://github.com/rectorphp/rector-src/pull/4769 rector dropped automatic loading of PHPStan extensions, because it seems to much work to maintain the feature.

As of this linked PR one needs to manually register PHPExtensions to rectors' internal PHPStan , so it will utilize the additional sources of type-knowledge. Its a pity that we have the luxury of the Extension Installer for PHPStan, but don't have it anymore for rector - as manually keeping a list of extensions is a maintenance pain.

my local testing suggests, to get it running again I need to add a phpstan.neon to rector which contains a includes: config with a php file like:

<?php

declare(strict_types=1);

use PHPStan\Command\InceptionNotSuccessfulException;
use PHPStan\ExtensionInstaller\GeneratedConfig;

$additionalConfigFiles = [];

if (class_exists('PHPStan\ExtensionInstaller\GeneratedConfig')) {
    $generatedConfigReflection = new ReflectionClass('PHPStan\ExtensionInstaller\GeneratedConfig');
    $generatedConfigDirectory = dirname($generatedConfigReflection->getFileName());
    foreach (GeneratedConfig::EXTENSIONS as $name => $extensionConfig) {
        foreach ($extensionConfig['extra']['includes'] ?? [] as $includedFile) {
            if (!is_string($includedFile)) {
                $errorOutput->writeLineFormatted(sprintf('Cannot include config from package %s, expecting string file path but got %s', $name, gettype($includedFile)));
                throw new InceptionNotSuccessfulException();
            }
            $includedFilePath = null;
            if (isset($extensionConfig['relative_install_path'])) {
                $includedFilePath = sprintf('%s/%s/%s', $generatedConfigDirectory, $extensionConfig['relative_install_path'], $includedFile);
                if (!is_file($includedFilePath) || !is_readable($includedFilePath)) {
                    $includedFilePath = null;
                }
            }

            if ($includedFilePath === null) {
                $includedFilePath = sprintf('%s/%s', $extensionConfig['install_path'], $includedFile);
            }
            if (!is_file($includedFilePath) || !is_readable($includedFilePath)) {
                $errorOutput->writeLineFormatted(sprintf('Config file %s does not exist or isn\'t readable', $includedFilePath));
                throw new InceptionNotSuccessfulException();
            }
            $additionalConfigFiles[] = $includedFilePath;
        }
    }
}

return ['includes' => $additionalConfigFiles];

this means I copied the logic from CommandHelper

could we move this part into a new method, so I can call it from my php-file which gets loaded via includes: instead of duplicating the logic?

Did PHPStan help you today? Did it make you happy in any way?

No response

staabm avatar Aug 16 '23 16:08 staabm