diff options
-rw-r--r-- | nullaway/src/main/java/com/uber/nullaway/generics/PreservedAnnotationTreeVisitor.java | 97 |
1 files changed, 56 insertions, 41 deletions
diff --git a/nullaway/src/main/java/com/uber/nullaway/generics/PreservedAnnotationTreeVisitor.java b/nullaway/src/main/java/com/uber/nullaway/generics/PreservedAnnotationTreeVisitor.java index 822fcf1..4549028 100644 --- a/nullaway/src/main/java/com/uber/nullaway/generics/PreservedAnnotationTreeVisitor.java +++ b/nullaway/src/main/java/com/uber/nullaway/generics/PreservedAnnotationTreeVisitor.java @@ -104,6 +104,41 @@ public class PreservedAnnotationTreeVisitor extends SimpleTreeVisitor<Type, Void TypeMetadata create(com.sun.tools.javac.util.List<Attribute.TypeCompound> attrs); Type cloneTypeWithMetadata(Type typeToBeCloned, TypeMetadata metaData); + + static MethodHandle createAnnotationsCtorHandle(Class<?> paramTypeClass) { + MethodHandles.Lookup lookup = MethodHandles.lookup(); + MethodType mt = MethodType.methodType(void.class, paramTypeClass); + try { + return lookup.findConstructor(TypeMetadata.Annotations.class, mt); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } + + /** + * Used to get a MethodHandle for a virtual method from the specified class + * + * @param retTypeClass Class to indicate the return type of the desired method + * @param paramTypeClass Class to indicate the parameter type of the desired method + * @param refClass Class within which the desired method is contained + * @param methodName Name of the desired method + * @return The appropriate MethodHandle for the virtual method + */ + static MethodHandle createVirtualMethodHandle( + Class<?> retTypeClass, Class<?> paramTypeClass, Class<?> refClass, String methodName) { + MethodHandles.Lookup lookup = MethodHandles.lookup(); + MethodType mt = MethodType.methodType(retTypeClass, paramTypeClass); + try { + return lookup.findVirtual(refClass, methodName, mt); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } + } /** @@ -112,9 +147,18 @@ public class PreservedAnnotationTreeVisitor extends SimpleTreeVisitor<Type, Void */ private static class JDK17AndEarlierTypeMetadataBuilder implements TypeMetadataBuilder { + private static final MethodHandle typeMetadataHandle = + TypeMetadataBuilder.createAnnotationsCtorHandle(com.sun.tools.javac.util.List.class); + private static final MethodHandle cloneHandle = TypeMetadataBuilder.createVirtualMethodHandle( + Type.class, TypeMetadata.class, Type.class, "cloneWithMetadata"); + @Override public TypeMetadata create(com.sun.tools.javac.util.List<Attribute.TypeCompound> attrs) { - return new TypeMetadata(new TypeMetadata.Annotations(attrs)); + try { + return (TypeMetadata) typeMetadataHandle.invoke(attrs); + } catch (Throwable e) { + throw new RuntimeException(e); + } } /** @@ -127,7 +171,11 @@ public class PreservedAnnotationTreeVisitor extends SimpleTreeVisitor<Type, Void */ @Override public Type cloneTypeWithMetadata(Type typeToBeCloned, TypeMetadata metadata) { - return typeToBeCloned.cloneWithMetadata(metadata); + try { + return (Type) cloneHandle.invoke(typeToBeCloned, metadata); + } catch (Throwable e) { + throw new RuntimeException(e); + } } } @@ -138,45 +186,12 @@ public class PreservedAnnotationTreeVisitor extends SimpleTreeVisitor<Type, Void */ private static class JDK21TypeMetadataBuilder implements TypeMetadataBuilder { - private static final MethodHandle typeMetadataHandle = createHandle(); - private static final MethodHandle addMetadataHandle = - createVirtualMethodHandle(Type.class, TypeMetadata.class, Type.class, "addMetadata"); - private static final MethodHandle dropMetadataHandle = - createVirtualMethodHandle(Type.class, Class.class, Type.class, "dropMetadata"); - - private static MethodHandle createHandle() { - MethodHandles.Lookup lookup = MethodHandles.lookup(); - MethodType mt = MethodType.methodType(void.class, com.sun.tools.javac.util.ListBuffer.class); - try { - return lookup.findConstructor(TypeMetadata.Annotations.class, mt); - } catch (NoSuchMethodException e) { - throw new RuntimeException(e); - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } - } - - /** - * Used to get a MethodHandle for a virtual method from the specified class - * - * @param retTypeClass Class to indicate the return type of the desired method - * @param paramTypeClass Class to indicate the parameter type of the desired method - * @param refClass Class within which the desired method is contained - * @param methodName Name of the desired method - * @return The appropriate MethodHandle for the virtual method - */ - private static MethodHandle createVirtualMethodHandle( - Class<?> retTypeClass, Class<?> paramTypeClass, Class<?> refClass, String methodName) { - MethodHandles.Lookup lookup = MethodHandles.lookup(); - MethodType mt = MethodType.methodType(retTypeClass, paramTypeClass); - try { - return lookup.findVirtual(refClass, methodName, mt); - } catch (NoSuchMethodException e) { - throw new RuntimeException(e); - } catch (IllegalAccessException e) { - throw new RuntimeException(e); - } - } + private static final MethodHandle typeMetadataHandle = + TypeMetadataBuilder.createAnnotationsCtorHandle(com.sun.tools.javac.util.ListBuffer.class); + private static final MethodHandle addMetadataHandle = TypeMetadataBuilder.createVirtualMethodHandle( + Type.class, TypeMetadata.class, Type.class, "addMetadata"); + private static final MethodHandle dropMetadataHandle = TypeMetadataBuilder.createVirtualMethodHandle( + Type.class, Class.class, Type.class, "dropMetadata"); @Override public TypeMetadata create(com.sun.tools.javac.util.List<Attribute.TypeCompound> attrs) { |