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.lineSeparator();
48
49
50 private AstTreeStringPrinter() {
51
52 }
53
54
55
56
57
58
59
60
61
62
63 public static String printFileAst(File file, JavaParser.Options options)
64 throws IOException, CheckstyleException {
65 return printTree(JavaParser.parseFile(file, options));
66 }
67
68
69
70
71
72
73
74
75
76 public static String printJavaAndJavadocTree(File file)
77 throws IOException, CheckstyleException {
78 final DetailAST tree = JavaParser.parseFile(file, JavaParser.Options.WITH_COMMENTS);
79 return printJavaAndJavadocTree(tree);
80 }
81
82
83
84
85
86
87
88 private static String printJavaAndJavadocTree(DetailAST ast) {
89 final StringBuilder messageBuilder = new StringBuilder(1024);
90 DetailAST node = ast;
91 while (node != null) {
92 messageBuilder.append(getIndentation(node))
93 .append(getNodeInfo(node))
94 .append(LINE_SEPARATOR);
95 if (node.getType() == TokenTypes.COMMENT_CONTENT
96 && JavadocUtil.isJavadocComment(node.getParent())) {
97 final String javadocTree = parseAndPrintJavadocTree(node);
98 messageBuilder.append(javadocTree);
99 }
100 else {
101 messageBuilder.append(printJavaAndJavadocTree(node.getFirstChild()));
102 }
103 node = node.getNextSibling();
104 }
105 return messageBuilder.toString();
106 }
107
108
109
110
111
112
113
114 private static String parseAndPrintJavadocTree(DetailAST node) {
115 final DetailAST javadocBlock = node.getParent();
116 final DetailNode tree = DetailNodeTreeStringPrinter.parseJavadocAsDetailNode(javadocBlock);
117
118 String baseIndentation = getIndentation(node);
119 baseIndentation = baseIndentation.substring(0, baseIndentation.length() - 2);
120 final String rootPrefix = baseIndentation + " `--";
121 final String prefix = baseIndentation + " ";
122 return DetailNodeTreeStringPrinter.printTree(tree, rootPrefix, prefix);
123 }
124
125
126
127
128
129
130
131
132
133 public static String printAst(FileText text, JavaParser.Options options)
134 throws CheckstyleException {
135 final DetailAST ast = JavaParser.parseFileText(text, options);
136 return printTree(ast);
137 }
138
139
140
141
142
143
144
145 public static String printBranch(DetailAST node) {
146 final String result;
147 if (node == null) {
148 result = "";
149 }
150 else {
151 result = printBranch(node.getParent())
152 + getIndentation(node)
153 + getNodeInfo(node)
154 + LINE_SEPARATOR;
155 }
156 return result;
157 }
158
159
160
161
162
163
164
165 private static String printTree(DetailAST ast) {
166 final StringBuilder messageBuilder = new StringBuilder(1024);
167 DetailAST node = ast;
168 while (node != null) {
169 messageBuilder.append(getIndentation(node))
170 .append(getNodeInfo(node))
171 .append(LINE_SEPARATOR)
172 .append(printTree(node.getFirstChild()));
173 node = node.getNextSibling();
174 }
175 return messageBuilder.toString();
176 }
177
178
179
180
181
182
183
184
185 private static String getNodeInfo(DetailAST node) {
186 return TokenUtil.getTokenName(node.getType())
187 + " -> " + escapeAllControlChars(node.getText())
188 + " [" + node.getLineNo() + ':' + node.getColumnNo() + ']';
189 }
190
191
192
193
194
195
196
197 private static String getIndentation(DetailAST ast) {
198 final boolean isLastChild = ast.getNextSibling() == null;
199 DetailAST node = ast;
200 final StringBuilder indentation = new StringBuilder(1024);
201 while (node.getParent() != null) {
202 node = node.getParent();
203 if (node.getParent() == null) {
204 if (isLastChild) {
205
206
207 indentation.append("`--");
208 }
209 else {
210 indentation.append("|--");
211 }
212 }
213 else {
214 if (node.getNextSibling() == null) {
215 indentation.insert(0, " ");
216 }
217 else {
218 indentation.insert(0, "| ");
219 }
220 }
221 }
222 return indentation.toString();
223 }
224
225
226
227
228
229
230
231 private static String escapeAllControlChars(String text) {
232 final String textWithoutNewlines = NEWLINE.matcher(text).replaceAll("\\\\n");
233 final String textWithoutReturns = RETURN.matcher(textWithoutNewlines).replaceAll("\\\\r");
234 return TAB.matcher(textWithoutReturns).replaceAll("\\\\t");
235 }
236
237 }