use of javax.lang.model.type.TypeMirror in project auto by google.
the class AutoValueProcessor method getFieldOfClasses.
/**
* Returns the contents of a {@code Class[]}-typed field in an annotation.
*
* <p>This method is needed because directly reading the value of such a field from an
* AnnotationMirror throws: <pre>
* javax.lang.model.type.MirroredTypeException: Attempt to access Class object for TypeMirror Foo.
* </pre>
*
* @param element The element on which the annotation is present. e.g. the class being processed
* by AutoValue.
* @param annotation The class of the annotation to read from., e.g. {@link
* AutoValue.CopyAnnotations}.
* @param fieldName The name of the field to read, e.g. "exclude".
* @return a set of fully-qualified names of classes appearing in 'fieldName' on 'annotation' on
* 'element'.
*/
private ImmutableSet<String> getFieldOfClasses(Element element, Class<? extends Annotation> annotation, String fieldName, Elements elementUtils) {
TypeElement annotationElement = elementUtils.getTypeElement(annotation.getCanonicalName());
if (annotationElement == null) {
// This can happen if the annotation is on the -processorpath but not on the -classpath.
return ImmutableSet.of();
}
TypeMirror annotationMirror = annotationElement.asType();
for (AnnotationMirror annot : element.getAnnotationMirrors()) {
if (!typeUtils.isSameType(annot.getAnnotationType(), annotationMirror)) {
continue;
}
for (Map.Entry<? extends ExecutableElement, ? extends AnnotationValue> entry : annot.getElementValues().entrySet()) {
if (fieldName.contentEquals(entry.getKey().getSimpleName())) {
ImmutableSet.Builder<String> result = ImmutableSet.builder();
@SuppressWarnings("unchecked") List<AnnotationValue> annotationsToCopy = (List<AnnotationValue>) entry.getValue().getValue();
for (AnnotationValue annotationValue : annotationsToCopy) {
String qualifiedName = ((TypeElement) ((DeclaredType) annotationValue.getValue()).asElement()).getQualifiedName().toString();
result.add(qualifiedName);
}
return result.build();
}
}
}
return ImmutableSet.of();
}
use of javax.lang.model.type.TypeMirror in project auto by google.
the class AutoValueProcessor method defineVarsForType.
private TypeSimplifier defineVarsForType(TypeElement type, AutoValueTemplateVars vars, ImmutableSet<ExecutableElement> toBuilderMethods, ImmutableSet<ExecutableElement> propertyMethods, Optional<BuilderSpec.Builder> builder) {
DeclaredType declaredType = MoreTypes.asDeclared(type.asType());
Set<TypeMirror> types = new TypeMirrorSet();
types.addAll(returnTypesOf(propertyMethods));
if (builder.isPresent()) {
types.addAll(builder.get().referencedTypes());
}
TypeElement generatedTypeElement = processingEnv.getElementUtils().getTypeElement("javax.annotation.Generated");
if (generatedTypeElement != null) {
types.add(generatedTypeElement.asType());
}
TypeMirror javaUtilArrays = getTypeMirror(Arrays.class);
if (containsArrayType(types)) {
// If there are array properties then we will be referencing java.util.Arrays.
// Arrange to import it unless that would introduce ambiguity.
types.add(javaUtilArrays);
}
vars.toBuilderMethods = FluentIterable.from(toBuilderMethods).transform(SimpleMethodFunction.INSTANCE).toList();
ImmutableSetMultimap<ExecutableElement, String> excludedAnnotationsMap = allMethodExcludedAnnotations(propertyMethods);
types.addAll(allMethodAnnotationTypes(propertyMethods, excludedAnnotationsMap));
String pkg = TypeSimplifier.packageNameOf(type);
TypeSimplifier typeSimplifier = new TypeSimplifier(typeUtils, pkg, types, declaredType);
vars.imports = typeSimplifier.typesToImport();
vars.generated = generatedTypeElement == null ? "" : typeSimplifier.simplify(generatedTypeElement.asType());
vars.arrays = typeSimplifier.simplify(javaUtilArrays);
ImmutableBiMap<ExecutableElement, String> methodToPropertyName = propertyNameToMethodMap(propertyMethods).inverse();
Map<ExecutableElement, String> methodToIdentifier = Maps.newLinkedHashMap(methodToPropertyName);
fixReservedIdentifiers(methodToIdentifier);
List<Property> props = new ArrayList<Property>();
EclipseHack eclipseHack = eclipseHack();
ImmutableMap<ExecutableElement, TypeMirror> returnTypes = eclipseHack.methodReturnTypes(propertyMethods, declaredType);
for (ExecutableElement method : propertyMethods) {
TypeMirror returnType = returnTypes.get(method);
String propertyType = typeSimplifier.simplify(returnType);
String propertyName = methodToPropertyName.get(method);
String identifier = methodToIdentifier.get(method);
ImmutableSet<String> excludedAnnotations = ImmutableSet.<String>builder().addAll(excludedAnnotationsMap.get(method)).add(Override.class.getCanonicalName()).build();
Property p = new Property(propertyName, identifier, method, propertyType, typeSimplifier, excludedAnnotations);
props.add(p);
if (p.isNullable() && returnType.getKind().isPrimitive()) {
errorReporter.reportError("Primitive types cannot be @Nullable", method);
}
}
// If we are running from Eclipse, undo the work of its compiler which sorts methods.
eclipseHack.reorderProperties(props);
vars.props = ImmutableSet.copyOf(props);
vars.serialVersionUID = getSerialVersionUID(type);
vars.formalTypes = typeSimplifier.formalTypeParametersString(type);
vars.actualTypes = TypeSimplifier.actualTypeParametersString(type);
vars.wildcardTypes = wildcardTypeParametersString(type);
// Check for @AutoValue.Builder and add appropriate variables if it is present.
if (builder.isPresent()) {
builder.get().defineVars(vars, typeSimplifier, methodToPropertyName);
}
return typeSimplifier;
}
use of javax.lang.model.type.TypeMirror in project auto by google.
the class Key method create.
/**
* Constructs a key based on the type {@code type} and any {@link Qualifier}s in {@code
* annotations}.
*
* <p>If {@code type} is a {@code Provider<T>}, the returned {@link Key}'s {@link #type()} is
* {@code T}. If {@code type} is a primitive, the returned {@link Key}'s {@link #type()} is the
* corresponding {@linkplain Types#boxedClass(PrimitiveType) boxed type}.
*
* <p>For example:
* <table>
* <tr><th>Input type <th>{@code Key.type()}
* <tr><td>{@code String} <td>{@code String}
* <tr><td>{@code Provider<String>} <td>{@code String}
* <tr><td>{@code int} <td>{@code Integer}
* </table>
*/
static Key create(TypeMirror type, Iterable<? extends AnnotationMirror> annotations, Types types) {
ImmutableSet.Builder<AnnotationMirror> qualifiers = ImmutableSet.builder();
for (AnnotationMirror annotation : annotations) {
if (isAnnotationPresent(annotation.getAnnotationType().asElement(), Qualifier.class)) {
qualifiers.add(annotation);
}
}
// TODO(gak): check for only one qualifier rather than using the first
Optional<AnnotationMirror> qualifier = FluentIterable.from(qualifiers.build()).first();
TypeMirror keyType = isProvider(type) ? MoreTypes.asDeclared(type).getTypeArguments().get(0) : boxedType(type, types);
return new AutoValue_Key(keyType, wrapOptionalInEquivalence(AnnotationMirrors.equivalence(), qualifier));
}
use of javax.lang.model.type.TypeMirror in project auto by google.
the class TypeSimplifier method findImports.
/**
* Given a set of referenced types, works out which of them should be imported and what the
* resulting spelling of each one is.
*
* <p>This method operates on a {@code Set<TypeMirror>} rather than just a {@code Set<String>}
* because it is not strictly possible to determine what part of a fully-qualified type name is
* the package and what part is the top-level class. For example, {@code java.util.Map.Entry} is
* a class called {@code Map.Entry} in a package called {@code java.util} assuming Java
* conventions are being followed, but it could theoretically also be a class called {@code Entry}
* in a package called {@code java.util.Map}. Since we are operating as part of the compiler, our
* goal should be complete correctness, and the only way to achieve that is to operate on the real
* representations of types.
*
* @param packageName The name of the package where the class containing these references is
* defined. Other classes within the same package do not need to be imported.
* @param referenced The complete set of declared types (classes and interfaces) that will be
* referenced in the generated code.
* @param defined The complete set of declared types (classes and interfaces) that are defined
* within the scope of the generated class (i.e. nested somewhere in its superclass chain,
* or in its interface set)
* @return a map where the keys are fully-qualified types and the corresponding values indicate
* whether the type should be imported, and how the type should be spelled in the source code.
*/
private static Map<String, Spelling> findImports(Types typeUtils, String packageName, Set<TypeMirror> referenced, Set<TypeMirror> defined) {
Map<String, Spelling> imports = new HashMap<String, Spelling>();
Set<TypeMirror> typesInScope = new TypeMirrorSet();
typesInScope.addAll(referenced);
typesInScope.addAll(defined);
Set<String> ambiguous = ambiguousNames(typeUtils, typesInScope);
for (TypeMirror type : referenced) {
TypeElement typeElement = (TypeElement) typeUtils.asElement(type);
String fullName = typeElement.getQualifiedName().toString();
String simpleName = typeElement.getSimpleName().toString();
String pkg = packageNameOf(typeElement);
boolean importIt;
String spelling;
if (ambiguous.contains(simpleName)) {
importIt = false;
spelling = fullName;
} else if (pkg.equals(packageName) || pkg.equals("java.lang")) {
importIt = false;
spelling = fullName.substring(pkg.isEmpty() ? 0 : pkg.length() + 1);
} else {
importIt = true;
spelling = simpleName;
}
imports.put(fullName, new Spelling(spelling, importIt));
}
return imports;
}
use of javax.lang.model.type.TypeMirror in project auto by google.
the class TypeSimplifier method referencedClassTypes.
/**
* Finds all declared types (classes and interfaces) that are referenced in the given
* {@code Set<TypeMirror>}. This includes classes and interfaces that appear directly in the set,
* but also ones that appear in type parameters and the like. For example, if the set contains
* {@code java.util.List<? extends java.lang.Number>} then both {@code java.util.List} and
* {@code java.lang.Number} will be in the resulting set.
*
* <p>The returned set contains only top-level types. If we reference {@code java.util.Map.Entry}
* then the returned set will contain {@code java.util.Map}. This is because we want to write
* {@code Map.Entry} everywhere rather than {@code Entry}.
*/
private static Set<TypeMirror> referencedClassTypes(Types typeUtil, Set<TypeMirror> types) {
Set<TypeMirror> allReferenced = new TypeMirrorSet();
ReferencedClassTypeVisitor referencedClassVisitor = new ReferencedClassTypeVisitor(typeUtil, allReferenced);
for (TypeMirror type : types) {
referencedClassVisitor.visit(type);
}
Set<TypeMirror> topLevelReferenced = new TypeMirrorSet();
for (TypeMirror type : allReferenced) {
TypeElement typeElement = MoreElements.asType(typeUtil.asElement(type));
topLevelReferenced.add(topLevelType(typeElement).asType());
}
return topLevelReferenced;
}
Aggregations