Skip to content

Commit

Permalink
Issue checkstyle#2427: added customizable javadoc tokens
Browse files Browse the repository at this point in the history
  • Loading branch information
rnveach committed Nov 1, 2016
1 parent dda0b9e commit ad58563
Show file tree
Hide file tree
Showing 13 changed files with 456 additions and 36 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -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 <a href="http://docs.oracle.com/javase/8/docs/technotes/tools/unix/javadoc.html">
* javadoc - The Java API Documentation Generator</a>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -32,14 +35,14 @@
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;

/**
* Base class for Checks that process Javadoc comments.
* @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
Expand Down Expand Up @@ -90,15 +93,18 @@ protected Map<String, ParseStatus> initialValue() {
*/
private final JavadocDetailNodeParser parser = new JavadocDetailNodeParser();

/** The javadoc tokens the check is interested in. */
private final Set<Integer> javadocTokens = new HashSet<>();

/**
* DetailAST node of considered Javadoc comment that is just a block comment
* in Java language syntax tree.
*/
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();
Expand All @@ -110,6 +116,84 @@ protected Map<String, ParseStatus> 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
Expand Down Expand Up @@ -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);
Expand All @@ -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;
Expand All @@ -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());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,11 @@ public int[] getDefaultJavadocTokens() {
};
}

@Override
public int[] getRequiredJavadocTokens() {
return getAcceptableJavadocTokens();
}

@Override
public int[] getAcceptableTokens() {
return new int[] {TokenTypes.BLOCK_COMMENT_BEGIN};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,11 @@ public int[] getDefaultJavadocTokens() {
};
}

@Override
public int[] getRequiredJavadocTokens() {
return getAcceptableJavadocTokens();
}

@Override
public int[] getAcceptableTokens() {
return new int[] {TokenTypes.BLOCK_COMMENT_BEGIN};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,11 @@ public int[] getDefaultJavadocTokens() {
};
}

@Override
public int[] getRequiredJavadocTokens() {
return getAcceptableJavadocTokens();
}

@Override
public int[] getAcceptableTokens() {
return new int[] {TokenTypes.BLOCK_COMMENT_BEGIN };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,11 @@ public int[] getDefaultJavadocTokens() {
};
}

@Override
public int[] getRequiredJavadocTokens() {
return getAcceptableJavadocTokens();
}

@Override
public int[] getAcceptableTokens() {
return new int[] {TokenTypes.BLOCK_COMMENT_BEGIN };
Expand Down

0 comments on commit ad58563

Please sign in to comment.