From 27cd8b23f6aa0d6c1aa81a2e5133b09b7c4a62d4 Mon Sep 17 00:00:00 2001 From: Michal Kruczek Date: Wed, 10 Jan 2024 11:38:07 +0100 Subject: [PATCH 1/4] feat: php-cs-fixer - removing deprecations 1. Detected deprecations in use: - Rule "braces" is deprecated. Use "single_space_around_construct", "control_structure_braces", "control_structure_continuation_position", "declare_parentheses", "no_multiple_statements_per_line", "curly_braces_position", "statement_indentation" and "no_extra_blank_lines" instead. 2. Detected deprecations in use: - Rule "curly_braces_position" is deprecated. Use "braces_position" instead. --- .php-cs-fixer.php | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/.php-cs-fixer.php b/.php-cs-fixer.php index 29ef69ef..33f4467d 100644 --- a/.php-cs-fixer.php +++ b/.php-cs-fixer.php @@ -15,9 +15,14 @@ '@Symfony' => true, '@Symfony:risky' => true, 'array_syntax' => ['syntax' => 'short'], - 'braces' => [ - 'allow_single_line_closure' => true, - ], + 'single_space_around_construct' => true, + 'control_structure_braces' => true, + 'control_structure_continuation_position' => true, + 'declare_parentheses' => true, + 'no_multiple_statements_per_line' => true, + 'braces_position' => true, + 'statement_indentation' => true, + 'no_extra_blank_lines' => true, 'concat_space' => [ 'spacing' => 'one', ], From 67125ae5b081f35f8d35aad0cdf6abfcdf98863a Mon Sep 17 00:00:00 2001 From: Maciej Holyszko <14310995+falkenhawk@users.noreply.github.com> Date: Sun, 28 Apr 2019 21:05:10 +0200 Subject: [PATCH 2/4] Optimize compiled factory definitions - compile final function with injected dependencies - only for closure factories for now (as the first step) --- src/Compiler/Compiler.php | 80 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 78 insertions(+), 2 deletions(-) diff --git a/src/Compiler/Compiler.php b/src/Compiler/Compiler.php index eeea2403..2a40505c 100644 --- a/src/Compiler/Compiler.php +++ b/src/Compiler/Compiler.php @@ -5,6 +5,7 @@ namespace DI\Compiler; use function chmod; +use DI\Container; use DI\Definition\ArrayDefinition; use DI\Definition\DecoratorDefinition; use DI\Definition\Definition; @@ -18,10 +19,12 @@ use DI\Definition\ValueDefinition; use DI\DependencyException; use DI\Proxy\ProxyFactory; -use function dirname; -use function file_put_contents; use InvalidArgumentException; use Laravel\SerializableClosure\Support\ReflectionClosure; +use ReflectionFunction; +use ReflectionFunctionAbstract; +use function dirname; +use function file_put_contents; use function rename; use function sprintf; use function tempnam; @@ -276,6 +279,35 @@ private function compileDefinition(string $entryName, Definition $definition) : )); } + if ($value instanceof \Closure) { + $reflection = new ReflectionFunction($value); + $requestedEntry = new RequestedEntryHolder($entryName); + $parametersByClassName = [ + 'DI\Factory\RequestedEntry' => $requestedEntry, + ]; + // default non-typehinted parameters + $defaultParameters = [new Reference(Container::class), $requestedEntry]; + + $resolvedParameters = $this->resolveFactoryParameters( + $reflection, + $definition->getParameters(), + $parametersByClassName, + $defaultParameters + ); + + $definitionParameters = array_map(function ($value) { + return $this->compileValue($value); + }, $resolvedParameters); + + $code = sprintf( + 'return (%s)(%s);', + $this->compileValue($value), + implode(', ', $definitionParameters) + ); + break; + } + + // todo optimize other (non-closure) factories $definitionParameters = ''; if (!empty($definition->getParameters())) { $definitionParameters = ', ' . $this->compileValue($definition->getParameters()); @@ -307,6 +339,11 @@ public function compileValue(mixed $value) : string throw new InvalidDefinition($errorMessage); } + // one step ahead to skip CompiledContainer->resolveFactory + if ($value instanceof RequestedEntryHolder) { + return 'new DI\Compiler\RequestedEntryHolder(\'' . $value->getName() . '\')'; + } + if ($value instanceof Definition) { // Give it an arbitrary unique name $subEntryName = 'subEntry' . (++$this->subEntryCounter); @@ -364,6 +401,10 @@ private function isCompilable($value) : string|bool if ($value instanceof \Closure) { return true; } + // added for skipping CompiledContainer->resolveFactory - there is a special case for this in compileValue method + if ($value instanceof RequestedEntryHolder) { + return true; + } /** @psalm-suppress UndefinedClass */ if ((\PHP_VERSION_ID >= 80100) && ($value instanceof \UnitEnum)) { return true; @@ -399,4 +440,39 @@ private function compileClosure(\Closure $closure) : string return trim($code, "\t\n\r;"); } + + public function resolveFactoryParameters( + ReflectionFunctionAbstract $reflection, + array $definitionParameters = [], + array $parametersByClassName = [], + array $defaultParameters = [] + ) { + $resolvedParameters = []; + $parameters = $reflection->getParameters(); + + foreach ($parameters as $index => $parameter) { + $name = $parameter->getName(); + if (array_key_exists($name, $definitionParameters)) { + $resolvedParameters[$index] = $definitionParameters[$name]; + continue; + } + + $parameterClass = $parameter->getClass(); + if (!$parameterClass) { + if (array_key_exists($index, $defaultParameters)) { + // take default parameters, when no typehint + $resolvedParameters[$index] = $defaultParameters[$index]; + } + continue; + } + + if (isset($parametersByClassName[$parameterClass->name])) { + $resolvedParameters[$index] = $parametersByClassName[$parameterClass->name]; + } else { + $resolvedParameters[$index] = new Reference($parameterClass->name); + } + } + + return $resolvedParameters; + } } From 9417366b20ab16fddc88d0d146df3cd06844e373 Mon Sep 17 00:00:00 2001 From: Michal Kruczek Date: Fri, 13 Jan 2023 15:34:56 +0100 Subject: [PATCH 3/4] porting Optimize compiled factory definitions for php-di v7 --- src/Compiler/Compiler.php | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/Compiler/Compiler.php b/src/Compiler/Compiler.php index 2a40505c..96462bef 100644 --- a/src/Compiler/Compiler.php +++ b/src/Compiler/Compiler.php @@ -295,9 +295,7 @@ private function compileDefinition(string $entryName, Definition $definition) : $defaultParameters ); - $definitionParameters = array_map(function ($value) { - return $this->compileValue($value); - }, $resolvedParameters); + $definitionParameters = array_map(fn ($value) => $this->compileValue($value), $resolvedParameters); $code = sprintf( 'return (%s)(%s);', @@ -446,7 +444,7 @@ public function resolveFactoryParameters( array $definitionParameters = [], array $parametersByClassName = [], array $defaultParameters = [] - ) { + ) : array { $resolvedParameters = []; $parameters = $reflection->getParameters(); @@ -457,8 +455,8 @@ public function resolveFactoryParameters( continue; } - $parameterClass = $parameter->getClass(); - if (!$parameterClass) { + $parameterType = $parameter->getType(); + if (!$parameterType) { if (array_key_exists($index, $defaultParameters)) { // take default parameters, when no typehint $resolvedParameters[$index] = $defaultParameters[$index]; @@ -466,10 +464,11 @@ public function resolveFactoryParameters( continue; } - if (isset($parametersByClassName[$parameterClass->name])) { - $resolvedParameters[$index] = $parametersByClassName[$parameterClass->name]; + $parameterTypeName = $parameterType->getName(); + if (isset($parametersByClassName[$parameterTypeName])) { + $resolvedParameters[$index] = $parametersByClassName[$parameterTypeName]; } else { - $resolvedParameters[$index] = new Reference($parameterClass->name); + $resolvedParameters[$index] = new Reference($parameterTypeName); } } From b6b60f35435f72d0a8cca585d4a9bdf9f3259053 Mon Sep 17 00:00:00 2001 From: Michal Kruczek Date: Wed, 10 Jan 2024 12:38:34 +0100 Subject: [PATCH 4/4] csfix --- src/Compiler/Compiler.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Compiler/Compiler.php b/src/Compiler/Compiler.php index 96462bef..699389e9 100644 --- a/src/Compiler/Compiler.php +++ b/src/Compiler/Compiler.php @@ -19,12 +19,12 @@ use DI\Definition\ValueDefinition; use DI\DependencyException; use DI\Proxy\ProxyFactory; +use function dirname; +use function file_put_contents; use InvalidArgumentException; use Laravel\SerializableClosure\Support\ReflectionClosure; use ReflectionFunction; use ReflectionFunctionAbstract; -use function dirname; -use function file_put_contents; use function rename; use function sprintf; use function tempnam;