Search in sources :

Example 1 with ClassTypingContext

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

the class GenericsTest method testClassTypingContext.

@Test
public void testClassTypingContext() throws Exception {
    // contract: a ClassTypingContext enables one to perform type resolution of generic types
    Factory factory = build(new File("src/test/java/spoon/test/generics/testclasses"));
    CtClass<?> ctClassCelebrationLunch = factory.Class().get(CelebrationLunch.class);
    CtTypeReference<?> typeReferenceOfDisgust = ctClassCelebrationLunch.filterChildren(new NamedElementFilter<>(CtNamedElement.class, "disgust")).map((CtTypedElement te) -> {
        return te.getType();
    }).first();
    assertEquals("spoon.test.generics.testclasses.CelebrationLunch<java.lang.Integer, java.lang.Long, java.lang.Double>.WeddingLunch<spoon.test.generics.testclasses.Mole>", typeReferenceOfDisgust.toString());
    // method WeddingLunch#eatMe
    CtMethod<?> tWeddingLunch_eatMe = typeReferenceOfDisgust.getDeclaration().filterChildren((CtNamedElement e) -> "eatMe".equals(e.getSimpleName())).first();
    CtClass<?> ctClassLunch = factory.Class().get(Lunch.class);
    // method Lunch#eatMe
    CtMethod<?> ctClassLunch_eatMe = ctClassLunch.filterChildren((CtNamedElement e) -> "eatMe".equals(e.getSimpleName())).first();
    // type of first parameter of  method WeddingLunch#eatMe
    CtTypeReference<?> ctWeddingLunch_X = tWeddingLunch_eatMe.getParameters().get(0).getType();
    // X is the type parameter of WeddingLunch
    assertEquals("X", ctWeddingLunch_X.getSimpleName());
    // type of first parameter of method Lunch#eatMe
    CtTypeReference<?> ctClassLunch_A = ctClassLunch_eatMe.getParameters().get(0).getType();
    assertEquals("A", ctClassLunch_A.getSimpleName());
    // are these two types same?
    ClassTypingContext typingContextOfDisgust = new ClassTypingContext(typeReferenceOfDisgust);
    // contract: the class typing context provides its scope
    assertSame(typeReferenceOfDisgust.getTypeDeclaration(), typingContextOfDisgust.getAdaptationScope());
    // in disgust, X of WeddingLunch is bound to "Model"
    assertEquals("spoon.test.generics.testclasses.Mole", typingContextOfDisgust.adaptType(ctWeddingLunch_X).getQualifiedName());
    // adapt A to scope of CelebrationLunch<Integer,Long,Double>.WeddingLunch<Mole>
    // in disgust, the A of Lunch is bound to "Mole"
    assertEquals("spoon.test.generics.testclasses.Mole", typingContextOfDisgust.adaptType(ctClassLunch_A).getQualifiedName());
    // I don't understand the goal and utility of this one
    assertEquals("java.lang.Double", typingContextOfDisgust.getEnclosingGenericTypeAdapter().adaptType(ctClassLunch_A).getQualifiedName());
    // now we resolve those types, but in the context of the declaration, where no concrete types exist
    // are these two types same in scope of CelebrationLunch<K,L,M>.WddingLunch<X> class itself
    ClassTypingContext sthOftWeddingLunch_X = new ClassTypingContext(typeReferenceOfDisgust.getDeclaration());
    // contract: the class typing context provides its scope
    assertSame(typeReferenceOfDisgust.getDeclaration(), sthOftWeddingLunch_X.getAdaptationScope());
    // in WeddingLunch "X" is still "X"
    assertEquals("X", sthOftWeddingLunch_X.adaptType(ctWeddingLunch_X).getQualifiedName());
    // in WeddingLunch the "A" from Lunch of is called "X"
    assertEquals("X", sthOftWeddingLunch_X.adaptType(ctClassLunch_A).getQualifiedName());
    // ?????
    // adapt A to scope of enclosing class of CelebrationLunch<K,L,M>.WddingLunch<X>, which is CelebrationLunch<K,L,M>
    assertEquals("M", sthOftWeddingLunch_X.getEnclosingGenericTypeAdapter().adaptType(ctClassLunch_A).getQualifiedName());
}
Also used : ClassTypingContext(spoon.support.visitor.ClassTypingContext) ModelUtils.createFactory(spoon.testing.utils.ModelUtils.createFactory) Factory(spoon.reflect.factory.Factory) CtTypedElement(spoon.reflect.declaration.CtTypedElement) File(java.io.File) CtNamedElement(spoon.reflect.declaration.CtNamedElement) MainTest(spoon.test.main.MainTest) Test(org.junit.Test)

Example 2 with ClassTypingContext

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

the class GenericsTest method testCannotAdaptTypeOfNonTypeScope.

@Test
public void testCannotAdaptTypeOfNonTypeScope() throws Exception {
    // contract: ClassTypingContext doesn't fail on type parameters, which are defined out of the scope of ClassTypingContext
    CtType<?> ctClass = ModelUtils.buildClass(OuterTypeParameter.class);
    // the method defines type parameter, which is used in super of local class
    CtReturn<?> retStmt = (CtReturn<?>) ctClass.getMethodsByName("method").get(0).getBody().getStatements().get(0);
    CtNewClass<?> newClassExpr = (CtNewClass<?>) retStmt.getReturnedExpression();
    CtType<?> declaringType = newClassExpr.getAnonymousClass();
    CtMethod<?> m1 = declaringType.getMethodsByName("iterator").get(0);
    ClassTypingContext c = new ClassTypingContext(declaringType);
    // the adaptation of such type parameter keeps that parameter as it is.
    assertFalse(c.isOverriding(m1, declaringType.getSuperclass().getTypeDeclaration().getMethodsByName("add").get(0)));
    assertTrue(c.isOverriding(m1, declaringType.getSuperclass().getTypeDeclaration().getMethodsByName("iterator").get(0)));
}
Also used : ClassTypingContext(spoon.support.visitor.ClassTypingContext) CtReturn(spoon.reflect.code.CtReturn) CtNewClass(spoon.reflect.code.CtNewClass) MainTest(spoon.test.main.MainTest) Test(org.junit.Test)

