diff --git a/config/suppressions.xml b/config/suppressions.xml
index 61ee66063..70ab69be3 100644
--- a/config/suppressions.xml
+++ b/config/suppressions.xml
@@ -140,7 +140,7 @@
-
+
@@ -161,5 +161,6 @@
lines="105, 143, 174"/>
-
+
+
diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/AstTreeStringPrinter.java b/src/main/java/com/puppycrawl/tools/checkstyle/AstTreeStringPrinter.java
index 27c761412..92617bc75 100644
--- a/src/main/java/com/puppycrawl/tools/checkstyle/AstTreeStringPrinter.java
+++ b/src/main/java/com/puppycrawl/tools/checkstyle/AstTreeStringPrinter.java
@@ -45,6 +45,9 @@ public final class AstTreeStringPrinter {
/** Tab pattern. */
private static final Pattern TAB = Pattern.compile("\t");
+ /** OS specific line separator. */
+ private static final String LINE_SEPARATOR = System.getProperty("line.separator");
+
/** Prevent instances. */
private AstTreeStringPrinter() {
// no code
@@ -53,12 +56,14 @@ public final class AstTreeStringPrinter {
/**
* Parse a file and print the parse tree.
* @param file the file to print.
+ * @param withComments true to include comments to AST
* @return the AST of the file in String form.
* @throws IOException if the file could not be read.
* @throws CheckstyleException if the file is not a Java source.
*/
- public static String printFileAst(File file) throws IOException, CheckstyleException {
- return printTree(parseFile(file));
+ public static String printFileAst(File file, boolean withComments)
+ throws IOException, CheckstyleException {
+ return printTree(parseFile(file, withComments));
}
/**
@@ -73,7 +78,8 @@ public final class AstTreeStringPrinter {
messageBuilder.append(getIndentation(node))
.append(TokenUtils.getTokenName(node.getType())).append(" -> ")
.append(excapeAllControlChars(node.getText())).append(" [")
- .append(node.getLineNo()).append(':').append(node.getColumnNo()).append("]\n")
+ .append(node.getLineNo()).append(':').append(node.getColumnNo()).append(']')
+ .append(LINE_SEPARATOR)
.append(printTree(node.getFirstChild()));
node = node.getNextSibling();
}
@@ -127,16 +133,24 @@ public final class AstTreeStringPrinter {
/**
* Parse a file and return the parse tree.
* @param file the file to parse.
+ * @param withComments true to include comment nodes to the tree
* @return the root node of the parse tree.
* @throws IOException if the file could not be read.
* @throws CheckstyleException if the file is not a Java source.
*/
- private static DetailAST parseFile(File file) throws IOException, CheckstyleException {
+ private static DetailAST parseFile(File file, boolean withComments)
+ throws IOException, CheckstyleException {
final FileText text = new FileText(file.getAbsoluteFile(),
System.getProperty("file.encoding", "UTF-8"));
final FileContents contents = new FileContents(text);
+ final DetailAST result;
try {
- return TreeWalker.parse(contents);
+ if (withComments) {
+ result = TreeWalker.parseWithComments(contents);
+ }
+ else {
+ result = TreeWalker.parse(contents);
+ }
}
catch (RecognitionException | TokenStreamException ex) {
final String exceptionMsg = String.format(Locale.ROOT,
@@ -144,5 +158,7 @@ public final class AstTreeStringPrinter {
ex.getClass().getSimpleName(), file.getPath());
throw new CheckstyleException(exceptionMsg, ex);
}
+
+ return result;
}
}
diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/Main.java b/src/main/java/com/puppycrawl/tools/checkstyle/Main.java
index bfc7f3eeb..811a19f5b 100644
--- a/src/main/java/com/puppycrawl/tools/checkstyle/Main.java
+++ b/src/main/java/com/puppycrawl/tools/checkstyle/Main.java
@@ -49,6 +49,9 @@ import com.puppycrawl.tools.checkstyle.utils.CommonUtils;
*
**/
public final class Main {
+ /** Width of CLI help option. */
+ private static final int HELP_WIDTH = 100;
+
/** Exit code returned when execution finishes with {@link CheckstyleException}. */
private static final int EXIT_WITH_CHECKSTYLE_EXCEPTION_CODE = -2;
@@ -70,6 +73,15 @@ public final class Main {
/** Name for the option 't'. */
private static final String OPTION_T_NAME = "t";
+ /** Name for the option '--tree'. */
+ private static final String OPTION_TREE_NAME = "tree";
+
+ /** Name for the option '-T'. */
+ private static final String OPTION_CAPITAL_T_NAME = "T";
+
+ /** Name for the option '--treeWithComments'. */
+ private static final String OPTION_TREE_COMMENT_NAME = "treeWithComments";
+
/** Name for 'xml' format. */
private static final String XML_FORMAT_NAME = "xml";
@@ -120,11 +132,15 @@ public final class Main {
else {
// create config helper object
final CliOptions config = convertCliToPojo(commandLine, filesToProcess);
-
if (commandLine.hasOption(OPTION_T_NAME)) {
// print AST
final File file = config.files.get(0);
- final String stringAst = AstTreeStringPrinter.printFileAst(file);
+ final String stringAst = AstTreeStringPrinter.printFileAst(file, false);
+ System.out.print(stringAst);
+ }
+ else if (commandLine.hasOption(OPTION_CAPITAL_T_NAME)) {
+ final File file = config.files.get(0);
+ final String stringAst = AstTreeStringPrinter.printFileAst(file, true);
System.out.print(stringAst);
}
else {
@@ -188,7 +204,7 @@ public final class Main {
result.add("Files to process must be specified, found 0.");
}
// ensure there is no conflicting options
- else if (cmdLine.hasOption(OPTION_T_NAME)) {
+ else if (cmdLine.hasOption(OPTION_T_NAME) || cmdLine.hasOption(OPTION_CAPITAL_T_NAME)) {
if (cmdLine.hasOption(OPTION_C_NAME) || cmdLine.hasOption(OPTION_P_NAME)
|| cmdLine.hasOption(OPTION_F_NAME) || cmdLine.hasOption(OPTION_O_NAME)) {
result.add("Option '-t' cannot be used with other options.");
@@ -430,6 +446,7 @@ public final class Main {
/** Prints the usage information. **/
private static void printUsage() {
final HelpFormatter formatter = new HelpFormatter();
+ formatter.setWidth(HELP_WIDTH);
formatter.printHelp(String.format("java %s [options] -c file...",
Main.class.getName()), buildOptions());
}
@@ -447,7 +464,10 @@ public final class Main {
"Sets the output format. (%s|%s). Defaults to %s",
PLAIN_FORMAT_NAME, XML_FORMAT_NAME, PLAIN_FORMAT_NAME));
options.addOption(OPTION_V_NAME, false, "Print product version and exit");
- options.addOption(OPTION_T_NAME, false, "Print Abstract Syntax Tree(AST) of the file");
+ options.addOption(OPTION_T_NAME, OPTION_TREE_NAME, false,
+ "Print Abstract Syntax Tree(AST) of the file");
+ options.addOption(OPTION_CAPITAL_T_NAME, OPTION_TREE_COMMENT_NAME, false,
+ "Print Abstract Syntax Tree(AST) of the file including comments");
return options;
}
diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/TreeWalker.java b/src/main/java/com/puppycrawl/tools/checkstyle/TreeWalker.java
index 958aeb648..54cc0aeef 100755
--- a/src/main/java/com/puppycrawl/tools/checkstyle/TreeWalker.java
+++ b/src/main/java/com/puppycrawl/tools/checkstyle/TreeWalker.java
@@ -443,6 +443,18 @@ public final class TreeWalker
return (DetailAST) parser.getAST();
}
+ /**
+ * Parses Java source file. Result AST contains comment nodes.
+ * @param contents source file content
+ * @return DetailAST tree
+ * @throws RecognitionException if parser failed
+ * @throws TokenStreamException if lexer failed
+ */
+ public static DetailAST parseWithComments(FileContents contents)
+ throws RecognitionException, TokenStreamException {
+ return appendHiddenCommentNodes(parse(contents));
+ }
+
@Override
public void destroy() {
for (AbstractCheck check : ordinaryChecks) {
diff --git a/src/test/java/com/puppycrawl/tools/checkstyle/AstTreeStringPrinterTest.java b/src/test/java/com/puppycrawl/tools/checkstyle/AstTreeStringPrinterTest.java
index 9b12cab99..0a20ef2e6 100644
--- a/src/test/java/com/puppycrawl/tools/checkstyle/AstTreeStringPrinterTest.java
+++ b/src/test/java/com/puppycrawl/tools/checkstyle/AstTreeStringPrinterTest.java
@@ -23,8 +23,11 @@ import static com.puppycrawl.tools.checkstyle.internal.TestUtils.assertUtilsClas
import java.io.File;
+import org.junit.Assert;
import org.junit.Test;
+import com.google.common.base.Charsets;
+import com.google.common.io.Files;
import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
public class AstTreeStringPrinterTest {
@@ -33,6 +36,10 @@ public class AstTreeStringPrinterTest {
return "src/test/resources-noncompilable/com/puppycrawl/tools/checkstyle/" + filename;
}
+ private static String getPath(String filename) {
+ return "src/test/resources/com/puppycrawl/tools/checkstyle/astprinter/" + filename;
+ }
+
@Test
public void testIsProperUtilsClass() throws ReflectiveOperationException {
assertUtilsClassHasPrivateConstructor(AstTreeStringPrinter.class);
@@ -41,6 +48,26 @@ public class AstTreeStringPrinterTest {
@Test(expected = CheckstyleException.class)
public void testParseFileThrowable() throws Exception {
AstTreeStringPrinter.printFileAst(
- new File(getNonCompilablePath("InputAstTreeStringPrinter.java")));
+ new File(getNonCompilablePath("InputAstTreeStringPrinter.java")), false);
+ }
+
+ @Test
+ public void testParseFile() throws Exception {
+ final String actual = AstTreeStringPrinter.printFileAst(
+ new File(getPath("InputAstTreeStringPrinterComments.java")), false);
+ final String expected = Files.toString(new File(
+ getPath("expectedInputAstTreeStringPrinter.txt")), Charsets.UTF_8);
+ Assert.assertEquals(expected, actual);
+ }
+
+ @Test
+ public void testParseFileWithComments() throws Exception {
+ final String actual = AstTreeStringPrinter.printFileAst(
+ new File(getPath("InputAstTreeStringPrinterComments.java")), true)
+ .replaceAll("\\\\r\\\\n", "\\\\n");
+ final String expected = Files.toString(new File(
+ getPath("expectedInputAstTreeStringPrinterComments.txt")), Charsets.UTF_8)
+ .replaceAll("\\\\r\\\\n", "\\\\n");
+ Assert.assertEquals(expected, actual);
}
}
diff --git a/src/test/java/com/puppycrawl/tools/checkstyle/MainTest.java b/src/test/java/com/puppycrawl/tools/checkstyle/MainTest.java
index cbdbeaa50..ffc979ce3 100644
--- a/src/test/java/com/puppycrawl/tools/checkstyle/MainTest.java
+++ b/src/test/java/com/puppycrawl/tools/checkstyle/MainTest.java
@@ -96,14 +96,17 @@ public class MainTest {
@Override
public void checkAssertion() {
final String usage = String.format(Locale.ROOT, "Unrecognized option: -w%n"
- + "usage: java com.puppycrawl.tools.checkstyle.Main [options] -c %n"
- + " file...%n"
- + " -c Sets the check configuration file to use.%n"
- + " -f Sets the output format. (plain|xml). Defaults to plain%n"
- + " -o Sets the output file. Defaults to stdout%n"
- + " -p Loads the properties file%n"
- + " -t Print Abstract Syntax Tree(AST) of the file%n"
- + " -v Print product version and exit%n");
+ + "usage: java com.puppycrawl.tools.checkstyle.Main [options] -c "
+ + " file...%n"
+ + " -c Sets the check configuration file to use.%n"
+ + " -f Sets the output format. (plain|xml). Defaults to"
+ + " plain%n"
+ + " -o Sets the output file. Defaults to stdout%n"
+ + " -p Loads the properties file%n"
+ + " -t,--tree Print Abstract Syntax Tree(AST) of the file%n"
+ + " -T,--treeWithComments Print Abstract Syntax Tree(AST) of the file"
+ + " including comments%n"
+ + " -v Print product version and exit%n");
assertEquals(usage, systemOut.getLog());
assertEquals("", systemErr.getLog());
@@ -647,31 +650,31 @@ public class MainTest {
@Test
public void testPrintTreeOption() throws Exception {
- final String expected = "PACKAGE_DEF -> package [1:0]\n"
- + "|--ANNOTATIONS -> ANNOTATIONS [1:28]\n"
- + "|--DOT -> . [1:28]\n"
- + "| |--DOT -> . [1:22]\n"
- + "| | |--DOT -> . [1:11]\n"
- + "| | | |--IDENT -> com [1:8]\n"
- + "| | | `--IDENT -> puppycrawl [1:12]\n"
- + "| | `--IDENT -> tools [1:23]\n"
- + "| `--IDENT -> checkstyle [1:29]\n"
- + "`--SEMI -> ; [1:39]\n"
- + "CLASS_DEF -> CLASS_DEF [3:0]\n"
- + "|--MODIFIERS -> MODIFIERS [3:0]\n"
- + "| `--LITERAL_PUBLIC -> public [3:0]\n"
- + "|--LITERAL_CLASS -> class [3:7]\n"
- + "|--IDENT -> InputMain [3:13]\n"
- + "`--OBJBLOCK -> OBJBLOCK [3:23]\n"
- + " |--LCURLY -> { [3:23]\n"
- + " `--RCURLY -> } [4:0]\n"
- + "CLASS_DEF -> CLASS_DEF [5:0]\n"
- + "|--MODIFIERS -> MODIFIERS [5:0]\n"
- + "|--LITERAL_CLASS -> class [5:0]\n"
- + "|--IDENT -> InputMainInner [5:6]\n"
- + "`--OBJBLOCK -> OBJBLOCK [5:21]\n"
- + " |--LCURLY -> { [5:21]\n"
- + " `--RCURLY -> } [6:0]\n";
+ final String expected = String.format(Locale.ROOT, "PACKAGE_DEF -> package [1:0]%n"
+ + "|--ANNOTATIONS -> ANNOTATIONS [1:28]%n"
+ + "|--DOT -> . [1:28]%n"
+ + "| |--DOT -> . [1:22]%n"
+ + "| | |--DOT -> . [1:11]%n"
+ + "| | | |--IDENT -> com [1:8]%n"
+ + "| | | `--IDENT -> puppycrawl [1:12]%n"
+ + "| | `--IDENT -> tools [1:23]%n"
+ + "| `--IDENT -> checkstyle [1:29]%n"
+ + "`--SEMI -> ; [1:39]%n"
+ + "CLASS_DEF -> CLASS_DEF [3:0]%n"
+ + "|--MODIFIERS -> MODIFIERS [3:0]%n"
+ + "| `--LITERAL_PUBLIC -> public [3:0]%n"
+ + "|--LITERAL_CLASS -> class [3:7]%n"
+ + "|--IDENT -> InputMain [3:13]%n"
+ + "`--OBJBLOCK -> OBJBLOCK [3:23]%n"
+ + " |--LCURLY -> { [3:23]%n"
+ + " `--RCURLY -> } [4:0]%n"
+ + "CLASS_DEF -> CLASS_DEF [5:0]%n"
+ + "|--MODIFIERS -> MODIFIERS [5:0]%n"
+ + "|--LITERAL_CLASS -> class [5:0]%n"
+ + "|--IDENT -> InputMainInner [5:6]%n"
+ + "`--OBJBLOCK -> OBJBLOCK [5:21]%n"
+ + " |--LCURLY -> { [5:21]%n"
+ + " `--RCURLY -> } [6:0]%n");
exit.checkAssertionAfterwards(new Assertion() {
@Override
@@ -683,6 +686,47 @@ public class MainTest {
Main.main("-t", getPath("InputMain.java"));
}
+ @Test
+ public void testPrintTreeCommentsOption() throws Exception {
+ final String expected = String.format(Locale.ROOT, "PACKAGE_DEF -> package [1:0]%n"
+ + "|--ANNOTATIONS -> ANNOTATIONS [1:28]%n"
+ + "|--DOT -> . [1:28]%n"
+ + "| |--DOT -> . [1:22]%n"
+ + "| | |--DOT -> . [1:11]%n"
+ + "| | | |--IDENT -> com [1:8]%n"
+ + "| | | `--IDENT -> puppycrawl [1:12]%n"
+ + "| | `--IDENT -> tools [1:23]%n"
+ + "| `--IDENT -> checkstyle [1:29]%n"
+ + "`--SEMI -> ; [1:39]%n"
+ + "CLASS_DEF -> CLASS_DEF [3:0]%n"
+ + "|--MODIFIERS -> MODIFIERS [3:0]%n"
+ + "| |--BLOCK_COMMENT_BEGIN -> /* [2:0]%n"
+ + "| | |--COMMENT_CONTENT -> comment [2:2]%n"
+ + "| | `--BLOCK_COMMENT_END -> */ [2:8]%n"
+ + "| `--LITERAL_PUBLIC -> public [3:0]%n"
+ + "|--LITERAL_CLASS -> class [3:7]%n"
+ + "|--IDENT -> InputMain [3:13]%n"
+ + "`--OBJBLOCK -> OBJBLOCK [3:23]%n"
+ + " |--LCURLY -> { [3:23]%n"
+ + " `--RCURLY -> } [4:0]%n"
+ + "CLASS_DEF -> CLASS_DEF [5:0]%n"
+ + "|--MODIFIERS -> MODIFIERS [5:0]%n"
+ + "|--LITERAL_CLASS -> class [5:0]%n"
+ + "|--IDENT -> InputMainInner [5:6]%n"
+ + "`--OBJBLOCK -> OBJBLOCK [5:21]%n"
+ + " |--LCURLY -> { [5:21]%n"
+ + " `--RCURLY -> } [6:0]%n");
+
+ exit.checkAssertionAfterwards(new Assertion() {
+ @Override
+ public void checkAssertion() {
+ assertEquals(expected, systemOut.getLog());
+ assertEquals("", systemErr.getLog());
+ }
+ });
+ Main.main("-T", getPath("InputMain.java"));
+ }
+
@Test
public void testConflictingOptionsTvsC() throws Exception {
diff --git a/src/test/resources/com/puppycrawl/tools/checkstyle/InputMain.java b/src/test/resources/com/puppycrawl/tools/checkstyle/InputMain.java
index b4ec9758c..1c8a12f42 100644
--- a/src/test/resources/com/puppycrawl/tools/checkstyle/InputMain.java
+++ b/src/test/resources/com/puppycrawl/tools/checkstyle/InputMain.java
@@ -1,5 +1,5 @@
package com.puppycrawl.tools.checkstyle;
-
+/*comment*/
public class InputMain {
}
class InputMainInner {
diff --git a/src/test/resources/com/puppycrawl/tools/checkstyle/astprinter/InputAstTreeStringPrinterComments.java b/src/test/resources/com/puppycrawl/tools/checkstyle/astprinter/InputAstTreeStringPrinterComments.java
new file mode 100644
index 000000000..76b9675b2
--- /dev/null
+++ b/src/test/resources/com/puppycrawl/tools/checkstyle/astprinter/InputAstTreeStringPrinterComments.java
@@ -0,0 +1,6 @@
+package com.puppycrawl.tools.checkstyle;
+
+/**my class*/
+class InputAstTreeStringPrinterComments {
+ // no code
+}
\ No newline at end of file
diff --git a/src/test/resources/com/puppycrawl/tools/checkstyle/astprinter/expectedInputAstTreeStringPrinter.txt b/src/test/resources/com/puppycrawl/tools/checkstyle/astprinter/expectedInputAstTreeStringPrinter.txt
new file mode 100644
index 000000000..97b757a46
--- /dev/null
+++ b/src/test/resources/com/puppycrawl/tools/checkstyle/astprinter/expectedInputAstTreeStringPrinter.txt
@@ -0,0 +1,17 @@
+PACKAGE_DEF -> package [1:0]
+|--ANNOTATIONS -> ANNOTATIONS [1:28]
+|--DOT -> . [1:28]
+| |--DOT -> . [1:22]
+| | |--DOT -> . [1:11]
+| | | |--IDENT -> com [1:8]
+| | | `--IDENT -> puppycrawl [1:12]
+| | `--IDENT -> tools [1:23]
+| `--IDENT -> checkstyle [1:29]
+`--SEMI -> ; [1:39]
+CLASS_DEF -> CLASS_DEF [4:0]
+|--MODIFIERS -> MODIFIERS [4:0]
+|--LITERAL_CLASS -> class [4:0]
+|--IDENT -> InputAstTreeStringPrinterComments [4:6]
+`--OBJBLOCK -> OBJBLOCK [4:40]
+ |--LCURLY -> { [4:40]
+ `--RCURLY -> } [6:0]
diff --git a/src/test/resources/com/puppycrawl/tools/checkstyle/astprinter/expectedInputAstTreeStringPrinterComments.txt b/src/test/resources/com/puppycrawl/tools/checkstyle/astprinter/expectedInputAstTreeStringPrinterComments.txt
new file mode 100644
index 000000000..2fd3700c6
--- /dev/null
+++ b/src/test/resources/com/puppycrawl/tools/checkstyle/astprinter/expectedInputAstTreeStringPrinterComments.txt
@@ -0,0 +1,22 @@
+PACKAGE_DEF -> package [1:0]
+|--ANNOTATIONS -> ANNOTATIONS [1:28]
+|--DOT -> . [1:28]
+| |--DOT -> . [1:22]
+| | |--DOT -> . [1:11]
+| | | |--IDENT -> com [1:8]
+| | | `--IDENT -> puppycrawl [1:12]
+| | `--IDENT -> tools [1:23]
+| `--IDENT -> checkstyle [1:29]
+`--SEMI -> ; [1:39]
+CLASS_DEF -> CLASS_DEF [4:0]
+|--MODIFIERS -> MODIFIERS [4:0]
+|--BLOCK_COMMENT_BEGIN -> /* [3:0]
+| |--COMMENT_CONTENT -> *my class [3:2]
+| `--BLOCK_COMMENT_END -> */ [3:10]
+|--LITERAL_CLASS -> class [4:0]
+|--IDENT -> InputAstTreeStringPrinterComments [4:6]
+`--OBJBLOCK -> OBJBLOCK [4:40]
+ |--LCURLY -> { [4:40]
+ |--SINGLE_LINE_COMMENT -> // [5:1]
+ | `--COMMENT_CONTENT -> no code\r\n [5:3]
+ `--RCURLY -> } [6:0]
diff --git a/src/xdocs/cmdline.xml.vm b/src/xdocs/cmdline.xml.vm
index da9368f63..3c800fe2c 100644
--- a/src/xdocs/cmdline.xml.vm
+++ b/src/xdocs/cmdline.xml.vm
@@ -38,7 +38,7 @@ java -D<property>=<value> \
com.puppycrawl.tools.checkstyle.Main \
-c <configurationFile> \
[-f <format>] [-p <propertiesFile>] [-o <file>] \
- [-t] [-v] \
+ [-t | --tree] [-T | --treeWithComments] [-v] \
file...
@@ -74,7 +74,11 @@ java -D<property>=<value> \
to.
- -t - print Abstract Syntax Tree(AST) of the checked file. The option
+ -t, --tree - print Abstract Syntax Tree(AST) of the checked file. The option
+ cannot be used other options and requires exactly one file to run on to be specified.
+
+
+ -T, --treeWithComments - print Abstract Syntax Tree(AST) with comment nodes of the checked file. The option
cannot be used other options and requires exactly one file to run on to be specified.