Search in sources :

Example 46 with CtInvocation

use of spoon.reflect.code.CtInvocation in project spoon by INRIA.

the class CtScannerTest method testScannerCallsAllProperties.

@Test
public void testScannerCallsAllProperties() throws Exception {
    // contract: CtScanner must visit all metamodel properties and use correct CtRole!
    final Launcher launcher = new Launcher();
    launcher.addInputResource("./src/main/java/spoon/reflect/");
    launcher.run();
    CtTypeReference<?> ctElementRef = launcher.getFactory().createCtTypeReference(CtElement.class);
    CtTypeReference<?> ctRefRef = launcher.getFactory().createCtTypeReference(CtReference.class);
    CtClass<?> scannerCtClass = (CtClass<?>) launcher.getFactory().Type().get(CtScanner.class);
    List<String> problems = new ArrayList<>();
    Set<String> ignoredInvocations = new HashSet(Arrays.asList("scan", "enter", "exit"));
    SpoonMetaModel metaModel = new SpoonMetaModel(new File("./src/main/java"));
    // collect all scanner visit methods, to check if all were checked
    Map<String, CtMethod<?>> scannerVisitMethodsByName = new HashMap<>();
    scannerCtClass.getAllMethods().forEach(m -> {
        if (m.getSimpleName().startsWith("visit")) {
            scannerVisitMethodsByName.put(m.getSimpleName(), m);
        }
    });
    class Counter {

        int nbChecks = 0;
    }
    Counter c = new Counter();
    for (MetamodelConcept leafConcept : metaModel.getConcepts()) {
        // we only consider leaf, actual classes of the metamodel (eg CtInvocation) and not abstract ones (eg CtModifiable)
        if (leafConcept.getKind() != MMTypeKind.LEAF) {
            continue;
        }
        CtMethod<?> visitMethod = scannerVisitMethodsByName.remove("visit" + leafConcept.getName());
        assertNotNull("CtScanner#" + "visit" + leafConcept.getName() + "(...) not found", visitMethod);
        Set<String> calledMethods = new HashSet<>();
        Set<String> checkedMethods = new HashSet<>();
        // go over the roles and the corresponding fields of this type
        leafConcept.getRoleToProperty().forEach((role, mmField) -> {
            if (mmField.isDerived()) {
                // return of the lambda
                return;
            }
            // ignore fields, which doesn't return CtElement
            if (mmField.getItemValueType().isSubtypeOf(ctElementRef) == false) {
                // return of the lambda
                return;
            }
            MMMethod getter = mmField.getMethod(MMMethodKind.GET);
            checkedMethods.add(getter.getSignature());
            // System.out.println("checking "+m.getSignature() +" in "+visitMethod.getSignature());
            // now, we collect at least one invocation to this getter in the visit method
            CtInvocation invocation = visitMethod.filterChildren(new TypeFilter<CtInvocation>(CtInvocation.class) {

                @Override
                public boolean matches(CtInvocation element) {
                    if (ignoredInvocations.contains(element.getExecutable().getSimpleName())) {
                        return false;
                    }
                    calledMethods.add(element.getExecutable().getSignature());
                    return super.matches(element) && element.getExecutable().getSimpleName().equals(getter.getName());
                }
            }).first();
            if (getter.getName().equals("getComments") && leafConcept.getModelInterface().isSubtypeOf(ctRefRef)) {
                // one cannot set comments on references see the @UnsettableProperty of CtReference#setComments
                return;
            }
            // contract: there ia at least one invocation to all non-derived, role-based getters in the visit method of the Scanner
            if (invocation == null) {
                problems.add("no " + getter.getSignature() + " in " + visitMethod);
            } else {
                c.nbChecks++;
                // System.out.println(invocation.toString());
                // contract: the scan method is called with the same role as the one set on field / property
                CtRole expectedRole = metaModel.getRoleOfMethod((CtMethod<?>) invocation.getExecutable().getDeclaration());
                CtInvocation<?> scanInvocation = invocation.getParent(CtInvocation.class);
                String realRoleName = ((CtFieldRead<?>) scanInvocation.getArguments().get(0)).getVariable().getSimpleName();
                if (expectedRole.name().equals(realRoleName) == false) {
                    problems.add("Wrong role " + realRoleName + " used in " + scanInvocation.getPosition());
                }
            }
        });
        calledMethods.removeAll(checkedMethods);
        // contract: CtScanner only calls methods that have a role and the associated getter
        if (calledMethods.size() > 0) {
            problems.add("CtScanner " + visitMethod.getPosition() + " calls unexpected methods: " + calledMethods);
        }
    }
    // contract: all visit* methods in CtScanner have been checked
    if (scannerVisitMethodsByName.isEmpty() == false) {
        problems.add("These CtScanner visit methods were not checked: " + scannerVisitMethodsByName.keySet());
    }
    if (problems.size() > 0) {
        fail(String.join("\n", problems));
    }
    assertTrue("not enough checks", c.nbChecks >= 200);
}
Also used : SpoonMetaModel(spoon.test.metamodel.SpoonMetaModel) MMMethod(spoon.test.metamodel.MMMethod) HashMap(java.util.HashMap) ArrayList(java.util.ArrayList) TypeFilter(spoon.reflect.visitor.filter.TypeFilter) CtClass(spoon.reflect.declaration.CtClass) CtInvocation(spoon.reflect.code.CtInvocation) Launcher(spoon.Launcher) CtRole(spoon.reflect.path.CtRole) File(java.io.File) MetamodelConcept(spoon.test.metamodel.MetamodelConcept) CtMethod(spoon.reflect.declaration.CtMethod) HashSet(java.util.HashSet) Test(org.junit.Test)

