mirror of
https://github.com/danog/psalm-plugin-symfony.git
synced 2024-11-26 11:55:00 +01:00
check services from cached container service file (#7)
* load with $config ContaimerServicefile, parse service<=>class * fix psalm messages, optimize code * debug plugin-config take only for symfony-psalm-plugin, some optimizations cache servicemap * Housekeeping fix psalm * Update ClassHandler.php Co-authored-by: Farhad Safarov <farhad.safarov@gmail.com>
This commit is contained in:
parent
4e45a9d033
commit
5e53558c97
@ -22,7 +22,12 @@ use Symfony\Component\DependencyInjection\ContainerInterface;
|
||||
class ClassHandler implements AfterClassLikeAnalysisInterface, AfterMethodCallAnalysisInterface
|
||||
{
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* @psalm-var array<string, string>
|
||||
*/
|
||||
private static $classServiceMap = [];
|
||||
|
||||
/**
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function afterStatementAnalysis(Node\Stmt\ClassLike $stmt, ClassLikeStorage $classlike_storage, StatementsSource $statements_source, Codebase $codebase, array &$file_replacements = [])
|
||||
{
|
||||
@ -43,7 +48,7 @@ class ClassHandler implements AfterClassLikeAnalysisInterface, AfterMethodCallAn
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* {@inheritdoc}
|
||||
*/
|
||||
public static function afterMethodCallAnalysis(
|
||||
Expr $expr,
|
||||
@ -63,6 +68,15 @@ class ClassHandler implements AfterClassLikeAnalysisInterface, AfterMethodCallAn
|
||||
$className = (string) $expr->args[0]->value->class->getAttribute('resolvedName');
|
||||
$return_type_candidate = new Union([new TNamedObject($className)]);
|
||||
}
|
||||
if (!count(self::$classServiceMap)) {
|
||||
self::$classServiceMap = self::loadServiceFile($codebase);
|
||||
}
|
||||
if ($return_type_candidate && count(self::$classServiceMap) && $expr->args[0]->value instanceof Node\Scalar\String_) {
|
||||
$serviceName = (string) $expr->args[0]->value->value;
|
||||
if (isset(self::$classServiceMap[$serviceName])) {
|
||||
$return_type_candidate = new Union([new TNamedObject((string) self::$classServiceMap[$serviceName])]);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'Symfony\Component\HttpFoundation\Request::getcontent':
|
||||
if ($return_type_candidate) {
|
||||
@ -85,4 +99,45 @@ class ClassHandler implements AfterClassLikeAnalysisInterface, AfterMethodCallAn
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo don't check every time if containerXml config is not set.
|
||||
* @psalm-return array<string, string>
|
||||
*/
|
||||
private static function loadServiceFile(Codebase $codebase): array
|
||||
{
|
||||
$classServiceMap = [];
|
||||
if (count($codebase->config->getPluginClasses())) {
|
||||
foreach ($codebase->config->getPluginClasses() as $pluginClass) {
|
||||
if ($pluginClass['class'] === str_replace('Handler', 'Plugin', __NAMESPACE__)) {
|
||||
$simpleXmlConfig = $pluginClass['config'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($simpleXmlConfig) && $simpleXmlConfig instanceof \SimpleXMLElement) {
|
||||
$serviceFilePath = (string) $simpleXmlConfig->containerXml;
|
||||
if (!file_exists($serviceFilePath)) {
|
||||
return [];
|
||||
}
|
||||
$xml = simplexml_load_file($serviceFilePath);
|
||||
if (!$xml->services instanceof \SimpleXMLElement) {
|
||||
return $classServiceMap;
|
||||
}
|
||||
$services = $xml->services;
|
||||
/** @psalm-suppress MixedAssignment */
|
||||
if (count($services)) {
|
||||
foreach ($services->service as $serviceObj) {
|
||||
if (isset($serviceObj) && $serviceObj instanceof \SimpleXMLElement) {
|
||||
$serviceAttributes = $serviceObj->attributes();
|
||||
if ($serviceAttributes && isset($serviceAttributes['id']) && isset($serviceAttributes['class'])) {
|
||||
$classServiceMap[(string) $serviceAttributes['id']] = (string) $serviceAttributes['class'];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $classServiceMap;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user