-
Notifications
You must be signed in to change notification settings - Fork 7.9k
ext/reflection: add getLine / getFileName / isUserDefined to reflection attribute #13889
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi @joelwurtz. Thank you for your contribution! I think this doesn't necessarily need an RFC if nobody complains, but it needs at least an e-mail to the internals mailing list.
c064c11
to
ce931cd
Compare
ce931cd
to
7b216a2
Compare
@@ -1956,7 +1958,7 @@ ZEND_METHOD(ReflectionFunctionAbstract, getAttributes) | |||
|
|||
reflect_attributes(INTERNAL_FUNCTION_PARAM_PASSTHRU, | |||
fptr->common.attributes, 0, fptr->common.scope, target, | |||
fptr->type == ZEND_USER_FUNCTION ? fptr->op_array.filename : NULL); | |||
fptr->type == ZEND_USER_FUNCTION ? fptr->op_array.filename : NULL, ZEND_USER_CODE(fptr->type)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, I'm a bit confused by the intention here. Does this check whether the attribute class is internal, or whether the target is internal? It currently does the latter, but that doesn't seem super useful?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The intention is more : does the attribute (the instance not the class) as been defined (written) in user land code (wether it's a method / parameter / class / etc ...),
If it's an attribute from user land on an user land code it should return true
If it's an attribute from php core on an user land code it should return true
If it's an attribute from php core on php core it should return false
If it's an attribute from user land code on php core it should return false (but i don't think this use case is possible)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you clarify why this matters? I understand that internal attributes can have additional validation without instanciation. But why does it matter whether the attrbute is placed on a user or internal target?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is mainly if some library that do error handling (like https://github.com/symfony/error-handler by example) want to provide a generic way to pin point those error, they could then only do that when they detect that the attribute has been writed by the user
But i'm wondering if PHP internal class may have internal attributes attached to their method or class (now or in the future) defined ? I know there is pre defined attributes by PHP but not sure if there are used in internal methods or if an extension can declare them using C code ?
If not then this is useless
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, internal attributes can be attached to internal classes, but instantiating them should never error. If it does error, that would be a bug in core/the extension itself. I'm still confused about when and why exactly Symfony error handler would need this information.
Can you provide a concrete example? Moreover, whether the target is internal would already be known, by looking at the reflection of the class/method itself.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As an example we could, in a generic error handler, do the following interface :
interface LinkReflectionAttribute
{
public function getAttribute(): \ReflectionAttribute;
}
When the error handler catch an exception with this interface it may do special things like show the exception (like before) and add a special text (or HTML in web context) to the user to show which attributes this exception concern (it could even show the portion of code in web context).
Library would only have to implement this interface in their exception and the error handler would do the rest
Having the isUserDefined()
method would allow this generic handler to be sure that the reflection attribute given has been written in a PHP file and does not originate from the core (in the last case there is no point showing something since it's not written in a PHP file and so it's not fixable by the user)
This method may not be necessary if the interface look like this :
interface LinkReflectionAttribute
{
public function getAttribute(): \ReflectionAttribute;
public function getTarget(): \ReflectionClass | \ReflectionMethod |\ReflectionFunction | \ReflectionParameter | \ReflectionProperty
}
In this case we could determine if it's user defined given the specific target.
The disadvantage, is that user implementing this interface would need to track every Attribute with their Target, and in some cases it may involved passing those 2 values a lot of times which is cumbersome.
But maybe the isUserDefined()
method is not the best approach. Wouldn't it be better if instead we have this getTarget()
method inside the ReflectionAttribute
class ?
So we could have the target of the attribute without having to keep track of it in PHP code ?
There is already a getTarget()
method that returns an int
, there could be a getDeclaringTarget()
that returns \ReflectionClass | \ReflectionMethod |\ReflectionFunction | \ReflectionParameter | \ReflectionProperty
7b216a2
to
fd42159
Compare
This add those methods to the
ReflectionAttribute
Those method can be really useful when a library want to throw an exception during the analysis of an attribute so the library can show to the user which attribute specifically induce this exception (like: "Attribute at line %d in file %s cause a bad configuration")
Does this need a RFC ?