private void visitSingleDeclarator(AstNode declaration, AstNode declarator) { AstNode docNode; AstNode params = declaration.getFirstDescendant(CxxGrammarImpl.parametersAndQualifiers); // in case of function declaration, // the docNode is set on the declaration node if (params != null) { docNode = declaration; } else { AstNode classSpecifier = declaration.getFirstDescendant(CxxGrammarImpl.classSpecifier); // if a class is specified on the same declaration, // e.g. 'struct {} a;' // the documentation node is set on the declarator if (classSpecifier != null) { docNode = declarator; } else { docNode = declaration; } } visitDeclarator(declarator, docNode); }
/** * 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); } }
private void visitAliasDeclaration(AstNode aliasDeclNode) { if (isPublicApiMember(aliasDeclNode)) { logDebug("AliasDeclaration"); AstNode aliasDeclIdNode = aliasDeclNode.getFirstDescendant(GenericTokenType.IDENTIFIER); if (aliasDeclIdNode == null) { LOG.error("No identifier found at {}", aliasDeclNode.getTokenLine()); } else { // check if this is a template specification to adjust // documentation node AstNode template = aliasDeclNode.getFirstAncestor(CxxGrammarImpl.templateDeclaration); AstNode docNode = (template != null) ? template : aliasDeclNode; // look for block documentation List<Token> comments = getBlockDocumentation(docNode); // documentation may be inlined if (comments.isEmpty()) { comments = getDeclaratorInlineComment(aliasDeclNode); } visitPublicApi(aliasDeclNode, aliasDeclIdNode.getTokenValue(), comments); } } }
private void visitEnumSpecifier(AstNode enumSpecifierNode) { AstNode enumIdNode = enumSpecifierNode.getFirstDescendant(GenericTokenType.IDENTIFIER); String enumId = (enumIdNode == null) ? UNNAMED_ENUM_ID : enumIdNode.getTokenValue(); if (!isPublicApiMember(enumSpecifierNode)) { logDebug(enumId + " not in public API"); return; } visitPublicApi(enumSpecifierNode, enumId, getBlockDocumentation(enumSpecifierNode)); // deal with enumeration values AstNode enumeratorList = enumSpecifierNode.getFirstDescendant(CxxGrammarImpl.enumeratorList); if (enumeratorList != null) { for (AstNode definition : enumeratorList.getChildren(CxxGrammarImpl.enumeratorDefinition)) { // look for block documentation List<Token> comments = getBlockDocumentation(definition); // look for inlined doc if (comments.isEmpty()) { AstNode next = definition.getNextAstNode(); // inline documentation may be on the next definition token // or next curly brace if (next != null) { // discard COMMA if (next.getToken().getType() == CxxPunctuator.COMMA) { next = next.getNextAstNode(); } comments = getInlineDocumentation(next.getToken(), definition.getTokenLine()); } } visitPublicApi( definition, definition.getFirstDescendant(GenericTokenType.IDENTIFIER).getTokenValue(), comments); } } }
/** * It is responsible for verifying whether the rule is met in the rule base. In the event that the * rule is not correct, create message error. * * @param astNode It is the node that stores all the rules. */ @Override public void visitNode(AstNode astNode) { try { String methodName = astNode.getFirstDescendant(ApexGrammarRuleKey.METHOD_IDENTIFIER).getTokenOriginalValue(); if (!pattern.matcher(methodName).matches()) { getContext().createLineViolation(this, MESSAGE, astNode, methodName, format); } } catch (Exception e) { ChecksLogger.logCheckError(this.toString(), "visitNode", e.toString()); } }
private void visitMemberDeclaration(AstNode memberDeclaration) { AstNode declaratorList = memberDeclaration.getFirstDescendant(CxxGrammarImpl.memberDeclaratorList); if (!isPublicApiMember(memberDeclaration)) { // if not part of the API, nothing to measure return; } AstNode subclassSpecifier = memberDeclaration.getFirstDescendant(CxxGrammarImpl.classSpecifier); if (subclassSpecifier != null) { // sub classes are handled by subscription return; } AstNode functionDef = memberDeclaration.getFirstDescendant(CxxGrammarImpl.functionDefinition); if (functionDef != null) { // functionDef are handled by subscription return; } if (declaratorList != null) { List<AstNode> declarators = declaratorList.getChildren(CxxGrammarImpl.memberDeclarator); // if only one declarator, the doc should be placed before the // memberDeclaration, or inlined if (declarators.size() == 1) { visitMemberDeclarator(memberDeclaration); } // if several declarators, doc should be placed before each // declarator, or inlined else { for (AstNode declarator : declarators) { visitMemberDeclarator(declarator); } } } }
private void visitClassSpecifier(AstNode classSpecifier) { // check if this is a template specification to adjust // documentation node AstNode template = classSpecifier.getFirstAncestor(CxxGrammarImpl.templateDeclaration); AstNode docNode = (template != null) ? template : classSpecifier; // narrow the identifier search scope to classHead AstNode classHead = classSpecifier.getFirstDescendant(CxxGrammarImpl.classHead); if (classHead == null) { LOG.warn( "classSpecifier does not embed a classHead at line " + classSpecifier.getTokenLine()); return; } // look for the specifier id AstNode id = classHead.getFirstDescendant(CxxGrammarImpl.className); AstNode idNode; String idName; // check if this is an unnamed specifier if (id == null) { idNode = classSpecifier; idName = UNNAMED_CLASSIFIER_ID; } else { idNode = id; idName = id.getTokenValue(); } if (!isPublicApiMember(classSpecifier)) { logDebug(idName + " not in public API"); } else { visitPublicApi(idNode, idName, getBlockDocumentation(docNode)); } }
// XXX may go to a utility class private String getOperatorId(AstNode operatorFunctionId) { StringBuilder builder = new StringBuilder(operatorFunctionId.getTokenValue()); AstNode operator = operatorFunctionId.getFirstDescendant(CxxGrammarImpl.operator); if (operator != null) { AstNode opNode = operator.getFirstChild(); while (opNode != null) { builder.append(opNode.getTokenValue()); opNode = opNode.getNextSibling(); } } return builder.toString(); }
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; } }
private void visitDeclarator(AstNode declarator, AstNode docNode) { // look for block documentation List<Token> comments = getBlockDocumentation(docNode); // documentation may be inlined if (comments.isEmpty()) { comments = getDeclaratorInlineComment(docNode); } AstNode declaratorId = declarator.getFirstDescendant(CxxGrammarImpl.declaratorId); if (declaratorId == null) { LOG.error("null declaratorId: {}", AstXmlPrinter.print(declarator)); } else { visitPublicApi(declaratorId, declaratorId.getTokenValue(), comments); } }
private static boolean hasSuperReferenceReturnedExpression(AstNode node) { AstNode returnStatement = node.getFirstDescendant(JavaGrammar.RETURN_STATEMENT); AstNode expression = returnStatement.getFirstChild(JavaGrammar.EXPRESSION); return expression != null && isSuperReference(expression); }