Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introducing CompileVisitor using the visitor pattern #112

Open
wants to merge 68 commits into
base: 1.x
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
68 commits
Select commit Hold shift + click to select a range
deb2303
Add VisitorInjector class and update test cases
koriym Jan 8, 2024
32bb446
Refactor 'VisitorInjector' class to 'AirInjector'
koriym May 21, 2024
7e292ba
Update compile method and introduce Aspect-Oriented Programming
koriym May 21, 2024
a242a64
Update Compiler and CompileVisitor for specific interface handling
koriym May 21, 2024
3a11da6
Enhance non-scalar instance handling in CompileVisitor class
koriym May 21, 2024
02bf8be
Update Compiler class to compile NullObject
koriym May 21, 2024
54e6488
Refactor ScriptInjector class and update corresponding tests
koriym May 22, 2024
79ebed0
Refactor InjectionPoint to use annotations for qualifiers
koriym May 21, 2024
aa67bc2
Refactor DiCompiler class and deprecate methods
koriym May 21, 2024
fc8b334
Add assertions to ensure injectionPoint is callable
koriym May 21, 2024
7718e89
Reorder aspect weaving and null object compilation
koriym May 21, 2024
90d0066
Add assertions to check if dependencies are callable
koriym May 21, 2024
a694369
Refactor CompileVisitor and InstanceScript classes
koriym May 21, 2024
016de19
Refactor MapModule and InstallBuiltinModule
koriym May 21, 2024
ed121de
Remove unused imports and clean up code
koriym May 21, 2024
69f779a
Refactor test cases and fix minor bugs
koriym May 21, 2024
e58e775
Move deprecated classes to src-deprecated and mark them as deprecated
koriym May 21, 2024
22727de
Remove "nikic/php-parser" from dependencies
koriym May 21, 2024
624bb2e
Replace file_put_contents with FilePutContents class in Scripts.php
koriym May 21, 2024
9e3e4c8
Update test files with minor revisions
koriym May 22, 2024
fe85c44
Update package dependencies in composer.json
koriym May 22, 2024
4a3545d
Update PHP versions in GitHub CI workflow
koriym May 22, 2024
e073a3d
Change `require` to `require_once` in AirInjector
koriym May 22, 2024
3d97eb4
Remove unnecessary Unbound test from DiCompilerTest
koriym May 22, 2024
54e0771
Add PHP 8.3 requirement to test methods
koriym May 22, 2024
93f5a13
Remove unused import statements
koriym May 22, 2024
b8d758d
Fix CS
koriym May 22, 2024
f4b1c29
Swap visitDependency and visitAspectBind methods
koriym May 22, 2024
1da3649
fixup! Update PHP versions in GitHub CI workflow
koriym May 22, 2024
4ef4158
Soothe psalm
koriym May 22, 2024
b0b9325
Fix CS
koriym May 22, 2024
0567a41
Remove unnecessary assert in Compiler.php
koriym May 22, 2024
b512991
Soothe psalm
koriym May 22, 2024
80f835f
Remove DependencyCompilerTest.php and NormalizerTest.php files
koriym May 22, 2024
c7d5635
Implement file locking mechanism in Compiler
koriym May 23, 2024
a6e7263
Add suppression for PHPMD warning in compile method
koriym May 23, 2024
ffc351f
Update phpmd command in composer.json
koriym May 23, 2024
450a924
Soothe require checker
koriym May 23, 2024
f1858e9
Refactor Compiler.php and update tests
koriym May 23, 2024
e210633
Remove unused dependencies from composer.json
koriym May 23, 2024
7d3a6ba
Add return type declarations for methods in CompileVisitor
koriym May 23, 2024
3c15c5a
Remove deprecated classes in src-deprecated directory
koriym May 23, 2024
72923c3
Add require-checker to composer scripts
koriym May 23, 2024
ec1c0da
Remove unused function and update formatting
koriym May 23, 2024
442736c
Update composer-require-checker and scripts
koriym May 23, 2024
4228f4d
Remove Script Injector section from README
koriym May 23, 2024
138de87
Simplify README with updated instruction for injections
koriym May 23, 2024
0ba5405
Replace RuntimeException with assert check in CompileVisitor
koriym May 23, 2024
ed57981
Apply MapModule for multiple bindings
koriym May 23, 2024
b877973
Refactor comment block in AbstractInjectorContext class
koriym May 23, 2024
9747f42
Update PHPDoc in Compiler.php
koriym May 23, 2024
aa6805a
Remove InstallBuiltinModule and refactor Compiler
koriym May 23, 2024
8cafc48
[ci skip] Add CompileInjector section to README.md
koriym May 23, 2024
c21a592
Remove 'MapModule.php' and 'ParamReaderModule.php' files
koriym May 23, 2024
aac3013
Remove @deprecated from CachedInjectorFactory
koriym May 24, 2024
774bfa4
Add exception for unbound injection point
koriym May 24, 2024
a7efd80
Set default value for $ip parameter in AirInjector
koriym May 24, 2024
8d90cc2
Refactor visitInstance method in CompileVisitor
koriym May 24, 2024
06497ea
Code coverage 100%
koriym May 24, 2024
fda614d
Remove CompileNullObject class
koriym May 24, 2024
83c2382
Update ray/di package version in composer.json
koriym May 27, 2024
5ee2026
Remove unused NullCache import from CachedFactoryTest
koriym May 27, 2024
009ca32
Update PHPStan version to 1.11.2
koriym May 27, 2024
5f75149
Change Ray\Di\NullCache to Ray\Compiler\NullCache
koriym May 27, 2024
8b1a91b
Add doctrine/cache requirement ^1.0
koriym May 27, 2024
e1d156a
Update ray/di version in composer.json
koriym May 27, 2024
2888e00
fixup! Update ray/di version in composer.json
koriym May 27, 2024
137515f
Update dependencies in composer.lock
koriym May 27, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ build
/.phpcs-cache
.phpunit.result.cache
/coverage.xml
/tests/Fake/tmp
52 changes: 6 additions & 46 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,60 +9,20 @@

