| /* |
| * Copyright (c) 2012, 2014, Oracle and/or its affiliates. All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * - Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * |
| * - Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * - Neither the name of Oracle nor the names of its |
| * contributors may be used to endorse or promote products derived |
| * from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS |
| * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
| * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
| * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
| * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
| * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
| * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
| * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
| * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
| * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| import java.lang.annotation.Annotation; |
| import javax.annotation.processing.SupportedSourceVersion; |
| import javax.lang.model.element.*; |
| import javax.lang.model.element.Modifier; |
| import javax.lang.model.type.*; |
| import javax.lang.model.util.*; |
| import java.lang.reflect.*; |
| import java.io.Writer; |
| import java.util.*; |
| |
| import static javax.lang.model.SourceVersion.RELEASE_9; |
| import static java.util.Objects.*; |
| |
| /** |
| * This class provides a proof-of-concept implementation of the {@code |
| * javax.lang.model.*} API backed by core reflection. That is, rather |
| * than having a source file or compile-time class file as the |
| * originator of the information about an element or type, as done |
| * during standard annotation processing, runtime core reflection |
| * objects serve that purpose instead. |
| * |
| * With this kind of implementation, the same logic can be used for |
| * both compile-time and runtime processing of annotations. |
| * |
| * The nested types in this class define a specialization of {@code |
| * javax.lang.model.*} to provide some additional functionality and |
| * type information. The original {@code javax.lang.model.*} API was |
| * designed to accommodate such a specialization by using wildcards in |
| * the return types of methods. |
| * |
| * It would be technically possible for further specializations of the |
| * API implemented in this class to define alternative semantics of |
| * annotation look-up. For example to allow one annotation to have the |
| * effect of macro-expanding into a set of other annotations. |
| * |
| * Some aspects of the implementation are left as "exercises for the |
| * reader" to complete if interested. |
| * |
| * When passed null pointers, the methods defined in this type will |
| * generally throw null pointer exceptions. |
| * |
| * To get started, first compile this file with a command line like: |
| * |
| * <pre> |
| * $JDK/bin/javac -parameters -Xdoclint:all/public -Xlint:all -d $OUTPUT_DIR CoreReflectionFactory.java |
| * </pre> |
| * |
| * and then run the main method of {@code CoreReflectionFactory}, |
| * which will print out a representation of {@code |
| * CoreReflectionFactory}. To use the printing logic defined in {@code |
| * javac}, put {@code tools.jar} on the classpath as in: |
| * |
| * <pre> |
| * $JDK/bin/java -cp $OUTPUT_DIR:$JDK_ROOT/lib/tools.jar CoreReflectionFactory |
| * </pre> |
| * |
| * @author Joseph D. Darcy (darcy) |
| * @author Joel Borggren-Franck (jfranck) |
| */ |
| public class CoreReflectionFactory { |
| private CoreReflectionFactory() { |
| throw new AssertionError("No instances of CoreReflectionFactory for you!"); |
| } |
| |
| /** |
| * Returns a reflection type element mirroring a {@code Class} object. |
| * @return a reflection type element mirroring a {@code Class} object |
| * @param clazz the {@code Class} to mirror |
| */ |
| public static ReflectionTypeElement createMirror(Class<?> clazz) { |
| return new CoreReflTypeElement(Objects.requireNonNull(clazz)); |
| } |
| |
| /** |
| * Returns a reflection package element mirroring a {@code Package} object. |
| * @return a reflection package element mirroring a {@code Package} object |
| * @param pkg the {@code Package} to mirror |
| */ |
| public static ReflectionPackageElement createMirror(Package pkg) { |
| // Treat a null pkg to mean an unnamed package. |
| return new CoreReflPackageElement(pkg); |
| } |
| |
| /** |
| * Returns a reflection variable element mirroring a {@code Field} object. |
| * @return a reflection variable element mirroring a {@code Field} object |
| * @param field the {@code Field} to mirror |
| */ |
| public static ReflectionVariableElement createMirror(Field field) { |
| return new CoreReflFieldVariableElement(Objects.requireNonNull(field)); |
| } |
| |
| /** |
| * Returns a reflection executable element mirroring a {@code Method} object. |
| * @return a reflection executable element mirroring a {@code Method} object |
| * @param method the {@code Method} to mirror |
| */ |
| public static ReflectionExecutableElement createMirror(Method method) { |
| return new CoreReflMethodExecutableElement(Objects.requireNonNull(method)); |
| } |
| |
| /** |
| * Returns a reflection executable element mirroring a {@code Constructor} object. |
| * @return a reflection executable element mirroring a {@code Constructor} object |
| * @param constructor the {@code Constructor} to mirror |
| */ |
| public static ReflectionExecutableElement createMirror(Constructor<?> constructor) { |
| return new CoreReflConstructorExecutableElement(Objects.requireNonNull(constructor)); |
| } |
| |
| /** |
| * Returns a type parameter element mirroring a {@code TypeVariable} object. |
| * @return a type parameter element mirroring a {@code TypeVariable} object |
| * @param tv the {@code TypeVariable} to mirror |
| */ |
| public static TypeParameterElement createMirror(java.lang.reflect.TypeVariable<?> tv) { |
| return new CoreReflTypeParameterElement(Objects.requireNonNull(tv)); |
| } |
| |
| /** |
| * Returns a variable element mirroring a {@code Parameter} object. |
| * @return a variable element mirroring a {@code Parameter} object |
| * @param p the {Parameter} to mirror |
| */ |
| public static VariableElement createMirror(java.lang.reflect.Parameter p) { |
| return new CoreReflParameterVariableElement(Objects.requireNonNull(p)); |
| } |
| |
| /** |
| * Returns an annotation mirror mirroring an annotation object. |
| * @return an annotation mirror mirroring an annotation object |
| * @param annotation the annotation to mirror |
| */ |
| public static AnnotationMirror createMirror(Annotation annotation) { |
| return new CoreReflAnnotationMirror(Objects.requireNonNull(annotation)); |
| } |
| |
| /** |
| * Returns a {@code Types} utility object for type objects backed by core reflection. |
| * @return a {@code Types} utility object for type objects backed by core reflection |
| */ |
| public static Types getTypes() { |
| return CoreReflTypes.instance(); |
| } |
| |
| /** |
| * Returns an {@code Elements} utility object for type objects backed by core reflection. |
| * @return an {@code Elements} utility object for type objects backed by core reflection |
| */ |
| public static Elements getElements() { |
| return CoreReflElements.instance(); |
| } |
| |
| // Helper |
| private static TypeMirror createTypeMirror(Class<?> c) { |
| return TypeFactory.instance(Objects.requireNonNull(c)); |
| } |
| |
| /** |
| * Main method; prints out a representation of this class. |
| * @param args command-line arguments, currently ignored |
| */ |
| public static void main(String... args) { |
| getElements().printElements(new java.io.PrintWriter(System.out), |
| createMirror(CoreReflectionFactory.class)); |
| } |
| |
| /** |
| * A specialization of {@code javax.lang.model.element.Element} that is |
| * backed by core reflection. |
| */ |
| public static interface ReflectionElement |
| extends Element, AnnotatedElement { |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| ReflectionElement getEnclosingElement(); |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| List<ReflectionElement> getEnclosedElements(); |
| |
| /** |
| * Applies a visitor to this element. |
| * |
| * @param v the visitor operating on this element |
| * @param p additional parameter to the visitor |
| * @param <R> the return type of the visitor's methods |
| * @param <P> the type of the additional parameter to the visitor's methods |
| * @return a visitor-specified result |
| */ |
| <R,P> R accept(ReflectionElementVisitor<R,P> v, P p); |
| |
| // Functionality specific to the specialization |
| /** |
| * Returns the underlying core reflection source object, if applicable. |
| * @return the underlying core reflection source object, if applicable |
| */ |
| AnnotatedElement getSource(); |
| |
| // Functionality from javax.lang.model.util.Elements |
| /** |
| * Returns the package of an element. The package of a package |
| * is itself. |
| * @return the package of an element |
| */ |
| ReflectionPackageElement getPackage(); |
| |
| } |
| |
| /** |
| * A logical specialization of {@code |
| * javax.lang.model.element.ElementVisitor} being backed by core |
| * reflection. |
| * |
| * @param <R> the return type of this visitor's methods. |
| * @param <P> the type of the additional parameter to this visitor's |
| * methods. |
| */ |
| public static interface ReflectionElementVisitor<R, P> { |
| /** |
| * Visits an element. |
| * @param e the element to visit |
| * @param p a visitor-specified parameter |
| * @return a visitor-specified result |
| */ |
| R visit(ReflectionElement e, P p); |
| |
| /** |
| * A convenience method equivalent to {@code v.visit(e, null)}. |
| * @param e the element to visit |
| * @return a visitor-specified result |
| */ |
| R visit(ReflectionElement e); |
| |
| /** |
| * Visits a package element. |
| * @param e the element to visit |
| * @param p a visitor-specified parameter |
| * @return a visitor-specified result |
| */ |
| R visitPackage(ReflectionPackageElement e, P p); |
| |
| /** |
| * Visits a type element. |
| * @param e the element to visit |
| * @param p a visitor-specified parameter |
| * @return a visitor-specified result |
| */ |
| R visitType(ReflectionTypeElement e, P p); |
| |
| /** |
| * Visits a variable element. |
| * @param e the element to visit |
| * @param p a visitor-specified parameter |
| * @return a visitor-specified result |
| */ |
| R visitVariable(ReflectionVariableElement e, P p); |
| |
| /** |
| * Visits an executable element. |
| * @param e the element to visit |
| * @param p a visitor-specified parameter |
| * @return a visitor-specified result |
| */ |
| R visitExecutable(ReflectionExecutableElement e, P p); |
| |
| /** |
| * Visits a type parameter element. |
| * @param e the element to visit |
| * @param p a visitor-specified parameter |
| * @return a visitor-specified result |
| */ |
| R visitTypeParameter(ReflectionTypeParameterElement e, P p); |
| |
| /** |
| * Visits an unknown kind of element. |
| * This can occur if the language evolves and new kinds |
| * of elements are added to the {@code Element} hierarchy. |
| * |
| * @param e the element to visit |
| * @param p a visitor-specified parameter |
| * @return a visitor-specified result |
| * @throws UnknownElementException |
| * a visitor implementation may optionally throw this exception |
| */ |
| R visitUnknown(ReflectionElement e, P p); |
| } |
| |
| /** |
| * A specialization of {@code javax.lang.model.element.ExecutableElement} that is |
| * backed by core reflection. |
| */ |
| public static interface ReflectionExecutableElement |
| extends ReflectionElement, ExecutableElement, ReflectionParameterizable { |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| List<ReflectionTypeParameterElement> getTypeParameters(); |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| List<ReflectionVariableElement> getParameters(); |
| |
| // Functionality specific to the specialization |
| /** |
| * Returns all parameters, including synthetic ones. |
| * @return all parameters, including synthetic ones |
| */ |
| List<ReflectionVariableElement> getAllParameters(); |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| Executable getSource(); |
| |
| /** |
| * Returns true if this executable is a synthetic construct; returns false otherwise. |
| * @return true if this executable is a synthetic construct; returns false otherwise |
| */ |
| boolean isSynthetic(); |
| |
| /** |
| * Returns true if this executable is a bridge method; returns false otherwise. |
| * @return true if this executable is a bridge method; returns false otherwise |
| */ |
| boolean isBridge(); |
| } |
| |
| /** |
| * A specialization of {@code javax.lang.model.element.PackageElement} being |
| * backed by core reflection. |
| */ |
| public static interface ReflectionPackageElement |
| extends ReflectionElement, PackageElement { |
| |
| // Functionality specific to the specialization |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| Package getSource(); |
| } |
| |
| /** |
| * A specialization of {@code javax.lang.model.element.TypeElement} that is |
| * backed by core reflection. |
| */ |
| public static interface ReflectionTypeElement |
| extends ReflectionElement, TypeElement, ReflectionParameterizable { |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| List<ReflectionTypeParameterElement> getTypeParameters(); |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| List<ReflectionElement> getEnclosedElements(); |
| |
| // Methods specific to the specialization, but functionality |
| // also present in javax.lang.model.util.Elements. |
| /** |
| * Returns all members of a type element, whether inherited or |
| * declared directly. For a class the result also includes its |
| * constructors, but not local or anonymous classes. |
| * @return all members of the type |
| */ |
| List<ReflectionElement> getAllMembers(); |
| |
| /** |
| * Returns the binary name of a type element. |
| * @return the binary name of a type element |
| */ |
| Name getBinaryName(); |
| |
| // Functionality specific to the specialization |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| Class<?> getSource(); |
| } |
| |
| /** |
| * A specialization of {@code javax.lang.model.element.TypeParameterElement} being |
| * backed by core reflection. |
| */ |
| public static interface ReflectionTypeParameterElement |
| extends ReflectionElement, TypeParameterElement { |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| ReflectionElement getGenericElement(); |
| |
| // Functionality specific to the specialization |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| java.lang.reflect.TypeVariable<?> getSource(); |
| } |
| |
| /** |
| * A specialization of {@code javax.lang.model.element.VariableElement} that is |
| * backed by core reflection. |
| */ |
| public static interface ReflectionVariableElement |
| extends ReflectionElement, VariableElement { |
| |
| // Functionality specific to the specialization |
| /** |
| * Returns true if this variable is a synthetic construct; returns false otherwise. |
| * @return true if this variable is a synthetic construct; returns false otherwise |
| */ |
| boolean isSynthetic(); |
| |
| /** |
| * Returns true if this variable is implicitly declared in source code; returns false otherwise. |
| * @return true if this variable is implicitly declared in source code; returns false otherwise |
| */ |
| boolean isImplicit(); |
| |
| // The VariableElement concept covers fields, variables, and |
| // method and constructor parameters. Therefore, this |
| // interface cannot define a more precise override of |
| // getSource since those three concept have different core |
| // reflection types with no supertype more precise than |
| // AnnotatedElement. |
| } |
| |
| /** |
| * A specialization of {@code javax.lang.model.element.Parameterizable} being |
| * backed by core reflection. |
| */ |
| public static interface ReflectionParameterizable |
| extends ReflectionElement, Parameterizable { |
| @Override |
| List<ReflectionTypeParameterElement> getTypeParameters(); |
| } |
| |
| /** |
| * Base class for concrete visitors of elements backed by core reflection. |
| */ |
| public static abstract class AbstractReflectionElementVisitor9<R, P> |
| extends AbstractElementVisitor9<R, P> |
| implements ReflectionElementVisitor<R, P> { |
| protected AbstractReflectionElementVisitor9() { |
| super(); |
| } |
| } |
| |
| /** |
| * Base class for simple visitors of elements that are backed by core reflection. |
| */ |
| @SupportedSourceVersion(value=RELEASE_9) |
| public static abstract class SimpleReflectionElementVisitor9<R, P> |
| extends SimpleElementVisitor9<R, P> |
| implements ReflectionElementVisitor<R, P> { |
| |
| protected SimpleReflectionElementVisitor9(){ |
| super(); |
| } |
| |
| protected SimpleReflectionElementVisitor9(R defaultValue) { |
| super(defaultValue); |
| } |
| |
| // Create manual "bridge methods" for now. |
| |
| @Override |
| public final R visitPackage(PackageElement e, P p) { |
| return visitPackage((ReflectionPackageElement) e , p); |
| } |
| |
| @Override |
| public final R visitType(TypeElement e, P p) { |
| return visitType((ReflectionTypeElement) e , p); |
| } |
| |
| @Override |
| public final R visitVariable(VariableElement e, P p) { |
| return visitVariable((ReflectionVariableElement) e , p); |
| } |
| |
| @Override |
| public final R visitExecutable(ExecutableElement e, P p) { |
| return visitExecutable((ReflectionExecutableElement) e , p); |
| } |
| |
| @Override |
| public final R visitTypeParameter(TypeParameterElement e, P p) { |
| return visitTypeParameter((ReflectionTypeParameterElement) e , p); |
| } |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| public static interface ReflectionElements extends Elements { |
| /** |
| * Returns the innermost enclosing {@link ReflectionTypeElement} |
| * of the {@link ReflectionElement} or {@code null} if the |
| * supplied ReflectionElement is toplevel or represents a |
| * Package. |
| * |
| * @param e the {@link ReflectionElement} whose innermost |
| * enclosing {@link ReflectionTypeElement} is sought |
| * @return the innermost enclosing {@link |
| * ReflectionTypeElement} or @{code null} if the parameter |
| * {@code e} is a toplevel element or a package |
| */ |
| ReflectionTypeElement getEnclosingTypeElement(ReflectionElement e); |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| List<? extends ReflectionElement> getAllMembers(TypeElement type); |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| ReflectionPackageElement getPackageElement(CharSequence name); |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| ReflectionPackageElement getPackageOf(Element type); |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| ReflectionTypeElement getTypeElement(CharSequence name); |
| } |
| |
| // ------------------------- Implementation classes ------------------------ |
| |
| // Exercise for the reader: review the CoreReflElement class |
| // hierarchy below with an eye toward exposing it as an extensible |
| // API that could be subclassed to provide customized behavior, |
| // such as alternate annotation lookup semantics. |
| |
| private static abstract class CoreReflElement |
| implements ReflectionElement, AnnotatedElement { |
| public abstract AnnotatedElement getSource(); |
| |
| protected CoreReflElement() { |
| super(); |
| } |
| |
| // ReflectionElement methods |
| @Override |
| public ReflectionPackageElement getPackage() { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public TypeMirror asType() { |
| throw new UnsupportedOperationException(getClass().toString()); |
| } |
| |
| @Override |
| public List<? extends AnnotationMirror> getAnnotationMirrors() { |
| Annotation[] annotations = getSource().getDeclaredAnnotations(); |
| int len = annotations.length; |
| |
| if (len > 0) { |
| List<AnnotationMirror> res = new ArrayList<>(len); |
| for (Annotation a : annotations) { |
| res.add(createMirror(a)); |
| } |
| return Collections.unmodifiableList(res); |
| } else { |
| return Collections.emptyList(); |
| } |
| } |
| |
| @Override |
| public Set<Modifier> getModifiers() { |
| return ModifierUtil.instance(0, false); |
| } |
| |
| @Override |
| public abstract Name getSimpleName(); |
| |
| @Override |
| public abstract ReflectionElement getEnclosingElement(); |
| |
| @Override |
| public abstract List<ReflectionElement> getEnclosedElements(); |
| |
| //AnnotatedElement methods |
| @Override |
| public <T extends Annotation> T getAnnotation(Class<T> annotationClass) { |
| return getSource().getAnnotation(annotationClass); |
| } |
| |
| @Override |
| public <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) { |
| return getSource().getAnnotationsByType(annotationClass); |
| } |
| |
| @Override |
| public Annotation[] getAnnotations() { |
| return getSource().getAnnotations(); |
| } |
| |
| @Override |
| public <T extends Annotation> T getDeclaredAnnotation(Class<T> annotationClass) { |
| return getSource().getDeclaredAnnotation(annotationClass); |
| } |
| |
| @Override |
| public <T extends Annotation> T[] getDeclaredAnnotationsByType(Class<T> annotationClass) { |
| return getSource().getDeclaredAnnotationsByType(annotationClass); |
| } |
| |
| @Override |
| public Annotation[] getDeclaredAnnotations() { |
| return getSource().getDeclaredAnnotations(); |
| } |
| |
| // java.lang.Object methods |
| @Override |
| public boolean equals(Object obj) { |
| if (obj instanceof CoreReflElement) { |
| CoreReflElement other = (CoreReflElement)obj; |
| return Objects.equals(other.getSource(), this.getSource()); |
| } |
| return false; |
| } |
| |
| @Override |
| public int hashCode() { |
| return Objects.hashCode(getSource()); |
| } |
| |
| @Override |
| public String toString() { |
| return getKind().toString() + " " + getSimpleName().toString(); |
| } |
| } |
| |
| // Type |
| private static class CoreReflTypeElement extends CoreReflElement |
| implements ReflectionTypeElement { |
| private final Class<?> source; |
| |
| protected CoreReflTypeElement(Class<?> source) { |
| Objects.requireNonNull(source); |
| if (source.isPrimitive() || |
| source.isArray()) { |
| throw new IllegalArgumentException("Cannot create a ReflectionTypeElement based on class: " + source); |
| } |
| |
| this.source = source; |
| } |
| |
| @Override |
| public TypeMirror asType() { |
| return createTypeMirror(source); |
| } |
| |
| @Override |
| public Class<?> getSource() { |
| return source; |
| } |
| |
| @Override |
| public boolean equals(Object o) { |
| if (o instanceof CoreReflTypeElement) { |
| return source.equals(((CoreReflTypeElement)o).getSource()); |
| } else { |
| return false; |
| } |
| } |
| |
| @Override |
| public <R,P> R accept(ElementVisitor<R,P> v, P p) { |
| return v.visitType(this, p); |
| } |
| |
| @Override |
| public <R,P> R accept(ReflectionElementVisitor<R,P> v, P p) { |
| return v.visitType(this, p); |
| } |
| |
| @Override |
| public Set<Modifier> getModifiers() { |
| return ModifierUtil.instance(source.getModifiers() & |
| (source.isInterface() ? |
| java.lang.reflect.Modifier.interfaceModifiers() : |
| java.lang.reflect.Modifier.classModifiers()), |
| false); |
| } |
| |
| @Override |
| public List<ReflectionElement> getEnclosedElements() { |
| List<ReflectionElement> enclosedElements = new ArrayList<>(); |
| |
| for (Class<?> declaredClass : source.getDeclaredClasses()) { |
| enclosedElements.add(createMirror(declaredClass)); |
| } |
| |
| // Add elements in the conventional ordering: fields, then |
| // constructors, then methods. |
| for (Field f : source.getDeclaredFields()) { |
| enclosedElements.add(createMirror(f)); |
| } |
| |
| for (Constructor<?> c : source.getDeclaredConstructors()) { |
| enclosedElements.add(createMirror(c)); |
| } |
| |
| for (Method m : source.getDeclaredMethods()) { |
| enclosedElements.add(createMirror(m)); |
| } |
| |
| return (enclosedElements.isEmpty() ? |
| Collections.emptyList(): |
| Collections.unmodifiableList(enclosedElements)); |
| } |
| |
| // Review for default method handling. |
| @Override |
| public List<ReflectionElement> getAllMembers() { |
| List<ReflectionElement> allMembers = new ArrayList<>(); |
| |
| // If I only had a MultiMap ... |
| List<ReflectionElement> fields = new ArrayList<>(); |
| List<ReflectionExecutableElement> methods = new ArrayList<>(); |
| List<ReflectionElement> classes = new ArrayList<>(); |
| |
| // Add all fields for this class |
| for (Field f : source.getDeclaredFields()) { |
| fields.add(createMirror(f)); |
| } |
| |
| // Add all methods for this class |
| for (Method m : source.getDeclaredMethods()) { |
| methods.add(createMirror(m)); |
| } |
| |
| // Add all classes for this class, except anonymous/local as per Elements.getAllMembers doc |
| for (Class<?> c : source.getDeclaredClasses()) { |
| if (c.isLocalClass() || c.isAnonymousClass()) |
| continue; |
| classes.add(createMirror(c)); |
| } |
| |
| Class<?> cls = source; |
| if (cls.isInterface()) { |
| cls = null; |
| } |
| do { |
| // Walk up superclasses adding non-private elements. |
| // If source is an interface, just add Object's |
| // elements. |
| |
| if (cls == null) { |
| cls = java.lang.Object.class; |
| } else { |
| cls = cls.getSuperclass(); |
| } |
| |
| addMembers(cls, fields, methods, classes); |
| |
| } while (cls != java.lang.Object.class); |
| |
| // add members on (super)interface(s) |
| Set<Class<?>> seenInterfaces = new HashSet<>(); |
| Queue<Class<?>> interfaces = new LinkedList<>(); |
| if (source.isInterface()) { |
| seenInterfaces.add(source); |
| interfaces.add(source); |
| } else { |
| Class<?>[] ifaces = source.getInterfaces(); |
| for (Class<?> iface : ifaces) { |
| seenInterfaces.add(iface); |
| interfaces.add(iface); |
| } |
| } |
| |
| while (interfaces.peek() != null) { |
| Class<?> head = interfaces.remove(); |
| addMembers(head, fields, methods, classes); |
| |
| Class<?>[] ifaces = head.getInterfaces(); |
| for (Class<?> iface : ifaces) { |
| if (!seenInterfaces.contains(iface)) { |
| seenInterfaces.add(iface); |
| interfaces.add(iface); |
| } |
| } |
| } |
| |
| // Add constructors |
| for (Constructor<?> c : source.getDeclaredConstructors()) { |
| allMembers.add(createMirror(c)); |
| } |
| |
| // Add all unique methods |
| allMembers.addAll(methods); |
| |
| // Add all unique fields |
| allMembers.addAll(fields); |
| |
| // Add all unique classes |
| allMembers.addAll(classes); |
| |
| return Collections.unmodifiableList(allMembers); |
| } |
| |
| private void addMembers(Class<?> cls, |
| List<ReflectionElement> fields, |
| List<ReflectionExecutableElement> methods, |
| List<ReflectionElement> classes) { |
| Elements elements = getElements(); |
| |
| for (Field f : cls.getDeclaredFields()) { |
| if (java.lang.reflect.Modifier.isPrivate(f.getModifiers())) { continue; } |
| ReflectionElement tmp = createMirror(f); |
| boolean add = true; |
| for (ReflectionElement e : fields) { |
| if (elements.hides(e, tmp)) { |
| add = false; |
| break; |
| } |
| } |
| if (add) { |
| fields.add(tmp); |
| } |
| } |
| |
| for (Method m : cls.getDeclaredMethods()) { |
| if (java.lang.reflect.Modifier.isPrivate(m.getModifiers())) |
| continue; |
| |
| ReflectionExecutableElement tmp = createMirror(m); |
| boolean add = true; |
| for (ReflectionExecutableElement e : methods) { |
| if (elements.hides(e, tmp)) { |
| add = false; |
| break; |
| } else if (elements.overrides(e, tmp, this)) { |
| add = false; |
| break; |
| } |
| } |
| if (add) { |
| methods.add(tmp); |
| } |
| } |
| |
| for (Class<?> c : cls.getDeclaredClasses()) { |
| if (java.lang.reflect.Modifier.isPrivate(c.getModifiers()) || |
| c.isLocalClass() || |
| c.isAnonymousClass()) |
| continue; |
| |
| ReflectionElement tmp = createMirror(c); |
| boolean add = true; |
| for (ReflectionElement e : classes) { |
| if (elements.hides(e, tmp)) { |
| add = false; |
| break; |
| } |
| } |
| if (add) { |
| classes.add(tmp); |
| } |
| } |
| } |
| |
| @Override |
| public ElementKind getKind() { |
| if (source.isInterface()) { |
| if (source.isAnnotation()) |
| return ElementKind.ANNOTATION_TYPE; |
| else |
| return ElementKind.INTERFACE; |
| } else if (source.isEnum()) { |
| return ElementKind.ENUM; |
| } else |
| return ElementKind.CLASS; |
| } |
| |
| @Override |
| public NestingKind getNestingKind() { |
| if (source.isAnonymousClass()) |
| return NestingKind.ANONYMOUS; |
| else if (source.isLocalClass()) |
| return NestingKind.LOCAL; |
| else if (source.isMemberClass()) |
| return NestingKind.MEMBER; |
| else return |
| NestingKind.TOP_LEVEL; |
| } |
| |
| @Override |
| public Name getQualifiedName() { |
| String name = source.getCanonicalName(); // TODO, this should be a FQN for |
| // the current element |
| if (name == null) |
| name = ""; |
| return StringName.instance(name); |
| } |
| |
| @Override |
| public Name getSimpleName() { |
| return StringName.instance(source.getSimpleName()); |
| } |
| |
| @Override |
| public TypeMirror getSuperclass() { |
| if (source.equals(java.lang.Object.class)) { |
| return NoType.getNoneInstance(); |
| } else { |
| return createTypeMirror(source.getSuperclass()); |
| } |
| } |
| |
| @Override |
| public List<? extends TypeMirror> getInterfaces() { |
| Class[] interfaces = source.getInterfaces(); |
| int len = interfaces.length; |
| List<TypeMirror> res = new ArrayList<>(len); |
| |
| if (len > 0) { |
| for (Class<?> c : interfaces) { |
| res.add(createTypeMirror(c)); |
| } |
| } else { |
| return Collections.emptyList(); |
| } |
| return Collections.unmodifiableList(res); |
| } |
| |
| @Override |
| public List<ReflectionTypeParameterElement> getTypeParameters() { |
| return createTypeParameterList(source); |
| } |
| |
| @Override |
| public ReflectionElement getEnclosingElement() { |
| // Returns the package of a top-level type and returns the |
| // immediately lexically enclosing element for a nested type. |
| |
| switch(getNestingKind()) { |
| case TOP_LEVEL: |
| return createMirror(source.getPackage()); |
| case MEMBER: |
| return createMirror(source.getEnclosingClass()); |
| default: |
| if (source.getEnclosingConstructor() != null) { |
| return createMirror(source.getEnclosingConstructor()); |
| } else if (source.getEnclosingMethod() != null) { |
| return createMirror(source.getEnclosingMethod()); |
| } else { |
| return createMirror(source.getEnclosingClass()); |
| } |
| } |
| } |
| |
| @Override |
| public Name getBinaryName() { |
| return StringName.instance(getSource().getName()); |
| } |
| } |
| |
| private static abstract class CoreReflExecutableElement extends CoreReflElement |
| implements ReflectionExecutableElement { |
| |
| protected Executable source = null; |
| protected final List<CoreReflParameterVariableElement> parameters; |
| |
| protected CoreReflExecutableElement(Executable source, |
| List<CoreReflParameterVariableElement> parameters) { |
| this.source = Objects.requireNonNull(source); |
| this.parameters = Objects.requireNonNull(parameters); |
| } |
| |
| @Override |
| public <R,P> R accept(ElementVisitor<R,P> v, P p) { |
| return v.visitExecutable(this, p); |
| } |
| |
| @Override |
| public <R,P> R accept(ReflectionElementVisitor<R,P> v, P p) { |
| return v.visitExecutable(this, p); |
| } |
| |
| @Override |
| public abstract ExecutableType asType(); |
| |
| // Only Types and Packages enclose elements; see Element.getEnclosedElements() |
| @Override |
| public List<ReflectionElement> getEnclosedElements() { |
| return Collections.emptyList(); |
| } |
| |
| @Override |
| public List<ReflectionVariableElement> getParameters() { |
| List<ReflectionVariableElement> tmp = new ArrayList<>(); |
| for (ReflectionVariableElement parameter : parameters) { |
| if (!parameter.isSynthetic()) |
| tmp.add(parameter); |
| } |
| return tmp; |
| } |
| |
| @Override |
| public List<ReflectionVariableElement> getAllParameters() { |
| // Could "fix" this if the return type included wildcards |
| @SuppressWarnings("unchecked") |
| List<ReflectionVariableElement> tmp = (List<ReflectionVariableElement>)(List)parameters; |
| return tmp; |
| } |
| |
| @Override |
| public List<? extends TypeMirror> getThrownTypes() { |
| Class<?>[] thrown = source.getExceptionTypes(); |
| int len = thrown.length; |
| List<TypeMirror> res = new ArrayList<>(len); |
| |
| if (len > 0) { |
| for (Class<?> c : thrown) { |
| res.add(createTypeMirror(c)); |
| } |
| } else { |
| return Collections.emptyList(); |
| } |
| return Collections.unmodifiableList(res); |
| } |
| |
| @Override |
| public boolean isVarArgs() { |
| return source.isVarArgs(); |
| } |
| |
| @Override |
| public boolean isSynthetic() { |
| return source.isSynthetic(); |
| } |
| |
| @Override |
| public boolean isBridge() { |
| return false; |
| } |
| |
| @Override |
| public List<ReflectionTypeParameterElement> getTypeParameters() { |
| return createTypeParameterList(source); |
| } |
| |
| public abstract AnnotationValue getDefaultValue(); |
| |
| @Override |
| public TypeMirror getReceiverType() { |
| // New in JDK 8 |
| throw new UnsupportedOperationException(this.toString()); |
| } |
| } |
| |
| private static class CoreReflConstructorExecutableElement |
| extends CoreReflExecutableElement { |
| |
| protected CoreReflConstructorExecutableElement(Constructor<?> source) { |
| super(Objects.requireNonNull(source), |
| createParameterList(source)); |
| } |
| |
| @Override |
| public Constructor<?> getSource() { |
| return (Constructor<?>)source; |
| } |
| |
| @Override |
| public TypeMirror getReturnType() { |
| return NoType.getVoidInstance(); |
| } |
| |
| @Override |
| public ExecutableType asType() { |
| throw new UnsupportedOperationException(getClass().toString()); |
| } |
| |
| @Override |
| public boolean equals(Object o) { |
| if (o instanceof CoreReflConstructorExecutableElement) { |
| return source.equals(((CoreReflConstructorExecutableElement)o).getSource()); |
| } else { |
| return false; |
| } |
| } |
| |
| @Override |
| public ElementKind getKind() { |
| return ElementKind.CONSTRUCTOR; |
| } |
| |
| @Override |
| public Set<Modifier> getModifiers() { |
| return ModifierUtil.instance(source.getModifiers() & |
| java.lang.reflect.Modifier.constructorModifiers(), false); |
| } |
| |
| @Override |
| public ReflectionElement getEnclosingElement() { |
| return createMirror(source.getDeclaringClass()); |
| } |
| |
| @Override |
| public Name getSimpleName() { |
| return StringName.instance("<init>"); |
| } |
| |
| @Override |
| public AnnotationValue getDefaultValue() { |
| // a constructor is never an annotation element |
| return null; |
| } |
| |
| @Override |
| public boolean isDefault() { |
| return false; // A constructor cannot be a default method |
| } |
| } |
| |
| private static class CoreReflMethodExecutableElement |
| extends CoreReflExecutableElement { |
| |
| protected CoreReflMethodExecutableElement(Method source) { |
| super(Objects.requireNonNull(source), |
| createParameterList(source)); |
| this.source = source; |
| } |
| |
| @Override |
| public Method getSource() { |
| return (Method)source; |
| } |
| |
| @Override |
| public TypeMirror getReturnType() { |
| return TypeFactory.instance(getSource().getReturnType()); |
| } |
| |
| @Override |
| public boolean equals(Object o) { |
| if (o instanceof CoreReflMethodExecutableElement) { |
| return source.equals( ((CoreReflMethodExecutableElement)o).getSource()); |
| } else { |
| return false; |
| } |
| } |
| |
| @Override |
| public ElementKind getKind() { |
| return ElementKind.METHOD; |
| } |
| |
| @Override |
| public Set<Modifier> getModifiers() { |
| return ModifierUtil.instance(source.getModifiers() & |
| java.lang.reflect.Modifier.methodModifiers(), |
| isDefault()); |
| } |
| |
| @Override |
| public ReflectionElement getEnclosingElement() { |
| return createMirror(source.getDeclaringClass()); |
| } |
| |
| @Override |
| public Name getSimpleName() { |
| return StringName.instance(source.getName()); |
| } |
| |
| @Override |
| public AnnotationValue getDefaultValue() { |
| Object value = getSource().getDefaultValue(); |
| if (null == value) { |
| return null; |
| } else { |
| return new CoreReflAnnotationValue(value); |
| } |
| } |
| |
| @Override |
| public boolean isDefault() { |
| return getSource().isDefault(); |
| } |
| |
| @Override |
| public boolean isBridge() { |
| return getSource().isBridge(); |
| } |
| |
| @Override |
| public ExecutableType asType() { |
| return TypeFactory.instance(getSource()); |
| } |
| } |
| |
| private static List<CoreReflParameterVariableElement> createParameterList(Executable source) { |
| Parameter[] parameters = source.getParameters(); |
| int length = parameters.length; |
| if (length == 0) |
| return Collections.emptyList(); |
| else { |
| List<CoreReflParameterVariableElement> tmp = new ArrayList<>(length); |
| for (Parameter parameter : parameters) { |
| tmp.add(new CoreReflParameterVariableElement(parameter)); |
| } |
| return Collections.unmodifiableList(tmp); |
| } |
| } |
| |
| private static List<ReflectionTypeParameterElement> createTypeParameterList(GenericDeclaration source) { |
| java.lang.reflect.TypeVariable<?>[] typeParams = source.getTypeParameters(); |
| int length = typeParams.length; |
| if (length == 0) |
| return Collections.emptyList(); |
| else { |
| List<ReflectionTypeParameterElement> tmp = new ArrayList<>(length); |
| for (java.lang.reflect.TypeVariable<?> typeVar : typeParams) |
| tmp.add(new CoreReflTypeParameterElement(typeVar)); |
| return Collections.unmodifiableList(tmp); |
| } |
| } |
| |
| private static class CoreReflTypeParameterElement |
| extends CoreReflElement |
| implements ReflectionTypeParameterElement { |
| |
| private final GenericDeclaration source; |
| private final java.lang.reflect.TypeVariable<?> sourceTypeVar; |
| |
| protected CoreReflTypeParameterElement(java.lang.reflect.TypeVariable<?> sourceTypeVar) { |
| this.sourceTypeVar = Objects.requireNonNull(sourceTypeVar); |
| this.source = Objects.requireNonNull(sourceTypeVar.getGenericDeclaration()); |
| } |
| |
| @Override |
| public java.lang.reflect.TypeVariable<?> getSource() { |
| return sourceTypeVar; |
| } |
| |
| protected java.lang.reflect.TypeVariable<?> getSourceTypeVar() { |
| return sourceTypeVar; |
| } |
| |
| @Override |
| public boolean equals(Object o) { |
| if (o instanceof CoreReflTypeParameterElement) { |
| return sourceTypeVar.equals(((CoreReflTypeParameterElement)o).sourceTypeVar); |
| } else { |
| return false; |
| } |
| } |
| |
| @Override |
| public <R,P> R accept(ElementVisitor<R,P> v, P p) { |
| return v.visitTypeParameter(this, p); |
| } |
| |
| @Override |
| public <R,P> R accept(ReflectionElementVisitor<R,P> v, P p) { |
| return v.visitTypeParameter(this, p); |
| } |
| |
| @Override |
| public List<ReflectionElement> getEnclosedElements() { |
| return Collections.emptyList(); |
| } |
| |
| @Override |
| public ReflectionElement getEnclosingElement() { |
| if (source instanceof Class) |
| return createMirror((Class<?>)source); |
| else if (source instanceof Method) |
| return createMirror((Method)source); |
| else if (source instanceof Constructor) |
| return createMirror((Constructor<?>)source); |
| else |
| throw new AssertionError("Unexpected enclosing element: " + source); |
| } |
| |
| @Override |
| public ElementKind getKind() { |
| return ElementKind.TYPE_PARAMETER; |
| } |
| |
| @Override |
| public Name getSimpleName() { |
| return StringName.instance(sourceTypeVar.getName()); |
| } |
| |
| // TypeParameterElement methods |
| @Override |
| public ReflectionElement getGenericElement() { |
| return getEnclosingElement(); // As per the doc, |
| // getEnclosingElement and |
| // getGenericElement return |
| // the same information. |
| } |
| |
| @Override |
| public List<? extends TypeMirror> getBounds() { |
| Type[] types = getSourceTypeVar().getBounds(); |
| int len = types.length; |
| |
| if (len > 0) { |
| List<TypeMirror> res = new ArrayList<>(len); |
| for (Type t : types) { |
| res.add(TypeFactory.instance(t)); |
| } |
| return Collections.unmodifiableList(res); |
| } else { |
| return Collections.emptyList(); |
| } |
| } |
| } |
| |
| private abstract static class CoreReflVariableElement extends CoreReflElement |
| implements ReflectionVariableElement { |
| |
| protected CoreReflVariableElement() {} |
| |
| // Element visitor |
| @Override |
| public <R,P> R accept(ElementVisitor<R,P>v, P p) { |
| return v.visitVariable(this, p); |
| } |
| |
| // ReflectElement visitor |
| @Override |
| public <R,P> R accept(ReflectionElementVisitor<R,P> v, P p) { |
| return v.visitVariable(this, p); |
| } |
| |
| @Override |
| public List<ReflectionElement> getEnclosedElements() { |
| return Collections.emptyList(); |
| } |
| |
| @Override |
| public ReflectionElement getEnclosingElement() { |
| return null; |
| } |
| |
| @Override |
| public boolean isSynthetic() { |
| return false; |
| } |
| |
| @Override |
| public boolean isImplicit() { |
| return false; |
| } |
| } |
| |
| private static class CoreReflFieldVariableElement extends CoreReflVariableElement { |
| private final Field source; |
| |
| protected CoreReflFieldVariableElement(Field source) { |
| this.source = Objects.requireNonNull(source); |
| } |
| |
| @Override |
| public Field getSource() { |
| return source; |
| } |
| |
| @Override |
| public TypeMirror asType() { |
| return createTypeMirror(getSource().getType()); |
| } |
| |
| @Override |
| public ElementKind getKind() { |
| if (source.isEnumConstant()) |
| return ElementKind.ENUM_CONSTANT; |
| else |
| return ElementKind.FIELD; |
| } |
| |
| @Override |
| public Set<Modifier> getModifiers() { |
| return ModifierUtil.instance(source.getModifiers() & |
| java.lang.reflect.Modifier.fieldModifiers(), false); |
| } |
| |
| @Override |
| public Name getSimpleName() { |
| return StringName.instance(source.getName()); |
| } |
| |
| @Override |
| public ReflectionElement getEnclosingElement() { |
| return createMirror(source.getDeclaringClass()); |
| } |
| |
| @Override |
| public boolean equals(Object o) { |
| if (o instanceof CoreReflFieldVariableElement) { |
| return Objects.equals(source, |
| ((CoreReflFieldVariableElement)o).getSource()); |
| } else { |
| return false; |
| } |
| } |
| |
| @Override |
| public Object getConstantValue() { |
| Field target = source; |
| |
| // The api says only Strings and primitives may be compile time constants. |
| // Ensure field is that, and final. |
| // |
| // Also, we don't have an instance so restrict to static Fields |
| // |
| if (!(source.getType().equals(java.lang.String.class) |
| || source.getType().isPrimitive())) { |
| return null; |
| } |
| final int modifiers = target.getModifiers(); |
| if (!( java.lang.reflect.Modifier.isFinal(modifiers) && |
| java.lang.reflect.Modifier.isStatic(modifiers))) { |
| return null; |
| } |
| |
| try { |
| return target.get(null); |
| } catch (IllegalAccessException e) { |
| try { |
| target.setAccessible(true); |
| return target.get(null); |
| } catch (IllegalAccessException i) { |
| throw new SecurityException(i); |
| } |
| } |
| } |
| } |
| |
| private static class CoreReflParameterVariableElement |
| extends CoreReflVariableElement { |
| private final Parameter source; |
| |
| protected CoreReflParameterVariableElement(Parameter source) { |
| this.source = Objects.requireNonNull(source); |
| } |
| |
| @Override |
| public Parameter getSource() { |
| return source; |
| } |
| |
| @Override |
| public Set<Modifier> getModifiers() { |
| return ModifierUtil.instance(source.getModifiers() & |
| java.lang.reflect.Modifier.parameterModifiers(), false); |
| } |
| |
| @Override |
| public TypeMirror asType() { |
| // TODO : switch to parameterized type |
| return createTypeMirror(source.getType()); |
| } |
| |
| @Override |
| public ElementKind getKind() { |
| return ElementKind.PARAMETER; |
| } |
| |
| @Override |
| public Name getSimpleName() { |
| return StringName.instance(source.getName()); |
| } |
| |
| @Override |
| public ReflectionElement getEnclosingElement() { |
| Executable enclosing = source.getDeclaringExecutable(); |
| if (enclosing instanceof Method) |
| return createMirror((Method)enclosing); |
| else if (enclosing instanceof Constructor) |
| return createMirror((Constructor<?>)enclosing); |
| else |
| throw new AssertionError("Bad enclosing value."); |
| } |
| |
| @Override |
| public boolean equals(Object o) { |
| if (o instanceof CoreReflParameterVariableElement) { |
| return source.equals(((CoreReflParameterVariableElement) o).getSource()); |
| } else |
| return false; |
| } |
| |
| // VariableElement methods |
| @Override |
| public Object getConstantValue() { |
| return null; |
| } |
| |
| @Override |
| public boolean isSynthetic() { |
| return source.isSynthetic(); |
| } |
| |
| @Override |
| public boolean isImplicit() { |
| return source.isImplicit(); |
| } |
| } |
| |
| private static class CoreReflPackageElement extends CoreReflElement |
| implements ReflectionPackageElement { |
| |
| private final Package source; |
| |
| protected CoreReflPackageElement(Package source) { |
| this.source = source; |
| } |
| |
| @Override |
| public Package getSource() { |
| return source; |
| } |
| |
| @Override |
| public <R,P> R accept(ElementVisitor<R,P> v, P p) { |
| return v.visitPackage(this, p); |
| } |
| |
| @Override |
| public <R,P> R accept(ReflectionElementVisitor<R,P> v, P p) { |
| return v.visitPackage(this, p); |
| } |
| |
| @Override |
| public boolean equals(Object o) { |
| if (o instanceof CoreReflPackageElement) { |
| return Objects.equals(source, |
| ((CoreReflPackageElement)o).getSource()); |
| } else { |
| return false; |
| } |
| } |
| |
| @Override |
| public ElementKind getKind() { |
| return ElementKind.PACKAGE; |
| } |
| |
| @Override |
| public ReflectionElement getEnclosingElement() { |
| return null; |
| } |
| |
| @Override |
| public List<ReflectionElement> getEnclosedElements() { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public Name getQualifiedName() { |
| return StringName.instance((source != null) ? |
| source.getName() : |
| "" ); |
| } |
| |
| @Override |
| public Name getSimpleName() { |
| String n = ((source != null) ? |
| source.getName() : |
| ""); |
| int index = n.lastIndexOf('.'); |
| if (index > 0) { |
| return StringName.instance(n.substring(index + 1, n.length())); |
| } else { |
| return StringName.instance(n); |
| } |
| } |
| |
| @Override |
| public boolean isUnnamed() { |
| if (source != null) { |
| String name = source.getName(); |
| return(name == null || name.isEmpty()); |
| } else |
| return true; |
| } |
| } |
| |
| private static class CoreReflAnnotationMirror |
| implements javax.lang.model.element.AnnotationMirror { |
| private final Annotation annotation; |
| |
| protected CoreReflAnnotationMirror(Annotation annotation) { |
| this.annotation = Objects.requireNonNull(annotation); |
| } |
| |
| @Override |
| public DeclaredType getAnnotationType() { |
| return (DeclaredType)TypeFactory.instance(annotation.annotationType()); |
| } |
| |
| @Override |
| public Map<? extends ReflectionExecutableElement, ? extends AnnotationValue> getElementValues() { |
| // This differs from the javac implementation in that it returns default values |
| |
| Method[] elems = annotation.annotationType().getDeclaredMethods(); |
| int len = elems.length; |
| |
| if (len > 0) { |
| Map<ReflectionExecutableElement, AnnotationValue> res = new HashMap<>(); |
| for (Method m : elems) { |
| AnnotationValue v; |
| try { |
| v = new CoreReflAnnotationValue(m.invoke(annotation)); |
| } catch (IllegalAccessException e) { |
| try { |
| m.setAccessible(true); |
| v = new CoreReflAnnotationValue(m.invoke(annotation)); |
| } catch (IllegalAccessException i) { |
| throw new SecurityException(i); |
| } catch (InvocationTargetException ee) { |
| throw new RuntimeException(ee); |
| } |
| } catch (InvocationTargetException ee) { |
| throw new RuntimeException(ee); |
| } |
| ReflectionExecutableElement e = createMirror(m); |
| res.put(e, v); |
| } |
| |
| return Collections.unmodifiableMap(res); |
| } else { |
| return Collections.emptyMap(); |
| } |
| } |
| |
| @Override |
| public boolean equals(Object other) { |
| if (other instanceof CoreReflAnnotationMirror) { |
| return annotation.equals(((CoreReflAnnotationMirror)other).annotation); |
| } else { |
| return false; |
| } |
| } |
| |
| @Override |
| public int hashCode() { |
| return Objects.hashCode(annotation); |
| } |
| |
| @Override |
| public String toString() { |
| return annotation.toString(); |
| } |
| } |
| |
| private static class CoreReflAnnotationValue |
| implements javax.lang.model.element.AnnotationValue { |
| private Object value = null; |
| |
| protected CoreReflAnnotationValue(Object value) { |
| // Is this constraint really necessary? |
| Objects.requireNonNull(value); |
| this.value = value; |
| } |
| |
| @Override |
| public Object getValue() { |
| return value; |
| } |
| |
| @Override |
| public String toString() { |
| return value.toString(); |
| } |
| |
| @Override |
| public <R,P> R accept(AnnotationValueVisitor<R,P> v, P p) { |
| return v.visit(this, p); |
| } |
| } |
| |
| // Helper utility classes |
| |
| private static class StringName implements Name { |
| private String name; |
| |
| private StringName(String name) { |
| this.name = Objects.requireNonNull(name); |
| } |
| |
| public static StringName instance(String name) { |
| return new StringName(name); |
| } |
| |
| @Override |
| public int length() { |
| return name.length(); |
| } |
| |
| @Override |
| public char charAt(int index) { |
| return name.charAt(index); |
| } |
| |
| @Override |
| public CharSequence subSequence(int start, int end) { |
| return name.subSequence(start, end); |
| } |
| |
| @Override |
| public String toString() { |
| return name; |
| } |
| |
| @Override |
| public boolean equals(Object other) { |
| if (other instanceof StringName) { |
| return name.equals(((StringName) other).name); |
| } else { |
| return false; |
| } |
| } |
| |
| @Override |
| public int hashCode() { |
| return name.hashCode(); |
| } |
| |
| @Override |
| public boolean contentEquals(CharSequence cs) { |
| return name.contentEquals(cs); |
| } |
| } |
| |
| /* |
| * Given an {@code int} value of modifiers, return a proper immutable set |
| * of {@code Modifier}s as a result. |
| */ |
| private static class ModifierUtil { |
| private ModifierUtil() { |
| throw new AssertionError("No instances for you."); |
| } |
| |
| // Exercise for the reader: explore if caching of sets of |
| // Modifiers would be helpful. |
| |
| public static Set<Modifier> instance(int modifiers, boolean isDefault) { |
| Set<Modifier> modSet = EnumSet.noneOf(Modifier.class); |
| |
| if (java.lang.reflect.Modifier.isAbstract(modifiers)) |
| modSet.add(Modifier.ABSTRACT); |
| |
| if (java.lang.reflect.Modifier.isFinal(modifiers)) |
| modSet.add(Modifier.FINAL); |
| |
| if (java.lang.reflect.Modifier.isNative(modifiers)) |
| modSet.add(Modifier.NATIVE); |
| |
| if (java.lang.reflect.Modifier.isPrivate(modifiers)) |
| modSet.add(Modifier.PRIVATE); |
| |
| if (java.lang.reflect.Modifier.isProtected(modifiers)) |
| modSet.add(Modifier.PROTECTED); |
| |
| if (java.lang.reflect.Modifier.isPublic(modifiers)) |
| modSet.add(Modifier.PUBLIC); |
| |
| if (java.lang.reflect.Modifier.isStatic(modifiers)) |
| modSet.add(Modifier.STATIC); |
| |
| if (java.lang.reflect.Modifier.isStrict(modifiers)) |
| modSet.add(Modifier.STRICTFP); |
| |
| if (java.lang.reflect.Modifier.isSynchronized(modifiers)) |
| modSet.add(Modifier.SYNCHRONIZED); |
| |
| if (java.lang.reflect.Modifier.isTransient(modifiers)) |
| modSet.add(Modifier.TRANSIENT); |
| |
| if (java.lang.reflect.Modifier.isVolatile(modifiers)) |
| modSet.add(Modifier.VOLATILE); |
| |
| if (isDefault) |
| modSet.add(Modifier.DEFAULT); |
| |
| return Collections.unmodifiableSet(modSet); |
| } |
| } |
| |
| private abstract static class AbstractTypeMirror implements TypeMirror { |
| private final TypeKind kind; |
| |
| protected AbstractTypeMirror(TypeKind kind) { |
| this.kind = Objects.requireNonNull(kind); |
| } |
| |
| @Override |
| public TypeKind getKind() { |
| return kind; |
| } |
| |
| @Override |
| public <R,P> R accept(TypeVisitor<R,P> v, P p) { |
| return v.visit(this, p); |
| } |
| |
| //Types methods |
| abstract List<? extends TypeMirror> directSuperTypes(); |
| |
| TypeMirror capture() { |
| // Exercise for the reader: make this abstract and implement in subtypes |
| throw new UnsupportedOperationException(); |
| } |
| |
| TypeMirror erasure() { |
| // Exercise for the reader: make this abstract and implement in subtypes |
| throw new UnsupportedOperationException(); |
| } |
| |
| // Exercise for the reader: implement the AnnotatedConstruct methods |
| @Override |
| public List<? extends AnnotationMirror> getAnnotationMirrors() { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public <T extends Annotation> T getAnnotation(Class<T> annotationClass) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public <T extends Annotation> T[] getAnnotationsByType(Class<T> annotationClass) { |
| throw new UnsupportedOperationException(); |
| } |
| } |
| |
| private static class CoreReflArrayType extends AbstractTypeMirror |
| implements javax.lang.model.type.ArrayType, |
| Reifiable { |
| private Class<?> source = null; |
| private Class<?> component = null; |
| private TypeMirror eagerComponent = null; |
| |
| protected CoreReflArrayType(Class<?> source) { |
| super(TypeKind.ARRAY); |
| this.source = source; |
| this.component = source.getComponentType(); |
| this.eagerComponent = TypeFactory.instance(component); |
| } |
| |
| public TypeMirror getComponentType() { |
| return eagerComponent; |
| } |
| |
| @Override |
| public Class<?> getSource() { |
| return source; |
| } |
| |
| @Override |
| List<? extends TypeMirror> directSuperTypes() { |
| final TypeMirror componentType = getComponentType(); |
| final TypeMirror[] directSupers; |
| |
| // JLS v4 4.10.3 |
| if (componentType.getKind().isPrimitive() || |
| component.equals(java.lang.Object.class)) { |
| directSupers = new TypeMirror[3]; |
| directSupers[0] = TypeFactory.instance(java.lang.Object.class); |
| directSupers[1] = TypeFactory.instance(java.lang.Cloneable.class); |
| directSupers[2] = TypeFactory.instance(java.io.Serializable.class); |
| } else if (componentType.getKind() == TypeKind.ARRAY) { |
| List<? extends TypeMirror> componentDirectSupertypes = CoreReflTypes.instance().directSupertypes(componentType); |
| directSupers = new TypeMirror[componentDirectSupertypes.size()]; |
| for (int i = 0; i < directSupers.length; i++) { |
| directSupers[i] = new CoreReflArrayType(Array.newInstance(((Reifiable)componentDirectSupertypes.get(i)).getSource(), 0).getClass()); |
| } |
| } else { |
| Class<?> superClass = component.getSuperclass(); |
| Class<?>[] interfaces = component.getInterfaces(); |
| directSupers = new TypeMirror[1 + interfaces.length]; |
| |
| directSupers[0] = TypeFactory.instance(Array.newInstance(superClass, 0).getClass()); |
| |
| for (int i = 0; i < interfaces.length; i++) { |
| directSupers[i + 1] = TypeFactory.instance(Array.newInstance(interfaces[i],0).getClass()); |
| } |
| } |
| |
| return Collections.unmodifiableList(Arrays.asList(directSupers)); |
| } |
| |
| @Override |
| public String toString() { |
| return getKind() + " of " + getComponentType().toString(); |
| } |
| } |
| |
| private static class CaptureTypeVariable extends AbstractTypeMirror implements javax.lang.model.type.TypeVariable { |
| private TypeMirror source = null; |
| private TypeMirror upperBound = null; |
| private TypeMirror lowerBound = null; |
| |
| CaptureTypeVariable(TypeMirror source, |
| TypeMirror upperBound, |
| TypeMirror lowerBound) { |
| super(TypeKind.TYPEVAR); |
| |
| this.source = Objects.requireNonNull(source); |
| this.upperBound = (upperBound == null ? CoreReflTypes.instance().getNullType() : upperBound); |
| this.lowerBound = (lowerBound == null ? CoreReflTypes.instance().getNullType() : lowerBound); |
| } |
| |
| protected Class<?> getSource() { |
| if (source instanceof CoreReflDeclaredType) { |
| return ((CoreReflDeclaredType)source).getSource(); |
| } else { |
| return null; |
| } |
| } |
| |
| @Override |
| public TypeMirror getUpperBound() { |
| return upperBound; |
| } |
| |
| @Override |
| public TypeMirror getLowerBound() { |
| return lowerBound; |
| } |
| |
| @Override |
| public Element asElement() { |
| if (null == getSource()) { |
| return null; |
| } |
| return CoreReflectionFactory.createMirror(getSource()); |
| } |
| |
| @Override |
| List<? extends TypeMirror> directSuperTypes() { |
| throw new UnsupportedOperationException(); |
| |
| } |
| |
| @Override |
| public String toString() { |
| return getKind() + " CAPTURE of: " + source.toString(); |
| } |
| } |
| |
| private static class CoreReflElements implements ReflectionElements { |
| private CoreReflElements() {} // mostly one instance for you |
| |
| private static CoreReflElements instance = new CoreReflElements(); |
| |
| static CoreReflElements instance() { |
| return instance; |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public ReflectionPackageElement getPackageElement(CharSequence name) { |
| return createMirror(Package.getPackage(name.toString())); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public ReflectionTypeElement getTypeElement(CharSequence name) { |
| // where name is a Canonical Name jls 6.7 |
| // but this method will probably accept an equivalent FQN |
| // depending on Class.forName(String) |
| |
| ReflectionTypeElement tmp = null; |
| |
| // Filter out arrays |
| String n = name.toString(); |
| if (n.contains("[")) return null; |
| if (n.equals("")) return null; |
| |
| // The intention of this loop is to handle nested |
| // elements. If finding the element using Class.forName |
| // fails, an attempt is made to find the element as an |
| // enclosed element by trying fo find a prefix of the name |
| // (dropping a trailing ".xyz") and looking for "xyz" as |
| // an enclosed element. |
| |
| Deque<String> parts = new ArrayDeque<>(); |
| boolean again; |
| do { |
| again = false; |
| try { |
| tmp = createMirror(Class.forName(n)); |
| } catch (ClassNotFoundException e) { |
| tmp = null; |
| } |
| |
| if (tmp != null) { |
| if (parts.isEmpty()) { |
| return tmp; |
| } |
| |
| tmp = findInner(tmp, parts); |
| if (tmp != null) { |
| return tmp; |
| } |
| } |
| |
| int indx = n.lastIndexOf('.'); |
| if (indx > -1) { |
| parts.addFirst(n.substring(indx + 1)); |
| n = n.substring(0, indx); |
| again = true; |
| } |
| } while (again); |
| |
| return null; |
| } |
| |
| // Recursively finds enclosed type elements named as part.top() popping part and repeating |
| private ReflectionTypeElement findInner(ReflectionTypeElement e, Deque<String> parts) { |
| if (parts.isEmpty()) { |
| return e; |
| } |
| |
| String part = parts.removeFirst(); |
| List<ReflectionElement> enclosed = e.getEnclosedElements(); |
| for (ReflectionElement elm : enclosed) { |
| if ((elm.getKind() == ElementKind.CLASS || |
| elm.getKind() == ElementKind.INTERFACE || |
| elm.getKind() == ElementKind.ENUM || |
| elm.getKind() == ElementKind.ANNOTATION_TYPE) |
| && elm.getSimpleName().toString().equals(part)) { |
| ReflectionTypeElement t = findInner((ReflectionTypeElement)elm, parts); |
| if (t != null) { |
| return t; |
| } |
| } |
| } |
| return null; |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public Map<? extends ReflectionExecutableElement, ? extends AnnotationValue> |
| getElementValuesWithDefaults(AnnotationMirror a) { |
| if (a instanceof CoreReflAnnotationMirror) { |
| return ((CoreReflAnnotationMirror)a).getElementValues(); |
| } else { |
| throw new IllegalArgumentException(); |
| } |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public String getDocComment(Element e) { |
| checkElement(e); |
| return null; // As per the doc |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public boolean isDeprecated(Element e) { |
| checkElement(e); |
| return ((CoreReflElement)e).getSource().isAnnotationPresent(java.lang.Deprecated.class); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public Name getBinaryName(TypeElement type) { |
| checkElement(type); |
| return StringName.instance(((CoreReflTypeElement)type) |
| .getSource() |
| .getName()); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public ReflectionPackageElement getPackageOf(Element type) { |
| checkElement(type); |
| if (type instanceof ReflectionPackageElement) { |
| return (ReflectionPackageElement)type; |
| } |
| |
| Package p; |
| if (type instanceof CoreReflTypeElement) { |
| p = ((CoreReflTypeElement)type).getSource().getPackage(); |
| } else { |
| CoreReflTypeElement enclosingTypeElement = (CoreReflTypeElement)getEnclosingTypeElement((ReflectionElement)type); |
| p = enclosingTypeElement.getSource().getPackage(); |
| } |
| |
| return createMirror(p); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public List<? extends ReflectionElement> getAllMembers(TypeElement type) { |
| checkElement(type); |
| return getAllMembers((ReflectionTypeElement)type); |
| } |
| |
| // Exercise for the reader: should this method, and similar |
| // ones that specialize on the more specific argument types, |
| // be addd to the public ReflectionElements API? |
| public List<? extends ReflectionElement> getAllMembers(ReflectionTypeElement type) { |
| return type.getAllMembers(); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public List<? extends AnnotationMirror> getAllAnnotationMirrors(Element e) { |
| checkElement(e); |
| AnnotatedElement ae = CoreReflElement.class.cast(e).getSource(); |
| Annotation[] annotations = ae.getAnnotations(); |
| int len = annotations.length; |
| |
| if (len > 0) { |
| List<AnnotationMirror> res = new ArrayList<>(len); |
| for (Annotation a : annotations) { |
| res.add(createMirror(a)); |
| } |
| return Collections.unmodifiableList(res); |
| } else { |
| List<AnnotationMirror> ret = Collections.emptyList(); |
| return ret; |
| } |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public boolean hides(Element hider, Element hidden) { |
| checkElement(hider); |
| checkElement(hidden); |
| |
| // Names must be equal |
| if (!hider.getSimpleName().equals(hidden.getSimpleName())) { |
| return false; |
| } |
| |
| // Hides isn't reflexive |
| if (hider.equals(hidden)) { |
| return false; |
| } |
| |
| // Hider and hidden needs to be field, method or type |
| // and fields hide fields, types hide types, methods hide methods |
| // IE a Field doesn't hide a Methods etc |
| ElementKind hiderKind = hider.getKind(); |
| ElementKind hiddenKind = hidden.getKind(); |
| if (hiderKind.isField() && !hiddenKind.isField()) { |
| return false; |
| } else if (hiderKind.isClass() && |
| !(hiddenKind.isClass() || hiddenKind.isInterface())) { |
| return false; |
| } else if (hiderKind.isInterface() && |
| !(hiddenKind.isClass() || hiddenKind.isInterface())) { |
| return false; |
| } else if (hiderKind == ElementKind.METHOD && hiddenKind != ElementKind.METHOD) { |
| return false; |
| } else if (!(hiderKind.isClass() || |
| hiderKind.isInterface() || |
| hiderKind.isField() || |
| hiderKind == ElementKind.METHOD)) { |
| return false; |
| } |
| |
| Set<Modifier> hm = hidden.getModifiers(); |
| // jls 8.4.8.2 only static methods can hide methods |
| if (hider.getKind() == ElementKind.METHOD) { |
| if (!hider.getModifiers().contains(Modifier.STATIC)) { |
| return false; // hider not static |
| } else if (!hm.contains(Modifier.STATIC)) { // we know it's a method |
| return false; // hidden not static |
| } |
| |
| // For methods we also need to check parameter types |
| Class<?>[] h1 = ((CoreReflMethodExecutableElement)hider).getSource().getParameterTypes(); |
| Class<?>[] h2 = ((CoreReflMethodExecutableElement)hidden).getSource().getParameterTypes(); |
| if (h1.length != h2.length) { |
| return false; |
| } |
| for (int i = 0; i < h1.length; i++) { |
| if (h1[i] != h2[i]) { |
| return false; |
| } |
| } |
| } |
| |
| // You can only hide visible elements |
| if (hm.contains(Modifier.PRIVATE)) { |
| return false; // hidden private, can't be hidden |
| } else if ((!(hm.contains(Modifier.PUBLIC) || hm.contains(Modifier.PROTECTED))) && // not private, not (public or protected) IE package private |
| (!getPackageOf(hider).equals(getPackageOf(hidden)))) { |
| return false; // hidden package private, and different packages, IE not visible |
| } |
| |
| // Ok so now hider actually hides hidden if hider is |
| // declared on a subtype of hidden. |
| // |
| // TODO: should this be a proper subtype or is that taken |
| // care of by the reflexive check in the beginning? |
| // |
| TypeMirror hiderType = getEnclosingTypeElement((ReflectionElement)hider).asType(); |
| TypeMirror hiddenType = getEnclosingTypeElement((ReflectionElement)hidden).asType(); |
| |
| return getTypes().isSubtype(hiderType, hiddenType); |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public ReflectionTypeElement getEnclosingTypeElement(ReflectionElement e) { |
| if (e.getKind() == ElementKind.PACKAGE) { |
| return null; |
| } |
| |
| if(e instanceof CoreReflTypeParameterElement) { |
| ReflectionElement encElem = ((CoreReflTypeParameterElement)e).getEnclosingElement(); |
| if (encElem instanceof ReflectionTypeElement) { |
| return (ReflectionTypeElement)encElem; |
| } else { |
| return getEnclosingTypeElement(encElem); |
| } |
| } |
| |
| Class<?> encl = null; |
| if (e instanceof CoreReflTypeElement) { |
| encl = ((CoreReflTypeElement)e).getSource().getDeclaringClass(); |
| } else if (e instanceof CoreReflExecutableElement) { |
| encl = (((CoreReflExecutableElement)e).getSource()).getDeclaringClass(); |
| } else if (e instanceof CoreReflFieldVariableElement) { |
| encl = ((CoreReflFieldVariableElement)e).getSource().getDeclaringClass(); |
| } else if (e instanceof CoreReflParameterVariableElement) { |
| encl = ((CoreReflParameterVariableElement)e).getSource().getDeclaringExecutable().getDeclaringClass(); |
| } |
| |
| return encl == null ? null : createMirror(encl); |
| } |
| |
| /** |
| *{@inheritDoc} |
| * |
| * Note that this implementation does not handle the situation |
| * where A overrides B and B overrides C but A does not |
| * directly override C. In this case, this implementation will |
| * erroneously return false. |
| */ |
| @Override |
| public boolean overrides(ExecutableElement overrider, ExecutableElement overridden, |
| TypeElement type) { |
| checkElement(overrider); |
| checkElement(overridden); |
| checkElement(type); |
| |
| // TODO handle transitive overrides |
| return overridesDirect(overrider, overridden, type); |
| } |
| |
| private boolean overridesDirect(ExecutableElement overrider, ExecutableElement overridden, |
| TypeElement type) { |
| // Should we check that at least one of the types |
| // overrider has is in fact a supertype of the TypeElement |
| // 'type' supplied? |
| |
| CoreReflExecutableElement rider = (CoreReflExecutableElement)overrider; |
| CoreReflExecutableElement ridden = (CoreReflExecutableElement)overridden; |
| CoreReflTypeElement riderType = (CoreReflTypeElement)type; |
| |
| // Names must match, redundant - see subsignature below |
| if (!rider.getSimpleName().equals(ridden.getSimpleName())) { |
| return false; |
| } |
| |
| // Constructors don't override |
| // TODO: verify this fact |
| if (rider.getKind() == ElementKind.CONSTRUCTOR || |
| ridden.getKind() == ElementKind.CONSTRUCTOR) { |
| return false; |
| } |
| |
| // Overridden must be visible to be overridden |
| // TODO Fix transitive visibility/override |
| Set<Modifier> rm = ridden.getModifiers(); |
| if (rm.contains(Modifier.PRIVATE)) { |
| return false; // overridden private, can't be overridden |
| } else if ((!(rm.contains(Modifier.PUBLIC) || rm.contains(Modifier.PROTECTED))) && // not private, not (public or protected) IE package private |
| (!getPackageOf(rider).equals(getPackageOf(ridden)))) { |
| return false; // ridden package private, and different packages, IE not visible |
| } |
| |
| // Static methods doesn't override |
| if (rm.contains(Modifier.STATIC) || |
| rider.getModifiers().contains(Modifier.STATIC)) { |
| return false; |
| } |
| |
| // Declaring class of overrider must be a subclass of declaring class of overridden |
| // except we use the parameter type as declaring class of overrider |
| if (!getTypes().isSubtype(riderType.asType(), getEnclosingTypeElement(ridden).asType())) { |
| return false; |
| } |
| |
| // Now overrider overrides overridden if the signature of rider is a subsignature of ridden |
| return getTypes().isSubsignature(rider.asType(), ridden.asType()); |
| } |
| |
| /** |
| *{@inheritDoc} |
| */ |
| @Override |
| public String getConstantExpression(Object value) { |
| return Constants.format(value); |
| } |
| |
| // If CoreReflectionFactory were a proper part of the JDK, the |
| // analogous functionality in javac could be reused. |
| private static class Constants { |
| /** |
| * Returns a string representation of a constant value (given in |
| * standard wrapped representation), quoted and formatted as in |
| * Java source. |
| */ |
| public static String format(Object value) { |
| if (value instanceof Byte) return formatByte((Byte) value); |
| if (value instanceof Short) return formatShort((Short) value); |
| if (value instanceof Long) return formatLong((Long) value); |
| if (value instanceof Float) return formatFloat((Float) value); |
| if (value instanceof Double) return formatDouble((Double) value); |
| if (value instanceof Character) return formatChar((Character) value); |
| if (value instanceof String) return formatString((String) value); |
| if (value instanceof Integer || |
| value instanceof Boolean) return value.toString(); |
| else |
| throw new IllegalArgumentException("Argument is not a primitive type or a string; it " + |
| ((value == null) ? |
| "is a null value." : |
| "has class " + |
| value.getClass().getName()) + "." ); |
| } |
| |
| private static String formatByte(byte b) { |
| return String.format("(byte)0x%02x", b); |
| } |
| |
| private static String formatShort(short s) { |
| return String.format("(short)%d", s); |
| } |
| |
| private static String formatLong(long lng) { |
| return lng + "L"; |
| } |
| |
| private static String formatFloat(float f) { |
| if (Float.isNaN(f)) |
| return "0.0f/0.0f"; |
| else if (Float.isInfinite(f)) |
| return (f < 0) ? "-1.0f/0.0f" : "1.0f/0.0f"; |
| else |
| return f + "f"; |
| } |
| |
| private static String formatDouble(double d) { |
| if (Double.isNaN(d)) |
| return "0.0/0.0"; |
| else if (Double.isInfinite(d)) |
| return (d < 0) ? "-1.0/0.0" : "1.0/0.0"; |
| else |
| return d + ""; |
| } |
| |
| private static String formatChar(char c) { |
| return '\'' + quote(c) + '\''; |
| } |
| |
| private static String formatString(String s) { |
| return '"' + quote(s) + '"'; |
| } |
| |
| /** |
| * Escapes each character in a string that has an escape sequence or |
| * is non-printable ASCII. Leaves non-ASCII characters alone. |
| */ |
| private static String quote(String s) { |
| StringBuilder buf = new StringBuilder(); |
| for (int i = 0; i < s.length(); i++) { |
| buf.append(quote(s.charAt(i))); |
| } |
| return buf.toString(); |
| } |
| |
| /** |
| * Escapes a character if it has an escape sequence or is |
| * non-printable ASCII. Leaves ASCII characters alone. |
| */ |
| private static String quote(char ch) { |
| switch (ch) { |
| case '\b': return "\\b"; |
| case '\f': return "\\f"; |
| case '\n': return "\\n"; |
| case '\r': return "\\r"; |
| case '\t': return "\\t"; |
| case '\'': return "\\'"; |
| case '\"': return "\\\""; |
| case '\\': return "\\\\"; |
| default: |
| return (isPrintableAscii(ch)) |
| ? String.valueOf(ch) |
| : String.format("\\u%04x", (int) ch); |
| } |
| } |
| |
| /** |
| * Is a character printable ASCII? |
| */ |
| private static boolean isPrintableAscii(char ch) { |
| return ch >= ' ' && ch <= '~'; |
| } |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public void printElements(Writer w, Element... elements) { |
| ElementVisitor<?, ?> printer = getPrinter(w); |
| try { |
| for (Element e : elements) { |
| checkElement(e); |
| printer.visit(e); |
| } |
| } finally { |
| try { |
| w.flush(); |
| } catch (java.io.IOException e) { /* Ignore */;} |
| } |
| } |
| |
| private ElementVisitor<?, ?> getPrinter(Writer w) { |
| // First try a reflective call into javac and if that |
| // fails, fallback to a very simple toString-based |
| // scanner. |
| try { |
| //reflective form of |
| // return new com.sun.tools.javac.processing.PrintingProcessor.PrintingElementVisitor(w, getElements()); |
| Class<?> printProcClass = |
| ClassLoader.getSystemClassLoader().loadClass("com.sun.tools.javac.processing.PrintingProcessor$PrintingElementVisitor"); |
| Constructor<?> printProcCtor = printProcClass.getConstructor(Writer.class, Elements.class); |
| return (ElementVisitor) printProcCtor.newInstance(w, getElements()); |
| } catch (ReflectiveOperationException | SecurityException e) { |
| return new ElementScanner9<Writer, Void>(w){ |
| @Override |
| public Writer scan(Element e, Void v) { |
| try { |
| DEFAULT_VALUE.append(e.toString()); |
| DEFAULT_VALUE.append("\n"); |
| } catch (java.io.IOException ioe) { |
| throw new RuntimeException(ioe); |
| } |
| return DEFAULT_VALUE; |
| } |
| }; |
| } |
| } |
| |
| /** |
| * {@inheritDoc} |
| */ |
| @Override |
| public Name getName(CharSequence cs) { |
| return StringName.instance(cs.toString()); |
| } |
| |
| private void checkElement(Element e) { |
| if(!(e instanceof CoreReflElement)) { |
| throw new IllegalArgumentException(); |
| } |
| } |
| |
| @Override |
| public boolean isFunctionalInterface(TypeElement e) { |
| throw new UnsupportedOperationException(); |
| // Update once this functionality is in core reflection |
| } |
| } |
| |
| private static class CoreReflTypes implements javax.lang.model.util.Types { |
| private static Types instance = new CoreReflTypes(); |
| |
| public static Types instance() { |
| return instance; |
| } |
| |
| // Private to suppress instantiation |
| private CoreReflTypes() {} |
| |
| // Types methods |
| @Override |
| public Element asElement(TypeMirror t) { |
| checkType(t); |
| if (t instanceof javax.lang.model.type.TypeVariable) { |
| ((javax.lang.model.type.TypeVariable)t).asElement(); |
| } else if (t instanceof DeclaredType) { |
| return ((DeclaredType)t).asElement(); |
| } |
| return null; |
| } |
| |
| @Override |
| public boolean isSameType(TypeMirror t1, TypeMirror t2) { |
| if (t1.getKind() != t2.getKind()) { |
| return false; |
| } |
| |
| if (t1.getKind() == TypeKind.WILDCARD || |
| t2.getKind() == TypeKind.WILDCARD) { |
| // Wildcards are not equal to any type |
| return false; |
| } |
| |
| if (t1 instanceof CoreReflDeclaredType && |
| t2 instanceof CoreReflDeclaredType) { |
| return ((CoreReflDeclaredType)t1).isSameType((CoreReflDeclaredType)t2); |
| } else if (t1 instanceof PrimitiveType && |
| t2 instanceof PrimitiveType) { |
| return t1.getKind() == t2.getKind(); |
| } else if (t1 instanceof NoType && |
| t2 instanceof NoType) { |
| return true; |
| } else if (t1 instanceof NullType && |
| t2 instanceof NullType) { |
| return true; |
| } else if (t1 instanceof ArrayType && |
| t2 instanceof ArrayType) { |
| return isSameType(((ArrayType)t1).getComponentType(), ((ArrayType)t2).getComponentType()); |
| } |
| |
| return false; |
| } |
| |
| @Override |
| public boolean isSubtype(TypeMirror t1, TypeMirror t2) { |
| checkType(t1); |
| checkType(t2); |
| |
| if (isSameType(t1, t2)) { |
| return true; |
| } else if(t1.getKind() == TypeKind.NULL) { |
| return true; |
| } |
| |
| // This depth first traversal should terminate due to the ban on circular inheritance |
| List<? extends TypeMirror> directSupertypes = directSupertypes(t1); |
| if (directSupertypes.isEmpty()) { |
| return false; |
| } |
| for (TypeMirror ti : directSupertypes) { |
| if (isSameType(ti, t2) || isSubtype(ti, t2)) { |
| return true; |
| } |
| } |
| return false; |
| } |
| |
| @Override |
| public boolean isAssignable(TypeMirror t1, TypeMirror t2) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public boolean contains(TypeMirror t1, TypeMirror t2) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public boolean isSubsignature(ExecutableType m1, ExecutableType m2) { |
| checkType(m1); |
| checkType(m2); |
| |
| ExecutableMethodType m0 = (ExecutableMethodType)m1; |
| |
| return m0.sameSignature((ExecutableMethodType)m2) || m0.sameSignature((ExecutableMethodType)erasure(m2)); |
| } |
| |
| @Override |
| public List<? extends TypeMirror> directSupertypes(TypeMirror t) { |
| checkType(t); |
| if (t instanceof ExecutableType || |
| t.getKind() == TypeKind.PACKAGE) { |
| throw new IllegalArgumentException("You can't ask for direct supertypes for type: " + t); |
| } |
| return ((AbstractTypeMirror)t).directSuperTypes(); |
| } |
| |
| @Override |
| public TypeMirror erasure(TypeMirror t) { |
| checkType(t); |
| return ((AbstractTypeMirror)t).erasure(); |
| } |
| |
| @Override |
| public TypeElement boxedClass(javax.lang.model.type.PrimitiveType p) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public PrimitiveType unboxedType(TypeMirror t) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public TypeMirror capture(TypeMirror t) { |
| checkType(t); |
| return ((AbstractTypeMirror)t).capture(); |
| } |
| |
| @Override |
| public PrimitiveType getPrimitiveType(TypeKind kind) { |
| return PrimitiveType.instance(kind); |
| } |
| |
| @Override |
| public NullType getNullType() { |
| return CoreReflNullType.getInstance(); |
| } |
| |
| @Override |
| public javax.lang.model.type.NoType getNoType(TypeKind kind) { |
| if (kind == TypeKind.NONE) { |
| return NoType.getNoneInstance(); |
| } else if (kind == TypeKind.VOID) { |
| return NoType.getVoidInstance(); |
| } else { |
| throw new IllegalArgumentException("No NoType of kind: " + kind); |
| } |
| } |
| |
| @Override |
| public ArrayType getArrayType(TypeMirror componentType) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public javax.lang.model.type.WildcardType getWildcardType(TypeMirror extendsBound, |
| TypeMirror superBound) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public DeclaredType getDeclaredType(TypeElement typeElem, TypeMirror... typeArgs) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public javax.lang.model.type.DeclaredType getDeclaredType(javax.lang.model.type.DeclaredType containing, |
| TypeElement typeElem, |
| TypeMirror... typeArgs) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public TypeMirror asMemberOf(javax.lang.model.type.DeclaredType containing, Element element) { |
| throw new UnsupportedOperationException(); |
| } |
| |
| private void checkType(TypeMirror t) { |
| if (!(t instanceof AbstractTypeMirror)) { |
| throw new IllegalArgumentException("This Types implementation can only operate on CoreReflectionFactory type classes"); |
| } |
| } |
| } |
| |
| private abstract static class CoreReflDeclaredType extends AbstractTypeMirror |
| implements javax.lang.model.type.DeclaredType { |
| private Class<?> source = null; |
| |
| private CoreReflDeclaredType(Class<?> source) { |
| super(TypeKind.DECLARED); |
| this.source = source; |
| } |
| |
| static DeclaredType instance(Class<?> source, Type genericSource) { |
| if (genericSource instanceof ParameterizedType) { |
| return new ParameterizedDeclaredType(source, (ParameterizedType)genericSource); |
| } else if (genericSource instanceof Class) { // This happens when a field has a raw type |
| if (!source.equals(genericSource)) { |
| throw new IllegalArgumentException("Don't know how to handle this"); |
| } |
| return instance(source); |
| } |
| throw new IllegalArgumentException("Don't know how to create a declared type from: " + |
| source + |
| " and genericSource " + |
| genericSource); |
| } |
| |
| static DeclaredType instance(Class<?> source) { |
| return new RawDeclaredType(source); |
| } |
| |
| protected Class<?> getSource() { |
| return source; |
| } |
| |
| @Override |
| public Element asElement() { |
| return CoreReflectionFactory.createMirror(getSource()); |
| } |
| |
| abstract boolean isSameType(DeclaredType other); |
| |
| @Override |
| TypeMirror capture() { |
| return new CaptureDeclaredType(this); |
| } |
| |
| private static class CaptureDeclaredType extends CoreReflDeclaredType { |
| CoreReflDeclaredType cap; |
| CaptureDeclaredType(CoreReflDeclaredType t) { |
| super(t.source); |
| this.cap = t; |
| } |
| |
| @Override |
| public List<? extends TypeMirror> getTypeArguments() { |
| List<? extends TypeMirror> wrapped = cap.getTypeArguments(); |
| ArrayList<TypeMirror> res = new ArrayList<>(wrapped.size()); |
| res.ensureCapacity(wrapped.size()); |
| |
| for (int i = 0; i < wrapped.size(); i++) { |
| TypeMirror t = wrapped.get(i); |
| |
| if (t instanceof javax.lang.model.type.WildcardType) { |
| res.add(i, convert(t)); |
| } else { |
| res.add(i, t); |
| } |
| } |
| return Collections.unmodifiableList(res); |
| } |
| |
| private TypeMirror convert(TypeMirror t) { |
| if (!(t instanceof javax.lang.model.type.WildcardType)) { |
| throw new IllegalArgumentException(); |
| } else { |
| javax.lang.model.type.WildcardType w = (javax.lang.model.type.WildcardType)t; |
| return TypeFactory.typeVariableInstance(w, w.getExtendsBound(), w.getSuperBound()); |
| } |
| } |
| |
| @Override |
| public TypeMirror getEnclosingType() { |
| return cap.getEnclosingType(); |
| } |
| |
| @Override |
| List<? extends TypeMirror> directSuperTypes() { |
| return cap.directSuperTypes(); |
| } |
| |
| @Override |
| boolean isSameType(DeclaredType other) { |
| return other == this; |
| } |
| |
| @Override |
| public String toString() { |
| return " CAPTURE of: " + cap.toString(); |
| } |
| } |
| |
| private static class RawDeclaredType extends CoreReflDeclaredType |
| implements Reifiable { |
| private RawDeclaredType(Class<?> source) { |
| super(source); |
| } |
| |
| @Override |
| public Class<?> getSource() { |
| return super.getSource(); |
| } |
| |
| @Override |
| public TypeMirror getEnclosingType() { |
| Class<?> enclosing = getSource().getEnclosingClass(); |
| if (null == enclosing) { |
| return NoType.getNoneInstance(); |
| } else { |
| return TypeFactory.instance(enclosing); |
| } |
| } |
| |
| @Override |
| public List<? extends TypeMirror> getTypeArguments() { |
| return Collections.emptyList(); |
| } |
| |
| @Override |
| List<? extends TypeMirror> directSuperTypes() { |
| if (getSource().isEnum()) { |
| return enumSuper(); |
| } |
| |
| if (getSource() == java.lang.Object.class) { |
| return Collections.emptyList(); |
| } |
| List<TypeMirror> res = new ArrayList<>(); |
| Type[] superInterfaces = getSource().getInterfaces(); |
| if (!getSource().isInterface()) { |
| res.add(TypeFactory.instance(getSource().getSuperclass())); |
| } else if (superInterfaces.length == 0) { |
| // Interfaces that don't extend another interface |
| // have java.lang.Object as a direct supertype. |
| return Collections.unmodifiableList(Arrays.asList(TypeFactory.instance(java.lang.Object.class))); |
| } |
| |
| for (Type t : superInterfaces) { |
| res.add(TypeFactory.instance(t)); |
| } |
| return Collections.unmodifiableList(res); |
| } |
| |
| private List<? extends TypeMirror> enumSuper() { |
| Class<?> rawSuper = getSource().getSuperclass(); |
| Type[] actualArgs = ((ParameterizedTypeImpl)getSource().getGenericSuperclass()).getActualTypeArguments(); |
| |
| // Reconsider this : assume the problem is making |
| // Enum<MyEnum> rather than just a raw enum. |
| return Collections.unmodifiableList(Arrays.asList(TypeFactory.instance(ParameterizedTypeImpl.make(rawSuper, |
| Arrays.copyOf(actualArgs, |
| actualArgs.length), |
| null)))); |
| } |
| |
| @Override |
| boolean isSameType(DeclaredType other) { |
| if (other instanceof RawDeclaredType) { |
| return Objects.equals(getSource(), ((RawDeclaredType)other).getSource()); |
| } else { |
| return false; |
| } |
| } |
| |
| @Override |
| public String toString() { |
| return getSource().toString(); |
| } |
| } |
| |
| private static class ParameterizedDeclaredType extends CoreReflDeclaredType { |
| private ParameterizedType genericSource = null; |
| private ParameterizedDeclaredType(Class<?> source, ParameterizedType genericSource) { |
| super(source); |
| this.genericSource = genericSource; |
| } |
| |
| @Override |
| public TypeMirror getEnclosingType() { |
| Type me = genericSource; |
| Type owner = GenericTypes.getEnclosingType(me); |
| if (owner == null) { |
| return NoType.getNoneInstance(); |
| } |
| return TypeFactory.instance(owner); |
| } |
| |
| @Override |
| public List<? extends TypeMirror> getTypeArguments() { |
| Type[] typeArgs = genericSource.getActualTypeArguments(); |
| |
| int length = typeArgs.length; |
| if (length == 0) |
| return Collections.emptyList(); |
| else { |
| List<TypeMirror> tmp = new ArrayList<>(length); |
| for (Type t : typeArgs) { |
| tmp.add(TypeFactory.instance(t)); |
| } |
| return Collections.unmodifiableList(tmp); |
| } |
| } |
| |
| @Override |
| List<? extends TypeMirror> directSuperTypes() { |
| if (getSource() == java.lang.Object.class) { |
| return Collections.emptyList(); |
| } |
| |
| List<TypeMirror> res = new ArrayList<>(); |
| Type[] superInterfaces = getSource().getGenericInterfaces(); |
| if (!getSource().isInterface()) { |
| // Replace actual type arguments with our type arguments |
| res.add(TypeFactory.instance(substituteTypeArgs(getSource().getGenericSuperclass()))); |
| } else if (superInterfaces.length == 0) { |
| // Interfaces that don't extend another interface |
| // have java.lang.Object as a direct supertype, plus |
| // possibly the interface's raw type |
| res.add(TypeFactory.instance(java.lang.Object.class)); |
| } |
| |
| for (Type t : superInterfaces) { |
| res.add(TypeFactory.instance(substituteTypeArgs(t))); |
| } |
| |
| res.add(TypeFactory.instance(getSource())); // Add raw type |
| return Collections.unmodifiableList(res); |
| } |
| |
| private Type substituteTypeArgs(Type type) { |
| if (!(type instanceof ParameterizedType)) { |
| return type; |
| } |
| |
| ParameterizedType target = (ParameterizedType)type; |
| // Cast to get a Class instead of a plain type. |
| Class<?> raw = ((ParameterizedTypeImpl)target).getRawType(); |
| Type[] actualArgs = genericSource.getActualTypeArguments(); |
| |
| return ParameterizedTypeImpl.make(raw, Arrays.copyOf(actualArgs, actualArgs.length), null); |
| } |
| |
| @Override |
| boolean isSameType(DeclaredType other) { |
| if (other instanceof ParameterizedDeclaredType) { |
| return GenericTypes.isSameGenericType(genericSource, |
| ((ParameterizedDeclaredType)other).genericSource); |
| } else { |
| return false; |
| } |
| } |
| |
| @Override |
| public String toString() { |
| return getKind().toString() + " " + genericSource.toString(); |
| } |
| } |
| |
| /** |
| * Implementing class for ParameterizedType interface. |
| * Derived from sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl |
| */ |
| |
| private static class ParameterizedTypeImpl implements ParameterizedType { |
| private Type[] actualTypeArguments; |
| private Class<?> rawType; |
| private Type ownerType; |
| |
| private ParameterizedTypeImpl(Class<?> rawType, |
| Type[] actualTypeArguments, |
| Type ownerType) { |
| this.actualTypeArguments = actualTypeArguments; |
| this.rawType = rawType; |
| if (ownerType != null) { |
| this.ownerType = ownerType; |
| } else { |
| this.ownerType = rawType.getDeclaringClass(); |
| } |
| validateConstructorArguments(); |
| } |
| |
| private void validateConstructorArguments() { |
| java.lang.reflect.TypeVariable/*<?>*/[] formals = rawType.getTypeParameters(); |
| // check correct arity of actual type args |
| if (formals.length != actualTypeArguments.length){ |
| throw new MalformedParameterizedTypeException(); |
| } |
| } |
| |
| /** |
| * Static factory. Given a (generic) class, actual type arguments |
| * and an owner type, creates a parameterized type. |
| * This class can be instantiated with a a raw type that does not |
| * represent a generic type, provided the list of actual type |
| * arguments is empty. |
| * If the ownerType argument is null, the declaring class of the |
| * raw type is used as the owner type. |
| * <p> This method throws a MalformedParameterizedTypeException |
| * under the following circumstances: |
| * If the number of actual type arguments (i.e., the size of the |
| * array {@code typeArgs}) does not correspond to the number of |
| * formal type arguments. |
| * If any of the actual type arguments is not an instance of the |
| * bounds on the corresponding formal. |
| * @param rawType the Class representing the generic type declaration being |
| * instantiated |
| * @param actualTypeArguments - a (possibly empty) array of types |
| * representing the actual type arguments to the parameterized type |
| * @param ownerType - the enclosing type, if known. |
| * @return An instance of {@code ParameterizedType} |
| * @throws MalformedParameterizedTypeException - if the instantiation |
| * is invalid |
| */ |
| public static ParameterizedTypeImpl make(Class<?> rawType, |
| Type[] actualTypeArguments, |
| Type ownerType) { |
| return new ParameterizedTypeImpl(rawType, actualTypeArguments, |
| ownerType); |
| } |
| |
| |
| /** |
| * Returns an array of {@code Type} objects representing the actual type |
| * arguments to this type. |
| * |
| * <p>Note that in some cases, the returned array be empty. This can occur |
| * if this type represents a non-parameterized type nested within |
| * a parameterized type. |
| * |
| * @return an array of {@code Type} objects representing the actual type |
| * arguments to this type |
| * @throws {@code TypeNotPresentException} if any of the |
| * actual type arguments refers to a non-existent type declaration |
| * @throws {@code MalformedParameterizedTypeException} if any of the |
| * actual type parameters refer to a parameterized type that cannot |
| * be instantiated for any reason |
| * @since 1.5 |
| */ |
| public Type[] getActualTypeArguments() { |
| return actualTypeArguments.clone(); |
| } |
| |
| /** |
| * Returns the {@code Type} object representing the class or interface |
| * that declared this type. |
| * |
| * @return the {@code Type} object representing the class or interface |
| * that declared this type |
| */ |
| public Class<?> getRawType() { |
| return rawType; |
| } |
| |
| |
| /** |
| * Returns a {@code Type} object representing the type that this type |
| * is a member of. For example, if this type is {@code O<T>.I<S>}, |
| * return a representation of {@code O<T>}. |
| * |
| * <p>If this type is a top-level type, {@code null} is returned. |
| * |
| * @return a {@code Type} object representing the type that |
| * this type is a member of. If this type is a top-level type, |
| * {@code null} is returned |
| */ |
| public Type getOwnerType() { |
| return ownerType; |
| } |
| |
| /* |
| * From the JavaDoc for java.lang.reflect.ParameterizedType |
| * "Instances of classes that implement this interface must |
| * implement an equals() method that equates any two instances |
| * that share the same generic type declaration and have equal |
| * type parameters." |
| */ |
| @Override |
| public boolean equals(Object o) { |
| if (o instanceof ParameterizedType) { |
| // Check that information is equivalent |
| ParameterizedType that = (ParameterizedType) o; |
| |
| if (this == that) |
| return true; |
| |
| Type thatOwner = that.getOwnerType(); |
| Type thatRawType = that.getRawType(); |
| |
| return Objects.equals(ownerType, thatOwner) && |
| Objects.equals(rawType, thatRawType) && |
| Arrays.equals(actualTypeArguments, // avoid clone |
| that.getActualTypeArguments()); |
| } else |
| return false; |
| } |
| |
| @Override |
| public int hashCode() { |
| return |
| Arrays.hashCode(actualTypeArguments) ^ |
| Objects.hashCode(ownerType) ^ |
| Objects.hashCode(rawType); |
| } |
| |
| public String toString() { |
| StringBuilder sb = new StringBuilder(); |
| |
| if (ownerType != null) { |
| if (ownerType instanceof Class) |
| sb.append(((Class)ownerType).getName()); |
| else |
| sb.append(ownerType.toString()); |
| |
| sb.append("."); |
| |
| if (ownerType instanceof ParameterizedTypeImpl) { |
| // Find simple name of nested type by removing the |
| // shared prefix with owner. |
| sb.append(rawType.getName().replace( ((ParameterizedTypeImpl)ownerType).rawType.getName() + "$", |
| "")); |
| } else |
| sb.append(rawType.getName()); |
| } else |
| sb.append(rawType.getName()); |
| |
| if (actualTypeArguments != null && |
| actualTypeArguments.length > 0) { |
| sb.append("<"); |
| boolean first = true; |
| for (Type t: actualTypeArguments) { |
| if (!first) |
| sb.append(", "); |
| if (t instanceof Class) |
| sb.append(((Class)t).getName()); |
| else |
| sb.append(t.toString()); |
| first = false; |
| } |
| sb.append(">"); |
| } |
| |
| return sb.toString(); |
| } |
| } |
| |
| } |
| |
| private static class ErasedMethodType extends ExecutableMethodType implements javax.lang.model.type.ExecutableType { |
| private final Method m; |
| |
| ErasedMethodType(Method m) { |
| super(m); |
| this.m = Objects.requireNonNull(m); |
| } |
| |
| @Override |
| public List<javax.lang.model.type.TypeVariable> getTypeVariables() { |
| return Collections.emptyList(); |
| } |
| |
| @Override |
| public List<? extends TypeMirror> getThrownTypes() { |
| Class<?>[] exceptions = m.getExceptionTypes(); |
| int len = exceptions.length; |
| |
| if (len > 0) { |
| List<TypeMirror> res = new ArrayList<TypeMirror>(len); |
| for (Class<?> t : exceptions) { |
| res.add(TypeFactory.instance(t)); |
| } |
| return Collections.unmodifiableList(res); |
| } else { |
| List<TypeMirror> ret = Collections.emptyList(); |
| return ret; |
| } |
| } |
| |
| @Override |
| public List<? extends TypeMirror> getParameterTypes() { |
| Class<?>[] params = m.getParameterTypes(); |
| int len = params.length; |
| |
| if (len > 0) { |
| List<TypeMirror> res = new ArrayList<TypeMirror>(len); |
| for (Class<?> t : params) { |
| res.add(TypeFactory.instance(t)); |
| } |
| return Collections.unmodifiableList(res); |
| } else { |
| List<TypeMirror> ret = Collections.emptyList(); |
| return ret; |
| } |
| } |
| |
| @Override |
| public TypeMirror getReturnType() { |
| return TypeFactory.instance(m.getReturnType()); |
| } |
| |
| @Override |
| TypeMirror erasure() { |
| return this; |
| } |
| } |
| |
| private static class ErrorType extends AbstractTypeMirror implements javax.lang.model.type.ErrorType { |
| private static ErrorType errorType = new ErrorType(); |
| |
| public static ErrorType getErrorInstance() { |
| return errorType; |
| } |
| |
| private ErrorType() { |
| super(TypeKind.ERROR); |
| } |
| |
| @Override |
| public List<? extends TypeMirror> getTypeArguments() { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public TypeMirror getEnclosingType() { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public Element asElement() { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| List<? extends TypeMirror> directSuperTypes() { |
| throw new UnsupportedOperationException(); |
| } |
| } |
| |
| private static class ExecutableMethodType extends AbstractTypeMirror |
| implements javax.lang.model.type.ExecutableType { |
| private final Method m; |
| |
| ExecutableMethodType(Method m) { |
| super(TypeKind.EXECUTABLE); |
| this.m = Objects.requireNonNull(m); |
| } |
| |
| @Override |
| public List<? extends TypeMirror> getThrownTypes() { |
| Type[] exceptions = m.getGenericExceptionTypes(); |
| int len = exceptions.length; |
| |
| if (len > 0) { |
| List<TypeMirror> res = new ArrayList<TypeMirror>(len); |
| for (Type t : exceptions) { |
| res.add(TypeFactory.instance(t)); |
| } |
| return Collections.unmodifiableList(res); |
| } else { |
| List<TypeMirror> ret = Collections.emptyList(); |
| return ret; |
| } |
| } |
| |
| @Override |
| public List<javax.lang.model.type.TypeVariable> getTypeVariables() { |
| java.lang.reflect.TypeVariable[] variables = m.getTypeParameters(); |
| int len = variables.length; |
| |
| if (len > 0) { |
| List<javax.lang.model.type.TypeVariable> res = new ArrayList<>(len); |
| for (java.lang.reflect.TypeVariable<?> t : variables) { |
| res.add(TypeFactory.typeVariableInstance(t)); |
| } |
| return Collections.unmodifiableList(res); |
| } else { |
| return Collections.emptyList(); |
| } |
| } |
| |
| @Override |
| public TypeMirror getReturnType() { |
| return TypeFactory.instance(m.getGenericReturnType()); |
| } |
| |
| @Override |
| public List<? extends TypeMirror> getParameterTypes() { |
| Type[] params = m.getGenericParameterTypes(); |
| int len = params.length; |
| |
| if (len > 0) { |
| List<TypeMirror> res = new ArrayList<TypeMirror>(len); |
| for (Type t : params) { |
| res.add(TypeFactory.instance(t)); |
| } |
| return Collections.unmodifiableList(res); |
| } else { |
| return Collections.emptyList(); |
| } |
| } |
| |
| @Override |
| List<? extends TypeMirror> directSuperTypes() { |
| // Spec says we don't need this |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| TypeMirror erasure() { |
| return new ErasedMethodType(m); |
| } |
| |
| @Override |
| public TypeMirror getReceiverType() { |
| throw new UnsupportedOperationException(); |
| } |
| |
| boolean sameSignature(ExecutableMethodType other){ |
| if (!m.getName().equals(other.m.getName())) { |
| return false; |
| } |
| |
| List<? extends TypeMirror> thisParams = getParameterTypes(); |
| List<? extends TypeMirror> otherParams = other.getParameterTypes(); |
| if (thisParams.size() != otherParams.size()) { |
| return false; |
| } |
| for (int i = 0; i < thisParams.size(); i++) { |
| if (!CoreReflTypes.instance().isSameType(thisParams.get(i), otherParams.get(i))) { |
| return false; |
| } |
| } |
| return true; |
| } |
| } |
| |
| private static class GenericTypes { |
| public static boolean isSameGenericType(Type t1, Type t2) { |
| if (t1 instanceof Class) { |
| return ((Class)t1).equals(t2); |
| } else if (t1 instanceof ParameterizedType) { |
| return ((ParameterizedType)t1).equals(t2); |
| } |
| throw new UnsupportedOperationException(); |
| } |
| |
| public static Type getEnclosingType(Type t1) { |
| if (t1 instanceof Class) { |
| return ((Class)t1).getEnclosingClass(); |
| } else if (t1 instanceof ParameterizedType) { |
| return ((ParameterizedType)t1).getOwnerType(); |
| } |
| throw new UnsupportedOperationException(); |
| } |
| } |
| |
| private static class IntersectionDeclaredType extends AbstractTypeMirror |
| implements javax.lang.model.type.DeclaredType { |
| private Type[] sources = null; |
| |
| IntersectionDeclaredType(Type[] sources) { |
| super(TypeKind.DECLARED); |
| this.sources = Arrays.copyOf(Objects.requireNonNull(sources), |
| sources.length); |
| } |
| |
| @Override |
| public TypeMirror getEnclosingType() { |
| return NoType.getNoneInstance(); |
| } |
| |
| @Override |
| public Element asElement() { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public List<? extends TypeMirror> getTypeArguments() { |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| List<? extends TypeMirror> directSuperTypes() { |
| int len = sources.length; |
| |
| if (len > 0) { |
| List<TypeMirror> res = new ArrayList<TypeMirror>(len); |
| for (Type c : sources) { |
| res.add(TypeFactory.instance(c)); |
| } |
| return Collections.unmodifiableList(res); |
| } else { |
| return Collections.emptyList(); |
| } |
| } |
| } |
| |
| private static class ModelWildcardType extends AbstractTypeMirror |
| implements javax.lang.model.type.WildcardType { |
| private java.lang.reflect.WildcardType genericSource; |
| |
| ModelWildcardType(java.lang.reflect.WildcardType genericSource) { |
| super(TypeKind.WILDCARD); |
| this.genericSource = Objects.requireNonNull(genericSource); |
| } |
| |
| @Override |
| List<? extends TypeMirror> directSuperTypes() { |
| // TODO Add support for this operation |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public TypeMirror getExtendsBound() { |
| Type[] t = genericSource.getUpperBounds(); |
| |
| if (t.length == 1) { |
| if (t[0].equals(Object.class) && getSuperBound() != null) { // can't have both lower and upper explicit |
| return null; |
| } |
| return TypeFactory.instance(t[0]); |
| } |
| throw new UnsupportedOperationException(); // TODO: intersection type? |
| } |
| |
| @Override |
| public TypeMirror getSuperBound() { |
| Type[] t = genericSource.getLowerBounds(); |
| |
| if (t.length == 0) { // bound is null |
| return null; |
| } else if (t.length == 1) { |
| return TypeFactory.instance(t[0]); |
| } |
| throw new UnsupportedOperationException(); // TODO: intersection type? |
| } |
| |
| @Override |
| public String toString() { |
| return getKind() + " " + genericSource.toString(); |
| } |
| } |
| |
| private static class NoType extends AbstractTypeMirror |
| implements javax.lang.model.type.NoType { |
| private static NoType noneType = new NoType(TypeKind.NONE, "none"); |
| private static NoType packageType = new NoType(TypeKind.PACKAGE, "package"); |
| private static NoType voidType = new NoType(TypeKind.VOID, "void"); |
| |
| private String str; |
| |
| public static NoType getNoneInstance() { |
| return noneType; |
| } |
| |
| public static NoType getPackageInstance() { |
| return packageType; |
| } |
| |
| public static NoType getVoidInstance() { |
| return voidType; |
| } |
| |
| private NoType(TypeKind k, String str) { |
| super(k); |
| this.str = str; |
| } |
| |
| @Override |
| List<? extends TypeMirror> directSuperTypes() { |
| // TODO We don't need this for the Package instance, how about the others? |
| throw new UnsupportedOperationException(); |
| } |
| |
| @Override |
| public String toString() { |
| return str; |
| } |
| } |
| |
| private static class CoreReflNullType extends AbstractTypeMirror |
| implements javax.lang.model.type.NullType { |
| private static CoreReflNullType nullType = new CoreReflNullType(); |
| |
| public static NullType getInstance() { |
| return nullType; |
| } |
| |
| private CoreReflNullType() { |
| super(TypeKind.NULL); |
| } |
| |
| @Override |
| List<? extends TypeMirror> directSuperTypes() { |
| // JLS 4.10.2 says: |
| // "The direct supertypes of the null type are all reference types other than the null type itself." |
| // TODO return null? an empty list? the error type? anyhow fix this |
| throw new UnsupportedOperationException(); |
| } |
| } |
| |
| private static interface Reifiable { |
| Class<?> getSource(); |
| } |
| |
| private static class PrimitiveType extends AbstractTypeMirror |
| implements javax.lang.model.type.PrimitiveType, |
| Reifiable { |
| private Class<?> source; |
| |
| private static PrimitiveType booleanInstance = new PrimitiveType(TypeKind.BOOLEAN, boolean.class); |
| private static PrimitiveType byteInstance = new PrimitiveType(TypeKind.BYTE, byte.class); |
| private static PrimitiveType charInstance = new PrimitiveType(TypeKind.CHAR, char.class); |
| private static PrimitiveType shortInstance = new PrimitiveType(TypeKind.SHORT, short.class); |
| private static PrimitiveType intInstance = new PrimitiveType(TypeKind.INT, int.class); |
| private static PrimitiveType longInstance = new PrimitiveType(TypeKind.LONG, long.class); |
| private static PrimitiveType floatInstance = new PrimitiveType(TypeKind.FLOAT, float.class); |
| private static PrimitiveType doubleInstance = new PrimitiveType(TypeKind.DOUBLE, double.class); |
| |
| private PrimitiveType(TypeKind kind, Class<?> source) { |
| super(kind); |
| this.source = source; |
| } |
| |
| @Override |
| public Class<?> getSource() { |
| return source; |
| } |
| |
| static PrimitiveType instance(Class<?> c) { |
| switch(c.getName()) { |
| case "boolean": |
| return booleanInstance; |
| case "byte": |
| return byteInstance; |
| case "char": |
| return charInstance; |
| case "short": |
| return shortInstance; |
| case "int": |
| return intInstance; |
| case "long": |
| return longInstance; |
| case "float": |
| return floatInstance; |
| case "double": |
| return doubleInstance; |
| default: |
| throw new IllegalArgumentException(); |
| } |
| } |
| |
| static PrimitiveType instance(TypeKind k) { |
| switch(k) { |
| case BOOLEAN: |
| return booleanInstance; |
| case BYTE: |
| return byteInstance; |
| case CHAR: |
| return charInstance; |
| case SHORT: |
| return shortInstance; |
| case INT: |
| return intInstance; |
| case LONG: |
| return longInstance; |
| case FLOAT: |
| return floatInstance; |
| case DOUBLE: |
| return doubleInstance; |
| default: |
| throw new IllegalArgumentException(); |
| } |
| } |
| |
| @Override |
| public String toString() { |
| return source.getName(); |
| } |
| |
| //Types methods |
| @Override |
| List<? extends TypeMirror> directSuperTypes() { |
| switch (getKind()) { |
| case DOUBLE: |
| return Collections.emptyList(); |
| case FLOAT: |
| return Arrays.asList(doubleInstance); |
| case LONG: |
| return Arrays.asList(floatInstance); |
| case INT: |
| return Arrays.asList(longInstance); |
| case CHAR: |
| return Arrays.asList(intInstance); |
| case SHORT: |
| return Arrays.asList(intInstance); |
| case BYTE: |
| return Arrays.asList(shortInstance); |
| default: |
| return Collections.emptyList(); |
| } |
| } |
| } |
| |
| private static class TypeFactory { |
| private TypeFactory() { }// no instances for you |
| |
| public static TypeMirror instance(Class<?> c) { |
| if (c.isPrimitive()) { |
| if (c.getName().equals("void")) { |
| return NoType.getVoidInstance(); |
| } else { |
| return PrimitiveType.instance(c); |
| } |
| } else if (c.isArray()) { |
| return new CoreReflArrayType(c); |
| } else if (c.isAnonymousClass() || |
| c.isLocalClass() || |
| c.isMemberClass() || |
| c.isInterface() || // covers annotations |
| c.isEnum()) { |
| return CoreReflDeclaredType.instance(c); |
| } else { // plain old class ?? |
| return CoreReflDeclaredType.instance(c); |
| } |
| } |
| |
| public static TypeMirror instance(Type t) { |
| if (t instanceof Class) { |
| return instance((Class)t); |
| } else if (t instanceof ParameterizedType) { |
| ParameterizedType tmp = (ParameterizedType)t; |
| Type raw = tmp.getRawType(); |
| if (!(raw instanceof Class)) { |
| throw new IllegalArgumentException(t + " " + raw ); |
| } |
| return CoreReflDeclaredType.instance((Class)raw, tmp); |
| } else if (t instanceof java.lang.reflect.WildcardType) { |
| return new ModelWildcardType((java.lang.reflect.WildcardType)t); |
| } else if (t instanceof java.lang.reflect.TypeVariable) { |
| return new CoreReflTypeVariable((java.lang.reflect.TypeVariable)t); |
| } |
| throw new IllegalArgumentException("Don't know how to make instance from: " + t.getClass()); |
| } |
| |
| public static TypeMirror instance(Field f) { |
| return CoreReflDeclaredType.instance(f.getType(), f.getGenericType()); |
| } |
| |
| public static ExecutableType instance(Method m) { |
| return new ExecutableMethodType(m); |
| } |
| |
| public static javax.lang.model.type.TypeVariable typeVariableInstance(java.lang.reflect.TypeVariable<?> v) { |
| return new CoreReflTypeVariable(v); |
| } |
| |
| public static javax.lang.model.type.TypeVariable typeVariableInstance(TypeMirror source, |
| TypeMirror upperBound, |
| TypeMirror lowerBound) { |
| return new CaptureTypeVariable(source, upperBound, lowerBound); |
| } |
| } |
| |
| private static class CoreReflTypeVariable extends AbstractTypeMirror |
| implements javax.lang.model.type.TypeVariable { |
| private final java.lang.reflect.TypeVariable<?> source; |
| private boolean isCapture = false; |
| |
| protected CoreReflTypeVariable(java.lang.reflect.TypeVariable<?> source) { |
| super(TypeKind.TYPEVAR); |
| Objects.requireNonNull(source); |
| this.source = source; |
| } |
| |
| @Override |
| public TypeMirror getUpperBound() { |
| return new IntersectionDeclaredType(source.getBounds()); |
| } |
| |
| @Override |
| public TypeMirror getLowerBound() { |
| return CoreReflTypes.instance().getNullType(); |
| } |
| |
| @Override |
| public Element asElement() { |
| return CoreReflectionFactory.createMirror(source); |
| } |
| |
| @Override |
| List<? extends TypeMirror> directSuperTypes() { |
| return ((AbstractTypeMirror)getUpperBound()).directSuperTypes(); |
| } |
| |
| @Override |
| public int hashCode() { |
| return source.hashCode(); |
| } |
| |
| @Override |
| public boolean equals(Object other) { |
| if (other instanceof CoreReflTypeVariable) { |
| return this.source.equals(((CoreReflTypeVariable)other).source); |
| } else { |
| return false; |
| } |
| } |
| } |
| } |