Search in sources :

Example 16 with CtIf

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

the class NullParentTest method testIfNullBranches.

@Test
public void testIfNullBranches() {
    CtIf ctIf = get(CtIf.class);
    assertEquals("if(true){}else{}", noSpaceToString(ctIf));
    ctIf.setThenStatement(null);
    assertEquals("if(true);else{}", noSpaceToString(ctIf));
    ctIf.setElseStatement(null);
    assertEquals("if(true);", noSpaceToString(ctIf));
}
Also used : CtIf(spoon.reflect.code.CtIf) Test(org.junit.Test)

Example 17 with CtIf

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

the class ParentTest method testParentSetInSetter.

@Test
// too fragile because of conventions
@Ignore
public void testParentSetInSetter() throws Exception {
    // contract: Check that all setters protect their parameter.
    final Launcher launcher = new Launcher();
    final Factory factory = launcher.getFactory();
    launcher.setArgs(new String[] { "--output-type", "nooutput" });
    launcher.getEnvironment().setNoClasspath(true);
    // interfaces.
    launcher.addInputResource("./src/main/java/spoon/reflect/code");
    launcher.addInputResource("./src/main/java/spoon/reflect/declaration");
    launcher.addInputResource("./src/main/java/spoon/reflect/reference");
    // implementations.
    launcher.addInputResource("./src/main/java/spoon/support/reflect/code");
    launcher.addInputResource("./src/main/java/spoon/support/reflect/declaration");
    launcher.addInputResource("./src/main/java/spoon/support/reflect/reference");
    // Utils.
    launcher.addInputResource("./src/test/java/spoon/reflect/ast/");
    launcher.buildModel();
    // Asserts.
    new IntercessionScanner(launcher.getFactory()) {

        @Override
        protected boolean isToBeProcessed(CtMethod<?> candidate) {
            return (// 
            candidate.getSimpleName().startsWith("set") || // 
            candidate.getSimpleName().startsWith("add")) && // 
            candidate.hasModifier(ModifierKind.PUBLIC) && // 
            takeSetterForCtElement(candidate) && // 
            avoidInterfaces(candidate) && avoidThrowUnsupportedOperationException(candidate);
        }

        @Override
        public void process(CtMethod<?> element) {
            if (element.getAnnotation(UnsettableProperty.class) != null) {
                // we don't check the contracts for unsettable setters
                return;
            }
            if (element.getSimpleName().startsWith("add")) {
                checkAddStrategy(element);
            } else {
                checkSetStrategy(element);
            }
        }

        private void checkAddStrategy(CtMethod<?> element) {
            final CtStatement statement = element.getBody().getStatement(0);
            if (!(statement instanceof CtIf)) {
                fail("First statement should be an if to check the parameter of the setter." + element.getSignature() + " declared in " + element.getDeclaringType().getQualifiedName());
            }
            if (!createCheckNull(element.getParameters().get(0)).equals(((CtIf) statement).getCondition())) {
                fail("Condition should test if the parameter is null. The condition was " + ((CtIf) statement).getCondition() + "in " + element.getSignature() + " declared in " + element.getDeclaringType().getQualifiedName());
            }
        }

        private void checkSetStrategy(CtMethod<?> element) {
            final CtTypeReference<?> type = element.getParameters().get(0).getType();
            if (!COLLECTIONS.contains(type) && !(type instanceof CtArrayTypeReference)) {
                CtInvocation<?> setParent = searchSetParent(element.getBody());
                if (setParent == null) {
                    return;
                }
                try {
                    if (setParent.getParent(CtIf.class) == null) {
                        fail("Missing condition in " + element.getSignature() + " declared in the class " + element.getDeclaringType().getQualifiedName());
                    }
                } catch (ParentNotInitializedException e) {
                    fail("Missing parent condition in " + element.getSignature() + " declared in the class " + element.getDeclaringType().getQualifiedName());
                }
            }
        }

        /**
         * Creates <code>parameter == null</code>.
         *
         * @param ctParameter <code>parameter</code>
         */
        private CtBinaryOperator<Boolean> createCheckNull(CtParameter<?> ctParameter) {
            final CtLiteral nullLiteral = factory.Code().createLiteral(null);
            nullLiteral.setType(factory.Type().NULL_TYPE.clone());
            final CtBinaryOperator<Boolean> operator = // 
            factory.Code().createBinaryOperator(// 
            factory.Code().createVariableRead(ctParameter.getReference(), true), nullLiteral, BinaryOperatorKind.EQ);
            operator.setType(factory.Type().BOOLEAN_PRIMITIVE);
            return operator;
        }

        private CtInvocation<?> searchSetParent(CtBlock<?> body) {
            final List<CtInvocation<?>> ctInvocations = body.getElements(new TypeFilter<CtInvocation<?>>(CtInvocation.class) {

                @Override
                public boolean matches(CtInvocation<?> element) {
                    return "setParent".equals(element.getExecutable().getSimpleName()) && super.matches(element);
                }
            });
            return ctInvocations.size() > 0 ? ctInvocations.get(0) : null;
        }
    }.scan(launcher.getModel().getRootPackage());
}
Also used : ParentNotInitializedException(spoon.reflect.declaration.ParentNotInitializedException) CtBinaryOperator(spoon.reflect.code.CtBinaryOperator) Factory(spoon.reflect.factory.Factory) TypeFilter(spoon.reflect.visitor.filter.TypeFilter) ReferenceTypeFilter(spoon.reflect.visitor.filter.ReferenceTypeFilter) CtIf(spoon.reflect.code.CtIf) CtInvocation(spoon.reflect.code.CtInvocation) CtLiteral(spoon.reflect.code.CtLiteral) CtStatement(spoon.reflect.code.CtStatement) CtTypeReference(spoon.reflect.reference.CtTypeReference) Launcher(spoon.Launcher) CtStatementList(spoon.reflect.code.CtStatementList) List(java.util.List) CtArrayTypeReference(spoon.reflect.reference.CtArrayTypeReference) IntercessionScanner(spoon.test.intercession.IntercessionScanner) Ignore(org.junit.Ignore) Test(org.junit.Test)

Example 18 with CtIf

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

the class PositionTest method getPositionOfImplicitBlock.

@Test
public void getPositionOfImplicitBlock() {
    // contract: position of implicit block in if (cond) [implicit block] else [implicit block] should be the source position of implicit block content.
    Launcher launcher = new Launcher();
    launcher.addInputResource("./src/test/java/spoon/test/position/testclasses/ImplicitBlock.java");
    launcher.buildModel();
    CtIf ifElement = launcher.getModel().getElements(new TypeFilter<CtIf>(CtIf.class)).get(0);
    CtStatement thenStatement = ifElement.getThenStatement();
    assertTrue(thenStatement instanceof CtBlock);
    CtBlock thenBlock = (CtBlock) thenStatement;
    SourcePosition positionThen = thenBlock.getPosition();
    CtStatement returnStatement = thenBlock.getStatement(0);
    assertEquals(returnStatement.getPosition(), positionThen);
    assertEquals("ImplicitBlock.java", positionThen.getFile().getName());
    assertEquals(7, positionThen.getLine());
    CtStatement elseStatement = ifElement.getElseStatement();
    assertTrue(elseStatement instanceof CtBlock);
    CtBlock elseBlock = (CtBlock) elseStatement;
    SourcePosition positionElse = elseBlock.getPosition();
    CtStatement otherReturnStatement = elseBlock.getStatement(0);
    assertEquals(otherReturnStatement.getPosition(), positionElse);
    assertEquals("ImplicitBlock.java", positionThen.getFile().getName());
    assertEquals(8, positionElse.getLine());
    assertNotEquals(returnStatement, otherReturnStatement);
}
Also used : CtBlock(spoon.reflect.code.CtBlock) CtStatement(spoon.reflect.code.CtStatement) DeclarationSourcePosition(spoon.reflect.cu.position.DeclarationSourcePosition) BodyHolderSourcePosition(spoon.reflect.cu.position.BodyHolderSourcePosition) SourcePosition(spoon.reflect.cu.SourcePosition) Launcher(spoon.Launcher) TypeFilter(spoon.reflect.visitor.filter.TypeFilter) CtIf(spoon.reflect.code.CtIf) Test(org.junit.Test)

Example 19 with CtIf

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

the class APITest method testSetterInNodes.

