refactor(di): add analysis components for dependency parsing and resolution

- Introduce `CodeParser` to extract dependencies from `container->get()` calls and `return new` statements.
- Add `DependencyPathAnalyzer` for recursive analysis of dependency paths with cycle detection.
- Implement `InitializerFinder` to locate initializers based on naming conventions.
- Include `InterfaceResolver` to determine interface implementations using introspection and initializers.
- Add `NamespaceResolver` for resolving class names from use statements and namespaces.
- Introduce `ReturnTypeAnalyzer` for method and closure return type analysis.
This commit is contained in:
2025-11-03 22:38:06 +01:00
parent 703d9b04fe
commit a93a086ee4
12 changed files with 1120 additions and 838 deletions

View File

@@ -6,6 +6,8 @@ namespace App\Framework\View;
use App\Framework\Http\Session\SessionInterface;
use App\Framework\Meta\MetaData;
use App\Framework\View\Loading\TemplateLoader;
use App\Framework\View\TemplateProcessor;
/**
* Renders LiveComponent templates
@@ -16,7 +18,8 @@ use App\Framework\Meta\MetaData;
final readonly class LiveComponentRenderer
{
public function __construct(
private TemplateRenderer $templateRenderer,
private TemplateLoader $templateLoader,
private TemplateProcessor $templateProcessor,
private SessionInterface $session
) {
}
@@ -46,7 +49,13 @@ final readonly class LiveComponentRenderer
processingMode: ProcessingMode::COMPONENT
);
return $this->templateRenderer->renderPartial($context);
$templateHtml = $this->templateLoader->load(
template: $templatePath,
controllerClass: null,
context: $context
);
return $this->templateProcessor->render($context, $templateHtml, component: true);
}
/**

View File

@@ -0,0 +1,39 @@
<?php
declare(strict_types=1);
namespace App\Framework\View;
use App\Framework\Cache\Cache;
use App\Framework\DI\DefaultContainer;
use App\Framework\DI\Initializer;
use App\Framework\Discovery\Results\DiscoveryRegistry;
use App\Framework\View\Loading\TemplateLoader;
use App\Framework\Core\PathProvider;
final readonly class TemplateLoaderInitializer
{
private const CACHE_ENABLED = false;
public function __construct(
private DefaultContainer $container,
private DiscoveryRegistry $discoveryRegistry,
) {
}
#[Initializer]
public function __invoke(PathProvider $pathProvider, Cache $cache): TemplateLoader
{
$loader = new TemplateLoader(
pathProvider: $pathProvider,
cache: $cache,
discoveryRegistry: $this->discoveryRegistry,
cacheEnabled: self::CACHE_ENABLED
);
$this->container->singleton(TemplateLoader::class, $loader);
return $loader;
}
}

View File

@@ -0,0 +1,72 @@
<?php
declare(strict_types=1);
namespace App\Framework\View;
use App\Framework\Cache\Cache;
use App\Framework\DI\DefaultContainer;
use App\Framework\DI\Initializer;
use App\Framework\View\Dom\Transformer\AssetInjectorTransformer;
use App\Framework\View\Dom\Transformer\CommentStripTransformer;
use App\Framework\View\Dom\Transformer\ForTransformer;
use App\Framework\View\Dom\Transformer\HoneypotTransformer;
use App\Framework\View\Dom\Transformer\IfTransformer;
use App\Framework\View\Dom\Transformer\LayoutTagTransformer;
use App\Framework\View\Dom\Transformer\MetaManipulatorTransformer;
use App\Framework\View\Dom\Transformer\WhitespaceCleanupTransformer;
use App\Framework\View\Dom\Transformer\XComponentTransformer;
use App\Framework\View\Processors\PlaceholderReplacer;
use App\Framework\View\Processors\VoidElementsSelfClosingProcessor;
final readonly class TemplateProcessorInitializer
{
public function __construct(
private DefaultContainer $container,
) {
}
#[Initializer]
public function __invoke(Cache $cache): TemplateProcessor
{
$astTransformers = [
LayoutTagTransformer::class,
XComponentTransformer::class,
ForTransformer::class,
IfTransformer::class,
MetaManipulatorTransformer::class,
AssetInjectorTransformer::class,
HoneypotTransformer::class,
CommentStripTransformer::class,
WhitespaceCleanupTransformer::class,
];
$stringProcessors = [
PlaceholderReplacer::class,
VoidElementsSelfClosingProcessor::class,
];
$chainOptimizer = new ProcessorChainOptimizer($cache);
$compiledTemplateCache = new CompiledTemplateCache($cache);
$performanceTracker = null;
if (getenv('ENABLE_TEMPLATE_PROFILING') === 'true') {
$performanceTracker = new ProcessorPerformanceTracker();
$performanceTracker->enable();
}
$processor = new TemplateProcessor(
astTransformers: $astTransformers,
stringProcessors: $stringProcessors,
container: $this->container,
chainOptimizer: $chainOptimizer,
compiledTemplateCache: $compiledTemplateCache,
performanceTracker: $performanceTracker
);
$this->container->singleton(TemplateProcessor::class, $processor);
return $processor;
}
}

View File

@@ -5,102 +5,30 @@ declare(strict_types=1);
namespace App\Framework\View;
use App\Framework\Cache\Cache;
use App\Framework\Core\PathProvider;
use App\Framework\DI\DefaultContainer;
use App\Framework\DI\Initializer;
use App\Framework\Discovery\Results\DiscoveryRegistry;
use App\Framework\Performance\PerformanceService;
use App\Framework\View\Dom\Transformer\AssetInjectorTransformer;
use App\Framework\View\Dom\Transformer\CommentStripTransformer;
use App\Framework\View\Dom\Transformer\ForTransformer;
use App\Framework\View\Dom\Transformer\HoneypotTransformer;
use App\Framework\View\Dom\Transformer\IfTransformer;
use App\Framework\View\Dom\Transformer\LayoutTagTransformer;
use App\Framework\View\Dom\Transformer\MetaManipulatorTransformer;
use App\Framework\View\Dom\Transformer\WhitespaceCleanupTransformer;
use App\Framework\View\Dom\Transformer\XComponentTransformer;
use App\Framework\View\Loading\TemplateLoader;
use App\Framework\View\Processors\PlaceholderReplacer;
use App\Framework\View\Processors\VoidElementsSelfClosingProcessor;
final readonly class TemplateRendererInitializer
{
public function __construct(
private DefaultContainer $container,
private DiscoveryRegistry $results,
) {}
#[Initializer]
public function __invoke(): TemplateRenderer
{
// AST Transformers (new approach) - Modern template processing
$astTransformers = [
// Core transformers (order matters!)
LayoutTagTransformer::class, // Process <layout> tags FIRST (before other processing)
XComponentTransformer::class, // Process <x-*> components (LiveComponents + HtmlComponents)
ForTransformer::class, // Process foreach loops and <for> elements (BEFORE if/placeholders)
IfTransformer::class, // Conditional rendering (if/condition attributes)
MetaManipulatorTransformer::class, // Set meta tags from context
AssetInjectorTransformer::class, // Inject Vite assets (CSS/JS)
HoneypotTransformer::class, // Add honeypot spam protection to forms
CommentStripTransformer::class, // Remove HTML comments
WhitespaceCleanupTransformer::class, // Remove empty text nodes
];
// TODO: Migrate remaining DOM processors to AST transformers:
// - ComponentProcessor (for <component> tags) - COMPLEX, keep in DOM for now
// - TableProcessor (for table rendering) - OPTIONAL
// - FormProcessor (for form handling) - OPTIONAL
$strings = [
PlaceholderReplacer::class, // PlaceholderReplacer handles simple {{ }} replacements
VoidElementsSelfClosingProcessor::class,
];
/** @var Cache $cache */
$cache = $this->container->get(Cache::class);
// Performance-Optimierungen (optional)
$chainOptimizer = new ProcessorChainOptimizer($cache);
$compiledTemplateCache = new CompiledTemplateCache($cache);
// Performance Tracker nur in Development/Profiling
$performanceTracker = null;
if (getenv('ENABLE_TEMPLATE_PROFILING') === 'true') {
$performanceTracker = new ProcessorPerformanceTracker();
$performanceTracker->enable();
}
$templateProcessor = new TemplateProcessor(
astTransformers: $astTransformers,
stringProcessors: $strings,
container: $this->container,
chainOptimizer: $chainOptimizer,
compiledTemplateCache: $compiledTemplateCache,
performanceTracker: $performanceTracker
);
$this->container->singleton(TemplateProcessor::class, $templateProcessor);
/** @var PathProvider $pathProvider */
$pathProvider = $this->container->get(PathProvider::class);
/** @var Cache $cache */
$cache = $this->container->get(Cache::class);
$templateProcessor = $this->container->get(TemplateProcessor::class);
$loader = $this->container->get(TemplateLoader::class);
/** @var PerformanceService $performanceService */
$performanceService = $this->container->get(PerformanceService::class);
// Define caching state centrally
$cacheEnabled = false; // Keep caching disabled while debugging template processing
/** @var Cache $cache */
$cache = $this->container->get(Cache::class);
$loader = new TemplateLoader(
pathProvider: $pathProvider,
cache: $cache,
discoveryRegistry: $this->results,
cacheEnabled: $cacheEnabled // Pass cache state to loader
);
$this->container->singleton(TemplateLoader::class, $loader);
$cacheEnabled = false;
return new Engine(
loader: $loader,