@Override public void visitNode(AstNode astNode) { if (skipFile) { return; } logDebug("***** Node: " + astNode); switch ((CxxGrammarImpl) astNode.getType()) { case classSpecifier: visitClassSpecifier(astNode); break; case memberDeclaration: visitMemberDeclaration(astNode); break; case functionDefinition: visitFunctionDefinition(astNode); break; case enumSpecifier: visitEnumSpecifier(astNode); break; case initDeclaratorList: visitDeclaratorList(astNode); break; case aliasDeclaration: visitAliasDeclaration(astNode); break; default: // should not happen LOG.error("Visiting unknown node: {}", astNode.getType()); break; } }
@Test public void should_skip_nodes() { char[] input = "foo".toCharArray(); MutableParsingRule ruleMatcher1 = mockRuleMatcher("rule1"); when(ruleMatcher1.hasToBeSkippedFromAst(Mockito.any(AstNode.class))).thenReturn(true); MutableParsingRule ruleMatcher2 = mockRuleMatcher("rule2"); AstNodeType realAstNodeType = mock(AstNodeType.class); when(ruleMatcher2.getRealAstNodeType()).thenReturn(realAstNodeType); ParseNode node = new ParseNode(0, 3, Collections.<ParseNode>emptyList(), ruleMatcher1); ParseNode parseTreeRoot = new ParseNode(0, 3, ImmutableList.of(node), ruleMatcher2); InputBuffer inputBuffer = new ImmutableInputBuffer(input); ParsingResult parsingResult = new ParsingResult(inputBuffer, true, parseTreeRoot, null); AstNode astNode = AstCreator.create(parsingResult, new LocatedText(null, input)); System.out.println(AstXmlPrinter.print(astNode)); assertThat(astNode.getType()).isSameAs(realAstNodeType); assertThat(astNode.getName()).isEqualTo("rule2"); assertThat(astNode.getFromIndex()).isEqualTo(0); assertThat(astNode.getToIndex()).isEqualTo(3); assertThat(astNode.hasChildren()).isFalse(); assertThat(astNode.getToken()).isNull(); }
@Test public void test_children_when_one_child() { AstNodeType type1 = mock(AstNodeType.class); AstNodeType type2 = mock(AstNodeType.class); AstNode child = mock(AstNode.class); when(node.getNumberOfChildren()).thenReturn(1); when(node.getFirstChild()).thenReturn(child); AstSelect children = select.children(); assertThat((Object) children).isInstanceOf(SingleAstSelect.class); assertThat(children).containsOnly(child); when(node.getChildren()).thenReturn(ImmutableList.of(child)); children = select.children(type1); assertThat((Object) children).isSameAs(AstSelectFactory.empty()); when(child.getType()).thenReturn(type1); children = select.children(type1); assertThat((Object) children).isInstanceOf(SingleAstSelect.class); assertThat(children).containsOnly(child); children = select.children(type1, type2); assertThat((Object) children).isSameAs(AstSelectFactory.empty()); when(child.is(type1, type2)).thenReturn(true); children = select.children(type1, type2); assertThat((Object) children).isInstanceOf(SingleAstSelect.class); assertThat(children).containsOnly(child); }
private static boolean isPublicApiMember(AstNode node) { AstNode access = node; // retrieve the accessSpecifier do { access = access.getPreviousAstNode(); } while (access != null && access.getType() != CxxGrammarImpl.accessSpecifier); if (access != null) { return access.getToken().getType() == CxxKeyword.PUBLIC || access.getToken().getType() == CxxKeyword.PROTECTED; } else { AstNode classSpecifier = node.getFirstAncestor(CxxGrammarImpl.classSpecifier); if (classSpecifier != null) { AstNode enclosingSpecifierNode = classSpecifier.getFirstDescendant(CxxKeyword.STRUCT, CxxKeyword.CLASS, CxxKeyword.ENUM); if (enclosingSpecifierNode != null) { switch ((CxxKeyword) enclosingSpecifierNode.getToken().getType()) { case STRUCT: // struct members have public access, thus access level // is the access level of the enclosing classSpecifier return isPublicApiMember(classSpecifier); case CLASS: // default access in classes is private return false; default: LOG.error( "isPublicApiMember unhandled case: {} at {}", enclosingSpecifierNode.getType(), enclosingSpecifierNode.getTokenLine()); return false; } } else { LOG.error( "isPublicApiMember: failed to get enclosing classSpecifier for node at {}", node.getTokenLine()); return false; } } // global member return true; } }
@Test public void test_filter_by_type() { AstNodeType type = mock(AstNodeType.class); assertThat((Object) select.filter(type)).isSameAs(AstSelectFactory.empty()); when(node.getType()).thenReturn(type); assertThat((Object) select.filter(type)).isSameAs(select); }
/** * Find documentation node, associated documentation, identifier of a <em>public</em> member * declarator and visit it as a public API. * * @param node the <em>public</em> member declarator to visit */ private void visitMemberDeclarator(AstNode node) { AstNode container = node.getFirstAncestor(CxxGrammarImpl.templateDeclaration, CxxGrammarImpl.classSpecifier); if (isOverriddenMethod(node)) { // assume that ancestor method is documented // and do not count as public API return; } AstNode docNode; if (container == null || container.getType() == CxxGrammarImpl.classSpecifier) { docNode = node; } else { docNode = container; } // look for block documentation List<Token> comments = getBlockDocumentation(docNode); // documentation may be inlined if (comments.isEmpty()) { comments = getDeclaratorInlineComment(node); } // find the identifier to present to concrete visitors String id = null; AstNode idNode = null; // first look for an operator function id idNode = node.getFirstDescendant(CxxGrammarImpl.operatorFunctionId); if (idNode != null) { id = getOperatorId(idNode); } else { // look for a declarator id idNode = node.getFirstDescendant(CxxGrammarImpl.declaratorId); if (idNode != null) { id = idNode.getTokenValue(); } else { // look for an identifier (e.g in bitfield declaration) idNode = node.getFirstDescendant(GenericTokenType.IDENTIFIER); if (idNode != null) { id = idNode.getTokenValue(); } else { LOG.error("Unsupported declarator at {}", node.getTokenLine()); } } } if (idNode != null && id != null) { visitPublicApi(idNode, id, comments); } }
@Test public void test_firstAncestor_by_type() { AstNodeType type = mock(AstNodeType.class); assertThat((Object) select.firstAncestor(type)).isSameAs(AstSelectFactory.empty()); AstNode parent = mock(AstNode.class); when(node.getParent()).thenReturn(parent); AstNode ancestor = mock(AstNode.class); when(ancestor.getType()).thenReturn(type); when(parent.getParent()).thenReturn(ancestor); assertThat((Object) select.firstAncestor(type)).isInstanceOf(SingleAstSelect.class); assertThat(select.firstAncestor(type)).containsOnly(ancestor); }
/** This test demonstrates how to use {@link ParserAdapter} to parse and construct AST. */ @Test public void ast() { ParserAdapter<LexerlessGrammar> parser = new ParserAdapter<LexerlessGrammar>(Charsets.UTF_8, b.build()); AstNode rootNode = parser.parse("2 + var"); assertThat(rootNode.getType()).isSameAs(ExpressionGrammar.EXPRESSION); AstNode astNode = rootNode; assertThat(astNode.getNumberOfChildren()).isEqualTo(1); assertThat(astNode.getChild(0).getType()).isSameAs(ExpressionGrammar.ADDITIVE_EXPRESSION); astNode = rootNode.getChild(0); assertThat(astNode.getNumberOfChildren()).isEqualTo(3); assertThat(astNode.getChild(0).getType()).isSameAs(ExpressionGrammar.NUMBER); assertThat(astNode.getChild(1).getType()).isSameAs(ExpressionGrammar.PLUS); assertThat(astNode.getChild(2).getType()).isSameAs(ExpressionGrammar.VARIABLE); }
@Test public void should_create_tokens_and_trivias() { char[] input = "foo bar".toCharArray(); TokenExpression tokenMatcher = mockTokenMatcher(GenericTokenType.IDENTIFIER); TokenExpression triviaMatcher = mockTokenMatcher(GenericTokenType.COMMENT); MutableParsingRule ruleMatcher = mockRuleMatcher("rule"); AstNodeType realAstNodeType = mock(AstNodeType.class); when(ruleMatcher.getRealAstNodeType()).thenReturn(realAstNodeType); ParseNode triviaNode = new ParseNode(0, 4, Collections.<ParseNode>emptyList(), triviaMatcher); ParseNode tokenNode = new ParseNode(4, 7, Collections.<ParseNode>emptyList(), tokenMatcher); ParseNode parseTreeRoot = new ParseNode(0, 7, ImmutableList.of(triviaNode, tokenNode), ruleMatcher); InputBuffer inputBuffer = new ImmutableInputBuffer(input); ParsingResult parsingResult = new ParsingResult(inputBuffer, true, parseTreeRoot, null); AstNode astNode = AstCreator.create(parsingResult, new LocatedText(null, input)); System.out.println(AstXmlPrinter.print(astNode)); assertThat(astNode.getType()).isSameAs(realAstNodeType); assertThat(astNode.getName()).isEqualTo("rule"); assertThat(astNode.getFromIndex()).isEqualTo(0); assertThat(astNode.getToIndex()).isEqualTo(7); assertThat(astNode.hasChildren()).isTrue(); assertThat(astNode.getTokens()).hasSize(1); Token token = astNode.getTokens().get(0); assertThat(astNode.getToken()).isSameAs(token); assertThat(token.getValue()).isEqualTo("bar"); assertThat(token.getOriginalValue()).isEqualTo("bar"); assertThat(token.getLine()).isEqualTo(1); assertThat(token.getColumn()).isEqualTo(4); assertThat(token.getType()).isEqualTo(GenericTokenType.IDENTIFIER); assertThat(token.getTrivia()).hasSize(1); Trivia trivia = token.getTrivia().get(0); Token triviaToken = trivia.getToken(); assertThat(triviaToken.getValue()).isEqualTo("foo "); assertThat(triviaToken.getOriginalValue()).isEqualTo("foo "); assertThat(triviaToken.getLine()).isEqualTo(1); assertThat(triviaToken.getColumn()).isEqualTo(0); assertThat(triviaToken.getType()).isEqualTo(GenericTokenType.COMMENT); }
@Test public void should_create_tokens_without_TokenMatcher() { char[] input = "foobar".toCharArray(); ParseNode firstTerminal = new ParseNode(0, 3, Collections.<ParseNode>emptyList(), null); ParseNode secondTerminal = new ParseNode(3, 6, Collections.<ParseNode>emptyList(), null); MutableParsingRule ruleMatcher = mockRuleMatcher("rule"); AstNodeType realAstNodeType = mock(AstNodeType.class); when(ruleMatcher.getRealAstNodeType()).thenReturn(realAstNodeType); ParseNode parseTreeRoot = new ParseNode(0, 6, ImmutableList.of(firstTerminal, secondTerminal), ruleMatcher); InputBuffer inputBuffer = new ImmutableInputBuffer(input); ParsingResult parsingResult = new ParsingResult(inputBuffer, true, parseTreeRoot, null); AstNode astNode = AstCreator.create(parsingResult, new LocatedText(null, input)); System.out.println(AstXmlPrinter.print(astNode)); assertThat(astNode.getType()).isSameAs(realAstNodeType); assertThat(astNode.getName()).isEqualTo("rule"); assertThat(astNode.getFromIndex()).isEqualTo(0); assertThat(astNode.getToIndex()).isEqualTo(6); assertThat(astNode.hasChildren()).isTrue(); assertThat(astNode.getTokens()).hasSize(2); Token token = astNode.getTokens().get(0); assertThat(astNode.getToken()).isSameAs(token); assertThat(token.getValue()).isEqualTo("foo"); assertThat(token.getOriginalValue()).isEqualTo("foo"); assertThat(token.getLine()).isEqualTo(1); assertThat(token.getColumn()).isEqualTo(0); assertThat(token.getType()).isSameAs(AstCreator.UNDEFINED_TOKEN_TYPE); assertThat(token.getType().getName()).isEqualTo("TOKEN"); token = astNode.getTokens().get(1); assertThat(token.getValue()).isEqualTo("bar"); assertThat(token.getOriginalValue()).isEqualTo("bar"); assertThat(token.getLine()).isEqualTo(1); assertThat(token.getColumn()).isEqualTo(3); assertThat(token.getType()).isSameAs(AstCreator.UNDEFINED_TOKEN_TYPE); }
@Override public boolean apply(AstNode node) { return !node.getType().equals(PythonGrammar.PASS_STMT); }