Search in sources :

Example 1 with MethodTypingContext

use of spoon.support.visitor.MethodTypingContext in project spoon by INRIA.

the class GenericsTest method testMethodTypingContextAdaptMethod.

@Test
public void testMethodTypingContextAdaptMethod() throws Exception {
    // core contracts of MethodTypingContext#adaptMethod
    Factory factory = build(new File("src/test/java/spoon/test/generics/testclasses"));
    CtClass<?> ctClassLunch = factory.Class().get(Lunch.class);
    // represents <C> void eatMe(A paramA, B paramB, C paramC){}
    CtMethod<?> trLunch_eatMe = ctClassLunch.filterChildren(new NamedElementFilter<>(CtMethod.class, "eatMe")).first();
    CtClass<?> ctClassWeddingLunch = factory.Class().get(WeddingLunch.class);
    ClassTypingContext ctcWeddingLunch = new ClassTypingContext(ctClassWeddingLunch);
    // we all analyze new methods
    final MethodTypingContext methodSTH = new MethodTypingContext().setClassTypingContext(ctcWeddingLunch);
    // contract: method can be adapted only using MethodTypingContext
    methodSTH.setMethod(trLunch_eatMe);
    CtMethod<?> adaptedLunchEatMe = (CtMethod<?>) methodSTH.getAdaptationScope();
    // contract: adapting of method declared in different scope, returns new method
    assertTrue(adaptedLunchEatMe != trLunch_eatMe);
    // check that new method is adapted correctly
    // is declared in correct class
    assertSame(ctClassWeddingLunch, adaptedLunchEatMe.getDeclaringType());
    // is not member of the same class (WeddingLunch)
    for (CtTypeMember typeMember : ctClassWeddingLunch.getTypeMembers()) {
        assertFalse(adaptedLunchEatMe == typeMember);
    }
    // the name is the same
    assertEquals("eatMe", adaptedLunchEatMe.getSimpleName());
    // it has the same number of of formal type parameters
    assertEquals(1, adaptedLunchEatMe.getFormalCtTypeParameters().size());
    assertEquals("C", adaptedLunchEatMe.getFormalCtTypeParameters().get(0).getQualifiedName());
    // parameters are correct
    assertEquals(3, adaptedLunchEatMe.getParameters().size());
    // "A paramA" becomes "X paramA" becomes Lunch%A corresponds to X in WeddingLunch
    assertEquals("X", adaptedLunchEatMe.getParameters().get(0).getType().getQualifiedName());
    // B paramB becomes Tacos becomes Lunch%B corresponds to Tacos in WeddingLunch (class WeddingLunch<X> extends CelebrationLunch<Tacos, Paella, X>)
    assertEquals(Tacos.class.getName(), adaptedLunchEatMe.getParameters().get(1).getType().getQualifiedName());
    // "C paramC" stays "C paramC"
    assertEquals("C", adaptedLunchEatMe.getParameters().get(2).getType().getQualifiedName());
    // contract: adapting of adapted method returns input method
    methodSTH.setMethod(adaptedLunchEatMe);
    assertSame(adaptedLunchEatMe, methodSTH.getAdaptationScope());
}
Also used : ClassTypingContext(spoon.support.visitor.ClassTypingContext) CtTypeMember(spoon.reflect.declaration.CtTypeMember) MethodTypingContext(spoon.support.visitor.MethodTypingContext) Tacos(spoon.test.generics.testclasses.Tacos) NamedElementFilter(spoon.reflect.visitor.filter.NamedElementFilter) ModelUtils.createFactory(spoon.testing.utils.ModelUtils.createFactory) Factory(spoon.reflect.factory.Factory) File(java.io.File) CtMethod(spoon.reflect.declaration.CtMethod) MainTest(spoon.test.main.MainTest) Test(org.junit.Test)

Example 2 with MethodTypingContext

use of spoon.support.visitor.MethodTypingContext in project spoon by INRIA.

the class GenericsTest method testMethodTypingContext.

