blob: 6c6a32dc003f35c68d4d73a4ce84ec03dcac380c [file] [log] [blame]
/*
* 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;
}
}
}
}