Search in sources :

Example 1 with SubInheritanceHierarchyResolver

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

the class FilterTest method testSubInheritanceHierarchyResolver.

@Test
public void testSubInheritanceHierarchyResolver() throws Exception {
    // contract; SubInheritanceHierarchyResolver supports finding subtypes in an incremental manner
    final Launcher launcher = new Launcher();
    launcher.setArgs(new String[] { "--output-type", "nooutput", "--level", "info" });
    launcher.addInputResource("./src/test/java/spoon/test/filters/testclasses");
    launcher.buildModel();
    SubInheritanceHierarchyResolver resolver = new SubInheritanceHierarchyResolver(launcher.getModel().getRootPackage());
    // contract: by default, nothing is sent to the consumer
    resolver.forEachSubTypeInPackage(new CtConsumer<CtType<?>>() {

        @Override
        public void accept(CtType<?> ctType) {
            fail();
        }
    });
    // we add a type
    resolver.addSuperType(launcher.getFactory().Type().createReference(AbstractTostada.class));
    class Counter {

        int counter = 0;
    }
    Counter c = new Counter();
    resolver.forEachSubTypeInPackage(new CtConsumer<CtType<?>>() {

        @Override
        public void accept(CtType<?> ctType) {
            c.counter++;
        }
    });
    // there are 5 subtypes of AbstractTostada
    assertEquals(5, c.counter);
    // we add a type already visited
    resolver.addSuperType(launcher.getFactory().Type().createReference(Tostada.class));
    // nothing is sent to the consumer
    resolver.forEachSubTypeInPackage(new CtConsumer<CtType<?>>() {

        @Override
        public void accept(CtType<?> ctType) {
            fail();
        }
    });
    // we add a new type
    resolver.addSuperType(launcher.getFactory().Type().createReference(ITostada.class));
    Counter c2 = new Counter();
    resolver.forEachSubTypeInPackage(new CtConsumer<CtType<?>>() {

        @Override
        public void accept(CtType<?> ctType) {
            c2.counter++;
            assertEquals("spoon.test.filters.testclasses.Tacos", ctType.getQualifiedName());
        }
    });
    // only one subtype remains unvisited
    assertEquals(1, c2.counter);
}
Also used : AbstractTostada(spoon.test.filters.testclasses.AbstractTostada) Tostada(spoon.test.filters.testclasses.Tostada) ITostada(spoon.test.filters.testclasses.ITostada) AbstractTostada(spoon.test.filters.testclasses.AbstractTostada) SubTostada(spoon.test.filters.testclasses.SubTostada) CtType(spoon.reflect.declaration.CtType) SubInheritanceHierarchyResolver(spoon.support.visitor.SubInheritanceHierarchyResolver) Launcher(spoon.Launcher) ITostada(spoon.test.filters.testclasses.ITostada) Test(org.junit.Test)

Example 2 with SubInheritanceHierarchyResolver

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

the class SubInheritanceHierarchyFunction method apply.

@Override
public void apply(CtTypeInformation input, final CtConsumer<Object> outputConsumer) {
    final SubInheritanceHierarchyResolver fnc = new SubInheritanceHierarchyResolver(((CtElement) input).getFactory().getModel().getRootPackage()).failOnClassNotFound(failOnClassNotFound).includingInterfaces(includingInterfaces);
    if (includingSelf) {
        if (input instanceof CtTypeReference) {
            outputConsumer.accept(((CtTypeReference<?>) input).getTypeDeclaration());
        } else {
            outputConsumer.accept(((CtType<?>) input));
        }
    }
    fnc.addSuperType(input);
    fnc.forEachSubTypeInPackage(new CtConsumer<CtType>() {

        @Override
        public void accept(CtType typeInfo) {
            outputConsumer.accept(typeInfo);
            if (query.isTerminated()) {
            // Cannot terminate, because it's support was removed.
            // I think there are cases where it might be useful.
            // fnc.terminate();
            }
        }
    });
}
Also used : CtType(spoon.reflect.declaration.CtType) CtTypeReference(spoon.reflect.reference.CtTypeReference) SubInheritanceHierarchyResolver(spoon.support.visitor.SubInheritanceHierarchyResolver)

Example 3 with SubInheritanceHierarchyResolver

use of spoon.support.visitor.SubInheritanceHierarchyResolver 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);
    }
}
Also used : ClassTypingContext(spoon.support.visitor.ClassTypingContext) ClassTypingContext(spoon.support.visitor.ClassTypingContext) CtLambda(spoon.reflect.code.CtLambda) CtQuery(spoon.reflect.visitor.chain.CtQuery) ArrayList(java.util.ArrayList) CtType(spoon.reflect.declaration.CtType) SubInheritanceHierarchyResolver(spoon.support.visitor.SubInheritanceHierarchyResolver) CtMethod(spoon.reflect.declaration.CtMethod) HashSet(java.util.HashSet)

Aggregations

CtType (spoon.reflect.declaration.CtType)3 SubInheritanceHierarchyResolver (spoon.support.visitor.SubInheritanceHierarchyResolver)3 ArrayList (java.util.ArrayList)1 HashSet (java.util.HashSet)1 Test (org.junit.Test)1 Launcher (spoon.Launcher)1 CtLambda (spoon.reflect.code.CtLambda)1 CtMethod (spoon.reflect.declaration.CtMethod)1 CtTypeReference (spoon.reflect.reference.CtTypeReference)1 CtQuery (spoon.reflect.visitor.chain.CtQuery)1 ClassTypingContext (spoon.support.visitor.ClassTypingContext)1 AbstractTostada (spoon.test.filters.testclasses.AbstractTostada)1 ITostada (spoon.test.filters.testclasses.ITostada)1 SubTostada (spoon.test.filters.testclasses.SubTostada)1 Tostada (spoon.test.filters.testclasses.Tostada)1