@Test
public void testMethodTypingContext() throws Exception {
    Factory factory = build(new File("src/test/java/spoon/test/generics/testclasses"));
    CtClass<?> ctClassWeddingLunch = factory.Class().get(WeddingLunch.class);
    CtMethod<?> trWeddingLunch_eatMe = ctClassWeddingLunch.filterChildren(new NamedElementFilter<>(CtMethod.class, "eatMe")).first();
    MethodTypingContext methodSTH = new MethodTypingContext().setMethod(trWeddingLunch_eatMe);
    // contract: the method typing context provides its scope
    assertSame(trWeddingLunch_eatMe, methodSTH.getAdaptationScope());
    CtClass<?> ctClassLunch = factory.Class().get(Lunch.class);
    CtMethod<?> trLunch_eatMe = ctClassLunch.filterChildren(new NamedElementFilter<>(CtMethod.class, "eatMe")).first();
    CtInvocation<?> invokeReserve = factory.Class().get(CelebrationLunch.class).filterChildren(new TypeFilter<>(CtInvocation.class)).select((CtInvocation i) -> "reserve".equals(i.getExecutable().getSimpleName())).first();
    MethodTypingContext methodReserveTC = new MethodTypingContext().setInvocation(invokeReserve);
    // contract: the method typing context provides its scope
    assertSame(invokeReserve.getExecutable().getDeclaration(), methodReserveTC.getAdaptationScope());
    // check that MethodTypingContext made from invocation knows actual type arguments of method and all declaring types
    // 1) check method actual type argument
    CtMethod<?> methodReserve = (CtMethod<?>) invokeReserve.getExecutable().getDeclaration();
    CtTypeParameter methodReserve_S = methodReserve.getFormalCtTypeParameters().get(0);
    assertEquals("S", methodReserve_S.getSimpleName());
    assertEquals("spoon.test.generics.testclasses.Tacos", methodReserveTC.adaptType(methodReserve_S).getQualifiedName());
    // 2) check actual type arguments of declaring type `Section`
    CtClass classSection = (CtClass) methodReserve.getDeclaringType();
    assertEquals("spoon.test.generics.testclasses.CelebrationLunch$WeddingLunch$Section", classSection.getQualifiedName());
    CtTypeParameter classSection_Y = classSection.getFormalCtTypeParameters().get(0);
    assertEquals("Y", classSection_Y.getSimpleName());
    assertEquals("spoon.test.generics.testclasses.Paella", methodReserveTC.adaptType(classSection_Y).getQualifiedName());
    // 3) check actual type arguments of declaring type `WeddingLunch`
    CtClass classWeddingLunch = (CtClass) classSection.getDeclaringType();
    assertEquals("spoon.test.generics.testclasses.CelebrationLunch$WeddingLunch", classWeddingLunch.getQualifiedName());
    CtTypeParameter classWeddingLunch_X = classWeddingLunch.getFormalCtTypeParameters().get(0);
    assertEquals("X", classWeddingLunch_X.getSimpleName());
    assertEquals("spoon.test.generics.testclasses.Mole", methodReserveTC.adaptType(classWeddingLunch_X).getQualifiedName());
    // 4) check actual type arguments of declaring type `CelebrationLunch`
    CtClass classCelebrationLunch = (CtClass) classWeddingLunch.getDeclaringType();
    assertEquals("spoon.test.generics.testclasses.CelebrationLunch", classCelebrationLunch.getQualifiedName());
    CtTypeParameter classCelebrationLunch_K = classCelebrationLunch.getFormalCtTypeParameters().get(0);
    CtTypeParameter classCelebrationLunch_L = classCelebrationLunch.getFormalCtTypeParameters().get(1);
    CtTypeParameter classCelebrationLunch_M = classCelebrationLunch.getFormalCtTypeParameters().get(2);
    assertEquals("K", classCelebrationLunch_K.getSimpleName());
    assertEquals("L", classCelebrationLunch_L.getSimpleName());
    assertEquals("M", classCelebrationLunch_M.getSimpleName());
    assertEquals("spoon.test.generics.testclasses.Tacos", methodReserveTC.adaptType(classCelebrationLunch_K).getQualifiedName());
    assertEquals("spoon.test.generics.testclasses.Paella", methodReserveTC.adaptType(classCelebrationLunch_L).getQualifiedName());
    assertEquals("spoon.test.generics.testclasses.Mole", methodReserveTC.adaptType(classCelebrationLunch_M).getQualifiedName());
    // method->Section->WeddingLunch->CelebrationLunch
    GenericTypeAdapter celebrationLunchTC = methodReserveTC.getEnclosingGenericTypeAdapter().getEnclosingGenericTypeAdapter().getEnclosingGenericTypeAdapter();
    assertEquals("java.lang.Integer", celebrationLunchTC.adaptType(classCelebrationLunch_K).getQualifiedName());
    assertEquals("java.lang.Long", celebrationLunchTC.adaptType(classCelebrationLunch_L).getQualifiedName());
    assertEquals("java.lang.Double", celebrationLunchTC.adaptType(classCelebrationLunch_M).getQualifiedName());
}
Also used : CtTypeParameter(spoon.reflect.declaration.CtTypeParameter) GenericTypeAdapter(spoon.support.visitor.GenericTypeAdapter) ModelUtils.createFactory(spoon.testing.utils.ModelUtils.createFactory) Factory(spoon.reflect.factory.Factory) LikeCtClass(spoon.test.generics.testclasses2.LikeCtClass) CtClass(spoon.reflect.declaration.CtClass) CtInvocation(spoon.reflect.code.CtInvocation) MethodTypingContext(spoon.support.visitor.MethodTypingContext) NamedElementFilter(spoon.reflect.visitor.filter.NamedElementFilter) CelebrationLunch(spoon.test.generics.testclasses.CelebrationLunch) File(java.io.File) CtMethod(spoon.reflect.declaration.CtMethod) MainTest(spoon.test.main.MainTest) Test(org.junit.Test)

