Issue #49. Added support of single-line and block comments
This commit is contained in:
parent
59aa66c3cc
commit
a24df47caf
8
pom.xml
8
pom.xml
|
|
@ -499,6 +499,14 @@
|
|||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<configLocation>checkstyle_checks.xml</configLocation>
|
||||
<suppressionsFileExpression>checkstyle.suppressions.file</suppressionsFileExpression>
|
||||
<suppressionsLocation>suppressions.xml</suppressionsLocation>
|
||||
<headerLocation>java.header</headerLocation>
|
||||
<propertyExpansion>checkstyle.importcontrol.file=import-control.xml</propertyExpansion>
|
||||
<enableFilesSummary>false</enableFilesSummary>
|
||||
</configuration>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
|
|
|
|||
|
|
@ -21,15 +21,19 @@ package com.puppycrawl.tools.checkstyle;
|
|||
import java.io.File;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.util.AbstractMap.SimpleEntry;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import antlr.CommonHiddenStreamToken;
|
||||
import antlr.RecognitionException;
|
||||
import antlr.Token;
|
||||
import antlr.TokenStreamException;
|
||||
import antlr.TokenStreamHiddenTokenFilter;
|
||||
import antlr.TokenStreamRecognitionException;
|
||||
|
|
@ -61,16 +65,42 @@ import com.puppycrawl.tools.checkstyle.grammars.GeneratedJavaRecognizer;
|
|||
public final class TreeWalker
|
||||
extends AbstractFileSetCheck
|
||||
{
|
||||
/**
|
||||
* State of AST.
|
||||
* Indicates whether tree contains certain nodes.
|
||||
*/
|
||||
private static enum AstState {
|
||||
/**
|
||||
* Ordinary tree.
|
||||
*/
|
||||
ORDINARY,
|
||||
|
||||
/**
|
||||
* AST contains comment nodes.
|
||||
*/
|
||||
WITH_COMMENTS
|
||||
}
|
||||
|
||||
/** default distance between tab stops */
|
||||
private static final int DEFAULT_TAB_WIDTH = 8;
|
||||
|
||||
/** maps from token name to checks */
|
||||
private final Multimap<String, Check> mTokenToChecks =
|
||||
/** maps from token name to ordinary checks */
|
||||
private final Multimap<String, Check> mTokenToOrdinaryChecks =
|
||||
HashMultimap.create();
|
||||
/** all the registered checks */
|
||||
private final Set<Check> mAllChecks = Sets.newHashSet();
|
||||
|
||||
/** maps from token name to comment checks */
|
||||
private final Multimap<String, Check> mTokenToCommentChecks =
|
||||
HashMultimap.create();
|
||||
|
||||
/** registered ordinary checks, that don't use comment nodes */
|
||||
private final Set<Check> mOrdinaryChecks = Sets.newHashSet();
|
||||
|
||||
/** registered comment checks */
|
||||
private final Set<Check> mCommentChecks = Sets.newHashSet();
|
||||
|
||||
/** the distance between tab stops */
|
||||
private int mTabWidth = DEFAULT_TAB_WIDTH;
|
||||
|
||||
/** cache file **/
|
||||
private PropertyCacheFile mCache = new PropertyCacheFile(null, null);
|
||||
|
||||
|
|
@ -83,11 +113,6 @@ public final class TreeWalker
|
|||
/** a factory for creating submodules (i.e. the Checks) */
|
||||
private ModuleFactory mModuleFactory;
|
||||
|
||||
/** controls whether we should use recursive or iterative
|
||||
* algorithm for tree processing.
|
||||
*/
|
||||
private final boolean mRecursive;
|
||||
|
||||
/** logger for debug purpose */
|
||||
private static final Log LOG =
|
||||
LogFactory.getLog("com.puppycrawl.tools.checkstyle.TreeWalker");
|
||||
|
|
@ -98,18 +123,6 @@ public final class TreeWalker
|
|||
public TreeWalker()
|
||||
{
|
||||
setFileExtensions(new String[]{"java"});
|
||||
// Tree walker can use two possible algorithms for
|
||||
// tree processing (iterative and recursive.
|
||||
// Recursive is default for now.
|
||||
final String recursive =
|
||||
System.getProperty("checkstyle.use.recursive.algorithm", "false");
|
||||
mRecursive = "true".equals(recursive);
|
||||
if (mRecursive) {
|
||||
LOG.debug("TreeWalker uses recursive algorithm");
|
||||
}
|
||||
else {
|
||||
LOG.debug("TreeWalker uses iterative algorithm");
|
||||
}
|
||||
}
|
||||
|
||||
/** @param aTabWidth the distance between tab stops */
|
||||
|
|
@ -188,7 +201,14 @@ public final class TreeWalker
|
|||
final FileText text = FileText.fromLines(aFile, aLines);
|
||||
final FileContents contents = new FileContents(text);
|
||||
final DetailAST rootAST = TreeWalker.parse(contents);
|
||||
walk(rootAST, contents);
|
||||
|
||||
getMessageCollector().reset();
|
||||
|
||||
walk(rootAST, contents, AstState.ORDINARY);
|
||||
|
||||
final DetailAST astWithComments = appendHiddenCommentNodes(rootAST);
|
||||
|
||||
walk(astWithComments, contents, AstState.WITH_COMMENTS);
|
||||
}
|
||||
catch (final RecognitionException re) {
|
||||
Utils.getExceptionLogger()
|
||||
|
|
@ -243,6 +263,7 @@ public final class TreeWalker
|
|||
this.getClass(), null));
|
||||
}
|
||||
catch (final Throwable err) {
|
||||
err.printStackTrace();
|
||||
Utils.getExceptionLogger().debug("Throwable occured.", err);
|
||||
getMessageCollector().add(
|
||||
new LocalizedMessage(
|
||||
|
|
@ -295,7 +316,12 @@ public final class TreeWalker
|
|||
for (int element : tokens) {
|
||||
registerCheck(element, aCheck);
|
||||
}
|
||||
mAllChecks.add(aCheck);
|
||||
if (aCheck.isCommentNodesRequired()) {
|
||||
mCommentChecks.add(aCheck);
|
||||
}
|
||||
else {
|
||||
mOrdinaryChecks.add(aCheck);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -315,106 +341,126 @@ public final class TreeWalker
|
|||
*/
|
||||
private void registerCheck(String aToken, Check aCheck)
|
||||
{
|
||||
mTokenToChecks.put(aToken, aCheck);
|
||||
if (aCheck.isCommentNodesRequired()) {
|
||||
mTokenToCommentChecks.put(aToken, aCheck);
|
||||
}
|
||||
else if (TokenTypes.isCommentType(aToken)) {
|
||||
LOG.warn("Check '"
|
||||
+ aCheck.getClass().getName()
|
||||
+ "' waits for comment type token ('"
|
||||
+ aToken
|
||||
+ "') and should override 'isCommentNodesRequred()'"
|
||||
+ " method to return 'true'");
|
||||
}
|
||||
else {
|
||||
mTokenToOrdinaryChecks.put(aToken, aCheck);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Initiates the walk of an AST.
|
||||
* @param aAST the root AST
|
||||
* @param aContents the contents of the file the AST was generated from
|
||||
* @param aContents the contents of the file the AST was generated from.
|
||||
* @param aAstState state of AST.
|
||||
*/
|
||||
private void walk(DetailAST aAST, FileContents aContents)
|
||||
private void walk(DetailAST aAST, FileContents aContents
|
||||
, AstState aAstState)
|
||||
{
|
||||
getMessageCollector().reset();
|
||||
notifyBegin(aAST, aContents);
|
||||
notifyBegin(aAST, aContents, aAstState);
|
||||
|
||||
// empty files are not flagged by javac, will yield aAST == null
|
||||
if (aAST != null) {
|
||||
if (useRecursiveAlgorithm()) {
|
||||
processRec(aAST);
|
||||
}
|
||||
else {
|
||||
processIter(aAST);
|
||||
}
|
||||
processIter(aAST, aAstState);
|
||||
}
|
||||
|
||||
notifyEnd(aAST);
|
||||
notifyEnd(aAST, aAstState);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Notify interested checks that about to begin walking a tree.
|
||||
* @param aRootAST the root of the tree
|
||||
* @param aContents the contents of the file the AST was generated from
|
||||
* Notify checks that we are about to begin walking a tree.
|
||||
* @param aRootAST the root of the tree.
|
||||
* @param aContents the contents of the file the AST was generated from.
|
||||
* @param aAstState state of AST.
|
||||
*/
|
||||
private void notifyBegin(DetailAST aRootAST, FileContents aContents)
|
||||
private void notifyBegin(DetailAST aRootAST, FileContents aContents
|
||||
, AstState aAstState)
|
||||
{
|
||||
for (Check ch : mAllChecks) {
|
||||
Set<Check> checks;
|
||||
|
||||
if (aAstState == AstState.WITH_COMMENTS) {
|
||||
checks = mCommentChecks;
|
||||
}
|
||||
else {
|
||||
checks = mOrdinaryChecks;
|
||||
}
|
||||
|
||||
for (Check ch : checks) {
|
||||
ch.setFileContents(aContents);
|
||||
ch.beginTree(aRootAST);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify checks that finished walking a tree.
|
||||
* @param aRootAST the root of the tree
|
||||
* Notify checks that we have finished walking a tree.
|
||||
* @param aRootAST the root of the tree.
|
||||
* @param aAstState state of AST.
|
||||
*/
|
||||
private void notifyEnd(DetailAST aRootAST)
|
||||
private void notifyEnd(DetailAST aRootAST, AstState aAstState)
|
||||
{
|
||||
for (Check ch : mAllChecks) {
|
||||
Set<Check> checks;
|
||||
|
||||
if (aAstState == AstState.WITH_COMMENTS) {
|
||||
checks = mCommentChecks;
|
||||
}
|
||||
else {
|
||||
checks = mOrdinaryChecks;
|
||||
}
|
||||
|
||||
for (Check ch : checks) {
|
||||
ch.finishTree(aRootAST);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Recursively processes a node calling interested checks at each node.
|
||||
* Uses recursive algorithm.
|
||||
* @param aAST the node to start from
|
||||
* Notify checks that visiting a node.
|
||||
* @param aAST the node to notify for.
|
||||
* @param aAstState state of AST.
|
||||
*/
|
||||
private void processRec(DetailAST aAST)
|
||||
private void notifyVisit(DetailAST aAST, AstState aAstState)
|
||||
{
|
||||
if (aAST == null) {
|
||||
return;
|
||||
Collection<Check> visitors;
|
||||
final String tokenType = TokenTypes.getTokenName(aAST.getType());
|
||||
|
||||
if (aAstState == AstState.WITH_COMMENTS) {
|
||||
visitors = mTokenToCommentChecks.get(tokenType);
|
||||
}
|
||||
else {
|
||||
visitors = mTokenToOrdinaryChecks.get(tokenType);
|
||||
}
|
||||
|
||||
notifyVisit(aAST);
|
||||
|
||||
final DetailAST child = aAST.getFirstChild();
|
||||
if (child != null) {
|
||||
processRec(child);
|
||||
}
|
||||
|
||||
notifyLeave(aAST);
|
||||
|
||||
final DetailAST sibling = aAST.getNextSibling();
|
||||
if (sibling != null) {
|
||||
processRec(sibling);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify interested checks that visiting a node.
|
||||
* @param aAST the node to notify for
|
||||
*/
|
||||
private void notifyVisit(DetailAST aAST)
|
||||
{
|
||||
final Collection<Check> visitors =
|
||||
mTokenToChecks.get(TokenTypes.getTokenName(aAST.getType()));
|
||||
for (Check c : visitors) {
|
||||
c.visitToken(aAST);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify interested checks that leaving a node.
|
||||
*
|
||||
* Notify checks that leaving a node.
|
||||
* @param aAST
|
||||
* the node to notify for
|
||||
* the node to notify for
|
||||
* @param aAstState state of AST.
|
||||
*/
|
||||
private void notifyLeave(DetailAST aAST)
|
||||
private void notifyLeave(DetailAST aAST, AstState aAstState)
|
||||
{
|
||||
final Collection<Check> visitors =
|
||||
mTokenToChecks.get(TokenTypes.getTokenName(aAST.getType()));
|
||||
Collection<Check> visitors;
|
||||
final String tokenType = TokenTypes.getTokenName(aAST.getType());
|
||||
|
||||
if (aAstState == AstState.WITH_COMMENTS) {
|
||||
visitors = mTokenToCommentChecks.get(tokenType);
|
||||
}
|
||||
else {
|
||||
visitors = mTokenToOrdinaryChecks.get(tokenType);
|
||||
}
|
||||
|
||||
for (Check ch : visitors) {
|
||||
ch.leaveToken(aAST);
|
||||
}
|
||||
|
|
@ -432,7 +478,7 @@ public final class TreeWalker
|
|||
* @return the root of the AST
|
||||
*/
|
||||
public static DetailAST parse(FileContents aContents)
|
||||
throws RecognitionException, TokenStreamException
|
||||
throws RecognitionException, TokenStreamException
|
||||
{
|
||||
final String fullText = aContents.getText().getFullText().toString();
|
||||
final Reader sr = new StringReader(fullText);
|
||||
|
|
@ -443,13 +489,13 @@ public final class TreeWalker
|
|||
lexer.setTreatEnumAsKeyword(true);
|
||||
lexer.setTokenObjectClass("antlr.CommonHiddenStreamToken");
|
||||
|
||||
TokenStreamHiddenTokenFilter filter = new TokenStreamHiddenTokenFilter(
|
||||
lexer);
|
||||
final TokenStreamHiddenTokenFilter filter =
|
||||
new TokenStreamHiddenTokenFilter(lexer);
|
||||
filter.hide(TokenTypes.SINGLE_LINE_COMMENT);
|
||||
filter.hide(TokenTypes.BLOCK_COMMENT_BEGIN);
|
||||
|
||||
final GeneratedJavaRecognizer parser =
|
||||
new GeneratedJavaRecognizer(filter);
|
||||
new GeneratedJavaRecognizer(filter);
|
||||
parser.setFilename(aContents.getFilename());
|
||||
parser.setASTNodeClass(DetailAST.class.getName());
|
||||
parser.compilationUnit();
|
||||
|
|
@ -460,35 +506,30 @@ public final class TreeWalker
|
|||
@Override
|
||||
public void destroy()
|
||||
{
|
||||
for (Check c : mAllChecks) {
|
||||
for (Check c : mOrdinaryChecks) {
|
||||
c.destroy();
|
||||
}
|
||||
for (Check c : mCommentChecks) {
|
||||
c.destroy();
|
||||
}
|
||||
mCache.destroy();
|
||||
super.destroy();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if we should use recursive algorithm
|
||||
* for tree processing, false for iterative one.
|
||||
*/
|
||||
private boolean useRecursiveAlgorithm()
|
||||
{
|
||||
return mRecursive;
|
||||
}
|
||||
|
||||
/**
|
||||
* Processes a node calling interested checks at each node.
|
||||
* Uses iterative algorithm.
|
||||
* @param aRoot the root of tree for process
|
||||
* @param aAstState state of AST.
|
||||
*/
|
||||
private void processIter(DetailAST aRoot)
|
||||
private void processIter(DetailAST aRoot, AstState aAstState)
|
||||
{
|
||||
DetailAST curNode = aRoot;
|
||||
while (curNode != null) {
|
||||
notifyVisit(curNode);
|
||||
notifyVisit(curNode, aAstState);
|
||||
DetailAST toVisit = curNode.getFirstChild();
|
||||
while ((curNode != null) && (toVisit == null)) {
|
||||
notifyLeave(curNode);
|
||||
notifyLeave(curNode, aAstState);
|
||||
toVisit = curNode.getNextSibling();
|
||||
if (toVisit == null) {
|
||||
curNode = curNode.getParent();
|
||||
|
|
@ -497,4 +538,206 @@ public final class TreeWalker
|
|||
curNode = toVisit;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Appends comment nodes to existing AST.
|
||||
* It traverses each node in AST, looks for hidden comment tokens
|
||||
* and appends found comment tokens as nodes in AST.
|
||||
* @param aRoot
|
||||
* root of AST.
|
||||
* @return root of AST with comment nodes.
|
||||
*/
|
||||
private static DetailAST appendHiddenCommentNodes(DetailAST aRoot)
|
||||
{
|
||||
DetailAST result = aRoot;
|
||||
DetailAST curNode = aRoot;
|
||||
DetailAST lastNode = aRoot;
|
||||
|
||||
while (curNode != null) {
|
||||
if (isPositionGreater(curNode, lastNode)) {
|
||||
lastNode = curNode;
|
||||
}
|
||||
|
||||
CommonHiddenStreamToken tokenBefore = curNode.getHiddenBefore();
|
||||
DetailAST currentSibling = curNode;
|
||||
while (tokenBefore != null) { // threat multiple comments
|
||||
final DetailAST newCommentNode =
|
||||
createCommentAstFromToken(tokenBefore);
|
||||
|
||||
currentSibling.addPreviousSibling(newCommentNode);
|
||||
|
||||
if (currentSibling == result) {
|
||||
result = newCommentNode;
|
||||
}
|
||||
|
||||
currentSibling = newCommentNode;
|
||||
tokenBefore = tokenBefore.getHiddenBefore();
|
||||
}
|
||||
|
||||
DetailAST toVisit = curNode.getFirstChild();
|
||||
while ((curNode != null) && (toVisit == null)) {
|
||||
toVisit = curNode.getNextSibling();
|
||||
if (toVisit == null) {
|
||||
curNode = curNode.getParent();
|
||||
}
|
||||
}
|
||||
curNode = toVisit;
|
||||
}
|
||||
if (lastNode != null) {
|
||||
CommonHiddenStreamToken tokenAfter = lastNode.getHiddenAfter();
|
||||
DetailAST currentSibling = lastNode;
|
||||
while (tokenAfter != null) {
|
||||
final DetailAST newCommentNode =
|
||||
createCommentAstFromToken(tokenAfter);
|
||||
|
||||
currentSibling.addNextSibling(newCommentNode);
|
||||
|
||||
currentSibling = newCommentNode;
|
||||
tokenAfter = tokenAfter.getHiddenAfter();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if position of first DetailAST is greater than position of
|
||||
* second DetailAST. Position is line number and column number in source
|
||||
* file.
|
||||
* @param aAST1
|
||||
* first DetailAST node.
|
||||
* @param aAst2
|
||||
* second DetailAST node.
|
||||
* @return true if position of aAst1 is greater than position of aAst2.
|
||||
*/
|
||||
private static boolean isPositionGreater(DetailAST aAST1, DetailAST aAst2)
|
||||
{
|
||||
if (aAST1.getLineNo() > aAst2.getLineNo()) {
|
||||
return true;
|
||||
}
|
||||
else if (aAST1.getLineNo() < aAst2.getLineNo()) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
if (aAST1.getColumnNo() > aAst2.getColumnNo()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create comment AST from token. Depending on token type
|
||||
* SINGLE_LINE_COMMENT or BLOCK_COMMENT_BEGIN is created.
|
||||
* @param aToken
|
||||
* Token object.
|
||||
* @return DetailAST of comment node.
|
||||
*/
|
||||
private static DetailAST createCommentAstFromToken(Token aToken)
|
||||
{
|
||||
switch (aToken.getType()) {
|
||||
case TokenTypes.SINGLE_LINE_COMMENT:
|
||||
return createSlCommentNode(aToken);
|
||||
case TokenTypes.BLOCK_COMMENT_BEGIN:
|
||||
return createBlockCommentNode(aToken);
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown comment type");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create single-line comment from token.
|
||||
* @param aToken
|
||||
* Token object.
|
||||
* @return DetailAST with SINGLE_LINE_COMMENT type.
|
||||
*/
|
||||
private static DetailAST createSlCommentNode(Token aToken)
|
||||
{
|
||||
final DetailAST slComment = new DetailAST();
|
||||
slComment.setType(TokenTypes.SINGLE_LINE_COMMENT);
|
||||
slComment.setText("//");
|
||||
|
||||
// column counting begins from 0
|
||||
slComment.setColumnNo(aToken.getColumn() - 1);
|
||||
slComment.setLineNo(aToken.getLine());
|
||||
|
||||
final DetailAST slCommentContent = new DetailAST();
|
||||
slCommentContent.initialize(aToken);
|
||||
slCommentContent.setType(TokenTypes.COMMENT_CONTENT);
|
||||
|
||||
// column counting begins from 0
|
||||
// plus length of '//'
|
||||
slCommentContent.setColumnNo(aToken.getColumn() - 1 + 2);
|
||||
slCommentContent.setLineNo(aToken.getLine());
|
||||
slCommentContent.setText(aToken.getText());
|
||||
|
||||
slComment.addChild(slCommentContent);
|
||||
return slComment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create block comment from token.
|
||||
* @param aToken
|
||||
* Token object.
|
||||
* @return DetailAST with BLOCK_COMMENT type.
|
||||
*/
|
||||
private static DetailAST createBlockCommentNode(Token aToken)
|
||||
{
|
||||
final DetailAST blockComment = new DetailAST();
|
||||
blockComment.initialize(TokenTypes.BLOCK_COMMENT_BEGIN, "/*");
|
||||
|
||||
// column counting begins from 0
|
||||
blockComment.setColumnNo(aToken.getColumn() - 1);
|
||||
blockComment.setLineNo(aToken.getLine());
|
||||
|
||||
final DetailAST blockCommentContent = new DetailAST();
|
||||
blockCommentContent.initialize(aToken);
|
||||
blockCommentContent.setType(TokenTypes.COMMENT_CONTENT);
|
||||
|
||||
// column counting begins from 0
|
||||
// plus length of '/*'
|
||||
blockCommentContent.setColumnNo(aToken.getColumn() - 1 + 2);
|
||||
blockCommentContent.setLineNo(aToken.getLine());
|
||||
blockCommentContent.setText(aToken.getText());
|
||||
|
||||
final DetailAST blockCommentClose = new DetailAST();
|
||||
blockCommentClose.initialize(TokenTypes.BLOCK_COMMENT_END, "*/");
|
||||
|
||||
final Entry<Integer, Integer> linesColumns = countLinesColumns(
|
||||
aToken.getText(), aToken.getLine(), aToken.getColumn());
|
||||
blockCommentClose.setLineNo(linesColumns.getKey());
|
||||
blockCommentClose.setColumnNo(linesColumns.getValue());
|
||||
|
||||
blockComment.addChild(blockCommentContent);
|
||||
blockComment.addChild(blockCommentClose);
|
||||
return blockComment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Count lines and columns (in last line) in text.
|
||||
* @param aText
|
||||
* String.
|
||||
* @param aInitialLinesCnt
|
||||
* initial value of lines counter.
|
||||
* @param aInitialColumnsCnt
|
||||
* initial value of columns counter.
|
||||
* @return entry(pair), first element is lines counter, second - columns
|
||||
* counter.
|
||||
*/
|
||||
private static Entry<Integer, Integer> countLinesColumns(
|
||||
String aText, int aInitialLinesCnt, int aInitialColumnsCnt)
|
||||
{
|
||||
int lines = aInitialLinesCnt;
|
||||
int columns = aInitialColumnsCnt;
|
||||
for (char c : aText.toCharArray()) {
|
||||
switch (c) {
|
||||
case '\n':
|
||||
lines++;
|
||||
columns = 0;
|
||||
break;
|
||||
default:
|
||||
columns++;
|
||||
}
|
||||
}
|
||||
return new SimpleEntry<Integer, Integer>(lines, columns);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,9 +18,10 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
package com.puppycrawl.tools.checkstyle.api;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
/**
|
||||
* The base class for checks.
|
||||
*
|
||||
|
|
@ -52,6 +53,11 @@ public abstract class Check extends AbstractViolationReporter
|
|||
*/
|
||||
private ClassLoader mLoader;
|
||||
|
||||
public boolean isCommentNodesRequired()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default token a check is interested in. Only used if the
|
||||
* configuration for a check does not define the tokens.
|
||||
|
|
|
|||
|
|
@ -78,6 +78,8 @@ public final class DetailAST extends CommonASTWithHiddenTokens
|
|||
setType(da.getType());
|
||||
mLineNo = da.getLineNo();
|
||||
mColumnNo = da.getColumnNo();
|
||||
hiddenAfter = da.getHiddenAfter();
|
||||
hiddenBefore = da.getHiddenBefore();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -102,6 +104,51 @@ public final class DetailAST extends CommonASTWithHiddenTokens
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add previous sibling.
|
||||
* @param aAST
|
||||
* DetailAST object.
|
||||
*/
|
||||
public void addPreviousSibling(DetailAST aAST)
|
||||
{
|
||||
if (aAST != null) {
|
||||
aAST.setParent(mParent);
|
||||
final DetailAST previousSibling = this.getPreviousSibling();
|
||||
|
||||
if (previousSibling != null) {
|
||||
aAST.setPreviousSibling(previousSibling);
|
||||
previousSibling.setNextSibling(aAST);
|
||||
}
|
||||
else if (mParent != null) {
|
||||
mParent.setFirstChild(aAST);
|
||||
}
|
||||
|
||||
aAST.setNextSibling(this);
|
||||
this.setPreviousSibling(aAST);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add next sibling.
|
||||
* @param aAST
|
||||
* DetailAST object.
|
||||
*/
|
||||
public void addNextSibling(DetailAST aAST)
|
||||
{
|
||||
if (aAST != null) {
|
||||
aAST.setParent(mParent);
|
||||
final DetailAST nextSibling = this.getNextSibling();
|
||||
|
||||
if (nextSibling != null) {
|
||||
aAST.setNextSibling(nextSibling);
|
||||
nextSibling.setPreviousSibling(aAST);
|
||||
}
|
||||
|
||||
aAST.setPreviousSibling(this);
|
||||
this.setNextSibling(aAST);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets previous sibling.
|
||||
* @param aAST a previous sibling
|
||||
|
|
@ -174,36 +221,82 @@ public final class DetailAST extends CommonASTWithHiddenTokens
|
|||
if (mLineNo == NOT_INITIALIZED) {
|
||||
// an inner AST that has been initialized
|
||||
// with initialize(String text)
|
||||
final DetailAST child = getFirstChild();
|
||||
final DetailAST sibling = getNextSibling();
|
||||
if (child != null) {
|
||||
return child.getLineNo();
|
||||
DetailAST child = getFirstChild();
|
||||
while (child != null) {
|
||||
// comment node can't be start of any java statement/definition
|
||||
if (TokenTypes.isCommentType(child.getType())) {
|
||||
child = child.getNextSibling();
|
||||
}
|
||||
else {
|
||||
return child.getLineNo();
|
||||
}
|
||||
}
|
||||
else if (sibling != null) {
|
||||
return sibling.getLineNo();
|
||||
|
||||
DetailAST sibling = getNextSibling();
|
||||
while (sibling != null) {
|
||||
// comment node can't be start of any java statement/definition
|
||||
if (TokenTypes.isCommentType(sibling.getType())) {
|
||||
sibling = sibling.getNextSibling();
|
||||
}
|
||||
else {
|
||||
return sibling.getLineNo();
|
||||
}
|
||||
}
|
||||
}
|
||||
return mLineNo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set line number.
|
||||
* @param aLineNo
|
||||
* line number.
|
||||
*/
|
||||
public void setLineNo(int aLineNo)
|
||||
{
|
||||
mLineNo = aLineNo;
|
||||
}
|
||||
|
||||
/** @return the column number **/
|
||||
public int getColumnNo()
|
||||
{
|
||||
if (mColumnNo == NOT_INITIALIZED) {
|
||||
// an inner AST that has been initialized
|
||||
// with initialize(String text)
|
||||
final DetailAST child = getFirstChild();
|
||||
final DetailAST sibling = getNextSibling();
|
||||
if (child != null) {
|
||||
return child.getColumnNo();
|
||||
DetailAST child = getFirstChild();
|
||||
while (child != null) {
|
||||
// comment node can't be start of any java statement/definition
|
||||
if (TokenTypes.isCommentType(child.getType())) {
|
||||
child = child.getNextSibling();
|
||||
}
|
||||
else {
|
||||
return child.getColumnNo();
|
||||
}
|
||||
}
|
||||
else if (sibling != null) {
|
||||
return sibling.getColumnNo();
|
||||
|
||||
DetailAST sibling = getNextSibling();
|
||||
while (sibling != null) {
|
||||
// comment node can't be start of any java statement/definition
|
||||
if (TokenTypes.isCommentType(sibling.getType())) {
|
||||
sibling = sibling.getNextSibling();
|
||||
}
|
||||
else {
|
||||
return sibling.getColumnNo();
|
||||
}
|
||||
}
|
||||
}
|
||||
return mColumnNo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set column number.
|
||||
* @param aColumnNo
|
||||
* column number.
|
||||
*/
|
||||
public void setColumnNo(int aColumnNo)
|
||||
{
|
||||
mColumnNo = aColumnNo;
|
||||
}
|
||||
|
||||
/** @return the last child node */
|
||||
public DetailAST getLastChild()
|
||||
{
|
||||
|
|
@ -308,4 +401,5 @@ public final class DetailAST extends CommonASTWithHiddenTokens
|
|||
{
|
||||
return (DetailAST) super.getFirstChild();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3437,24 +3437,61 @@ public final class TokenTypes
|
|||
public static final int LAMBDA = GeneratedJavaTokenTypes.LAMBDA;
|
||||
|
||||
/**
|
||||
* Begining of single line comment: '//'
|
||||
* Begining of single line comment: '//'.
|
||||
*
|
||||
* <pre>
|
||||
* +--SINLE_LINE_COMMENT
|
||||
* |
|
||||
* +--COMMENT_CONTENT
|
||||
* </pre>
|
||||
*/
|
||||
public static final int SINGLE_LINE_COMMENT = GeneratedJavaTokenTypes.SINGLE_LINE_COMMENT;
|
||||
public static final int SINGLE_LINE_COMMENT =
|
||||
GeneratedJavaTokenTypes.SINGLE_LINE_COMMENT;
|
||||
|
||||
/**
|
||||
* Begining of block comment: '/*'
|
||||
* Begining of block comment: '/*'.
|
||||
*
|
||||
* <pre>
|
||||
* +--BLOCK_COMMENT_BEGIN
|
||||
* |
|
||||
* +--COMMENT_CONTENT
|
||||
* +--BLOCK_COMMENT_END
|
||||
* </pre>
|
||||
*/
|
||||
public static final int BLOCK_COMMENT_BEGIN = GeneratedJavaTokenTypes.BLOCK_COMMENT_BEGIN;
|
||||
public static final int BLOCK_COMMENT_BEGIN =
|
||||
GeneratedJavaTokenTypes.BLOCK_COMMENT_BEGIN;
|
||||
|
||||
/**
|
||||
* End of block comment: '* /'
|
||||
* End of block comment: '* /'.
|
||||
*
|
||||
* <pre>
|
||||
* +--BLOCK_COMMENT_BEGIN
|
||||
* |
|
||||
* +--COMMENT_CONTENT
|
||||
* +--BLOCK_COMMENT_END
|
||||
* </pre>
|
||||
*/
|
||||
public static final int BLOCK_COMMENT_END = GeneratedJavaTokenTypes.BLOCK_COMMENT_END;
|
||||
public static final int BLOCK_COMMENT_END =
|
||||
GeneratedJavaTokenTypes.BLOCK_COMMENT_END;
|
||||
|
||||
/**
|
||||
* Text of single-line or block comment.
|
||||
*
|
||||
*<pre>
|
||||
* +--SINLE_LINE_COMMENT
|
||||
* |
|
||||
* +--COMMENT_CONTENT
|
||||
* </pre>
|
||||
*
|
||||
* <pre>
|
||||
* +--BLOCK_COMMENT_BEGIN
|
||||
* |
|
||||
* +--COMMENT_CONTENT
|
||||
* +--BLOCK_COMMENT_END
|
||||
* </pre>
|
||||
*/
|
||||
public static final int COMMENT_CONTENT = GeneratedJavaTokenTypes.COMMENT_CONTENT;
|
||||
public static final int COMMENT_CONTENT =
|
||||
GeneratedJavaTokenTypes.COMMENT_CONTENT;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// The interesting code goes here
|
||||
|
|
@ -3552,15 +3589,29 @@ public final class TokenTypes
|
|||
}
|
||||
|
||||
/**
|
||||
* Check that argument is SINGLE_LINE_COMMENT or BLOCK_COMMENT_BEGIN
|
||||
* or BLOCK_COMMENT_END or COMMENT_CONTENT.
|
||||
* @param aType token type
|
||||
* @return true if aType is comment token type
|
||||
* Is argument comment-related type (SINGLE_LINE_COMMENT,
|
||||
* BLOCK_COMMENT_BEGIN, BLOCK_COMMENT_END, COMMENT_CONTENT).
|
||||
* @param aType
|
||||
* token type.
|
||||
* @return true if aType is comment-related type.
|
||||
*/
|
||||
public static boolean isCommentType(int aType) {
|
||||
public static boolean isCommentType(int aType)
|
||||
{
|
||||
return aType == TokenTypes.SINGLE_LINE_COMMENT
|
||||
|| aType == TokenTypes.BLOCK_COMMENT_BEGIN
|
||||
|| aType == TokenTypes.BLOCK_COMMENT_END
|
||||
|| aType == TokenTypes.COMMENT_CONTENT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is argument comment-related type name (SINGLE_LINE_COMMENT,
|
||||
* BLOCK_COMMENT_BEGIN, BLOCK_COMMENT_END, COMMENT_CONTENT).
|
||||
* @param aType
|
||||
* token type name.
|
||||
* @return true if aType is comment-related type name.
|
||||
*/
|
||||
public static boolean isCommentType(String aType)
|
||||
{
|
||||
return isCommentType(getTokenId(aType));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -23,6 +23,8 @@ import java.io.File;
|
|||
|
||||
import javax.swing.JFrame;
|
||||
|
||||
import com.puppycrawl.tools.checkstyle.api.DetailAST;
|
||||
|
||||
/**
|
||||
* Entry point for starting the checkstyle GUI.
|
||||
*/
|
||||
|
|
@ -43,4 +45,15 @@ public class Main
|
|||
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
frame.setVisible(true);
|
||||
}
|
||||
|
||||
public static void displayAst(DetailAST ast)
|
||||
{
|
||||
JFrame frame = new JFrame("CheckStyle");
|
||||
final ParseTreeInfoPanel panel = new ParseTreeInfoPanel();
|
||||
frame.getContentPane().add(panel);
|
||||
panel.openAst(ast, frame);
|
||||
frame.setSize(1500, 800);
|
||||
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
frame.setVisible(true);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,6 +29,7 @@ import java.io.IOException;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.TooManyListenersException;
|
||||
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.Action;
|
||||
import javax.swing.JButton;
|
||||
|
|
@ -39,7 +40,9 @@ import javax.swing.JScrollPane;
|
|||
import javax.swing.JTextArea;
|
||||
import javax.swing.SwingUtilities;
|
||||
import javax.swing.filechooser.FileFilter;
|
||||
|
||||
import antlr.ANTLRException;
|
||||
|
||||
import com.puppycrawl.tools.checkstyle.TreeWalker;
|
||||
import com.puppycrawl.tools.checkstyle.api.DetailAST;
|
||||
import com.puppycrawl.tools.checkstyle.api.FileContents;
|
||||
|
|
@ -82,6 +85,26 @@ public class ParseTreeInfoPanel extends JPanel
|
|||
}
|
||||
}
|
||||
|
||||
public void openAst(DetailAST parseTree, final Component aParent)
|
||||
{
|
||||
mParseTreeModel.setParseTree(parseTree);
|
||||
reloadAction.setEnabled(true);
|
||||
|
||||
// clear for each new file
|
||||
getLines2position().clear();
|
||||
// starts line counting at 1
|
||||
getLines2position().add(0);
|
||||
// insert the contents of the file to the text area
|
||||
|
||||
// clean the text area before inserting the lines of the new file
|
||||
if (mJTextArea.getText().length() != 0) {
|
||||
mJTextArea.replaceRange("", 0, mJTextArea.getText().length());
|
||||
}
|
||||
|
||||
// move back to the top of the file
|
||||
mJTextArea.moveCaretPosition(0);
|
||||
}
|
||||
|
||||
private class FileSelectionAction extends AbstractAction
|
||||
{
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -0,0 +1,85 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// checkstyle: Checks Java source code for adherence to a set of rules.
|
||||
// Copyright (C) 2001-2014 Oliver Burn
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
package com.puppycrawl.tools.checkstyle.comments;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import com.puppycrawl.tools.checkstyle.BaseCheckTestSupport;
|
||||
import com.puppycrawl.tools.checkstyle.DefaultConfiguration;
|
||||
import com.puppycrawl.tools.checkstyle.api.Check;
|
||||
import com.puppycrawl.tools.checkstyle.api.DetailAST;
|
||||
import com.puppycrawl.tools.checkstyle.api.TokenTypes;
|
||||
|
||||
public class AllBlockCommentsTest extends BaseCheckTestSupport
|
||||
{
|
||||
protected static final Set<String> allComments = Sets.newLinkedHashSet();
|
||||
|
||||
public static class BlockCommentListenerCheck extends Check
|
||||
{
|
||||
@Override
|
||||
public boolean isCommentNodesRequired()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getDefaultTokens()
|
||||
{
|
||||
return new int[] {TokenTypes.BLOCK_COMMENT_BEGIN};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init()
|
||||
{
|
||||
allComments.addAll(Arrays.asList("0", "1", "2", "3", "4", "5", "6",
|
||||
"7", "8", "9", "10", "11", "12", "13", "14", "15", "16",
|
||||
"17", "18", "19", "20", "\n21\n", "22", "23", "24", "25", "26",
|
||||
"27", "28", "29", "30", "31", "32", "33", "34", "35", "36",
|
||||
"37", "38", " 39 ", "40", "41", "42", "43", "44", "45", "46",
|
||||
"47", "48", "49", "50", "51", "52", "53", "54", "55", "56",
|
||||
"57", "58", "59", "60", "61"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitToken(DetailAST aAST)
|
||||
{
|
||||
String commentContent = aAST.getFirstChild().getText();
|
||||
if (!allComments.remove(commentContent)) {
|
||||
Assert.fail("Unexpected comment: " + commentContent);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAllBlockComments() throws Exception
|
||||
{
|
||||
DefaultConfiguration checkConfig = createCheckConfig(BlockCommentListenerCheck.class);
|
||||
final String[] expected = {};
|
||||
verify(checkConfig, getPath("comments" + File.separator
|
||||
+ "InputFullOfBlockComments.java"), expected);
|
||||
Assert.assertTrue(allComments.isEmpty());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,85 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// checkstyle: Checks Java source code for adherence to a set of rules.
|
||||
// Copyright (C) 2001-2014 Oliver Burn
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
package com.puppycrawl.tools.checkstyle.comments;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import com.puppycrawl.tools.checkstyle.BaseCheckTestSupport;
|
||||
import com.puppycrawl.tools.checkstyle.DefaultConfiguration;
|
||||
import com.puppycrawl.tools.checkstyle.api.Check;
|
||||
import com.puppycrawl.tools.checkstyle.api.DetailAST;
|
||||
import com.puppycrawl.tools.checkstyle.api.TokenTypes;
|
||||
|
||||
public class AllSinglelineCommentsTest extends BaseCheckTestSupport
|
||||
{
|
||||
protected static final Set<String> allComments = Sets.newLinkedHashSet();
|
||||
|
||||
public static class SinglelineCommentListenerCheck extends Check
|
||||
{
|
||||
@Override
|
||||
public boolean isCommentNodesRequired()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getDefaultTokens()
|
||||
{
|
||||
return new int[] {TokenTypes.SINGLE_LINE_COMMENT};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init()
|
||||
{
|
||||
allComments.addAll(Arrays.asList("0\n", "1\n", "2\n", "3\n", "4\n", "5\n", "6\n",
|
||||
"7\n", "8\n", "9\n", "10\n", "11\n", "12\n", "13\n", "14\n", "15\n", "16\n",
|
||||
"17\n", "18\n", "19\n", "20\n", "21\n", "22\n", "23\n", "24\n", "25\n", "26\n",
|
||||
"27\n", "28\n", "29\n", "30\n", "31\n", "32\n", "33\n", "34\n", "35\n", "36\n",
|
||||
"37\n", "38\n", "39\n", "40\n", "41\n", "42\n", "43\n", "44\n", "45\n", "46\n",
|
||||
"47\n", "48\n", "49\n", "50\n", "51\n", "52\n", "53\n", "54\n", "55\n", "56\n",
|
||||
"57\n", "58\n", "59\n", "60\n", "61\n", "62\n", "63"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitToken(DetailAST aAST)
|
||||
{
|
||||
String commentContent = aAST.getFirstChild().getText();
|
||||
if (!allComments.remove(commentContent)) {
|
||||
Assert.fail("Unexpected comment: " + commentContent);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAllBlockComments() throws Exception
|
||||
{
|
||||
DefaultConfiguration checkConfig = createCheckConfig(SinglelineCommentListenerCheck.class);
|
||||
final String[] expected = {};
|
||||
verify(checkConfig, getPath("comments" + File.separator
|
||||
+ "InputFullOfSinglelineComments.java"), expected);
|
||||
Assert.assertTrue(allComments.isEmpty());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,413 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// checkstyle: Checks Java source code for adherence to a set of rules.
|
||||
// Copyright (C) 2001-2014 Oliver Burn
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
package com.puppycrawl.tools.checkstyle.comments;
|
||||
|
||||
import static com.puppycrawl.tools.checkstyle.api.TokenTypes.BLOCK_COMMENT_BEGIN;
|
||||
import static com.puppycrawl.tools.checkstyle.api.TokenTypes.BLOCK_COMMENT_END;
|
||||
import static com.puppycrawl.tools.checkstyle.api.TokenTypes.CLASS_DEF;
|
||||
import static com.puppycrawl.tools.checkstyle.api.TokenTypes.COMMENT_CONTENT;
|
||||
import static com.puppycrawl.tools.checkstyle.api.TokenTypes.IDENT;
|
||||
import static com.puppycrawl.tools.checkstyle.api.TokenTypes.LCURLY;
|
||||
import static com.puppycrawl.tools.checkstyle.api.TokenTypes.LITERAL_CLASS;
|
||||
import static com.puppycrawl.tools.checkstyle.api.TokenTypes.LITERAL_PROTECTED;
|
||||
import static com.puppycrawl.tools.checkstyle.api.TokenTypes.LITERAL_PUBLIC;
|
||||
import static com.puppycrawl.tools.checkstyle.api.TokenTypes.LPAREN;
|
||||
import static com.puppycrawl.tools.checkstyle.api.TokenTypes.METHOD_DEF;
|
||||
import static com.puppycrawl.tools.checkstyle.api.TokenTypes.MODIFIERS;
|
||||
import static com.puppycrawl.tools.checkstyle.api.TokenTypes.OBJBLOCK;
|
||||
import static com.puppycrawl.tools.checkstyle.api.TokenTypes.PARAMETERS;
|
||||
import static com.puppycrawl.tools.checkstyle.api.TokenTypes.RCURLY;
|
||||
import static com.puppycrawl.tools.checkstyle.api.TokenTypes.RPAREN;
|
||||
import static com.puppycrawl.tools.checkstyle.api.TokenTypes.SINGLE_LINE_COMMENT;
|
||||
import static com.puppycrawl.tools.checkstyle.api.TokenTypes.SLIST;
|
||||
import static com.puppycrawl.tools.checkstyle.api.TokenTypes.TYPE;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import com.puppycrawl.tools.checkstyle.BaseCheckTestSupport;
|
||||
import com.puppycrawl.tools.checkstyle.DefaultConfiguration;
|
||||
import com.puppycrawl.tools.checkstyle.api.DetailAST;
|
||||
|
||||
public class CommentsTest extends BaseCheckTestSupport
|
||||
{
|
||||
/*
|
||||
* +--CLASS_DEF [1,0]
|
||||
* |
|
||||
* +--MODIFIERS [1,0]
|
||||
* |
|
||||
* +--LITERAL_PUBLIC [1,0]
|
||||
* +--LITERAL_CLASS [1,7]
|
||||
* +--BLOCK_COMMENT_BEGIN [1,13]
|
||||
* |
|
||||
* +--COMMENT_CONTENT [1,15]
|
||||
* +--BLOCK_COMMENT_END [3,4]
|
||||
* +--IDENT [4,0]
|
||||
* +--OBJBLOCK [5,0]
|
||||
* |
|
||||
* +--LCURLY [5,0]
|
||||
* |
|
||||
* +--SINGLE_LINE_COMMENT [5,2]
|
||||
* |
|
||||
* +--COMMENT_CONTENT [5,4]
|
||||
* +--RCURLY [6,0]
|
||||
*/
|
||||
private static DetailAST buildInput_1()
|
||||
{
|
||||
DetailAST classDef = new DetailAST();
|
||||
classDef.setType(CLASS_DEF);
|
||||
classDef.setText("CLASS_DEF");
|
||||
classDef.setLineNo(1);
|
||||
classDef.setColumnNo(0);
|
||||
|
||||
DetailAST modifiers = new DetailAST();
|
||||
modifiers.setType(MODIFIERS);
|
||||
modifiers.setText("MODIFIERS");
|
||||
modifiers.setLineNo(1);
|
||||
modifiers.setColumnNo(0);
|
||||
|
||||
DetailAST literalPublic = new DetailAST();
|
||||
literalPublic.setType(LITERAL_PUBLIC);
|
||||
literalPublic.setText("public");
|
||||
literalPublic.setLineNo(1);
|
||||
literalPublic.setColumnNo(0);
|
||||
|
||||
DetailAST literalClass = new DetailAST();
|
||||
literalClass.setType(LITERAL_CLASS);
|
||||
literalClass.setText("class");
|
||||
literalClass.setLineNo(1);
|
||||
literalClass.setColumnNo(7);
|
||||
|
||||
DetailAST blockCommentStart = new DetailAST();
|
||||
blockCommentStart.setType(BLOCK_COMMENT_BEGIN);
|
||||
blockCommentStart.setText("/*");
|
||||
blockCommentStart.setLineNo(1);
|
||||
blockCommentStart.setColumnNo(13);
|
||||
|
||||
DetailAST blockCommentContent = new DetailAST();
|
||||
blockCommentContent.setType(COMMENT_CONTENT);
|
||||
blockCommentContent.setText("\n i'mcomment567\n ");
|
||||
blockCommentContent.setLineNo(1);
|
||||
blockCommentContent.setColumnNo(15);
|
||||
|
||||
DetailAST blockCommentEnd = new DetailAST();
|
||||
blockCommentEnd.setType(BLOCK_COMMENT_END);
|
||||
blockCommentEnd.setText("*/");
|
||||
blockCommentEnd.setLineNo(3);
|
||||
blockCommentEnd.setColumnNo(4);
|
||||
|
||||
DetailAST ident = new DetailAST();
|
||||
ident.setType(IDENT);
|
||||
ident.setText("InputCommentsTest");
|
||||
ident.setLineNo(4);
|
||||
ident.setColumnNo(0);
|
||||
|
||||
DetailAST objBlock = new DetailAST();
|
||||
objBlock.setType(OBJBLOCK);
|
||||
objBlock.setText("OBJBLOCK");
|
||||
objBlock.setLineNo(5);
|
||||
objBlock.setColumnNo(0);
|
||||
|
||||
DetailAST lcurly = new DetailAST();
|
||||
lcurly.setType(LCURLY);
|
||||
lcurly.setText("{");
|
||||
lcurly.setLineNo(5);
|
||||
lcurly.setColumnNo(0);
|
||||
|
||||
DetailAST slComment = new DetailAST();
|
||||
slComment.setType(SINGLE_LINE_COMMENT);
|
||||
slComment.setText("//");
|
||||
slComment.setLineNo(5);
|
||||
slComment.setColumnNo(2);
|
||||
|
||||
DetailAST slCommentContent = new DetailAST();
|
||||
slCommentContent.setType(COMMENT_CONTENT);
|
||||
slCommentContent.setText(" comment to left curly brace\n");
|
||||
slCommentContent.setLineNo(5);
|
||||
slCommentContent.setColumnNo(4);
|
||||
|
||||
DetailAST rcurly = new DetailAST();
|
||||
rcurly.setType(RCURLY);
|
||||
rcurly.setText("}");
|
||||
rcurly.setLineNo(6);
|
||||
rcurly.setColumnNo(0);
|
||||
|
||||
classDef.setFirstChild(modifiers);
|
||||
modifiers.setNextSibling(literalClass);
|
||||
literalClass.setNextSibling(blockCommentStart);
|
||||
blockCommentStart.setNextSibling(ident);
|
||||
ident.setNextSibling(objBlock);
|
||||
|
||||
modifiers.setFirstChild(literalPublic);
|
||||
|
||||
blockCommentStart.setFirstChild(blockCommentContent);
|
||||
blockCommentContent.setNextSibling(blockCommentEnd);
|
||||
|
||||
objBlock.setFirstChild(lcurly);
|
||||
lcurly.setNextSibling(slComment);
|
||||
slComment.setNextSibling(rcurly);
|
||||
|
||||
slComment.setFirstChild(slCommentContent);
|
||||
|
||||
return classDef;
|
||||
}
|
||||
|
||||
/*
|
||||
* +--CLASS_DEF [2,0]
|
||||
* |
|
||||
* +--MODIFIERS [2,0]
|
||||
* +--SINGLE_LINE_COMMENT [1,0]
|
||||
* |
|
||||
* +--COMMENT_CONTENT [1,2]
|
||||
* +--LITERAL_CLASS [2,0]
|
||||
* +--IDENT [2,6]
|
||||
* +--OBJBLOCK [3,0]
|
||||
* |
|
||||
* +--LCURLY [3,0]
|
||||
* +--METHOD_DEF [9,4]
|
||||
* |
|
||||
* +--MODIFIERS [9,4]
|
||||
* |
|
||||
* +--BLOCK_COMMENT_BEGIN [4,4]
|
||||
* |
|
||||
* +--COMMENT_CONTENT [4,6]
|
||||
* +--BLOCK_COMMENT_END [8,5]
|
||||
* +--LITERAL_PROTECTED [9,4]
|
||||
* +--TYPE [9,14]
|
||||
* |
|
||||
* +--IDENT [9,14]
|
||||
* +--IDENT [9,21]
|
||||
* +--LPAREN [9,25]
|
||||
* +--PARAMETERS [9,26]
|
||||
* +--RPAREN [9,26]
|
||||
* +--SLIST [10,4]
|
||||
* |
|
||||
* +--RCURLY [11,4]
|
||||
* +--RCURLY [12,0]
|
||||
*/
|
||||
private static DetailAST buildInput_2()
|
||||
{
|
||||
DetailAST classDef = new DetailAST();
|
||||
classDef.setType(CLASS_DEF);
|
||||
classDef.setText("CLASS_DEF");
|
||||
classDef.setLineNo(2);
|
||||
classDef.setColumnNo(0);
|
||||
|
||||
DetailAST modifiers = new DetailAST();
|
||||
modifiers.setType(MODIFIERS);
|
||||
modifiers.setText("MODIFIERS");
|
||||
modifiers.setLineNo(2);
|
||||
modifiers.setColumnNo(0);
|
||||
|
||||
classDef.setFirstChild(modifiers);
|
||||
|
||||
DetailAST slComment = new DetailAST();
|
||||
slComment.setType(SINGLE_LINE_COMMENT);
|
||||
slComment.setText("//");
|
||||
slComment.setLineNo(1);
|
||||
slComment.setColumnNo(0);
|
||||
|
||||
DetailAST slCommentContent = new DetailAST();
|
||||
slCommentContent.setType(COMMENT_CONTENT);
|
||||
slCommentContent.setText(" my class\n");
|
||||
slCommentContent.setLineNo(1);
|
||||
slCommentContent.setColumnNo(2);
|
||||
|
||||
slComment.setFirstChild(slCommentContent);
|
||||
modifiers.setNextSibling(slComment);
|
||||
|
||||
DetailAST literalClass = new DetailAST();
|
||||
literalClass.setType(LITERAL_CLASS);
|
||||
literalClass.setText("class");
|
||||
literalClass.setLineNo(2);
|
||||
literalClass.setColumnNo(0);
|
||||
|
||||
slComment.setNextSibling(literalClass);
|
||||
|
||||
DetailAST identClassName = new DetailAST();
|
||||
identClassName.setType(IDENT);
|
||||
identClassName.setText("A");
|
||||
identClassName.setLineNo(2);
|
||||
identClassName.setColumnNo(6);
|
||||
|
||||
literalClass.setNextSibling(identClassName);
|
||||
|
||||
DetailAST objBlock = new DetailAST();
|
||||
objBlock.setType(OBJBLOCK);
|
||||
objBlock.setText("OBJBLOCK");
|
||||
objBlock.setLineNo(3);
|
||||
objBlock.setColumnNo(0);
|
||||
|
||||
identClassName.setNextSibling(objBlock);
|
||||
|
||||
DetailAST lcurly = new DetailAST();
|
||||
lcurly.setType(LCURLY);
|
||||
lcurly.setText("{");
|
||||
lcurly.setLineNo(3);
|
||||
lcurly.setColumnNo(0);
|
||||
|
||||
objBlock.setFirstChild(lcurly);
|
||||
|
||||
DetailAST methodDef = new DetailAST();
|
||||
methodDef.setType(METHOD_DEF);
|
||||
methodDef.setText("METHOD_DEF");
|
||||
methodDef.setLineNo(9);
|
||||
methodDef.setColumnNo(4);
|
||||
|
||||
lcurly.setNextSibling(methodDef);
|
||||
|
||||
DetailAST rcurly = new DetailAST();
|
||||
rcurly.setType(RCURLY);
|
||||
rcurly.setText("}");
|
||||
rcurly.setLineNo(12);
|
||||
rcurly.setColumnNo(0);
|
||||
|
||||
methodDef.setNextSibling(rcurly);
|
||||
|
||||
DetailAST methodModifiers = new DetailAST();
|
||||
methodModifiers.setType(MODIFIERS);
|
||||
methodModifiers.setText("MODIFIERS");
|
||||
methodModifiers.setLineNo(9);
|
||||
methodModifiers.setColumnNo(4);
|
||||
|
||||
methodDef.setFirstChild(methodModifiers);
|
||||
|
||||
DetailAST methodType = new DetailAST();
|
||||
methodType.setType(TYPE);
|
||||
methodType.setText("TYPE");
|
||||
methodType.setLineNo(9);
|
||||
methodType.setColumnNo(14);
|
||||
|
||||
methodModifiers.setNextSibling(methodType);
|
||||
|
||||
DetailAST identMethodType = new DetailAST();
|
||||
identMethodType.setType(IDENT);
|
||||
identMethodType.setText("String");
|
||||
identMethodType.setLineNo(9);
|
||||
identMethodType.setColumnNo(14);
|
||||
|
||||
methodType.setFirstChild(identMethodType);
|
||||
|
||||
DetailAST identMethodName = new DetailAST();
|
||||
identMethodName.setType(IDENT);
|
||||
identMethodName.setText("line");
|
||||
identMethodName.setLineNo(9);
|
||||
identMethodName.setColumnNo(21);
|
||||
|
||||
methodType.setNextSibling(identMethodName);
|
||||
|
||||
DetailAST lparen = new DetailAST();
|
||||
lparen.setType(LPAREN);
|
||||
lparen.setText("(");
|
||||
lparen.setLineNo(9);
|
||||
lparen.setColumnNo(25);
|
||||
|
||||
identMethodName.setNextSibling(lparen);
|
||||
|
||||
DetailAST parameters = new DetailAST();
|
||||
parameters.setType(PARAMETERS);
|
||||
parameters.setText("PARAMETERS");
|
||||
parameters.setLineNo(9);
|
||||
parameters.setColumnNo(26);
|
||||
|
||||
lparen.setNextSibling(parameters);
|
||||
|
||||
DetailAST rparen = new DetailAST();
|
||||
rparen.setType(RPAREN);
|
||||
rparen.setText(")");
|
||||
rparen.setLineNo(9);
|
||||
rparen.setColumnNo(26);
|
||||
|
||||
parameters.setNextSibling(rparen);
|
||||
|
||||
DetailAST slist = new DetailAST();
|
||||
slist.setType(SLIST);
|
||||
slist.setText("{");
|
||||
slist.setLineNo(10);
|
||||
slist.setColumnNo(4);
|
||||
|
||||
rparen.setNextSibling(slist);
|
||||
|
||||
DetailAST methodRcurly = new DetailAST();
|
||||
methodRcurly.setType(RCURLY);
|
||||
methodRcurly.setText("}");
|
||||
methodRcurly.setLineNo(11);
|
||||
methodRcurly.setColumnNo(4);
|
||||
|
||||
slist.setFirstChild(methodRcurly);
|
||||
|
||||
DetailAST blockCommentStart = new DetailAST();
|
||||
blockCommentStart.setType(BLOCK_COMMENT_BEGIN);
|
||||
blockCommentStart.setText("/*");
|
||||
blockCommentStart.setLineNo(4);
|
||||
blockCommentStart.setColumnNo(4);
|
||||
|
||||
DetailAST blockCommentContent = new DetailAST();
|
||||
blockCommentContent.setType(COMMENT_CONTENT);
|
||||
blockCommentContent.setText("*\n"
|
||||
+ " * Lines <b>method</b>.\n"
|
||||
+ " * \n"
|
||||
+ " * @return string.\n"
|
||||
+ " ");
|
||||
blockCommentContent.setLineNo(4);
|
||||
blockCommentContent.setColumnNo(6);
|
||||
|
||||
blockCommentStart.setFirstChild(blockCommentContent);
|
||||
|
||||
DetailAST blockCommentEnd = new DetailAST();
|
||||
blockCommentEnd.setType(BLOCK_COMMENT_END);
|
||||
blockCommentEnd.setText("*/");
|
||||
blockCommentEnd.setLineNo(8);
|
||||
blockCommentEnd.setColumnNo(5);
|
||||
|
||||
blockCommentContent.setNextSibling(blockCommentEnd);
|
||||
methodModifiers.setFirstChild(blockCommentStart);
|
||||
|
||||
DetailAST literalProtected = new DetailAST();
|
||||
literalProtected.setType(LITERAL_PROTECTED);
|
||||
literalProtected.setText("protected");
|
||||
literalProtected.setLineNo(9);
|
||||
literalProtected.setColumnNo(4);
|
||||
|
||||
blockCommentStart.setNextSibling(literalProtected);
|
||||
|
||||
return classDef;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCompareExpectedTreeWithInput_1() throws Exception
|
||||
{
|
||||
DefaultConfiguration checkConfig = createCheckConfig(CompareTreesWithComments.class);
|
||||
CompareTreesWithComments.expectedTree = buildInput_1();
|
||||
final String[] expected = {};
|
||||
verify(checkConfig, getPath("comments" + File.separator
|
||||
+ "InputCommentsTest_1.java"), expected);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCompareExpectedTreeWithInput_2() throws Exception
|
||||
{
|
||||
DefaultConfiguration checkConfig = createCheckConfig(CompareTreesWithComments.class);
|
||||
CompareTreesWithComments.expectedTree = buildInput_2();
|
||||
final String[] expected = {};
|
||||
verify(checkConfig, getPath("comments" + File.separator
|
||||
+ "InputCommentsTest_2.java"), expected);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,67 @@
|
|||
package com.puppycrawl.tools.checkstyle.comments;
|
||||
|
||||
import org.junit.Assert;
|
||||
|
||||
import com.puppycrawl.tools.checkstyle.api.Check;
|
||||
import com.puppycrawl.tools.checkstyle.api.DetailAST;
|
||||
|
||||
public class CompareTreesWithComments extends Check
|
||||
{
|
||||
protected static DetailAST expectedTree;
|
||||
|
||||
@Override
|
||||
public boolean isCommentNodesRequired()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] getDefaultTokens()
|
||||
{
|
||||
return new int[]{};
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beginTree(DetailAST aRootAST)
|
||||
{
|
||||
Assert.assertTrue(isAstEquals(expectedTree, aRootAST));
|
||||
}
|
||||
|
||||
private boolean isAstEquals(DetailAST expected, DetailAST actual)
|
||||
{
|
||||
boolean result = false;
|
||||
if (expected == actual) {
|
||||
result = true;
|
||||
}
|
||||
else if (actual == null || expected == null) {
|
||||
result = false;
|
||||
} else {
|
||||
if (expected.getType() == actual.getType()
|
||||
&& expected.getLineNo() == actual.getLineNo()
|
||||
&& expected.getColumnNo() == actual.getColumnNo())
|
||||
{
|
||||
if (expected.getText() == null) {
|
||||
result = actual.getText() == null;
|
||||
}
|
||||
else if (expected.getText().equals(actual.getText())) {
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (result) {
|
||||
DetailAST childExpected = expected.getFirstChild();
|
||||
DetailAST childActual = actual.getFirstChild();
|
||||
result = isAstEquals(childExpected, childActual);
|
||||
if (result) {
|
||||
DetailAST nextSiblingExpected = expected.getNextSibling();
|
||||
DetailAST nextSiblingActual = actual.getNextSibling();
|
||||
result = isAstEquals(nextSiblingExpected, nextSiblingActual);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!result) {
|
||||
System.out.println("Expected: " + expected + " | Actual: " + actual);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
public class /*
|
||||
i'mcomment567
|
||||
*/
|
||||
InputCommentsTest
|
||||
{ // comment to left curly brace
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
// my class
|
||||
class A
|
||||
{
|
||||
/**
|
||||
* Lines <b>method</b>.
|
||||
*
|
||||
* @return string.
|
||||
*/
|
||||
protected String line()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
/*0*//*1*/package/*2*/ com/*3*/./*4*/puppycrawl/*5*/./*6*/tools/*7*/./*8*/checkstyle/*9*/./*10*/javadoc/*11*/;/*12*/
|
||||
/*13*/
|
||||
/*14*/public/*15*/ class /*16*/InputFullOfBlockComments /*49*/{/*17*/
|
||||
/*18*/
|
||||
/*19*/public/*20*/ static/*
|
||||
21
|
||||
*/ String/*22*/ main/*23*/(/*24*/String/*25*/[/*26*/]/*27*/ args/*28*/)/*29*/ {/*30*/
|
||||
/*31*/String /*32*/line /*33*/= /*34*/"/*I'm NOT comment*/blabla"/*35*/;/*36*/
|
||||
/*37*/System/*38*/./* 39 */out/*40*/./*41*/println/*42*/(/*43*/line/*44*/)/*45*/;/*46*/
|
||||
/*50*/for/*51*/ (/*52*/Integer/*53*/ i/*54*/:/*55*/ array/*56*/)/*57*/ {/*58*/
|
||||
/*59*/
|
||||
}/*60*/
|
||||
}/*47*/
|
||||
}/*48*/
|
||||
/*61*/
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
//0
|
||||
package//1
|
||||
com//2
|
||||
.//3
|
||||
puppycrawl//4
|
||||
.//5
|
||||
tools//6
|
||||
.//7
|
||||
checkstyle//8
|
||||
.//9
|
||||
checks//10
|
||||
.//11
|
||||
javadoc//12
|
||||
;//13
|
||||
//14
|
||||
public//15
|
||||
class//16
|
||||
InputFullOfSinglelineComments//17
|
||||
{//18
|
||||
public//19
|
||||
static//20
|
||||
void//21
|
||||
main//22
|
||||
(//23
|
||||
String//24
|
||||
[//25
|
||||
]//26
|
||||
args//27
|
||||
)//28
|
||||
{//29
|
||||
for//30
|
||||
(//31
|
||||
int//32
|
||||
i//33
|
||||
=//34
|
||||
0//35
|
||||
;//36
|
||||
i//37
|
||||
<=//38
|
||||
10//39
|
||||
;//40
|
||||
i++//41
|
||||
)//42
|
||||
{//43
|
||||
String//44
|
||||
line//45
|
||||
=//46
|
||||
i//47
|
||||
+//48
|
||||
""//49
|
||||
;//50
|
||||
System//51
|
||||
.//52
|
||||
out//53
|
||||
.//54
|
||||
println//55
|
||||
(//56
|
||||
line//57
|
||||
)//58
|
||||
;//59
|
||||
}//60
|
||||
}//61
|
||||
}//62
|
||||
//63
|
||||
|
|
@ -50,4 +50,7 @@
|
|||
<suppress checks="." files=".*[\\/]grammars[\\/]Generated[a-zA-Z]*\.java"/>
|
||||
<suppress checks="." files=".*[\\/]grammars[\\/]Generated[a-zA-Z]*\.java"/>
|
||||
<suppress checks="." files=".*[\\/]checkstyle[\\/]gui[\\/]"/>
|
||||
|
||||
<!-- Methods that build fake AST are very long-->
|
||||
<suppress checks="MethodLength" files="src[\\/]test[\\/]java[\\/]com[\\/]puppycrawl[\\/]tools[\\/]checkstyle[\\/]comments[\\/]CommentsTest\.java"/>
|
||||
</suppressions>
|
||||
|
|
|
|||
Loading…
Reference in New Issue