Example 47 with CtInvocation

use of spoon.reflect.code.CtInvocation in project spoon by INRIA.

the class ReplaceScanner method visitCtMethod.

@Override
public <T> void visitCtMethod(CtMethod<T> element) {
    if (!element.getSimpleName().startsWith("visitCt")) {
        return;
    }
    Factory factory = element.getFactory();
    CtMethod<T> clone = element.clone();
    factory.Annotation().annotate(clone, Override.class);
    clone.getBody().getStatements().clear();
    for (int i = 1; i < element.getBody().getStatements().size() - 1; i++) {
        CtInvocation inv = element.getBody().getStatement(i);
        List<CtExpression<?>> invArgs = new ArrayList<>(inv.getArguments());
        if (invArgs.size() <= 1) {
            throw new RuntimeException("You forget the role argument in line " + i + " of method " + element.getSimpleName() + " from " + element.getDeclaringType().getQualifiedName());
        }
        // remove role argument
        invArgs.remove(0);
        CtInvocation getter = (CtInvocation) invArgs.get(0);
        if (clone.getComments().size() == 0) {
            // Add auto-generated comment.
            final CtComment comment = factory.Core().createComment();
            comment.setCommentType(CtComment.CommentType.INLINE);
            comment.setContent("auto-generated, see " + ReplacementVisitorGenerator.class.getName());
            clone.addComment(comment);
        }
        Class actualClass = getter.getType().getActualClass();
        CtInvocation<?> invocation = createInvocation(factory, element, invArgs, getter, actualClass);
        clone.getBody().addStatement(invocation);
    }
    target.addMethod(clone);
}
Also used : CtComment(spoon.reflect.code.CtComment) CtInvocation(spoon.reflect.code.CtInvocation) CtExpression(spoon.reflect.code.CtExpression) ArrayList(java.util.ArrayList) Factory(spoon.reflect.factory.Factory) CtClass(spoon.reflect.declaration.CtClass)

Example 48 with CtInvocation

use of spoon.reflect.code.CtInvocation in project spoon by INRIA.

the class AstCheckerTest method testAvoidSetCollectionSavedOnAST.

@Test
public void testAvoidSetCollectionSavedOnAST() throws Exception {
    final Launcher launcher = new Launcher();
    launcher.getEnvironment().setNoClasspath(true);
    launcher.addInputResource("src/main/java");
    launcher.buildModel();
    final Factory factory = launcher.getFactory();
    final List<CtTypeReference<?>> collectionsRef = // 
    Arrays.asList(// 
    factory.Type().createReference(Collection.class), // 
    factory.Type().createReference(List.class), // 
    factory.Type().createReference(Set.class), factory.Type().createReference(Map.class));
    final List<CtInvocation<?>> invocations = Query.getElements(factory, new TypeFilter<CtInvocation<?>>(CtInvocation.class) {

        @Override
        public boolean matches(CtInvocation<?> element) {
            if (!(element.getParent() instanceof CtInvocation)) {
                return false;
            }
            final CtInvocation<?> parent = (CtInvocation<?>) element.getParent();
            if (parent.getTarget() == null || !parent.getTarget().equals(element)) {
                return false;
            }
            if (!element.getExecutable().getDeclaringType().getSimpleName().startsWith("Ct")) {
                return false;
            }
            boolean isDataStructure = false;
            for (int i = 0; i < collectionsRef.size(); i++) {
                CtTypeReference<?> ctTypeReference = collectionsRef.get(i);
                if (element.getType().isSubtypeOf(ctTypeReference)) {
                    isDataStructure = true;
                    break;
                }
            }
            if (!isDataStructure) {
                return false;
            }
            final String simpleName = parent.getExecutable().getSimpleName();
            return simpleName.startsWith("add") || simpleName.startsWith("remove") || simpleName.startsWith("put");
        }
    });
    if (invocations.size() > 0) {
        final String error = // 
        invocations.stream().sorted(// 
        new CtLineElementComparator()).map(// 
        i -> "see " + i.getPosition().getFile().getAbsoluteFile() + " at " + i.getPosition().getLine()).collect(Collectors.joining(",\n"));
        throw new AssertionError(error);
    }
}
Also used : Arrays(java.util.Arrays) CtIf(spoon.reflect.code.CtIf) Launcher(spoon.Launcher) CtScanner(spoon.reflect.visitor.CtScanner) CtThrow(spoon.reflect.code.CtThrow) FineModelChangeListener(spoon.experimental.modelobs.FineModelChangeListener) Map(java.util.Map) CtExecutable(spoon.reflect.declaration.CtExecutable) Query(spoon.reflect.visitor.Query) DerivedProperty(spoon.support.DerivedProperty) CtLineElementComparator(spoon.support.comparator.CtLineElementComparator) TypeFilter(spoon.reflect.visitor.filter.TypeFilter) CtInvocation(spoon.reflect.code.CtInvocation) Collection(java.util.Collection) Set(java.util.Set) Test(org.junit.Test) Factory(spoon.reflect.factory.Factory) Collectors(java.util.stream.Collectors) CtTypeReference(spoon.reflect.reference.CtTypeReference) List(java.util.List) ModifierKind(spoon.reflect.declaration.ModifierKind) CtBlock(spoon.reflect.code.CtBlock) CtReturn(spoon.reflect.code.CtReturn) UnsettableProperty(spoon.support.UnsettableProperty) CtMethod(spoon.reflect.declaration.CtMethod) Set(java.util.Set) Factory(spoon.reflect.factory.Factory) CtInvocation(spoon.reflect.code.CtInvocation) CtTypeReference(spoon.reflect.reference.CtTypeReference) Launcher(spoon.Launcher) Collection(java.util.Collection) CtLineElementComparator(spoon.support.comparator.CtLineElementComparator) List(java.util.List) Map(java.util.Map) Test(org.junit.Test)

Example 49 with CtInvocation

use of spoon.reflect.code.CtInvocation in project spoon by INRIA.

the class EqualTest method testEqualsEmptyException.

