-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Support @ClassName in function return type #9268
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
Support @ClassName in function return type #9268
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.
Hello reviewers,
I found in order to support function-return type matching in ShadowWrangler, I might need to add one more return-type in following functions?
ShadowWrangler.pickShadowMethod(Class<?> definingClass, String name, Class<?>[] paramTypes, @Nullable Class<?> rType)
ShadowWrangler.findShadowMethod(..., @Nullable Class<?> rType)
ShadowWrangler.findShadowMethodDeclaredOnClass(..., @Nullable Class<?> rType)
However, would change protected function function signature break backward compatibility?
I prefer to add new functions/methods to support new logic instead of modifying the current one if it was exposed to normal users before. Looks like I didn't modify these methods' signature to support return type for ClassName. |
annotations/src/main/java/org/robolectric/annotation/ClassName.java
Outdated
Show resolved
Hide resolved
|
Hello,
which now will take function return type into consideration when find a matching-method.
to use the new method However, I think I will break the expectation of anyone who already overridden the old |
sandbox/src/main/java/org/robolectric/internal/bytecode/ShadowWrangler.java
Outdated
Show resolved
Hide resolved
83c3d6b
to
9739682
Compare
* | ||
* } | ||
* } | ||
* </pre> | ||
*/ | ||
@Target(ElementType.PARAMETER) | ||
@Target({ElementType.PARAMETER, ElementType.TYPE_USE}) |
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.
I think this should be @Target({ElementType.METHOD, ElementType.PARAMETER})
.
TYPE_USE means it can be used for any use, i.e. at the class level, interfaces, casts.
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 prefer method first, but after some thoughts, it might be strange to use method for return type. Anyway, I am fine to both of method and 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.
done. changed to @Target({ElementType.METHOD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME) | ||
public @interface ClassName { | ||
|
||
/** | ||
* The class name intended for this parameter. | ||
* The class name intended for the parameter, function return. |
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 class name intended for the parameter or the function return value.
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.
done
@@ -181,7 +181,7 @@ public MethodHandle findShadowMethodHandle( | |||
MethodType actualType = isStatic ? methodType : methodType.dropParameterTypes(0, 1); | |||
Class<?>[] paramTypes = actualType.parameterArray(); | |||
|
|||
Method shadowMethod = pickShadowMethod(definingClass, name, paramTypes); | |||
Method shadowMethod = pickShadowMethod(definingClass, name, actualType); |
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 we just keep ShadowWrangler as-is for now instead of checking the @ClassName
return type annotation?
We don't check the return type when checking any other shadow methods, so I am not seeing a strong reason to special-case the @ClassName
return types. It adds a lot of complexity to ShadowWrangler but it does not seem to make a difference functionally. As far as I know, when doing invokedynamic binding, the return type is not considered.
validator/SdkStore.java
is what cares about the return type, so we should just add logic to that to check it.
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 Michael,
I have a side question, may I ask when the SdkStore logic is executed? 1) in the stage of pre-instrument Android-all jars to publish to maven
or 2) when in the early stage of unit-test startup during which verify all shadows are correctly defined or 3) in early stage of each test function to verify that shadows used in current test-function are correctly defined? or 4) any other timing?
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.
SdkStore logic is executed whenever the shadows/framework
code is compiled. It is invoked by an annotation processor, which occurs during compile-time. So whenever we add/modify a shadow method, it is verified against the Android sdks.
ShadowWrangler is invoked during runtime when an Android method is first called. It looks to check if a shadow method should be called instead of the real Android code.
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.
I think we can write method signature to SdkStore, and ShadowWrangle only do basic validation without caring about too much about ClassName's details.
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.
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.
done.
make SdkStore take care of ClassName annotation in function return 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.
Hello reviewers,
by running test ./gradlew :shadows:framework:compileJava
locally, I found that
1, ClassName must target to {ElementType.TYPE_USE, ElementType.PARAMETER}
, otherwise the annotation will not be able to be found in SdkStore logic.
2, sometimes I have to enumerate all annotations for a parameter/return type to find ClassName annotation, sometimes I can use xxx.getAnnotation(ClassName.class) to quickly get a handle to the annotation
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 @Mia0451 ,
We can start off using TYPE_USE for now, and perhaps as a follow-up we can clean it up.
Thanks!
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.
got it
ebc83e9
to
23396d7
Compare
@classname annoated function return type is actually NOT used in picking shadow method in test runtime, however we will enforce type matching in earlier stage which is sdk verifying stage.
23396d7
to
c6293e4
Compare
@classname annotation are now also required in function return type of the shadow method. We will verify the shadow method in test compile time to make sure the shadows are correctly defined.
Overview
Proposed Changes