-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Description
The predicate RefType.getAnAcestor() is error-prone when one of the supertypes is a generic type parameterized with Object as type argument. In that case getASupertype() and getAnAcestor() return all types which have a lower bound (but are not actually relevant), e.g.:
import java
from RefType t
where t.hasName("ObjectToStringComparator")
select t, t.getAnAncestor()Result hierarchy (click to expand)
ObjectToStringComparatorSerializableObjectComparator<Object>Comparator<>Comparator<? super Boolean>Comparator<? super Callable<Integer>>Comparator<? super CharSequence>Comparator<? super Class<?>>Comparator<? super Diff<?>>Comparator<? super Double>Comparator<? super E>Comparator<? super E>Comparator<? super E>Comparator<? super E>Comparator<? super E>Comparator<? super E>Comparator<? super E>Comparator<? super E>Comparator<? super E>Comparator<? super E>Comparator<? super E>Comparator<? super E>Comparator<? super Field>Comparator<? super Format>Comparator<? super Hobby>Comparator<? super ImmutablePair<Integer,Integer>>Comparator<? super ImmutableTriple<Integer,Integer,Integer>>Comparator<? super Integer>Comparator<? super K>Comparator<? super K>Comparator<? super K>Comparator<? super K>Comparator<? super L>Comparator<? super Locale>Comparator<? super Long>Comparator<? super Method>Comparator<? super MethodDescriptor>Comparator<? super Method[]>Comparator<? super O>Comparator<? super O>Comparator<? super O>Comparator<? super O>Comparator<? super Object>Comparator<? super Pair<String,Object>>Comparator<? super Rule>Comparator<? super StrategyAndWidth>Comparator<? super String>Comparator<? super Student>Comparator<? super T>Comparator<? super T>Comparator<? super T>Comparator<? super T>Comparator<? super T>Comparator<? super T>Comparator<? super T>Comparator<? super T>Comparator<? super T>Comparator<? super T>Comparator<? super T>Comparator<? super T>Comparator<? super T>Comparator<? super T>Comparator<? super T>Comparator<? super T>Comparator<? super T>Comparator<? super T>Comparator<? super T>Comparator<? super T>Comparator<? super T>Comparator<? super T>Comparator<? super T>Comparator<? super T>Comparator<? super T>Comparator<? super T>Comparator<? super T>Comparator<? super T>Comparator<? super Thing>Comparator<? super Thread>Comparator<? super ThreadGroup>Comparator<? super Throwable>Comparator<? super Token>Comparator<? super Traffic>Comparator<? super Transaction>Comparator<? super TypeVariable<Class<T>>>Comparator<? super U>Comparator<? super U>Comparator<? super V>Comparator<? super VetoableChangeListener>Comparator<?>Object
This is most likely not the desired behavior. Therefore it might be good to deprecate getAnAncestor() and instead add a predicate getASourceAncestor() (which also deliberately does not have this as result):
/**
* Gets a source ancestor of this type, that is, a direct supertype or a direct supertype of the
* source declaration of a supertype, recursively.
*/
RefType getASourceAncestor() {
// Checking for source declaration is necessary, otherwise class `Generic<T>` would have `Generic<>` (raw),
// `Generic<?>` and `Generic<? super T>` as supertypes
result = getASupertype() and result.getSourceDeclaration() != getSourceDeclaration()
or result = getASourceAncestor(getASupertype().getSourceDeclaration())
}As seen here, it is necessary to check result.getSourceDeclaration() != getSourceDeclaration() since RefType is currently missing a predicate for getting a supertype declared in source (or the implicit Object); this is slightly related to #3818.
Ideally such a predicate would have the name getASourceSupertype(), however that name is already taken. A better fitting name for the existing predicate would probably be getASupertypeSource() / getASupertypeSourceDeclaration(), since that is what it actually does: "Gets the source declaration of a direct supertype of this type"