use of javax.lang.model.type.DeclaredType in project auto by google.
the class TypeSimplifierTest method testTypeMirrorSetWildcardCapture.
@Test
public void testTypeMirrorSetWildcardCapture() {
// TODO(emcmanus): this test should really be in MoreTypesTest.
// This test checks the assumption made by MoreTypes that you can find the
// upper bounds of a TypeVariable tv like this:
// TypeParameterElement tpe = (TypeParameterElement) tv.asElement();
// List<? extends TypeMirror> bounds = tpe.getBounds();
// There was some doubt as to whether this would be true in exotic cases involving
// wildcard capture, but apparently it is.
// The methods one and two here have identical signatures:
// abstract <T extends V, U extends T, V> Map<? extends T, ? super U> name();
// Their return types should be considered equal by TypeMirrorSet. The capture of
// each return type is different from the original return type, but the two captures
// should compare equal to each other. We also add various other types like ? super U
// to the set to ensure that the implied calls to the equals and hashCode visitors
// don't cause a ClassCastException for TypeParameterElement.
TypeElement wildcardsElement = typeElementOf(Wildcards.class);
List<? extends ExecutableElement> methods = ElementFilter.methodsIn(wildcardsElement.getEnclosedElements());
assertThat(methods).hasSize(2);
ExecutableElement one = methods.get(0);
ExecutableElement two = methods.get(1);
assertThat(one.getSimpleName().toString()).isEqualTo("one");
assertThat(two.getSimpleName().toString()).isEqualTo("two");
TypeMirrorSet typeMirrorSet = new TypeMirrorSet();
assertThat(typeMirrorSet.add(one.getReturnType())).isTrue();
assertThat(typeMirrorSet.add(two.getReturnType())).isFalse();
DeclaredType captureOne = (DeclaredType) typeUtils.capture(one.getReturnType());
assertThat(typeMirrorSet.add(captureOne)).isTrue();
DeclaredType captureTwo = (DeclaredType) typeUtils.capture(two.getReturnType());
assertThat(typeMirrorSet.add(captureTwo)).isFalse();
// Reminder: captureOne is Map<?#123 extends T, ?#456 super U>
TypeVariable extendsT = (TypeVariable) captureOne.getTypeArguments().get(0);
assertThat(typeMirrorSet.add(extendsT)).isTrue();
// NoType
assertThat(typeMirrorSet.add(extendsT.getLowerBound())).isTrue();
for (TypeMirror bound : ((TypeParameterElement) extendsT.asElement()).getBounds()) {
assertThat(typeMirrorSet.add(bound)).isTrue();
}
TypeVariable superU = (TypeVariable) captureOne.getTypeArguments().get(1);
assertThat(typeMirrorSet.add(superU)).isTrue();
assertThat(typeMirrorSet.add(superU.getLowerBound())).isTrue();
}
use of javax.lang.model.type.DeclaredType 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.DeclaredType 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.DeclaredType in project auto by google.
the class BuilderMethodClassifier method builderMethodReturnType.
/**
* Returns the return type of the given method from the builder. This should be the final type of
* the method when any bound type variables are substituted. Consider this example:
* <pre>{@code
* abstract static class ParentBuilder<B extends ParentBuilder> {
* B setFoo(String s);
* }
* abstract static class ChildBuilder extends ParentBuilder<ChildBuilder> {
* ...
* }
* }</pre>
* If the builder is {@code ChildBuilder} then the return type of {@code setFoo} is also
* {@code ChildBuilder}, and not {@code B} as its {@code getReturnType()} method would claim.
*
* <p>If the caller is in a version of Eclipse with
* <a href="https://bugs.eclipse.org/bugs/show_bug.cgi?id=382590">this bug</a> then the
* {@code asMemberOf} call will fail if the method is inherited from an interface. We work around
* that for methods in the {@code @AutoValue} class using {@link EclipseHack#methodReturnTypes}
* but we don't try to do so here because it should be much less likely. You might need to change
* {@code ParentBuilder} from an interface to an abstract class to make it work, but you'll often
* need to do that anyway.
*/
TypeMirror builderMethodReturnType(ExecutableElement builderMethod) {
DeclaredType builderTypeMirror = MoreTypes.asDeclared(builderType.asType());
TypeMirror methodMirror;
try {
methodMirror = typeUtils.asMemberOf(builderTypeMirror, builderMethod);
} catch (IllegalArgumentException e) {
// Presumably we've hit the Eclipse bug cited.
return builderMethod.getReturnType();
}
return MoreTypes.asExecutable(methodMirror).getReturnType();
}
use of javax.lang.model.type.DeclaredType in project auto by google.
the class Optionalish method isOptional.
static boolean isOptional(TypeMirror type) {
if (type.getKind() != TypeKind.DECLARED) {
return false;
}
DeclaredType declaredType = MoreTypes.asDeclared(type);
TypeElement typeElement = MoreElements.asType(declaredType.asElement());
return OPTIONAL_CLASS_NAMES.contains(typeElement.getQualifiedName().toString()) && typeElement.getTypeParameters().size() == declaredType.getTypeArguments().size();
}
Aggregations