refactor(di): enhance InitializerDependencyAnalyzer with fallback namespace resolution and improved return type handling

- Add fallback logic to resolve classes in the same namespace from file contents.
- Simplify `getInitializerInvokeReturnType` by reducing redundancy in return type validation.
- Extend support for detecting and resolving full class names from method return statements.
- Introduce named parameter pattern matching for return type extraction.
This commit is contained in:
2025-11-03 22:08:49 +01:00
parent d0c36b9245
commit 703d9b04fe
4 changed files with 112 additions and 86 deletions

View File

@@ -224,6 +224,16 @@ final readonly class InitializerDependencyAnalyzer
}
}
// Fallback: Prüfe ob Klasse im gleichen Namespace ist
// Extrahiere Namespace aus der Datei
if (preg_match('/^namespace\s+([^;]+);/m', $fileContent, $namespaceMatch)) {
$namespace = trim($namespaceMatch[1]);
$fullClassName = $namespace . '\\' . $shortName;
if (class_exists($fullClassName)) {
return $fullClassName;
}
}
return null;
} catch (\Throwable) {
return null;
@@ -560,12 +570,8 @@ final readonly class InitializerDependencyAnalyzer
$initializerClass = $this->findInitializerForInterface($interface);
if ($initializerClass !== null && class_exists($initializerClass)) {
$invokeReturnType = $this->getInitializerInvokeReturnType($initializerClass);
if ($invokeReturnType !== null) {
// getInitializerInvokeReturnType() extrahiert bereits die tatsächliche Klasse
// aus dem Code (z.B. "return new Engine(...)"), also können wir sie direkt verwenden
if (class_exists($invokeReturnType)) {
return $invokeReturnType;
}
if ($invokeReturnType !== null && class_exists($invokeReturnType)) {
return $invokeReturnType;
}
}
}
@@ -788,6 +794,7 @@ final readonly class InitializerDependencyAnalyzer
$methodCode = implode("\n", $methodLines);
// Suche nach "return new ClassName(" oder "return new ClassName;"
// Pattern muss auch Named Parameters unterstützen: "return new Engine(...)"
$pattern = '/return\s+new\s+([A-Z][A-Za-z0-9\\\\]+)\s*[\(;]/';
if (preg_match($pattern, $methodCode, $matches)) {
$className = $matches[1];
@@ -800,6 +807,21 @@ final readonly class InitializerDependencyAnalyzer
return $className;
}
}
// Fallback: Suche auch nach Named Parameters Syntax: "return new Engine(...)"
// mit Named Parameters: loader: ..., processor: ...
$pattern2 = '/return\s+new\s+([A-Z][A-Za-z0-9\\\\]+)\s*\(/';
if (preg_match($pattern2, $methodCode, $matches)) {
$className = $matches[1];
// Resolve vollständigen Namespace
$fullClassName = $this->resolveClassNameFromMethod($className, $fileContent, $invokeMethod);
if ($fullClassName !== null && class_exists($fullClassName)) {
return $fullClassName;
} elseif (class_exists($className)) {
return $className;
}
}
return null;
} catch (\Throwable) {

View File

@@ -150,83 +150,3 @@ final readonly class CompiledComponentMetadata
);
}
}
/**
* Component Property Metadata
*/
final readonly class ComponentPropertyMetadata
{
public function __construct(
public string $name,
public string $type,
public bool $isPublic,
public bool $isReadonly,
public mixed $defaultValue = null,
public bool $hasDefaultValue = false
) {
}
public function toArray(): array
{
return [
'name' => $this->name,
'type' => $this->type,
'is_public' => $this->isPublic,
'is_readonly' => $this->isReadonly,
'default_value' => $this->defaultValue,
'has_default_value' => $this->hasDefaultValue,
];
}
public static function fromArray(array $data): self
{
return new self(
name: $data['name'],
type: $data['type'],
isPublic: $data['is_public'],
isReadonly: $data['is_readonly'],
defaultValue: $data['default_value'] ?? null,
hasDefaultValue: $data['has_default_value'] ?? false
);
}
}
/**
* Component Action Metadata
*/
final readonly class ComponentActionMetadata
{
/**
* @param string $name Action name
* @param array<string, string> $parameters Parameter name => type
* @param string|null $returnType Return type
* @param bool $isPublic Is public method
*/
public function __construct(
public string $name,
public array $parameters,
public ?string $returnType = null,
public bool $isPublic = true
) {
}
public function toArray(): array
{
return [
'name' => $this->name,
'parameters' => $this->parameters,
'return_type' => $this->returnType,
'is_public' => $this->isPublic,
];
}
public static function fromArray(array $data): self
{
return new self(
name: $data['name'],
parameters: $data['parameters'],
returnType: $data['return_type'] ?? null,
isPublic: $data['is_public'] ?? true
);
}
}

View File

@@ -0,0 +1,42 @@
<?php
namespace App\Framework\LiveComponents\Performance;
/**
* Component Action Metadata
*/
final readonly class ComponentActionMetadata
{
/**
* @param string $name Action name
* @param array<string, string> $parameters Parameter name => type
* @param string|null $returnType Return type
* @param bool $isPublic Is public method
*/
public function __construct(
public string $name,
public array $parameters,
public ?string $returnType = null,
public bool $isPublic = true
) {}
public function toArray(): array
{
return [
'name' => $this->name,
'parameters' => $this->parameters,
'return_type' => $this->returnType,
'is_public' => $this->isPublic,
];
}
public static function fromArray(array $data): self
{
return new self(
name : $data['name'],
parameters: $data['parameters'],
returnType: $data['return_type'] ?? null,
isPublic : $data['is_public'] ?? true
);
}
}

View File

@@ -0,0 +1,42 @@
<?php
namespace App\Framework\LiveComponents\Performance;
/**
* Component Property Metadata
*/
final readonly class ComponentPropertyMetadata
{
public function __construct(
public string $name,
public string $type,
public bool $isPublic,
public bool $isReadonly,
public mixed $defaultValue = null,
public bool $hasDefaultValue = false
) {}
public function toArray(): array
{
return [
'name' => $this->name,
'type' => $this->type,
'is_public' => $this->isPublic,
'is_readonly' => $this->isReadonly,
'default_value' => $this->defaultValue,
'has_default_value' => $this->hasDefaultValue,
];
}
public static function fromArray(array $data): self
{
return new self(
name : $data['name'],
type : $data['type'],
isPublic : $data['is_public'],
isReadonly : $data['is_readonly'],
defaultValue : $data['default_value'] ?? null,
hasDefaultValue: $data['has_default_value'] ?? false
);
}
}