Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/langtools/jdk/javadoc/tool/CheckResourceKeys.java
40957 views
1
/*
2
* Copyright (c) 2010, 2021, Oracle and/or its affiliates. All rights reserved.
3
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4
*
5
* This code is free software; you can redistribute it and/or modify it
6
* under the terms of the GNU General Public License version 2 only, as
7
* published by the Free Software Foundation.
8
*
9
* This code is distributed in the hope that it will be useful, but WITHOUT
10
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12
* version 2 for more details (a copy is included in the LICENSE file that
13
* accompanied this code).
14
*
15
* You should have received a copy of the GNU General Public License version
16
* 2 along with this work; if not, write to the Free Software Foundation,
17
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18
*
19
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20
* or visit www.oracle.com if you need additional information or have any
21
* questions.
22
*/
23
24
/*
25
* @test
26
* @bug 8000612 8254627 8247994
27
* @summary need test program to validate javadoc resource bundles
28
* @modules jdk.javadoc/jdk.javadoc.internal.tool
29
* jdk.javadoc/jdk.javadoc.internal.doclets.formats.html.resources:open
30
* jdk.javadoc/jdk.javadoc.internal.doclets.toolkit.resources:open
31
* jdk.javadoc/jdk.javadoc.internal.tool.resources:open
32
* jdk.jdeps/com.sun.tools.classfile
33
*/
34
35
import java.io.*;
36
import java.util.*;
37
import java.util.regex.Matcher;
38
import java.util.regex.Pattern;
39
import javax.tools.*;
40
import com.sun.tools.classfile.*;
41
42
/**
43
* Compare string constants in javadoc classes against keys in javadoc resource bundles.
44
*/
45
public class CheckResourceKeys {
46
/**
47
* Main program.
48
* Options:
49
* -finddeadkeys
50
* look for keys in resource bundles that are no longer required
51
* -findmissingkeys
52
* look for keys in resource bundles that are missing
53
*
54
* @throws Exception if invoked by jtreg and errors occur
55
*/
56
public static void main(String... args) throws Exception {
57
CheckResourceKeys c = new CheckResourceKeys();
58
if (c.run(args))
59
return;
60
61
if (is_jtreg())
62
throw new Exception(c.errors + " errors occurred");
63
else
64
System.exit(1);
65
}
66
67
static boolean is_jtreg() {
68
return (System.getProperty("test.src") != null);
69
}
70
71
/**
72
* Main entry point.
73
*/
74
boolean run(String... args) throws Exception {
75
boolean findDeadKeys = false;
76
boolean findMissingKeys = false;
77
78
if (args.length == 0) {
79
if (is_jtreg()) {
80
findDeadKeys = true;
81
findMissingKeys = true;
82
} else {
83
System.err.println("Usage: java CheckResourceKeys <options>");
84
System.err.println("where options include");
85
System.err.println(" -finddeadkeys find keys in resource bundles which are no longer required");
86
System.err.println(" -findmissingkeys find keys in resource bundles that are required but missing");
87
return true;
88
}
89
} else {
90
for (String arg: args) {
91
if (arg.equalsIgnoreCase("-finddeadkeys"))
92
findDeadKeys = true;
93
else if (arg.equalsIgnoreCase("-findmissingkeys"))
94
findMissingKeys = true;
95
else
96
error("bad option: " + arg);
97
}
98
}
99
100
if (errors > 0)
101
return false;
102
103
Set<String> codeKeys = getCodeKeys();
104
Set<String> resourceKeys = getResourceKeys();
105
106
System.err.println("found " + codeKeys.size() + " keys in code");
107
System.err.println("found " + resourceKeys.size() + " keys in resource bundles");
108
109
if (findDeadKeys)
110
findDeadKeys(codeKeys, resourceKeys);
111
112
if (findMissingKeys)
113
findMissingKeys(codeKeys, resourceKeys);
114
115
usageTests(false);
116
usageTests(true);
117
118
return (errors == 0);
119
}
120
121
void usageTests(boolean xflag) {
122
String[] argarray = { xflag ? "-X" : "--help" };
123
StringWriter sw = new StringWriter();
124
PrintWriter pw = new PrintWriter(sw);
125
if (jdk.javadoc.internal.tool.Main.execute(argarray, pw) == 0) {
126
pw.flush();
127
String s = sw.toString();
128
if (s.isEmpty()) {
129
error("no javadoc output ?");
130
return;
131
}
132
if (sw.toString().contains("<MISSING KEY>")) {
133
System.out.println(s);
134
error("missing resources in output ?");
135
}
136
} else {
137
error("failed to execute javadoc");
138
}
139
}
140
141
/**
142
* Find keys in resource bundles which are probably no longer required.
143
* A key is required if there is a string in the code that is a resource key,
144
* or if the key is well-known according to various pragmatic rules.
145
*/
146
void findDeadKeys(Set<String> codeKeys, Set<String> resourceKeys) {
147
for (String rk: resourceKeys) {
148
// ignore these synthesized keys, tested by usageTests
149
if (rk.startsWith("doclet.usage.") || rk.startsWith("doclet.xusage"))
150
continue;
151
// ignore these synthesized keys, tested by usageTests
152
if (rk.matches("main\\.opt\\..*\\.(arg|desc)"))
153
continue;
154
// ignore this partial key
155
if (rk.startsWith("doclet.Declared_Using_Preview."))
156
continue;
157
if (codeKeys.contains(rk))
158
continue;
159
160
error("Resource key not found in code: '" + rk + '"');
161
}
162
}
163
164
/**
165
* For all strings in the code that look like they might be
166
* a resource key, verify that a key exists.
167
*/
168
void findMissingKeys(Set<String> codeKeys, Set<String> resourceKeys) {
169
for (String ck: codeKeys) {
170
// ignore these synthesized keys, tested by usageTests
171
if (ck.startsWith("doclet.usage.") || ck.startsWith("doclet.xusage."))
172
continue;
173
// ignore this partial key, tested by usageTests
174
if (ck.equals("main.opt."))
175
continue;
176
// ignore these system property names
177
if (ck.equals("javadoc.internal.show.taglets") || ck.equals("javadoc.legal-notices"))
178
continue;
179
if (resourceKeys.contains(ck))
180
continue;
181
error("No resource for \"" + ck + "\"");
182
}
183
}
184
185
/**
186
* Get the set of strings from (most of) the javadoc classfiles.
187
*/
188
Set<String> getCodeKeys() throws IOException {
189
Set<String> results = new TreeSet<String>();
190
JavaCompiler c = ToolProvider.getSystemJavaCompiler();
191
try (JavaFileManager fm = c.getStandardFileManager(null, null, null)) {
192
JavaFileManager.Location javadocLoc = findJavadocLocation(fm);
193
String[] pkgs = {
194
"jdk.javadoc.internal.doclets",
195
"jdk.javadoc.internal.tool"
196
};
197
for (String pkg: pkgs) {
198
for (JavaFileObject fo: fm.list(javadocLoc,
199
pkg, EnumSet.of(JavaFileObject.Kind.CLASS), true)) {
200
String name = fo.getName();
201
// ignore resource files
202
if (name.matches(".*resources.[A-Za-z_0-9]+\\.class.*"))
203
continue;
204
scan(fo, results);
205
}
206
}
207
208
// special handling for strings in search.js.template
209
FileObject fo = fm.getFileForInput(javadocLoc,
210
"jdk.javadoc.internal.doclets.formats.html",
211
"resources/search.js.template");
212
CharSequence search_js = fo.getCharContent(true);
213
Pattern p = Pattern.compile("##REPLACE:(?<key>[A-Za-z0-9._]+)##");
214
Matcher m = p.matcher(search_js);
215
while (m.find()) {
216
results.add(m.group("key"));
217
}
218
219
// special handling for code strings synthesized in
220
// jdk.javadoc.internal.doclets.toolkit.util.Utils.getTypeName
221
String[] extras = {
222
"AnnotationType", "Class", "Enum", "EnumClass", "Error", "Exception", "Interface", "RecordClass"
223
};
224
for (String s: extras) {
225
if (results.contains("doclet." + s))
226
results.add("doclet." + s.toLowerCase());
227
}
228
229
// special handling for code strings synthesized in
230
// jdk.javadoc.internal.tool.Messager
231
results.add("javadoc.error.msg");
232
results.add("javadoc.note.msg");
233
results.add("javadoc.note.pos.msg");
234
results.add("javadoc.warning.msg");
235
236
results.add("javadoc.err.message");
237
results.add("javadoc.warn.message");
238
results.add("javadoc.note.message");
239
240
return results;
241
}
242
}
243
244
// depending on how the test is run, javadoc may be on bootclasspath or classpath
245
JavaFileManager.Location findJavadocLocation(JavaFileManager fm) {
246
JavaFileManager.Location[] locns =
247
{ StandardLocation.PLATFORM_CLASS_PATH, StandardLocation.CLASS_PATH };
248
try {
249
for (JavaFileManager.Location l: locns) {
250
JavaFileObject fo = fm.getJavaFileForInput(l,
251
"jdk.javadoc.internal.tool.Main", JavaFileObject.Kind.CLASS);
252
if (fo != null) {
253
System.err.println("found javadoc in " + l);
254
return l;
255
}
256
}
257
} catch (IOException e) {
258
throw new Error(e);
259
}
260
throw new IllegalStateException("Cannot find javadoc");
261
}
262
263
/**
264
* Get the set of strings from a class file.
265
* Only strings that look like they might be a resource key are returned.
266
*/
267
void scan(JavaFileObject fo, Set<String> results) throws IOException {
268
//System.err.println("scan " + fo.getName());
269
InputStream in = fo.openInputStream();
270
try {
271
ClassFile cf = ClassFile.read(in);
272
for (ConstantPool.CPInfo cpinfo: cf.constant_pool.entries()) {
273
if (cpinfo.getTag() == ConstantPool.CONSTANT_Utf8) {
274
String v = ((ConstantPool.CONSTANT_Utf8_info) cpinfo).value;
275
if (v.matches("(doclet|main|javadoc|tag)\\.[A-Za-z0-9-_.]+"))
276
results.add(v);
277
}
278
}
279
} catch (ConstantPoolException ignore) {
280
} finally {
281
in.close();
282
}
283
}
284
285
/**
286
* Get the set of keys from the javadoc resource bundles.
287
*/
288
Set<String> getResourceKeys() {
289
Module jdk_javadoc = ModuleLayer.boot().findModule("jdk.javadoc").get();
290
String[] names = {
291
"jdk.javadoc.internal.doclets.formats.html.resources.standard",
292
"jdk.javadoc.internal.doclets.toolkit.resources.doclets",
293
"jdk.javadoc.internal.tool.resources.javadoc",
294
};
295
Set<String> results = new TreeSet<String>();
296
for (String name : names) {
297
ResourceBundle b = ResourceBundle.getBundle(name, jdk_javadoc);
298
results.addAll(b.keySet());
299
}
300
return results;
301
}
302
303
/**
304
* Report an error.
305
*/
306
void error(String msg) {
307
System.err.println("Error: " + msg);
308
errors++;
309
}
310
311
int errors;
312
}
313
314