Search in sources :

Example 61 with CtElement

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

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

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

the class CommentTest method testDocumentationContract.

@Test
public void testDocumentationContract() throws Exception {
    // contract: all metamodel classes must be commented with an example.
    final Launcher launcher = new Launcher();
    launcher.getEnvironment().setNoClasspath(true);
    launcher.getEnvironment().setCommentEnabled(true);
    // interfaces.
    launcher.addInputResource("./src/main/java/spoon/reflect/");
    launcher.addInputResource("./src/main/java/spoon/support/reflect/");
    launcher.buildModel();
    StringBuffer codeElementsDocumentationPage = new StringBuffer();
    codeElementsDocumentationPage.append(IOUtils.toString(new FileReader("doc/code_elements_header.md")));
    codeElementsDocumentationPage.append("\n\n");
    launcher.getModel().getElements(new TypeFilter<>(CtInterface.class)).stream().forEach(x -> {
        assertTrue(x.getSimpleName() + " has no documentation", x.getDocComment() != null);
        assertTrue(x.getSimpleName() + " has no documentation", x.getDocComment().length() > 0);
        // we only consider instantiable interfaces
        if (launcher.getModel().getElements(new AbstractFilter<CtElement>() {

            @Override
            public boolean matches(CtElement element) {
                return (element instanceof CtNamedElement) && ((CtNamedElement) element).getSimpleName().equals(x.getSimpleName() + "Impl") && (element instanceof CtClass) && !((CtClass) element).hasModifier(ModifierKind.ABSTRACT);
            }
        }).size() == 0) {
            return;
        }
        // we don't consider references
        if (x.getSimpleName().endsWith("Reference")) {
            return;
        }
        if (x.isSubtypeOf(launcher.getFactory().Type().get(CtStatement.class).getReference()) || x.isSubtypeOf(launcher.getFactory().Type().get(CtExpression.class).getReference())) {
            // no meaningful snippet
            if (x.getSimpleName().equals("CtCodeSnippetStatement")) {
                return;
            }
            // no meaningful snippet
            if (x.getSimpleName().equals("CtCodeSnippetExpression")) {
                return;
            }
            // no comment in snippet mode
            if (x.getSimpleName().equals("CtComment")) {
                return;
            }
            // a statement in really rare cases
            if (x.getSimpleName().equals("CtEnum")) {
                return;
            }
            // too hard to snippetize
            if (x.getSimpleName().equals("CtAnnotationFieldAccess")) {
                return;
            }
            codeElementsDocumentationPage.append("### " + x.getSimpleName() + "\n");
            codeElementsDocumentationPage.append("[(javadoc)](http://spoon.gforge.inria.fr/mvnsites/spoon-core/apidocs/" + x.getQualifiedName().replace('.', '/') + ".html)\n\n");
            codeElementsDocumentationPage.append("```java" + "\n");
            Pattern p = Pattern.compile("<pre>(.*?)</pre>", Pattern.CASE_INSENSITIVE | Pattern.DOTALL | Pattern.MULTILINE | Pattern.UNIX_LINES);
            Matcher m = p.matcher(x.getDocComment());
            m.find();
            do {
                String snippet = null;
                try {
                    snippet = m.group(1);
                } catch (IllegalStateException e) {
                    fail(x + " does not have code snippet");
                }
                snippet = StringEscapeUtils.unescapeHtml4(snippet);
                // it must compile
                CtElement el = launcher.getFactory().Code().createCodeSnippetStatement(snippet).compile();
                // the snippet contains this element
                assertTrue(snippet + " does not contain a " + x.getSimpleName(), el.getElements(new TypeFilter<>(x.getActualClass())).size() > 0);
                codeElementsDocumentationPage.append(snippet + "\n");
            } while (m.find());
            codeElementsDocumentationPage.append("```" + "\n");
        }
    });
    try {
        assertEquals("doc outdated, please commit doc/code_elements.md", codeElementsDocumentationPage.toString(), IOUtils.toString(new FileReader("doc/code_elements.md")));
    } finally {
        write(codeElementsDocumentationPage.toString(), new FileOutputStream("doc/code_elements.md"));
    }
}
Also used : CtInterface(spoon.reflect.declaration.CtInterface) Pattern(java.util.regex.Pattern) CtExpression(spoon.reflect.code.CtExpression) Matcher(java.util.regex.Matcher) CtElement(spoon.reflect.declaration.CtElement) TypeFilter(spoon.reflect.visitor.filter.TypeFilter) CtClass(spoon.reflect.declaration.CtClass) CtStatement(spoon.reflect.code.CtStatement) FileOutputStream(java.io.FileOutputStream) Launcher(spoon.Launcher) FileReader(java.io.FileReader) CtNamedElement(spoon.reflect.declaration.CtNamedElement) Test(org.junit.Test)

