You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Note: Transformers are always executed before Aspects.
Example of why it is incompatible:
class Target
{
publicfunctionanswer(): int
{
return42;
}
}
class Transformer extends TransformerClass
{
// ...publicfunctiontransform(Code$code): void
{
$sourceFileNode = $code->getSourceFileNode();
// Find return type: 'int' ...$code->edit($node, 'int|float');
// Find return value '42' ...$code->edit($node, "$nodeText.69");
}
}
#[AspectAttribute]
class Aspect
{
#[After(
class: Target::class,
method: 'answer',
)]
publicfunctionhigherAnswer(AfterMethodInvocation$methodInvocation): int|float
{
$result = $methodInvocation->proceed();
return$result + 378;
}
}
$target->answer(); // Returns "420", should return "420.69"
First the transformer is applied, it changes the return type from int to int|float and changes the number 42 to 42.69
After that the aspect is applied, it adds 378 to the result, which should result to the final number 420.69
But it doesn't return 420.69, it returns 420
Why? Because the aspect builds the woven file only with the int type and not int|float
Why? Because the WovenClassBuilder uses the ReflectionMethod from the matching process (AspectMatcher->$matchedAdviceContainers) and not from the newly transformed file (After the transformer has been applied)
Here is how the woven class looks like:
class Target extends Target__AopProxied
{
publicfunctionanswer(): int// Should be int|float
{
returncall_user_func_array(self::$__joinPoints['method']['answer'], [$this]);
}
}
// Proxied class:class Target__AopProxied
{
publicfunctionanswer(): int|float// Has int|float
{
return42.69;
}
}
Current workflow:
(In ClassLoader)
Match the aspects
Match the transformers (order doesn't matter)
Rewrite the file path to a StreamFilter which modifies the source code as a stream and at runtime. See PHP Stream Filters
Inside the StreamFilter the appliance of the transformers happens first, then the aspects are applied
How to fix this?
(In ClassLoader)
First match the transformers
Apply the transformers
Save the new class as a BetterReflection in a ReflectionContainer
Match the aspects by the new BetterReflection instance
Problems with this solution:
Usually first the matching is done, then the StreamFilter rewrites the file at runtime and this is where the appliance of both transformers and aspects happens. The StreamFilter provided the source code of the file as a stream.
Here the problem would be that we have to load the file manually when applying the transformers in the ClassLoader, which would be unnecessary.
Alternatively we could move the matching logic right into the StreamFilter, but then we'd have to figure out the namespace manually and every loaded class would end up in the StreamFilter, which would be a huge performance loss.
Do we even need Stream Filters?????
Don't even know why I am using them...
Yes, Xdebug will jump into the original file instead of debugging the proxied/woven files that are generated by this library, thanks to the Stream Filters. See #72 for more information.
The text was updated successfully, but these errors were encountered:
Using Code Transformers with Aspects has some problems.
Note: Transformers are always executed before Aspects.
Example of why it is incompatible:
int
toint|float
and changes the number42
to42.69
378
to the result, which should result to the final number420.69
420.69
, it returns420
int
type and notint|float
WovenClassBuilder
uses theReflectionMethod
from the matching process (AspectMatcher->$matchedAdviceContainers
) and not from the newly transformed file (After the transformer has been applied)Here is how the woven class looks like:
Current workflow:
ClassLoader
)StreamFilter
which modifies the source code as a stream and at runtime. See PHP Stream FiltersStreamFilter
the appliance of the transformers happens first, then the aspects are appliedHow to fix this?
ClassLoader
)BetterReflection
in aReflectionContainer
BetterReflection
instanceProblems with this solution:
Usually first the matching is done, then the
StreamFilter
rewrites the file at runtime and this is where the appliance of both transformers and aspects happens. TheStreamFilter
provided the source code of the file as a stream.Here the problem would be that we have to load the file manually when applying the transformers in the
ClassLoader
, which would be unnecessary.Alternatively we could move the matching logic right into the
StreamFilter
, but then we'd have to figure out the namespace manually and every loaded class would end up in theStreamFilter
, which would be a huge performance loss.Do we even need Stream Filters?????
Don't even know why I am using them...Yes, Xdebug will jump into the original file instead of debugging the proxied/woven files that are generated by this library, thanks to the Stream Filters. See #72 for more information.
The text was updated successfully, but these errors were encountered: