Search in sources :

Example 1 with IntercessionScanner

use of spoon.test.intercession.IntercessionScanner 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)

Aggregations

List (java.util.List)1 Ignore (org.junit.Ignore)1 Test (org.junit.Test)1 Launcher (spoon.Launcher)1 CtBinaryOperator (spoon.reflect.code.CtBinaryOperator)1 CtIf (spoon.reflect.code.CtIf)1 CtInvocation (spoon.reflect.code.CtInvocation)1 CtLiteral (spoon.reflect.code.CtLiteral)1 CtStatement (spoon.reflect.code.CtStatement)1 CtStatementList (spoon.reflect.code.CtStatementList)1 ParentNotInitializedException (spoon.reflect.declaration.ParentNotInitializedException)1 Factory (spoon.reflect.factory.Factory)1 CtArrayTypeReference (spoon.reflect.reference.CtArrayTypeReference)1 CtTypeReference (spoon.reflect.reference.CtTypeReference)1 ReferenceTypeFilter (spoon.reflect.visitor.filter.ReferenceTypeFilter)1 TypeFilter (spoon.reflect.visitor.filter.TypeFilter)1 IntercessionScanner (spoon.test.intercession.IntercessionScanner)1