diff --git a/cxx-squid/src/main/java/org/sonar/cxx/visitors/AbstractCxxPublicApiVisitor.java b/cxx-squid/src/main/java/org/sonar/cxx/visitors/AbstractCxxPublicApiVisitor.java index 4d61391c68..ac3d274357 100644 --- a/cxx-squid/src/main/java/org/sonar/cxx/visitors/AbstractCxxPublicApiVisitor.java +++ b/cxx-squid/src/main/java/org/sonar/cxx/visitors/AbstractCxxPublicApiVisitor.java @@ -204,12 +204,12 @@ private void visitDeclaratorList(AstNode declaratorList) { if (memberDeclaration != null) { return; } - + // ignore classSpefifier typedefs (classSpefifier at classSpefifier) if (isTypedef(declaratorList)) { return; } - + // ignore friend declarations if (isFriendDeclarationList(declaratorList)) { return; @@ -254,7 +254,7 @@ private boolean isTypedef(AstNode declaratorList) { } return false; } - + private boolean isFriendDeclarationList(AstNode declaratorList) { AstNode simpleDeclNode = declaratorList .getFirstAncestor(CxxGrammarImpl.simpleDeclaration); @@ -353,7 +353,7 @@ private AstNode getTypedefNode(AstNode classSpecifier) { } return null; } - + private void visitClassSpecifier(AstNode classSpecifier) { // check if this is a template specification to adjust documentation node @@ -365,7 +365,7 @@ private void visitClassSpecifier(AstNode classSpecifier) { docNode = classSpecifier; } } - + // narrow the identifier search scope to classHead AstNode classHead = classSpecifier .getFirstDescendant(CxxGrammarImpl.classHead); @@ -477,15 +477,18 @@ private boolean isFriendMemberDeclaration(AstNode memberDeclaration) { return false; } - + private void visitTemplateDeclaration(AstNode templateDeclaration) { if (isFriendMemberDeclaration(templateDeclaration.getParent())) { return; } - String id = templateDeclaration.getFirstDescendant(CxxGrammarImpl.className) - .getTokenValue(); + AstNode className = templateDeclaration.getFirstDescendant(CxxGrammarImpl.className); + if (className == null) { + return; + } + String id = className.getTokenValue(); // handle cascaded template declarations AstNode node = templateDeclaration; @@ -498,10 +501,10 @@ private void visitTemplateDeclaration(AstNode templateDeclaration) { } node = node.getFirstAncestor(CxxGrammarImpl.templateDeclaration); } while (node != null); - + visitPublicApi(templateDeclaration, id, comments); } - + private void visitFunctionDefinition(AstNode functionDef) { if (isPublicApiMember(functionDef)) { // filter out deleted and defaulted methods @@ -570,7 +573,7 @@ private void visitMemberDeclarator(AstNode node) { AstNode container = node.getFirstAncestor( CxxGrammarImpl.templateDeclaration, CxxGrammarImpl.classSpecifier); - + AstNode docNode = node; List comments; @@ -629,8 +632,8 @@ private void visitAliasDeclaration(AstNode aliasDeclNode) { CxxGrammarImpl.classSpecifier); // An alias declaration inside a function is not part of the public API - if (parent != null && parent.getType() == CxxGrammarImpl.functionDefinition){ - return; + if (parent != null && parent.getType() == CxxGrammarImpl.functionDefinition) { + return; } if (isPublicApiMember(aliasDeclNode)) { @@ -687,7 +690,7 @@ private void visitEnumSpecifier(AstNode enumSpecifierNode) { if (docNode == null) { docNode = enumSpecifierNode; } - + visitPublicApi( enumSpecifierNode, enumId, getBlockDocumentation(docNode)); @@ -778,7 +781,7 @@ private static List getDeclaratorInlineComment(AstNode declarator) { private static boolean isPublicApiMember(AstNode node) { AstNode access = node; - + // retrieve the accessSpecifier do { access = access.getPreviousAstNode(); @@ -816,9 +819,9 @@ private static boolean isPublicApiMember(AstNode node) { } else { LOG.error("isPublicApiMember: failed to get enclosing classSpecifier for node at {}", node.getTokenLine()); return false; - } + } } - + // method or function outside of class return true; } diff --git a/cxx-squid/src/test/java/org/sonar/cxx/visitors/CxxPublicApiVisitorTest.java b/cxx-squid/src/test/java/org/sonar/cxx/visitors/CxxPublicApiVisitorTest.java index 7efd5f8da8..eba4a30ee0 100644 --- a/cxx-squid/src/test/java/org/sonar/cxx/visitors/CxxPublicApiVisitorTest.java +++ b/cxx-squid/src/test/java/org/sonar/cxx/visitors/CxxPublicApiVisitorTest.java @@ -137,7 +137,7 @@ public void no_doc() throws IOException { @Test public void template() throws IOException { - testFile("src/test/resources/metrics/template.h", 13, 4, false); + testFile("src/test/resources/metrics/template.h", 14, 4, false); } @Test diff --git a/cxx-squid/src/test/resources/metrics/template.h b/cxx-squid/src/test/resources/metrics/template.h index 666e50dcdd..b5b3663b05 100644 --- a/cxx-squid/src/test/resources/metrics/template.h +++ b/cxx-squid/src/test/resources/metrics/template.h @@ -64,3 +64,10 @@ template void TestClass2::functionTest2() { } + +/** + * @brief issue #1067 + */ +struct A { + template class B; +};