@Test
public void testSetterInNodes() throws Exception {
    // that the new value is != null to avoid NPE when we set the parent.
    class SetterMethodWithoutCollectionsFilter extends TypeFilter<CtMethod<?>> {

        private final List<CtTypeReference<?>> collections = new ArrayList<>(4);

        public SetterMethodWithoutCollectionsFilter(Factory factory) {
            super(CtMethod.class);
            for (Class<?> aCollectionClass : Arrays.asList(Collection.class, List.class, Map.class, Set.class)) {
                collections.add(factory.Type().createReference(aCollectionClass));
            }
        }

        @Override
        public boolean matches(CtMethod<?> element) {
            boolean isSetter = isSetterMethod(element);
            boolean isNotSubType = !isSubTypeOfCollection(element);
            // setter with unsettableProperty should not respect the contract, as well as derived properties
            boolean doesNotHaveUnsettableAnnotation = doesNotHaveUnsettableAnnotation(element);
            boolean isNotSetterForADerivedProperty = isNotSetterForADerivedProperty(element);
            boolean superMatch = super.matches(element);
            return isSetter && doesNotHaveUnsettableAnnotation && isNotSetterForADerivedProperty && isNotSubType && superMatch;
        }

        private boolean isNotSetterForADerivedProperty(CtMethod<?> method) {
            String methodName = method.getSimpleName();
            String getterName = methodName.replace("set", "get");
            if (getterName.equals(methodName)) {
                return false;
            }
            CtType<?> zeClass = (CtType) method.getParent();
            List<CtMethod<?>> getterMethods = zeClass.getMethodsByName(getterName);
            if (getterMethods.size() != 1) {
                return false;
            }
            CtMethod<?> getterMethod = getterMethods.get(0);
            return (getterMethod.getAnnotation(DerivedProperty.class) == null);
        }

        private boolean doesNotHaveUnsettableAnnotation(CtMethod<?> element) {
            return (element.getAnnotation(UnsettableProperty.class) == null);
        }

        private boolean isSubTypeOfCollection(CtMethod<?> element) {
            final List<CtParameter<?>> parameters = element.getParameters();
            if (parameters.size() != 1) {
                return false;
            }
            final CtTypeReference<?> type = parameters.get(0).getType();
            for (CtTypeReference<?> aCollectionRef : collections) {
                if (type.isSubtypeOf(aCollectionRef) || type.equals(aCollectionRef)) {
                    return true;
                }
            }
            return false;
        }

        private boolean isSetterMethod(CtMethod<?> element) {
            final List<CtParameter<?>> parameters = element.getParameters();
            if (parameters.size() != 1) {
                return false;
            }
            final CtTypeReference<?> typeParameter = parameters.get(0).getType();
            final CtTypeReference<CtElement> ctElementRef = element.getFactory().Type().createReference(CtElement.class);
            // isSubtypeOf will return true in case of equality
            boolean isSubtypeof = typeParameter.isSubtypeOf(ctElementRef);
            if (!isSubtypeof) {
                return false;
            }
            return element.getSimpleName().startsWith("set") && element.getDeclaringType().getSimpleName().startsWith("Ct") && element.getBody() != null;
        }
    }
    class CheckNotNullToSetParentMatcher extends CtElementImpl {

        public TemplateParameter<CtVariableAccess<?>> _parameter_access_;

        public void matcher() {
            if (_parameter_access_.S() != null) {
                _parameter_access_.S().setParent(this);
            }
        }

        @Override
        @Local
        public void accept(CtVisitor visitor) {
        }
    }
    final Launcher launcher = new Launcher();
    launcher.setArgs(new String[] { "--output-type", "nooutput" });
    launcher.getEnvironment().setNoClasspath(true);
    // Implementations
    launcher.addInputResource("./src/main/java/spoon/support/reflect/code");
    launcher.addInputResource("./src/main/java/spoon/support/reflect/declaration");
    launcher.addInputResource("./src/main/java/spoon/support/reflect/reference");
    launcher.addInputResource("./src/test/java/" + this.getClass().getCanonicalName().replace(".", "/") + ".java");
    // Needed for #isSubTypeOf method.
    launcher.addInputResource("./src/main/java/spoon/reflect/");
    launcher.buildModel();
    // Template matcher.
    CtClass<CheckNotNullToSetParentMatcher> matcherCtClass = launcher.getFactory().Class().get(CheckNotNullToSetParentMatcher.class);
    CtIf templateRoot = matcherCtClass.getMethod("matcher").getBody().getStatement(0);
    final List<CtMethod<?>> setters = Query.getElements(launcher.getFactory(), new SetterMethodWithoutCollectionsFilter(launcher.getFactory()));
    assertTrue("Number of setters found null", setters.size() > 0);
    for (CtStatement statement : setters.stream().map((Function<CtMethod<?>, CtStatement>) ctMethod -> ctMethod.getBody().getStatement(0)).collect(Collectors.toList())) {
        // First statement should be a condition to protect the setter of the parent.
        assertTrue("Check the method " + statement.getParent(CtMethod.class).getSignature() + " in the declaring class " + statement.getParent(CtType.class).getQualifiedName(), statement instanceof CtIf);
        CtIf ifCondition = (CtIf) statement;
        TemplateMatcher matcher = new TemplateMatcher(templateRoot);
        assertEquals("Check the number of if in method " + statement.getParent(CtMethod.class).getSignature() + " in the declaring class " + statement.getParent(CtType.class).getQualifiedName(), 1, matcher.find(ifCondition).size());
    }
}
Also used : Factory(spoon.reflect.factory.Factory) CtParameter(spoon.reflect.declaration.CtParameter) TypeFilter(spoon.reflect.visitor.filter.TypeFilter) Function(java.util.function.Function) CtStatement(spoon.reflect.code.CtStatement) List(java.util.List) ArrayList(java.util.ArrayList) CtVisitor(spoon.reflect.visitor.CtVisitor) CtElement(spoon.reflect.declaration.CtElement) CtIf(spoon.reflect.code.CtIf) TemplateParameter(spoon.template.TemplateParameter) CtElementImpl(spoon.support.reflect.declaration.CtElementImpl) CtType(spoon.reflect.declaration.CtType) TemplateMatcher(spoon.template.TemplateMatcher) Launcher(spoon.Launcher) CtMethod(spoon.reflect.declaration.CtMethod) Test(org.junit.Test)

