/** * Checks whether the current node should be processed by the check. * @param curNode current node. * @return true if the current node should be processed by the check. */ private boolean shouldBeProcessed(DetailNode curNode) { return javadocTokens.contains(curNode.getType()); }
/** * Returns nearest node. * @param node DetailNode node. * @return nearest node. */ private static DetailNode getNearestNode(DetailNode node) { DetailNode tag = JavadocUtil.getNextSibling(node); while (tag.getType() == JavadocTokenTypes.LEADING_ASTERISK || tag.getType() == JavadocTokenTypes.NEWLINE) { tag = JavadocUtil.getNextSibling(tag); } return tag; }
@Override public void visitJavadocToken(DetailNode ast) { if (ast.getType() == JavadocTokenTypes.NEWLINE && isEmptyLine(ast)) { checkEmptyLine(ast); } else if (ast.getType() == JavadocTokenTypes.HTML_ELEMENT && JavadocUtil.getFirstChild(ast).getType() == JavadocTokenTypes.P_TAG_START) { checkParagraphTag(ast); } }
/** * Tests whether the paragraph tag is immediately followed by the text. * @param tag html tag. * @return true, if the paragraph tag is immediately followed by the text. */ private static boolean isImmediatelyFollowedByText(DetailNode tag) { final DetailNode nextSibling = JavadocUtil.getNextSibling(tag); return nextSibling.getType() == JavadocTokenTypes.NEWLINE || nextSibling.getType() == JavadocTokenTypes.EOF || CommonUtil.startsWithChar(nextSibling.getText(), ' '); }
/** * Determines whether or not the line with paragraph tag is first line in javadoc. * @param paragraphTag paragraph tag. * @return true, if line with paragraph tag is first line in javadoc. */ private static boolean isFirstParagraph(DetailNode paragraphTag) { boolean result = true; DetailNode previousNode = JavadocUtil.getPreviousSibling(paragraphTag); while (previousNode != null) { if (previousNode.getType() == JavadocTokenTypes.TEXT && !CommonUtil.isBlank(previousNode.getText()) || previousNode.getType() != JavadocTokenTypes.LEADING_ASTERISK && previousNode.getType() != JavadocTokenTypes.NEWLINE && previousNode.getType() != JavadocTokenTypes.TEXT) { result = false; break; } previousNode = JavadocUtil.getPreviousSibling(previousNode); } return result; }
/** * Concatenates string within text of html tags. * @param result javadoc string * @param detailNode javadoc tag node * @return java doc tag content appended in result */ private static String getStringInsideTag(String result, DetailNode detailNode) { final StringBuilder contents = new StringBuilder(result); DetailNode tempNode = detailNode; while (tempNode != null) { if (tempNode.getType() == JavadocTokenTypes.TEXT) { contents.append(tempNode.getText()); } tempNode = JavadocUtil.getNextSibling(tempNode); } return contents.toString(); }
/** * Gets next sibling of specified node with the specified type. * * @param node DetailNode * @param tokenType javadoc token type * @return next sibling. */ public static DetailNode getNextSibling(DetailNode node, int tokenType) { DetailNode nextSibling = getNextSibling(node); while (nextSibling != null && nextSibling.getType() != tokenType) { nextSibling = getNextSibling(nextSibling); } return nextSibling; }
/** * Finds and collects all NEWLINE nodes inside DESCRIPTION node. * @param descriptionNode DESCRIPTION node. * @return List with NEWLINE nodes. */ private static List<DetailNode> getAllNewlineNodes(DetailNode descriptionNode) { final List<DetailNode> textNodes = new ArrayList<>(); DetailNode node = JavadocUtil.getFirstChild(descriptionNode); while (JavadocUtil.getNextSibling(node) != null) { if (node.getType() == JavadocTokenTypes.NEWLINE) { textNodes.add(node); } node = JavadocUtil.getNextSibling(node); } return textNodes; }
/** * Determines whether or not the line is empty line. * @param newLine NEWLINE node. * @return true, if line is empty line. */ private static boolean isEmptyLine(DetailNode newLine) { boolean result = false; DetailNode previousSibling = JavadocUtil.getPreviousSibling(newLine); if (previousSibling != null && previousSibling.getParent().getType() == JavadocTokenTypes.JAVADOC) { if (previousSibling.getType() == JavadocTokenTypes.TEXT && CommonUtil.isBlank(previousSibling.getText())) { previousSibling = JavadocUtil.getPreviousSibling(previousSibling); } result = previousSibling != null && previousSibling.getType() == JavadocTokenTypes.LEADING_ASTERISK; } return result; }
/** * Checks, if description node is a description of in-line tag. * @param description DESCRIPTION node. * @return true, if description node is a description of in-line tag. */ private static boolean isInlineDescription(DetailNode description) { boolean isInline = false; DetailNode inlineTag = description.getParent(); while (inlineTag != null) { if (inlineTag.getType() == JavadocTokenTypes.JAVADOC_INLINE_TAG) { isInline = true; break; } inlineTag = inlineTag.getParent(); } return isInline; }
/** * Returns the first child token that has a specified type. * @param detailNode * Javadoc AST node * @param type * the token type to match * @return the matching token, or null if no match */ public static DetailNode findFirstToken(DetailNode detailNode, int type) { DetailNode returnValue = null; DetailNode node = getFirstChild(detailNode); while (node != null) { if (node.getType() == type) { returnValue = node; break; } node = getNextSibling(node); } return returnValue; }
/** * Concatenates the HTML text from AST of a JavadocTokenTypes.HTML_ELEMENT. * @param builder to append * @param node to format */ private static void formatHtmlElement(StringBuilder builder, DetailNode node) { switch (node.getType()) { case JavadocTokenTypes.START: case JavadocTokenTypes.HTML_TAG_NAME: case JavadocTokenTypes.END: case JavadocTokenTypes.TEXT: case JavadocTokenTypes.SLASH: builder.append(node.getText()); break; default: for (DetailNode child : node.getChildren()) { formatHtmlElement(builder, child); } break; } }
/** * Finds and returns nearest empty line in javadoc. * @param node DetailNode node. * @return Some nearest empty line in javadoc. */ private static DetailNode getNearestEmptyLine(DetailNode node) { DetailNode newLine = JavadocUtil.getPreviousSibling(node); while (newLine != null) { final DetailNode previousSibling = JavadocUtil.getPreviousSibling(newLine); if (newLine.getType() == JavadocTokenTypes.NEWLINE && isEmptyLine(newLine)) { break; } newLine = previousSibling; } return newLine; }
@Override public void visitJavadocToken(DetailNode ast) { if (!isInlineDescription(ast)) { final List<DetailNode> textNodes = getAllNewlineNodes(ast); for (DetailNode newlineNode : textNodes) { final DetailNode textNode = JavadocUtil.getNextSibling(JavadocUtil .getNextSibling(newlineNode)); if (textNode != null && textNode.getType() == JavadocTokenTypes.TEXT) { final String text = textNode.getText(); if (!CommonUtil.isBlank(text.trim()) && (text.length() <= offset || !text.substring(1, offset + 1).trim().isEmpty())) { log(textNode.getLineNumber(), MSG_KEY, offset); } } } } }
/** * Checks order of atclauses in tag section node. * @param javadoc Javadoc root node. */ private void checkOrderInTagSection(DetailNode javadoc) { int maxIndexOfPreviousTag = 0; for (DetailNode node : javadoc.getChildren()) { if (node.getType() == JavadocTokenTypes.JAVADOC_TAG) { final String tagText = JavadocUtil.getFirstChild(node).getText(); final int indexOfCurrentTag = tagOrder.indexOf(tagText); if (indexOfCurrentTag != -1) { if (indexOfCurrentTag < maxIndexOfPreviousTag) { log(node.getLineNumber(), MSG_KEY, tagOrder.toString()); } else { maxIndexOfPreviousTag = indexOfCurrentTag; } } } } }
/** * Determines whether or not the next line after empty line has paragraph tag in the beginning. * @param newline NEWLINE node. */ private void checkEmptyLine(DetailNode newline) { final DetailNode nearestToken = getNearestNode(newline); if (nearestToken.getType() == JavadocTokenTypes.TEXT && !CommonUtil.isBlank(nearestToken.getText())) { log(newline.getLineNumber(), MSG_TAG_AFTER); } }
/** * Gets tag name from javadocTagSection. * * @param javadocTagSection to get tag name from. * @return name, of the javadocTagSection's tag. */ public static String getTagName(DetailNode javadocTagSection) { final String javadocTagName; if (javadocTagSection.getType() == JavadocTokenTypes.JAVADOC_INLINE_TAG) { javadocTagName = getNextSibling( getFirstChild(javadocTagSection)).getText(); } else { javadocTagName = getFirstChild(javadocTagSection).getText(); } return javadocTagName; }
@Test public void testJavadocChild() { final DetailAST commentContentNode = tree.getFirstChild().getNextSibling().getFirstChild(); final ParseTreeTablePresentation parseTree = new ParseTreeTablePresentation(null); parseTree.setParseMode(ParseMode.JAVA_WITH_JAVADOC_AND_COMMENTS); final Object javadoc = parseTree.getChild(commentContentNode, 0); Assert.assertTrue("Invalid child type", javadoc instanceof DetailNode); Assert.assertEquals("Invalid child token type", JavadocTokenTypes.JAVADOC, ((DetailNode) javadoc).getType()); final Object javadocChild = parseTree.getChild(javadoc, 2); Assert.assertTrue("Invalid child type", javadocChild instanceof DetailNode); Assert.assertEquals("Invalid child token type", JavadocTokenTypes.TEXT, ((DetailNode) javadocChild).getType()); }
@Test public void testJavadocCommentChild() { final DetailAST commentContentNode = tree.getFirstChild().getNextSibling().getFirstChild(); final ParseTreeTablePresentation parseTree = new ParseTreeTablePresentation(null); parseTree.setParseMode(ParseMode.JAVA_WITH_JAVADOC_AND_COMMENTS); final Object child = parseTree.getChild(commentContentNode, 0); Assert.assertTrue("Invalid child type", child instanceof DetailNode); Assert.assertEquals("Invalid child token type", JavadocTokenTypes.JAVADOC, ((DetailNode) child).getType()); // get Child one more time to test cache of PModel final Object childSame = parseTree.getChild(commentContentNode, 0); Assert.assertTrue("Invalid child type", childSame instanceof DetailNode); Assert.assertEquals("Invalid child token type", JavadocTokenTypes.JAVADOC, ((DetailNode) childSame).getType()); }
@Test public void testJavadocChildCount() { final DetailAST commentContentNode = tree.getFirstChild().getNextSibling().getFirstChild(); final ParseTreeTablePresentation parseTree = new ParseTreeTablePresentation(null); parseTree.setParseMode(ParseMode.JAVA_WITH_JAVADOC_AND_COMMENTS); final Object javadoc = parseTree.getChild(commentContentNode, 0); Assert.assertTrue("Invalid child type", javadoc instanceof DetailNode); Assert.assertEquals("Invalid child token type", JavadocTokenTypes.JAVADOC, ((DetailNode) javadoc).getType()); final int javadocChildCount = parseTree.getChildCount(javadoc); Assert.assertEquals("Invalid child count", 5, javadocChildCount); }