Ray.Compiler compiles Ray.Di bindings into PHP code, providing a performance boost that makes Dependency Injection couldn't be any faster.

## Script Injector
## Compile Injector

`ScriptInjector` has the same interface as Ray.Di Injector; whereas Ray.Di Injector resolves dependencies based on memory bindings, ScriptInjector executes pre-compiled PHP code and is faster.
`CompileInjector` is designed to enhance performance by utilizing `Compiler` to compile modules and initializing `AirInjector` for managing dependencies. This approach ensures efficient dependency management and faster execution.

Ray.Di injector
```php
$injector = new Injector(new CarModule); // Ray.Di injector
```

Ray.Compiler injector
```php
$injector = new ScriptInjector($tmpDir, fn => new CarModule);
$injector = new CompileInjector($tmpDir, fn => new CarModule);
$car = $injector->getInstance(CarInterface::class);
koriym marked this conversation as resolved.
Show resolved Hide resolved
```

## Precompile

You will want to compile all dependencies into code before deploying the production. The `DiCompiler` will compile all bindings into PHP code.
You will want to compile all dependencies into code before deploying the production.

```php
$compiler = new DiCompiler(new CarModule, $tmpDir);
$compiler = new Compiler($tmpDir, new CarModule);
$compiler->compile();
```

## Object graph visualization

Object graph can be visualized with `dumpGraph()`.
Graph HTML files will be output at `graph` folder under `$tmpDir`.

```php
$compiler = new DiCompiler(new Module, $tmpDir);
$compiler->compile();
$compiler->dumpGraph();
```

```
open tmp/graph/Ray_Compiler_FakeCarInterface-.html
```

## CompileInjector

The `CompileInjector` gives you the best performance in both development (x2) and production (x10) by switching two injector.

Get the injector by specifying the binding and cache, depending on the execution context of the application.

```php
$injector = new CompileInjector($tmpDir, $injectorContext);
```

`$injectorContext` example:

* [dev](docs/exmaple/DevInjectorContext.php)
* [prod](docs/exmaple/ProdInjectorContext.php)

The `__invoke()` method prepares the modules needed in that context.
The `getCache()` method specifies the cache of the injector itself.

Install `DiCompileModule` in the context for production. The injector is more optimized and dependency errors are reported at compile-time instead of run-time.
17 changes: 3 additions & 14 deletions composer-require-checker.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,8 @@
"static", "self", "parent",
"array", "string", "int", "float", "bool", "iterable", "callable", "void", "object",
"Attribute", "ReflectionAttribute",
"Ray\\Di\\AbstractModule", "Ray\\Di\\Annotation\\ScriptDir",
"Ray\\Di\\Argument", "Ray\\Di\\Arguments",
"Ray\\Di\\AssistedModule", "Ray\\Di\\Bind",
"Ray\\Di\\Container", "Ray\\Di\\Dependency",
"Ray\\Di\\DependencyInterface","Ray\\Di\\DependencyProvider",
"Ray\\Di\\Di\\Qualifier", "Ray\\Di\\Exception\\NotFound",
"Ray\\Di\\Exception\\Unbound", "Ray\\Di\\InjectionPointInterface",
"Ray\\Di\\Injector", "Ray\\Di\\InjectorInterface", "Ray\\Di\\Instance",
"Ray\\Di\\MultiBinding\\Map", "Ray\\Di\\MultiBinding\\MapProvider",
"Ray\\Di\\Name", "Ray\\Di\\NullCache",
"Ray\\Di\\NullModule", "Ray\\Di\\NullObjectDependency",
"Ray\\Di\\ProviderInterface", "Ray\\Di\\ProviderSetModule",
"Ray\\Di\\SetContextInterface"