Example 64 with CtElement

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

the class CommentTest method testInLineComment.

@Test
public void testInLineComment() {
    Factory f = getSpoonFactory();
    CtClass<?> type = (CtClass<?>) f.Type().get(InlineComment.class);
    String strType = type.toString();
    List<CtComment> comments = type.getElements(new TypeFilter<CtComment>(CtComment.class));
    // verify that the number of comment present in the AST is correct
    assertEquals(64, comments.size());
    // verify that all comments present in the AST is printed
    for (CtComment comment : comments) {
        if (comment.getCommentType() == CtComment.CommentType.FILE) {
            // the header of the file is not printed with the toString
            continue;
        }
        assertNotNull(comment.getParent());
        assertTrue(comment.toString() + ":" + comment.getParent() + " is not printed", strType.contains(comment.toString()));
    }
    assertEquals(3, type.getComments().size());
    assertEquals(CtComment.CommentType.FILE, type.getComments().get(0).getCommentType());
    assertEquals(createFakeComment(f, "comment class"), type.getComments().get(1));
    CtField<?> field = type.getField("field");
    assertEquals(3, field.getComments().size());
    assertEquals(createFakeComment(f, "Comment Field"), field.getComments().get(0));
    assertEquals("// Comment Field" + newLine + "// comment field 2" + newLine + "// comment in field" + newLine + "private int field = 10;", field.toString());
    CtAnonymousExecutable ctAnonymousExecutable = type.getAnonymousExecutables().get(0);
    assertEquals(1, ctAnonymousExecutable.getComments().size());
    assertEquals(createFakeComment(f, "comment static block"), ctAnonymousExecutable.getComments().get(0));
    assertEquals(createFakeComment(f, "comment inside static"), ctAnonymousExecutable.getBody().getStatement(0));
    assertEquals("// comment static block" + newLine + "static {" + newLine + "    // comment inside static" + newLine + "}", ctAnonymousExecutable.toString());
    CtConstructor constructor = type.getConstructor();
    assertEquals(1, constructor.getComments().size());
    assertEquals(createFakeComment(f, "comment constructor"), constructor.getComments().get(0));
    // index 0 is the implicit super call
    assertEquals(createFakeComment(f, "Comment in constructor"), constructor.getBody().getStatement(1));
    assertEquals("// comment constructor" + newLine + "public InlineComment() {" + newLine + "    // Comment in constructor" + newLine + "}", constructor.toString());
    CtMethod<Object> m = type.getMethod("m");
    assertEquals(1, m.getComments().size());
    assertEquals(createFakeComment(f, "comment method"), m.getComments().get(0));
    assertEquals(createFakeComment(f, "comment empty method block"), m.getBody().getStatement(0));
    assertEquals("// comment method" + newLine + "public void m() {" + newLine + "    // comment empty method block" + newLine + "}", m.toString());
    CtMethod<Object> m1 = type.getMethod("m1");
    CtSwitch ctSwitch = m1.getBody().getStatement(0);
    assertEquals(createFakeComment(f, "comment switch"), ctSwitch.getComments().get(0));
    assertEquals("// comment switch" + newLine + "switch (1) {" + newLine + "    // before first case" + newLine + "    case 0 :" + newLine + "        // comment case 0: empty case" + newLine + "    case 1 :" + newLine + "        // comment case 1" + newLine + "        int i = 0;" + newLine + "    default :" + newLine + "        // comment default" + newLine + "}", ctSwitch.toString());
    CtFor ctFor = m1.getBody().getStatement(1);
    assertEquals(createFakeComment(f, "comment for"), ctFor.getComments().get(0));
    assertEquals("// comment for" + newLine + "for (int i = 0; i < 10; i++) {" + newLine + "    // comment for block" + newLine + "}", ctFor.toString());
    CtIf ctIf = m1.getBody().getStatement(2);
    assertEquals(createFakeComment(f, "comment if"), ctIf.getComments().get(0));
    assertEquals("// comment if" + newLine + "if ((1 % 2) == 0) {" + newLine + "    // comment unary operator" + newLine + "    (field)++;" + newLine + "}", ctIf.toString());
    CtConstructorCall ctConstructorCall = m1.getBody().getStatement(3);
    assertEquals(createFakeComment(f, "comment constructor call"), ctConstructorCall.getComments().get(0));
    assertEquals("// comment constructor call" + newLine + "new spoon.test.comment.testclasses.InlineComment()", ctConstructorCall.toString());
    CtInvocation ctInvocation = m1.getBody().getStatement(4);
    assertEquals(createFakeComment(f, "comment invocation"), ctInvocation.getComments().get(0));
    assertEquals("// comment invocation" + newLine + "this.m()", ctInvocation.toString());
    CtLocalVariable ctLocalVariable = m1.getBody().getStatement(5);
    assertEquals(createFakeComment(f, "comment local variable"), ctLocalVariable.getComments().get(0));
    assertEquals("// comment local variable" + newLine + "int i = 0", ctLocalVariable.toString());
    CtLocalVariable ctLocalVariable2 = m1.getBody().getStatement(6);
    assertEquals(createFakeComment(f, "comment multi assignments"), ctLocalVariable2.getComments().get(0));
    assertEquals("// comment multi assignments" + newLine + "int j = 2", ctLocalVariable2.toString());
    CtDo ctDo = m1.getBody().getStatement(7);
    assertEquals(createFakeComment(f, "comment dowhile"), ctDo.getComments().get(0));
    assertEquals("// comment dowhile" + newLine + "do {" + newLine + "    // comment in do while" + newLine + "    i++;" + newLine + "    // comment end do while" + newLine + "} while (i < 10 )", ctDo.toString());
    CtTry ctTry = m1.getBody().getStatement(8);
    assertEquals(createFakeComment(f, "comment try"), ctTry.getComments().get(0));
    assertEquals("// comment try" + newLine + "try {" + newLine + "    // comment in try" + newLine + "    i++;" + newLine + "}// between" + newLine + "// try/catch" + newLine + " catch (java.lang.Exception e) {" + newLine + "    // comment in catch" + newLine + "}", ctTry.toString());
    CtSynchronized ctSynchronized = m1.getBody().getStatement(9);
    assertEquals(createFakeComment(f, "comment synchronized"), ctSynchronized.getComments().get(0));
    assertEquals("// comment synchronized" + newLine + "synchronized(this) {" + newLine + "    // comment in synchronized" + newLine + "}", ctSynchronized.toString());
    CtLocalVariable ctLocalVariable1 = m1.getBody().getStatement(10);
    CtConditional ctConditional = (CtConditional) ctLocalVariable1.getDefaultExpression();
    assertEquals(createFakeComment(f, "comment after condition CtConditional"), ctConditional.getCondition().getComments().get(0));
    assertEquals(createFakeComment(f, "comment before then CtConditional"), ctConditional.getThenExpression().getComments().get(0));
    assertEquals(createFakeComment(f, "comment after then CtConditional"), ctConditional.getThenExpression().getComments().get(1));
    assertEquals(createFakeComment(f, "comment before else CtConditional"), ctConditional.getElseExpression().getComments().get(0));
    assertEquals(createFakeComment(f, "comment after else CtConditional"), ctLocalVariable1.getComments().get(0));
    assertEquals("java.lang.Double dou = (i == 1// comment after condition CtConditional" + newLine + ") ? // comment before then CtConditional" + newLine + "null// comment after then CtConditional" + newLine + " : // comment before else CtConditional" + newLine + "new java.lang.Double((j / ((double) (i - 1))))", ctLocalVariable1.toString());
    CtNewArray ctNewArray = (CtNewArray) ((CtLocalVariable) m1.getBody().getStatement(11)).getDefaultExpression();
    assertEquals(createFakeComment(f, "last comment at the end of array"), ctNewArray.getComments().get(0));
    CtElement arrayValue = (CtElement) ctNewArray.getElements().get(0);
    assertEquals(createFakeComment(f, "comment before array value"), arrayValue.getComments().get(0));
    assertEquals(createFakeComment(f, "comment after array value"), arrayValue.getComments().get(1));
    CtLocalVariable ctLocalVariableString = m1.getBody().getStatement(12);
    assertEquals(createFakeComment(f, "comment multi line string"), ((CtBinaryOperator) ((CtBinaryOperator) ctLocalVariableString.getDefaultExpression()).getRightHandOperand()).getLeftHandOperand().getComments().get(0));
    assertEquals("\"\" + (\"\"// comment multi line string" + newLine + " + \"\")", ctLocalVariableString.getDefaultExpression().toString());
    ctLocalVariable1 = m1.getBody().getStatement(13);
    ctConditional = (CtConditional) ctLocalVariable1.getDefaultExpression();
    assertEquals("boolean c = (i == 1) ? // comment before then boolean CtConditional" + newLine + "i == 1// comment after then boolean CtConditional" + newLine + " : i == 2", ctLocalVariable1.toString());
    CtReturn ctReturn = m1.getBody().getStatement(14);
    assertEquals(createFakeComment(f, "comment return"), ctReturn.getComments().get(0));
    assertEquals("// comment return" + newLine + "return", ctReturn.toString());
    CtMethod m2 = type.getMethodsByName("m2").get(0);
    assertEquals(6, m2.getComments().size());
    CtParameter ctParameter = (CtParameter) m2.getParameters().get(0);
    assertEquals(4, ctParameter.getComments().size());
    assertEquals("// comment before type" + newLine + "// comment after parameter" + newLine + "// comment before throws" + newLine + "// comment before exception 1" + newLine + "// comment before exception 2" + newLine + "// comment before block" + newLine + "public void m2(// comment before name" + newLine + "// comment before parameters" + newLine + "// comment before type parameter" + newLine + "// comment before name parameter" + newLine + "int i) throws java.lang.Error, java.lang.Exception {" + newLine + "}", m2.toString());
}
Also used : CtConditional(spoon.reflect.code.CtConditional) CtComment(spoon.reflect.code.CtComment) CtSwitch(spoon.reflect.code.CtSwitch) DefaultCoreFactory(spoon.support.DefaultCoreFactory) Factory(spoon.reflect.factory.Factory) CtParameter(spoon.reflect.declaration.CtParameter) CtTry(spoon.reflect.code.CtTry) CtNewArray(spoon.reflect.code.CtNewArray) CtSynchronized(spoon.reflect.code.CtSynchronized) InlineComment(spoon.test.comment.testclasses.InlineComment) CtInvocation(spoon.reflect.code.CtInvocation) CtReturn(spoon.reflect.code.CtReturn) CtDo(spoon.reflect.code.CtDo) CtFor(spoon.reflect.code.CtFor) CtBinaryOperator(spoon.reflect.code.CtBinaryOperator) CtElement(spoon.reflect.declaration.CtElement) CtLocalVariable(spoon.reflect.code.CtLocalVariable) CtIf(spoon.reflect.code.CtIf) CtConstructor(spoon.reflect.declaration.CtConstructor) CtClass(spoon.reflect.declaration.CtClass) CtConstructorCall(spoon.reflect.code.CtConstructorCall) CtAnonymousExecutable(spoon.reflect.declaration.CtAnonymousExecutable) CtMethod(spoon.reflect.declaration.CtMethod) Test(org.junit.Test)

