Search in sources :

Example 6 with CtQuery

use of spoon.reflect.visitor.chain.CtQuery in project spoon by INRIA.

the class AllMethodsSameSignatureFunction method forEachOverridenMethod.

/**
 * calls outputConsumer for each method which is overridden by 'thisMethod' in scope of `ctc`.
 * There is assured that each method is returned only once.
 *
 * @param ctc - class typing context whose scope is searched for overridden methods
 * @param thisMethod - the
 * @param distintTypesSet set of qualified names of types which were already visited
 * @param outputConsumer result handling consumer
 */
private void forEachOverridenMethod(final ClassTypingContext ctc, final CtMethod<?> thisMethod, Set<String> distintTypesSet, final CtConsumer<CtMethod<?>> outputConsumer) {
    final CtQuery q = ctc.getAdaptationScope().map(new AllTypeMembersFunction(CtMethod.class).distinctSet(distintTypesSet));
    q.forEach(new CtConsumer<CtMethod<?>>() {

        @Override
        public void accept(CtMethod<?> thatMethod) {
            if (thisMethod == thatMethod) {
                // do not return scope method
                return;
            }
            /*
				 * note: we are in super inheritance hierarchy of type declaring input `method`, so we do not have to check isSubTypeOf.
				 * Check for isSubSignature is enough
				 */
            if (ctc.isSubSignature(thisMethod, thatMethod)) {
                outputConsumer.accept(thatMethod);
                if (query.isTerminated()) {
                    q.terminate();
                }
            }
        }
    });
}
Also used : CtQuery(spoon.reflect.visitor.chain.CtQuery) CtMethod(spoon.reflect.declaration.CtMethod)

Example 7 with CtQuery

use of spoon.reflect.visitor.chain.CtQuery in project spoon by INRIA.

the class AllTypeMembersFunction method apply.

@Override
public void apply(CtTypeInformation input, final CtConsumer<Object> outputConsumer) {
    final CtQuery q = ((CtQueryable) input).map(new SuperInheritanceHierarchyFunction(distinctSet == null ? new HashSet<String>() : distinctSet).includingSelf(true));
    q.forEach(new CtConsumer<CtType<?>>() {

        @Override
        public void accept(CtType<?> type) {
            for (CtTypeMember typeMember : type.getTypeMembers()) {
                if (memberClass == null || memberClass.isInstance(typeMember)) {
                    outputConsumer.accept(typeMember);
                }
                if (query.isTerminated()) {
                    q.terminate();
                }
            }
        }
    });
}
Also used : CtType(spoon.reflect.declaration.CtType) CtTypeMember(spoon.reflect.declaration.CtTypeMember) CtQueryable(spoon.reflect.visitor.chain.CtQueryable) CtQuery(spoon.reflect.visitor.chain.CtQuery) HashSet(java.util.HashSet)

Example 8 with CtQuery

use of spoon.reflect.visitor.chain.CtQuery in project spoon by INRIA.

the class SubInheritanceHierarchyResolver method forEachSubTypeInPackage.

/**
 * Calls `outputConsumer.apply(subType)` for each sub type of the targetSuperTypes that are found in `inputPackage`.
 * Each sub type is returned only once.
 * It makes sense to call this method again for example after new super types are added
 * by {@link #addSuperType(CtTypeInformation)}.
 *
 * 	If this method is called again with same input and configuration, nothing in sent to outputConsumer
 * @param outputConsumer the consumer for found sub types
 */
