1
0
mirror of https://github.com/danog/psalm.git synced 2025-01-22 05:41:20 +01:00

Add means to guess PSR4 file path

This commit is contained in:
Matthew Brown 2019-06-05 00:00:42 -04:00
parent f309c755f8
commit ad4e2f72e2
4 changed files with 98 additions and 3 deletions

View File

@ -882,7 +882,7 @@ class Config
/**
* @return void
*/
public function setComposerClassLoader(ClassLoader $loader = null)
public function setComposerClassLoader(?ClassLoader $loader = null)
{
$this->composer_class_loader = $loader;
}
@ -1642,6 +1642,47 @@ class Config
return $this->composer_class_loader->findFile($fq_classlike_name);
}
public function getPotentialComposerFilePathForClassLike(string $class) : ?string
{
if (!$this->composer_class_loader) {
return null;
}
/** @var array<string, array<int, string>> */
$psr4_prefixes = $this->composer_class_loader->getPrefixesPsr4();
// PSR-4 lookup
$logicalPathPsr4 = strtr($class, '\\', DIRECTORY_SEPARATOR) . '.php';
$candidate_path = null;
$maxDepth = 0;
$subPath = $class;
while (false !== $lastPos = strrpos($subPath, '\\')) {
$subPath = substr($subPath, 0, $lastPos);
$search = $subPath . '\\';
if (isset($psr4_prefixes[$search])) {
$depth = substr_count($search, '\\');
$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
foreach ($psr4_prefixes[$search] as $dir) {
$dir = realpath($dir);
if ($dir
&& $depth > $maxDepth
&& $this->isInProjectDirs($dir . DIRECTORY_SEPARATOR . 'testdummy.php')
) {
$maxDepth = $depth;
$candidate_path = realpath($dir) . $pathEnd;
}
}
}
}
return $candidate_path;
}
/**
* @param string $dir
*

View File

@ -118,7 +118,7 @@ class ForeachAnalyzer
$statements_analyzer,
$var_comment->type_start,
$var_comment->type_end,
$var_comment->line_number,
$var_comment->line_number
);
$codebase->classlikes->handleDocblockTypeInMigration(

View File

@ -128,7 +128,7 @@ class AssignmentAnalyzer
$statements_analyzer,
$var_comment->type_start,
$var_comment->type_end,
$var_comment->line_number,
$var_comment->line_number
);
$codebase->classlikes->handleDocblockTypeInMigration(

View File

@ -1310,4 +1310,58 @@ class ConfigTest extends \Psalm\Tests\TestCase
$this->analyzeFile($file_path, new Context());
}
/**
* @return void
*/
public function testGetPossiblePsr4Path()
{
$this->project_analyzer = $this->getProjectAnalyzerWithConfig(
Config::loadFromXML(
dirname(__DIR__, 2),
'<?xml version="1.0"?>
<psalm>
<projectFiles>
<directory name="src" />
<directory name="tests" />
</projectFiles>
</psalm>'
)
);
$config = $this->project_analyzer->getConfig();
$classloader = new \Composer\Autoload\ClassLoader();
$classloader->addPsr4(
'Psalm\\',
[
dirname(__DIR__, 2)
. DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'composer' . DIRECTORY_SEPARATOR
. '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR
. 'src' . DIRECTORY_SEPARATOR . 'Psalm'
]
);
$classloader->addPsr4(
'Psalm\\Tests\\',
[
dirname(__DIR__, 2)
. DIRECTORY_SEPARATOR . 'vendor' . DIRECTORY_SEPARATOR . 'composer' . DIRECTORY_SEPARATOR
. '..' . DIRECTORY_SEPARATOR . '..' . DIRECTORY_SEPARATOR
. 'tests'
]
);
$config->setComposerClassLoader($classloader);
$this->assertSame(
dirname(__DIR__, 2) . DIRECTORY_SEPARATOR . 'src' . DIRECTORY_SEPARATOR . 'Psalm' . DIRECTORY_SEPARATOR . 'Foo.php',
$config->getPotentialComposerFilePathForClassLike("Psalm\\Foo")
);
$this->assertSame(
dirname(__DIR__, 2) . DIRECTORY_SEPARATOR . 'tests' . DIRECTORY_SEPARATOR . 'Foo.php',
$config->getPotentialComposerFilePathForClassLike("Psalm\\Tests\\Foo")
);
}
}