diff options
author | Piyush Sharma <ps26oct@gmail.com> | 2017-07-13 15:50:03 +0530 |
---|---|---|
committer | Roman Ivanov <romani@users.noreply.github.com> | 2017-09-08 05:40:02 -0700 |
commit | 3660e750a3835eaeffec0f5451bee7a5189d0e0f (patch) | |
tree | f77ec014d54d9c865a79e06e5dec462e85fc8939 | |
parent | c31bffe59c342dd5fdcfc8f55ca339b3520eef3e (diff) | |
download | checkstyle-3660e750a3835eaeffec0f5451bee7a5189d0e0f.tar.gz |
Issue #3311: Modified javadoc grammar, JavadocDetailNodeParser, AbstractJavadocCheck to enable selective processing of javadoc with non tight HTML
8 files changed, 866 insertions, 273 deletions
@@ -1577,13 +1577,13 @@ </regex> <regex> <pattern>com.puppycrawl.tools.checkstyle.grammars.javadoc.JavadocParser</pattern> - <branchRate>37</branchRate> - <lineRate>48</lineRate> + <branchRate>42</branchRate> + <lineRate>53</lineRate> </regex> <regex> <pattern>com.puppycrawl.tools.checkstyle.grammars.javadoc.JavadocLexer</pattern> - <branchRate>63</branchRate> - <lineRate>83</lineRate> + <branchRate>64</branchRate> + <lineRate>84</lineRate> </regex> </regexes> </check> diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/JavadocDetailNodeParser.java b/src/main/java/com/puppycrawl/tools/checkstyle/JavadocDetailNodeParser.java index 8ba390496..d5df6e786 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/JavadocDetailNodeParser.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/JavadocDetailNodeParser.java @@ -27,6 +27,7 @@ import org.antlr.v4.runtime.ANTLRInputStream; import org.antlr.v4.runtime.BailErrorStrategy; import org.antlr.v4.runtime.BaseErrorListener; import org.antlr.v4.runtime.BufferedTokenStream; +import org.antlr.v4.runtime.CommonToken; import org.antlr.v4.runtime.CommonTokenStream; import org.antlr.v4.runtime.FailedPredicateException; import org.antlr.v4.runtime.InputMismatchException; @@ -82,6 +83,11 @@ public class JavadocDetailNodeParser { */ public static final String MSG_KEY_PARSE_ERROR = "javadoc.parse.error"; + /** + * Message property key for the Unclosed HTML message. + */ + public static final String MSG_UNCLOSED_HTML_TAG = "javadoc.unclosedHtml"; + /** Symbols with which javadoc starts. */ private static final String JAVADOC_START = "/**"; @@ -119,14 +125,17 @@ public class JavadocDetailNodeParser { final ParseStatus result = new ParseStatus(); try { - final ParseTree parseTree = parseJavadocAsParseTree(javadocComment); + final JavadocParser javadocParser = createJavadocParser(javadocComment); + + final ParseTree javadocParseTree = javadocParser.javadoc(); - final DetailNode tree = convertParseTreeToDetailNode(parseTree); + final DetailNode tree = convertParseTreeToDetailNode(javadocParseTree); // adjust first line to indent of /** adjustFirstLineToJavadocIndent(tree, javadocCommentAst.getColumnNo() + JAVADOC_START.length()); result.setTree(tree); + result.firstNonTightHtmlTag = getFirstNonTightHtmlTag(javadocParser); } catch (ParseCancellationException | IllegalArgumentException ex) { ParseErrorMessage parseErrorMessage = null; @@ -164,7 +173,7 @@ public class JavadocDetailNodeParser { * @return parse tree * @noinspection deprecation */ - private ParseTree parseJavadocAsParseTree(String blockComment) { + private JavadocParser createJavadocParser(String blockComment) { final ANTLRInputStream input = new ANTLRInputStream(blockComment); final JavadocLexer lexer = new JavadocLexer(input); @@ -179,11 +188,11 @@ public class JavadocDetailNodeParser { // add custom error listener that logs syntax errors parser.addErrorListener(errorListener); - // This strategy stops parsing when parser error occurs. - // By default it uses Error Recover Strategy which is slow and useless. + // JavadocParserErrorStrategy stops parsing on first parse error encountered unlike the + // DefaultErrorStrategy used by ANTLR which rather attempts error recovery. parser.setErrorHandler(new JavadocParserErrorStrategy()); - return parser.javadoc(); + return parser; } /** @@ -503,6 +512,31 @@ public class JavadocDetailNodeParser { } /** + * This method is used to get the first non-tight HTML tag encountered while parsing javadoc. + * This shall eventually be reflected by the {@link ParseStatus} object returned by + * {@link #parseJavadocAsDetailNode(DetailAST)} method via the instance member + * {@link ParseStatus#firstNonTightHtmlTag}, and checks not supposed to process non-tight HTML + * or the ones which are supposed to log violation for non-tight javadocs can utilize that. + * + * @param javadocParser The ANTLR recognizer instance which has been used to parse the javadoc + * @return First non-tight HTML tag if one exists; null otherwise + */ + private Token getFirstNonTightHtmlTag(JavadocParser javadocParser) { + final CommonToken offendingToken; + final ParserRuleContext nonTightTagStartContext = javadocParser.nonTightTagStartContext; + if (nonTightTagStartContext == null) { + offendingToken = null; + } + else { + final Token token = ((TerminalNode) nonTightTagStartContext.getChild(1)) + .getSymbol(); + offendingToken = new CommonToken(token); + offendingToken.setLine(offendingToken.getLine() + errorListener.offset); + } + return offendingToken; + } + + /** * Custom error listener for JavadocParser that prints user readable errors. */ private static class DescriptiveErrorListener extends BaseErrorListener { @@ -590,6 +624,15 @@ public class JavadocDetailNodeParser { private ParseErrorMessage parseErrorMessage; /** + * Stores the first non-tight HTML tag encountered while parsing javadoc. + * + * @see <a + * href="http://checkstyle.sourceforge.net/writingjavadocchecks.html#Tight-HTML_rules"> + * Tight HTML rules</a> + */ + private Token firstNonTightHtmlTag; + + /** * Getter for DetailNode tree. * @return DetailNode tree if parsing was successful, null otherwise. */ @@ -621,6 +664,28 @@ public class JavadocDetailNodeParser { this.parseErrorMessage = parseErrorMessage; } + /** + * This method is used to check if the javadoc parsed has non-tight HTML tags. + * + * @return returns true if the javadoc has at least one non-tight HTML tag; false otherwise + * @see <a + * href="http://checkstyle.sourceforge.net/writingjavadocchecks.html#Tight-HTML_rules"> + * Tight HTML rules</a> + */ + public boolean isNonTight() { + return firstNonTightHtmlTag != null; + } + + /** + * Getter for {@link #firstNonTightHtmlTag}. + * + * @return the first non-tight HTML tag that is encountered while parsing Javadoc, + * if one exists + */ + public Token getFirstNonTightHtmlTag() { + return firstNonTightHtmlTag; + } + } /** @@ -681,6 +746,10 @@ public class JavadocDetailNodeParser { } /** + * The DefaultErrorStrategy used by ANTLR attempts to recover from parse errors + * which might result in a performance overhead. Also, a parse error indicate + * that javadoc doesn't follow checkstyle Javadoc grammar and the user should be made aware + * of it. * <a href="http://www.antlr.org/api/Java/org/antlr/v4/runtime/BailErrorStrategy.html"> * BailErrorStrategy</a> is used to make ANTLR generated parser bail out on the first error * in parser and not attempt any recovery methods but it doesn't report error to the diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/checks/javadoc/AbstractJavadocCheck.java b/src/main/java/com/puppycrawl/tools/checkstyle/checks/javadoc/AbstractJavadocCheck.java index bf87d3503..4e9575ca3 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/checks/javadoc/AbstractJavadocCheck.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/checks/javadoc/AbstractJavadocCheck.java @@ -88,6 +88,19 @@ public abstract class AbstractJavadocCheck extends AbstractCheck { private final Set<Integer> javadocTokens = new HashSet<>(); /** + * This property determines if a check should log a violation upon encountering javadoc with + * non-tight html. The default return value for this method is set to false since checks + * generally tend to be fine with non tight html. It can be set through config file if a check + * is to log violation upon encountering non-tight HTML in javadoc. + * + * @see ParseStatus#firstNonTightHtmlTag + * @see ParseStatus#isNonTight() + * @see <a href="http://checkstyle.sourceforge.net/writingjavadocchecks.html#Tight-HTML_rules"> + * Tight HTML rules</a> + */ + private boolean violateExecutionOnNonTightHtml; + + /** * Returns the default javadoc token types a check is interested in. * @return the default javadoc token types * @see JavadocTokenTypes @@ -126,6 +139,31 @@ public abstract class AbstractJavadocCheck extends AbstractCheck { } /** + * This method determines if a check should process javadoc containing non-tight html tags. + * This method must be overridden in checks extending {@code AbstractJavadocCheck} which + * are not supposed to process javadoc containing non-tight html tags. + * + * @return true if the check should or can process javadoc containing non-tight html tags; + * false otherwise + * @see ParseStatus#isNonTight() + * @see <a href="http://checkstyle.sourceforge.net/writingjavadocchecks.html#Tight-HTML_rules"> + * Tight HTML rules</a> + */ + public boolean acceptJavadocWithNonTightHtml() { + return true; + } + + /** + * Setter for {@link #violateExecutionOnNonTightHtml}. + * @param shouldReportViolation value to which the field shall be set to + * @see <a href="http://checkstyle.sourceforge.net/writingjavadocchecks.html#Tight-HTML_rules"> + * Tight HTML rules</a> + */ + public final void setViolateExecutionOnNonTightHtml(boolean shouldReportViolation) { + violateExecutionOnNonTightHtml = shouldReportViolation; + } + + /** * Adds a set of tokens the check is interested in. * @param strRep the string representation of the tokens interested in */ @@ -261,12 +299,21 @@ public abstract class AbstractJavadocCheck extends AbstractCheck { result = TREE_CACHE.get().get(treeCacheKey); } else { - result = context.get().parser.parseJavadocAsDetailNode(blockCommentNode); + result = context.get().parser + .parseJavadocAsDetailNode(blockCommentNode); TREE_CACHE.get().put(treeCacheKey, result); } if (result.getParseErrorMessage() == null) { - processTree(result.getTree()); + if (acceptJavadocWithNonTightHtml() || !result.isNonTight()) { + processTree(result.getTree()); + } + + if (violateExecutionOnNonTightHtml && result.isNonTight()) { + log(result.getFirstNonTightHtmlTag().getLine(), + JavadocDetailNodeParser.MSG_UNCLOSED_HTML_TAG, + result.getFirstNonTightHtmlTag().getText()); + } } else { final ParseErrorMessage parseErrorMessage = result.getParseErrorMessage(); diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/checks/javadoc/JavadocStyleCheck.java b/src/main/java/com/puppycrawl/tools/checkstyle/checks/javadoc/JavadocStyleCheck.java index 0da1de8f4..198723dbc 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/checks/javadoc/JavadocStyleCheck.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/checks/javadoc/JavadocStyleCheck.java @@ -30,6 +30,7 @@ import java.util.TreeSet; import java.util.regex.Pattern; import java.util.stream.Collectors; +import com.puppycrawl.tools.checkstyle.JavadocDetailNodeParser; import com.puppycrawl.tools.checkstyle.api.AbstractCheck; import com.puppycrawl.tools.checkstyle.api.DetailAST; import com.puppycrawl.tools.checkstyle.api.FileContents; @@ -63,7 +64,7 @@ public class JavadocStyleCheck public static final String MSG_INCOMPLETE_TAG = "javadoc.incompleteTag"; /** Message property key for the Unclosed HTML message. */ - public static final String MSG_UNCLOSED_HTML = "javadoc.unclosedHtml"; + public static final String MSG_UNCLOSED_HTML = JavadocDetailNodeParser.MSG_UNCLOSED_HTML_TAG; /** Message property key for the Extra HTML message. */ public static final String MSG_EXTRA_HTML = "javadoc.extraHtml"; diff --git a/src/main/resources/com/puppycrawl/tools/checkstyle/grammars/javadoc/JavadocParser.g4 b/src/main/resources/com/puppycrawl/tools/checkstyle/grammars/javadoc/JavadocParser.g4 index 1baa520ae..94d70301e 100644 --- a/src/main/resources/com/puppycrawl/tools/checkstyle/grammars/javadoc/JavadocParser.g4 +++ b/src/main/resources/com/puppycrawl/tools/checkstyle/grammars/javadoc/JavadocParser.g4 @@ -31,11 +31,13 @@ options { tokenVocab=JavadocLexer; } } } - boolean isSameTagNames(ParserRuleContext htmlTagStart, ParserRuleContext htmlTagEnd) { - String startTag = htmlTagStart.getToken(HTML_TAG_NAME, 0).getText().toLowerCase(); - String endTag = htmlTagEnd.getToken(HTML_TAG_NAME, 0).getText().toLowerCase(); - return startTag.equals(endTag); - } + boolean isSameTagNames(ParserRuleContext htmlTagStart, ParserRuleContext htmlTagEnd) { + String startTag = htmlTagStart.getToken(HTML_TAG_NAME, 0).getText().toLowerCase(); + String endTag = htmlTagEnd.getToken(HTML_TAG_NAME, 0).getText().toLowerCase(); + return startTag.equals(endTag); + } + + public ParserRuleContext nonTightTagStartContext; } javadoc: ( @@ -68,21 +70,21 @@ htmlElement: htmlTag | thead | tfoot - | pTagStart - | liTagStart - | trTagStart - | tdTagStart - | thTagStart - | bodyTagStart - | colgroupTagStart - | ddTagStart - | dtTagStart - | headTagStart - | htmlTagStart - | optionTagStart - | tbodyTagStart - | theadTagStart - | tfootTagStart + | pTagStart[true] + | liTagStart[true] + | trTagStart[true] + | tdTagStart[true] + | thTagStart[true] + | bodyTagStart[true] + | colgroupTagStart[true] + | ddTagStart[true] + | dtTagStart[true] + | headTagStart[true] + | htmlTagStart[true] + | optionTagStart[true] + | tbodyTagStart[true] + | theadTagStart[true] + | tfootTagStart[true] | pTagEnd | liTagEnd @@ -120,9 +122,15 @@ htmlTag: htmlElementStart (htmlElement ////////////////////////////////////////////////////////////////////////////////////// //////////////////// HTML TAGS WITH OPTIONAL END TAG //////////////////////////////// ////////////////////////////////////////////////////////////////////////////////////// -pTagStart: START P_HTML_TAG_NAME (attribute | NEWLINE | LEADING_ASTERISK | WS)* END; +pTagStart[boolean isNonTight] +@after { + if (isNonTight && nonTightTagStartContext == null) { + nonTightTagStartContext = _localctx; + } +} + : START P_HTML_TAG_NAME (attribute | NEWLINE | LEADING_ASTERISK | WS)* END; pTagEnd: START SLASH P_HTML_TAG_NAME (NEWLINE | LEADING_ASTERISK | WS)* END; -paragraph: pTagStart +paragraph: pTagStart[false] (htmlTag | singletonElement | li @@ -139,20 +147,20 @@ paragraph: pTagStart | tbody | thead | tfoot - | liTagStart - | trTagStart - | tdTagStart - | thTagStart - | bodyTagStart - | colgroupTagStart - | ddTagStart - | dtTagStart - | headTagStart - | htmlTagStart - | optionTagStart - | tbodyTagStart - | theadTagStart - | tfootTagStart + | liTagStart[true] + | trTagStart[true] + | tdTagStart[true] + | thTagStart[true] + | bodyTagStart[true] + | colgroupTagStart[true] + | ddTagStart[true] + | dtTagStart[true] + | headTagStart[true] + | htmlTagStart[true] + | optionTagStart[true] + | tbodyTagStart[true] + | theadTagStart[true] + | tfootTagStart[true] | ({!isNextJavadocTag()}? LEADING_ASTERISK) | htmlComment | CDATA @@ -162,9 +170,15 @@ paragraph: pTagStart pTagEnd ; -liTagStart: START LI_HTML_TAG_NAME (attribute | NEWLINE | LEADING_ASTERISK | WS)* END; +liTagStart[boolean isNonTight] +@after { + if (isNonTight && nonTightTagStartContext == null) { + nonTightTagStartContext = _localctx; + } +} + : START LI_HTML_TAG_NAME (attribute | NEWLINE | LEADING_ASTERISK | WS)* END; liTagEnd: START SLASH LI_HTML_TAG_NAME (NEWLINE | LEADING_ASTERISK | WS)* END; -li: liTagStart +li: liTagStart[false] (htmlTag | singletonElement | paragraph @@ -181,20 +195,20 @@ li: liTagStart | tbody | thead | tfoot - | pTagStart - | trTagStart - | tdTagStart - | thTagStart - | bodyTagStart - | colgroupTagStart - | ddTagStart - | dtTagStart - | headTagStart - | htmlTagStart - | optionTagStart - | tbodyTagStart - | theadTagStart - | tfootTagStart + | pTagStart[true] + | trTagStart[true] + | tdTagStart[true] + | thTagStart[true] + | bodyTagStart[true] + | colgroupTagStart[true] + | ddTagStart[true] + | dtTagStart[true] + | headTagStart[true] + | htmlTagStart[true] + | optionTagStart[true] + | tbodyTagStart[true] + | theadTagStart[true] + | tfootTagStart[true] | ({!isNextJavadocTag()}? LEADING_ASTERISK) | htmlComment | CDATA @@ -204,9 +218,15 @@ li: liTagStart liTagEnd ; -trTagStart: START TR_HTML_TAG_NAME (attribute | NEWLINE | LEADING_ASTERISK | WS)* END; +trTagStart[boolean isNonTight] +@after { + if (isNonTight && nonTightTagStartContext == null) { + nonTightTagStartContext = _localctx; + } +} + : START TR_HTML_TAG_NAME (attribute | NEWLINE | LEADING_ASTERISK | WS)* END; trTagEnd: START SLASH TR_HTML_TAG_NAME (NEWLINE | LEADING_ASTERISK | WS)* END; -tr: trTagStart +tr: trTagStart[false] (htmlTag | singletonElement | paragraph @@ -223,20 +243,20 @@ tr: trTagStart | tbody | thead | tfoot - | pTagStart - | liTagStart - | tdTagStart - | thTagStart - | bodyTagStart - | colgroupTagStart - | ddTagStart - | dtTagStart - | headTagStart - | htmlTagStart - | optionTagStart - | tbodyTagStart - | theadTagStart - | tfootTagStart + | pTagStart[true] + | liTagStart[true] + | tdTagStart[true] + | thTagStart[true] + | bodyTagStart[true] + | colgroupTagStart[true] + | ddTagStart[true] + | dtTagStart[true] + | headTagStart[true] + | htmlTagStart[true] + | optionTagStart[true] + | tbodyTagStart[true] + | theadTagStart[true] + | tfootTagStart[true] | ({!isNextJavadocTag()}? LEADING_ASTERISK) | htmlComment | CDATA @@ -246,9 +266,15 @@ tr: trTagStart trTagEnd ; -tdTagStart: START TD_HTML_TAG_NAME (attribute | NEWLINE | LEADING_ASTERISK | WS)* END; +tdTagStart[boolean isNonTight] +@after { + if (isNonTight && nonTightTagStartContext == null) { + nonTightTagStartContext = _localctx; + } +} + : START TD_HTML_TAG_NAME (attribute | NEWLINE | LEADING_ASTERISK | WS)* END; tdTagEnd: START SLASH TD_HTML_TAG_NAME (NEWLINE | LEADING_ASTERISK | WS)* END; -td: tdTagStart +td: tdTagStart[false] (htmlTag | singletonElement | paragraph @@ -265,20 +291,20 @@ td: tdTagStart | tbody | thead | tfoot - | pTagStart - | liTagStart - | tdTagStart - | thTagStart - | bodyTagStart - | colgroupTagStart - | ddTagStart - | dtTagStart - | headTagStart - | htmlTagStart - | optionTagStart - | tbodyTagStart - | theadTagStart - | tfootTagStart + | pTagStart[true] + | liTagStart[true] + | tdTagStart[true] + | thTagStart[true] + | bodyTagStart[true] + | colgroupTagStart[true] + | ddTagStart[true] + | dtTagStart[true] + | headTagStart[true] + | htmlTagStart[true] + | optionTagStart[true] + | tbodyTagStart[true] + | theadTagStart[true] + | tfootTagStart[true] | ({!isNextJavadocTag()}? LEADING_ASTERISK) | htmlComment | CDATA @@ -288,9 +314,15 @@ td: tdTagStart tdTagEnd ; -thTagStart: START TH_HTML_TAG_NAME (attribute | NEWLINE | LEADING_ASTERISK | WS)* END; +thTagStart[boolean isNonTight] +@after { + if (isNonTight && nonTightTagStartContext == null) { + nonTightTagStartContext = _localctx; + } +} + : START TH_HTML_TAG_NAME (attribute | NEWLINE | LEADING_ASTERISK | WS)* END; thTagEnd: START SLASH TH_HTML_TAG_NAME (NEWLINE | LEADING_ASTERISK | WS)* END; -th: thTagStart +th: thTagStart[false] (htmlTag | singletonElement | paragraph @@ -307,20 +339,20 @@ th: thTagStart | tbody | thead | tfoot - | pTagStart - | liTagStart - | trTagStart - | tdTagStart - | bodyTagStart - | colgroupTagStart - | ddTagStart - | dtTagStart - | headTagStart - | htmlTagStart - | optionTagStart - | tbodyTagStart - | theadTagStart - | tfootTagStart + | pTagStart[true] + | liTagStart[true] + | trTagStart[true] + | tdTagStart[true] + | bodyTagStart[true] + | colgroupTagStart[true] + | ddTagStart[true] + | dtTagStart[true] + | headTagStart[true] + | htmlTagStart[true] + | optionTagStart[true] + | tbodyTagStart[true] + | theadTagStart[true] + | tfootTagStart[true] | ({!isNextJavadocTag()}? LEADING_ASTERISK) | htmlComment | CDATA @@ -330,9 +362,15 @@ th: thTagStart thTagEnd ; -bodyTagStart: START BODY_HTML_TAG_NAME (attribute | NEWLINE | LEADING_ASTERISK | WS)* END; +bodyTagStart[boolean isNonTight] +@after { + if (isNonTight && nonTightTagStartContext == null) { + nonTightTagStartContext = _localctx; + } +} + : START BODY_HTML_TAG_NAME (attribute | NEWLINE | LEADING_ASTERISK | WS)* END; bodyTagEnd: START SLASH BODY_HTML_TAG_NAME (NEWLINE | LEADING_ASTERISK | WS)* END; -body: bodyTagStart +body: bodyTagStart[false] (htmlTag | singletonElement | paragraph @@ -349,20 +387,20 @@ body: bodyTagStart | tbody | thead | tfoot - | pTagStart - | liTagStart - | trTagStart - | tdTagStart - | thTagStart - | colgroupTagStart - | ddTagStart - | dtTagStart - | headTagStart - | htmlTagStart - | optionTagStart - | tbodyTagStart - | theadTagStart - | tfootTagStart + | pTagStart[true] + | liTagStart[true] + | trTagStart[true] + | tdTagStart[true] + | thTagStart[true] + | colgroupTagStart[true] + | ddTagStart[true] + | dtTagStart[true] + | headTagStart[true] + | htmlTagStart[true] + | optionTagStart[true] + | tbodyTagStart[true] + | theadTagStart[true] + | tfootTagStart[true] | ({!isNextJavadocTag()}? LEADING_ASTERISK) | htmlComment | CDATA @@ -372,9 +410,15 @@ body: bodyTagStart bodyTagEnd ; -colgroupTagStart: START COLGROUP_HTML_TAG_NAME (attribute | NEWLINE | LEADING_ASTERISK | WS)* END; +colgroupTagStart[boolean isNonTight] +@after { + if (isNonTight && nonTightTagStartContext == null) { + nonTightTagStartContext = _localctx; + } +} + : START COLGROUP_HTML_TAG_NAME (attribute | NEWLINE | LEADING_ASTERISK | WS)* END; colgroupTagEnd: START SLASH COLGROUP_HTML_TAG_NAME (NEWLINE | LEADING_ASTERISK | WS)* END; -colgroup: colgroupTagStart +colgroup: colgroupTagStart[false] (htmlTag | singletonElement | paragraph @@ -391,20 +435,20 @@ colgroup: colgroupTagStart | tbody | thead | tfoot - | pTagStart - | liTagStart - | trTagStart - | tdTagStart - | thTagStart - | bodyTagStart - | ddTagStart - | dtTagStart - | headTagStart - | htmlTagStart - | optionTagStart - | tbodyTagStart - | theadTagStart - | tfootTagStart + | pTagStart[true] + | liTagStart[true] + | trTagStart[true] + | tdTagStart[true] + | thTagStart[true] + | bodyTagStart[true] + | ddTagStart[true] + | dtTagStart[true] + | headTagStart[true] + | htmlTagStart[true] + | optionTagStart[true] + | tbodyTagStart[true] + | theadTagStart[true] + | tfootTagStart[true] | ({!isNextJavadocTag()}? LEADING_ASTERISK) | htmlComment | CDATA @@ -414,9 +458,15 @@ colgroup: colgroupTagStart colgroupTagEnd ; -ddTagStart: START DD_HTML_TAG_NAME (attribute | NEWLINE | LEADING_ASTERISK | WS)* END; +ddTagStart[boolean isNonTight] +@after { + if (isNonTight && nonTightTagStartContext == null) { + nonTightTagStartContext = _localctx; + } +} + : START DD_HTML_TAG_NAME (attribute | NEWLINE | LEADING_ASTERISK | WS)* END; ddTagEnd: START SLASH DD_HTML_TAG_NAME (NEWLINE | LEADING_ASTERISK | WS)* END; -dd: ddTagStart +dd: ddTagStart[false] (htmlTag | singletonElement | paragraph @@ -433,20 +483,20 @@ dd: ddTagStart | tbody | thead | tfoot - | pTagStart - | liTagStart - | trTagStart - | tdTagStart - | thTagStart - | bodyTagStart - | colgroupTagStart - | dtTagStart - | headTagStart - | htmlTagStart - | optionTagStart - | tbodyTagStart - | theadTagStart - | tfootTagStart + | pTagStart[true] + | liTagStart[true] + | trTagStart[true] + | tdTagStart[true] + | thTagStart[true] + | bodyTagStart[true] + | colgroupTagStart[true] + | dtTagStart[true] + | headTagStart[true] + | htmlTagStart[true] + | optionTagStart[true] + | tbodyTagStart[true] + | theadTagStart[true] + | tfootTagStart[true] | ({!isNextJavadocTag()}? LEADING_ASTERISK) | htmlComment | CDATA @@ -456,9 +506,15 @@ dd: ddTagStart ddTagEnd ; -dtTagStart: START DT_HTML_TAG_NAME (attribute | NEWLINE | LEADING_ASTERISK | WS)* END; +dtTagStart[boolean isNonTight] +@after { + if (isNonTight && nonTightTagStartContext == null) { + nonTightTagStartContext = _localctx; + } +} + : START DT_HTML_TAG_NAME (attribute | NEWLINE | LEADING_ASTERISK | WS)* END; dtTagEnd: START SLASH DT_HTML_TAG_NAME (NEWLINE | LEADING_ASTERISK | WS)* END; -dt: dtTagStart +dt: dtTagStart[false] (htmlTag | singletonElement | paragraph @@ -475,20 +531,20 @@ dt: dtTagStart | tbody | thead | tfoot - | pTagStart - | liTagStart - | trTagStart - | tdTagStart - | thTagStart - | bodyTagStart - | colgroupTagStart - | ddTagStart - | headTagStart - | htmlTagStart - | optionTagStart - | tbodyTagStart - | theadTagStart - | tfootTagStart + | pTagStart[true] + | liTagStart[true] + | trTagStart[true] + | tdTagStart[true] + | thTagStart[true] + | bodyTagStart[true] + | colgroupTagStart[true] + | ddTagStart[true] + | headTagStart[true] + | htmlTagStart[true] + | optionTagStart[true] + | tbodyTagStart[true] + | theadTagStart[true] + | tfootTagStart[true] | ({!isNextJavadocTag()}? LEADING_ASTERISK) | htmlComment | CDATA @@ -498,9 +554,15 @@ dt: dtTagStart dtTagEnd ; -headTagStart: START HEAD_HTML_TAG_NAME (attribute | NEWLINE | LEADING_ASTERISK | WS)* END; +headTagStart[boolean isNonTight] +@after { + if (isNonTight && nonTightTagStartContext == null) { + nonTightTagStartContext = _localctx; + } +} + : START HEAD_HTML_TAG_NAME (attribute | NEWLINE | LEADING_ASTERISK | WS)* END; headTagEnd: START SLASH HEAD_HTML_TAG_NAME (NEWLINE | LEADING_ASTERISK | WS)* END; -head: headTagStart +head: headTagStart[false] (htmlTag | singletonElement | paragraph @@ -517,20 +579,20 @@ head: headTagStart | tbody | thead | tfoot - | pTagStart - | liTagStart - | trTagStart - | tdTagStart - | thTagStart - | bodyTagStart - | colgroupTagStart - | ddTagStart - | dtTagStart - | htmlTagStart - | optionTagStart - | tbodyTagStart - | theadTagStart - | tfootTagStart + | pTagStart[true] + | liTagStart[true] + | trTagStart[true] + | tdTagStart[true] + | thTagStart[true] + | bodyTagStart[true] + | colgroupTagStart[true] + | ddTagStart[true] + | dtTagStart[true] + | htmlTagStart[true] + | optionTagStart[true] + | tbodyTagStart[true] + | theadTagStart[true] + | tfootTagStart[true] | ({!isNextJavadocTag()}? LEADING_ASTERISK) | htmlComment | CDATA @@ -540,9 +602,15 @@ head: headTagStart headTagEnd ; -htmlTagStart: START HTML_HTML_TAG_NAME (attribute | NEWLINE | LEADING_ASTERISK | WS)* END; +htmlTagStart[boolean isNonTight] +@after { + if (isNonTight && nonTightTagStartContext == null) { + nonTightTagStartContext = _localctx; + } +} + : START HTML_HTML_TAG_NAME (attribute | NEWLINE | LEADING_ASTERISK | WS)* END; htmlTagEnd: START SLASH HTML_HTML_TAG_NAME (NEWLINE | LEADING_ASTERISK | WS)* END; -html: htmlTagStart +html: htmlTagStart[false] (htmlTag | singletonElement | paragraph @@ -559,20 +627,20 @@ html: htmlTagStart | tbody | thead | tfoot - | pTagStart - | liTagStart - | trTagStart - | tdTagStart - | thTagStart - | bodyTagStart - | colgroupTagStart - | ddTagStart - | dtTagStart - | headTagStart - | optionTagStart - | tbodyTagStart - | theadTagStart - | tfootTagStart + | pTagStart[true] + | liTagStart[true] + | trTagStart[true] + | tdTagStart[true] + | thTagStart[true] + | bodyTagStart[true] + | colgroupTagStart[true] + | ddTagStart[true] + | dtTagStart[true] + | headTagStart[true] + | optionTagStart[true] + | tbodyTagStart[true] + | theadTagStart[true] + | tfootTagStart[true] | ({!isNextJavadocTag()}? LEADING_ASTERISK) | htmlComment | CDATA @@ -582,9 +650,15 @@ html: htmlTagStart htmlTagEnd ; -optionTagStart: START OPTION_HTML_TAG_NAME (attribute | NEWLINE | LEADING_ASTERISK | WS)* END; +optionTagStart[boolean isNonTight] +@after { + if (isNonTight && nonTightTagStartContext == null) { + nonTightTagStartContext = _localctx; + } +} + : START OPTION_HTML_TAG_NAME (attribute | NEWLINE | LEADING_ASTERISK | WS)* END; optionTagEnd: START SLASH OPTION_HTML_TAG_NAME (NEWLINE | LEADING_ASTERISK | WS)* END; -option: optionTagStart +option: optionTagStart[false] (htmlTag | singletonElement | paragraph @@ -601,20 +675,20 @@ option: optionTagStart | tbody | thead | tfoot - | pTagStart - | liTagStart - | trTagStart - | tdTagStart - | thTagStart - | bodyTagStart - | colgroupTagStart - | ddTagStart - | dtTagStart - | headTagStart - | htmlTagStart - | tbodyTagStart - | theadTagStart - | tfootTagStart + | pTagStart[true] + | liTagStart[true] + | trTagStart[true] + | tdTagStart[true] + | thTagStart[true] + | bodyTagStart[true] + | colgroupTagStart[true] + | ddTagStart[true] + | dtTagStart[true] + | headTagStart[true] + | htmlTagStart[true] + | tbodyTagStart[true] + | theadTagStart[true] + | tfootTagStart[true] | ({!isNextJavadocTag()}? LEADING_ASTERISK) | htmlComment | CDATA @@ -624,9 +698,15 @@ option: optionTagStart optionTagEnd ; -tbodyTagStart: START TBODY_HTML_TAG_NAME (attribute | NEWLINE | LEADING_ASTERISK | WS)* END; +tbodyTagStart[boolean isNonTight] +@after { + if (isNonTight && nonTightTagStartContext == null) { + nonTightTagStartContext = _localctx; + } +} + : START TBODY_HTML_TAG_NAME (attribute | NEWLINE | LEADING_ASTERISK | WS)* END; tbodyTagEnd: START SLASH TBODY_HTML_TAG_NAME (NEWLINE | LEADING_ASTERISK | WS)* END; -tbody: tbodyTagStart +tbody: tbodyTagStart[false] (htmlTag | singletonElement | paragraph @@ -643,20 +723,20 @@ tbody: tbodyTagStart | option | thead | tfoot - | pTagStart - | liTagStart - | trTagStart - | tdTagStart - | thTagStart - | bodyTagStart - | colgroupTagStart - | ddTagStart - | dtTagStart - | headTagStart - | htmlTagStart - | optionTagStart - | theadTagStart - | tfootTagStart + | pTagStart[true] + | liTagStart[true] + | trTagStart[true] + | tdTagStart[true] + | thTagStart[true] + | bodyTagStart[true] + | colgroupTagStart[true] + | ddTagStart[true] + | dtTagStart[true] + | headTagStart[true] + | htmlTagStart[true] + | optionTagStart[true] + | theadTagStart[true] + | tfootTagStart[true] | ({!isNextJavadocTag()}? LEADING_ASTERISK) | htmlComment | CDATA @@ -666,9 +746,15 @@ tbody: tbodyTagStart tbodyTagEnd ; -tfootTagStart: START TFOOT_HTML_TAG_NAME (attribute | NEWLINE | LEADING_ASTERISK | WS)* END; +tfootTagStart[boolean isNonTight] +@after { + if (isNonTight && nonTightTagStartContext == null) { + nonTightTagStartContext = _localctx; + } +} + : START TFOOT_HTML_TAG_NAME (attribute | NEWLINE | LEADING_ASTERISK | WS)* END; tfootTagEnd: START SLASH TFOOT_HTML_TAG_NAME (NEWLINE | LEADING_ASTERISK | WS)* END; -tfoot: tfootTagStart +tfoot: tfootTagStart[false] (htmlTag | singletonElement | paragraph @@ -685,20 +771,20 @@ tfoot: tfootTagStart | option | tbody | thead - | pTagStart - | liTagStart - | trTagStart - | tdTagStart - | thTagStart - | bodyTagStart - | colgroupTagStart - | ddTagStart - | dtTagStart - | headTagStart - | htmlTagStart - | optionTagStart - | tbodyTagStart - | theadTagStart + | pTagStart[true] + | liTagStart[true] + | trTagStart[true] + | tdTagStart[true] + | thTagStart[true] + | bodyTagStart[true] + | colgroupTagStart[true] + | ddTagStart[true] + | dtTagStart[true] + | headTagStart[true] + | htmlTagStart[true] + | optionTagStart[true] + | tbodyTagStart[true] + | theadTagStart[true] | ({!isNextJavadocTag()}? LEADING_ASTERISK) | htmlComment | CDATA @@ -708,9 +794,15 @@ tfoot: tfootTagStart tfootTagEnd ; -theadTagStart: START THEAD_HTML_TAG_NAME (attribute | NEWLINE | LEADING_ASTERISK | WS)* END; +theadTagStart[boolean isNonTight] +@after { + if (isNonTight && nonTightTagStartContext == null) { + nonTightTagStartContext = _localctx; + } +} + : START THEAD_HTML_TAG_NAME (attribute | NEWLINE | LEADING_ASTERISK | WS)* END; theadTagEnd: START SLASH THEAD_HTML_TAG_NAME (NEWLINE | LEADING_ASTERISK | WS)* END; -thead: theadTagStart +thead: theadTagStart[false] (htmlTag | singletonElement | paragraph @@ -727,20 +819,20 @@ thead: theadTagStart | option | tbody | tfoot - | pTagStart - | liTagStart - | trTagStart - | tdTagStart - | thTagStart - | bodyTagStart - | colgroupTagStart - | ddTagStart - | dtTagStart - | headTagStart - | htmlTagStart - | optionTagStart - | tbodyTagStart - | tfootTagStart + | pTagStart[true] + | liTagStart[true] + | trTagStart[true] + | tdTagStart[true] + | thTagStart[true] + | bodyTagStart[true] + | colgroupTagStart[true] + | ddTagStart[true] + | dtTagStart[true] + | headTagStart[true] + | htmlTagStart[true] + | optionTagStart[true] + | tbodyTagStart[true] + | tfootTagStart[true] | ({!isNextJavadocTag()}? LEADING_ASTERISK) | htmlComment | CDATA diff --git a/src/test/java/com/puppycrawl/tools/checkstyle/checks/javadoc/AbstractJavadocCheckTest.java b/src/test/java/com/puppycrawl/tools/checkstyle/checks/javadoc/AbstractJavadocCheckTest.java index 56718b078..4c8f912d2 100644 --- a/src/test/java/com/puppycrawl/tools/checkstyle/checks/javadoc/AbstractJavadocCheckTest.java +++ b/src/test/java/com/puppycrawl/tools/checkstyle/checks/javadoc/AbstractJavadocCheckTest.java @@ -20,8 +20,10 @@ package com.puppycrawl.tools.checkstyle.checks.javadoc; import static com.puppycrawl.tools.checkstyle.JavadocDetailNodeParser.MSG_JAVADOC_PARSE_RULE_ERROR; +import static com.puppycrawl.tools.checkstyle.JavadocDetailNodeParser.MSG_UNCLOSED_HTML_TAG; import static com.puppycrawl.tools.checkstyle.checks.javadoc.AbstractJavadocCheck.MSG_JAVADOC_MISSED_HTML_CLOSE; import static com.puppycrawl.tools.checkstyle.checks.javadoc.AbstractJavadocCheck.MSG_JAVADOC_WRONG_SINGLETON_TAG; +import static com.puppycrawl.tools.checkstyle.checks.javadoc.SummaryJavadocCheck.MSG_SUMMARY_FIRST_SENTENCE; import static java.util.Arrays.asList; import static java.util.Collections.singletonList; import static org.junit.Assert.assertEquals; @@ -48,6 +50,7 @@ import com.puppycrawl.tools.checkstyle.utils.BlockCommentPosition; import com.puppycrawl.tools.checkstyle.utils.CommonUtils; public class AbstractJavadocCheckTest extends AbstractModuleTestSupport { + @Rule public final SystemErrRule systemErr = new SystemErrRule().enableLog().mute(); @@ -350,6 +353,113 @@ public class AbstractJavadocCheckTest extends AbstractModuleTestSupport { expected); } + @Test + public void testNonTightHtmlTagIntolerantCheck() throws Exception { + final DefaultConfiguration checkConfig = + createModuleConfig(NonTightHtmlTagIntolerantCheck.class); + checkConfig.addAttribute("violateExecutionOnNonTightHtml", "true"); + final String[] expected = { + "6: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "p"), + "13: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "p"), + "16: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "li"), + "21: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "p"), + "27: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "tr"), + "34: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "li"), + "54: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "li"), + "71: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "p"), + "80: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "tr"), + "124: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "p"), + }; + verify(checkConfig, getPath("InputAbstractJavadocNonTightHtmlTags.java"), expected); + } + + @Test + public void testNonTightHtmlTagIntolerantCheckReportingNoViolation() throws Exception { + final DefaultConfiguration checkConfig = + createModuleConfig(NonTightHtmlTagIntolerantCheck.class); + final String[] expected = CommonUtils.EMPTY_STRING_ARRAY; + verify(checkConfig, getPath("InputAbstractJavadocNonTightHtmlTags.java"), expected); + } + + @Test + public void testNonTightHtmlTagIntolerantCheckVisitCount() + throws Exception { + final DefaultConfiguration checkConfig = + createModuleConfig(NonTightHtmlTagIntolerantCheck.class); + checkConfig.addAttribute("violateExecutionOnNonTightHtml", "true"); + checkConfig.addAttribute("reportVisitJavadocToken", "true"); + final String[] expected = { + "6: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "p"), + "13: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "p"), + "16: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "li"), + "21: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "p"), + "27: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "tr"), + "34: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "li"), + "41:8: " + getCheckMessage(MSG_SUMMARY_FIRST_SENTENCE), + "54: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "li"), + "62:13: " + getCheckMessage(MSG_SUMMARY_FIRST_SENTENCE), + "71: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "p"), + "80: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "tr"), + "99:8: " + getCheckMessage(MSG_SUMMARY_FIRST_SENTENCE), + "105:8: " + getCheckMessage(MSG_SUMMARY_FIRST_SENTENCE), + "109:8: " + getCheckMessage(MSG_SUMMARY_FIRST_SENTENCE), + "124: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "p"), + }; + verify(checkConfig, getPath("InputAbstractJavadocNonTightHtmlTags.java"), expected); + } + + @Test + public void testVisitCountForCheckAcceptingJavadocWithNonTightHtml() + throws Exception { + final DefaultConfiguration checkConfig = + createModuleConfig(NonTightHtmlTagTolerantCheck.class); + checkConfig.addAttribute("violateExecutionOnNonTightHtml", "true"); + checkConfig.addAttribute("reportVisitJavadocToken", "true"); + final String[] expected = { + "4:4: " + getCheckMessage(MSG_SUMMARY_FIRST_SENTENCE), + "5:4: " + getCheckMessage(MSG_SUMMARY_FIRST_SENTENCE), + "6: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "p"), + "6:4: " + getCheckMessage(MSG_SUMMARY_FIRST_SENTENCE), + "7:4: " + getCheckMessage(MSG_SUMMARY_FIRST_SENTENCE), + "7:39: " + getCheckMessage(MSG_SUMMARY_FIRST_SENTENCE), + "13: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "p"), + "13:9: " + getCheckMessage(MSG_SUMMARY_FIRST_SENTENCE), + "13:13: " + getCheckMessage(MSG_SUMMARY_FIRST_SENTENCE), + "16: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "li"), + "16:8: " + getCheckMessage(MSG_SUMMARY_FIRST_SENTENCE), + "20:8: " + getCheckMessage(MSG_SUMMARY_FIRST_SENTENCE), + "21: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "p"), + "21:8: " + getCheckMessage(MSG_SUMMARY_FIRST_SENTENCE), + "21:30: " + getCheckMessage(MSG_SUMMARY_FIRST_SENTENCE), + "26:8: " + getCheckMessage(MSG_SUMMARY_FIRST_SENTENCE), + "26:22: " + getCheckMessage(MSG_SUMMARY_FIRST_SENTENCE), + "27: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "tr"), + "32:8: " + getCheckMessage(MSG_SUMMARY_FIRST_SENTENCE), + "33:8: " + getCheckMessage(MSG_SUMMARY_FIRST_SENTENCE), + "34: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "li"), + "34:8: " + getCheckMessage(MSG_SUMMARY_FIRST_SENTENCE), + "34:23: " + getCheckMessage(MSG_SUMMARY_FIRST_SENTENCE), + "39:8: " + getCheckMessage(MSG_SUMMARY_FIRST_SENTENCE), + "39:20: " + getCheckMessage(MSG_SUMMARY_FIRST_SENTENCE), + "39:34: " + getCheckMessage(MSG_SUMMARY_FIRST_SENTENCE), + "41: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "li"), + "41:16: " + getCheckMessage(MSG_SUMMARY_FIRST_SENTENCE), + "41:21: " + getCheckMessage(MSG_SUMMARY_FIRST_SENTENCE), + "49:8: " + getCheckMessage(MSG_SUMMARY_FIRST_SENTENCE), + "51: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "p"), + "51:22: " + getCheckMessage(MSG_SUMMARY_FIRST_SENTENCE), + "56:8: " + getCheckMessage(MSG_SUMMARY_FIRST_SENTENCE), + "57:8: " + getCheckMessage(MSG_SUMMARY_FIRST_SENTENCE), + "60: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "tr"), + "79:8: " + getCheckMessage(MSG_SUMMARY_FIRST_SENTENCE), + "85: " + getCheckMessage(MSG_UNCLOSED_HTML_TAG, "p"), + "85:9: " + getCheckMessage(MSG_SUMMARY_FIRST_SENTENCE), + "85:13: " + getCheckMessage(MSG_SUMMARY_FIRST_SENTENCE), + "85:33: " + getCheckMessage(MSG_SUMMARY_FIRST_SENTENCE), + }; + verify(checkConfig, getPath("InputAbstractJavadocNonTightHtmlTags2.java"), expected); + } + private static class TempCheck extends AbstractJavadocCheck { @Override @@ -460,4 +570,59 @@ public class AbstractJavadocCheckTest extends AbstractModuleTestSupport { leaveCount++; } } + + public static class NonTightHtmlTagIntolerantCheck extends AbstractJavadocCheck { + + private boolean reportVisitJavadocToken; + + public final void setReportVisitJavadocToken(boolean reportVisitJavadocToken) { + this.reportVisitJavadocToken = reportVisitJavadocToken; + } + + @Override + public int[] getDefaultJavadocTokens() { + return new int[] { + JavadocTokenTypes.P_TAG_START, + JavadocTokenTypes.LI_TAG_START, + JavadocTokenTypes.BODY_TAG_START, + }; + } + + @Override + public void visitJavadocToken(DetailNode ast) { + if (reportVisitJavadocToken) { + log(ast.getLineNumber(), ast.getColumnNumber(), MSG_SUMMARY_FIRST_SENTENCE); + } + } + + @Override + public boolean acceptJavadocWithNonTightHtml() { + return false; + } + } + + public static class NonTightHtmlTagTolerantCheck extends AbstractJavadocCheck { + + private boolean reportVisitJavadocToken; + + public final void setReportVisitJavadocToken(boolean reportVisitJavadocToken) { + this.reportVisitJavadocToken = reportVisitJavadocToken; + } + + @Override + public int[] getDefaultJavadocTokens() { + return new int[] { + JavadocTokenTypes.P_TAG_START, + JavadocTokenTypes.LI_TAG_START, + JavadocTokenTypes.BODY_TAG_START, + }; + } + + @Override + public void visitJavadocToken(DetailNode ast) { + if (reportVisitJavadocToken) { + log(ast.getLineNumber(), ast.getColumnNumber(), MSG_SUMMARY_FIRST_SENTENCE); + } + } + } } diff --git a/src/test/resources/com/puppycrawl/tools/checkstyle/checks/javadoc/abstractjavadoc/InputAbstractJavadocNonTightHtmlTags.java b/src/test/resources/com/puppycrawl/tools/checkstyle/checks/javadoc/abstractjavadoc/InputAbstractJavadocNonTightHtmlTags.java new file mode 100644 index 000000000..a2e2ec563 --- /dev/null +++ b/src/test/resources/com/puppycrawl/tools/checkstyle/checks/javadoc/abstractjavadoc/InputAbstractJavadocNonTightHtmlTags.java @@ -0,0 +1,129 @@ +package com.puppycrawl.tools.checkstyle.checks.javadoc.abstractjavadoc; + +/** + * <body> + * <p> This class is only meant for testing. </p> + * <p> In html, closing all tags is not necessary. + * <li> neither is opening every tag <p> </li> + * </body> + * + * @see "https://www.w3.org/TR/html51/syntax.html#optional-start-and-end-tags" + */ +public class InputAbstractJavadocNonTightHtmlTags { + /** <p> <p> paraception </p> </p> */ + private int field1; + + /**<li> paraTags should be opened</p> list isn't nested in parse tree </li>*/ + private int field2; + + /** + * <p> this paragraph is closed and would be nested in javadoc tree </p> + * <li> this list has an <p> unclosed para, but still the list would get nested </li> + */ + private int field3; + + /** + * <li> Complete <p> nesting </p> </li> + * <tr> Zero </p> nesting despite `tr` is closed </tr> + */ + private int field4; + + /** + * <p> <a href="www.something.com">something</a> paragraph with `htmlTag` </p> + * <p> <a href="www.something.com"/> Nested paragraph with `singletonTag` </p> + * <li> Outer tag <li> Inner tag nested </li> not nested </li> + */ + private int field5; + + /** + * <th> !isNonTight </th> + * <th> th with <base/> singletonElement </th> + * <body> body with <br/> singletonElement </body> + * <colgroup><col><col><col></colgroup> + * <dd> dd with <hr> singletonElement </dd> + * <dt> dt with <img src="~/singletonElement.jpg" alt="" width="100" height="150"/> + * singletonElement </dt> + * <head> head with <img src="~/singletonElement.jpg" alt="" width="100" height="150"> + * singletonElement </head> + */ + private int field6; + + /** + * <body> body <p> paragraph <li> list </li> </p> </body> + * + * @return <li> <li> outer list isn't nested in parse tree </li> </li> + */ + int getField1() {return field1;} + + /***/ + int getField2() {return field2;} //method with empty javadoc + + /** + * <tr> <li> list is going to be nested in the parse tree </li> </tr> + * + * @param field1 {@code <p> paraTag will not be recognized} in javadoc tree </p> + */ + void setField1(int field1) {this.field1 = field1;} + + /** + * <p>This is a setter method. + * And paraTag shall be nested in parse tree </p> + * @param field2 <p> settter + */ + void setField2(int field2) {this.field2 = field2;} + + /** + * <p> paragraph with a <br>singletonElement. <hr> And it contains another one. </p> + * <li> List with singletonElement + * <param name=mov value="~/imitation game.mp4"> <param name=allowfullscreen value=true> </li> + * @return <tr> tr with <base href="www.something.com"> singletonElement </tr> + * <tr> nonTight </th> + */ + private int getField3() {return field3;} + + /** + * @param field3 <td> td with singletonElement <br/> </td> + */ + private void setField3(int field3) { this.field3 = field3;} + + /** + * <html> <bR> <Br> <BR> <Br/> <BR/> <bR/> </html> + * <option> <INPut/> </option> + * @return <tbody> <input/> <br> </tbody> + */ + private int getField4() {return field4;} + + /** + * <thead> <br> </thead> + * <tfoot> <AREA ALT="alt" COORDS="100,0,200,50" HREF="/href/"> </tfoot> + * <p> </p> + * @param field4 value to which {@link #field4} is to be set to + */ + private void setField4(int field4) {this.field4 = field4;} + + /** + * <li> </li> + * <TR> </tr> + * <Td> </td> + * <tH> </th> + * <body> </body> + * <colGROUP> </COLgroup> + * <DD> </dd> + * <dt> </dt> + * <Head> </head> + * <HTML> </HTML> + * <option> </option> + * <tBody> </TbODY> + * <tHead> </ThEAD> + * <tFoot> </TfOOT> + * @param field5 value to which {@link #field5} is to be set to + */ + private void setField5(int field5) {this.field5 = field5;} + + /** + * <p> <li> <TR> <Td> <tH> <body> <colGROUP> <DD> <dt> <Head> <HTML> <option> <tBody> <tHead> + * <tFoot> + * @param field6 </p> value to which {@link #field6} is to be set to + */ + private void setField6(int field6) {this.field6 = field6;} +} diff --git a/src/test/resources/com/puppycrawl/tools/checkstyle/checks/javadoc/abstractjavadoc/InputAbstractJavadocNonTightHtmlTags2.java b/src/test/resources/com/puppycrawl/tools/checkstyle/checks/javadoc/abstractjavadoc/InputAbstractJavadocNonTightHtmlTags2.java new file mode 100644 index 000000000..1cf6024f4 --- /dev/null +++ b/src/test/resources/com/puppycrawl/tools/checkstyle/checks/javadoc/abstractjavadoc/InputAbstractJavadocNonTightHtmlTags2.java @@ -0,0 +1,90 @@ +package com.puppycrawl.tools.checkstyle.checks.javadoc.abstractjavadoc; + +/** + * <body> + * <p> This class is only meant for testing. </p> + * <p> In html, closing all tags is not necessary. + * <li> neither is opening every tag. <p>Only the first non-tight tag is logged</li> + * </body> + * + * @see "https://www.w3.org/TR/html51/syntax.html#optional-start-and-end-tags" + */ +public class InputAbstractJavadocNonTightHtmlTags2 { + /** <p> <p> paraception </p> </p> */ + private int field1; + + /**<li> paraTags should be opened</p> list isn't nested in parse tree </li>*/ + private int field2; + + /** + * <p> this paragraph is closed and would be nested in javadoc tree </p> + * <li> this list has an <p> unclosed para, but still the list would get nested </li> + */ + private int field3; + + /** + * <li> Complete <p> nesting </p> </li> + * <tr> Zero </p> nesting despite `tr` is closed </tr> + */ + private int field4; + + /** + * <p> <a href="www.something.com">something</a> paragraph with `htmlTag` </p> + * <p> <a href="www.something.com"/> Nested paragraph with `singletonTag` </p> + * <li> Outer tag <li> Inner tag nested </li> not nested </li> + */ + private int field5; + + /** + * <body> body <p> paragraph <li> list </li> </p> </body> + * + * @return <li> <li> outer list isn't nested in parse tree </li> </li> + */ + int getField1() {return field1;} + + /***/ + int getField2() {return field2;} //method with empty javadoc + + /** + * <p>This is a setter method. + * And paraTag shall be nested in parse tree </p> + * @param field2 <p> settter + */ + void setField2(int field2) {this.field2 = field2;} + + /** + * <p> paragraph with a <br>singletonElement. <hr> And it contains another one. </p> + * <li> List with singletonElement + * <param name=mov value="~/imitation game.mp4"> <param name=allowfullscreen value=true> </li> + * @return <tr> tr with <base href="www.something.com"> singletonElement </tr> + * <tr> nonTight </th> + */ + private int getField3() {return field3;} + + /** + * @param field3 <td> td with singletonElement <br/> </td> + */ + private void setField3(int field3) { this.field3 = field3;} + + /** + * <html> <bR> <Br> <BR> <Br/> <BR/> <bR/> </html> + * <option> <INPut/> </option> + * @return <tbody> <input/> <br> </tbody> + */ + private int getField4() {return field4;} + + /** + * <thead> <br> </thead> + * <tfoot> <AREA ALT="alt" COORDS="100,0,200,50" HREF="/href/"> </tfoot> + * <p> </p> + * @param field4 value to which {@link #field4} is to be set to + */ + private void setField4(int field4) {this.field4 = field4;} + + /** + * <p> <li> <TR> <Td> <tH> <body> <colGROUP> <DD> <dt> <Head> <HTML> <option> <tBody> <tHead> + * <tFoot> + * @param field5 </p> value to which {@link #field5} is to be set to + */ + private void setField5(int field5) {this.field5 = field5;} +} |