use of spoon.support.visitor.ClassTypingContext in project spoon by INRIA.
the class GenericsTest method testIsSameSignatureWithReferencedGenerics.
@Test
public void testIsSameSignatureWithReferencedGenerics() {
Launcher launcher = new Launcher();
launcher.addInputResource("./src/test/java/spoon/test/generics/testclasses2/SameSignature3.java");
launcher.buildModel();
CtClass ctClass = launcher.getFactory().Class().get(SameSignature3.class);
CtMethod classMethod = (CtMethod) ctClass.getMethodsByName("visitCtConditional").get(0);
CtType<?> iface = launcher.getFactory().Type().get("spoon.test.generics.testclasses2.ISameSignature3");
CtMethod ifaceMethod = (CtMethod) iface.getMethodsByName("visitCtConditional").get(0);
ClassTypingContext ctcSub = new ClassTypingContext(ctClass.getReference());
assertTrue(ctcSub.isOverriding(classMethod, ifaceMethod));
assertTrue(ctcSub.isOverriding(ifaceMethod, classMethod));
assertTrue(ctcSub.isSubSignature(classMethod, ifaceMethod));
assertTrue(ctcSub.isSubSignature(ifaceMethod, classMethod));
assertTrue(ctcSub.isSameSignature(classMethod, ifaceMethod));
assertTrue(ctcSub.isSameSignature(ifaceMethod, classMethod));
}
use of spoon.support.visitor.ClassTypingContext in project spoon by INRIA.
the class GenericsTest method testTypeAdapted.
@Test
public void testTypeAdapted() throws Exception {
// contract: one can get the actual value of a generic type in a given context
CtClass<?> ctModel = (CtClass<?>) ModelUtils.buildClass(ErasureModelA.class);
CtTypeParameter tpA = ctModel.getFormalCtTypeParameters().get(0);
CtTypeParameter tpB = ctModel.getFormalCtTypeParameters().get(1);
CtTypeParameter tpC = ctModel.getFormalCtTypeParameters().get(2);
CtTypeParameter tpD = ctModel.getFormalCtTypeParameters().get(3);
CtClass<?> ctModelB = ctModel.filterChildren(new NamedElementFilter<>(CtClass.class, "ModelB")).first();
ClassTypingContext sth = new ClassTypingContext(ctModelB);
// in ModelB, "A" is "A2"
assertEquals("A2", sth.adaptType(tpA).getQualifiedName());
// in ModelB, "B" is "B2"
assertEquals("B2", sth.adaptType(tpB).getQualifiedName());
// and so on and so forth
assertEquals("C2", sth.adaptType(tpC).getQualifiedName());
assertEquals("D2", sth.adaptType(tpD).getQualifiedName());
CtClass<?> ctModelC = ctModel.filterChildren(new NamedElementFilter<>(CtClass.class, "ModelC")).first();
ClassTypingContext sthC = new ClassTypingContext(ctModelC);
assertEquals("java.lang.Integer", sthC.adaptType(tpA).getQualifiedName());
assertEquals("java.lang.RuntimeException", sthC.adaptType(tpB).getQualifiedName());
assertEquals("java.lang.IllegalArgumentException", sthC.adaptType(tpC).getQualifiedName());
assertEquals("java.util.List", sthC.adaptType(tpD).getQualifiedName());
}
use of spoon.support.visitor.ClassTypingContext in project spoon by INRIA.
the class GenericsTest method testIsGenericTypeEqual.
@Test
public void testIsGenericTypeEqual() {
Launcher launcher = new Launcher();
launcher.addInputResource("./src/test/java/spoon/test/generics/testclasses2/LikeCtClass.java");
launcher.addInputResource("./src/test/java/spoon/test/generics/testclasses2/LikeCtClassImpl.java");
launcher.buildModel();
CtType<?> ctIFace = launcher.getFactory().Interface().get(LikeCtClass.class);
CtMethod<?> ifaceGetter = (CtMethod) ctIFace.getMethodsByName("getConstructors").get(0);
CtMethod<?> ifaceSetter = (CtMethod) ctIFace.getMethodsByName("setConstructors").get(0);
assertEquals(ifaceGetter.getType().toString(), ifaceSetter.getParameters().get(0).getType().toString());
assertEquals(ifaceGetter.getType(), ifaceSetter.getParameters().get(0).getType());
CtType<?> ctClass = launcher.getFactory().Class().get(LikeCtClassImpl.class);
CtMethod<?> classGetter = (CtMethod) ctClass.getMethodsByName("getConstructors").get(0);
CtMethod<?> classSetter = (CtMethod) ctClass.getMethodsByName("setConstructors").get(0);
assertEquals(classGetter.getType().toString(), classSetter.getParameters().get(0).getType().toString());
assertEquals(classGetter.getType(), classSetter.getParameters().get(0).getType());
assertEquals(ifaceGetter.getType().toString(), classGetter.getType().toString());
assertEquals(ifaceGetter.getType(), classGetter.getType());
assertEquals(ifaceSetter.getParameters().get(0).getType().toString(), classSetter.getParameters().get(0).getType().toString());
assertEquals(ifaceSetter.getParameters().get(0).getType(), classSetter.getParameters().get(0).getType());
assertEquals(ifaceSetter.getParameters().get(0).getType(), classGetter.getType());
MethodTypingContext mtc = new MethodTypingContext().setClassTypingContext(new ClassTypingContext(ctClass)).setMethod(ifaceSetter);
CtMethod<?> adaptedMethod = (CtMethod<?>) mtc.getAdaptationScope();
/*
* after adaptation of `Set<AnType<T>>` from scope of interface to scope of class there is Set<AnType<T extends Object>>
* Which is semantically equivalent, but Equals check does not know that
*/
assertEquals(adaptedMethod.getParameters().get(0).getType(), classGetter.getType());
assertEquals(adaptedMethod.getParameters().get(0).getType(), classSetter.getParameters().get(0).getType());
MainTest.checkParentConsistency(launcher.getFactory().getModel().getRootPackage());
MainTest.checkParentConsistency(adaptedMethod);
}
use of spoon.support.visitor.ClassTypingContext in project spoon by INRIA.
the class AllMethodsSameSignatureFunction method apply.
@Override
public void apply(final CtExecutable<?> targetExecutable, final CtConsumer<Object> outputConsumer) {
// prepare filter for lambda expression. It will be configured by the algorithm below
final LambdaFilter lambdaFilter = new LambdaFilter();
final CtQuery lambdaQuery = targetExecutable.getFactory().getModel().filterChildren(lambdaFilter);
// the to be searched method
CtMethod<?> targetMethod;
if (targetExecutable instanceof CtLambda) {
// the input is lambda
if (includingSelf && includingLambdas) {
outputConsumer.accept(targetExecutable);
if (query.isTerminated()) {
return;
}
}
// in case of lambda, the target method is the method implemented by lambda
targetMethod = ((CtLambda<?>) targetExecutable).getOverriddenMethod();
outputConsumer.accept(targetMethod);
if (query.isTerminated()) {
return;
}
// the input is the lambda expression, which was already returned or doesn't have to be returned at all because includingSelf == false
// add extra filter into lambdaQuery which skips that input lambda expression
lambdaQuery.select(new Filter<CtLambda<?>>() {
@Override
public boolean matches(CtLambda<?> lambda) {
return targetExecutable != lambda;
}
});
} else if (targetExecutable instanceof CtMethod) {
if (includingSelf) {
outputConsumer.accept(targetExecutable);
if (query.isTerminated()) {
return;
}
}
targetMethod = (CtMethod<?>) targetExecutable;
} else {
// CtConstructor or CtAnonymousExecutable never overrides other executable. We are done
if (includingSelf) {
outputConsumer.accept(targetExecutable);
}
return;
}
final List<CtMethod<?>> targetMethods = new ArrayList<>();
targetMethods.add(targetMethod);
CtType<?> declaringType = targetMethod.getDeclaringType();
lambdaFilter.addImplementingInterface(declaringType);
// search for all declarations and implementations of this method in sub and super classes and interfaces of all related hierarchies.
class Context {
boolean haveToSearchForSubtypes;
}
final Context context = new Context();
// at the beginning we know that we have to always search for sub types too.
context.haveToSearchForSubtypes = true;
// Sub inheritance hierarchy function, which remembers visited sub types and does not returns/visits them again
final SubInheritanceHierarchyResolver subHierarchyFnc = new SubInheritanceHierarchyResolver(declaringType.getFactory().getModel().getRootPackage());
// add hierarchy of `targetMethod` as to be checked for sub types of declaring type
subHierarchyFnc.addSuperType(declaringType);
// unique names of all types whose super inheritance hierarchy was searched for rootType
Set<String> typesCheckedForRootType = new HashSet<>();
// list of sub types whose inheritance hierarchy has to be checked
final List<CtType<?>> toBeCheckedSubTypes = new ArrayList<>();
// add hierarchy of `targetMethod` as to be checked for super types of declaring type
toBeCheckedSubTypes.add(declaringType);
while (toBeCheckedSubTypes.size() > 0) {
for (CtType<?> subType : toBeCheckedSubTypes) {
ClassTypingContext ctc = new ClassTypingContext(subType);
// search for first target method from the same type inheritance hierarchy
targetMethod = getTargetMethodOfHierarchy(targetMethods, ctc);
// search for all methods with same signature in inheritance hierarchy of `subType`
forEachOverridenMethod(ctc, targetMethod, typesCheckedForRootType, new CtConsumer<CtMethod<?>>() {
@Override
public void accept(CtMethod<?> overriddenMethod) {
targetMethods.add(overriddenMethod);
outputConsumer.accept(overriddenMethod);
CtType<?> type = overriddenMethod.getDeclaringType();
lambdaFilter.addImplementingInterface(type);
subHierarchyFnc.addSuperType(type);
// mark that new super type was added, so we have to search for sub types again
context.haveToSearchForSubtypes = true;
}
});
if (query.isTerminated()) {
return;
}
}
toBeCheckedSubTypes.clear();
if (context.haveToSearchForSubtypes) {
context.haveToSearchForSubtypes = false;
// there are some new super types, whose sub inheritance hierarchy has to be checked
// search their inheritance hierarchy for sub types
subHierarchyFnc.forEachSubTypeInPackage(new CtConsumer<CtType<?>>() {
@Override
public void accept(CtType<?> type) {
toBeCheckedSubTypes.add(type);
}
});
}
}
if (includingLambdas) {
// search for all lambdas implementing any of the found interfaces
lambdaQuery.forEach(outputConsumer);
}
}
use of spoon.support.visitor.ClassTypingContext in project spoon by INRIA.
the class CtMethodImpl method getTopDefinitions.
@Override
public Collection<CtMethod<?>> getTopDefinitions() {
List<CtMethod<?>> s = new ArrayList<>();
// first collect potential declarations of this method in the type hierarchy
ClassTypingContext context = new ClassTypingContext(this.getDeclaringType());
getDeclaringType().map(new AllTypeMembersFunction(CtMethod.class)).forEach((CtMethod<?> m) -> {
if (m != this && context.isOverriding(this, m)) {
s.add(m);
}
});
// now removing the intermediate methods for which there exists a definition upper in the hierarchy
List<CtMethod<?>> finalMeths = new ArrayList<>(s);
for (CtMethod m1 : s) {
boolean m1IsIntermediate = false;
for (CtMethod m2 : s) {
if (context.isOverriding(m1, m2)) {
m1IsIntermediate = true;
}
}
if (!m1IsIntermediate) {
finalMeths.add(m1);
}
}
return finalMeths;
}
Aggregations