下面列出了javax.lang.model.type.IntersectionType#javax.lang.model.type.TypeVariable 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
public List<? extends TypeMirror> getUpperBounds(TypeMirror t) {
if (t == null) {
return Collections.singletonList(
javacElements.getTypeElement("java.lang.Object").asType());
}
switch (t.getKind()) {
case INTERSECTION:
return ((IntersectionType) t).getBounds();
case TYPEVAR:
return getUpperBounds(((TypeVariable) t).getUpperBound());
case WILDCARD:
return getUpperBounds(((WildcardType) t).getExtendsBound());
default:
return Collections.singletonList(t);
}
}
private static boolean verifyTypeVarAccessible(ExecutableElement method, TypeMirror forType, List<Element> usedLocalTypeVariables, Element target) {
Collection<TypeVariable> typeVars = Utilities.containedTypevarsRecursively(forType);
if (method != null) {
for (Iterator<TypeVariable> it = typeVars.iterator(); it.hasNext(); ) {
TypeVariable tvar = it.next();
Element tvarEl = tvar.asElement();
if (method.getTypeParameters().contains(tvarEl)) {
usedLocalTypeVariables.add(tvarEl);
it.remove();
}
}
}
return allTypeVarsAccessible(typeVars, target);
}
/**
* uses FQNs where possible since javadoc does not match imports for
* parameter types
*/
private CharSequence resolveTypeName(TypeMirror asType, boolean isVarArgs) {
CharSequence ptype;
if (asType.getKind() == TypeKind.DECLARED) {
// snip generics
Element e = ((DeclaredType) asType).asElement();
ptype = e.getKind().isClass() || e.getKind().isInterface()
? ((TypeElement) e).getQualifiedName()
: e.getSimpleName();
} else if (asType.getKind() == TypeKind.TYPEVAR) {
do {
// Type Erasure JLS 4.6
asType = ((TypeVariable) asType).getUpperBound();
} while (asType.getKind() == TypeKind.TYPEVAR);
ptype = resolveTypeName(asType, isVarArgs);
} else if (isVarArgs && asType.getKind() == TypeKind.ARRAY) {
ptype = resolveTypeName(((ArrayType)asType).getComponentType(), false) + "..."; //NOI18N
} else {
ptype = asType.toString();
}
return ptype;
}
@Override
public Void visitTypeVariable(TypeVariable type, Void p) {
Element e = type.asElement();
if (e != null) {
CharSequence name = e.getSimpleName();
if (!CAPTURED_WILDCARD.contentEquals(name)) {
builder.append(name);
return null;
}
}
builder.append("?"); //NOI18N
TypeMirror bound = type.getLowerBound();
if (bound != null && bound.getKind() != TypeKind.NULL) {
builder.append(" super "); //NOI18N
visit(bound);
} else {
bound = type.getUpperBound();
if (bound != null && bound.getKind() != TypeKind.NULL) {
builder.append(" extends "); //NOI18N
if (bound.getKind() == TypeKind.TYPEVAR)
bound = ((TypeVariable)bound).getLowerBound();
visit(bound);
}
}
return null;
}
private static String describeGenericBound(TypeMirror type) {
if (type instanceof TypeVariable) {
StringBuilder description = new StringBuilder("<");
TypeVariable typeVar = (TypeVariable)type;
description.append(typeVar.toString());
TypeMirror lowerBound = typeVar.getLowerBound();
if (lowerBound.getKind() != TypeKind.NULL) {
description.append(" super ").append(lowerBound);
}
TypeMirror upperBound = typeVar.getUpperBound();
if (upperBound.getKind() != TypeKind.NULL) {
description.append(" extends ").append(upperBound);
}
return description.append(">").toString();
}
return type.toString();
}
@Override
protected boolean handleBothTypeVars( TypeMirror argType,
TypeMirror varTypeArg, Types types )
{
/*
* Implementation of spec item :
* the delegate type parameter and the bean type parameter are both
* type variables and the upper bound of the bean type
* parameter is assignable to the upper bound,
* if any, of the delegate type parameter
*/
TypeMirror upper = ((TypeVariable)argType).getUpperBound();
TypeMirror upperVar = ((TypeVariable)varTypeArg).getUpperBound();
if ( upperVar == null || upperVar.getKind() == TypeKind.NULL ){
return true;
}
if ( upper == null || upper.getKind() == TypeKind.NULL ){
return false;
}
return checkIsAssignable(types, upper, upperVar);
}
@Override
protected boolean handleRequiredTypeVar( TypeMirror argType,
TypeMirror varTypeArg, Types types )
{
/*
* Implementation of spec item : the delegate type parameter is a
* type variable, the bean type parameter is an actual type, and the
* actual type is assignable to the upper bound, if any, of the type variable
*/
TypeMirror upper = ((TypeVariable)varTypeArg).getUpperBound();
if ( upper == null || upper.getKind()== TypeKind.NULL ){
return true;
}
return checkIsAssignable(types, argType, upper);
}
TypeMirror inferType(
TypeVariable typeVariable, TypeElement classElement, TypeMirror classMirror) {
DeclaredType declaredType = ctx.getMoreTypes().toDeclaredType(classMirror);
if (declaredType == null) {
return null;
}
List<? extends TypeMirror> args = declaredType.getTypeArguments();
if (args.isEmpty()) {
return null;
}
int argsSize = args.size();
int index = 0;
for (TypeParameterElement typeParam : classElement.getTypeParameters()) {
if (index >= argsSize) {
break;
}
if (ctx.getMoreTypes().isSameTypeWithErasure(typeVariable, typeParam.asType())) {
return args.get(index);
}
index++;
}
return null;
}
/** @see #get(java.lang.reflect.TypeVariable, Map) */
static TypeVariableName get(java.lang.reflect.TypeVariable<?> type,
Map<Type, TypeVariableName> map) {
TypeVariableName result = map.get(type);
if (result == null) {
List<TypeName> bounds = new ArrayList<>();
List<TypeName> visibleBounds = Collections.unmodifiableList(bounds);
result = new TypeVariableName(type.getName(), visibleBounds);
map.put(type, result);
for (Type bound : type.getBounds()) {
bounds.add(TypeName.get(bound, map));
}
bounds.remove(OBJECT);
}
return result;
}
static String getErasedType(TypeMirror type) {
switch (type.getKind()) {
case DECLARED:
DeclaredType declared = (DeclaredType) type;
TypeElement element = (TypeElement) declared.asElement();
return element.getQualifiedName().toString();
case TYPEVAR:
return getErasedType(((TypeVariable) type).getUpperBound());
case WILDCARD:
return getErasedType(((WildcardType) type).getExtendsBound());
case ARRAY:
return getErasedType(((ArrayType) type).getComponentType()) + "[]";
default:
return type.toString();
}
}
private static void appendSimpleTypeName(StringBuilder ret, TypeMirror type) {
switch (type.getKind()) {
case DECLARED:
DeclaredType declared = (DeclaredType) type;
TypeElement element = (TypeElement) declared.asElement();
ret.append(element.getSimpleName());
break;
case TYPEVAR:
appendSimpleTypeName(ret, ((TypeVariable) type).getUpperBound());
break;
case WILDCARD:
appendSimpleTypeName(ret, ((WildcardType) type).getExtendsBound());
break;
case ARRAY:
appendSimpleTypeName(ret, ((ArrayType) type).getComponentType());
ret.append("Array");
break;
default:
ret.append(type);
}
}
/**
* 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;
}
@Test
public void tyVar() {
TypeVariable t =
(TypeVariable)
Iterables.getOnlyElement(
factory
.typeElement(new ClassSymbol("java/util/Collections"))
.getEnclosedElements()
.stream()
.filter(e -> e.getSimpleName().contentEquals("sort"))
.filter(ExecutableElement.class::isInstance)
.map(ExecutableElement.class::cast)
.filter(e -> e.getParameters().size() == 1)
.findFirst()
.get()
.getTypeParameters())
.asType();
assertThat(t.getKind()).isEqualTo(TypeKind.TYPEVAR);
assertThat(t.getLowerBound().getKind()).isEqualTo(TypeKind.NONE);
assertThat(t.getUpperBound().toString()).isEqualTo("java.lang.Comparable<? super T>");
}
@Override
public Void visitTypeVariable(TypeVariable t, StringBuilderAndState<TypeMirror> state) {
if (state.visitingMethod) {
TypeMirror upperBound = IgnoreCompletionFailures.in(t::getUpperBound);
upperBound.accept(this, state);
return null;
}
if (state.visitedObjects.contains(t)) {
state.bld.append("%");
return null;
}
state.visitedObjects.add(t);
TypeMirror lowerBound = IgnoreCompletionFailures.in(t::getLowerBound);
if (lowerBound != null && lowerBound.getKind() != TypeKind.NULL) {
lowerBound.accept(this, state);
state.bld.append("-");
}
IgnoreCompletionFailures.in(t::getUpperBound).accept(this, state);
state.bld.append("+");
return null;
}
private TypeName getFeatureParameterTypeVariableName(DeclaredType featureType,
int featureParameterIndex) {
Element paramElem = getFeatureParameterElement(featureType, featureParameterIndex);
if (paramElem == null) {
return null;
}
if (paramElem.getKind() == ElementKind.TYPE_PARAMETER) {
return TypeVariableName.get((TypeVariable) paramElem.asType());
} else if (paramElem.getKind() == ElementKind.CLASS) {
return TypeName.get(paramElem.asType());
}
return null;
}
@Override
public Boolean visitTypeVariable(TypeVariable a, EqualVisitorParam p) {
if (p.type.getKind().equals(TYPEVAR)) {
TypeVariable b = (TypeVariable) p.type;
TypeParameterElement aElement = (TypeParameterElement) a.asElement();
TypeParameterElement bElement = (TypeParameterElement) b.asElement();
Set<ComparedElements> newVisiting = visitingSetPlus(p.visiting, aElement, bElement);
if (newVisiting.equals(p.visiting)) {
// We're already visiting this pair of elements.
// This can happen with our friend Eclipse when looking at <T extends Comparable<T>>.
// It incorrectly reports the upper bound of T as T itself.
return true;
}
// We use aElement.getBounds() instead of a.getUpperBound() to avoid having to deal with
// the different way intersection types (like <T extends Number & Comparable<T>>) are
// represented before and after Java 8. We do have an issue that this code may consider
// that <T extends Foo & Bar> is different from <T extends Bar & Foo>, but it's very
// hard to avoid that, and not likely to be much of a problem in practice.
return equalLists(aElement.getBounds(), bElement.getBounds(), newVisiting)
&& equal(a.getLowerBound(), b.getLowerBound(), newVisiting)
&& a.asElement().getSimpleName().equals(b.asElement().getSimpleName());
}
return false;
}
void test(TypeElement element, boolean fbound) {
TypeParameterElement tpe = element.getTypeParameters().iterator().next();
tpe.getBounds().getClass();
if (fbound) {
DeclaredType type = (DeclaredType)tpe.getBounds().get(0);
if (type.asElement() != element)
throw error("%s != %s", type.asElement(), element);
TypeVariable tv = (TypeVariable)type.getTypeArguments().get(0);
if (tv.asElement() != tpe)
throw error("%s != %s", tv.asElement(), tpe);
}
}
@Override
public TypeMirror visitTypeVariable(TypeVariable t, TypeElement typeElement) {
// we are checking if T (declared as T extends A&B&C) is assignable to sup.
// so apply bounds recursively.
for (TypeMirror typeMirror : ((TypeParameterElement) t.asElement()).getBounds()) {
TypeMirror m = visit(typeMirror, typeElement);
if (m != null)
return m;
}
return null;
}
private boolean isSameTypeVariable(TypeVariable t1, TypeVariable t2) {
if (!t1.asElement().equals(t2.asElement())) {
return false;
}
// TODO(jkeljo): Upper and lower bounds could also matter if the type variable is the result of
// capture conversion, but we don't support capture conversion yet (or maybe ever).
return true;
}
private List<CName> getParameterTypes(ExecutableElement executableElement) {
List<? extends VariableElement> methodParameters = executableElement.getParameters();
List<CName> parameterTypes = new ArrayList<>();
for (VariableElement variableElement : methodParameters) {
TypeMirror methodParameterType = variableElement.asType();
if (methodParameterType instanceof TypeVariable) {
TypeVariable typeVariable = (TypeVariable) methodParameterType;
methodParameterType = typeVariable.getUpperBound();
}
parameterTypes.add(new CName(methodParameterType));
}
return parameterTypes;
}
@Override public Void visitTypeVariable(TypeVariable t, Void p) {
Name name = null;
try {
name = ((Type) t).tsym.name;
} catch (NullPointerException e) {}
if (name != null) typeVariables.add(name.toString());
subVisit(t.getLowerBound());
subVisit(t.getUpperBound());
return null;
}
void test(TypeElement element, boolean fbound) {
TypeParameterElement tpe = element.getTypeParameters().iterator().next();
tpe.getBounds().getClass();
if (fbound) {
DeclaredType type = (DeclaredType)tpe.getBounds().get(0);
if (type.asElement() != element)
throw error("%s != %s", type.asElement(), element);
TypeVariable tv = (TypeVariable)type.getTypeArguments().get(0);
if (tv.asElement() != tpe)
throw error("%s != %s", tv.asElement(), tpe);
}
}
@Override
public final T visitTypeVariable(TypeVariable t, StringBuilderAndState<S> st) {
try {
st.depth++;
return doVisitTypeVariable(t, st);
} finally {
st.depth--;
}
}
@Override
public StringBuilder visitTypeVariable(TypeVariable t, Boolean p) {
Element e = t.asElement();
if (e != null) {
String name = e.getSimpleName().toString();
if (!CAPTURED_WILDCARD.equals(name)) {
return DEFAULT_VALUE.append(name);
}
}
DEFAULT_VALUE.append("?"); //NOI18N
if (!insideCapturedWildcard) {
insideCapturedWildcard = true;
TypeMirror bound = t.getLowerBound();
if (bound != null && bound.getKind() != TypeKind.NULL) {
DEFAULT_VALUE.append(" super "); //NOI18N
visit(bound, p);
} else {
bound = t.getUpperBound();
if (bound != null && bound.getKind() != TypeKind.NULL) {
DEFAULT_VALUE.append(" extends "); //NOI18N
if (bound.getKind() == TypeKind.TYPEVAR) {
bound = ((TypeVariable)bound).getLowerBound();
}
visit(bound, p);
}
}
insideCapturedWildcard = false;
}
return DEFAULT_VALUE;
}
@Override
public StringBuilder visitTypeVariable(TypeVariable t, Boolean p) {
Element e = t.asElement();
if (e != null) {
String name = e.getSimpleName().toString();
if (!CAPTURED_WILDCARD.equals(name))
return DEFAULT_VALUE.append(name);
}
DEFAULT_VALUE.append("?"); //NOI18N
if (!insideCapturedWildcard) {
insideCapturedWildcard = true;
TypeMirror bound = t.getLowerBound();
if (bound != null && bound.getKind() != TypeKind.NULL) {
DEFAULT_VALUE.append(" super "); //NOI18N
visit(bound, p);
} else {
bound = t.getUpperBound();
if (bound != null && bound.getKind() != TypeKind.NULL) {
DEFAULT_VALUE.append(" extends "); //NOI18N
if (bound.getKind() == TypeKind.TYPEVAR)
bound = ((TypeVariable)bound).getLowerBound();
visit(bound, p);
}
}
insideCapturedWildcard = false;
}
return DEFAULT_VALUE;
}
@Override
public Void visitTypeVariable(TypeVariable t, TypeMirrorSet visiting) {
if (visiting.add(t)) {
t.getLowerBound().accept(this, visiting);
t.getUpperBound().accept(this, visiting);
}
return null;
}
@Override
public Void visitTypeVariable(TypeVariable t, Collection<DeclaredType> p) {
if (t.getLowerBound() != null) {
visit(t.getLowerBound(), p);
}
if (t.getUpperBound() != null) {
visit(t.getUpperBound(), p);
}
return DEFAULT_VALUE;
}
private void parseBindText(Element element, Map<TypeElement, BindingClass> targetClassMap,
Set<String> erasedTargetNames) {
TypeElement enclosingElement = (TypeElement) element.getEnclosingElement();
TypeMirror elementType = element.asType();
if (elementType.getKind() == TypeKind.TYPEVAR) {
TypeVariable typeVariable = (TypeVariable) elementType;
elementType = typeVariable.getUpperBound();
}
// Assemble information on the field.
int[] ids = element.getAnnotation(BindText.class).value();
BindingClass bindingClass = getOrCreateTargetClass(targetClassMap, enclosingElement, false, false);
for (int id : ids) {
if (bindingClass != null) {
KBindings bindings = bindingClass.getKBindings(String.valueOf(id));
if (bindings != null) {
Iterator<FieldViewBinding> iterator = bindings.getFieldBindings().iterator();
if (iterator.hasNext()) {
FieldViewBinding existingBinding = iterator.next();
error(element, "Attempt to use @%s for an already bound ID %s on '%s'. (%s.%s)",
BindText.class.getSimpleName(), id, existingBinding.getName(),
enclosingElement.getQualifiedName(), element.getSimpleName());
return;
}
}
} else {
bindingClass = getOrCreateTargetClass(targetClassMap, enclosingElement, false, false);
}
String name = element.getSimpleName().toString();
TypeName type = TypeName.get(elementType);
boolean required = isRequiredBinding(element);
FieldViewBinding binding = new FieldViewBinding(name, type, required);
bindingClass.addField(String.valueOf(id), binding);
}
// Add the type-erased version to the valid binding targets set.
erasedTargetNames.add(enclosingElement.toString());
}
public static boolean allTypeVarsAccessible(Collection<TypeVariable> typeVars, Element target) {
if (target == null) {
return typeVars.isEmpty();
}
Set<TypeVariable> targetTypeVars = new HashSet<TypeVariable>();
OUTER: while (target.getKind() != ElementKind.PACKAGE) {
Iterable<? extends TypeParameterElement> tpes;
switch (target.getKind()) {
case ANNOTATION_TYPE:
case CLASS:
case ENUM:
case INTERFACE:
tpes = ((TypeElement) target).getTypeParameters();
break;
case METHOD:
case CONSTRUCTOR:
tpes = ((ExecutableElement) target).getTypeParameters();
break;
default:
break OUTER;
}
for (TypeParameterElement tpe : tpes) {
targetTypeVars.add((TypeVariable) tpe.asType());
}
if (target.getModifiers().contains(Modifier.STATIC)) {
break;
}
target = target.getEnclosingElement();
}
return targetTypeVars.containsAll(typeVars);
}
@Test
public void testGetUpperBoundUnbounded() throws IOException {
compile("class Foo<T> { }");
TypeMirror objectType = elements.getTypeElement("java.lang.Object").asType();
TypeVariable tVar =
(TypeVariable) elements.getTypeElement("Foo").getTypeParameters().get(0).asType();
assertSameType(objectType, tVar.getUpperBound());
}