From ad585631576a49b45b2f1802c7197cc57bf2a504 Mon Sep 17 00:00:00 2001 From: rnveach Date: Sun, 23 Oct 2016 08:47:47 -0400 Subject: [PATCH] Issue #2427: added customizable javadoc tokens --- .../checkstyle/api/JavadocTokenTypes.java | 3 + .../checks/javadoc/AbstractJavadocCheck.java | 104 +++++++++++-- .../checks/javadoc/AtclauseOrderCheck.java | 5 + .../checks/javadoc/JavadocParagraphCheck.java | 5 + ...avadocTagContinuationIndentationCheck.java | 5 + .../javadoc/SingleLineJavadocCheck.java | 5 + .../checks/javadoc/SummaryJavadocCheck.java | 5 + .../javadoc/AbstractJavadocCheckTest.java | 142 ++++++++++++++++++ .../tools/checkstyle/internal/CheckUtil.java | 39 +++++ .../checkstyle/internal/XDocsPagesTest.java | 110 +++++++++++--- .../checkstyle/checks/javadoc/InputMain.java | 4 + src/xdocs/config_javadoc.xml | 27 ++++ src/xdocs/writingjavadocchecks.xml.vm | 38 ++++- 13 files changed, 456 insertions(+), 36 deletions(-) create mode 100644 src/test/resources/com/puppycrawl/tools/checkstyle/checks/javadoc/InputMain.java diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/api/JavadocTokenTypes.java b/src/main/java/com/puppycrawl/tools/checkstyle/api/JavadocTokenTypes.java index c09a67b0b29..624cff82d74 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/api/JavadocTokenTypes.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/api/JavadocTokenTypes.java @@ -24,6 +24,9 @@ import com.puppycrawl.tools.checkstyle.grammars.javadoc.JavadocParser; /** + * Contains the constants for all the tokens contained in the Abstract + * Syntax Tree for the javadoc grammar. + * * @author Baratali Izmailov * @see * javadoc - The Java API Documentation Generator 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 faed34a1817..3ca4ab1f6e7 100755 --- a/src/main/java/com/puppycrawl/tools/checkstyle/checks/javadoc/AbstractJavadocCheck.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/checks/javadoc/AbstractJavadocCheck.java @@ -19,9 +19,12 @@ package com.puppycrawl.tools.checkstyle.checks.javadoc; +import java.util.Arrays; import java.util.HashMap; +import java.util.HashSet; +import java.util.Locale; import java.util.Map; -import java.util.stream.IntStream; +import java.util.Set; import com.puppycrawl.tools.checkstyle.JavadocDetailNodeParser; import com.puppycrawl.tools.checkstyle.JavadocDetailNodeParser.ParseErrorMessage; @@ -32,6 +35,7 @@ import com.puppycrawl.tools.checkstyle.api.JavadocTokenTypes; import com.puppycrawl.tools.checkstyle.api.TokenTypes; import com.puppycrawl.tools.checkstyle.utils.BlockCommentPosition; +import com.puppycrawl.tools.checkstyle.utils.CommonUtils; import com.puppycrawl.tools.checkstyle.utils.JavadocUtils; /** @@ -39,7 +43,6 @@ * @author Baratali Izmailov */ public abstract class AbstractJavadocCheck extends AbstractCheck { - /** * Message key of error message. Missed close HTML tag breaks structure * of parse tree, so parser stops parsing and generates such error @@ -90,6 +93,9 @@ protected Map initialValue() { */ private final JavadocDetailNodeParser parser = new JavadocDetailNodeParser(); + /** The javadoc tokens the check is interested in. */ + private final Set javadocTokens = new HashSet<>(); + /** * DetailAST node of considered Javadoc comment that is just a block comment * in Java language syntax tree. @@ -97,8 +103,8 @@ protected Map initialValue() { private DetailAST blockCommentAst; /** - * Returns the default token types a check is interested in. - * @return the default token types + * Returns the default javadoc token types a check is interested in. + * @return the default javadoc token types * @see JavadocTokenTypes */ public abstract int[] getDefaultJavadocTokens(); @@ -110,6 +116,84 @@ protected Map initialValue() { */ public abstract void visitJavadocToken(DetailNode ast); + /** + * The configurable javadoc token set. + * Used to protect Checks against malicious users who specify an + * unacceptable javadoc token set in the configuration file. + * The default implementation returns the check's default javadoc tokens. + * @return the javadoc token set this check is designed for. + * @see JavadocTokenTypes + */ + public int[] getAcceptableJavadocTokens() { + final int[] defaultJavadocTokens = getDefaultJavadocTokens(); + final int[] copy = new int[defaultJavadocTokens.length]; + System.arraycopy(defaultJavadocTokens, 0, copy, 0, defaultJavadocTokens.length); + return copy; + } + + /** + * The javadoc tokens that this check must be registered for. + * @return the javadoc token set this must be registered for. + * @see JavadocTokenTypes + */ + public int[] getRequiredJavadocTokens() { + return CommonUtils.EMPTY_INT_ARRAY; + } + + /** + * Adds a set of tokens the check is interested in. + * @param strRep the string representation of the tokens interested in + */ + public final void setJavadocTokens(String... strRep) { + javadocTokens.clear(); + for (String str : strRep) { + javadocTokens.add(JavadocUtils.getTokenId(str)); + } + } + + @Override + public void init() { + validateDefaultJavadocTokens(); + if (javadocTokens.isEmpty()) { + for (int id : getDefaultJavadocTokens()) { + javadocTokens.add(id); + } + } + else { + final int[] acceptableJavadocTokens = getAcceptableJavadocTokens(); + Arrays.sort(acceptableJavadocTokens); + for (Integer javadocTokenId : javadocTokens) { + if (Arrays.binarySearch(acceptableJavadocTokens, javadocTokenId) < 0) { + final String message = String.format(Locale.ROOT, "Javadoc Token \"%s\" was " + + "not found in Acceptable javadoc tokens list in check %s", + JavadocUtils.getTokenName(javadocTokenId), getClass().getName()); + throw new IllegalStateException(message); + } + } + } + } + + /** + * Validates that check's required javadoc tokens are subset of default javadoc tokens. + * @throws IllegalStateException when validation of default javadoc tokens fails + */ + private void validateDefaultJavadocTokens() { + if (getRequiredJavadocTokens().length != 0) { + final int[] defaultJavadocTokens = getDefaultJavadocTokens(); + Arrays.sort(defaultJavadocTokens); + for (final int javadocToken : getRequiredJavadocTokens()) { + if (Arrays.binarySearch(defaultJavadocTokens, javadocToken) < 0) { + final String message = String.format(Locale.ROOT, + "Javadoc Token \"%s\" from required javadoc " + + "tokens was not found in default " + + "javadoc tokens list in check %s", + javadocToken, getClass().getName()); + throw new IllegalStateException(message); + } + } + } + } + /** * Called before the starting to process a tree. * @param rootAst @@ -246,11 +330,9 @@ private void processTree(DetailNode root) { * the root of tree for process */ private void walk(DetailNode root) { - final int[] defaultTokenTypes = getDefaultJavadocTokens(); - DetailNode curNode = root; while (curNode != null) { - final boolean waitsForProcessing = shouldBeProcessed(defaultTokenTypes, curNode); + boolean waitsForProcessing = shouldBeProcessed(curNode); if (waitsForProcessing) { visitJavadocToken(curNode); @@ -265,6 +347,9 @@ private void walk(DetailNode root) { toVisit = JavadocUtils.getNextSibling(curNode); if (toVisit == null) { curNode = curNode.getParent(); + if (curNode != null) { + waitsForProcessing = shouldBeProcessed(curNode); + } } } curNode = toVisit; @@ -273,12 +358,11 @@ private void walk(DetailNode root) { /** * Checks whether the current node should be processed by the check. - * @param defaultTokenTypes default token types. * @param curNode current node. * @return true if the current node should be processed by the check. */ - private boolean shouldBeProcessed(int[] defaultTokenTypes, DetailNode curNode) { - return IntStream.of(defaultTokenTypes).anyMatch(i -> i == curNode.getType()); + private boolean shouldBeProcessed(DetailNode curNode) { + return javadocTokens.contains(curNode.getType()); } } diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/checks/javadoc/AtclauseOrderCheck.java b/src/main/java/com/puppycrawl/tools/checkstyle/checks/javadoc/AtclauseOrderCheck.java index 6becb4cd16e..70c7141282d 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/checks/javadoc/AtclauseOrderCheck.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/checks/javadoc/AtclauseOrderCheck.java @@ -130,6 +130,11 @@ public int[] getDefaultJavadocTokens() { }; } + @Override + public int[] getRequiredJavadocTokens() { + return getAcceptableJavadocTokens(); + } + @Override public int[] getAcceptableTokens() { return new int[] {TokenTypes.BLOCK_COMMENT_BEGIN}; diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/checks/javadoc/JavadocParagraphCheck.java b/src/main/java/com/puppycrawl/tools/checkstyle/checks/javadoc/JavadocParagraphCheck.java index 5c3c1ba39b7..d77cef83ff0 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/checks/javadoc/JavadocParagraphCheck.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/checks/javadoc/JavadocParagraphCheck.java @@ -119,6 +119,11 @@ public int[] getDefaultJavadocTokens() { }; } + @Override + public int[] getRequiredJavadocTokens() { + return getAcceptableJavadocTokens(); + } + @Override public int[] getAcceptableTokens() { return new int[] {TokenTypes.BLOCK_COMMENT_BEGIN}; diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/checks/javadoc/JavadocTagContinuationIndentationCheck.java b/src/main/java/com/puppycrawl/tools/checkstyle/checks/javadoc/JavadocTagContinuationIndentationCheck.java index 4a9140f6609..2e7b7998fd9 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/checks/javadoc/JavadocTagContinuationIndentationCheck.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/checks/javadoc/JavadocTagContinuationIndentationCheck.java @@ -72,6 +72,11 @@ public int[] getDefaultJavadocTokens() { return new int[] {JavadocTokenTypes.DESCRIPTION }; } + @Override + public int[] getRequiredJavadocTokens() { + return getAcceptableJavadocTokens(); + } + @Override public int[] getAcceptableTokens() { return new int[] {TokenTypes.BLOCK_COMMENT_BEGIN }; diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/checks/javadoc/SingleLineJavadocCheck.java b/src/main/java/com/puppycrawl/tools/checkstyle/checks/javadoc/SingleLineJavadocCheck.java index 744ae108295..1a314c1372c 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/checks/javadoc/SingleLineJavadocCheck.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/checks/javadoc/SingleLineJavadocCheck.java @@ -100,6 +100,11 @@ public int[] getDefaultJavadocTokens() { }; } + @Override + public int[] getRequiredJavadocTokens() { + return getAcceptableJavadocTokens(); + } + @Override public int[] getAcceptableTokens() { return new int[] {TokenTypes.BLOCK_COMMENT_BEGIN }; diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/checks/javadoc/SummaryJavadocCheck.java b/src/main/java/com/puppycrawl/tools/checkstyle/checks/javadoc/SummaryJavadocCheck.java index 05549818e86..c2414530728 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/checks/javadoc/SummaryJavadocCheck.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/checks/javadoc/SummaryJavadocCheck.java @@ -116,6 +116,11 @@ public int[] getDefaultJavadocTokens() { }; } + @Override + public int[] getRequiredJavadocTokens() { + return getAcceptableJavadocTokens(); + } + @Override public int[] getAcceptableTokens() { return new int[] {TokenTypes.BLOCK_COMMENT_BEGIN }; 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 b2ae65b8837..5aa22d41e88 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 @@ -33,7 +33,9 @@ import java.util.Map; import org.junit.Assert; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import com.puppycrawl.tools.checkstyle.BaseCheckTestSupport; import com.puppycrawl.tools.checkstyle.Checker; @@ -47,6 +49,9 @@ import com.puppycrawl.tools.checkstyle.utils.CommonUtils; public class AbstractJavadocCheckTest extends BaseCheckTestSupport { + @Rule + public final TemporaryFolder temporaryFolder = new TemporaryFolder(); + @Override protected String getPath(String filename) throws IOException { return super.getPath("checks" + File.separator @@ -166,6 +171,64 @@ public void testBlockCommentPositionHasPrivateConstr() throws Exception { TestUtils.assertUtilsClassHasPrivateConstructor(BlockCommentPosition.class); } + @Test + public void testAcceptableTokensFail() + throws Exception { + final DefaultConfiguration checkConfig = + createCheckConfig(TokenIsNotInAcceptablesJavadocCheck.class); + checkConfig.addAttribute("javadocTokens", "RETURN_LITERAL"); + try { + final String[] expected = CommonUtils.EMPTY_STRING_ARRAY; + verify(checkConfig, getPath("InputMain.java"), expected); + Assert.fail("CheckstyleException is expected"); + } + catch (IllegalStateException ex) { + Assert.assertTrue(ex.getMessage().startsWith("Javadoc Token " + + "\"RETURN_LITERAL\" was not found in " + + "Acceptable javadoc tokens list in check")); + } + } + + @Test + public void testAcceptableTokensPass() + throws Exception { + final DefaultConfiguration checkConfig = + createCheckConfig(TokenIsNotInAcceptablesJavadocCheck.class); + checkConfig.addAttribute("javadocTokens", "DEPRECATED_LITERAL"); + + final String[] expected = CommonUtils.EMPTY_STRING_ARRAY; + verify(checkConfig, getPath("InputMain.java"), expected); + } + + @Test + public void testRequiredTokenIsNotInDefaultTokens() throws Exception { + final DefaultConfiguration checkConfig = + createCheckConfig(RequiredTokenIsNotInDefaultsJavadocCheck.class); + final String pathToEmptyFile = temporaryFolder.newFile("file.java").getPath(); + + try { + final String[] expected = CommonUtils.EMPTY_STRING_ARRAY; + verify(checkConfig, pathToEmptyFile, expected); + Assert.fail("CheckstyleException is expected"); + } + catch (IllegalStateException ex) { + Assert.assertTrue(ex.getMessage().startsWith("Javadoc Token \"" + + JavadocTokenTypes.RETURN_LITERAL + "\" from required" + + " javadoc tokens was not found in default javadoc tokens list in check")); + } + } + + @Test + public void testVisitLeaveToken() + throws Exception { + JavadocVisitLeaveCheck.clearCounter(); + final DefaultConfiguration checkConfig = createCheckConfig(JavadocVisitLeaveCheck.class); + final String[] expected = CommonUtils.EMPTY_STRING_ARRAY; + verify(checkConfig, getPath("InputJavadocPosition.java"), expected); + Assert.assertTrue(JavadocVisitLeaveCheck.visitCount > 0); + Assert.assertEquals(JavadocVisitLeaveCheck.visitCount, JavadocVisitLeaveCheck.leaveCount); + } + private static class TempCheck extends AbstractJavadocCheck { @Override @@ -217,4 +280,83 @@ public void visitJavadocToken(DetailNode ast) { javadocsNumber++; } } + + private static class RequiredTokenIsNotInDefaultsJavadocCheck extends AbstractJavadocCheck { + @Override + public int[] getRequiredJavadocTokens() { + return new int[] {JavadocTokenTypes.RETURN_LITERAL}; + } + + @Override + public int[] getDefaultJavadocTokens() { + return new int[] {JavadocTokenTypes.DEPRECATED_LITERAL}; + } + + @Override + public int[] getAcceptableJavadocTokens() { + return CommonUtils.EMPTY_INT_ARRAY; + } + + @Override + public void visitJavadocToken(DetailNode ast) { + // not used + } + } + + private static class TokenIsNotInAcceptablesJavadocCheck extends AbstractJavadocCheck { + @Override + public int[] getRequiredJavadocTokens() { + return new int[] {JavadocTokenTypes.DEPRECATED_LITERAL}; + } + + @Override + public int[] getDefaultJavadocTokens() { + return new int[] {JavadocTokenTypes.DEPRECATED_LITERAL}; + } + + @Override + public int[] getAcceptableJavadocTokens() { + return new int[] {JavadocTokenTypes.DEPRECATED_LITERAL}; + } + + @Override + public void visitJavadocToken(DetailNode ast) { + // not used + } + } + + private static class JavadocVisitLeaveCheck extends AbstractJavadocCheck { + private static int visitCount; + private static int leaveCount; + + static void clearCounter() { + visitCount = 0; + leaveCount = 0; + } + + @Override + public int[] getRequiredJavadocTokens() { + return new int[] {JavadocTokenTypes.CHAR}; + } + + @Override + public int[] getDefaultJavadocTokens() { + return getRequiredJavadocTokens(); + } + + @Override + public int[] getAcceptableJavadocTokens() { + return getRequiredJavadocTokens(); + } + + @Override + public void visitJavadocToken(DetailNode ast) { + visitCount++; + } + + @Override + public void leaveJavadocToken(DetailNode ast) { + leaveCount++; + } + } } diff --git a/src/test/java/com/puppycrawl/tools/checkstyle/internal/CheckUtil.java b/src/test/java/com/puppycrawl/tools/checkstyle/internal/CheckUtil.java index a1971a7f0ab..d680c364631 100644 --- a/src/test/java/com/puppycrawl/tools/checkstyle/internal/CheckUtil.java +++ b/src/test/java/com/puppycrawl/tools/checkstyle/internal/CheckUtil.java @@ -46,6 +46,7 @@ import com.puppycrawl.tools.checkstyle.checks.regexp.RegexpMultilineCheck; import com.puppycrawl.tools.checkstyle.checks.regexp.RegexpSinglelineCheck; import com.puppycrawl.tools.checkstyle.checks.regexp.RegexpSinglelineJavaCheck; +import com.puppycrawl.tools.checkstyle.utils.JavadocUtils; import com.puppycrawl.tools.checkstyle.utils.TokenUtils; public final class CheckUtil { @@ -335,4 +336,42 @@ public static String getTokenText(int[] tokens, int... subtractions) { return result.toString(); } } + + public static String getJavadocTokenText(int[] tokens, int... subtractions) { + final StringBuilder result = new StringBuilder(); + boolean first = true; + + for (int token : tokens) { + boolean found = false; + + for (int subtraction : subtractions) { + if (subtraction == token) { + found = true; + break; + } + } + + if (found) { + continue; + } + + if (first) { + first = false; + } + else { + result.append(", "); + } + + result.append(JavadocUtils.getTokenName(token)); + } + + if (result.length() == 0) { + result.append("empty"); + } + else { + result.append("."); + } + + return result.toString(); + } } diff --git a/src/test/java/com/puppycrawl/tools/checkstyle/internal/XDocsPagesTest.java b/src/test/java/com/puppycrawl/tools/checkstyle/internal/XDocsPagesTest.java index ae4493c6f3a..3b763e4f698 100644 --- a/src/test/java/com/puppycrawl/tools/checkstyle/internal/XDocsPagesTest.java +++ b/src/test/java/com/puppycrawl/tools/checkstyle/internal/XDocsPagesTest.java @@ -59,6 +59,7 @@ import com.puppycrawl.tools.checkstyle.api.AbstractFileSetCheck; import com.puppycrawl.tools.checkstyle.api.CheckstyleException; import com.puppycrawl.tools.checkstyle.api.Configuration; +import com.puppycrawl.tools.checkstyle.checks.javadoc.AbstractJavadocCheck; public class XDocsPagesTest { private static final Path JAVA_SOURCES_DIRECTORY = Paths.get("src/main/java"); @@ -112,6 +113,8 @@ public class XDocsPagesTest { ); private static final Set CHECK_PROPERTIES = getProperties(AbstractCheck.class); + private static final Set JAVADOC_CHECK_PROPERTIES = + getProperties(AbstractJavadocCheck.class); private static final Set FILESET_PROPERTIES = getProperties(AbstractFileSetCheck.class); private static final List UNDOCUMENTED_PROPERTIES = Arrays.asList( @@ -395,9 +398,30 @@ private static void validatePropertySection(String fileName, String sectionName, final Set properties = getProperties(instance.getClass()); final Class clss = instance.getClass(); + fixCapturedProperties(sectionName, instance, clss, properties); + + if (subSection != null) { + Assert.assertTrue(fileName + " section '" + sectionName + + "' should have no properties to show", !properties.isEmpty()); + + validatePropertySectionProperties(fileName, sectionName, subSection, instance, + properties); + } + + Assert.assertTrue(fileName + " section '" + sectionName + "' should show properties: " + + properties, properties.isEmpty()); + } + + private static void fixCapturedProperties(String sectionName, Object instance, Class clss, + Set properties) { // remove global properties that don't need documentation if (hasParentModule(sectionName)) { - properties.removeAll(CHECK_PROPERTIES); + if (AbstractJavadocCheck.class.isAssignableFrom(clss)) { + properties.removeAll(JAVADOC_CHECK_PROPERTIES); + } + else if (AbstractCheck.class.isAssignableFrom(clss)) { + properties.removeAll(CHECK_PROPERTIES); + } } else if (AbstractFileSetCheck.class.isAssignableFrom(clss)) { properties.removeAll(FILESET_PROPERTIES); @@ -427,21 +451,27 @@ else if (AbstractFileSetCheck.class.isAssignableFrom(clss)) { } } - if (subSection != null) { - Assert.assertTrue(fileName + " section '" + sectionName - + "' should have no properties to show", !properties.isEmpty()); + if (AbstractJavadocCheck.class.isAssignableFrom(clss)) { + final AbstractJavadocCheck check = (AbstractJavadocCheck) instance; - validatePropertySectionProperties(fileName, sectionName, subSection, instance, - properties); - } + final int[] acceptableJavadocTokens = check.getAcceptableJavadocTokens(); + Arrays.sort(acceptableJavadocTokens); + final int[] defaultJavadocTokens = check.getDefaultJavadocTokens(); + Arrays.sort(defaultJavadocTokens); + final int[] requiredJavadocTokens = check.getRequiredJavadocTokens(); + Arrays.sort(requiredJavadocTokens); - Assert.assertTrue(fileName + " section '" + sectionName + "' should show properties: " - + properties, properties.isEmpty()); + if (!Arrays.equals(acceptableJavadocTokens, defaultJavadocTokens) + || !Arrays.equals(acceptableJavadocTokens, requiredJavadocTokens)) { + properties.add("javadocTokens"); + } + } } private static void validatePropertySectionProperties(String fileName, String sectionName, Node subSection, Object instance, Set properties) throws Exception { boolean skip = true; + boolean didJavadocTokens = false; boolean didTokens = false; for (Node row : XmlUtil.getChildrenElements(XmlUtil.getFirstChildElement(subSection))) { @@ -461,25 +491,18 @@ private static void validatePropertySectionProperties(String fileName, String se if ("tokens".equals(propertyName)) { final AbstractCheck check = (AbstractCheck) instance; - - Assert.assertEquals(fileName + " section '" + sectionName - + "' should have the basic token description", "tokens to check", columns - .get(1).getTextContent()); - Assert.assertEquals( - fileName + " section '" + sectionName - + "' should have all the acceptable tokens", - "subset of tokens " - + CheckUtil.getTokenText(check.getAcceptableTokens(), - check.getRequiredTokens()), columns.get(2).getTextContent() - .replaceAll("\\s+", " ").trim()); - Assert.assertEquals( - fileName + " section '" + sectionName - + "' should have all the default tokens", - CheckUtil.getTokenText(check.getDefaultTokens(), check.getRequiredTokens()), - columns.get(3).getTextContent().replaceAll("\\s+", " ").trim()); + validatePropertySectionPropertyTokens(fileName, sectionName, check, columns); didTokens = true; } + else if ("javadocTokens".equals(propertyName)) { + final AbstractJavadocCheck check = (AbstractJavadocCheck) instance; + validatePropertySectionPropertyJavadocTokens(fileName, sectionName, check, columns); + didJavadocTokens = true; + } else { + Assert.assertFalse(fileName + " section '" + sectionName + + "' should have javadoc token properties next to last, before tokens", + didJavadocTokens); Assert.assertFalse(fileName + " section '" + sectionName + "' should have a description for " + propertyName, columns.get(1) .getTextContent().trim().isEmpty()); @@ -514,6 +537,43 @@ private static void validatePropertySectionProperties(String fileName, String se } } + private static void validatePropertySectionPropertyTokens(String fileName, String sectionName, + AbstractCheck check, List columns) { + Assert.assertEquals(fileName + " section '" + sectionName + + "' should have the basic token description", "tokens to check", columns.get(1) + .getTextContent()); + Assert.assertEquals( + fileName + " section '" + sectionName + "' should have all the acceptable tokens", + "subset of tokens " + + CheckUtil.getTokenText(check.getAcceptableTokens(), + check.getRequiredTokens()), columns.get(2).getTextContent() + .replaceAll("\\s+", " ").trim()); + Assert.assertEquals(fileName + " section '" + sectionName + + "' should have all the default tokens", + CheckUtil.getTokenText(check.getDefaultTokens(), check.getRequiredTokens()), + columns.get(3).getTextContent().replaceAll("\\s+", " ").trim()); + } + + private static void validatePropertySectionPropertyJavadocTokens(String fileName, + String sectionName, AbstractJavadocCheck check, List columns) { + Assert.assertEquals(fileName + " section '" + sectionName + + "' should have the basic token javadoc description", "javadoc tokens to check", + columns.get(1).getTextContent()); + Assert.assertEquals( + fileName + " section '" + sectionName + + "' should have all the acceptable javadoc tokens", + "subset of javadoc tokens " + + CheckUtil.getJavadocTokenText(check.getAcceptableJavadocTokens(), + check.getRequiredJavadocTokens()), columns.get(2).getTextContent() + .replaceAll("\\s+", " ").trim()); + Assert.assertEquals( + fileName + " section '" + sectionName + + "' should have all the default javadoc tokens", + CheckUtil.getJavadocTokenText(check.getDefaultJavadocTokens(), + check.getRequiredJavadocTokens()), columns.get(3).getTextContent() + .replaceAll("\\s+", " ").trim()); + } + private static String getCheckPropertyExpectedTypeName(Class clss, Object instance, String propertyName) { final String instanceName = instance.getClass().getSimpleName(); diff --git a/src/test/resources/com/puppycrawl/tools/checkstyle/checks/javadoc/InputMain.java b/src/test/resources/com/puppycrawl/tools/checkstyle/checks/javadoc/InputMain.java new file mode 100644 index 00000000000..75c76701230 --- /dev/null +++ b/src/test/resources/com/puppycrawl/tools/checkstyle/checks/javadoc/InputMain.java @@ -0,0 +1,4 @@ +package com.puppycrawl.tools.checkstyle.checks.javadoc; +/** Javadoc */ +public class InputMain { +} diff --git a/src/xdocs/config_javadoc.xml b/src/xdocs/config_javadoc.xml index 125e2d160c4..da4b62cfe6c 100644 --- a/src/xdocs/config_javadoc.xml +++ b/src/xdocs/config_javadoc.xml @@ -1372,6 +1372,33 @@ public boolean isSomething()