public <T extends CtType<?>> void forEachSubTypeInPackage(final CtConsumer<T> outputConsumer) {
    /*
		 * Set of qualified names of all visited types, independent on whether they are sub types or not.
		 */
    final Set<String> allVisitedTypeNames = new HashSet<>();
    /*
		 * the queue of types whose super inheritance hierarchy we are just visiting.
		 * They are potential sub types of an `targetSuperTypes`
		 */
    final Deque<CtTypeReference<?>> currentSubTypes = new ArrayDeque<>();
    // algorithm
    // 1) query step: scan input package for sub classes and sub interfaces
    final CtQuery q = inputPackage.map(new CtScannerFunction());
    // 2) query step: visit only required CtTypes
    if (includingInterfaces) {
        // the client is interested in sub inheritance hierarchy of interfaces too. Check interfaces, classes, enums, Annotations, but not CtTypeParameters.
        q.select(typeFilter);
    } else {
        // the client is not interested in sub inheritance hierarchy of interfaces. Check only classes and enums.
        q.select(classFilter);
    }
    /*
		 * 3) query step: for each found CtType, visit it's super inheritance hierarchy and search there for a type which is equal to one of targetSuperTypes.
		 * If found then all sub types in hierarchy (variable `currentSubTypes`) are sub types of targetSuperTypes. So return them
		 */
    q.map(new SuperInheritanceHierarchyFunction().includingInterfaces(hasSuperInterface).failOnClassNotFound(failOnClassNotFound).setListener(new CtScannerListener() {

        @Override
        public ScanningMode enter(CtElement element) {
            final CtTypeReference<?> typeRef = (CtTypeReference<?>) element;
            String qName = typeRef.getQualifiedName();
            if (targetSuperTypes.contains(qName)) {
                /*
						 * FOUND! we are in super inheritance hierarchy, which extends from an searched super type(s).
						 * All `currentSubTypes` are sub types of searched super type
						 */
                while (currentSubTypes.size() > 0) {
                    final CtTypeReference<?> currentTypeRef = currentSubTypes.pop();
                    String currentQName = currentTypeRef.getQualifiedName();
                    /*
							 * Send them to outputConsumer and add then as targetSuperTypes too, to perform faster with detection of next sub types.
							 */
                    if (!targetSuperTypes.contains(currentQName)) {
                        targetSuperTypes.add(currentQName);
                        outputConsumer.accept((T) currentTypeRef.getTypeDeclaration());
                    }
                }
                // but continue visiting of siblings (do not terminate query)
                return SKIP_ALL;
            }
            if (allVisitedTypeNames.add(qName) == false) {
                /*
						 * this type was already visited, by another way. So it is not sub type of `targetSuperTypes`.
						 * Stop visiting it's inheritance hierarchy.
						 */
                return SKIP_ALL;
            }
            /*
					 * This type was not visited yet.
					 * We still do not know whether this type is a sub type of any target super type(s)
					 * continue searching in super inheritance hierarchy
					 */
            currentSubTypes.push(typeRef);
            return NORMAL;
        }

        @Override
        public void exit(CtElement element) {
            CtTypeInformation type = (CtTypeInformation) element;
            if (currentSubTypes.isEmpty() == false) {
                // remove current type, which is not a sub type of targetSuperTypes from the currentSubTypes
                CtTypeInformation stackType = currentSubTypes.pop();
                if (stackType != type) {
                    // the enter/exit was not called consistently. There is a bug in SuperInheritanceHierarchyFunction
                    throw new SpoonException("CtScannerListener#exit was not called after enter.");
                }
            }
        }
    })).forEach(new CtConsumer<CtType<?>>() {

        @Override
        public void accept(CtType<?> type) {
        // we do not care about types visited by query `q`.
        // the result of whole mapping function was already produced by `sendResult` call
        // but we have to consume all these results to let query running
        }
    });
}
Also used : SuperInheritanceHierarchyFunction(spoon.reflect.visitor.filter.SuperInheritanceHierarchyFunction) SpoonException(spoon.SpoonException) CtElement(spoon.reflect.declaration.CtElement) CtQuery(spoon.reflect.visitor.chain.CtQuery) CtTypeInformation(spoon.reflect.declaration.CtTypeInformation) ArrayDeque(java.util.ArrayDeque) ScanningMode(spoon.reflect.visitor.chain.ScanningMode) CtType(spoon.reflect.declaration.CtType) CtTypeReference(spoon.reflect.reference.CtTypeReference) CtScannerFunction(spoon.reflect.visitor.filter.CtScannerFunction) CtScannerListener(spoon.reflect.visitor.chain.CtScannerListener) HashSet(java.util.HashSet)

