private static TypeName[] getBounds(TypeParameterElement typeParameterElement) { final TypeName[] bounds = new TypeName[typeParameterElement.getBounds().size()]; for (int i = 0, size = typeParameterElement.getBounds().size(); i < size; i++) { bounds[i] = TypeName.get(typeParameterElement.getBounds().get(i)); } return bounds; } }
List<TypeMirror> getExplicitBounds(TypeParameterElement typeParam) { return newArrayList(Iterables.filter(typeParam.getBounds(), notObject)); }
@Override @SuppressWarnings({"unchecked"}) protected boolean doEquivalent(TypeParameterElement arg0, TypeParameterElement arg1) { // Casts are necessary due to flaw in pairwise equivalence implementation. return typeMirrorEq.pairwise().equivalent((List<TypeMirror>) arg0.getBounds(), (List<TypeMirror>) arg1.getBounds()); }
/** Returns type variable equivalent to {@code element}. */ public static TypeVariableName get(TypeParameterElement element) { String name = element.getSimpleName().toString(); List<? extends TypeMirror> boundsMirrors = element.getBounds(); List<TypeName> boundsTypeNames = new ArrayList<>(); for (TypeMirror typeMirror : boundsMirrors) { boundsTypeNames.add(TypeName.get(typeMirror)); } return TypeVariableName.of(name, boundsTypeNames); }
private List<Type.Defined> getBounds(Type.Parameters parameters, TypeParameterElement p) { List<Type.Defined> bounds = new ArrayList<>(); for (TypeMirror b : p.getBounds()) { bounds.add((Type.Defined) b.accept(converter, parameters)); } return bounds; }
/** * Get the type variables from the given {@link TypeElement}. */ public static List<TypeVariableName> getTypeVariables(TypeElement typeElement) { final List<? extends TypeParameterElement> typeParameters = typeElement.getTypeParameters(); final int typeParameterCount = typeParameters.size(); final List<TypeVariableName> typeVariables = new ArrayList<>(typeParameterCount); for (TypeParameterElement typeParameterElement : typeParameters) { final int boundTypesCount = typeParameterElement.getBounds().size(); final TypeName[] boundsTypeNames = new TypeName[boundTypesCount]; for (int i = 0; i < boundTypesCount; i++) { boundsTypeNames[i] = TypeName.get(typeParameterElement.getBounds().get(i)); } final TypeVariableName typeVariable = TypeVariableName.get(typeParameterElement.getSimpleName().toString(), boundsTypeNames); typeVariables.add(typeVariable); } return typeVariables; } }
/** * Make a TypeVariableName for the given TypeMirror. This form is used internally to avoid * infinite recursion in cases like {@code Enum<E extends Enum<E>>}. When we encounter such a * thing, we will make a TypeVariableName without bounds and add that to the {@code typeVariables} * map before looking up the bounds. Then if we encounter this TypeVariable again while * constructing the bounds, we can just return it from the map. And, the code that put the entry * in {@code variables} will make sure that the bounds are filled in before returning. */ static TypeVariableName get( TypeVariable mirror, Map<TypeParameterElement, TypeVariableName> typeVariables) { TypeParameterElement element = (TypeParameterElement) mirror.asElement(); TypeVariableName typeVariableName = typeVariables.get(element); if (typeVariableName == null) { // Since the bounds field is public, we need to make it an unmodifiableList. But we control // the List that that wraps, which means we can change it before returning. List<TypeName> bounds = new ArrayList<>(); List<TypeName> visibleBounds = Collections.unmodifiableList(bounds); typeVariableName = new TypeVariableName(element.getSimpleName().toString(), visibleBounds); typeVariables.put(element, typeVariableName); for (TypeMirror typeMirror : element.getBounds()) { bounds.add(TypeName.get(typeMirror, typeVariables)); } bounds.remove(OBJECT); } return typeVariableName; }
public void generify(IJGenerifiable generifiable, TypeElement fromTypeParameters) { for (TypeParameterElement param : fromTypeParameters.getTypeParameters()) { List<AbstractJClass> bounds = typeBoundsToJClass(param.getBounds()); addTypeBounds(generifiable, bounds, param.getSimpleName().toString()); } }
private void registerType(TypeElement type) { if (type != null && !importMap.containsKey(type)) { typeMap.put(type.getSimpleName().toString(), type); importMap.put(type, type); for (TypeParameterElement typeParam : type.getTypeParameters()) { for (TypeMirror bound : typeParam.getBounds()) { // FIXME: get rid of cast using a visitor TypeElement boundElement = TYPE_ELEMENT_VISITOR.visit(helpers.asElement(bound)); registerType(boundElement); } } } }
List<? extends TypeMirror> bounds = typeParameter.getBounds();
private TypeExtractor processTypeParameters(ExecutableElement method, EncodedElement.Builder builder) { boolean isStatic = method.getModifiers().contains(Modifier.STATIC); TypeExtractor typesReader = isStatic ? new TypeExtractor(types, method) : this.typesReader; for (TypeParameterElement p : method.getTypeParameters()) { String name = p.getSimpleName().toString(); ImmutableList<Defined> bounds = typesReader.getDefined(p.getBounds()); if (!isStatic) { typesReader = typesReader.withParameter(name, bounds); } builder.addTypeParams(new EncodedElement.TypeParam.Builder() .name(name) .addAllBounds(bounds) .build()); } builder.typeParameters(typesReader.parameters); return typesReader; }
private static boolean extendsObject(TypeParameterElement element) { if (element.getBounds().size() != 1) { return false; } TypeElement bound = maybeAsTypeElement(getOnlyElement(element.getBounds())).orElse(null); if (bound == null) { return false; } return bound.getQualifiedName().contentEquals(Object.class.getName()); } }
@Override public Boolean visitTypeVariable(TypeVariable t, Void p) { TypeParameterElement element = (TypeParameterElement) t.asElement(); return any(element.getBounds(), this); }
@Override public TypeMirror visitTypeVariable(TypeVariable t, TypeElement sup) { // we are checking if T (declared as T extends A&B&C) is assignable to sup. // so apply bounds recursively. for (TypeMirror r : ((TypeParameterElement) t.asElement()).getBounds()) { TypeMirror m = visit(r, sup); if (m != null) return m; } return null; }
@Override public Void visitTypeParameter(TypeParameterElement x, State state) { for (TypeMirror bound : x.getBounds()) { if (!state.isTransportableType(bound)) { state.poison(x, Messages.untransportableType(bound)); } } return super.visitTypeParameter(x, state); } }
private static void addDeclarationParameters( SourceBuilder source, List<TypeParameterElement> typeParameters) { if (!typeParameters.isEmpty()) { String prefix = "<"; for (TypeParameterElement typeParameter : typeParameters) { source.add("%s%s", prefix, typeParameter.getSimpleName()); if (!extendsObject(typeParameter)) { String separator = " extends "; for (TypeMirror bound : typeParameter.getBounds()) { source.add("%s%s", separator, bound); separator = " & "; } } prefix = ", "; } source.add(">"); } }
@Test public void testGenericMirror_withSelfReference() { Consumer<DeclaredType> test = foobar -> { // FooBar<E extends FooBar<E>> TypeElement foobarElement = maybeAsTypeElement(foobar).get(); assertThat(foobarElement.getSimpleName().toString()).isEqualTo("FooBar"); assertThat(foobar.getTypeArguments()).hasSize(1); assertThat(SourceBuilder.forTesting().add("%s", foobar).toString()) .isEqualTo("FooBar<E>"); // E extends FooBar<E> TypeParameterElement typeParameter = foobarElement.getTypeParameters().get(0); assertThat(typeParameter.getSimpleName().toString()).isEqualTo("E"); assertThat(typeParameter.getBounds()).hasSize(1); // FooBar<E> DeclaredType bound = maybeDeclared(typeParameter.getBounds().get(0)).get(); assertThat(bound.asElement().getSimpleName().toString()).isEqualTo("FooBar"); assertThat(bound.getTypeArguments()).hasSize(1); // E TypeVariable typeArgument = maybeVariable(bound.getTypeArguments().get(0)).get(); assertThat(typeArgument.asElement()).isEqualTo(typeParameter); }; DeclaredType realFoobar = (DeclaredType) model .newType("package org.example; interface FooBar<E extends FooBar<E>> { }").asType(); GenericElement.Builder fakeFoobarBuilder = new GenericElement.Builder(FOO_BAR_NAME); fakeFoobarBuilder.getTypeParameter("E").addBound(fakeFoobarBuilder.asType()); GenericMirror fakeFoobar = fakeFoobarBuilder.build().asType(); test.accept(realFoobar); test.accept(fakeFoobar); } }
@Override public List<? extends TypeMirror> getBounds() { if (this.bounds == null) { this.bounds = TypeMirrorDecorator.decorate(this.delegate.getBounds(), env); } return this.bounds; }
private static boolean extendsObject(TypeParameterElement element) { if (element.getBounds().size() != 1) { return false; } TypeElement bound = maybeAsTypeElement(getOnlyElement(element.getBounds())).orElse(null); if (bound == null) { return false; } return bound.getQualifiedName().contentEquals(Object.class.getName()); } }
@Override public Integer visitTypeVariable(TypeVariable t, Set<Element> visiting) { int result = hashKind(HASH_SEED, t); result *= HASH_MULTIPLIER; result += t.getLowerBound().accept(this, visiting); TypeParameterElement element = (TypeParameterElement) t.asElement(); for (TypeMirror bound : element.getBounds()) { result *= HASH_MULTIPLIER; result += bound.accept(this, visiting); } return result; }