+ + + + + + + + + + + + + + +
namedescriptiontypedefault value
javadocTokensjavadoc tokens to checksubset of javadoc tokens + PARAM_LITERAL, + RETURN_LITERAL, + THROWS_LITERAL, + DEPRECATED_LITERAL. + + PARAM_LITERAL, + RETURN_LITERAL, + THROWS_LITERAL, + DEPRECATED_LITERAL. +
+
+

Default configuration that will check @param, @return, diff --git a/src/xdocs/writingjavadocchecks.xml.vm b/src/xdocs/writingjavadocchecks.xml.vm index b6757caabf3..5ae02874661 100644 --- a/src/xdocs/writingjavadocchecks.xml.vm +++ b/src/xdocs/writingjavadocchecks.xml.vm @@ -532,7 +532,43 @@ JAVADOC ->

First

\r\n

Second

[0:0]
- Not implemented yet. See Github Issue #2427. +

+ There are four methods in AbstractJavadocCheck class to control the processed + JavadocTokenTypes - + one setter + + setTokens(), which is used to define a custom set (which is different + from the default one) of the processed JavadocTokenTypes via config file and + three getters, which have to be overridden: + + getDefaultJavadocTokens(), + + getAcceptableJavadocTokens(), + + getRequiredJavadocTokens(). +

+ +
    + +
  • + getDefaultJavadocTokens() - returns a set of JavadocTokenTypes which are processed in + + visitToken() method by default. +
  • + +
  • + getRequiredJavadocTokens() - returns a set of JavadocTokenTypes which Check must be subscribed to for + a valid execution. If the user wants to specify a custom set of JavadocTokenTypes then + this set must contain all the JavadocTokenTypes from RequiredJavadocTokens. +
  • + +
  • + getAcceptableJavadocTokens() - returns a set, which contains all the JavadocTokenTypes that + can be processed by the check. Both DefaultJavadocTokens and RequiredJavadocTokens and any custom + set of JavadocTokenTypes are subsets of AcceptableJavadocTokens. +
  • + +