1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package com.puppycrawl.tools.checkstyle;
21
22 import java.io.File;
23 import java.io.IOException;
24 import java.util.regex.Pattern;
25
26 import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
27 import com.puppycrawl.tools.checkstyle.api.DetailAST;
28 import com.puppycrawl.tools.checkstyle.api.DetailNode;
29 import com.puppycrawl.tools.checkstyle.api.FileText;
30 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
31 import com.puppycrawl.tools.checkstyle.utils.JavadocUtil;
32 import com.puppycrawl.tools.checkstyle.utils.TokenUtil;
33
34
35
36
37 public final class AstTreeStringPrinter {
38
39
40 private static final Pattern NEWLINE = Pattern.compile("\n");
41
42 private static final Pattern RETURN = Pattern.compile("\r");
43
44 private static final Pattern TAB = Pattern.compile("\t");
45
46
47 private static final String LINE_SEPARATOR = System.getProperty("line.separator");
48
49
50 private AstTreeStringPrinter() {
51
52 }
53
54
55
56
57
58
59
60
61
62 public static String printFileAst(File file, JavaParser.Options options)
63 throws IOException, CheckstyleException {
64 return printTree(JavaParser.parseFile(file, options));
65 }
66
67
68
69
70
71
72
73
74 public static String printJavaAndJavadocTree(File file)
75 throws IOException, CheckstyleException {
76 final DetailAST tree = JavaParser.parseFile(file, JavaParser.Options.WITH_COMMENTS);
77 return printJavaAndJavadocTree(tree);
78 }
79
80
81
82
83
84
85 private static String printJavaAndJavadocTree(DetailAST ast) {
86 final StringBuilder messageBuilder = new StringBuilder(1024);
87 DetailAST node = ast;
88 while (node != null) {
89 messageBuilder.append(getIndentation(node))
90 .append(getNodeInfo(node))
91 .append(LINE_SEPARATOR);
92 if (node.getType() == TokenTypes.COMMENT_CONTENT
93 && JavadocUtil.isJavadocComment(node.getParent())) {
94 final String javadocTree = parseAndPrintJavadocTree(node);
95 messageBuilder.append(javadocTree);
96 }
97 else {
98 messageBuilder.append(printJavaAndJavadocTree(node.getFirstChild()));
99 }
100 node = node.getNextSibling();
101 }
102 return messageBuilder.toString();
103 }
104
105
106
107
108
109
110 private static String parseAndPrintJavadocTree(DetailAST node) {
111 final DetailAST javadocBlock = node.getParent();
112 final DetailNode tree = DetailNodeTreeStringPrinter.parseJavadocAsDetailNode(javadocBlock);
113
114 String baseIndentation = getIndentation(node);
115 baseIndentation = baseIndentation.substring(0, baseIndentation.length() - 2);
116 final String rootPrefix = baseIndentation + " `--";
117 final String prefix = baseIndentation + " ";
118 return DetailNodeTreeStringPrinter.printTree(tree, rootPrefix, prefix);
119 }
120
121
122
123
124
125
126
127
128 public static String printAst(FileText text, JavaParser.Options options)
129 throws CheckstyleException {
130 final DetailAST ast = JavaParser.parseFileText(text, options);
131 return printTree(ast);
132 }
133
134
135
136
137
138
139 private static String printTree(DetailAST ast) {
140 final StringBuilder messageBuilder = new StringBuilder(1024);
141 DetailAST node = ast;
142 while (node != null) {
143 messageBuilder.append(getIndentation(node))
144 .append(getNodeInfo(node))
145 .append(LINE_SEPARATOR)
146 .append(printTree(node.getFirstChild()));
147 node = node.getNextSibling();
148 }
149 return messageBuilder.toString();
150 }
151
152
153
154
155
156
157
158 private static String getNodeInfo(DetailAST node) {
159 return TokenUtil.getTokenName(node.getType())
160 + " -> " + escapeAllControlChars(node.getText())
161 + " [" + node.getLineNo() + ':' + node.getColumnNo() + ']';
162 }
163
164
165
166
167
168
169 private static String getIndentation(DetailAST ast) {
170 final boolean isLastChild = ast.getNextSibling() == null;
171 DetailAST node = ast;
172 final StringBuilder indentation = new StringBuilder(1024);
173 while (node.getParent() != null) {
174 node = node.getParent();
175 if (node.getParent() == null) {
176 if (isLastChild) {
177
178
179 indentation.append("`--");
180 }
181 else {
182 indentation.append("|--");
183 }
184 }
185 else {
186 if (node.getNextSibling() == null) {
187 indentation.insert(0, " ");
188 }
189 else {
190 indentation.insert(0, "| ");
191 }
192 }
193 }
194 return indentation.toString();
195 }
196
197
198
199
200
201
202 private static String escapeAllControlChars(String text) {
203 final String textWithoutNewlines = NEWLINE.matcher(text).replaceAll("\\\\n");
204 final String textWithoutReturns = RETURN.matcher(textWithoutNewlines).replaceAll("\\\\r");
205 return TAB.matcher(textWithoutReturns).replaceAll("\\\\t");
206 }
207
208 }