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 com.puppycrawl.tools.checkstyle.JavadocDetailNodeParser;
26 import com.puppycrawl.tools.checkstyle.api.DetailAST;
27 import com.puppycrawl.tools.checkstyle.api.DetailNode;
28 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
29 import com.puppycrawl.tools.checkstyle.gui.MainFrameModel.ParseMode;
30 import com.puppycrawl.tools.checkstyle.utils.JavadocUtil;
31 import com.puppycrawl.tools.checkstyle.utils.TokenUtil;
32
33
34
35
36
37 public class ParseTreeTablePresentation {
38
39
40 private static final String UNKNOWN_COLUMN_MSG = "Unknown column";
41
42
43 private static final String[] COLUMN_NAMES = {
44 "Tree",
45 "Type",
46 "Line",
47 "Column",
48 "Text",
49 };
50
51
52 private final Map<DetailAST, DetailNode> blockCommentToJavadocTree = new HashMap<>();
53
54
55 private DetailAST root;
56
57
58 private ParseMode parseMode;
59
60
61
62
63
64
65 public ParseTreeTablePresentation(DetailAST parseTree) {
66 root = parseTree;
67 }
68
69
70
71
72
73
74 protected final void setRoot(DetailAST parseTree) {
75 root = parseTree;
76 }
77
78
79
80
81
82
83 protected void setParseMode(ParseMode mode) {
84 parseMode = mode;
85 }
86
87
88
89
90
91
92 public int getColumnCount() {
93 return COLUMN_NAMES.length;
94 }
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
114
115 public Class<?> getColumnClass(int column) {
116
117 return switch (column) {
118 case 0 -> ParseTreeTableModel.class;
119 case 1, 4 -> String.class;
120 case 2, 3 -> Integer.class;
121 default -> throw new IllegalStateException(UNKNOWN_COLUMN_MSG);
122 };
123 }
124
125
126
127
128
129
130
131
132 public Object getValueAt(Object node, int column) {
133 final Object result;
134
135 if (node instanceof DetailNode detailNode) {
136 result = getValueAtDetailNode(detailNode, column);
137 }
138 else {
139 result = getValueAtDetailAST((DetailAST) node, column);
140 }
141
142 return result;
143 }
144
145
146
147
148
149
150
151
152 public Object getChild(Object parent, int index) {
153 final Object result;
154
155 if (parent instanceof DetailNode parentNode) {
156 DetailNode node = parentNode.getFirstChild();
157 for (int nodeIndex = 0; nodeIndex < index; nodeIndex++) {
158 node = node.getNextSibling();
159 }
160 result = node;
161 }
162 else {
163 result = getChildAtDetailAst((DetailAST) parent, index);
164 }
165
166 return result;
167 }
168
169
170
171
172
173
174
175 public int getChildCount(Object parent) {
176 int result = 0;
177
178 if (parent instanceof DetailNode parentNode) {
179 DetailNode node = parentNode.getFirstChild();
180 while (node != null) {
181 node = node.getNextSibling();
182 result++;
183 }
184 }
185 else {
186 if (parseMode == ParseMode.JAVA_WITH_JAVADOC_AND_COMMENTS
187 && ((DetailAST) parent).getType() == TokenTypes.COMMENT_CONTENT
188 && JavadocUtil.isJavadocComment(((DetailAST) parent).getParent())) {
189
190
191 result = 1;
192 }
193 else {
194 result = ((DetailAST) parent).getChildCount();
195 }
196 }
197
198 return result;
199 }
200
201
202
203
204
205
206 public Object getRoot() {
207 return root;
208 }
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
250 public boolean isCellEditable(int column) {
251 return false;
252 }
253
254
255
256
257
258
259
260
261
262 private Object getChildAtDetailAst(DetailAST parent, int index) {
263 final Object result;
264 if (parseMode == ParseMode.JAVA_WITH_JAVADOC_AND_COMMENTS
265 && parent.getType() == TokenTypes.COMMENT_CONTENT
266 && JavadocUtil.isJavadocComment(parent.getParent())) {
267 result = getJavadocTree(parent.getParent());
268 }
269 else {
270 int currentIndex = 0;
271 DetailAST child = parent.getFirstChild();
272 while (currentIndex < index) {
273 child = child.getNextSibling();
274 currentIndex++;
275 }
276 result = child;
277 }
278
279 return result;
280 }
281
282
283
284
285
286
287
288
289
290 private static Object getValueAtDetailNode(DetailNode node, int column) {
291
292 return switch (column) {
293 case 0 ->
294
295 null;
296 case 1 -> JavadocUtil.getTokenName(node.getType());
297 case 2 -> node.getLineNumber();
298 case 3 -> node.getColumnNumber();
299 case 4 -> node.getText();
300 default -> throw new IllegalStateException(UNKNOWN_COLUMN_MSG);
301 };
302 }
303
304
305
306
307
308
309
310
311
312 private static Object getValueAtDetailAST(DetailAST ast, int column) {
313
314 return switch (column) {
315 case 0 ->
316
317 null;
318 case 1 -> TokenUtil.getTokenName(ast.getType());
319 case 2 -> ast.getLineNo();
320 case 3 -> ast.getColumnNo();
321 case 4 -> ast.getText();
322 default -> throw new IllegalStateException(UNKNOWN_COLUMN_MSG);
323 };
324 }
325
326
327
328
329
330
331
332 private DetailNode getJavadocTree(DetailAST blockComment) {
333 return blockCommentToJavadocTree.computeIfAbsent(blockComment,
334 ParseTreeTablePresentation::parseJavadocTree);
335 }
336
337
338
339
340
341
342
343 private static DetailNode parseJavadocTree(DetailAST blockComment) {
344 return new JavadocDetailNodeParser().parseJavadocComment(blockComment).getTree();
345 }
346
347 }