Package spoon.support.adaption
Class TypeAdaptor
java.lang.Object
spoon.support.adaption.TypeAdaptor
Determines subtyping relationships and adapts generics from a super- to a subclass.
-
Constructor Summary
ConstructorDescriptionTypeAdaptor(CtConstructor<?> hierarchyStart)
Creates a new type adaptor using the given constructor as the start of its hierarchy.TypeAdaptor(CtMethod<?> hierarchyStart)
Creates a new type adaptor using the given method as the start of its hierarchy.TypeAdaptor(CtType<?> hierarchyStart)
Creates a new type adaptor using the given type as the start of its hierarchy.TypeAdaptor(CtTypeReference<?> hierarchyStart)
Creates a new type adaptor using the given reference as the start of its hierarchy. -
Method Summary
Modifier and TypeMethodDescriptionCtMethod<?>
adaptMethod(CtMethod<?> inputMethod)
Adapts a given method to the context of this type adapter.Adapts a type from a supertype to the context of this adaptor.adaptType(CtTypeReference<?> superRef)
Adapts a type from a supertype to the context of this adaptor.CtType<?>
boolean
isConflicting(CtMethod<?> first, CtMethod<?> second)
Checks if two given methods are conflicting, i.e.boolean
isOverriding(CtMethod<?> subMethod, CtMethod<?> superMethod)
Checks ifsubMethod
overridessuperMethod
.boolean
isSameSignature(CtMethod<?> first, CtMethod<?> second)
Checks if two methods have the same signature, once you adapt both to the context of this type adapter.static boolean
isSubtype(CtType<?> base, CtTypeReference<?> superRef)
Checks whether the base is a subtype of the passed superref.boolean
isSubtypeOf(CtTypeReference<?> superRef)
Checks if the context of this type adapter is a subtype of the passed superRef.
-
Constructor Details
-
TypeAdaptor
Creates a new type adaptor using the given type as the start of its hierarchy.- Parameters:
hierarchyStart
- the start of the hierarchy
-
TypeAdaptor
Creates a new type adaptor using the given reference as the start of its hierarchy.- Parameters:
hierarchyStart
- the start of the hierarchy
-
TypeAdaptor
Creates a new type adaptor using the given method as the start of its hierarchy.- Parameters:
hierarchyStart
- the start of the hierarchy
-
TypeAdaptor
Creates a new type adaptor using the given constructor as the start of its hierarchy.- Parameters:
hierarchyStart
- the start of the hierarchy
-
-
Method Details
-
isSubtypeOf
Checks if the context of this type adapter is a subtype of the passed superRef.- Parameters:
superRef
- the super reference to check against- Returns:
- true if the context of this type adapter is a subtype of the passed superRef
- See Also:
isSubtype(CtType, CtTypeReference)
-
getHierarchyStart
- Returns:
- the context of this type adaptor
-
isSubtype
Checks whether the base is a subtype of the passed superref. Generic parameters in superRef are ignored.- Parameters:
base
- the base typesuperRef
- the potential supertype- Returns:
- true if base extends/implements the super type
-
adaptMethod
Adapts a given method to the context of this type adapter. The parent of the method will be set to the context of this adapter.As an example: The method
method
in
adapted tointerface Parent<T, X> { <R> R method(T t, X x); }
would returninterface Child<Q> extends Parent<Q, String> {}
.<R> R method(Q t, String x);
- Parameters:
inputMethod
- the method to adapt- Returns:
- the input method but with the return type, parameter types and thrown types adapted to the context of this type adapter
-
isConflicting
Checks if two given methods are conflicting, i.e. they can not both be declared in the same class. This happens if the erasure of the methods is the same or one overrides the other. This method is used to remove methods that were already visited or were overwritten/shadowed by a subclass in various places.- Parameters:
first
- the first methodsecond
- the second method- Returns:
- true if the methods are conflicting
-
isSameSignature
Checks if two methods have the same signature, once you adapt both to the context of this type adapter.Two methods, M and N, have the same signature if they have the same name, the same type parameters (if any) (ยง8.4.4), and, after adapting the formal parameter types of N to the type parameters of M, the same formal parameter types.
Adapting both to the context of this adapter is needed when dealing with inherited methods:class TypeA { void foo(String bar); } interface IFoo<T> { void foo(T bar); } class Foo extends TypeA implements IFoo<String> {}
Here
TypeA#foo
andIFoo#foo
have the same signature if checked withFoo
as the context. In fact,TypeA#foo
actually implements the method fromIFoo
, even though it does not share any inheritance relation with it.- Parameters:
first
- the first methodsecond
- the second method- Returns:
- true if the two methods have the same signature
-
isOverriding
Checks ifsubMethod
overridessuperMethod
. A method overrides another, iff- They have the same name
- They have the same amount of parameters
- They are not static
-
The declaring type of
subMethod
is a subtype of the declaring type ofsuperMethod
-
The erasure of the parameters is equal, after
adapting
thesuperMethod
to the declaring type ofsubMethod
. One needs to adapt the whole method here and can not just check the erasure of the adapted parameter types, as they might depend on formal type parameters declared on the method:
If we did not adapt the whole method, we would not have a corresponding formal parameter declaration with the correct upper bound we can adapt to and would erase to Object instead.class Foo<T> { <F extends T> void foo(F t); } class Sub<R extends String> extends Foo<R> { <Q extends R> void foo(Q t); }
- Parameters:
subMethod
- the method that might override the othersuperMethod
- the method that might be overridden- Returns:
- true if
subMethod
overridessuperMethod
-
adaptType
Adapts a type from a supertype to the context of this adaptor. In essence, this method builds the inheritance hierarchy from its context to the super reference (with some smarts to figure out what to do if superRef is actually a type parameter) and then walks backwards along that chain until it finds a type variable in the adaptor's context or a terminating type.For example:
If you adaptinterface Top<T, S> {} interface Middle<Q> extends Top<Q, String> {} interface Bottom<R> extends Middle<R> {}
T
fromTop
toMiddle
you getQ
. If you adaptT
fromTop
toBottom
you getR
.
If you adaptS
fromTop
toMiddle
/Bottom
you getString
.
If the input reference is a formal type parameter declared on a method, adaption is only possible if this adaptor was created usingTypeAdaptor(CtMethod)
. Otherwise, there is no reference method to adapt to and the input will be returned unchanged.
If that constructor was used, this method will return the corresponding type parameter declared on the context method of this adaptor.- Parameters:
superRef
- the super type to adapt- Returns:
- the adapted type
-
adaptType
Adapts a type from a supertype to the context of this adaptor.- Parameters:
superType
- the super type to adapt- Returns:
- the adapted type
- See Also:
adaptType(CtTypeReference)
-