Search in sources :

Example 21 with CtElement

use of spoon.reflect.declaration.CtElement in project spoon by INRIA.

the class SiblingsFunction method apply.

@Override
public void apply(final CtElement input, final CtConsumer<Object> outputConsumer) {
    final CtElement parent = input.getParent();
    parent.accept(new CtScanner() {

        boolean hasVisitedInput = false;

        boolean visitPrev = mode == Mode.ALL || mode == Mode.PREVIOUS;

        boolean visitNext = mode == Mode.ALL || mode == Mode.NEXT;

        @Override
        public void scan(CtElement element) {
            if (element != null && element.isParentInitialized() && element.getParent() == parent) {
                // visit only elements whose parent is same
                boolean canVisit = hasVisitedInput ? visitNext : visitPrev;
                if (input == element) {
                    hasVisitedInput = true;
                    canVisit = includingSelf;
                }
                if (canVisit) {
                    outputConsumer.accept(element);
                }
            }
        }
    });
}
Also used : CtElement(spoon.reflect.declaration.CtElement) CtScanner(spoon.reflect.visitor.CtScanner)

Example 22 with CtElement

use of spoon.reflect.declaration.CtElement in project spoon by INRIA.

the class AstParentConsistencyChecker method scan.

@Override
public void scan(CtElement element) {
    if (element == null) {
        return;
    }
    if (parent != null && // this is the fix of #1747
    element.isParentInitialized() && element.getParent() != parent) {
        throw new IllegalStateException(// better debug
        toDebugString(element) + " is set as child of\n" + toDebugString(element.getParent()) + "however it is visited as a child of\n" + toDebugString(parent));
    }
    CtElement parent = this.parent;
    this.parent = element;
    super.scan(element);
    this.parent = parent;
}
Also used : CtElement(spoon.reflect.declaration.CtElement)

Example 23 with CtElement

use of spoon.reflect.declaration.CtElement in project spoon by INRIA.

the class CtDequeScanner method exit.

/**
 * Pops the element.
 */
protected void exit(CtElement e) {
    CtElement ret = elementsDeque.pop();
    if (ret != e) {
        throw new RuntimeException("Unconsitant Stack");
    }
    super.exit(e);
}
Also used : CtElement(spoon.reflect.declaration.CtElement)

Example 24 with CtElement

use of spoon.reflect.declaration.CtElement in project spoon by INRIA.

the class CtCatchVariableReferenceImpl method getDeclaration.

@Override
public CtCatchVariable<T> getDeclaration() {
    CtElement element = this;
    String name = getSimpleName();
    CtCatchVariable var;
    try {
        do {
            CtCatch catchBlock = element.getParent(CtCatch.class);
            if (catchBlock == null) {
                return null;
            }
            var = catchBlock.getParameter();
            element = catchBlock;
        } while (!name.equals(var.getSimpleName()));
    } catch (ParentNotInitializedException e) {
        return null;
    }
    return var;
}
Also used : ParentNotInitializedException(spoon.reflect.declaration.ParentNotInitializedException) CtElement(spoon.reflect.declaration.CtElement) CtCatch(spoon.reflect.code.CtCatch) CtCatchVariable(spoon.reflect.code.CtCatchVariable)

Example 25 with CtElement

use of spoon.reflect.declaration.CtElement 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)

Aggregations

CtElement (spoon.reflect.declaration.CtElement)86 Test (org.junit.Test)39 Launcher (spoon.Launcher)23 Factory (spoon.reflect.factory.Factory)18 ArrayList (java.util.ArrayList)17 CtMethod (spoon.reflect.declaration.CtMethod)17 CtType (spoon.reflect.declaration.CtType)15 CtStatement (spoon.reflect.code.CtStatement)14 CtTypeReference (spoon.reflect.reference.CtTypeReference)14 List (java.util.List)12 CtClass (spoon.reflect.declaration.CtClass)12 CtField (spoon.reflect.declaration.CtField)12 CtIf (spoon.reflect.code.CtIf)11 CtInvocation (spoon.reflect.code.CtInvocation)11 TypeFilter (spoon.reflect.visitor.filter.TypeFilter)11 CtLocalVariable (spoon.reflect.code.CtLocalVariable)10 CtExecutableReference (spoon.reflect.reference.CtExecutableReference)9 CtScanner (spoon.reflect.visitor.CtScanner)9 NamedElementFilter (spoon.reflect.visitor.filter.NamedElementFilter)9 Collection (java.util.Collection)8