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.gui;
21
22 import java.util.HashMap;
23 import java.util.Map;
24
25 import antlr.ASTFactory;
26 import antlr.collections.AST;
27 import com.puppycrawl.tools.checkstyle.JavadocDetailNodeParser;
28 import com.puppycrawl.tools.checkstyle.api.DetailAST;
29 import com.puppycrawl.tools.checkstyle.api.DetailNode;
30 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
31 import com.puppycrawl.tools.checkstyle.gui.MainFrameModel.ParseMode;
32 import com.puppycrawl.tools.checkstyle.utils.JavadocUtil;
33 import com.puppycrawl.tools.checkstyle.utils.TokenUtil;
34
35
36
37
38
39 public class ParseTreeTablePresentation {
40
41
42 private static final String UNKNOWN_COLUMN_MSG = "Unknown column";
43
44
45 private static final String[] COLUMN_NAMES = {
46 "Tree",
47 "Type",
48 "Line",
49 "Column",
50 "Text",
51 };
52
53
54
55
56 private final Object root;
57
58
59 private final Map<DetailAST, DetailNode> blockCommentToJavadocTree = new HashMap<>();
60
61
62 private ParseMode parseMode;
63
64
65
66
67
68 public ParseTreeTablePresentation(DetailAST parseTree) {
69 root = createArtificialTreeRoot();
70 setParseTree(parseTree);
71 }
72
73
74
75
76
77 protected final void setParseTree(DetailAST parseTree) {
78 ((AST) root).setFirstChild(parseTree);
79 }
80
81
82
83
84
85 protected void setParseMode(ParseMode mode) {
86 parseMode = mode;
87 }
88
89
90
91
92
93 public int getColumnCount() {
94 return COLUMN_NAMES.length;
95 }
96
97
98
99
100
101
102 public String getColumnName(int column) {
103 return COLUMN_NAMES[column];
104 }
105
106
107
108
109
110
111
112
113 public Class<?> getColumnClass(int column) {
114 final Class<?> columnClass;
115
116 switch (column) {
117 case 0:
118 columnClass = ParseTreeTableModel.class;
119 break;
120 case 1:
121 columnClass = String.class;
122 break;
123 case 2:
124 columnClass = Integer.class;
125 break;
126 case 3:
127 columnClass = Integer.class;
128 break;
129 case 4:
130 columnClass = String.class;
131 break;
132 default:
133 throw new IllegalStateException(UNKNOWN_COLUMN_MSG);
134 }
135 return columnClass;
136 }
137
138
139
140
141
142
143
144 public Object getValueAt(Object node, int column) {
145 final Object result;
146
147 if (node instanceof DetailNode) {
148 result = getValueAtDetailNode((DetailNode) node, column);
149 }
150 else {
151 result = getValueAtDetailAST((DetailAST) node, column);
152 }
153
154 return result;
155 }
156
157
158
159
160
161
162
163 public Object getChild(Object parent, int index) {
164 final Object result;
165
166 if (parent instanceof DetailNode) {
167 result = ((DetailNode) parent).getChildren()[index];
168 }
169 else {
170 result = getChildAtDetailAst((DetailAST) parent, index);
171 }
172
173 return result;
174 }
175
176
177
178
179
180
181 public int getChildCount(Object parent) {
182 final int result;
183
184 if (parent instanceof DetailNode) {
185 result = ((DetailNode) parent).getChildren().length;
186 }
187 else {
188 if (parseMode == ParseMode.JAVA_WITH_JAVADOC_AND_COMMENTS
189 && ((AST) parent).getType() == TokenTypes.COMMENT_CONTENT
190 && JavadocUtil.isJavadocComment(((DetailAST) parent).getParent())) {
191
192
193 result = 1;
194 }
195 else {
196 result = ((DetailAST) parent).getChildCount();
197 }
198 }
199
200 return result;
201 }
202
203
204
205
206
207 public Object getRoot() {
208 return root;
209 }
210
211
212
213
214
215
216 public boolean isLeaf(Object node) {
217 return getChildCount(node) == 0;
218 }
219
220
221
222
223
224
225
226
227
228
229
230
231
232 public int getIndexOfChild(Object parent, Object child) {
233 int index = -1;
234 for (int i = 0; i < getChildCount(parent); i++) {
235 if (getChild(parent, i).equals(child)) {
236 index = i;
237 break;
238 }
239 }
240 return index;
241 }
242
243
244
245
246
247
248
249 public boolean isCellEditable(int column) {
250 return false;
251 }
252
253
254
255
256
257 private static DetailAST createArtificialTreeRoot() {
258 final ASTFactory factory = new ASTFactory();
259 factory.setASTNodeClass(DetailAST.class.getName());
260 return (DetailAST) factory.create(TokenTypes.EOF, "ROOT");
261 }
262
263
264
265
266
267
268
269
270 private Object getChildAtDetailAst(DetailAST parent, int index) {
271 final Object result;
272 if (parseMode == ParseMode.JAVA_WITH_JAVADOC_AND_COMMENTS
273 && parent.getType() == TokenTypes.COMMENT_CONTENT
274 && JavadocUtil.isJavadocComment(parent.getParent())) {
275 result = getJavadocTree(parent.getParent());
276 }
277 else {
278 int currentIndex = 0;
279 DetailAST child = parent.getFirstChild();
280 while (currentIndex < index) {
281 child = child.getNextSibling();
282 currentIndex++;
283 }
284 result = child;
285 }
286
287 return result;
288 }
289
290
291
292
293
294
295
296 private static Object getValueAtDetailNode(DetailNode node, int column) {
297 final Object value;
298
299 switch (column) {
300 case 0:
301
302 value = null;
303 break;
304 case 1:
305 value = JavadocUtil.getTokenName(node.getType());
306 break;
307 case 2:
308 value = node.getLineNumber();
309 break;
310 case 3:
311 value = node.getColumnNumber();
312 break;
313 case 4:
314 value = node.getText();
315 break;
316 default:
317 throw new IllegalStateException(UNKNOWN_COLUMN_MSG);
318 }
319 return value;
320 }
321
322
323
324
325
326
327
328 private static Object getValueAtDetailAST(DetailAST ast, int column) {
329 final Object value;
330
331 switch (column) {
332 case 0:
333
334 value = null;
335 break;
336 case 1:
337 value = TokenUtil.getTokenName(ast.getType());
338 break;
339 case 2:
340 value = ast.getLineNo();
341 break;
342 case 3:
343 value = ast.getColumnNo();
344 break;
345 case 4:
346 value = ast.getText();
347 break;
348 default:
349 throw new IllegalStateException(UNKNOWN_COLUMN_MSG);
350 }
351 return value;
352 }
353
354
355
356
357
358
359 private DetailNode getJavadocTree(DetailAST blockComment) {
360 DetailNode javadocTree = blockCommentToJavadocTree.get(blockComment);
361 if (javadocTree == null) {
362 javadocTree = new JavadocDetailNodeParser().parseJavadocAsDetailNode(blockComment)
363 .getTree();
364 blockCommentToJavadocTree.put(blockComment, javadocTree);
365 }
366 return javadocTree;
367 }
368
369 }