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.utils;
21
22 import java.lang.reflect.Field;
23 import java.lang.reflect.Modifier;
24 import java.util.Arrays;
25 import java.util.Collections;
26 import java.util.Locale;
27 import java.util.Map;
28 import java.util.Optional;
29 import java.util.ResourceBundle;
30 import java.util.function.Consumer;
31 import java.util.function.Predicate;
32 import java.util.stream.Collectors;
33
34 import com.puppycrawl.tools.checkstyle.api.DetailAST;
35 import com.puppycrawl.tools.checkstyle.api.TokenTypes;
36
37
38
39
40
41 public final class TokenUtil {
42
43
44 private static final Map<String, Integer> TOKEN_NAME_TO_VALUE;
45
46 private static final String[] TOKEN_VALUE_TO_NAME;
47
48
49 private static final int[] TOKEN_IDS;
50
51
52 private static final String TOKEN_ID_EXCEPTION_PREFIX = "given id ";
53
54
55 private static final String TOKEN_NAME_EXCEPTION_PREFIX = "given name ";
56
57
58 static {
59 TOKEN_NAME_TO_VALUE = nameToValueMapFromPublicIntFields(TokenTypes.class);
60 TOKEN_VALUE_TO_NAME = valueToNameArrayFromNameToValueMap(TOKEN_NAME_TO_VALUE);
61 TOKEN_IDS = TOKEN_NAME_TO_VALUE.values().stream().mapToInt(Integer::intValue).toArray();
62 }
63
64
65 private TokenUtil() {
66 }
67
68
69
70
71
72
73
74
75
76
77
78 public static int getIntFromField(Field field, Object object) {
79 try {
80 return field.getInt(object);
81 }
82 catch (final IllegalAccessException exception) {
83 throw new IllegalStateException(exception);
84 }
85 }
86
87
88
89
90
91
92
93 public static Map<String, Integer> nameToValueMapFromPublicIntFields(Class<?> cls) {
94 final Map<String, Integer> map = Arrays.stream(cls.getDeclaredFields())
95 .filter(fld -> Modifier.isPublic(fld.getModifiers()) && fld.getType() == Integer.TYPE)
96 .collect(Collectors.toMap(Field::getName, fld -> getIntFromField(fld, fld.getName())));
97 return Collections.unmodifiableMap(map);
98 }
99
100
101
102
103
104
105 public static String[] valueToNameArrayFromNameToValueMap(Map<String, Integer> map) {
106 String[] valueToNameArray = CommonUtil.EMPTY_STRING_ARRAY;
107
108 for (Map.Entry<String, Integer> entry : map.entrySet()) {
109 final int value = entry.getValue();
110
111 if (value >= 0) {
112 if (value >= valueToNameArray.length) {
113 final String[] temp = new String[value + 1];
114 System.arraycopy(valueToNameArray, 0, temp, 0, valueToNameArray.length);
115 valueToNameArray = temp;
116 }
117 valueToNameArray[value] = entry.getKey();
118 }
119 }
120 return valueToNameArray;
121 }
122
123
124
125
126
127 public static int getTokenTypesTotalNumber() {
128 return TOKEN_IDS.length;
129 }
130
131
132
133
134
135 public static int[] getAllTokenIds() {
136 final int[] safeCopy = new int[TOKEN_IDS.length];
137 System.arraycopy(TOKEN_IDS, 0, safeCopy, 0, TOKEN_IDS.length);
138 return safeCopy;
139 }
140
141
142
143
144
145
146 public static String getTokenName(int id) {
147 if (id > TOKEN_VALUE_TO_NAME.length - 1) {
148 throw new IllegalArgumentException(TOKEN_ID_EXCEPTION_PREFIX + id);
149 }
150 final String name = TOKEN_VALUE_TO_NAME[id];
151 if (name == null) {
152 throw new IllegalArgumentException(TOKEN_ID_EXCEPTION_PREFIX + id);
153 }
154 return name;
155 }
156
157
158
159
160
161
162 public static int getTokenId(String name) {
163 final Integer id = TOKEN_NAME_TO_VALUE.get(name);
164 if (id == null) {
165 throw new IllegalArgumentException(TOKEN_NAME_EXCEPTION_PREFIX + name);
166 }
167 return id;
168 }
169
170
171
172
173
174
175 public static String getShortDescription(String name) {
176 if (!TOKEN_NAME_TO_VALUE.containsKey(name)) {
177 throw new IllegalArgumentException(TOKEN_NAME_EXCEPTION_PREFIX + name);
178 }
179
180 final String tokenTypes =
181 "com.puppycrawl.tools.checkstyle.api.tokentypes";
182 final ResourceBundle bundle = ResourceBundle.getBundle(tokenTypes, Locale.ROOT);
183 return bundle.getString(name);
184 }
185
186
187
188
189
190
191
192
193 public static boolean isCommentType(int type) {
194 return type == TokenTypes.SINGLE_LINE_COMMENT
195 || type == TokenTypes.BLOCK_COMMENT_BEGIN
196 || type == TokenTypes.BLOCK_COMMENT_END
197 || type == TokenTypes.COMMENT_CONTENT;
198 }
199
200
201
202
203
204
205
206
207 public static boolean isCommentType(String type) {
208 return isCommentType(getTokenId(type));
209 }
210
211
212
213
214
215
216
217
218 public static Optional<DetailAST> findFirstTokenByPredicate(DetailAST root,
219 Predicate<DetailAST> predicate) {
220 Optional<DetailAST> result = Optional.empty();
221 for (DetailAST ast = root.getFirstChild(); ast != null; ast = ast.getNextSibling()) {
222 if (predicate.test(ast)) {
223 result = Optional.of(ast);
224 break;
225 }
226 }
227 return result;
228 }
229
230
231
232
233
234
235
236
237 public static void forEachChild(DetailAST root, int type, Consumer<DetailAST> action) {
238 for (DetailAST ast = root.getFirstChild(); ast != null; ast = ast.getNextSibling()) {
239 if (ast.getType() == type) {
240 action.accept(ast);
241 }
242 }
243 }
244
245 }