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) {
136 result = getValueAtDetailNode((DetailNode) node, 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) {
156 result = ((DetailNode) parent).getChildren()[index];
157 }
158 else {
159 result = getChildAtDetailAst((DetailAST) parent, index);
160 }
161
162 return result;
163 }
164
165
166
167
168
169
170
171 public int getChildCount(Object parent) {
172 final int result;
173
174 if (parent instanceof DetailNode) {
175 result = ((DetailNode) parent).getChildren().length;
176 }
177 else {
178 if (parseMode == ParseMode.JAVA_WITH_JAVADOC_AND_COMMENTS
179 && ((DetailAST) parent).getType() == TokenTypes.COMMENT_CONTENT
180 && JavadocUtil.isJavadocComment(((DetailAST) parent).getParent())) {
181
182
183 result = 1;
184 }
185 else {
186 result = ((DetailAST) parent).getChildCount();
187 }
188 }
189
190 return result;
191 }
192
193
194
195
196
197
198 public Object getRoot() {
199 return root;
200 }
201
202
203
204
205
206
207
208 public boolean isLeaf(Object node) {
209 return getChildCount(node) == 0;
210 }
211
212
213
214
215
216
217
218
219
220
221
222
223
224 public int getIndexOfChild(Object parent, Object child) {
225 int index = -1;
226 for (int i = 0; i < getChildCount(parent); i++) {
227 if (getChild(parent, i).equals(child)) {
228 index = i;
229 break;
230 }
231 }
232 return index;
233 }
234
235
236
237
238
239
240
241
242 public boolean isCellEditable(int column) {
243 return false;
244 }
245
246
247
248
249
250
251
252
253
254 private Object getChildAtDetailAst(DetailAST parent, int index) {
255 final Object result;
256 if (parseMode == ParseMode.JAVA_WITH_JAVADOC_AND_COMMENTS
257 && parent.getType() == TokenTypes.COMMENT_CONTENT
258 && JavadocUtil.isJavadocComment(parent.getParent())) {
259 result = getJavadocTree(parent.getParent());
260 }
261 else {
262 int currentIndex = 0;
263 DetailAST child = parent.getFirstChild();
264 while (currentIndex < index) {
265 child = child.getNextSibling();
266 currentIndex++;
267 }
268 result = child;
269 }
270
271 return result;
272 }
273
274
275
276
277
278
279
280
281
282 private static Object getValueAtDetailNode(DetailNode node, int column) {
283
284 return switch (column) {
285 case 0 ->
286
287 null;
288 case 1 -> JavadocUtil.getTokenName(node.getType());
289 case 2 -> node.getLineNumber();
290 case 3 -> node.getColumnNumber();
291 case 4 -> node.getText();
292 default -> throw new IllegalStateException(UNKNOWN_COLUMN_MSG);
293 };
294 }
295
296
297
298
299
300
301
302
303
304 private static Object getValueAtDetailAST(DetailAST ast, int column) {
305
306 return switch (column) {
307 case 0 ->
308
309 null;
310 case 1 -> TokenUtil.getTokenName(ast.getType());
311 case 2 -> ast.getLineNo();
312 case 3 -> ast.getColumnNo();
313 case 4 -> ast.getText();
314 default -> throw new IllegalStateException(UNKNOWN_COLUMN_MSG);
315 };
316 }
317
318
319
320
321
322
323
324 private DetailNode getJavadocTree(DetailAST blockComment) {
325 return blockCommentToJavadocTree.computeIfAbsent(blockComment,
326 ParseTreeTablePresentation::parseJavadocTree);
327 }
328
329
330
331
332
333
334
335 private static DetailNode parseJavadocTree(DetailAST blockComment) {
336 return new JavadocDetailNodeParser().parseJavadocAsDetailNode(blockComment).getTree();
337 }
338
339 }