Example 3 with ClassTypingContext

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

the class GenericsTest method testClassContextOnInnerClass.

@Test
public void testClassContextOnInnerClass() throws Exception {
    CtClass<?> classBanana = (CtClass<?>) buildClass(Banana.class);
    CtClass<?> classVitamins = classBanana.getNestedType("Vitamins");
    CtTypeReference<?> refList_T = classVitamins.getSuperclass();
    // contract: generic types defined in enclocing classe (Banana<T>) are resolved from inner class hierarchy (Vitamins->List<T>) too.
    assertSame(classBanana.getFormalCtTypeParameters().get(0), new ClassTypingContext(classVitamins).adaptType(refList_T.getActualTypeArguments().get(0)).getDeclaration());
}
Also used : LikeCtClass(spoon.test.generics.testclasses2.LikeCtClass) CtClass(spoon.reflect.declaration.CtClass) ClassTypingContext(spoon.support.visitor.ClassTypingContext) Banana(spoon.test.generics.testclasses.Banana) MainTest(spoon.test.main.MainTest) Test(org.junit.Test)

Example 4 with ClassTypingContext

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

the class GenericsTest method testRecursiveTypeAdapting.

@Test
public void testRecursiveTypeAdapting() throws Exception {
    CtType<?> classOrange = buildClass(Orange.class);
    CtClass<?> classA = classOrange.getNestedType("A");
    CtTypeParameter typeParamO = classA.getFormalCtTypeParameters().get(0);
    CtTypeParameter typeParamM = classA.getFormalCtTypeParameters().get(1);
    assertEquals("O", typeParamO.getQualifiedName());
    assertEquals("M", typeParamM.getQualifiedName());
    assertEquals("K", typeParamO.getSuperclass().getQualifiedName());
    assertEquals("O", typeParamM.getSuperclass().getQualifiedName());
    assertEquals("K", typeParamM.getSuperclass().getSuperclass().getQualifiedName());
    CtClass<?> classB = classOrange.getNestedType("B");
    CtTypeParameter typeParamN = classB.getFormalCtTypeParameters().get(0);
    CtTypeParameter typeParamP = classB.getFormalCtTypeParameters().get(1);
    assertEquals("N", typeParamN.getQualifiedName());
    assertEquals("P", typeParamP.getQualifiedName());
    ClassTypingContext ctcB = new ClassTypingContext(classB);
    assertEquals("N", ctcB.adaptType(typeParamO).getQualifiedName());
    assertEquals("P", ctcB.adaptType(typeParamM).getQualifiedName());
    // contract: superClass of CtTypeParam is adapted too
    assertEquals("K", ctcB.adaptType(typeParamO).getSuperclass().getQualifiedName());
    assertEquals("N", ctcB.adaptType(typeParamM).getSuperclass().getQualifiedName());
    assertEquals("K", ctcB.adaptType(typeParamM).getSuperclass().getSuperclass().getQualifiedName());
    CtTypeReference<?> typeRef_list2m = classA.getField("list2m").getType();
    assertEquals("java.util.List<java.util.List<M>>", typeRef_list2m.toString());
    // contract: the CtTypeReference is adapted recursive including actual type arguments
    assertEquals("java.util.List<java.util.List<P>>", ctcB.adaptType(typeRef_list2m).toString());
    CtTypeReference<?> typeRef_ListQextendsM = classA.getMethodsByName("method").get(0).getParameters().get(0).getType();
    assertEquals("java.util.List<? extends M>", typeRef_ListQextendsM.toString());
    // contract: the CtTypeReference is adapted recursive including actual type arguments and their bounds
    assertEquals("java.util.List<? extends P>", ctcB.adaptType(typeRef_ListQextendsM).toString());
}
Also used : ClassTypingContext(spoon.support.visitor.ClassTypingContext) CtTypeParameter(spoon.reflect.declaration.CtTypeParameter) MainTest(spoon.test.main.MainTest) Test(org.junit.Test)

Example 5 with ClassTypingContext

use of spoon.support.visitor.ClassTypingContext 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)

Aggregations

ClassTypingContext (spoon.support.visitor.ClassTypingContext)17 Test (org.junit.Test)11 MainTest (spoon.test.main.MainTest)11 CtMethod (spoon.reflect.declaration.CtMethod)10 CtClass (spoon.reflect.declaration.CtClass)6 LikeCtClass (spoon.test.generics.testclasses2.LikeCtClass)5 Launcher (spoon.Launcher)4 File (java.io.File)3 Factory (spoon.reflect.factory.Factory)3 AllTypeMembersFunction (spoon.reflect.visitor.filter.AllTypeMembersFunction)3 NamedElementFilter (spoon.reflect.visitor.filter.NamedElementFilter)3 MethodTypingContext (spoon.support.visitor.MethodTypingContext)3 ModelUtils.createFactory (spoon.testing.utils.ModelUtils.createFactory)3 ArrayList (java.util.ArrayList)2 HashSet (java.util.HashSet)2 CtTypeMember (spoon.reflect.declaration.CtTypeMember)2 CtTypeParameter (spoon.reflect.declaration.CtTypeParameter)2 CtLambda (spoon.reflect.code.CtLambda)1 CtNewClass (spoon.reflect.code.CtNewClass)1 CtReturn (spoon.reflect.code.CtReturn)1