mirror of
https://github.com/danog/psalm.git
synced 2025-01-21 21:31:13 +01:00
Use composer autoloader for class resolution where possible
This commit is contained in:
parent
1982d08573
commit
ade9e03c85
@ -377,23 +377,19 @@ class Scanner
|
||||
throw new \InvalidArgumentException('Why are you asking about a builtin class?');
|
||||
}
|
||||
|
||||
if ($this->composer_classmap === null) {
|
||||
$this->composer_classmap = $this->config->getComposerClassMap($this->debug_output);
|
||||
}
|
||||
$composer_file_path = $this->config->getComposerFilePathForClassLike($fq_class_name);
|
||||
|
||||
if (isset($this->composer_classmap[$fq_class_name_lc])) {
|
||||
if (file_exists($this->composer_classmap[$fq_class_name_lc])) {
|
||||
if ($this->debug_output) {
|
||||
echo 'Using generated composer classmap to locate file for ' . $fq_class_name . PHP_EOL;
|
||||
}
|
||||
|
||||
$classlikes->addFullyQualifiedClassLikeName(
|
||||
$fq_class_name_lc,
|
||||
$this->composer_classmap[$fq_class_name_lc]
|
||||
);
|
||||
|
||||
return true;
|
||||
if ($composer_file_path && file_exists($composer_file_path)) {
|
||||
if ($this->debug_output) {
|
||||
echo 'Using composer to locate file for ' . $fq_class_name . PHP_EOL;
|
||||
}
|
||||
|
||||
$classlikes->addFullyQualifiedClassLikeName(
|
||||
$fq_class_name_lc,
|
||||
realpath($composer_file_path)
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
$old_level = error_reporting();
|
||||
|
@ -1,6 +1,7 @@
|
||||
<?php
|
||||
namespace Psalm;
|
||||
|
||||
use Composer\Autoload\ClassLoader;
|
||||
use Psalm\Checker\ClassLikeChecker;
|
||||
use Psalm\Checker\ProjectChecker;
|
||||
use Psalm\Config\IssueHandler;
|
||||
@ -233,6 +234,9 @@ class Config
|
||||
/** @var array<string, bool> */
|
||||
private $predefined_functions = [];
|
||||
|
||||
/** @var ClassLoader|null */
|
||||
private $composer_class_loader;
|
||||
|
||||
protected function __construct()
|
||||
{
|
||||
self::$instance = $this;
|
||||
@ -512,6 +516,11 @@ class Config
|
||||
throw new \UnexpectedValueException('No config initialized');
|
||||
}
|
||||
|
||||
public function setComposerClassLoader(ClassLoader $loader)
|
||||
{
|
||||
$this->composer_class_loader = $loader;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param string $issue_key
|
||||
* @param string $error_level
|
||||
@ -941,74 +950,17 @@ class Config
|
||||
}
|
||||
|
||||
/**
|
||||
* @param bool $debug_output
|
||||
* @return array<string, string>
|
||||
* @param string $fq_classlike_name
|
||||
*
|
||||
* @psalm-suppress LessSpecificReturnStatement
|
||||
* @psalm-suppress MoreSpecificReturnType
|
||||
* @return string|false
|
||||
*/
|
||||
public function getComposerClassMap($debug_output)
|
||||
public function getComposerFilePathForClassLike($fq_classlike_name)
|
||||
{
|
||||
if ($debug_output) {
|
||||
echo 'Trying to get composer classmap in ' . $this->base_dir . PHP_EOL;
|
||||
if (!$this->composer_class_loader) {
|
||||
throw new \LogicException('Composer class loader should exist here');
|
||||
}
|
||||
|
||||
$vendor_dir_path = $this->base_dir . self::getVendorDir($this->base_dir);
|
||||
|
||||
if (!is_dir($vendor_dir_path)) {
|
||||
if ($debug_output) {
|
||||
echo 'Could not resolve path to ' . $vendor_dir_path . PHP_EOL;
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
$vendor_dir_path = realpath($vendor_dir_path);
|
||||
|
||||
if (!$vendor_dir_path) {
|
||||
if ($debug_output) {
|
||||
echo 'Realpath failed when loading composer classmap' . PHP_EOL;
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
$autoload_files_classmap =
|
||||
$vendor_dir_path . DIRECTORY_SEPARATOR . 'composer' . DIRECTORY_SEPARATOR . 'autoload_classmap.php';
|
||||
|
||||
if (!file_exists($autoload_files_classmap)) {
|
||||
if ($debug_output) {
|
||||
echo 'No autoload_classmap.php found in ' . $vendor_dir_path . PHP_EOL;
|
||||
}
|
||||
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @psalm-suppress MixedAssignment
|
||||
* @psalm-suppress UnresolvableInclude
|
||||
*/
|
||||
$class_map = include_once $autoload_files_classmap;
|
||||
|
||||
if (is_array($class_map)) {
|
||||
$composer_classmap = array_change_key_case($class_map);
|
||||
|
||||
$composer_classmap = array_filter(
|
||||
$composer_classmap,
|
||||
/**
|
||||
* @param string $file_path
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
function ($file_path) use ($vendor_dir_path) {
|
||||
return strpos($file_path, $vendor_dir_path) === 0;
|
||||
}
|
||||
);
|
||||
} else {
|
||||
$composer_classmap = [];
|
||||
}
|
||||
|
||||
return $composer_classmap;
|
||||
return $this->composer_class_loader->findFile($fq_classlike_name);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -5,7 +5,7 @@
|
||||
* @param bool $has_explicit_root
|
||||
* @param string $vendor_dir
|
||||
*
|
||||
* @return void
|
||||
* @return \Composer\Autoload\ClassLoader
|
||||
*/
|
||||
function requireAutoloaders($current_dir, $has_explicit_root, $vendor_dir)
|
||||
{
|
||||
@ -25,7 +25,10 @@ function requireAutoloaders($current_dir, $has_explicit_root, $vendor_dir)
|
||||
$nested_autoload_file = dirname(dirname($autoload_root)) . DIRECTORY_SEPARATOR . 'autoload.php';
|
||||
|
||||
if (file_exists($nested_autoload_file)) {
|
||||
$autoload_files[] = realpath($nested_autoload_file);
|
||||
$nested_autoload_file_path = realpath($nested_autoload_file);
|
||||
if (!in_array($nested_autoload_file_path, $autoload_files, false)) {
|
||||
$autoload_files[] = $nested_autoload_file_path;
|
||||
}
|
||||
$has_autoloader = true;
|
||||
}
|
||||
|
||||
@ -33,7 +36,10 @@ function requireAutoloaders($current_dir, $has_explicit_root, $vendor_dir)
|
||||
$autoload_root . DIRECTORY_SEPARATOR . $vendor_dir . DIRECTORY_SEPARATOR . 'autoload.php';
|
||||
|
||||
if (file_exists($vendor_autoload_file)) {
|
||||
$autoload_files[] = realpath($vendor_autoload_file);
|
||||
$autoload_file_path = realpath($vendor_autoload_file);
|
||||
if (!in_array($autoload_file_path, $autoload_files, false)) {
|
||||
$autoload_files[] = $autoload_file_path;
|
||||
}
|
||||
$has_autoloader = true;
|
||||
}
|
||||
|
||||
@ -49,12 +55,20 @@ function requireAutoloaders($current_dir, $has_explicit_root, $vendor_dir)
|
||||
}
|
||||
}
|
||||
|
||||
$first_autoloader = null;
|
||||
|
||||
foreach ($autoload_files as $file) {
|
||||
/** @psalm-suppress UnresolvableInclude */
|
||||
require_once $file;
|
||||
$autoloader = require_once $file;
|
||||
|
||||
if (!$first_autoloader) {
|
||||
$first_autoloader = $autoloader;
|
||||
}
|
||||
}
|
||||
|
||||
define('PSALM_VERSION', (string) \Muglug\PackageVersions\Versions::getVersion('vimeo/psalm'));
|
||||
|
||||
return $first_autoloader;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -139,7 +139,7 @@ if (isset($options['r']) && is_string($options['r'])) {
|
||||
|
||||
$vendor_dir = getVendorDir($current_dir);
|
||||
|
||||
requireAutoloaders($current_dir, isset($options['r']), $vendor_dir);
|
||||
$first_autoloader = requireAutoloaders($current_dir, isset($options['r']), $vendor_dir);
|
||||
|
||||
if (array_key_exists('v', $options)) {
|
||||
echo 'Psalm ' . PSALM_VERSION . PHP_EOL;
|
||||
@ -266,6 +266,8 @@ if ($path_to_config) {
|
||||
$config = Config::getConfigForPath($current_dir, $current_dir, $output_format);
|
||||
}
|
||||
|
||||
$config->setComposerClassLoader($first_autoloader);
|
||||
|
||||
$file_storage_cache_provider = isset($options['no-cache'])
|
||||
? new Psalm\Provider\NoCache\NoFileStorageCacheProvider()
|
||||
: new Psalm\Provider\FileStorageCacheProvider($config);
|
||||
|
Loading…
x
Reference in New Issue
Block a user