Search in sources :

Example 31 with DeclaredType

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();
}
Also used : TypeVariable(javax.lang.model.type.TypeVariable) TypeMirror(javax.lang.model.type.TypeMirror) TypeElement(javax.lang.model.element.TypeElement) ExecutableElement(javax.lang.model.element.ExecutableElement) DeclaredType(javax.lang.model.type.DeclaredType) TypeParameterElement(javax.lang.model.element.TypeParameterElement) Test(org.junit.Test)

Example 32 with DeclaredType

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();
}
Also used : TypeElement(javax.lang.model.element.TypeElement) AnnotationMirror(javax.lang.model.element.AnnotationMirror) ImmutableSet(com.google.common.collect.ImmutableSet) TypeMirror(javax.lang.model.type.TypeMirror) AnnotationValue(javax.lang.model.element.AnnotationValue) List(java.util.List) ArrayList(java.util.ArrayList) ImmutableList(com.google.common.collect.ImmutableList) Map(java.util.Map) ImmutableMap(com.google.common.collect.ImmutableMap) ImmutableBiMap(com.google.common.collect.ImmutableBiMap) DeclaredType(javax.lang.model.type.DeclaredType)

Example 33 with DeclaredType

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;
}
Also used : TypeElement(javax.lang.model.element.TypeElement) ExecutableElement(javax.lang.model.element.ExecutableElement) ArrayList(java.util.ArrayList) TypeMirror(javax.lang.model.type.TypeMirror) DeclaredType(javax.lang.model.type.DeclaredType)

Example 34 with DeclaredType

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();
}
Also used : TypeMirror(javax.lang.model.type.TypeMirror) DeclaredType(javax.lang.model.type.DeclaredType)

Example 35 with DeclaredType

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();
}
Also used : TypeElement(javax.lang.model.element.TypeElement) DeclaredType(javax.lang.model.type.DeclaredType)

Aggregations

DeclaredType (javax.lang.model.type.DeclaredType)138 TypeElement (javax.lang.model.element.TypeElement)82 TypeMirror (javax.lang.model.type.TypeMirror)75 ExecutableElement (javax.lang.model.element.ExecutableElement)38 Element (javax.lang.model.element.Element)28 VariableElement (javax.lang.model.element.VariableElement)26 AnnotationMirror (javax.lang.model.element.AnnotationMirror)19 Test (org.junit.Test)19 ArrayType (javax.lang.model.type.ArrayType)15 ArrayList (java.util.ArrayList)14 List (java.util.List)10 Map (java.util.Map)9 AbstractJClass (com.helger.jcodemodel.AbstractJClass)8 HashSet (java.util.HashSet)8 AnnotationValue (javax.lang.model.element.AnnotationValue)8 HashMap (java.util.HashMap)6 TypeParameterElement (javax.lang.model.element.TypeParameterElement)6 Types (javax.lang.model.util.Types)6 Name (javax.lang.model.element.Name)5 PackageElement (javax.lang.model.element.PackageElement)5