Search in sources :

Example 86 with CtType

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

the class SuperInheritanceHierarchyFunction method apply.

@Override
public void apply(CtTypeInformation input, CtConsumer<Object> outputConsumer) {
    CtTypeReference<?> typeRef;
    CtType<?> type;
    // detect whether input is a class or something else (e.g. interface)
    boolean isClass;
    if (input instanceof CtType) {
        type = (CtType<?>) input;
        typeRef = type.getReference();
    } else {
        typeRef = (CtTypeReference<?>) input;
        try {
            type = typeRef.getTypeDeclaration();
        } catch (SpoonClassNotFoundException e) {
            if (typeRef.getFactory().getEnvironment().getNoClasspath() == false) {
                throw e;
            }
            type = null;
        }
    }
    // if the type is unknown, than we expect it is interface, otherwise we would visit java.lang.Object too, even for interfaces
    isClass = type == null ? false : (type instanceof CtClass);
    if (isClass == false && includingInterfaces == false) {
        // the input is interface, but this scanner should visit only interfaces. Finish
        return;
    }
    ScanningMode mode = enter(typeRef, isClass);
    if (mode == SKIP_ALL) {
        // listener decided to not visit that input. Finish
        return;
    }
    if (includingSelf) {
        sendResult(typeRef, outputConsumer);
        if (query.isTerminated()) {
            mode = SKIP_CHILDREN;
        }
    }
    if (mode == NORMAL) {
        if (isClass == false) {
            visitSuperInterfaces(typeRef, outputConsumer);
        } else {
            // call visitSuperClasses only for input of type class. The contract of visitSuperClasses requires that
            visitSuperClasses(typeRef, outputConsumer, includingInterfaces);
        }
    }
    exit(typeRef, isClass);
}
Also used : CtClass(spoon.reflect.declaration.CtClass) CtType(spoon.reflect.declaration.CtType) SpoonClassNotFoundException(spoon.support.SpoonClassNotFoundException) ScanningMode(spoon.reflect.visitor.chain.ScanningMode)

Example 87 with CtType

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

Example 88 with CtType

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

the class LocalVariableReferenceFunction method apply.

@Override
public void apply(final CtElement scope, CtConsumer<Object> outputConsumer) {
    CtVariable<?> var = targetVariable;
    if (var == null) {
        if (variableClass.isInstance(scope)) {
            var = (CtVariable<?>) scope;
        } else {
            throw new SpoonException("The input of " + getClass().getSimpleName() + " must be a " + variableClass.getSimpleName() + " but is " + scope.getClass().getSimpleName());
        }
    }
    final CtVariable<?> variable = var;
    final String simpleName = variable.getSimpleName();
    // the context which knows whether we are scanning in scope of local type or not
    final Context context = new Context();
    CtQuery scopeQuery;
    if (scope == variable) {
        // we are starting search from local variable declaration
        scopeQuery = createScopeQuery(variable, scope, context);
    } else {
        // we are starting search later, somewhere deep in scope of variable declaration
        final CtElement variableParent = variable.getParent();
        /*
			 * search in parents of searching scope for the variableParent
			 * 1) to check that scope is a child of variableParent
			 * 2) to detect if there is an local class between variable declaration and scope
			 */
        if (scope.map(new ParentFunction()).select(new Filter<CtElement>() {

            @Override
            public boolean matches(CtElement element) {
                if (element instanceof CtType) {
                    // detected that the search scope is in local class declared in visibility scope of variable
                    context.nrTypes++;
                }
                return variableParent == element;
            }
        }).first() == null) {
            // the scope is not under children of localVariable
            throw new SpoonException("Cannot search for references of variable in wrong scope.");
        }
        // search in all children of the scope element
        scopeQuery = scope.map(new CtScannerFunction().setListener(context));
    }
    scopeQuery.select(new Filter<CtElement>() {

        @Override
        public boolean matches(CtElement element) {
            if (variableReferenceClass.isInstance(element)) {
                CtVariableReference<?> varRef = (CtVariableReference<?>) element;
                if (simpleName.equals(varRef.getSimpleName())) {
                    // we have found a variable reference of required type in visibility scope of targetVariable
                    if (context.hasLocalType()) {
                        // so finally check that found variable reference is really a reference to target variable
                        return variable == varRef.getDeclaration();
                    }
                    // else we can be sure that found reference is reference to variable
                    return true;
                }
            }
            return false;
        }
    }).forEach(outputConsumer);
}
Also used : CtVariableReference(spoon.reflect.reference.CtVariableReference) SpoonException(spoon.SpoonException) CtElement(spoon.reflect.declaration.CtElement) CtQuery(spoon.reflect.visitor.chain.CtQuery) CtType(spoon.reflect.declaration.CtType) Filter(spoon.reflect.visitor.Filter)