Example 3 with MethodTypingContext

use of spoon.support.visitor.MethodTypingContext in project spoon by INRIA.

the class TypeFactory method createTypeAdapter.

/**
 * Create a {@link GenericTypeAdapter} for adapting of formal type parameters from any compatible context to the context of provided `formalTypeDeclarer`
 *
 * @param formalTypeDeclarer
 * 		the target scope of the returned {@link GenericTypeAdapter}
 */
public GenericTypeAdapter createTypeAdapter(CtFormalTypeDeclarer formalTypeDeclarer) {
    class Visitor extends CtAbstractVisitor {

        GenericTypeAdapter adapter;

        @Override
        public <T> void visitCtClass(CtClass<T> ctClass) {
            adapter = new ClassTypingContext(ctClass);
        }

        @Override
        public <T> void visitCtInterface(CtInterface<T> intrface) {
            adapter = new ClassTypingContext(intrface);
        }

        @Override
        public <T> void visitCtMethod(CtMethod<T> m) {
            adapter = new MethodTypingContext().setMethod(m);
        }

        @Override
        public <T> void visitCtConstructor(CtConstructor<T> c) {
            adapter = new MethodTypingContext().setConstructor(c);
        }
    }
    Visitor visitor = new Visitor();
    ((CtElement) formalTypeDeclarer).accept(visitor);
    return visitor.adapter;
}
Also used : CtAbstractVisitor(spoon.reflect.visitor.CtAbstractVisitor) CtClass(spoon.reflect.declaration.CtClass) CtInterface(spoon.reflect.declaration.CtInterface) ClassTypingContext(spoon.support.visitor.ClassTypingContext) GenericTypeAdapter(spoon.support.visitor.GenericTypeAdapter) CtAbstractVisitor(spoon.reflect.visitor.CtAbstractVisitor) MethodTypingContext(spoon.support.visitor.MethodTypingContext) CtElement(spoon.reflect.declaration.CtElement) CtMethod(spoon.reflect.declaration.CtMethod) CtConstructor(spoon.reflect.declaration.CtConstructor)

Example 4 with MethodTypingContext

use of spoon.support.visitor.MethodTypingContext 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);
}
Also used : ClassTypingContext(spoon.support.visitor.ClassTypingContext) MethodTypingContext(spoon.support.visitor.MethodTypingContext) Launcher(spoon.Launcher) CtMethod(spoon.reflect.declaration.CtMethod) MainTest(spoon.test.main.MainTest) Test(org.junit.Test)

Aggregations

CtMethod (spoon.reflect.declaration.CtMethod)4 MethodTypingContext (spoon.support.visitor.MethodTypingContext)4 Test (org.junit.Test)3 ClassTypingContext (spoon.support.visitor.ClassTypingContext)3 MainTest (spoon.test.main.MainTest)3 File (java.io.File)2 CtClass (spoon.reflect.declaration.CtClass)2 Factory (spoon.reflect.factory.Factory)2 NamedElementFilter (spoon.reflect.visitor.filter.NamedElementFilter)2 GenericTypeAdapter (spoon.support.visitor.GenericTypeAdapter)2 ModelUtils.createFactory (spoon.testing.utils.ModelUtils.createFactory)2 Launcher (spoon.Launcher)1 CtInvocation (spoon.reflect.code.CtInvocation)1 CtConstructor (spoon.reflect.declaration.CtConstructor)1 CtElement (spoon.reflect.declaration.CtElement)1 CtInterface (spoon.reflect.declaration.CtInterface)1 CtTypeMember (spoon.reflect.declaration.CtTypeMember)1 CtTypeParameter (spoon.reflect.declaration.CtTypeParameter)1 CtAbstractVisitor (spoon.reflect.visitor.CtAbstractVisitor)1 CelebrationLunch (spoon.test.generics.testclasses.CelebrationLunch)1