Example 9 with CtQuery

use of spoon.reflect.visitor.chain.CtQuery in project spoon by INRIA.

the class FilterTest method testElementMapFunctionOtherContracts.

@Test
public void testElementMapFunctionOtherContracts() throws Exception {
    // contract: when a function returns an array, all non-null values are sent to the next step
    final Launcher launcher = new Launcher();
    CtQuery q = launcher.getFactory().Query().createQuery().map((String s) -> new String[] { "a", null, s });
    List<String> list = q.setInput(null).list();
    assertEquals(0, list.size());
    list = q.setInput("c").list();
    assertEquals(2, list.size());
    assertEquals("a", list.get(0));
    assertEquals("c", list.get(1));
    // contract: the input is stored, and we can evaluate the same query several times
    // using "c" as input
    list = q.list();
    assertEquals(2, list.size());
    assertEquals("a", list.get(0));
    assertEquals("c", list.get(1));
    // contract: when input is null then the query function is not called at all.
    CtQuery q2 = launcher.getFactory().Query().createQuery().map((String s) -> {
        throw new AssertionError();
    });
    assertEquals(0, q2.setInput(null).list().size());
}
Also used : CtQuery(spoon.reflect.visitor.chain.CtQuery) Launcher(spoon.Launcher) Test(org.junit.Test)

Example 10 with CtQuery

use of spoon.reflect.visitor.chain.CtQuery in project spoon by INRIA.

the class FilterTest method testReuseOfQuery.

@Test
public void testReuseOfQuery() throws Exception {
    // contract: a query created from an existing element can be reused on other inputs
    final Launcher launcher = new Launcher();
    launcher.setArgs(new String[] { "--output-type", "nooutput", "--level", "info" });
    launcher.addInputResource("./src/test/java/spoon/test/filters/testclasses");
    launcher.run();
    CtClass<?> cls = launcher.getFactory().Class().get(Tacos.class);
    CtClass<?> cls2 = launcher.getFactory().Class().get(Tostada.class);
    // by default the query starts with "cls" as input
    CtQuery q = cls.map((CtClass c) -> c.getSimpleName());
    // high-level assert
    assertEquals(cls.getSimpleName(), q.list().get(0));
    // low-level assert on implementation
    assertEquals(1, ((CtQueryImpl) q).getInputs().size());
    assertSame(cls, ((CtQueryImpl) q).getInputs().get(0));
    // now changing the input of query to cls2
    q.setInput(cls2);
    // the input is still cls2
    assertEquals(cls2.getSimpleName(), q.list().get(0));
    assertEquals(1, ((CtQueryImpl) q).getInputs().size());
    assertSame(cls2, ((CtQueryImpl) q).getInputs().get(0));
}
Also used : CtClass(spoon.reflect.declaration.CtClass) CtQuery(spoon.reflect.visitor.chain.CtQuery) Launcher(spoon.Launcher) CtQueryImpl(spoon.reflect.visitor.chain.CtQueryImpl) Test(org.junit.Test)

Aggregations

CtQuery (spoon.reflect.visitor.chain.CtQuery)16 Test (org.junit.Test)10 Launcher (spoon.Launcher)10 CtType (spoon.reflect.declaration.CtType)7 CtClass (spoon.reflect.declaration.CtClass)6 CtElement (spoon.reflect.declaration.CtElement)5 CtMethod (spoon.reflect.declaration.CtMethod)5 HashSet (java.util.HashSet)3 CtTypeReference (spoon.reflect.reference.CtTypeReference)3 ArrayList (java.util.ArrayList)2 SpoonException (spoon.SpoonException)2 CtField (spoon.reflect.declaration.CtField)2 CtQueryImpl (spoon.reflect.visitor.chain.CtQueryImpl)2 ArrayDeque (java.util.ArrayDeque)1 Arrays (java.util.Arrays)1 Collections (java.util.Collections)1 List (java.util.List)1 Set (java.util.Set)1 Collectors (java.util.stream.Collectors)1 MatcherAssert.assertThat (org.hamcrest.MatcherAssert.assertThat)1