"Doctrine\\Common\\Annotations\\Reader",
"Doctrine\\Common\\Cache\\CacheProvider",
"Koriym\\Printo\\Printo"
]
}
22 changes: 10 additions & 12 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -12,20 +12,17 @@
],
"require": {
"php": "^7.2 || ^8.0",
"doctrine/annotations": "^1.12 || ^2.0",
"doctrine/cache": "^1.10 || ^2.1",
"koriym/attributes": "^1.0",
"koriym/null-object": "^1.0",
"koriym/param-reader": "^1.0",
"koriym/printo": "^1.0",
"nikic/php-parser": "^4.5 || ^5.0",
"ray/aop": "^2.14"
"ray/aop": "^2.15",
"ray/di": "^2.17.1"
},
"require-dev": {
"ext-pdo": "*",
"ray/di": "^2.16",
"phpunit/phpunit": "^8.5.24 || ^9.5",
"bamarni/composer-bin-plugin": "^1.4"
"bamarni/composer-bin-plugin": "^1.4",
"doctrine/cache": "^1.0 || ^2.2",
"phpunit/phpunit": "^8.5.24 || ^9.5"
},
"config": {
"sort-packages": true,
Expand All @@ -35,7 +32,7 @@
},
"autoload": {
"psr-4": {
"Ray\\Compiler\\": ["src", "src-deprecated"]
"Ray\\Compiler\\": ["src", "src-cached-injector-factory", "src-deprecated"]
}
},
"autoload-dev": {
Expand All @@ -53,10 +50,11 @@
"cs": ["phpcs --standard=./phpcs.xml src tests"],
"cs-fix": ["phpcbf src tests"],
"clean": ["phpstan clear-result-cache", "psalm --clear-cache", "rm -rf tests/tmp/*.php"],
"sa": ["psalm -c psalm.compiler.xml --show-info=true", "phpstan analyse -c phpstan.neon --no-progress"],
"sa": ["psalm -c psalm.compiler.xml --show-info=false", "phpstan analyse -c phpstan.neon --no-progress"],
"metrics": ["@test", "phpmetrics --report-html=build/metrics --exclude=Exception --log-junit=build/junit.xml --junit=build/junit.xml src"],
"phpmd": ["phpmd src/di text ./phpmd.xml"],
"build": ["@cs", "@sa", "@pcov", "@metrics"]
"phpmd": ["phpmd src text ./phpmd.xml"],
"build": ["@cs", "@sa", "@pcov", "@metrics"],
"req-check": ["./vendor/bin/composer-require-checker"]
},
"extra": {
"bamarni-bin": {
Expand Down
3 changes: 0 additions & 3 deletions docs/exmaple/DevInjectorContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,8 @@

declare(strict_types=1);

use Doctrine\Common\Cache\ApcuCache;
use Doctrine\Common\Cache\CacheProvider;
use Ray\Compiler\AbstractInjectorContext;
use Ray\Compiler\DiCompileModule;
use Ray\Compiler\FakeCarModule;
use Ray\Di\AbstractModule;
use Ray\Di\NullCache;

Expand Down
1 change: 0 additions & 1 deletion docs/exmaple/ProdInjectorContext.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
use Doctrine\Common\Cache\CacheProvider;
use Ray\Compiler\AbstractInjectorContext;
use Ray\Compiler\DiCompileModule;
use Ray\Compiler\FakeCarModule;
use Ray\Di\AbstractModule;

final class ProdInjectorContext extends AbstractInjectorContext
Expand Down
2 changes: 2 additions & 0 deletions phpcs.xml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
<!-- Base -->
<exclude name="Generic.Formatting.MultipleStatementAlignment.NotSame"/>
<exclude name="Squiz.Strings.DoubleQuoteUsage.ContainsVar"/>
<exclude name="Squiz.Functions.MultiLineFunctionDeclaration.ContentAfterBrace"/>
<exclude name="SlevomatCodingStandard.Classes.SuperfluousAbstractClassNaming.SuperfluousPrefix"/>
<exclude name="SlevomatCodingStandard.Classes.SuperfluousExceptionNaming.SuperfluousSuffix"/>
<exclude name="SlevomatCodingStandard.Classes.SuperfluousInterfaceNaming.SuperfluousSuffix"/>
Expand All @@ -39,6 +40,7 @@
<exclude name="Squiz.PHP.GlobalKeyword.NotAllowed"/>
<exclude name="SlevomatCodingStandard.PHP.RequireExplicitAssertion.RequiredExplicitAssertion"/>
<exclude name="SlevomatCodingStandard.Commenting.InlineDocCommentDeclaration.InvalidFormat"/>
<exclude name="SlevomatCodingStandard.Functions.UnusedInheritedVariablePassedToClosure.UnusedInheritedVariable" />
<!-- PHP8 attribute -->
<exclude name="PSR12.Files.FileHeader.IncorrectOrder"/>
<!-- /Base -->
Expand Down
1 change: 0 additions & 1 deletion phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -6,5 +6,4 @@ parameters:
excludePaths:
- tests/tmp/*
- tests/Fake/*
checkGenericClassInNonGenericObjectType: false

Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,19 @@
use Doctrine\Common\Cache\CacheProvider;
use Ray\Di\AbstractModule;
use Ray\Di\InjectorInterface;
use Ray\Di\NullCache;

use function assert;
use function class_exists;
use function serialize;
use function unserialize;

final class CachedInjectorFactory
{
public function __construct()
{
if (! class_exists(CacheProvider::class)) {
throw new \RuntimeException('CachedInjectorFactory requires doctrine/cache');
}
}
/** @var array<string, string> */
private static $injectors = [];

Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,10 @@
use Ray\Di\Exception\Unbound;
use Ray\Di\Injector as RayInjector;
use Ray\Di\InjectorInterface;

use function is_dir;
use function mkdir;

/**
* @psalm-immutable
*/
/** @psalm-immutable */
final class InjectorFactory
{
/**
Expand Down
58 changes: 58 additions & 0 deletions src-cached-injector-factory/NullCache.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?php

declare(strict_types=1);

namespace Ray\Compiler;

use Doctrine\Common\Cache\CacheProvider;

final class NullCache extends CacheProvider
{
/**
* {@inheritDoc}
*/
protected function doFetch($id)
{
return false;
}

/**
* {@inheritDoc}
*/
protected function doContains($id)
{
return false;
}

/**
* {@inheritDoc}
*/
protected function doSave($id, $data, $lifeTime = 0)
{
return true;
}

/**
* {@inheritDoc}
*/
protected function doDelete($id)
{
return true;
}

/**
* {@inheritDoc}
*/
protected function doFlush()
{
return true;
}

/**
* {@inheritDoc}
*/
protected function doGetStats()
{
return [];
}
}
67 changes: 67 additions & 0 deletions src-deprecated/DiCompiler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?php

declare(strict_types=1);

namespace Ray\Compiler;

use Ray\Di\AbstractModule;
use Ray\Di\InjectorInterface;
use Ray\Di\Name;

/** @deprecated */
final class DiCompiler implements InjectorInterface
{
/** @var AirInjector */
private $injector;

/** @var AbstractModule */
private $module;

/** @var string */
private $scriptDir;

public function __construct(AbstractModule $module, string $scriptDir)
{
$this->module = $module;
$this->scriptDir = $scriptDir;
$this->injector = new AirInjector($scriptDir);
$injectorModule = new class ($this->injector) extends AbstractModule {
private $injector;

public function __construct(InjectorInterface $injector)
{
$this->injector = $injector;
}

protected function configure()
{
$this->bind(InjectorInterface::class)->toInstance($this->injector);
}
};
$module->install($injectorModule);
(new Compiler())->compile($module, $scriptDir);
}

/**
* {@inheritdoc}
*/
public function getInstance($interface, $name = Name::ANY)
{
return $this->injector->getInstance($interface, $name);
}

/** @deprecated */
public function compile(): void
{
}

/** @deprecated */
public function savePointcuts(): void
{
}

/** @deprecated */
public function dumpGraph(): void
{
}
koriym marked this conversation as resolved.
Show resolved Hide resolved
}
3 changes: 1 addition & 2 deletions src/GraphDumper.php → src-deprecated/GraphDumper.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@
use Koriym\Printo\Printo;
use Ray\Di\Container;
use Ray\Di\Name;

use function assert;
use function class_exists;
use function explode;
Expand All @@ -16,9 +15,9 @@
use function interface_exists;
use function mkdir;
use function str_replace;

use const LOCK_EX;

/** @deprecated */
final class GraphDumper
{
/** @var Container */
Expand Down
2 changes: 1 addition & 1 deletion src/IpQualifier.php → src-deprecated/IpQualifier.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@
namespace Ray\Compiler;

use ReflectionParameter;

use function serialize;

/** @deprecated */
final class IpQualifier
{
/** @var ReflectionParameter */
Expand Down
Loading
Loading