/** * Checks if the node starts with an {@inheritDoc}. * @param root The root node to examine. * @return {@code true} if the javadoc starts with an {@inheritDoc}. */ private static boolean startsWithInheritDoc(DetailNode root) { boolean found = false; final DetailNode[] children = root.getChildren(); for (int i = 0; !found; i++) { final DetailNode child = children[i]; if (child.getType() == JavadocTokenTypes.JAVADOC_INLINE_TAG && child.getChildren()[1].getType() == JavadocTokenTypes.INHERIT_DOC_LITERAL) { found = true; } else if (child.getType() != JavadocTokenTypes.LEADING_ASTERISK && !CommonUtil.isBlank(child.getText())) { break; } } return found; }
/** * Gets a value for DetailNode object. * @param node DetailNode(Javadoc) node. * @param column column index. * @return value at specified column. */ private static Object getValueAtDetailNode(DetailNode node, int column) { final Object value; switch (column) { case 0: // first column is tree model. no value needed value = null; break; case 1: value = JavadocUtil.getTokenName(node.getType()); break; case 2: value = node.getLineNumber(); break; case 3: value = node.getColumnNumber(); break; case 4: value = node.getText(); break; default: throw new IllegalStateException(UNKNOWN_COLUMN_MSG); } return value; }
/** * Gets previous sibling of specified node. * @param node DetailNode * @return previous sibling */ public static DetailNode getPreviousSibling(DetailNode node) { DetailNode previousSibling = null; final int previousSiblingIndex = node.getIndex() - 1; if (previousSiblingIndex >= 0) { final DetailNode parent = node.getParent(); final DetailNode[] children = parent.getChildren(); previousSibling = children[previousSiblingIndex]; } return previousSibling; }
/** * 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; }
/** * Finds the last position of node without children. * @param detailNode DetailNode node. * @return Last position of node without children. */ private int findLastPosition(final DetailNode detailNode) { final int lastPosition; if (detailNode.getChildren().length == 0) { lastPosition = lines2position.get(detailNode.getLineNumber()) + detailNode.getColumnNumber() + detailNode.getText().length(); } else { final DetailNode lastChild = detailNode.getChildren()[detailNode.getChildren().length - 1]; lastPosition = findLastPosition(lastChild); } return lastPosition; }
/** * 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); } }
/** * 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(), ' '); }
/** * 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; } } } } }
/** * Adjust first line nodes to javadoc indent. * @param tree DetailNode tree root * @param javadocColumnNumber javadoc indent */ private void adjustFirstLineToJavadocIndent(DetailNode tree, int javadocColumnNumber) { if (tree.getLineNumber() == blockCommentLineNumber) { ((JavadocNodeImpl) tree).setColumnNumber(tree.getColumnNumber() + javadocColumnNumber); final DetailNode[] children = tree.getChildren(); for (DetailNode child : children) { adjustFirstLineToJavadocIndent(child, javadocColumnNumber); } } }
/** * 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()); }
/** * Find start and end selection positions from DetailNode line and Column. * @param detailNode DetailNode node for which selection finds */ private void findSelectionPositions(DetailNode detailNode) { selectionStart = lines2position.get(detailNode.getLineNumber()) + detailNode.getColumnNumber(); selectionEnd = findLastPosition(detailNode); }
@Override public void visitJavadocToken(DetailNode ast) { if (isEmptyTag(ast.getParent())) { log(ast.getLineNumber(), MSG_KEY, ast.getText()); } }
/** * 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; }
/** * Finds and returns first sentence. * @param ast Javadoc root node. * @return first sentence. */ private static String getFirstSentence(DetailNode ast) { final StringBuilder result = new StringBuilder(256); final String periodSuffix = PERIOD + ' '; for (DetailNode child : ast.getChildren()) { final String text; if (child.getChildren().length == 0) { text = child.getText(); } else { text = getFirstSentence(child); } if (text.contains(periodSuffix)) { result.append(text, 0, text.indexOf(periodSuffix) + 1); break; } else { result.append(text); } } return result.toString(); }
/** * Gets first child node of specified node. * * @param node DetailNode * @return first child */ public static DetailNode getFirstChild(DetailNode node) { DetailNode resultNode = null; if (node.getChildren().length > 0) { resultNode = node.getChildren()[0]; } return resultNode; }
/** * Determines whether or not the line with paragraph tag has previous empty line. * @param tag html tag. */ private void checkParagraphTag(DetailNode tag) { final DetailNode newLine = getNearestEmptyLine(tag); if (isFirstParagraph(tag)) { log(tag.getLineNumber(), MSG_REDUNDANT_PARAGRAPH); } else if (newLine == null || tag.getLineNumber() - newLine.getLineNumber() != 1) { log(tag.getLineNumber(), MSG_LINE_BEFORE); } if (allowNewlineParagraph && isImmediatelyFollowedByText(tag)) { log(tag.getLineNumber(), MSG_MISPLACED_TAG); } }
@Override public void visitJavadocToken(DetailNode ast) { assertEquals(ast.toString(), "JAVADOC", ast.getText()); final DetailNode text = JavadocUtil.findFirstToken(ast, JavadocTokenTypes.TEXT); Assert.assertNotNull("Empty javadoc text at " + ast, text); assertEquals(ast.toString(), "Javadoc", text.getText()); javadocsNumber++; }
@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); } } } } }
/** * 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(); }