diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7511b967..8b45824e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,7 @@ Changelog
* [Feature] `self::` in proxied classes now resolves to the proxy class naturally (via PHP trait semantics), removing the need for `SelfValueTransformer`.
* [Feature] **First-class callable syntax** — generated proxy code and invocation constructors use PHP 8.1+ first-class callable syntax (`$this->__aop__method(...)`, `parent::method(...)`, `\func(...)`) to reference original method and function bodies, eliminating the need for `Closure::bind` at construction time.
* [BC BREAK] Removed DeclareError support, including the `DeclareError` attribute, `DeclareErrorInterceptor`, and `PointcutBuilder::declareError()`. Use `Before` or `Around` interceptors to emit user warnings or throw exceptions instead.
+* [BC BREAK] Removed support for the "dynamic" pointcut (`dynamic(public Foo->method*(*))`), including `MagicMethodDynamicPointcut`, `DynamicInvocationMatcherInterceptor`, the `Pointcut::KIND_DYNAMIC` constant and the `$instanceOrScope`/`$arguments` parameters of `Pointcut::matches()`. Use a traditional execution pointcut for the magic methods instead, e.g. `execution(public Foo->__call(*))` or `execution(public Foo::__callStatic(*))`, and check the invoked method name from `$invocation->getArguments()[0]` inside the advice.
* [Removed] `SelfValueTransformer` and `SelfValueVisitor` — no longer needed with the trait-based engine.
* [Performance] **Direct static joinpoint initialization** — leveraging PHP 8.3+ support for dynamic expressions in static variable initializers, all generated proxy method bodies now initialize their static joinpoint variables directly.
diff --git a/demos/Demo/Aspect/DynamicMethodsAspect.php b/demos/Demo/Aspect/DynamicMethodsAspect.php
index e93294d2..957295e2 100644
--- a/demos/Demo/Aspect/DynamicMethodsAspect.php
+++ b/demos/Demo/Aspect/DynamicMethodsAspect.php
@@ -17,21 +17,27 @@
use Go\Lang\Attribute\Before;
/**
- * Aspect that intercepts specific magic methods, declared with __call and __callStatic
+ * Aspect that intercepts magic methods, declared with __call and __callStatic
+ *
+ * Traditional "execution" pointcuts match the magic method itself, so the real method name
+ * should be extracted from the invocation arguments and filtered inside the advice.
*/
class DynamicMethodsAspect implements Aspect
{
/**
- * This advice intercepts an execution of __call methods
+ * This advice intercepts an execution of __call method
*
- * Unlike traditional "execution" pointcut, "dynamic" is checking the name of method in
- * the runtime, allowing to write interceptors for __call more transparently.
+ * The name of the invoked method is the first invocation argument,
+ * so we filter interesting methods (save*) right inside the advice.
*/
- #[Before('dynamic(public Demo\Example\DynamicMethodsDemo->save*(*))')]
+ #[Before('execution(public Demo\Example\DynamicMethodsDemo->__call(*))')]
public function beforeMagicMethodExecution(MethodInvocation $invocation): void
{
// we need to unpack args from invocation args
[$methodName, $args] = $invocation->getArguments();
+ if (!str_starts_with($methodName, 'save')) {
+ return;
+ }
echo 'Calling Magic Interceptor for method: ',
$invocation->getScope(),
'->',
@@ -45,11 +51,14 @@ public function beforeMagicMethodExecution(MethodInvocation $invocation): void
/**
* This advice intercepts an execution of methods via __callStatic
*/
- #[Before('dynamic(public Demo\Example\DynamicMethodsDemo::find*(*))')]
+ #[Before('execution(public Demo\Example\DynamicMethodsDemo::__callStatic(*))')]
public function beforeMagicStaticMethodExecution(MethodInvocation $invocation): void
{
// we need to unpack args from invocation args
[$methodName, $args] = $invocation->getArguments();
+ if (!str_starts_with($methodName, 'find')) {
+ return;
+ }
echo 'Calling Static Magic Interceptor for method: ',
$invocation->getScope(),
'::',
diff --git a/demos/index.php b/demos/index.php
index ee1ae71b..e58c8563 100644
--- a/demos/index.php
+++ b/demos/index.php
@@ -170,7 +170,7 @@
$example = new DynamicMethodsDemo();
$example->saveById(123); // intercept magic dynamic method
- $example->load(456); // notice, that advice for this magic method is not called
+ $example->load(456); // notice, that advice filters out this method by name
DynamicMethodsDemo::find(['id' =>124]); //intercept magic static method
break;
diff --git a/src/Aop/AGENTS.md b/src/Aop/AGENTS.md
index 9caf9c28..ba208f5f 100644
--- a/src/Aop/AGENTS.md
+++ b/src/Aop/AGENTS.md
@@ -37,7 +37,7 @@ Proxy generators use TypeGenerator::renderTypeForPhpDoc() to emit V as 2nd gener
## Pointcuts (src/Aop/Pointcut/)
- LALR grammar: PointcutGrammar, PointcutParser, PointcutLexer, PointcutParseTable
-- Combinators: AndPointcut, OrPointcut, NotPointcut, NamePointcut, AttributePointcut, ClassInheritancePointcut, MatchInheritedPointcut, ModifierPointcut, ReturnTypePointcut, MagicMethodDynamicPointcut, TruePointcut
+- Combinators: AndPointcut, OrPointcut, NotPointcut, NamePointcut, AttributePointcut, ClassInheritancePointcut, MatchInheritedPointcut, ModifierPointcut, ReturnTypePointcut, TruePointcut
- PointcutReference, ClassMemberReference
## Attributes (src/Lang/Attribute/)
diff --git a/src/Aop/Framework/DynamicInvocationMatcherInterceptor.php b/src/Aop/Framework/DynamicInvocationMatcherInterceptor.php
deleted file mode 100644
index 12e53666..00000000
--- a/src/Aop/Framework/DynamicInvocationMatcherInterceptor.php
+++ /dev/null
@@ -1,50 +0,0 @@
-
- *
- * This source file is subject to the license that is bundled
- * with this source code in the file LICENSE.
- */
-
-namespace Go\Aop\Framework;
-
-use Go\Aop\Intercept\Interceptor;
-use Go\Aop\Intercept\Joinpoint;
-use Go\Aop\Intercept\MethodInvocation;
-use Go\Aop\Pointcut;
-use ReflectionClass;
-
-/**
- * Dynamic invocation matcher combines a pointcut and interceptor.
- *
- * For each invocation interceptor asks the pointcut if it matches the invocation.
- * Matcher will receive reflection point, object instance and invocation arguments to make a decision
- */
-readonly class DynamicInvocationMatcherInterceptor implements Interceptor
-{
- /**
- * Dynamic invocation matcher constructor
- */
- public function __construct(
- private Pointcut $pointcut,
- private Interceptor $interceptor
- ){}
-
- final public function invoke(Joinpoint $joinpoint): mixed
- {
- if ($joinpoint instanceof MethodInvocation) {
- $method = $joinpoint->getMethod();
- $context = $joinpoint->getThis() ?? $joinpoint->getScope();
- $contextClass = new ReflectionClass($context);
- if ($this->pointcut->matches($contextClass, $method, $context, $joinpoint->getArguments())) {
- return $this->interceptor->invoke($joinpoint);
- }
- }
-
- return $joinpoint->proceed();
- }
-}
diff --git a/src/Aop/Pointcut.php b/src/Aop/Pointcut.php
index 02787d81..b3545ad1 100644
--- a/src/Aop/Pointcut.php
+++ b/src/Aop/Pointcut.php
@@ -19,14 +19,11 @@
use ReflectionProperty;
/**
- * Pointcut is responsible for matching any reflection items both statically and dynamically.
+ * Pointcut is responsible for matching any reflection items statically.
*
- * Pointcut may be evaluated statically or at runtime (dynamically).
* Matcher uses smart technique of matching elements, consisting of several stages described below.
*
- * Static matching
- *
- * First stage of static matching involves context only (just one argument). This pre-stage is used to optimize
+ * First stage of matching involves context only (just one argument). This pre-stage is used to optimize
* filtering on matcher side to avoid nested loops of checks. For example, if we have a method pointcut, but
* it doesn't match first with class, then we don't need to scan all methods at all and can exit earlier.
*
@@ -35,21 +32,13 @@
* - For any functions, context will be `ReflectionFileNamespace` where internal function is analyzed.
* - For any methods or properties, context will be `ReflectionClass` which is currently analysed (even for inherited items)
*
- * Second stage of static matching uses exactly two arguments (context and reflector). Filter then fully checks
+ * Second stage of matching uses exactly two arguments (context and reflector). Filter then fully checks
* static information from reflection to make a decision about matching of given point.
*
* At this stage we can verify names, attributes, signature, parameters, types, etc.
*
- * If point filter is not dynamic {@see self::KIND_DYNAMIC}, then evaluation ends here statically,
- * and generated code will not contain any runtime checks for given point filter, allowing for better performance.
- *
- * Dynamic matching
- *
- * If instance of filter is dynamic and uses {@see self::KIND_DYNAMIC} flag, then after static matching which has been
- * used to prepare a dynamic hook, framework will call our pointcut again in runtime for dynamic matching.
- *
- * This dynamic matching stage uses full information about given join point, including possible instance/scope and
- * arguments for a particular point.
+ * Evaluation ends here statically, and generated code will not contain any runtime checks
+ * for given point filter, allowing for better performance.
*/
interface Pointcut
{
@@ -61,7 +50,6 @@ interface Pointcut
public const KIND_INIT = 32;
public const KIND_STATIC_INIT = 64;
public const KIND_ALL = 127;
- public const KIND_DYNAMIC = 256;
public const KIND_INTRODUCTION = 512;
/**
@@ -74,15 +62,11 @@ public function getKind(): int;
*
* @param ReflectionClass|ReflectionFileNamespace $context Related context, can be class or file namespace
* @param ReflectionMethod|ReflectionProperty|ReflectionFunction|null $reflector Specific part of code, can be any Reflection class
- * @param null|class-string|T $instanceOrScope Invocation instance or string for static calls
- * @param null|array $arguments Dynamic arguments for method
*
* @template T of object
*/
public function matches(
ReflectionClass|ReflectionFileNamespace $context,
- ReflectionMethod|ReflectionProperty|ReflectionFunction|null $reflector = null,
- null|object|string $instanceOrScope = null,
- ?array $arguments = null
+ ReflectionMethod|ReflectionProperty|ReflectionFunction|null $reflector = null
): bool;
}
\ No newline at end of file
diff --git a/src/Aop/Pointcut/AndPointcut.php b/src/Aop/Pointcut/AndPointcut.php
index 3d53a353..e9545b20 100644
--- a/src/Aop/Pointcut/AndPointcut.php
+++ b/src/Aop/Pointcut/AndPointcut.php
@@ -54,12 +54,10 @@ public function __construct(?int $pointcutKind = null, Pointcut ...$pointcuts)
public function matches(
ReflectionClass|ReflectionFileNamespace $context,
- ReflectionMethod|ReflectionProperty|ReflectionFunction|null $reflector = null,
- null|object|string $instanceOrScope = null,
- ?array $arguments = null
+ ReflectionMethod|ReflectionProperty|ReflectionFunction|null $reflector = null
): bool {
foreach ($this->pointcuts as $singlePointcut) {
- if (!$singlePointcut->matches($context, $reflector, $instanceOrScope, $arguments)) {
+ if (!$singlePointcut->matches($context, $reflector)) {
return false;
}
}
diff --git a/src/Aop/Pointcut/AttributePointcut.php b/src/Aop/Pointcut/AttributePointcut.php
index a9d23c51..2b84e5a4 100644
--- a/src/Aop/Pointcut/AttributePointcut.php
+++ b/src/Aop/Pointcut/AttributePointcut.php
@@ -43,9 +43,7 @@ public function __construct(
final public function matches(
ReflectionClass|ReflectionFileNamespace $context,
- ReflectionMethod|ReflectionProperty|ReflectionFunction|null $reflector = null,
- null|object|string $instanceOrScope = null,
- ?array $arguments = null
+ ReflectionMethod|ReflectionProperty|ReflectionFunction|null $reflector = null
): bool {
// If we don't use context for matching and we do static check, then always match
if (!$this->useContextForMatching && !isset($reflector)) {
diff --git a/src/Aop/Pointcut/ClassInheritancePointcut.php b/src/Aop/Pointcut/ClassInheritancePointcut.php
index 44e4bbb3..85de9bba 100644
--- a/src/Aop/Pointcut/ClassInheritancePointcut.php
+++ b/src/Aop/Pointcut/ClassInheritancePointcut.php
@@ -33,9 +33,7 @@ public function __construct(private string $parentClassOrInterfaceName) {}
public function matches(
ReflectionClass|ReflectionFileNamespace $context,
- ReflectionMethod|ReflectionProperty|ReflectionFunction|null $reflector = null,
- null|object|string $instanceOrScope = null,
- ?array $arguments = null
+ ReflectionMethod|ReflectionProperty|ReflectionFunction|null $reflector = null
): bool {
// We match only with ReflectionClass as a context
if (!$context instanceof ReflectionClass) {
diff --git a/src/Aop/Pointcut/MagicMethodDynamicPointcut.php b/src/Aop/Pointcut/MagicMethodDynamicPointcut.php
deleted file mode 100644
index df23f696..00000000
--- a/src/Aop/Pointcut/MagicMethodDynamicPointcut.php
+++ /dev/null
@@ -1,93 +0,0 @@
-
- *
- * This source file is subject to the license that is bundled
- * with this source code in the file LICENSE.
- */
-
-namespace Go\Aop\Pointcut;
-
-use Go\Aop\Pointcut;
-use Go\ParserReflection\ReflectionFileNamespace;
-use ReflectionClass;
-use ReflectionFunction;
-use ReflectionMethod;
-use ReflectionProperty;
-
-/**
- * Magic method pointcut is a dynamic checker that verifies calls for __call and __callStatic
- *
- * With one (or two) arguments it always statically matches with __call and __callStatic methods.
- * With four arguments, it takes real argument for invocation and matches it again dynamically.
- */
-final readonly class MagicMethodDynamicPointcut implements Pointcut
-{
- /**
- * Compiled regular expression for matching
- */
- private string $regexp;
-
- /**
- * Magic method matcher constructor
- *
- * @param string $methodName Method name to match, can contain wildcards "*","?" or "|"
- */
- public function __construct(private string $methodName) {
- $this->regexp = '/^(' . strtr(
- preg_quote($this->methodName, '/'),
- [
- '\\*' => '.*?',
- '\\?' => '.',
- '\\|' => '|'
- ]
- ) . ')$/';
- }
-
- public function matches(
- ReflectionClass|ReflectionFileNamespace $context,
- ReflectionMethod|ReflectionProperty|ReflectionFunction|null $reflector = null,
- null|object|string $instanceOrScope = null,
- ?array $arguments = null
- ): bool {
- // Magic methods can be only inside class context
- if (!$context instanceof ReflectionClass) {
- return false;
- }
-
- // For pre-filter we match only with context that has magic methods
- if (!isset($reflector)) {
- return $context->hasMethod('__call') || $context->hasMethod('__callStatic');
- }
-
- // If we receive something not expected here (ReflectionMethod), we should not match
- if (!$reflector instanceof ReflectionMethod) {
- return false;
- }
-
- // With single parameter (statically) always matches for __call, __callStatic methods
- if ($instanceOrScope === null) {
- return ($reflector->name === '__call' || $reflector->name === '__callStatic');
- }
-
- // If for some reason we don't have arguments, or first argument is not a string with valid function name
- if (!isset($arguments) || count($arguments) < 1 || !is_string($arguments[0])) {
- return false;
- }
-
- // for __call and __callStatic method name is the first argument on invocation
- [$methodName] = $arguments;
-
- // Perform final dynamic check
- return ($methodName === $this->methodName) || preg_match($this->regexp, $methodName);
- }
-
- public function getKind(): int
- {
- return Pointcut::KIND_METHOD | Pointcut::KIND_DYNAMIC;
- }
-}
diff --git a/src/Aop/Pointcut/MatchInheritedPointcut.php b/src/Aop/Pointcut/MatchInheritedPointcut.php
index b1408332..e183db50 100644
--- a/src/Aop/Pointcut/MatchInheritedPointcut.php
+++ b/src/Aop/Pointcut/MatchInheritedPointcut.php
@@ -28,9 +28,7 @@ final class MatchInheritedPointcut implements Pointcut
{
public function matches(
ReflectionClass|ReflectionFileNamespace $context,
- ReflectionMethod|ReflectionProperty|ReflectionFunction|null $reflector = null,
- null|object|string $instanceOrScope = null,
- ?array $arguments = null
+ ReflectionMethod|ReflectionProperty|ReflectionFunction|null $reflector = null
): bool {
// Inherited items can be only inside class context
if (!$context instanceof ReflectionClass) {
diff --git a/src/Aop/Pointcut/ModifierPointcut.php b/src/Aop/Pointcut/ModifierPointcut.php
index 97db3767..653148f3 100644
--- a/src/Aop/Pointcut/ModifierPointcut.php
+++ b/src/Aop/Pointcut/ModifierPointcut.php
@@ -54,9 +54,7 @@ public function __construct(int $initialMask = 0)
*/
public function matches(
ReflectionClass|ReflectionFileNamespace $context,
- ReflectionMethod|ReflectionProperty|ReflectionFunction|null $reflector = null,
- null|object|string $instanceOrScope = null,
- ?array $arguments = null
+ ReflectionMethod|ReflectionProperty|ReflectionFunction|null $reflector = null
): bool {
// With context only we always match, as we don't know about modifiers of given reflector
if (!isset($reflector)) {
diff --git a/src/Aop/Pointcut/NamePointcut.php b/src/Aop/Pointcut/NamePointcut.php
index a576bdcf..b54bf735 100644
--- a/src/Aop/Pointcut/NamePointcut.php
+++ b/src/Aop/Pointcut/NamePointcut.php
@@ -54,9 +54,7 @@ public function __construct(
public function matches(
ReflectionClass|ReflectionFileNamespace $context,
- ReflectionMethod|ReflectionProperty|ReflectionFunction|null $reflector = null,
- null|object|string $instanceOrScope = null,
- ?array $arguments = null
+ ReflectionMethod|ReflectionProperty|ReflectionFunction|null $reflector = null
): bool {
// Let's determine what will be used for matching - context or reflector
if ($this->useContextForMatching) {
diff --git a/src/Aop/Pointcut/NotPointcut.php b/src/Aop/Pointcut/NotPointcut.php
index 71917c65..f0845f58 100644
--- a/src/Aop/Pointcut/NotPointcut.php
+++ b/src/Aop/Pointcut/NotPointcut.php
@@ -34,17 +34,15 @@ public function __construct(private Pointcut $pointcut) {}
*/
public function matches(
ReflectionClass|ReflectionFileNamespace $context,
- ReflectionMethod|ReflectionProperty|ReflectionFunction|null $reflector = null,
- null|object|string $instanceOrScope = null,
- ?array $arguments = null
+ ReflectionMethod|ReflectionProperty|ReflectionFunction|null $reflector = null
): bool {
// For Logical "not" expression without reflector, we should match statically for any context
if (!isset($reflector)) {
return true;
}
- // Otherwise we return inverted result from static/dynamic matching
- return !$this->pointcut->matches($context, $reflector, $instanceOrScope, $arguments);
+ // Otherwise we return inverted result from static matching
+ return !$this->pointcut->matches($context, $reflector);
}
public function getKind(): int
diff --git a/src/Aop/Pointcut/OrPointcut.php b/src/Aop/Pointcut/OrPointcut.php
index 7dc9f509..9a9457f2 100644
--- a/src/Aop/Pointcut/OrPointcut.php
+++ b/src/Aop/Pointcut/OrPointcut.php
@@ -51,12 +51,10 @@ public function __construct(Pointcut ...$pointcuts)
public function matches(
ReflectionClass|ReflectionFileNamespace $context,
- ReflectionMethod|ReflectionProperty|ReflectionFunction|null $reflector = null,
- null|object|string $instanceOrScope = null,
- ?array $arguments = null
+ ReflectionMethod|ReflectionProperty|ReflectionFunction|null $reflector = null
): bool {
foreach ($this->pointcuts as $singlePointcut) {
- if ($singlePointcut->matches($context, $reflector, $instanceOrScope, $arguments)) {
+ if ($singlePointcut->matches($context, $reflector)) {
return true;
}
}
diff --git a/src/Aop/Pointcut/PointcutGrammar.php b/src/Aop/Pointcut/PointcutGrammar.php
index a5c8f676..277162b5 100644
--- a/src/Aop/Pointcut/PointcutGrammar.php
+++ b/src/Aop/Pointcut/PointcutGrammar.php
@@ -68,7 +68,6 @@ public function __construct(AspectContainer $container)
->is('annotatedWithinPointcut')
->is('initializationPointcut')
->is('staticInitializationPointcut')
- ->is('dynamicExecutionPointcut')
->is('matchInheritedPointcut')
->is('pointcutReference')
;
@@ -153,24 +152,6 @@ function (mixed $_0, mixed $_1, Pointcut $classFilter) {
->call(fn(mixed ...$_) => new MatchInheritedPointcut())
;
- $this('dynamicExecutionPointcut')
- // ideally, this should be 'dynamic', 'methodExecutionReference'
- ->is('dynamic', '(', 'memberReference', '(', 'argumentList', ')', ')')
- ->call(
- function ($_0, $_1, ClassMemberReference $reference) {
- $pointcut = new AndPointcut(
- Pointcut::KIND_METHOD | Pointcut::KIND_DYNAMIC,
- $reference->classFilter,
- $reference->visibilityFilter,
- $reference->accessTypeFilter,
- new MagicMethodDynamicPointcut($reference->memberNamePattern)
- );
-
- return $pointcut;
- }
- )
- ;
-
$this('pointcutReference')
->is('namespaceName', '->', 'namePatternPart')
->call(fn(string $className, mixed $_0, string $name) => new PointcutReference($container, "{$className}->{$name}"))
diff --git a/src/Aop/Pointcut/PointcutLexer.php b/src/Aop/Pointcut/PointcutLexer.php
index 2293df21..a6239f40 100644
--- a/src/Aop/Pointcut/PointcutLexer.php
+++ b/src/Aop/Pointcut/PointcutLexer.php
@@ -26,7 +26,6 @@ public function __construct()
{
// General tokens
$this->token('execution');
- $this->token('dynamic');
$this->token('within');
$this->token('access');
$this->token('initialization');
diff --git a/src/Aop/Pointcut/PointcutParseTable.php b/src/Aop/Pointcut/PointcutParseTable.php
index 98dab96f..9ee5bf1f 100644
--- a/src/Aop/Pointcut/PointcutParseTable.php
+++ b/src/Aop/Pointcut/PointcutParseTable.php
@@ -12,4 +12,4 @@
/**
* This table was generated for production use, do not touch it
*/
-return ['action' => [0 => ['!' => 4, '(' => 6, 'access' => 19, 'annotation' => 20, 'execution' => 21, 'within' => 22, 'initialization' => 23, 'staticinitialization' => 24, 'dynamic' => 25, 'matchInherited' => 26, 'namePart' => 28,], 1 => ['||' => 29, '$eof' => 0,], 2 => ['&&' => 30, '$eof' => -3, '||' => -3, ')' => -3,], 4 => ['(' => 6, 'access' => 19, 'annotation' => 20, 'execution' => 21, 'within' => 22, 'initialization' => 23, 'staticinitialization' => 24, 'dynamic' => 25, 'matchInherited' => 26, 'namePart' => 28,], 6 => ['!' => 4, '(' => 6, 'access' => 19, 'annotation' => 20, 'execution' => 21, 'within' => 22, 'initialization' => 23, 'staticinitialization' => 24, 'dynamic' => 25, 'matchInherited' => 26, 'namePart' => 28,], 19 => ['(' => 33,], 20 => ['access' => 34, 'execution' => 35, 'within' => 36,], 21 => ['(' => 37,], 22 => ['(' => 38,], 23 => ['(' => 39,], 24 => ['(' => 40,], 25 => ['(' => 41,], 26 => ['(' => 42,], 27 => ['->' => 43, 'nsSeparator' => 44,], 29 => ['!' => 4, '(' => 6, 'access' => 19, 'annotation' => 20, 'execution' => 21, 'within' => 22, 'initialization' => 23, 'staticinitialization' => 24, 'dynamic' => 25, 'matchInherited' => 26, 'namePart' => 28,], 30 => ['!' => 4, '(' => 6, 'access' => 19, 'annotation' => 20, 'execution' => 21, 'within' => 22, 'initialization' => 23, 'staticinitialization' => 24, 'dynamic' => 25, 'matchInherited' => 26, 'namePart' => 28,], 32 => [')' => 47, '||' => 29,], 33 => ['public' => 52, 'protected' => 53, 'private' => 54, 'final' => 55,], 34 => ['(' => 56,], 35 => ['(' => 57,], 36 => ['(' => 58,], 37 => ['**' => 63, '*' => 65, 'namePart' => 66, 'public' => 52, 'protected' => 53, 'private' => 54, 'final' => 55,], 38 => ['**' => 63, '*' => 65, 'namePart' => 66,], 39 => ['**' => 63, '*' => 65, 'namePart' => 66,], 40 => ['**' => 63, '*' => 65, 'namePart' => 66,], 41 => ['public' => 52, 'protected' => 53, 'private' => 54, 'final' => 55,], 42 => [')' => 72,], 43 => ['*' => 65, 'namePart' => 66,], 44 => ['namePart' => 74,], 45 => ['&&' => 30, '$eof' => -2, '||' => -2, ')' => -2,], 48 => [')' => 75,], 50 => ['**' => 63, '*' => 65, 'namePart' => 66,], 51 => ['|' => 77, 'public' => 52, 'protected' => 53, 'private' => 54, 'final' => 55, '**' => -57, '*' => -57, 'namePart' => -57,], 56 => ['namePart' => 28,], 57 => ['namePart' => 28,], 58 => ['namePart' => 28,], 59 => [')' => 82,], 60 => [')' => 83,], 61 => ['(' => 84,], 62 => ['nsSeparator' => 85,], 64 => ['*' => 86, 'namePart' => 87, '|' => 88, 'nsSeparator' => -45, ')' => -45, '+' => -45, '::' => -45, '->' => -45,], 67 => [')' => 89,], 68 => ['+' => 90, 'nsSeparator' => 91, ')' => -39, '::' => -39, '->' => -39,], 69 => [')' => 92,], 70 => [')' => 93,], 71 => ['(' => 94,], 73 => ['*' => 86, 'namePart' => 87, '|' => 88, '$eof' => -32, '||' => -32, '&&' => -32, ')' => -32,], 76 => ['::' => 96, '->' => 97,], 77 => ['public' => 52, 'protected' => 53, 'private' => 54, 'final' => 55,], 79 => [')' => 99, 'nsSeparator' => 44,], 80 => [')' => 100, 'nsSeparator' => 44,], 81 => [')' => 101, 'nsSeparator' => 44,], 84 => ['*' => 103,], 85 => ['**' => 105, '*' => 65, 'namePart' => 66,], 88 => ['namePart' => 106,], 91 => ['**' => 105, '*' => 65, 'namePart' => 66,], 94 => ['*' => 103,], 95 => ['*' => 65, 'namePart' => 66,], 102 => [')' => 110,], 104 => ['(' => 111, '*' => 86, 'namePart' => 87, '|' => 88, 'nsSeparator' => -46,], 107 => ['*' => 86, 'namePart' => 87, '|' => 88, ')' => -46, '+' => -46, 'nsSeparator' => -46, '::' => -46, '->' => -46,], 108 => [')' => 112,], 109 => ['*' => 86, 'namePart' => 87, '|' => 88, ')' => -38, '(' => -38,], 110 => [':' => 113, ')' => -34,], 111 => ['*' => 103,], 112 => [')' => 115,], 113 => ['namePart' => 28,], 114 => [')' => 117,], 116 => ['nsSeparator' => 44, ')' => -35,], 117 => [':' => 118, ')' => -36,], 118 => ['namePart' => 28,], 119 => ['nsSeparator' => 44, ')' => -37,], 3 => ['$eof' => -5, '||' => -5, '&&' => -5, ')' => -5,], 5 => ['$eof' => -7, '||' => -7, '&&' => -7, ')' => -7,], 7 => ['$eof' => -9, '||' => -9, '&&' => -9, ')' => -9,], 8 => ['$eof' => -10, '||' => -10, '&&' => -10, ')' => -10,], 9 => ['$eof' => -11, '||' => -11, '&&' => -11, ')' => -11,], 10 => ['$eof' => -12, '||' => -12, '&&' => -12, ')' => -12,], 11 => ['$eof' => -13, '||' => -13, '&&' => -13, ')' => -13,], 12 => ['$eof' => -14, '||' => -14, '&&' => -14, ')' => -14,], 13 => ['$eof' => -15, '||' => -15, '&&' => -15, ')' => -15,], 14 => ['$eof' => -16, '||' => -16, '&&' => -16, ')' => -16,], 15 => ['$eof' => -17, '||' => -17, '&&' => -17, ')' => -17,], 16 => ['$eof' => -18, '||' => -18, '&&' => -18, ')' => -18,], 17 => ['$eof' => -19, '||' => -19, '&&' => -19, ')' => -19,], 18 => ['$eof' => -20, '||' => -20, '&&' => -20, ')' => -20,], 28 => ['->' => -53, 'nsSeparator' => -53, ')' => -53,], 31 => ['$eof' => -6, '||' => -6, '&&' => -6, ')' => -6,], 46 => ['$eof' => -4, '||' => -4, '&&' => -4, ')' => -4,], 47 => ['$eof' => -8, '||' => -8, '&&' => -8, ')' => -8,], 49 => [')' => -33,], 52 => ['**' => -58, '*' => -58, 'namePart' => -58, '|' => -58, 'public' => -58, 'protected' => -58, 'private' => -58, 'final' => -58,], 53 => ['**' => -59, '*' => -59, 'namePart' => -59, '|' => -59, 'public' => -59, 'protected' => -59, 'private' => -59, 'final' => -59,], 54 => ['**' => -60, '*' => -60, 'namePart' => -60, '|' => -60, 'public' => -60, 'protected' => -60, 'private' => -60, 'final' => -60,], 55 => ['**' => -61, '*' => -61, 'namePart' => -61, '|' => -61, 'public' => -61, 'protected' => -61, 'private' => -61, 'final' => -61,], 63 => ['nsSeparator' => -44, ')' => -44, '+' => -44, '::' => -44, '->' => -44,], 65 => ['$eof' => -48, '||' => -48, '&&' => -48, ')' => -48, '(' => -48, 'nsSeparator' => -48, '*' => -48, 'namePart' => -48, '|' => -48, '+' => -48, '::' => -48, '->' => -48,], 66 => ['$eof' => -49, '||' => -49, '&&' => -49, ')' => -49, '(' => -49, 'nsSeparator' => -49, '*' => -49, 'namePart' => -49, '|' => -49, '+' => -49, '::' => -49, '->' => -49,], 72 => ['$eof' => -30, '||' => -30, '&&' => -30, ')' => -30,], 74 => ['->' => -54, 'nsSeparator' => -54, ')' => -54,], 75 => ['$eof' => -21, '||' => -21, '&&' => -21, ')' => -21,], 78 => ['**' => -56, '*' => -56, 'namePart' => -56,], 82 => ['$eof' => -22, '||' => -22, '&&' => -22, ')' => -22,], 83 => ['$eof' => -23, '||' => -23, '&&' => -23, ')' => -23,], 86 => ['$eof' => -50, '||' => -50, '&&' => -50, ')' => -50, '(' => -50, 'nsSeparator' => -50, '*' => -50, 'namePart' => -50, '|' => -50, '+' => -50, '::' => -50, '->' => -50,], 87 => ['$eof' => -51, '||' => -51, '&&' => -51, ')' => -51, '(' => -51, 'nsSeparator' => -51, '*' => -51, 'namePart' => -51, '|' => -51, '+' => -51, '::' => -51, '->' => -51,], 89 => ['$eof' => -24, '||' => -24, '&&' => -24, ')' => -24,], 90 => [')' => -40, '::' => -40, '->' => -40,], 92 => ['$eof' => -28, '||' => -28, '&&' => -28, ')' => -28,], 93 => ['$eof' => -29, '||' => -29, '&&' => -29, ')' => -29,], 96 => ['*' => -42, 'namePart' => -42,], 97 => ['*' => -43, 'namePart' => -43,], 98 => ['**' => -55, '*' => -55, 'namePart' => -55,], 99 => ['$eof' => -25, '||' => -25, '&&' => -25, ')' => -25,], 100 => ['$eof' => -26, '||' => -26, '&&' => -26, ')' => -26,], 101 => ['$eof' => -27, '||' => -27, '&&' => -27, ')' => -27,], 103 => [')' => -41,], 105 => ['nsSeparator' => -47, ')' => -47, '+' => -47, '::' => -47, '->' => -47,], 106 => ['$eof' => -52, '||' => -52, '&&' => -52, ')' => -52, '(' => -52, 'nsSeparator' => -52, '*' => -52, 'namePart' => -52, '|' => -52, '+' => -52, '::' => -52, '->' => -52,], 115 => ['$eof' => -31, '||' => -31, '&&' => -31, ')' => -31,],], 'goto' => [0 => ['pointcutExpression' => 1, 'conjugatedExpression' => 2, 'negatedExpression' => 3, 'brakedExpression' => 5, 'singlePointcut' => 7, 'accessPointcut' => 8, 'annotatedAccessPointcut' => 9, 'executionPointcut' => 10, 'annotatedExecutionPointcut' => 11, 'withinPointcut' => 12, 'annotatedWithinPointcut' => 13, 'initializationPointcut' => 14, 'staticInitializationPointcut' => 15, 'dynamicExecutionPointcut' => 16, 'matchInheritedPointcut' => 17, 'pointcutReference' => 18, 'namespaceName' => 27,], 4 => ['brakedExpression' => 31, 'singlePointcut' => 7, 'accessPointcut' => 8, 'annotatedAccessPointcut' => 9, 'executionPointcut' => 10, 'annotatedExecutionPointcut' => 11, 'withinPointcut' => 12, 'annotatedWithinPointcut' => 13, 'initializationPointcut' => 14, 'staticInitializationPointcut' => 15, 'dynamicExecutionPointcut' => 16, 'matchInheritedPointcut' => 17, 'pointcutReference' => 18, 'namespaceName' => 27,], 6 => ['pointcutExpression' => 32, 'conjugatedExpression' => 2, 'negatedExpression' => 3, 'brakedExpression' => 5, 'singlePointcut' => 7, 'accessPointcut' => 8, 'annotatedAccessPointcut' => 9, 'executionPointcut' => 10, 'annotatedExecutionPointcut' => 11, 'withinPointcut' => 12, 'annotatedWithinPointcut' => 13, 'initializationPointcut' => 14, 'staticInitializationPointcut' => 15, 'dynamicExecutionPointcut' => 16, 'matchInheritedPointcut' => 17, 'pointcutReference' => 18, 'namespaceName' => 27,], 29 => ['conjugatedExpression' => 45, 'negatedExpression' => 3, 'brakedExpression' => 5, 'singlePointcut' => 7, 'accessPointcut' => 8, 'annotatedAccessPointcut' => 9, 'executionPointcut' => 10, 'annotatedExecutionPointcut' => 11, 'withinPointcut' => 12, 'annotatedWithinPointcut' => 13, 'initializationPointcut' => 14, 'staticInitializationPointcut' => 15, 'dynamicExecutionPointcut' => 16, 'matchInheritedPointcut' => 17, 'pointcutReference' => 18, 'namespaceName' => 27,], 30 => ['negatedExpression' => 46, 'brakedExpression' => 5, 'singlePointcut' => 7, 'accessPointcut' => 8, 'annotatedAccessPointcut' => 9, 'executionPointcut' => 10, 'annotatedExecutionPointcut' => 11, 'withinPointcut' => 12, 'annotatedWithinPointcut' => 13, 'initializationPointcut' => 14, 'staticInitializationPointcut' => 15, 'dynamicExecutionPointcut' => 16, 'matchInheritedPointcut' => 17, 'pointcutReference' => 18, 'namespaceName' => 27,], 33 => ['propertyAccessReference' => 48, 'memberReference' => 49, 'memberModifiers' => 50, 'memberModifier' => 51,], 37 => ['methodExecutionReference' => 59, 'functionExecutionReference' => 60, 'memberReference' => 61, 'namespacePattern' => 62, 'memberModifiers' => 50, 'namePatternPart' => 64, 'memberModifier' => 51,], 38 => ['classFilter' => 67, 'namespacePattern' => 68, 'namePatternPart' => 64,], 39 => ['classFilter' => 69, 'namespacePattern' => 68, 'namePatternPart' => 64,], 40 => ['classFilter' => 70, 'namespacePattern' => 68, 'namePatternPart' => 64,], 41 => ['memberReference' => 71, 'memberModifiers' => 50, 'memberModifier' => 51,], 43 => ['namePatternPart' => 73,], 50 => ['classFilter' => 76, 'namespacePattern' => 68, 'namePatternPart' => 64,], 51 => ['memberModifiers' => 78, 'memberModifier' => 51,], 56 => ['namespaceName' => 79,], 57 => ['namespaceName' => 80,], 58 => ['namespaceName' => 81,], 76 => ['memberAccessType' => 95,], 77 => ['memberModifiers' => 98, 'memberModifier' => 51,], 84 => ['argumentList' => 102,], 85 => ['namePatternPart' => 104,], 91 => ['namePatternPart' => 107,], 94 => ['argumentList' => 108,], 95 => ['namePatternPart' => 109,], 111 => ['argumentList' => 114,], 113 => ['namespaceName' => 116,], 118 => ['namespaceName' => 119,],]];
+return ['action' => [0 => ['!' => 4, '(' => 6, 'access' => 18, 'annotation' => 19, 'execution' => 20, 'within' => 21, 'initialization' => 22, 'staticinitialization' => 23, 'matchInherited' => 24, 'namePart' => 26,], 1 => ['||' => 27, '$eof' => 0,], 2 => ['&&' => 28, '$eof' => -3, '||' => -3, ')' => -3,], 4 => ['(' => 6, 'access' => 18, 'annotation' => 19, 'execution' => 20, 'within' => 21, 'initialization' => 22, 'staticinitialization' => 23, 'matchInherited' => 24, 'namePart' => 26,], 6 => ['!' => 4, '(' => 6, 'access' => 18, 'annotation' => 19, 'execution' => 20, 'within' => 21, 'initialization' => 22, 'staticinitialization' => 23, 'matchInherited' => 24, 'namePart' => 26,], 18 => ['(' => 31,], 19 => ['access' => 32, 'execution' => 33, 'within' => 34,], 20 => ['(' => 35,], 21 => ['(' => 36,], 22 => ['(' => 37,], 23 => ['(' => 38,], 24 => ['(' => 39,], 25 => ['->' => 40, 'nsSeparator' => 41,], 27 => ['!' => 4, '(' => 6, 'access' => 18, 'annotation' => 19, 'execution' => 20, 'within' => 21, 'initialization' => 22, 'staticinitialization' => 23, 'matchInherited' => 24, 'namePart' => 26,], 28 => ['!' => 4, '(' => 6, 'access' => 18, 'annotation' => 19, 'execution' => 20, 'within' => 21, 'initialization' => 22, 'staticinitialization' => 23, 'matchInherited' => 24, 'namePart' => 26,], 30 => [')' => 44, '||' => 27,], 31 => ['public' => 49, 'protected' => 50, 'private' => 51, 'final' => 52,], 32 => ['(' => 53,], 33 => ['(' => 54,], 34 => ['(' => 55,], 35 => ['**' => 60, '*' => 62, 'namePart' => 63, 'public' => 49, 'protected' => 50, 'private' => 51, 'final' => 52,], 36 => ['**' => 60, '*' => 62, 'namePart' => 63,], 37 => ['**' => 60, '*' => 62, 'namePart' => 63,], 38 => ['**' => 60, '*' => 62, 'namePart' => 63,], 39 => [')' => 68,], 40 => ['*' => 62, 'namePart' => 63,], 41 => ['namePart' => 70,], 42 => ['&&' => 28, '$eof' => -2, '||' => -2, ')' => -2,], 45 => [')' => 71,], 47 => ['**' => 60, '*' => 62, 'namePart' => 63,], 48 => ['|' => 73, 'public' => 49, 'protected' => 50, 'private' => 51, 'final' => 52, '**' => -55, '*' => -55, 'namePart' => -55,], 53 => ['namePart' => 26,], 54 => ['namePart' => 26,], 55 => ['namePart' => 26,], 56 => [')' => 78,], 57 => [')' => 79,], 58 => ['(' => 80,], 59 => ['nsSeparator' => 81,], 61 => ['*' => 82, 'namePart' => 83, '|' => 84, 'nsSeparator' => -43, ')' => -43, '+' => -43, '::' => -43, '->' => -43,], 64 => [')' => 85,], 65 => ['+' => 86, 'nsSeparator' => 87, ')' => -37, '::' => -37, '->' => -37,], 66 => [')' => 88,], 67 => [')' => 89,], 69 => ['*' => 82, 'namePart' => 83, '|' => 84, '$eof' => -30, '||' => -30, '&&' => -30, ')' => -30,], 72 => ['::' => 91, '->' => 92,], 73 => ['public' => 49, 'protected' => 50, 'private' => 51, 'final' => 52,], 75 => [')' => 94, 'nsSeparator' => 41,], 76 => [')' => 95, 'nsSeparator' => 41,], 77 => [')' => 96, 'nsSeparator' => 41,], 80 => ['*' => 98,], 81 => ['**' => 100, '*' => 62, 'namePart' => 63,], 84 => ['namePart' => 101,], 87 => ['**' => 100, '*' => 62, 'namePart' => 63,], 90 => ['*' => 62, 'namePart' => 63,], 97 => [')' => 104,], 99 => ['(' => 105, '*' => 82, 'namePart' => 83, '|' => 84, 'nsSeparator' => -44,], 102 => ['*' => 82, 'namePart' => 83, '|' => 84, ')' => -44, '+' => -44, 'nsSeparator' => -44, '::' => -44, '->' => -44,], 103 => ['*' => 82, 'namePart' => 83, '|' => 84, ')' => -36, '(' => -36,], 104 => [':' => 106, ')' => -32,], 105 => ['*' => 98,], 106 => ['namePart' => 26,], 107 => [')' => 109,], 108 => ['nsSeparator' => 41, ')' => -33,], 109 => [':' => 110, ')' => -34,], 110 => ['namePart' => 26,], 111 => ['nsSeparator' => 41, ')' => -35,], 3 => ['$eof' => -5, '||' => -5, '&&' => -5, ')' => -5,], 5 => ['$eof' => -7, '||' => -7, '&&' => -7, ')' => -7,], 7 => ['$eof' => -9, '||' => -9, '&&' => -9, ')' => -9,], 8 => ['$eof' => -10, '||' => -10, '&&' => -10, ')' => -10,], 9 => ['$eof' => -11, '||' => -11, '&&' => -11, ')' => -11,], 10 => ['$eof' => -12, '||' => -12, '&&' => -12, ')' => -12,], 11 => ['$eof' => -13, '||' => -13, '&&' => -13, ')' => -13,], 12 => ['$eof' => -14, '||' => -14, '&&' => -14, ')' => -14,], 13 => ['$eof' => -15, '||' => -15, '&&' => -15, ')' => -15,], 14 => ['$eof' => -16, '||' => -16, '&&' => -16, ')' => -16,], 15 => ['$eof' => -17, '||' => -17, '&&' => -17, ')' => -17,], 16 => ['$eof' => -18, '||' => -18, '&&' => -18, ')' => -18,], 17 => ['$eof' => -19, '||' => -19, '&&' => -19, ')' => -19,], 26 => ['->' => -51, 'nsSeparator' => -51, ')' => -51,], 29 => ['$eof' => -6, '||' => -6, '&&' => -6, ')' => -6,], 43 => ['$eof' => -4, '||' => -4, '&&' => -4, ')' => -4,], 44 => ['$eof' => -8, '||' => -8, '&&' => -8, ')' => -8,], 46 => [')' => -31,], 49 => ['**' => -56, '*' => -56, 'namePart' => -56, '|' => -56, 'public' => -56, 'protected' => -56, 'private' => -56, 'final' => -56,], 50 => ['**' => -57, '*' => -57, 'namePart' => -57, '|' => -57, 'public' => -57, 'protected' => -57, 'private' => -57, 'final' => -57,], 51 => ['**' => -58, '*' => -58, 'namePart' => -58, '|' => -58, 'public' => -58, 'protected' => -58, 'private' => -58, 'final' => -58,], 52 => ['**' => -59, '*' => -59, 'namePart' => -59, '|' => -59, 'public' => -59, 'protected' => -59, 'private' => -59, 'final' => -59,], 60 => ['nsSeparator' => -42, ')' => -42, '+' => -42, '::' => -42, '->' => -42,], 62 => ['$eof' => -46, '||' => -46, '&&' => -46, ')' => -46, '(' => -46, 'nsSeparator' => -46, '*' => -46, 'namePart' => -46, '|' => -46, '+' => -46, '::' => -46, '->' => -46,], 63 => ['$eof' => -47, '||' => -47, '&&' => -47, ')' => -47, '(' => -47, 'nsSeparator' => -47, '*' => -47, 'namePart' => -47, '|' => -47, '+' => -47, '::' => -47, '->' => -47,], 68 => ['$eof' => -29, '||' => -29, '&&' => -29, ')' => -29,], 70 => ['->' => -52, 'nsSeparator' => -52, ')' => -52,], 71 => ['$eof' => -20, '||' => -20, '&&' => -20, ')' => -20,], 74 => ['**' => -54, '*' => -54, 'namePart' => -54,], 78 => ['$eof' => -21, '||' => -21, '&&' => -21, ')' => -21,], 79 => ['$eof' => -22, '||' => -22, '&&' => -22, ')' => -22,], 82 => ['$eof' => -48, '||' => -48, '&&' => -48, ')' => -48, '(' => -48, 'nsSeparator' => -48, '*' => -48, 'namePart' => -48, '|' => -48, '+' => -48, '::' => -48, '->' => -48,], 83 => ['$eof' => -49, '||' => -49, '&&' => -49, ')' => -49, '(' => -49, 'nsSeparator' => -49, '*' => -49, 'namePart' => -49, '|' => -49, '+' => -49, '::' => -49, '->' => -49,], 85 => ['$eof' => -23, '||' => -23, '&&' => -23, ')' => -23,], 86 => [')' => -38, '::' => -38, '->' => -38,], 88 => ['$eof' => -27, '||' => -27, '&&' => -27, ')' => -27,], 89 => ['$eof' => -28, '||' => -28, '&&' => -28, ')' => -28,], 91 => ['*' => -40, 'namePart' => -40,], 92 => ['*' => -41, 'namePart' => -41,], 93 => ['**' => -53, '*' => -53, 'namePart' => -53,], 94 => ['$eof' => -24, '||' => -24, '&&' => -24, ')' => -24,], 95 => ['$eof' => -25, '||' => -25, '&&' => -25, ')' => -25,], 96 => ['$eof' => -26, '||' => -26, '&&' => -26, ')' => -26,], 98 => [')' => -39,], 100 => ['nsSeparator' => -45, ')' => -45, '+' => -45, '::' => -45, '->' => -45,], 101 => ['$eof' => -50, '||' => -50, '&&' => -50, ')' => -50, '(' => -50, 'nsSeparator' => -50, '*' => -50, 'namePart' => -50, '|' => -50, '+' => -50, '::' => -50, '->' => -50,],], 'goto' => [0 => ['pointcutExpression' => 1, 'conjugatedExpression' => 2, 'negatedExpression' => 3, 'brakedExpression' => 5, 'singlePointcut' => 7, 'accessPointcut' => 8, 'annotatedAccessPointcut' => 9, 'executionPointcut' => 10, 'annotatedExecutionPointcut' => 11, 'withinPointcut' => 12, 'annotatedWithinPointcut' => 13, 'initializationPointcut' => 14, 'staticInitializationPointcut' => 15, 'matchInheritedPointcut' => 16, 'pointcutReference' => 17, 'namespaceName' => 25,], 4 => ['brakedExpression' => 29, 'singlePointcut' => 7, 'accessPointcut' => 8, 'annotatedAccessPointcut' => 9, 'executionPointcut' => 10, 'annotatedExecutionPointcut' => 11, 'withinPointcut' => 12, 'annotatedWithinPointcut' => 13, 'initializationPointcut' => 14, 'staticInitializationPointcut' => 15, 'matchInheritedPointcut' => 16, 'pointcutReference' => 17, 'namespaceName' => 25,], 6 => ['pointcutExpression' => 30, 'conjugatedExpression' => 2, 'negatedExpression' => 3, 'brakedExpression' => 5, 'singlePointcut' => 7, 'accessPointcut' => 8, 'annotatedAccessPointcut' => 9, 'executionPointcut' => 10, 'annotatedExecutionPointcut' => 11, 'withinPointcut' => 12, 'annotatedWithinPointcut' => 13, 'initializationPointcut' => 14, 'staticInitializationPointcut' => 15, 'matchInheritedPointcut' => 16, 'pointcutReference' => 17, 'namespaceName' => 25,], 27 => ['conjugatedExpression' => 42, 'negatedExpression' => 3, 'brakedExpression' => 5, 'singlePointcut' => 7, 'accessPointcut' => 8, 'annotatedAccessPointcut' => 9, 'executionPointcut' => 10, 'annotatedExecutionPointcut' => 11, 'withinPointcut' => 12, 'annotatedWithinPointcut' => 13, 'initializationPointcut' => 14, 'staticInitializationPointcut' => 15, 'matchInheritedPointcut' => 16, 'pointcutReference' => 17, 'namespaceName' => 25,], 28 => ['negatedExpression' => 43, 'brakedExpression' => 5, 'singlePointcut' => 7, 'accessPointcut' => 8, 'annotatedAccessPointcut' => 9, 'executionPointcut' => 10, 'annotatedExecutionPointcut' => 11, 'withinPointcut' => 12, 'annotatedWithinPointcut' => 13, 'initializationPointcut' => 14, 'staticInitializationPointcut' => 15, 'matchInheritedPointcut' => 16, 'pointcutReference' => 17, 'namespaceName' => 25,], 31 => ['propertyAccessReference' => 45, 'memberReference' => 46, 'memberModifiers' => 47, 'memberModifier' => 48,], 35 => ['methodExecutionReference' => 56, 'functionExecutionReference' => 57, 'memberReference' => 58, 'namespacePattern' => 59, 'memberModifiers' => 47, 'namePatternPart' => 61, 'memberModifier' => 48,], 36 => ['classFilter' => 64, 'namespacePattern' => 65, 'namePatternPart' => 61,], 37 => ['classFilter' => 66, 'namespacePattern' => 65, 'namePatternPart' => 61,], 38 => ['classFilter' => 67, 'namespacePattern' => 65, 'namePatternPart' => 61,], 40 => ['namePatternPart' => 69,], 47 => ['classFilter' => 72, 'namespacePattern' => 65, 'namePatternPart' => 61,], 48 => ['memberModifiers' => 74, 'memberModifier' => 48,], 53 => ['namespaceName' => 75,], 54 => ['namespaceName' => 76,], 55 => ['namespaceName' => 77,], 72 => ['memberAccessType' => 90,], 73 => ['memberModifiers' => 93, 'memberModifier' => 48,], 80 => ['argumentList' => 97,], 81 => ['namePatternPart' => 99,], 87 => ['namePatternPart' => 102,], 90 => ['namePatternPart' => 103,], 105 => ['argumentList' => 107,], 106 => ['namespaceName' => 108,], 110 => ['namespaceName' => 111,],]];
diff --git a/src/Aop/Pointcut/PointcutReference.php b/src/Aop/Pointcut/PointcutReference.php
index 33c46036..367c41c6 100644
--- a/src/Aop/Pointcut/PointcutReference.php
+++ b/src/Aop/Pointcut/PointcutReference.php
@@ -41,11 +41,9 @@ public function __construct(
public function matches(
ReflectionClass|ReflectionFileNamespace $context,
- ReflectionMethod|ReflectionProperty|ReflectionFunction|null $reflector = null,
- null|object|string $instanceOrScope = null,
- ?array $arguments = null
+ ReflectionMethod|ReflectionProperty|ReflectionFunction|null $reflector = null
): bool {
- return $this->getPointcut()->matches($context, $reflector, $instanceOrScope, $arguments);
+ return $this->getPointcut()->matches($context, $reflector);
}
public function getKind(): int
diff --git a/src/Aop/Pointcut/ReturnTypePointcut.php b/src/Aop/Pointcut/ReturnTypePointcut.php
index 39cd6755..e337bd8b 100644
--- a/src/Aop/Pointcut/ReturnTypePointcut.php
+++ b/src/Aop/Pointcut/ReturnTypePointcut.php
@@ -60,9 +60,7 @@ public function __construct(string $returnTypeName)
public function matches(
ReflectionClass|ReflectionFileNamespace $context,
- ReflectionMethod|ReflectionProperty|ReflectionFunction|null $reflector = null,
- null|object|string $instanceOrScope = null,
- ?array $arguments = null
+ ReflectionMethod|ReflectionProperty|ReflectionFunction|null $reflector = null
): bool {
// With only static context we always match, as we don't have any information about concrete reflector
if (!isset($reflector)) {
diff --git a/src/Aop/Pointcut/TruePointcut.php b/src/Aop/Pointcut/TruePointcut.php
index 4253b3ad..199de47e 100644
--- a/src/Aop/Pointcut/TruePointcut.php
+++ b/src/Aop/Pointcut/TruePointcut.php
@@ -35,9 +35,7 @@ public function __construct(private int $pointcutKind = self::KIND_ALL) {}
*/
public function matches(
ReflectionClass|ReflectionFileNamespace $context,
- ReflectionMethod|ReflectionProperty|ReflectionFunction|null $reflector = null,
- null|object|string $instanceOrScope = null,
- ?array $arguments = null
+ ReflectionMethod|ReflectionProperty|ReflectionFunction|null $reflector = null
): true {
return true;
}
diff --git a/src/Aop/Support/GenericPointcutAdvisor.php b/src/Aop/Support/GenericPointcutAdvisor.php
index 2affcb68..e1c247a7 100644
--- a/src/Aop/Support/GenericPointcutAdvisor.php
+++ b/src/Aop/Support/GenericPointcutAdvisor.php
@@ -13,8 +13,6 @@
namespace Go\Aop\Support;
use Go\Aop\Advice;
-use Go\Aop\Framework\DynamicInvocationMatcherInterceptor;
-use Go\Aop\Intercept\Interceptor;
use Go\Aop\Pointcut;
use Go\Aop\PointcutAdvisor;
@@ -30,18 +28,7 @@ public function __construct(private Pointcut $pointcut, private Advice $advice)
public function getAdvice(): Advice
{
- // For dynamic pointcuts, we use special dynamic invocation matcher interceptor
- // This part can't be moved to the constructor, as it breaks lazy-evaluation for PointcutReference
- if (($this->advice instanceof Interceptor) && ($this->pointcut->getKind() & Pointcut::KIND_DYNAMIC)) {
- $advice = new DynamicInvocationMatcherInterceptor(
- $this->pointcut,
- $this->advice
- );
- } else {
- $advice = $this->advice;
- }
-
- return $advice;
+ return $this->advice;
}
public function getPointcut(): Pointcut
diff --git a/tests/Aop/Pointcut/MagicMethodDynamicPointcutTest.php b/tests/Aop/Pointcut/MagicMethodDynamicPointcutTest.php
deleted file mode 100644
index a2f14b09..00000000
--- a/tests/Aop/Pointcut/MagicMethodDynamicPointcutTest.php
+++ /dev/null
@@ -1,136 +0,0 @@
-
- *
- * This source file is subject to the license that is bundled
- * with this source code in the file LICENSE.
- */
-
-namespace Go\Aop\Pointcut;
-
-use Go\Aop\Pointcut;
-use Go\ParserReflection\ReflectionFileNamespace;
-use Go\Stubs\ClassWithMagicMethods;
-use PHPUnit\Framework\TestCase;
-use ReflectionClass;
-use ReflectionMethod;
-use ReflectionProperty;
-
-class MagicMethodDynamicPointcutTest extends TestCase
-{
- public function testMatchesExactDynamicMethodName(): void
- {
- $pointcut = new MagicMethodDynamicPointcut('test');
-
- // Statically should match any class with magic methods inside
- $matched = $pointcut->matches(new ReflectionClass(ClassWithMagicMethods::class));
- $this->assertTrue($matched, "MagicMethodDynamicPointcut should match classes with magic methods");
-
- // Pointcut should statically match __call magic method in the class
- $matched = $pointcut->matches(
- new ReflectionClass(ClassWithMagicMethods::class),
- new ReflectionMethod(ClassWithMagicMethods::class, '__call')
- );
- $this->assertTrue($matched, "Pointcut should match __call method because it is magic");
-
- // Pointcut should statically match __callStatic magic method in the class
- $matched = $pointcut->matches(
- new ReflectionClass(ClassWithMagicMethods::class),
- new ReflectionMethod(ClassWithMagicMethods::class, '__callStatic')
- );
- $this->assertTrue($matched, "Pointcut should match __callStatic method because it is magic");
-
- // During dynamic matching, it should match arguments from corresponding magic calls
- $matched = $pointcut->matches(
- new ReflectionClass(ClassWithMagicMethods::class),
- new ReflectionMethod(ClassWithMagicMethods::class, '__call'),
- new ClassWithMagicMethods(),
- ['test']
- );
- $this->assertTrue($matched, "Pointcut should dynamically match 'test' method because it matches");
- }
-
- public function testDoesntMatchExactDynamicMethodName(): void
- {
- $pointcut = new MagicMethodDynamicPointcut('another');
-
- // During dynamic matching, it should not match dynamic method name
- $matched = $pointcut->matches(
- new ReflectionClass(ClassWithMagicMethods::class),
- new ReflectionMethod(ClassWithMagicMethods::class, '__call'),
- new ClassWithMagicMethods(),
- ['test']
- );
- $this->assertFalse($matched, "Pointcut should not dynamically match 'test' method because we expect 'another'");
- }
-
-
- public function testDoesntMatchWrongContextOrReflectorGiven(): void
- {
- $pointcut = new MagicMethodDynamicPointcut('test');
-
- // Unsupported context (ReflectionFileNamespace)
- $matched = $pointcut->matches(new ReflectionFileNamespace(__FILE__, __NAMESPACE__));
- $this->assertFalse($matched, "MagicMethodDynamicPointcut should not match ReflectionFileNamespace statically");
-
- // Non-magic static method
- $matched = $pointcut->matches(
- new ReflectionClass(ClassWithMagicMethods::class),
- new ReflectionMethod(ClassWithMagicMethods::class, 'notMagicMethod')
- );
- $this->assertFalse($matched, "MagicMethodDynamicPointcut should not match non-magic method");
-
- // Attempt to match property with magic name
- $matched = $pointcut->matches(
- new ReflectionClass(ClassWithMagicMethods::class),
- new ReflectionProperty(ClassWithMagicMethods::class, '__call')
- );
- $this->assertFalse($matched, "MagicMethodDynamicPointcut should not match property with magic name");
-
- // Pointcut should not match statically for __callMe magic method in the class
- $matched = $pointcut->matches(
- new ReflectionClass(ClassWithMagicMethods::class),
- new ReflectionMethod(ClassWithMagicMethods::class, '__callMe')
- );
- $this->assertFalse($matched, "MagicMethodDynamicPointcut should not match __callMe method");
-
- // During dynamic matching, attempt to match without arguments
- $matched = $pointcut->matches(
- new ReflectionClass(ClassWithMagicMethods::class),
- new ReflectionMethod(ClassWithMagicMethods::class, '__call'),
- new ClassWithMagicMethods(),
- );
- $this->assertFalse($matched, "Pointcut should not dynamically match 'test' method without info about args");
-
- // During dynamic matching, attempt to match with empty arguments
- $matched = $pointcut->matches(
- new ReflectionClass(ClassWithMagicMethods::class),
- new ReflectionMethod(ClassWithMagicMethods::class, '__call'),
- new ClassWithMagicMethods(),
- []
- );
- $this->assertFalse($matched, "Pointcut should not dynamically match 'test' method without info about args");
-
- // During dynamic matching, attempt to match arguments with wrong type
- $matched = $pointcut->matches(
- new ReflectionClass(ClassWithMagicMethods::class),
- new ReflectionMethod(ClassWithMagicMethods::class, '__call'),
- new ClassWithMagicMethods(),
- [new \stdClass()]
- );
- $this->assertFalse($matched, "Pointcut should not dynamically match 'test' method without info about args");
-
- }
-
- public function testGetKind(): void
- {
- $pointcut = new MagicMethodDynamicPointcut('test');
-
- $this->assertTrue(($pointcut->getKind() & Pointcut::KIND_DYNAMIC) > 0, 'Pointcut should be dynamic');
- $this->assertTrue(($pointcut->getKind() & Pointcut::KIND_METHOD) > 0, 'Pointcut should be for methods');
- }
-}
diff --git a/tests/Aop/Pointcut/PointcutParserTest.php b/tests/Aop/Pointcut/PointcutParserTest.php
index e0d00356..b276ef71 100644
--- a/tests/Aop/Pointcut/PointcutParserTest.php
+++ b/tests/Aop/Pointcut/PointcutParserTest.php
@@ -96,11 +96,6 @@ public static function validPointcutDefinitions(): array
// Function with return-type
['execution(Demo\*\Test\**\*(*): bool)'],
-
- // Dynamic pointcut for methods via __callStatic and __call
- ['dynamic(public Demo\Example\DynamicMethodsDemo::find*(*))'],
- ['dynamic(public Demo\Example\DynamicMethodsDemo->save*(*))'],
-
// This will match static initialization pointcut
['staticinitialization(Some\Specific\Class\**)'],
diff --git a/tests/Aop/Pointcut/TruePointcutTest.php b/tests/Aop/Pointcut/TruePointcutTest.php
index 864faa5f..3a1e1485 100644
--- a/tests/Aop/Pointcut/TruePointcutTest.php
+++ b/tests/Aop/Pointcut/TruePointcutTest.php
@@ -49,9 +49,9 @@ public function testItMatchesWithDefaultKinds(): void
$this->assertTrue((bool)($kind & Pointcut::KIND_STATIC_INIT));
}
- public function testItDoesNotMatchWithDynamicKindByDefault(): void
+ public function testItDoesNotMatchWithIntroductionKindByDefault(): void
{
$kind = $this->pointcut->getKind();
- $this->assertFalse((bool)($kind & Pointcut::KIND_DYNAMIC));
+ $this->assertFalse((bool)($kind & Pointcut::KIND_INTRODUCTION));
}
}