Example 65 with CtElement

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

the class CtScannerTest method testScan.

@Test
public void testScan() throws Exception {
    // contract: all AST nodes are visisted through method "scan"
    Launcher launcher;
    launcher = new Launcher();
    launcher.getEnvironment().setNoClasspath(true);
    launcher.addInputResource("src/test/resources/noclasspath/draw2d");
    launcher.buildModel();
    class Counter {

        int nEnter = 0;

        int nExit = 0;

        int nObject = 0;

        int nElement = 0;

        Deque<CollectionContext> contexts = new ArrayDeque<>();
    }
    ;
    Counter counter = new Counter();
    launcher.getModel().getRootPackage().accept(new CtScanner() {

        @Override
        public void scan(Object o) {
            counter.nObject++;
            super.scan(o);
        }

        @Override
        public void scan(CtElement o) {
            counter.nElement++;
            super.scan(o);
        }

        @Override
        public void enter(CtElement o) {
            counter.nEnter++;
            super.enter(o);
        }

        @Override
        public void exit(CtElement o) {
            counter.nExit++;
            super.exit(o);
        }
    });
    // interesting, this is never called because of covariance, only CtElement or Collection is called
    assertEquals(0, counter.nObject);
    // this is a coarse-grain check to see if the scanner changes
    // no more exec ref in paramref
    assertEquals(3616, counter.nElement);
    assertEquals(2396, counter.nEnter);
    assertEquals(2396, counter.nExit);
    // contract: all AST nodes which are part of Collection or Map are visited first by method "scan(Collection|Map)" and then by method "scan(CtElement)"
    Counter counter2 = new Counter();
    launcher.getModel().getRootPackage().accept(new CtScanner() {

        @Override
        public void scan(Object o) {
            counter2.nObject++;
            super.scan(o);
        }

        @Override
        public void scan(CtRole role, CtElement o) {
            if (o == null) {
                // there is no collection involved in scanning of this single value NULL attribute
                assertNull(counter2.contexts.peek().col);
            } else {
                RoleHandler rh = RoleHandlerHelper.getRoleHandler(o.getParent().getClass(), role);
                if (rh.getContainerKind() == ContainerKind.SINGLE) {
                    // there is no collection involved in scanning of this single value attribute
                    assertNull(counter2.contexts.peek().col);
                } else {
                    counter2.contexts.peek().assertRemoveSame(o);
                }
            }
            counter2.nElement++;
            super.scan(o);
        }

        @Override
        public void scan(CtRole role, Collection<? extends CtElement> elements) {
            // contract: before processed collection is finished before it starts with next collection
            counter2.contexts.peek().initCollection(elements);
            super.scan(role, elements);
            // contract: all elements of collection are processed in previous super.scan call
            counter2.contexts.peek().assertCollectionIsEmpty();
        }

        @Override
        public void scan(CtRole role, Map<String, ? extends CtElement> elements) {
            // contract: before processed collection is finished before it starts with next collection
            counter2.contexts.peek().initCollection(elements.values());
            super.scan(role, elements);
            // contract: all elements of collection are processed in previous super.scan call
            counter2.contexts.peek().assertCollectionIsEmpty();
        }

        @Override
        public void enter(CtElement o) {
            counter2.nEnter++;
            counter2.contexts.push(new CollectionContext());
        }

        @Override
        public void exit(CtElement o) {
            counter2.nExit++;
            counter2.contexts.peek().assertCollectionIsEmpty();
            counter2.contexts.pop();
        }
    });
    assertEquals(counter.nObject, counter2.nObject);
    assertEquals(counter.nElement, counter2.nElement);
    assertEquals(counter.nEnter, counter2.nEnter);
    assertEquals(counter.nExit, counter2.nExit);
}
Also used : CtElement(spoon.reflect.declaration.CtElement) RoleHandler(spoon.reflect.meta.RoleHandler) Deque(java.util.Deque) ArrayDeque(java.util.ArrayDeque) Launcher(spoon.Launcher) CtRole(spoon.reflect.path.CtRole) Test(org.junit.Test)

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