@Test
public void testEqualsEmptyException() throws Exception {
    Factory factory = new Launcher().createFactory();
    String realParam1 = "\"\"";
    String content = "" + "class X {" + "public Object foo() {" + " Integer.getInteger(" + realParam1 + ");" + " return \"\";" + "}};";
    SpoonModelBuilder builder = new JDTSnippetCompiler(factory, content);
    try {
        builder.build();
    } catch (Exception e) {
        e.printStackTrace();
        fail("Unable create model");
    }
    CtClass<?> clazz1 = (CtClass<?>) factory.Type().getAll().get(0);
    CtMethod<?> method = (CtMethod<?>) clazz1.getMethods().toArray()[0];
    CtInvocation<?> invo = (CtInvocation<?>) method.getBody().getStatement(0);
    CtLiteral<?> argument1 = (CtLiteral<?>) invo.getArguments().get(0);
    assertEquals(realParam1, argument1.toString());
    CtReturn<?> returnStatement = (CtReturn<?>) method.getBody().getStatement(1);
    CtLiteral<?> returnExp = (CtLiteral<?>) returnStatement.getReturnedExpression();
    assertEquals(realParam1, returnExp.toString());
    try {
        assertEquals(argument1, returnExp);
    } catch (Exception e) {
        fail(e.getMessage());
    }
}
Also used : SpoonModelBuilder(spoon.SpoonModelBuilder) Factory(spoon.reflect.factory.Factory) CtClass(spoon.reflect.declaration.CtClass) CtInvocation(spoon.reflect.code.CtInvocation) CtLiteral(spoon.reflect.code.CtLiteral) CtReturn(spoon.reflect.code.CtReturn) JDTSnippetCompiler(spoon.support.compiler.jdt.JDTSnippetCompiler) Launcher(spoon.Launcher) CtMethod(spoon.reflect.declaration.CtMethod) Test(org.junit.Test)

Example 50 with CtInvocation

use of spoon.reflect.code.CtInvocation in project spoon by INRIA.

the class JDTTreeBuilder method visit.

@Override
public boolean visit(SingleNameReference singleNameReference, BlockScope scope) {
    if (singleNameReference.binding instanceof FieldBinding) {
        context.enter(helper.createFieldAccess(singleNameReference), singleNameReference);
    } else if (singleNameReference.binding instanceof VariableBinding) {
        context.enter(helper.createVariableAccess(singleNameReference), singleNameReference);
    } else if (singleNameReference.binding instanceof TypeBinding) {
        context.enter(factory.Code().createTypeAccessWithoutCloningReference(references.getTypeReference((TypeBinding) singleNameReference.binding)), singleNameReference);
    } else if (singleNameReference.binding instanceof ProblemBinding) {
        if (context.stack.peek().element instanceof CtInvocation && Character.isUpperCase(CharOperation.charToString(singleNameReference.token).charAt(0))) {
            context.enter(helper.createTypeAccessNoClasspath(singleNameReference), singleNameReference);
        } else {
            context.enter(helper.createFieldAccessNoClasspath(singleNameReference), singleNameReference);
        }
    } else if (singleNameReference.binding == null) {
        CtExpression access = helper.createVariableAccessNoClasspath(singleNameReference);
        if (access == null) {
            access = helper.createTypeAccessNoClasspath(singleNameReference);
        }
        context.enter(access, singleNameReference);
    }
    return true;
}
Also used : CtInvocation(spoon.reflect.code.CtInvocation) CtExpression(spoon.reflect.code.CtExpression) TypeBinding(org.eclipse.jdt.internal.compiler.lookup.TypeBinding) FieldBinding(org.eclipse.jdt.internal.compiler.lookup.FieldBinding) VariableBinding(org.eclipse.jdt.internal.compiler.lookup.VariableBinding) ProblemBinding(org.eclipse.jdt.internal.compiler.lookup.ProblemBinding)

Aggregations

CtInvocation (spoon.reflect.code.CtInvocation)64 Test (org.junit.Test)49 Factory (spoon.reflect.factory.Factory)30 Launcher (spoon.Launcher)27 CtMethod (spoon.reflect.declaration.CtMethod)25 TypeFilter (spoon.reflect.visitor.filter.TypeFilter)25 CtClass (spoon.reflect.declaration.CtClass)18 CtTypeReference (spoon.reflect.reference.CtTypeReference)11 List (java.util.List)9 CtExecutableReference (spoon.reflect.reference.CtExecutableReference)9 ReferenceTypeFilter (spoon.reflect.visitor.filter.ReferenceTypeFilter)9 CtStatement (spoon.reflect.code.CtStatement)8 CtBlock (spoon.reflect.code.CtBlock)7 CtElement (spoon.reflect.declaration.CtElement)7 CtIf (spoon.reflect.code.CtIf)6 CtLiteral (spoon.reflect.code.CtLiteral)6 AbstractTest (fr.inria.AbstractTest)5 InputProgram (fr.inria.diversify.utils.sosiefier.InputProgram)5 ArrayList (java.util.ArrayList)5 Arrays (java.util.Arrays)5