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.internal.utils;
21
22 import java.io.File;
23 import java.io.IOException;
24 import java.lang.reflect.Field;
25 import java.text.MessageFormat;
26 import java.util.Arrays;
27 import java.util.HashSet;
28 import java.util.Locale;
29 import java.util.Properties;
30 import java.util.Set;
31 import java.util.stream.Collectors;
32
33 import javax.xml.parsers.DocumentBuilder;
34 import javax.xml.parsers.DocumentBuilderFactory;
35
36 import org.w3c.dom.Document;
37 import org.w3c.dom.Element;
38 import org.w3c.dom.Node;
39 import org.w3c.dom.NodeList;
40
41 import com.google.common.reflect.ClassPath;
42 import com.puppycrawl.tools.checkstyle.checks.regexp.RegexpMultilineCheck;
43 import com.puppycrawl.tools.checkstyle.checks.regexp.RegexpSinglelineCheck;
44 import com.puppycrawl.tools.checkstyle.checks.regexp.RegexpSinglelineJavaCheck;
45 import com.puppycrawl.tools.checkstyle.utils.JavadocUtil;
46 import com.puppycrawl.tools.checkstyle.utils.ModuleReflectionUtil;
47 import com.puppycrawl.tools.checkstyle.utils.TokenUtil;
48
49 public final class CheckUtil {
50
51 private CheckUtil() {
52 }
53
54 public static Set<String> getConfigCheckStyleModules() {
55 return getCheckStyleModulesReferencedInConfig("config/checkstyle_checks.xml");
56 }
57
58 public static Set<String> getConfigSunStyleModules() {
59 return getCheckStyleModulesReferencedInConfig("src/main/resources/sun_checks.xml");
60 }
61
62 public static Set<String> getConfigGoogleStyleModules() {
63 return getCheckStyleModulesReferencedInConfig("src/main/resources/google_checks.xml");
64 }
65
66
67
68
69
70
71
72 public static Set<String> getSimpleNames(Set<Class<?>> checks) {
73 return checks.stream().map(check -> {
74 String name = check.getSimpleName();
75
76 if (name.endsWith("Check")) {
77 name = name.substring(0, name.length() - 5);
78 }
79
80 return name;
81 }).collect(Collectors.toSet());
82 }
83
84
85
86
87
88
89
90
91 private static Set<String> getCheckStyleModulesReferencedInConfig(String configFilePath) {
92 try {
93 final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
94
95
96
97 factory.setNamespaceAware(false);
98 factory.setValidating(false);
99 factory.setFeature("http://xml.org/sax/features/namespaces", false);
100 factory.setFeature("http://xml.org/sax/features/validation", false);
101 factory.setFeature("http://apache.org/xml/features/nonvalidating/load-dtd-grammar",
102 false);
103 factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd",
104 false);
105
106 final DocumentBuilder builder = factory.newDocumentBuilder();
107 final Document document = builder.parse(new File(configFilePath));
108
109
110
111
112
113 document.getDocumentElement().normalize();
114
115 final NodeList nodeList = document.getElementsByTagName("module");
116
117 final Set<String> checksReferencedInCheckstyleChecksXml = new HashSet<>();
118 for (int i = 0; i < nodeList.getLength(); i++) {
119 final Node currentNode = nodeList.item(i);
120 if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
121 final Element module = (Element) currentNode;
122 final String checkName = module.getAttribute("name");
123 checksReferencedInCheckstyleChecksXml.add(checkName);
124 }
125 }
126 return checksReferencedInCheckstyleChecksXml;
127 }
128 catch (Exception exception) {
129 throw new IllegalStateException(exception);
130 }
131 }
132
133
134
135
136
137
138 public static Set<Class<?>> getCheckstyleChecks() throws IOException {
139 final ClassLoader loader = Thread.currentThread()
140 .getContextClassLoader();
141 final String packageName = "com.puppycrawl.tools.checkstyle";
142 return getCheckstyleModulesRecursive(packageName, loader).stream()
143 .filter(ModuleReflectionUtil::isCheckstyleTreeWalkerCheck)
144 .collect(Collectors.toSet());
145 }
146
147
148
149
150
151
152 public static Set<Class<?>> getCheckstyleModules() throws IOException {
153 final ClassLoader loader = Thread.currentThread()
154 .getContextClassLoader();
155 final String packageName = "com.puppycrawl.tools.checkstyle";
156 return getCheckstyleModulesRecursive(packageName, loader);
157 }
158
159
160
161
162
163
164
165
166
167 private static Set<Class<?>> getCheckstyleModulesRecursive(
168 String packageName, ClassLoader loader) throws IOException {
169 final ClassPath classPath = ClassPath.from(loader);
170 return classPath.getTopLevelClassesRecursive(packageName).stream()
171 .map(ClassPath.ClassInfo::load)
172 .filter(ModuleReflectionUtil::isCheckstyleModule)
173 .filter(cls -> !cls.getCanonicalName()
174 .startsWith("com.puppycrawl.tools.checkstyle.internal.testmodules"))
175 .filter(cls -> !cls.getCanonicalName()
176 .startsWith("com.puppycrawl.tools.checkstyle.packageobjectfactory"))
177 .collect(Collectors.toSet());
178 }
179
180
181
182
183
184
185
186 public static Set<Field> getCheckMessages(Class<?> module) throws ClassNotFoundException {
187 final Set<Field> checkstyleMessages = new HashSet<>();
188
189
190 final Field[] fields = module.getDeclaredFields();
191
192 for (Field field : fields) {
193 if (field.getName().startsWith("MSG_")) {
194 checkstyleMessages.add(field);
195 }
196 }
197
198
199 final Class<?> superModule = module.getSuperclass();
200
201 if (superModule != null) {
202 checkstyleMessages.addAll(getCheckMessages(superModule));
203 }
204
205
206 if (module == RegexpMultilineCheck.class) {
207 checkstyleMessages.addAll(getCheckMessages(Class
208 .forName("com.puppycrawl.tools.checkstyle.checks.regexp.MultilineDetector")));
209 }
210 else if (module == RegexpSinglelineCheck.class
211 || module == RegexpSinglelineJavaCheck.class) {
212 checkstyleMessages.addAll(getCheckMessages(Class
213 .forName("com.puppycrawl.tools.checkstyle.checks.regexp.SinglelineDetector")));
214 }
215
216 return checkstyleMessages;
217 }
218
219
220
221
222
223
224
225
226
227
228
229 public static String getCheckMessage(Class<?> module, Locale locale, String messageKey,
230 Object... arguments) {
231 String checkMessage;
232 try {
233 final Properties pr = new Properties();
234 if (locale == Locale.ENGLISH) {
235 pr.load(module.getResourceAsStream("messages.properties"));
236 }
237 else {
238 pr.load(module
239 .getResourceAsStream("messages_" + locale.getLanguage() + ".properties"));
240 }
241 final MessageFormat formatter = new MessageFormat(pr.getProperty(messageKey), locale);
242 checkMessage = formatter.format(arguments);
243 }
244 catch (IOException ignored) {
245 checkMessage = null;
246 }
247 return checkMessage;
248 }
249
250 public static String getTokenText(int[] tokens, int... subtractions) {
251 final String tokenText;
252 if (subtractions.length == 0 && Arrays.equals(tokens, TokenUtil.getAllTokenIds())) {
253 tokenText = "TokenTypes.";
254 }
255 else {
256 final StringBuilder result = new StringBuilder(50);
257 boolean first = true;
258
259 for (int token : tokens) {
260 boolean found = false;
261
262 for (int subtraction : subtractions) {
263 if (subtraction == token) {
264 found = true;
265 break;
266 }
267 }
268
269 if (found) {
270 continue;
271 }
272
273 if (first) {
274 first = false;
275 }
276 else {
277 result.append(", ");
278 }
279
280 result.append(TokenUtil.getTokenName(token));
281 }
282
283 if (result.length() == 0) {
284 result.append("empty");
285 }
286 else {
287 result.append('.');
288 }
289
290 tokenText = result.toString();
291 }
292 return tokenText;
293 }
294
295 public static Set<String> getTokenNameSet(int... tokens) {
296 final Set<String> result = new HashSet<>();
297
298 for (int token : tokens) {
299 result.add(TokenUtil.getTokenName(token));
300 }
301
302 return result;
303 }
304
305 public static String getJavadocTokenText(int[] tokens, int... subtractions) {
306 final StringBuilder result = new StringBuilder(50);
307 boolean first = true;
308
309 for (int token : tokens) {
310 boolean found = false;
311
312 for (int subtraction : subtractions) {
313 if (subtraction == token) {
314 found = true;
315 break;
316 }
317 }
318
319 if (found) {
320 continue;
321 }
322
323 if (first) {
324 first = false;
325 }
326 else {
327 result.append(", ");
328 }
329
330 result.append(JavadocUtil.getTokenName(token));
331 }
332
333 if (result.length() == 0) {
334 result.append("empty");
335 }
336 else {
337 result.append('.');
338 }
339
340 return result.toString();
341 }
342
343 }