Example 20 with CtIf

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

the class ConditionalTest method testBlockInConditionAndLoop.

@Test
public void testBlockInConditionAndLoop() throws Exception {
    final CtType<Foo> aFoo = ModelUtils.buildClass(Foo.class);
    final List<CtIf> conditions = aFoo.getMethod("m3").getElements(new TypeFilter<CtIf>(CtIf.class));
    assertEquals(4, conditions.size());
    for (CtIf condition : conditions) {
        assertTrue(condition.getThenStatement() instanceof CtBlock);
        if (condition.getElseStatement() != null && !(condition.getElseStatement() instanceof CtIf)) {
            assertTrue(condition.getElseStatement() instanceof CtBlock);
        }
    }
}
Also used : CtBlock(spoon.reflect.code.CtBlock) Foo(spoon.test.condition.testclasses.Foo) CtIf(spoon.reflect.code.CtIf) Test(org.junit.Test)

Aggregations

CtIf (spoon.reflect.code.CtIf)29 Test (org.junit.Test)25 CtBlock (spoon.reflect.code.CtBlock)15 CtMethod (spoon.reflect.declaration.CtMethod)14 Factory (spoon.reflect.factory.Factory)13 Launcher (spoon.Launcher)11 CtStatement (spoon.reflect.code.CtStatement)11 TypeFilter (spoon.reflect.visitor.filter.TypeFilter)9 CtElement (spoon.reflect.declaration.CtElement)8 NamedElementFilter (spoon.reflect.visitor.filter.NamedElementFilter)7 CtParameter (spoon.reflect.declaration.CtParameter)6 ArrayList (java.util.ArrayList)5 List (java.util.List)5 CtInvocation (spoon.reflect.code.CtInvocation)5 CtSwitch (spoon.reflect.code.CtSwitch)5 CtClass (spoon.reflect.declaration.CtClass)5 CtBinaryOperator (spoon.reflect.code.CtBinaryOperator)4 CtCodeSnippetStatement (spoon.reflect.code.CtCodeSnippetStatement)4 CtComment (spoon.reflect.code.CtComment)3 CtConstructorCall (spoon.reflect.code.CtConstructorCall)3