Example 89 with CtType

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

the class CtQueryImpl method getIndexOfCallerInStackOfLambda.

/**
 * JVM implementations reports exception in call of lambda in different way.
 * A) the to be called lambda expression whose input parameters are invalid is on top of stack trace
 * B) the to be called lambda expression whose input parameters are invalid is NOT in stack trace at all
 *
 * This method detects actual behavior of JVM, so the code, which decides whether ClassCastException is expected (part of filtering process)
 * or unexpected - thrown by clients wrong code works on all JVM implementations
 */
private static int getIndexOfCallerInStackOfLambda() {
    CtConsumer<CtType<?>> f = (CtType<?> t) -> {
    };
    CtConsumer<Object> unchecked = (CtConsumer) f;
    Object obj = new Integer(1);
    try {
        unchecked.accept(obj);
        throw new SpoonException("The lambda expression with input type CtType must throw ClassCastException when input type is Integer. Basic CtQuery contract is violated by JVM!");
    } catch (ClassCastException e) {
        StackTraceElement[] stack = e.getStackTrace();
        for (int i = 0; i < stack.length; i++) {
            if ("getIndexOfCallerInStackOfLambda".equals(stack[i].getMethodName())) {
                // check whether we can detect type of lambda input parameter from CCE
                Class<?> detectectedClass = detectTargetClassFromCCE(e, obj);
                if (CtType.class.equals(detectectedClass) == false) {
                    // mark it by negative index, so the query engine will fall back to eating of all CCEs and slow implementation
                    return -1;
                }
                return i;
            }
        }
        throw new SpoonException("Spoon cannot detect index of caller of lambda expression in stack trace.", e);
    }
}
Also used : CtType(spoon.reflect.declaration.CtType) SpoonException(spoon.SpoonException)

Example 90 with CtType

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

the class APITest method testPrintNotAllSourcesWithFilter.

@Test
public void testPrintNotAllSourcesWithFilter() throws Exception {
    // contract: setOutputFilter can take an arbitrary filter
    final File target = new File("./target/print-not-all/default");
    final SpoonAPI launcher = new Launcher();
    launcher.getEnvironment().setNoClasspath(true);
    launcher.addInputResource("./src/main/java/spoon/template/");
    launcher.setSourceOutputDirectory(target);
    launcher.setOutputFilter(new AbstractFilter<CtType<?>>(CtType.class) {

        @Override
        public boolean matches(CtType<?> element) {
            return "spoon.template.Parameter".equals(element.getQualifiedName()) || "spoon.template.AbstractTemplate".equals(element.getQualifiedName());
        }
    });
    launcher.run();
    List<File> list = new ArrayList<>(FileUtils.listFiles(target, new String[] { "java" }, true));
    final List<String> filesName = list.stream().map(File::getName).sorted().collect(Collectors.<String>toList());
    assertEquals(2, filesName.size());
    assertEquals("AbstractTemplate.java", filesName.get(0));
    assertEquals("Parameter.java", filesName.get(1));
}
Also used : CtType(spoon.reflect.declaration.CtType) ArrayList(java.util.ArrayList) Launcher(spoon.Launcher) File(java.io.File) SpoonAPI(spoon.SpoonAPI) Test(org.junit.Test)

Aggregations

CtType (spoon.reflect.declaration.CtType)134 Test (org.junit.Test)67 Launcher (spoon.Launcher)60 ArrayList (java.util.ArrayList)42 CtMethod (spoon.reflect.declaration.CtMethod)38 CtTypeReference (spoon.reflect.reference.CtTypeReference)30 DefaultJavaPrettyPrinter (spoon.reflect.visitor.DefaultJavaPrettyPrinter)20 File (java.io.File)19 Factory (spoon.reflect.factory.Factory)19 PrettyPrinter (spoon.reflect.visitor.PrettyPrinter)19 List (java.util.List)18 Collectors (java.util.stream.Collectors)17 CtField (spoon.reflect.declaration.CtField)17 CtElement (spoon.reflect.declaration.CtElement)16 CtPackage (spoon.reflect.declaration.CtPackage)16 InputConfiguration (fr.inria.diversify.utils.sosiefier.InputConfiguration)14 IOException (java.io.IOException)12 SpoonException (spoon.SpoonException)12 DSpotCompiler (fr.inria.diversify.utils.compilation.DSpotCompiler)11 Set (java.util.Set)11