From 8a060aa06da32bb5b8568472c40b21f52d86a750 Mon Sep 17 00:00:00 2001 From: ytake Date: Sun, 7 Oct 2018 23:30:17 +0900 Subject: [PATCH 1/7] patch for hhvm3.28 --- composer.json | 15 +++---- phpunit.xml | 23 ----------- src/FactoryContainer.php | 21 +++------- src/MethodCaller.php | 2 + tests/ContainerTest.php | 85 +++++++++++++++++--------------------- tests/FactoryTest.php | 22 +++++----- tests/MethodCallerTest.php | 14 ++++--- 7 files changed, 70 insertions(+), 112 deletions(-) delete mode 100644 phpunit.xml diff --git a/composer.json b/composer.json index 2cd6337..6f953d9 100644 --- a/composer.json +++ b/composer.json @@ -10,15 +10,15 @@ "container" ], "require": { - "hhvm": ">=3.24", + "hhvm": ">=3.28", "hhvm/hhvm-autoload": "^1.6", + "hhvm/hsl": "^3.28", "ytake/psr-container-hhi": "^1.0" }, "require-dev": { - "phpunit/phpunit": "^5.0", - "91carriage/phpunit-hhi": "^5.7.1", - "hhvm/hsl": "^1.0.0|^3.26.0", - "hhvm/hhast": "^1.0.1|>=3.26.0" + "hhvm/hacktest": "^1.0", + "facebook/fbexpect": "^2.1.3", + "hhvm/hhast": ">=3.28.0" }, "autoload": { "psr-4": { @@ -28,9 +28,6 @@ "autoload-dev": { "classmap": [ "tests/" - ] - }, - "scripts": { - "test": "./vendor/bin/phpunit" + ] } } diff --git a/phpunit.xml b/phpunit.xml deleted file mode 100644 index 83cf128..0000000 --- a/phpunit.xml +++ /dev/null @@ -1,23 +0,0 @@ - - - - - ./tests/ - - - - - ./src - - - diff --git a/src/FactoryContainer.php b/src/FactoryContainer.php index 2a135fe..f5245e3 100644 --- a/src/FactoryContainer.php +++ b/src/FactoryContainer.php @@ -53,9 +53,7 @@ public function set( TCallable $callback, Scope $scope = Scope::PROTOTYPE, ): void { - if (!$this->locked) { - $this->mapper->add(Pair {$id, Map{$scope => $callback}}); - } + $this->mapper->add(Pair {$id, Map{$scope => $callback}}); } public function parameters( @@ -63,9 +61,7 @@ public function parameters( string $name, TCallable $callback, ): void { - if (!$this->locked) { - $this->parameters[$id][$name] = $callback; - } + $this->parameters[$id][$name] = $callback; } public function get($id): mixed { @@ -104,8 +100,7 @@ public function get($id): mixed { <<__Memoize>> protected function shared(string $id): mixed { - $shared = $this->mapper->at($id); - $call = $shared->firstValue(); + $call = $this->mapper->at($id)->firstValue(); if(!is_null($call)) { return call_user_func($call, $this); } @@ -122,26 +117,20 @@ public function bindings( public function flush(): void { $this->mapper->clear(); - $this->locked = false; } public function remove(string $id): void { - if (!$this->locked) { - $this->mapper->removeKey($id); - } + $this->mapper->removeKey($id); } public function registerModule(TServiceModule $moduleClassName): void { - if (!$this->locked) { - $this->modules->add($moduleClassName); - } + $this->modules->add($moduleClassName); } public function lockModule(): void { foreach ($this->modules->getIterator() as $iterator) { (new $iterator())->provide($this); } - $this->locked = true; } protected function resolveConstructorParameters( diff --git a/src/MethodCaller.php b/src/MethodCaller.php index ec498f7..040e2d1 100644 --- a/src/MethodCaller.php +++ b/src/MethodCaller.php @@ -18,6 +18,8 @@ namespace Ytake\HHContainer; +use function is_object; + class MethodCaller implements MethodCallIntreface { public function __construct( diff --git a/tests/ContainerTest.php b/tests/ContainerTest.php index c716ec7..9b9fca6 100644 --- a/tests/ContainerTest.php +++ b/tests/ContainerTest.php @@ -1,108 +1,99 @@ set( 'testing', $container ==> 'testing' ); - $this->assertSame('testing', $container->get('testing')); - + expect($container->get('testing')); $container->set('testing123', $container ==> 1); - $this->assertSame(1, $container->get('testing123')); + expect($container->get('testing123'))->toBeSame(1); $container->set('testing:testing', $container ==> true); - $this->assertSame(true, $container->get('testing:testing')); + expect($container->get('testing:testing'))->toBeTrue(); } - public function testShouldReturnSingletonObject(): void - { + public function testShouldReturnSingletonObject(): void { $container = new \Ytake\HHContainer\FactoryContainer(); $container->set( 'testing:testing', $container ==> new \stdClass(), \Ytake\HHContainer\Scope::SINGLETON ); - $this->assertInstanceOf(\stdClass::class, $container->get('testing:testing')); - $this->assertSame($container->get('testing:testing'), $container->get('testing:testing')); + expect($container->get('testing:testing'))->toBeInstanceOf(\stdClass::class); + expect($container->get('testing:testing'))->toBeSame($container->get('testing:testing')); } - public function testShouldReturnPrototypeObject(): void - { + public function testShouldReturnPrototypeObject(): void { $container = new \Ytake\HHContainer\FactoryContainer(); $container->set('testing:testing', $container ==> new \stdClass(), \Ytake\HHContainer\Scope::PROTOTYPE); - $this->assertInstanceOf(\stdClass::class, $container->get('testing:testing')); - $this->assertNotSame($container->get('testing:testing'), $container->get('testing:testing')); + expect($container->get('testing:testing'))->toBeInstanceOf(\stdClass::class); + expect($container->get('testing:testing'))->toBePHPEqual($container->get('testing:testing')); } - public function testShouldReturunResolveInstance(): void - { - $container = new \Ytake\HHContainer\FactoryContainer(); - $container->set('testing', $container ==> 1); - $container->set( - 'testing:testing', - $container ==> $container->get('testing'), - \Ytake\HHContainer\Scope::PROTOTYPE - ); - $this->assertSame(1, $container->get('testing:testing')); + public function testShouldReturunResolveInstance(): void { + $container = new \Ytake\HHContainer\FactoryContainer(); + $container->set('testing', $container ==> 1); + $container->set( + 'testing:testing', + $container ==> $container->get('testing'), + \Ytake\HHContainer\Scope::PROTOTYPE + ); + expect($container->get('testing:testing'))->toBeSame(1); } - public function testShouldThrowException() :void - { - $this->expectException(\Ytake\HHContainer\NotFoundException::class); + <> + public function testShouldThrowException() :void { $container = new \Ytake\HHContainer\FactoryContainer(); $container->get('testing'); } - /** - * @expectedException \Ytake\HHContainer\NotFoundException - */ - public function testShouldReturnProvideInstance(): void - { + <> + public function testShouldReturnProvideInstance(): void { $container = new \Ytake\HHContainer\FactoryContainer(); $container->registerModule(StubModule::class); $container->lockModule(); - $this->assertInstanceOf(\stdClass::class, $container->get('provide:sample')); + expect($container->get('provide:sample'))->toBeInstanceOf(\stdClass::class); $container->set('message.class', $container ==> new MockMessageClass('testing')); - $container->get('message.class'); + expect($container->get('message.class'))->toBeInstanceOf(MockMessageClass::class); } - public function testShouldResolveInstance(): void - { + public function testShouldResolveInstance(): void { $container = new \Ytake\HHContainer\FactoryContainer(); - $this->assertInstanceOf(\stdClass::class, $container->get(\stdClass::class)); + expect($container->get(\stdClass::class))->toBeInstanceOf(\stdClass::class); $container->parameters(ResolvedObject::class, 'object', $container ==> new \stdClass()); $container->parameters(ResolvedObject::class, 'integer', $container ==> 100); $instance = $container->get(ResolvedObject::class); - $this->assertInstanceOf(ResolvedObject::class, $instance); + expect($instance)->toBeInstanceOf(ResolvedObject::class); } - public function testShouldResolveConstructorPromotionInstance(): void - { + public function testShouldResolveConstructorPromotionInstance(): void { $container = new \Ytake\HHContainer\FactoryContainer(); $container->parameters(ConstructorPromotionClass::class, 'object', $container ==> new \stdClass()); $container->parameters(ConstructorPromotionClass::class, 'integer', $container ==> 100); $instance = $container->get(ConstructorPromotionClass::class); - $this->assertInstanceOf(ConstructorPromotionClass::class, $instance); + expect($instance)->toBeInstanceOf(ConstructorPromotionClass::class); if ($instance instanceof ConstructorPromotionClass) { - $this->assertSame(100, $instance->getInteger()); + expect($instance->getInteger())->toBeSame(100); } } - public function testShouldResolveDependencyInjectionWithLocation(): void - { + public function testShouldResolveDependencyInjectionWithLocation(): void { $container = new FactoryContainer(); $container->set('message.class', $container ==> new MockMessageClass('testing')); $container->parameters(MessageClient::class, 'message', $container ==> $container->get('message.class')); $instance = $container->get(MessageClient::class); if ($instance instanceof MessageClient) { - $this->assertSame('testing', $instance->message()->message()); + expect($instance->message()->message())->toBeSame('testing'); } } } diff --git a/tests/FactoryTest.php b/tests/FactoryTest.php index 1816ded..1e6f8ec 100644 --- a/tests/FactoryTest.php +++ b/tests/FactoryTest.php @@ -1,30 +1,30 @@ registerFactory(new StringFactory()); - $this->assertSame('testing', $factory->create('testing')); + expect($factory->create('testing'))->toBeSame('testing'); } - public function testShouldReturnStdClass(): void - { + public function testShouldReturnStdClass(): void { $factory = new ServiceFactory(new FactoryContainer()); $factory->registerFactory(new MockClassFactory()); $i = $factory->create(MockClass::class); - $this->assertInstanceOf(MockClass::class, $i); + expect($i)->toBeInstanceOf(MockClass::class); if($i instanceof MockClass) { - $this->assertSame(1, $i->getT()); + expect($i->getT())->toBeSame(1); } - $this->assertInstanceOf(MockClass::class, $factory->create(MockClass::class)); - $this->assertSame($factory->create(MockClass::class), $factory->create(MockClass::class)); + expect($factory->create(MockClass::class))->toBeInstanceOf(MockClass::class); + expect($factory->create(MockClass::class))->toBeSame($factory->create(MockClass::class)); } } diff --git a/tests/MethodCallerTest.php b/tests/MethodCallerTest.php index 25d6cf6..02a2e82 100644 --- a/tests/MethodCallerTest.php +++ b/tests/MethodCallerTest.php @@ -1,12 +1,14 @@ set( TestingInvokable::class, @@ -18,8 +20,8 @@ public function testShouldReturnExpectValues(): void $container ==> $container->callable(new MethodCaller(new TestingInvokableTwo(), 'execute')) ); - $this->assertSame(1, $container->get(TestingInvokable::class)); - $this->assertSame('testing', $container->get(TestingInvokableTwo::class)); + expect($container->get(TestingInvokable::class))->toBeSame(1); + expect($container->get(TestingInvokableTwo::class))->toBeSame('testing'); } } From 2eb50d155c003d454b285dd79f589798d334f6a4 Mon Sep 17 00:00:00 2001 From: ytake Date: Mon, 8 Oct 2018 01:35:51 +0900 Subject: [PATCH 2/7] removed parameter inject method --- .hhconfig | 3 + README.md | 33 +++++------ src/ContainerException.php | 2 +- src/FactoryContainer.php | 108 ++++++++++-------------------------- src/FactoryInterface.php | 8 ++- src/MethodCallIntreface.php | 3 +- src/MethodCaller.php | 1 + src/NotFoundException.php | 2 +- src/Scope.php | 8 +++ src/ServiceFactory.php | 28 ++++++---- src/ServiceModule.php | 6 +- tests/ContainerTest.php | 55 +++++++++++------- tests/FactoryTest.php | 15 +++-- 13 files changed, 132 insertions(+), 140 deletions(-) create mode 100644 src/Scope.php diff --git a/.hhconfig b/.hhconfig index 0c2153c..7bb4605 100644 --- a/.hhconfig +++ b/.hhconfig @@ -1 +1,4 @@ assume_php=false +safe_array = true +safe_vector_array = true +unsafe_rx = false diff --git a/README.md b/README.md index 4c6cae1..4ea412e 100644 --- a/README.md +++ b/README.md @@ -45,30 +45,24 @@ $container->set('scope:prototype', $container ==> new \stdClass(), \Ytake\HHCont ## Dependency Injection ### set parameters - -```hack -$container->parameters( - 'string className', - 'parameter name', - $container ==> 'parameter value' -); -``` - sample class ```hack final class MessageClass { - public function __construct(protected string $message) { - } + public function __construct( + protected string $message + ) {} + public function message(): string { return $this->message; } } final class MessageClient { - public function __construct(protected MessageClass $message) { + public function __construct( + protected MessageClass $message + ) {} - } public function message(): MessageClass { return $this->message; } @@ -80,7 +74,11 @@ final class MessageClient { ```hack $container = new \Ytake\HHContainer\FactoryContainer(); $container->set('message.class', $container ==> new MessageClass('testing')); -$container->parameters(MessageClient::class, 'message', $container ==> $container->get('message.class')); +$container->set(MessageClient::class, $container ==> { + $instance = $container->get('message.class'); + invariant($instance instanceof MockMessageClass, 'error'); + new MessageClient($instance); +}); $instance = $container->get(MessageClient::class); ``` @@ -112,10 +110,9 @@ $container->set(TestingInvokable::class, $container ==> use Ytake\HHContainer\ServiceModule; use Ytake\HHContainer\FactoryContainer; -class ExampleModule extends ServiceModule -{ - public function provide(FactoryContainer $container): void - { +class ExampleModule extends ServiceModule { + + public function provide(FactoryContainer $container): void { $container->set('example', $container ==> new \stdClass()); } } diff --git a/src/ContainerException.php b/src/ContainerException.php index b1eefa4..239214f 100644 --- a/src/ContainerException.php +++ b/src/ContainerException.php @@ -19,5 +19,5 @@ use type Psr\Container\ContainerExceptionInterface; -class ContainerException extends \Exception +final class ContainerException extends \Exception implements ContainerExceptionInterface {} diff --git a/src/FactoryContainer.php b/src/FactoryContainer.php index f5245e3..9e2aa34 100644 --- a/src/FactoryContainer.php +++ b/src/FactoryContainer.php @@ -18,19 +18,20 @@ namespace Ytake\HHContainer; use type Psr\Container\ContainerInterface; +use type ReflectionClass; +use type ReflectionMethod; +use type ReflectionException; -enum Scope : int { - PROTOTYPE = 0; - SINGLETON = 1; -} - +use namespace HH\Lib\Dict; type TServiceModule = classname; type TCallable = (function(FactoryContainer): mixed); +use function count; use function is_null; use function call_user_func; use function sprintf; use function array_key_exists; +use function unset; /** * simple light weight service locator container @@ -39,34 +40,19 @@ enum Scope : int { */ class FactoryContainer implements ContainerInterface { - protected Vector $modules = Vector {}; - - protected array> - $parameters = []; - - protected bool $locked = false; - - protected Map> $mapper = Map{}; - + protected dict> $mapper = dict[]; + public function set( string $id, TCallable $callback, Scope $scope = Scope::PROTOTYPE, ): void { - $this->mapper->add(Pair {$id, Map{$scope => $callback}}); + $this->mapper[$id] = Map{$scope => $callback}; } - - public function parameters( - string $id, - string $name, - TCallable $callback, - ): void { - $this->parameters[$id][$name] = $callback; - } - + public function get($id): mixed { if ($this->has($id)) { - $resolved = $this->mapper->get($id); + $resolved = $this->mapper[$id]; if (!is_null($resolved)) { if ($resolved->firstKey() === Scope::SINGLETON) { return $this->shared($id); @@ -77,79 +63,43 @@ public function get($id): mixed { } } } - try { - $reflectionClass = new \ReflectionClass($id); - if ($reflectionClass->isInstantiable()) { - $arguments = Vector{}; - $constructor = $reflectionClass->getConstructor(); - if ($constructor instanceof \ReflectionMethod) { - $resolvedParameters = $this->resolveConstructorParameters($id, $constructor); - if ($resolvedParameters->count()) { - $arguments = $resolvedParameters; - } - } - return $reflectionClass->newInstanceArgs($arguments); - } - } catch (\ReflectionException $e) { - throw new NotFoundException( - sprintf('Identifier "%s" is not binding.', $id), - ); - } - throw new ContainerException(sprintf('Error retrieving "%s"', $id)); + throw new NotFoundException( + sprintf('Identifier "%s" is not binding.', $id), + ); } <<__Memoize>> protected function shared(string $id): mixed { - $call = $this->mapper->at($id)->firstValue(); + $call = $this->mapper[$id]->firstValue(); if(!is_null($call)) { return call_user_func($call, $this); } } - + + <<__Rx, __Mutable>> public function has($id): bool { - return $this->mapper->containsKey($id); + return array_key_exists($id, $this->mapper); } - + public function bindings( - ): ImmMap> { - return $this->mapper->toImmMap(); + ): dict> { + return $this->mapper; } public function flush(): void { - $this->mapper->clear(); + $this->mapper = dict[]; } + <<__Rx, __Mutable>> public function remove(string $id): void { - $this->mapper->removeKey($id); - } - - public function registerModule(TServiceModule $moduleClassName): void { - $this->modules->add($moduleClassName); - } - - public function lockModule(): void { - foreach ($this->modules->getIterator() as $iterator) { - (new $iterator())->provide($this); + if ($this->has($id)) { + unset($this->mapper[$id]); } } - - protected function resolveConstructorParameters( - string $id, - \ReflectionMethod $constructor, - ): Vector { - $r = Vector{}; - $parameters = $constructor->getParameters(); - foreach ($parameters as $parameter) { - if (array_key_exists($id, $this->parameters)) { - if (array_key_exists($parameter->getName(), $this->parameters[$id])) { - $r->add(call_user_func( - $this->parameters[$id][$parameter->getName()], - $this, - )); - } - } - } - return $r; + + public function registerModule(TServiceModule $moduleClassName): void { + new $moduleClassName() + |> $$->provide($this); } public function callable(MethodCallIntreface $invokable): mixed { diff --git a/src/FactoryInterface.php b/src/FactoryInterface.php index fde9638..feea878 100644 --- a/src/FactoryInterface.php +++ b/src/FactoryInterface.php @@ -20,10 +20,12 @@ interface FactoryInterface { abstract const type T; - + public function provide(FactoryContainer $container): this::T; - + + <<__Rx>> public function scope(): Scope; - + + <<__Rx>> public function name(): string; } diff --git a/src/MethodCallIntreface.php b/src/MethodCallIntreface.php index f9a3fc0..6f49167 100644 --- a/src/MethodCallIntreface.php +++ b/src/MethodCallIntreface.php @@ -19,6 +19,7 @@ namespace Ytake\HHContainer; interface MethodCallIntreface { - + + <<__Rx>> public function proceed(): mixed; } diff --git a/src/MethodCaller.php b/src/MethodCaller.php index 040e2d1..a0d093b 100644 --- a/src/MethodCaller.php +++ b/src/MethodCaller.php @@ -32,6 +32,7 @@ public function __construct( } } + <<__Rx>> public function proceed(): mixed { $dynamicMethod = $this->invokeMethod; return /* UNSAFE_EXPR */ $this->instance->$dynamicMethod(...$this->args); diff --git a/src/NotFoundException.php b/src/NotFoundException.php index 7f6a2ff..ae04ac6 100644 --- a/src/NotFoundException.php +++ b/src/NotFoundException.php @@ -19,5 +19,5 @@ use type Psr\Container\NotFoundExceptionInterface; -class NotFoundException extends \Exception +final class NotFoundException extends \Exception implements NotFoundExceptionInterface {} diff --git a/src/Scope.php b/src/Scope.php new file mode 100644 index 0000000..1664626 --- /dev/null +++ b/src/Scope.php @@ -0,0 +1,8 @@ + $factories = Map{}; + protected dict $factories = dict[]; public function __construct( protected FactoryContainer $container ) {} - + + <<__Rx, __Mutable>> public function registerFactory(FactoryInterface $factory): void { - $this->factories->add(Pair{$factory->name(), $factory}); + $this->factories[$factory->name()] = $factory; + } + + <<__Rx, __Mutable>> + public function has(string $factoryName): bool { + return array_key_exists($factoryName, $this->factories); } public function create(string $factoryName): FactoryInterface::T { - $resolve = $this->factories->get($factoryName); - if (!is_null($resolve)) { - if ($resolve->scope() === Scope::SINGLETON) { - return $this->createShared($factoryName); + if ($this->has($factoryName)) { + $resolve = $this->factories[$factoryName]; + if (!is_null($resolve)) { + if ($resolve->scope() === Scope::SINGLETON) { + return $this->createShared($factoryName); + } + return $resolve->provide($this->container); } - return $resolve->provide($this->container); } throw new NotFoundException( sprintf('"%s" is not found.', $factoryName), @@ -47,8 +56,7 @@ public function create(string $factoryName): FactoryInterface::T { <<__Memoize>> protected function createShared(string $factoryName): FactoryInterface::T { - return $this->factories - ->at($factoryName) + return $this->factories[$factoryName] ->provide($this->container); } } diff --git a/src/ServiceModule.php b/src/ServiceModule.php index b61fc51..1f5c046 100644 --- a/src/ServiceModule.php +++ b/src/ServiceModule.php @@ -19,6 +19,8 @@ <<__ConsistentConstruct>> abstract class ServiceModule { - - abstract public function provide(FactoryContainer $container): void; + + abstract public function provide( + FactoryContainer $container + ): void; } diff --git a/tests/ContainerTest.php b/tests/ContainerTest.php index 9b9fca6..a46024d 100644 --- a/tests/ContainerTest.php +++ b/tests/ContainerTest.php @@ -57,11 +57,16 @@ public function testShouldThrowException() :void { $container->get('testing'); } + <> + public function testShouldThrowNotFoundException() :void { + $container = new \Ytake\HHContainer\FactoryContainer(); + expect($container->get(\stdClass::class))->toBeInstanceOf(\stdClass::class); + } + <> public function testShouldReturnProvideInstance(): void { $container = new \Ytake\HHContainer\FactoryContainer(); $container->registerModule(StubModule::class); - $container->lockModule(); expect($container->get('provide:sample'))->toBeInstanceOf(\stdClass::class); $container->set('message.class', $container ==> new MockMessageClass('testing')); expect($container->get('message.class'))->toBeInstanceOf(MockMessageClass::class); @@ -69,17 +74,18 @@ public function testShouldReturnProvideInstance(): void { public function testShouldResolveInstance(): void { $container = new \Ytake\HHContainer\FactoryContainer(); - expect($container->get(\stdClass::class))->toBeInstanceOf(\stdClass::class); - $container->parameters(ResolvedObject::class, 'object', $container ==> new \stdClass()); - $container->parameters(ResolvedObject::class, 'integer', $container ==> 100); + $container->set(ResolvedObject::class, $container ==> { + return new ResolvedObject(new \stdClass(), 100); + }); $instance = $container->get(ResolvedObject::class); expect($instance)->toBeInstanceOf(ResolvedObject::class); } public function testShouldResolveConstructorPromotionInstance(): void { $container = new \Ytake\HHContainer\FactoryContainer(); - $container->parameters(ConstructorPromotionClass::class, 'object', $container ==> new \stdClass()); - $container->parameters(ConstructorPromotionClass::class, 'integer', $container ==> 100); + $container->set(ConstructorPromotionClass::class, $container ==> { + return new ConstructorPromotionClass(new \stdClass(), 100, ); + }); $instance = $container->get(ConstructorPromotionClass::class); expect($instance)->toBeInstanceOf(ConstructorPromotionClass::class); if ($instance instanceof ConstructorPromotionClass) { @@ -90,7 +96,11 @@ public function testShouldResolveConstructorPromotionInstance(): void { public function testShouldResolveDependencyInjectionWithLocation(): void { $container = new FactoryContainer(); $container->set('message.class', $container ==> new MockMessageClass('testing')); - $container->parameters(MessageClient::class, 'message', $container ==> $container->get('message.class')); + $container->set(MessageClient::class, $container ==> { + $instance = $container->get('message.class'); + invariant($instance instanceof MockMessageClass, 'error'); + new MessageClient($instance); + }); $instance = $container->get(MessageClient::class); if ($instance instanceof MessageClient) { expect($instance->message()->message())->toBeSame('testing'); @@ -105,23 +115,23 @@ public function provide(FactoryContainer $container): void { } } -class ResolvedObject -{ +class ResolvedObject { private \stdClass $object; private int $integer; - public function __construct(\stdClass $object, int $integer = 1) - { + public function __construct( + \stdClass $object, + int $integer = 1 + ) { $this->object = $object; $this->integer = $integer; } } -class ConstructorPromotionClass -{ - public function __construct(private \stdClass $object, private int $integer) - { - - } +class ConstructorPromotionClass { + public function __construct( + private \stdClass $object, + private int $integer + ) {} public function getInteger(): int { return $this->integer; @@ -129,17 +139,20 @@ public function getInteger(): int { } class MockMessageClass { - public function __construct(protected string $message) { - } + public function __construct( + protected string $message + ) {} + public function message(): string { return $this->message; } } final class MessageClient { - public function __construct(protected MockMessageClass $message) { + public function __construct( + protected MockMessageClass $message + ) {} - } public function message(): MockMessageClass { return $this->message; } diff --git a/tests/FactoryTest.php b/tests/FactoryTest.php index 1e6f8ec..5f3ada4 100644 --- a/tests/FactoryTest.php +++ b/tests/FactoryTest.php @@ -30,28 +30,35 @@ public function testShouldReturnStdClass(): void { class StringFactory implements FactoryInterface { const type T = string; + public function provide(FactoryContainer $_container): this::T { return 'testing'; } - public function name(): string { - return 'testing'; - } + + <<__Rx>> public function scope(): Scope { return Scope::SINGLETON; } + + <<__Rx>> + public function name(): string { + return 'testing'; + } } class MockClassFactory implements FactoryInterface { const type T = MockClass; - + public function provide(FactoryContainer $_container): this::T { return new MockClass(1); } + <<__Rx>> public function scope(): Scope { return Scope::SINGLETON; } + <<__Rx>> public function name(): string { return MockClass::class; } From 5b0e260fdffa00a01a2521718e1c80d1febe94c1 Mon Sep 17 00:00:00 2001 From: ytake Date: Mon, 8 Oct 2018 01:36:35 +0900 Subject: [PATCH 3/7] changed env for testing --- .travis.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index c75f8a4..95b9566 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,9 +4,10 @@ services: - docker env: matrix: - - HHVM_VERSION=3.24-lts-latest - - HHVM_VERSION=3.25.3 - - HHVM_VERSION=3.26.0 + - HHVM_VERSION=3.28.0 + - HHVM_VERSION=3.28.1 + - HHVM_VERSION=3.28.2 + - HHVM_VERSION=3.28.3 - HHVM_VERSION=latest - HHVM_VERSION=nightly install: From 16b1170f68bb0dc89646886ddade627043695cf0 Mon Sep 17 00:00:00 2001 From: ytake Date: Mon, 8 Oct 2018 01:41:53 +0900 Subject: [PATCH 4/7] fixed --- .travis.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.sh b/.travis.sh index 5b1af47..97cfce5 100755 --- a/.travis.sh +++ b/.travis.sh @@ -4,6 +4,6 @@ hhvm --version curl https://getcomposer.org/installer | hhvm -d hhvm.jit=0 --php -- /dev/stdin --install-dir=/usr/local/bin --filename=composer cd /var/source -hhvm -d hhvm.php7.all=1 -d hhvm.jit=0 -d hhvm.hack.lang.auto_typecheck=0 /usr/local/bin/composer install +hhvm -d hhvm.jit=0 -d hhvm.hack.lang.auto_typecheck=0 /usr/local/bin/composer install -hhvm -d hhvm.php7.all=1 -d hhvm.jit=0 -d hhvm.hack.lang.auto_typecheck=0 vendor/bin/phpunit +hhvm -d hhvm.jit=0 -d hhvm.hack.lang.auto_typecheck=0 vendor/bin/hacktest tests/ From 48dbca5f2a1dd4880b99fd2dd62acc39af260233 Mon Sep 17 00:00:00 2001 From: ytake Date: Mon, 8 Oct 2018 02:05:27 +0900 Subject: [PATCH 5/7] lint --- src/FactoryContainer.php | 11 ++++++----- src/FactoryInterface.php | 4 ++-- src/MethodCallIntreface.php | 2 +- src/ServiceFactory.php | 4 ++-- src/ServiceModule.php | 2 +- tests/ContainerTest.php | 2 +- tests/FactoryTest.php | 4 ++-- 7 files changed, 15 insertions(+), 14 deletions(-) diff --git a/src/FactoryContainer.php b/src/FactoryContainer.php index 9e2aa34..3e5568e 100644 --- a/src/FactoryContainer.php +++ b/src/FactoryContainer.php @@ -23,6 +23,7 @@ use type ReflectionException; use namespace HH\Lib\Dict; + type TServiceModule = classname; type TCallable = (function(FactoryContainer): mixed); @@ -41,7 +42,7 @@ class FactoryContainer implements ContainerInterface { protected dict> $mapper = dict[]; - + public function set( string $id, TCallable $callback, @@ -49,7 +50,7 @@ public function set( ): void { $this->mapper[$id] = Map{$scope => $callback}; } - + public function get($id): mixed { if ($this->has($id)) { $resolved = $this->mapper[$id]; @@ -75,12 +76,12 @@ protected function shared(string $id): mixed { return call_user_func($call, $this); } } - + <<__Rx, __Mutable>> public function has($id): bool { return array_key_exists($id, $this->mapper); } - + public function bindings( ): dict> { return $this->mapper; @@ -96,7 +97,7 @@ public function remove(string $id): void { unset($this->mapper[$id]); } } - + public function registerModule(TServiceModule $moduleClassName): void { new $moduleClassName() |> $$->provide($this); diff --git a/src/FactoryInterface.php b/src/FactoryInterface.php index feea878..8572b0d 100644 --- a/src/FactoryInterface.php +++ b/src/FactoryInterface.php @@ -22,10 +22,10 @@ interface FactoryInterface { abstract const type T; public function provide(FactoryContainer $container): this::T; - + <<__Rx>> public function scope(): Scope; - + <<__Rx>> public function name(): string; } diff --git a/src/MethodCallIntreface.php b/src/MethodCallIntreface.php index 6f49167..11c23d7 100644 --- a/src/MethodCallIntreface.php +++ b/src/MethodCallIntreface.php @@ -19,7 +19,7 @@ namespace Ytake\HHContainer; interface MethodCallIntreface { - + <<__Rx>> public function proceed(): mixed; } diff --git a/src/ServiceFactory.php b/src/ServiceFactory.php index f52422c..3c15910 100644 --- a/src/ServiceFactory.php +++ b/src/ServiceFactory.php @@ -28,12 +28,12 @@ class ServiceFactory { public function __construct( protected FactoryContainer $container ) {} - + <<__Rx, __Mutable>> public function registerFactory(FactoryInterface $factory): void { $this->factories[$factory->name()] = $factory; } - + <<__Rx, __Mutable>> public function has(string $factoryName): bool { return array_key_exists($factoryName, $this->factories); diff --git a/src/ServiceModule.php b/src/ServiceModule.php index 1f5c046..efb5647 100644 --- a/src/ServiceModule.php +++ b/src/ServiceModule.php @@ -19,7 +19,7 @@ <<__ConsistentConstruct>> abstract class ServiceModule { - + abstract public function provide( FactoryContainer $container ): void; diff --git a/tests/ContainerTest.php b/tests/ContainerTest.php index a46024d..bad1bdf 100644 --- a/tests/ContainerTest.php +++ b/tests/ContainerTest.php @@ -119,7 +119,7 @@ class ResolvedObject { private \stdClass $object; private int $integer; public function __construct( - \stdClass $object, + \stdClass $object, int $integer = 1 ) { $this->object = $object; diff --git a/tests/FactoryTest.php b/tests/FactoryTest.php index 5f3ada4..bc81471 100644 --- a/tests/FactoryTest.php +++ b/tests/FactoryTest.php @@ -34,7 +34,7 @@ class StringFactory implements FactoryInterface { public function provide(FactoryContainer $_container): this::T { return 'testing'; } - + <<__Rx>> public function scope(): Scope { return Scope::SINGLETON; @@ -48,7 +48,7 @@ public function name(): string { class MockClassFactory implements FactoryInterface { const type T = MockClass; - + public function provide(FactoryContainer $_container): this::T { return new MockClass(1); } From ee571615bda847d618682f3a54bf3f1e56ab2da1 Mon Sep 17 00:00:00 2001 From: ytake Date: Mon, 8 Oct 2018 02:11:36 +0900 Subject: [PATCH 6/7] removed flush --- src/FactoryContainer.php | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/FactoryContainer.php b/src/FactoryContainer.php index 3e5568e..1fa9954 100644 --- a/src/FactoryContainer.php +++ b/src/FactoryContainer.php @@ -87,10 +87,6 @@ public function bindings( return $this->mapper; } - public function flush(): void { - $this->mapper = dict[]; - } - <<__Rx, __Mutable>> public function remove(string $id): void { if ($this->has($id)) { From 51048fba4a657d922549c198409c8da10487295a Mon Sep 17 00:00:00 2001 From: ytake Date: Mon, 8 Oct 2018 02:46:24 +0900 Subject: [PATCH 7/7] fixed lint and reactive attributes --- hhast-lint.json | 5 +---- src/FactoryContainer.php | 23 ++++++++++------------- src/FactoryInterface.php | 2 +- tests/ContainerTest.php | 2 +- 4 files changed, 13 insertions(+), 19 deletions(-) diff --git a/hhast-lint.json b/hhast-lint.json index cf2cf13..19a2096 100644 --- a/hhast-lint.json +++ b/hhast-lint.json @@ -2,8 +2,5 @@ "roots": [ "src/", "tests/" - ], - "namespaceAliases": { - "HHAST": "Facebook\\HHAST\\Linters" - } + ] } diff --git a/src/FactoryContainer.php b/src/FactoryContainer.php index 1fa9954..254dbba 100644 --- a/src/FactoryContainer.php +++ b/src/FactoryContainer.php @@ -18,21 +18,14 @@ namespace Ytake\HHContainer; use type Psr\Container\ContainerInterface; -use type ReflectionClass; -use type ReflectionMethod; -use type ReflectionException; - -use namespace HH\Lib\Dict; type TServiceModule = classname; type TCallable = (function(FactoryContainer): mixed); -use function count; use function is_null; use function call_user_func; use function sprintf; use function array_key_exists; -use function unset; /** * simple light weight service locator container @@ -41,14 +34,14 @@ */ class FactoryContainer implements ContainerInterface { - protected dict> $mapper = dict[]; + protected Map> $mapper = Map{}; public function set( string $id, TCallable $callback, Scope $scope = Scope::PROTOTYPE, ): void { - $this->mapper[$id] = Map{$scope => $callback}; + $this->mapper->add(Pair {$id, Map{$scope => $callback}}); } public function get($id): mixed { @@ -82,18 +75,22 @@ public function has($id): bool { return array_key_exists($id, $this->mapper); } + <<__Rx>> public function bindings( - ): dict> { - return $this->mapper; + ): ImmMap> { + return $this->mapper->toImmMap(); } - <<__Rx, __Mutable>> public function remove(string $id): void { if ($this->has($id)) { - unset($this->mapper[$id]); + $this->mapper->removeKey($id); } } + public function flush(): void { + $this->mapper->clear(); + } + public function registerModule(TServiceModule $moduleClassName): void { new $moduleClassName() |> $$->provide($this); diff --git a/src/FactoryInterface.php b/src/FactoryInterface.php index 8572b0d..d351d2d 100644 --- a/src/FactoryInterface.php +++ b/src/FactoryInterface.php @@ -20,7 +20,7 @@ interface FactoryInterface { abstract const type T; - + public function provide(FactoryContainer $container): this::T; <<__Rx>> diff --git a/tests/ContainerTest.php b/tests/ContainerTest.php index bad1bdf..999f589 100644 --- a/tests/ContainerTest.php +++ b/tests/ContainerTest.php @@ -4,7 +4,7 @@ use type Ytake\HHContainer\FactoryContainer; use type Ytake\HHContainer\ServiceModule; use function Facebook\FBExpect\expect; -use \Ytake\HHContainer\NotFoundException; +use type Ytake\HHContainer\NotFoundException; final class ContainerTest extends HackTest {