From 2700cd423556e287bea0aae092eeffcd5b966a8e Mon Sep 17 00:00:00 2001 From: Yuta Nagamiya Date: Thu, 13 Feb 2025 16:34:29 +0900 Subject: [PATCH 1/8] Add support for readonly class in PHP 8.2 --- src-php8/Php82InterceptTrait.php | 53 +++++++++++++++++++ src/AopCode.php | 5 +- src/Compiler.php | 5 +- src/InterceptTrait.php | 25 +++++---- src/InterceptTraitState.php | 27 ++++++++++ src/WeavedInterface.php | 2 + src/Weaver.php | 4 +- tests/CompilerTest.php | 24 ++++++--- tests/Fake/FakePhp82ReadOnlyClass.php | 7 +++ tests/Fake/FakeWeavedClass.php | 4 ++ .../Ray_Aop_FakeWeaverMock_523567342.php | 36 +++++++++++++ 11 files changed, 168 insertions(+), 24 deletions(-) create mode 100644 src-php8/Php82InterceptTrait.php create mode 100644 src/InterceptTraitState.php create mode 100644 tests/Fake/FakePhp82ReadOnlyClass.php create mode 100644 tests/tmp_unerase/Ray_Aop_FakeWeaverMock_523567342.php diff --git a/src-php8/Php82InterceptTrait.php b/src-php8/Php82InterceptTrait.php new file mode 100644 index 00000000..6ef98fc8 --- /dev/null +++ b/src-php8/Php82InterceptTrait.php @@ -0,0 +1,53 @@ +> $bindings + * + * @see WeavedInterface::initState() + */ + public function initState(array $bindings): void + { + $this->state = new InterceptTraitState($bindings, true); + } + + /** + * @param array $args + * + * @return mixed + * + * @SuppressWarnings(PHPMD.CamelCaseMethodName) + */ + private function _intercept(string $func, array $args) // phpcs:ignore + { + if (! $this->state->isAspect) { + $this->state->isAspect = true; + + return call_user_func_array([parent::class, $func], $args); + } + + $this->state->isAspect = false; + $result = (new Invocation($this, $func, $args, $this->state->bindings[$func]))->proceed(); + $this->state->isAspect = true; + + return $result; + } +} diff --git a/src/AopCode.php b/src/AopCode.php index fdfea200..f461f4af 100644 --- a/src/AopCode.php +++ b/src/AopCode.php @@ -19,6 +19,7 @@ use function sprintf; use function token_get_all; +use const PHP_VERSION_ID; use const T_CLASS; use const T_EXTENDS; use const T_STRING; @@ -202,7 +203,9 @@ private function addMethods(ReflectionClass $class, BindInterface $bind): void /** @psalm-external-mutation-free */ private function addIntercepterTrait(): void { - $this->add(sprintf("{\n use \%s;\n}\n", InterceptTrait::class)); + PHP_VERSION_ID >= 80200 + ? $this->add(sprintf("{\n use \%s;\n}\n", Php82InterceptTrait::class)) + : $this->add(sprintf("{\n use \%s;\n}\n", InterceptTrait::class)); } /** @psalm-external-mutation-free */ diff --git a/src/Compiler.php b/src/Compiler.php index 0f009cf3..61568a60 100644 --- a/src/Compiler.php +++ b/src/Compiler.php @@ -64,9 +64,8 @@ public function newInstance(string $class, array $args, BindInterface $bind): ob $compiledClass = $this->compile($class, $bind); assert(class_exists($compiledClass)); $instance = (new ReflectionClass($compiledClass))->newInstanceArgs($args); - assert($instance instanceof $class); - if (isset($instance->bindings)) { - $instance->bindings = $bind->getBindings(); + if ($instance instanceof WeavedInterface) { + $instance->initState($bind->getBindings()); } assert($instance instanceof $class); diff --git a/src/InterceptTrait.php b/src/InterceptTrait.php index 8bd207de..2568fb90 100644 --- a/src/InterceptTrait.php +++ b/src/InterceptTrait.php @@ -11,16 +11,21 @@ trait InterceptTrait { /** - * @var array>> + * @var InterceptTraitState * @readonly + * @internal Public for CompilerTest */ - public $bindings = []; + public $state; /** - * @var bool - * @readonly + * @param array> $bindings + * + * @see WeavedInterface::initState() */ - private $isAspect = true; + public function initState(array $bindings): void + { + $this->state = new InterceptTraitState($bindings, true); + } /** * @param array $args @@ -31,15 +36,15 @@ trait InterceptTrait */ private function _intercept(string $func, array $args) // phpcs:ignore { - if (! $this->isAspect) { - $this->isAspect = true; + if (! $this->state->isAspect) { + $this->state->isAspect = true; return call_user_func_array([parent::class, $func], $args); } - $this->isAspect = false; - $result = (new Invocation($this, $func, $args, $this->bindings[$func]))->proceed(); - $this->isAspect = true; + $this->state->isAspect = false; + $result = (new Invocation($this, $func, $args, $this->state->bindings[$func]))->proceed(); + $this->state->isAspect = true; return $result; } diff --git a/src/InterceptTraitState.php b/src/InterceptTraitState.php new file mode 100644 index 00000000..d1da9f67 --- /dev/null +++ b/src/InterceptTraitState.php @@ -0,0 +1,27 @@ +>> + * @readonly + */ + public $bindings; + + /** @var bool */ + public $isAspect; + + /** + * @param array>> $bindings + * @param bool $isAspect + */ + public function __construct($bindings, $isAspect) + { + $this->bindings = $bindings; + $this->isAspect = $isAspect; + } +} diff --git a/src/WeavedInterface.php b/src/WeavedInterface.php index 9e1d0c64..b8e49b79 100644 --- a/src/WeavedInterface.php +++ b/src/WeavedInterface.php @@ -6,4 +6,6 @@ interface WeavedInterface { + /** @param array> $bindings */ + public function initState(array $bindings): void; } diff --git a/src/Weaver.php b/src/Weaver.php index 0d803fa6..294c422d 100644 --- a/src/Weaver.php +++ b/src/Weaver.php @@ -57,12 +57,12 @@ public function newInstance(string $class, array $args): object { $aopClass = $this->weave($class); $instance = (new ReflectionClass($aopClass))->newInstanceArgs($args); - if (! isset($instance->bindings)) { + if (! $instance instanceof WeavedInterface) { /** @var T $instance */ return $instance; } - $instance->bindings = $this->bind->getBindings(); + $instance->initState($this->bind->getBindings()); assert($instance instanceof $class); return $instance; diff --git a/tests/CompilerTest.php b/tests/CompilerTest.php index 25e391e1..9dc04407 100644 --- a/tests/CompilerTest.php +++ b/tests/CompilerTest.php @@ -78,8 +78,8 @@ public function testParentClassName(object $class): void /** @depends testNewInstance */ public function testBuildClassWeaved(FakeMock $weaved): void { - assert(isset($weaved->bindings)); - $weaved->bindings = $this->bind->getBindings(); + assert(property_exists($weaved, 'state')); + $weaved->state->bindings = $this->bind->getBindings(); $result = $weaved->returnSame(1); $this->assertSame(2, $result); } @@ -117,8 +117,8 @@ public function testParentMethodIntercept(): void { $mock = $this->compiler->newInstance(FakeMockGrandChild::class, [], $this->bind); assert($mock instanceof FakeMockGrandChild); - assert(property_exists($mock, 'bindings')); - $mock->bindings = $this->bind->getBindings(); + assert(property_exists($mock, 'state')); + $mock->state->bindings = $this->bind->getBindings(); $result = $mock->returnSame(1); $this->assertSame(2, $result); } @@ -128,8 +128,8 @@ public function testTypedParentMethodIntercept(): void $bind = (new Bind())->bindInterceptors('passIterator', [new NullInterceptor()]); $mock = $this->compiler->newInstance(FakeTypedMockGrandChild::class, [], $bind); assert($mock instanceof FakeTypedMockGrandChild); - assert(property_exists($mock, 'bindings')); - $mock->bindings = $bind->getBindings(); + assert(property_exists($mock, 'state')); + $mock->state->bindings = $bind->getBindings(); $result = $mock->passIterator(new ArrayIterator()); $this->assertInstanceOf(ArrayIterator::class, $result); } @@ -138,8 +138,8 @@ public function testParentOfParentMethodIntercept(): void { $mock = $this->compiler->newInstance(FakeMockChildChild::class, [], $this->bind); assert($mock instanceof FakeMockChild); - assert(property_exists($mock, 'bindings')); - $mock->bindings = $this->bind->getBindings(); + assert(property_exists($mock, 'state')); + $mock->state->bindings = $this->bind->getBindings(); $result = $mock->returnSame(1); $this->assertSame(2, $result); } @@ -350,4 +350,12 @@ public function testMethodWithMixedArgument(): void $this->assertInstanceOf(FakeMixedParamClass::class, $mock); $this->assertInstanceOf(WeavedInterface::class, $mock); } + + /** @requires PHP 8.2 */ + public function testNewInstanceWithPhp82ReadOnlyClass(): void + { + $mock = $this->compiler->newInstance(FakePhp82ReadOnlyClass::class, [], $this->bind); + $this->assertInstanceOf(FakePhp82ReadOnlyClass::class, $mock); + $this->assertInstanceOf(WeavedInterface::class, $mock); + } } diff --git a/tests/Fake/FakePhp82ReadOnlyClass.php b/tests/Fake/FakePhp82ReadOnlyClass.php new file mode 100644 index 00000000..552239f9 --- /dev/null +++ b/tests/Fake/FakePhp82ReadOnlyClass.php @@ -0,0 +1,7 @@ +_intercept(__FUNCTION__, func_get_args()); + } + + /** + * doc comment of getSub + */ + public function getSub($a, $b) + { + return $this->_intercept(__FUNCTION__, func_get_args()); + } + + public function returnValue(null|\Ray\Aop\FakeNum $num = NULL) + { + return $this->_intercept(__FUNCTION__, func_get_args()); + } + + public function getPrivateVal() + { + return $this->_intercept(__FUNCTION__, func_get_args()); + } +} \ No newline at end of file From eb00afee3c7fc77627834c66dca58932dce4752e Mon Sep 17 00:00:00 2001 From: Akihito Koriyama Date: Thu, 13 Feb 2025 23:59:17 +0900 Subject: [PATCH 2/8] Update PHPDoc annotations to use imported MethodBindings type Replaced verbose array annotations with the `MethodBindings` type imported via Psalm across interfaces and traits. This improves code readability and ensures type consistency throughout the project. --- src/BindInterface.php | 7 +++++-- src/InterceptTrait.php | 3 ++- src/WeavedInterface.php | 3 ++- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/BindInterface.php b/src/BindInterface.php index 3d379337..1e07eedb 100644 --- a/src/BindInterface.php +++ b/src/BindInterface.php @@ -4,7 +4,10 @@ namespace Ray\Aop; -/** @psalm-import-type MethodName from Types */ +/** + * @psalm-import-type MethodName from Types + * @psalm-import-type MethodBindings from Types + */ interface BindInterface { /** @@ -28,7 +31,7 @@ public function bindInterceptors(string $method, array $interceptors): self; * * [$methodNameA => [$interceptorA, ...][] * - * @return array> + * @return MethodBindings */ public function getBindings(); diff --git a/src/InterceptTrait.php b/src/InterceptTrait.php index 2568fb90..7313b7c5 100644 --- a/src/InterceptTrait.php +++ b/src/InterceptTrait.php @@ -8,6 +8,7 @@ use function call_user_func_array; +/** @psalm-import-type MethodBindings from Types */ trait InterceptTrait { /** @@ -18,7 +19,7 @@ trait InterceptTrait public $state; /** - * @param array> $bindings + * @param MethodBindings $bindings * * @see WeavedInterface::initState() */ diff --git a/src/WeavedInterface.php b/src/WeavedInterface.php index b8e49b79..3d80d2fd 100644 --- a/src/WeavedInterface.php +++ b/src/WeavedInterface.php @@ -4,8 +4,9 @@ namespace Ray\Aop; +/** @psalm-import-type MethodBindings from Types */ interface WeavedInterface { - /** @param array> $bindings */ + /** @param MethodBindings $bindings */ public function initState(array $bindings): void; } From 73e5dcdd7b1566a474f0d03125bfb124d8b71620 Mon Sep 17 00:00:00 2001 From: Akihito Koriyama Date: Fri, 14 Feb 2025 00:19:38 +0900 Subject: [PATCH 3/8] Rename `initState` method for not conflict with the method names of the AOP class that inherits it --- src-php8/Php82InterceptTrait.php | 4 ++-- src/Compiler.php | 2 +- src/InterceptTrait.php | 5 +++-- src/WeavedInterface.php | 8 ++++++-- src/Weaver.php | 2 +- tests/Fake/FakeWeavedClass.php | 2 +- 6 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src-php8/Php82InterceptTrait.php b/src-php8/Php82InterceptTrait.php index 6ef98fc8..51441270 100644 --- a/src-php8/Php82InterceptTrait.php +++ b/src-php8/Php82InterceptTrait.php @@ -22,9 +22,9 @@ trait Php82InterceptTrait /** * @param array> $bindings * - * @see WeavedInterface::initState() + * @see WeavedInterface::_initState() */ - public function initState(array $bindings): void + public function _initState(array $bindings): void { $this->state = new InterceptTraitState($bindings, true); } diff --git a/src/Compiler.php b/src/Compiler.php index 61568a60..ea4d395a 100644 --- a/src/Compiler.php +++ b/src/Compiler.php @@ -65,7 +65,7 @@ public function newInstance(string $class, array $args, BindInterface $bind): ob assert(class_exists($compiledClass)); $instance = (new ReflectionClass($compiledClass))->newInstanceArgs($args); if ($instance instanceof WeavedInterface) { - $instance->initState($bind->getBindings()); + $instance->_initState($bind->getBindings()); } assert($instance instanceof $class); diff --git a/src/InterceptTrait.php b/src/InterceptTrait.php index 7313b7c5..63c6c65a 100644 --- a/src/InterceptTrait.php +++ b/src/InterceptTrait.php @@ -21,9 +21,10 @@ trait InterceptTrait /** * @param MethodBindings $bindings * - * @see WeavedInterface::initState() + * @see WeavedInterface::_initState() + * @SuppressWarnings(PHPMD.CamelCaseMethodName) */ - public function initState(array $bindings): void + public function _initState(array $bindings): void // phpcs:ignore { $this->state = new InterceptTraitState($bindings, true); } diff --git a/src/WeavedInterface.php b/src/WeavedInterface.php index 3d80d2fd..17d73028 100644 --- a/src/WeavedInterface.php +++ b/src/WeavedInterface.php @@ -7,6 +7,10 @@ /** @psalm-import-type MethodBindings from Types */ interface WeavedInterface { - /** @param MethodBindings $bindings */ - public function initState(array $bindings): void; + /** + * @param MethodBindings $bindings + * + * @SuppressWarnings(PHPMD.CamelCaseMethodName) + */ + public function _initState(array $bindings): void; // phpcs:ignore } diff --git a/src/Weaver.php b/src/Weaver.php index 294c422d..2ee361c9 100644 --- a/src/Weaver.php +++ b/src/Weaver.php @@ -62,7 +62,7 @@ public function newInstance(string $class, array $args): object return $instance; } - $instance->initState($this->bind->getBindings()); + $instance->_initState($this->bind->getBindings()); assert($instance instanceof $class); return $instance; diff --git a/tests/Fake/FakeWeavedClass.php b/tests/Fake/FakeWeavedClass.php index cc1e052b..68356624 100644 --- a/tests/Fake/FakeWeavedClass.php +++ b/tests/Fake/FakeWeavedClass.php @@ -9,5 +9,5 @@ class FakeWeavedClass extends FakeClass implements WeavedInterface /** * {@inheritDoc} */ - public function initState(array $bindings): void {} + public function _initState(array $bindings): void {} } From 57aa7e3a6cde7ae0fc999fa440436c63c61a95c0 Mon Sep 17 00:00:00 2001 From: Akihito Koriyama Date: Fri, 14 Feb 2025 01:11:23 +0900 Subject: [PATCH 4/8] Add red test Add $state property to FakeMockChild class --- tests/Fake/FakeMockChild.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/Fake/FakeMockChild.php b/tests/Fake/FakeMockChild.php index 80284b03..2e6d00fa 100644 --- a/tests/Fake/FakeMockChild.php +++ b/tests/Fake/FakeMockChild.php @@ -6,4 +6,5 @@ class FakeMockChild extends FakeMock { + public $state; } From a9749865e8aac39fb6b756c581fbe3f6d0d68bdf Mon Sep 17 00:00:00 2001 From: Akihito Koriyama Date: Fri, 14 Feb 2025 01:23:02 +0900 Subject: [PATCH 5/8] Rename `state` to `_state` to avoid conflicts This change updates the property name from `state` to `_state` across relevant classes and tests to reinforce encapsulation and align with internal naming conventions. Adjustments were made to all associated references to ensure consistency and functionality. --- src-php8/Php82InterceptTrait.php | 14 +++++++------- src/InterceptTrait.php | 14 +++++++------- tests/CompilerTest.php | 15 +++++++-------- 3 files changed, 21 insertions(+), 22 deletions(-) diff --git a/src-php8/Php82InterceptTrait.php b/src-php8/Php82InterceptTrait.php index 51441270..377acc75 100644 --- a/src-php8/Php82InterceptTrait.php +++ b/src-php8/Php82InterceptTrait.php @@ -17,7 +17,7 @@ trait Php82InterceptTrait * @var InterceptTraitState * @internal Public for CompilerTest */ - public readonly InterceptTraitState $state; + public readonly InterceptTraitState $_state; /** * @param array> $bindings @@ -26,7 +26,7 @@ trait Php82InterceptTrait */ public function _initState(array $bindings): void { - $this->state = new InterceptTraitState($bindings, true); + $this->_state = new InterceptTraitState($bindings, true); } /** @@ -38,15 +38,15 @@ public function _initState(array $bindings): void */ private function _intercept(string $func, array $args) // phpcs:ignore { - if (! $this->state->isAspect) { - $this->state->isAspect = true; + if (! $this->_state->isAspect) { + $this->_state->isAspect = true; return call_user_func_array([parent::class, $func], $args); } - $this->state->isAspect = false; - $result = (new Invocation($this, $func, $args, $this->state->bindings[$func]))->proceed(); - $this->state->isAspect = true; + $this->_state->isAspect = false; + $result = (new Invocation($this, $func, $args, $this->_state->bindings[$func]))->proceed(); + $this->_state->isAspect = true; return $result; } diff --git a/src/InterceptTrait.php b/src/InterceptTrait.php index 63c6c65a..888ce6a8 100644 --- a/src/InterceptTrait.php +++ b/src/InterceptTrait.php @@ -16,7 +16,7 @@ trait InterceptTrait * @readonly * @internal Public for CompilerTest */ - public $state; + public $_state; /** * @param MethodBindings $bindings @@ -26,7 +26,7 @@ trait InterceptTrait */ public function _initState(array $bindings): void // phpcs:ignore { - $this->state = new InterceptTraitState($bindings, true); + $this->_state = new InterceptTraitState($bindings, true); } /** @@ -38,15 +38,15 @@ public function _initState(array $bindings): void // phpcs:ignore */ private function _intercept(string $func, array $args) // phpcs:ignore { - if (! $this->state->isAspect) { - $this->state->isAspect = true; + if (! $this->_state->isAspect) { + $this->_state->isAspect = true; return call_user_func_array([parent::class, $func], $args); } - $this->state->isAspect = false; - $result = (new Invocation($this, $func, $args, $this->state->bindings[$func]))->proceed(); - $this->state->isAspect = true; + $this->_state->isAspect = false; + $result = (new Invocation($this, $func, $args, $this->_state->bindings[$func]))->proceed(); + $this->_state->isAspect = true; return $result; } diff --git a/tests/CompilerTest.php b/tests/CompilerTest.php index 9dc04407..08cd5489 100644 --- a/tests/CompilerTest.php +++ b/tests/CompilerTest.php @@ -78,8 +78,8 @@ public function testParentClassName(object $class): void /** @depends testNewInstance */ public function testBuildClassWeaved(FakeMock $weaved): void { - assert(property_exists($weaved, 'state')); - $weaved->state->bindings = $this->bind->getBindings(); + assert(property_exists($weaved, '_state')); + $weaved->_state->bindings = $this->bind->getBindings(); $result = $weaved->returnSame(1); $this->assertSame(2, $result); } @@ -117,8 +117,7 @@ public function testParentMethodIntercept(): void { $mock = $this->compiler->newInstance(FakeMockGrandChild::class, [], $this->bind); assert($mock instanceof FakeMockGrandChild); - assert(property_exists($mock, 'state')); - $mock->state->bindings = $this->bind->getBindings(); + assert(property_exists($mock, '_state')); $result = $mock->returnSame(1); $this->assertSame(2, $result); } @@ -128,8 +127,8 @@ public function testTypedParentMethodIntercept(): void $bind = (new Bind())->bindInterceptors('passIterator', [new NullInterceptor()]); $mock = $this->compiler->newInstance(FakeTypedMockGrandChild::class, [], $bind); assert($mock instanceof FakeTypedMockGrandChild); - assert(property_exists($mock, 'state')); - $mock->state->bindings = $bind->getBindings(); + assert(property_exists($mock, '_state')); + $mock->_state->bindings = $bind->getBindings(); $result = $mock->passIterator(new ArrayIterator()); $this->assertInstanceOf(ArrayIterator::class, $result); } @@ -138,8 +137,8 @@ public function testParentOfParentMethodIntercept(): void { $mock = $this->compiler->newInstance(FakeMockChildChild::class, [], $this->bind); assert($mock instanceof FakeMockChild); - assert(property_exists($mock, 'state')); - $mock->state->bindings = $this->bind->getBindings(); + assert(property_exists($mock, '_state')); + $mock->_state->bindings = $this->bind->getBindings(); $result = $mock->returnSame(1); $this->assertSame(2, $result); } From 9aa197c7876e52ffb74c2c2ae41b4747c3f33c5c Mon Sep 17 00:00:00 2001 From: Akihito Koriyama Date: Fri, 14 Feb 2025 02:01:08 +0900 Subject: [PATCH 6/8] Refactor `_state` property to private visibility. Changed `_state` visibility from public to private in `InterceptTrait` and `Php82InterceptTrait`. Updated tests to remove direct modifications to `_state`, ensuring encapsulation and adherence to best practices. --- src-php8/Php82InterceptTrait.php | 3 +-- src/InterceptTrait.php | 3 +-- tests/CompilerTest.php | 4 ---- 3 files changed, 2 insertions(+), 8 deletions(-) diff --git a/src-php8/Php82InterceptTrait.php b/src-php8/Php82InterceptTrait.php index 377acc75..600360f0 100644 --- a/src-php8/Php82InterceptTrait.php +++ b/src-php8/Php82InterceptTrait.php @@ -15,9 +15,8 @@ trait Php82InterceptTrait { /** * @var InterceptTraitState - * @internal Public for CompilerTest */ - public readonly InterceptTraitState $_state; + private readonly InterceptTraitState $_state; /** * @param array> $bindings diff --git a/src/InterceptTrait.php b/src/InterceptTrait.php index 888ce6a8..1432bd16 100644 --- a/src/InterceptTrait.php +++ b/src/InterceptTrait.php @@ -14,9 +14,8 @@ trait InterceptTrait /** * @var InterceptTraitState * @readonly - * @internal Public for CompilerTest */ - public $_state; + private $_state; /** * @param MethodBindings $bindings diff --git a/tests/CompilerTest.php b/tests/CompilerTest.php index 08cd5489..a2bc6db7 100644 --- a/tests/CompilerTest.php +++ b/tests/CompilerTest.php @@ -78,8 +78,6 @@ public function testParentClassName(object $class): void /** @depends testNewInstance */ public function testBuildClassWeaved(FakeMock $weaved): void { - assert(property_exists($weaved, '_state')); - $weaved->_state->bindings = $this->bind->getBindings(); $result = $weaved->returnSame(1); $this->assertSame(2, $result); } @@ -128,7 +126,6 @@ public function testTypedParentMethodIntercept(): void $mock = $this->compiler->newInstance(FakeTypedMockGrandChild::class, [], $bind); assert($mock instanceof FakeTypedMockGrandChild); assert(property_exists($mock, '_state')); - $mock->_state->bindings = $bind->getBindings(); $result = $mock->passIterator(new ArrayIterator()); $this->assertInstanceOf(ArrayIterator::class, $result); } @@ -138,7 +135,6 @@ public function testParentOfParentMethodIntercept(): void $mock = $this->compiler->newInstance(FakeMockChildChild::class, [], $this->bind); assert($mock instanceof FakeMockChild); assert(property_exists($mock, '_state')); - $mock->_state->bindings = $this->bind->getBindings(); $result = $mock->returnSame(1); $this->assertSame(2, $result); } From 20f917ec811020da4b55b35e0cf7334e8628bbc8 Mon Sep 17 00:00:00 2001 From: Akihito Koriyama Date: Fri, 14 Feb 2025 02:17:59 +0900 Subject: [PATCH 7/8] Simplify constructor for InterceptTraitState Removed the unnecessary `isAspect` parameter from the InterceptTraitState constructor and set its default value directly in the class property. This simplifies the initialization process and reduces redundant arguments. --- src-php8/Php82InterceptTrait.php | 2 +- src/InterceptTrait.php | 3 ++- src/InterceptTraitState.php | 13 +++++-------- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/src-php8/Php82InterceptTrait.php b/src-php8/Php82InterceptTrait.php index 600360f0..3afc51e5 100644 --- a/src-php8/Php82InterceptTrait.php +++ b/src-php8/Php82InterceptTrait.php @@ -25,7 +25,7 @@ trait Php82InterceptTrait */ public function _initState(array $bindings): void { - $this->_state = new InterceptTraitState($bindings, true); + $this->_state = new InterceptTraitState($bindings); } /** diff --git a/src/InterceptTrait.php b/src/InterceptTrait.php index 1432bd16..2eaa9dfe 100644 --- a/src/InterceptTrait.php +++ b/src/InterceptTrait.php @@ -14,6 +14,7 @@ trait InterceptTrait /** * @var InterceptTraitState * @readonly + * @psalm-suppress MissingConstructor */ private $_state; @@ -25,7 +26,7 @@ trait InterceptTrait */ public function _initState(array $bindings): void // phpcs:ignore { - $this->_state = new InterceptTraitState($bindings, true); + $this->_state = new InterceptTraitState($bindings); } /** diff --git a/src/InterceptTraitState.php b/src/InterceptTraitState.php index d1da9f67..38aa63fb 100644 --- a/src/InterceptTraitState.php +++ b/src/InterceptTraitState.php @@ -4,24 +4,21 @@ namespace Ray\Aop; +/** @psalm-import-type MethodBindings from Types */ final class InterceptTraitState { /** - * @var array>> + * @var MethodBindings * @readonly */ public $bindings; /** @var bool */ - public $isAspect; + public $isAspect = true; - /** - * @param array>> $bindings - * @param bool $isAspect - */ - public function __construct($bindings, $isAspect) + /** @param MethodBindings $bindings */ + public function __construct(array $bindings) { $this->bindings = $bindings; - $this->isAspect = $isAspect; } } From 105a980ac1c003305890d9fe807e3491c00afbea Mon Sep 17 00:00:00 2001 From: Akihito Koriyama Date: Fri, 14 Feb 2025 02:26:18 +0900 Subject: [PATCH 8/8] Refactor type annotations in Php82InterceptTrait Replaced explicit type definitions with imported Psalm type aliases for better readability and maintainability. Updated method parameter annotations to use `MethodBindings` and `Arguments` from the `Types` class. --- src-php8/Php82InterceptTrait.php | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src-php8/Php82InterceptTrait.php b/src-php8/Php82InterceptTrait.php index 3afc51e5..44433319 100644 --- a/src-php8/Php82InterceptTrait.php +++ b/src-php8/Php82InterceptTrait.php @@ -9,17 +9,15 @@ use function call_user_func_array; /** - * WARNING: All properties in this trait must be readonly to allow its use in a readonly class. + * @psalm-import-type MethodBindings from Types + * @psalm-import-type Arguments from Types */ trait Php82InterceptTrait { - /** - * @var InterceptTraitState - */ private readonly InterceptTraitState $_state; /** - * @param array> $bindings + * @param MethodBindings $bindings * * @see WeavedInterface::_initState() */ @@ -29,7 +27,7 @@ public function _initState(array $bindings): void } /** - * @param array $args + * @param Arguments $args * * @return mixed *