Sat, 22 Dec 2018 13:10:38 -0800
Added tag jdk8u202-b25 for changeset 15d8c732039b
1 /*
2 * Copyright (c) 2010, 2013, 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 */
24 /**
25 * @test
26 * @bug 7013272 7127924
27 * @summary Automatically generate info about how compiler resource keys are used
28 * @build Example ArgTypeCompilerFactory MessageFile MessageInfo
29 * @run main/othervm MessageInfo
30 */
31 /*
32 * See CR 7127924 for info on why othervm is used.
33 */
35 import java.io.*;
36 import java.text.SimpleDateFormat;
37 import java.util.*;
39 /**
40 * Utility to manipulate compiler.properties, and suggest info comments based
41 * on information derived from running examples.
42 *
43 * Options:
44 * -examples dir location of examples directory
45 * -o file output file
46 * -check just check message file
47 * -ensureNewlines ensure newline after each entry
48 * -fixIndent fix indentation of continuation lines
49 * -sort sort messages
50 * -verbose verbose output
51 * -replace replace comments instead of merging comments
52 * file javac compiler.properties file
53 *
54 */
55 public class MessageInfo {
56 public static void main(String... args) throws Exception {
57 jtreg = (System.getProperty("test.src") != null);
58 File tmpDir;
59 if (jtreg) {
60 // use standard jtreg scratch directory: the current directory
61 tmpDir = new File(System.getProperty("user.dir"));
62 } else {
63 tmpDir = new File(System.getProperty("java.io.tmpdir"),
64 MessageInfo.class.getName()
65 + (new SimpleDateFormat("yyMMddHHmmss")).format(new Date()));
66 }
67 Example.setTempDir(tmpDir);
68 Example.Compiler.factory = new ArgTypeCompilerFactory();
70 MessageInfo mi = new MessageInfo();
72 try {
73 if (mi.run(args))
74 return;
75 } finally {
76 /* VERY IMPORTANT NOTE. In jtreg mode, tmpDir is set to the
77 * jtreg scratch directory, which is the current directory.
78 * In case someone is faking jtreg mode, make sure to only
79 * clean tmpDir when it is reasonable to do so.
80 */
81 if (tmpDir.isDirectory() &&
82 tmpDir.getName().startsWith(MessageInfo.class.getName())) {
83 if (clean(tmpDir))
84 tmpDir.delete();
85 }
86 }
88 if (jtreg)
89 throw new Exception(mi.errors + " errors occurred");
90 else
91 System.exit(1);
92 }
94 void usage() {
95 System.out.println("Usage:");
96 System.out.println(" java MessageInfo [options] [file]");
97 System.out.println("where options include");
98 System.out.println(" -examples dir location of examples directory");
99 System.out.println(" -o file output file");
100 System.out.println(" -check just check message file");
101 System.out.println(" -ensureNewlines ensure newline after each entry");
102 System.out.println(" -fixIndent fix indentation of continuation lines");
103 System.out.println(" -sort sort messages");
104 System.out.println(" -verbose verbose output");
105 System.out.println(" -replace replace comments instead of merging comments");
106 System.out.println(" file javac compiler.properties file");
107 }
109 boolean run(String... args) {
110 File testSrc = new File(System.getProperty("test.src", "."));
111 File examplesDir = new File(testSrc, "examples");
112 File notYetFile = null;
113 File msgFile = null;
114 File outFile = null;
115 boolean verbose = false;
116 boolean ensureNewlines = false;
117 boolean fixIndent = false;
118 boolean sort = false;
119 boolean replace = false;
120 boolean check = jtreg; // default true in jtreg mode
122 for (int i = 0; i < args.length; i++) {
123 String arg = args[i];
124 if (arg.equals("-examples") && (i + 1) < args.length)
125 examplesDir = new File(args[++i]);
126 else if(arg.equals("-notyet") && (i + 1) < args.length)
127 notYetFile = new File(args[++i]);
128 else if (arg.equals("-ensureNewlines"))
129 ensureNewlines = true;
130 else if (arg.equals("-fixIndent"))
131 fixIndent = true;
132 else if (arg.equals("-sort"))
133 sort = true;
134 else if (arg.equals("-verbose"))
135 verbose = true;
136 else if (arg.equals("-replace"))
137 replace = true;
138 else if (arg.equals("-check"))
139 check = true;
140 else if (arg.equals("-o") && (i + 1) < args.length)
141 outFile = new File(args[++i]);
142 else if (arg.startsWith("-")) {
143 error("unknown option: " + arg);
144 return false;
145 } else if (i == args.length - 1) {
146 msgFile = new File(arg);
147 } else {
148 error("unknown arg: " + arg);
149 return false;
150 }
151 }
153 if (!check && outFile == null) {
154 usage();
155 return true;
156 }
158 if ((ensureNewlines || fixIndent || sort) && outFile == null) {
159 error("must set output file for these options");
160 return false;
161 }
163 if (notYetFile == null) {
164 notYetFile = new File(examplesDir.getParentFile(), "examples.not-yet.txt");
165 }
167 if (msgFile == null) {
168 for (File d = testSrc; d != null; d = d.getParentFile()) {
169 if (new File(d, "TEST.ROOT").exists()) {
170 d = d.getParentFile();
171 File f = new File(d, "src/share/classes/com/sun/tools/javac/resources/compiler.properties");
172 if (f.exists()) {
173 msgFile = f;
174 break;
175 }
176 }
177 }
178 if (msgFile == null) {
179 if (jtreg) {
180 System.err.println("Warning: no message file available, test skipped");
181 return true;
182 }
183 error("no message file available");
184 return false;
185 }
186 }
188 MessageFile mf;
189 try {
190 mf = new MessageFile(msgFile);
191 } catch (IOException e) {
192 error("problem reading message file: " + e);
193 return false;
194 }
196 Map<String, Set<String>> msgInfo = runExamples(examplesDir, verbose);
198 if (ensureNewlines)
199 ensureNewlines(mf);
201 if (fixIndent)
202 fixIndent(mf);
204 if (sort)
205 sort(mf, true);
207 for (Map.Entry<String, Set<String>> e: msgInfo.entrySet()) {
208 String k = e.getKey();
209 Set<String> suggestions = e.getValue();
210 MessageFile.Message m = mf.messages.get(k);
211 if (m == null) {
212 error("Can't find message for " + k + " in message file");
213 continue;
214 }
216 MessageFile.Info info = m.getInfo();
217 Set<Integer> placeholders = m.getPlaceholders();
218 MessageFile.Info suggestedInfo = new MessageFile.Info(suggestions);
219 suggestedInfo.markUnused(placeholders);
221 if (!info.isEmpty()) {
222 if (info.contains(suggestedInfo))
223 continue;
224 if (!replace) {
225 if (info.fields.size() != suggestedInfo.fields.size())
226 error("Cannot merge info for " + k);
227 else
228 suggestedInfo.merge(info);
229 }
230 }
232 if (outFile == null) {
233 System.err.println("suggest for " + k);
234 System.err.println(suggestedInfo.toComment());
235 } else
236 m.setInfo(suggestedInfo);
237 }
239 if (check)
240 check(mf, notYetFile);
242 try {
243 if (outFile != null)
244 mf.write(outFile);
245 } catch (IOException e) {
246 error("problem writing file: " + e);
247 return false;
248 }
250 return (errors == 0);
251 }
253 void check(MessageFile mf, File notYetFile) {
254 Set<String> notYetList = null;
255 for (Map.Entry<String, MessageFile.Message> e: mf.messages.entrySet()) {
256 String key = e.getKey();
257 MessageFile.Message m = e.getValue();
258 if (m.needInfo() && m.getInfo().isEmpty()) {
259 if (notYetList == null)
260 notYetList = getNotYetList(notYetFile);
261 if (notYetList.contains(key))
262 System.err.println("Warning: no info for " + key);
263 else
264 error("no info for " + key);
265 }
266 }
268 }
270 void ensureNewlines(MessageFile mf) {
271 for (MessageFile.Message m: mf.messages.values()) {
272 MessageFile.Line l = m.firstLine;
273 while (l.text.endsWith("\\"))
274 l = l.next;
275 if (l.next != null && !l.next.text.isEmpty())
276 l.insertAfter("");
277 }
278 }
280 void fixIndent(MessageFile mf) {
281 for (MessageFile.Message m: mf.messages.values()) {
282 MessageFile.Line l = m.firstLine;
283 while (l.text.endsWith("\\") && l.next != null) {
284 if (!l.next.text.matches("^ \\S.*"))
285 l.next.text = " " + l.next.text.trim();
286 l = l.next;
287 }
288 }
289 }
291 void sort(MessageFile mf, boolean includePrecedingNewlines) {
292 for (MessageFile.Message m: mf.messages.values()) {
293 for (MessageFile.Line l: m.getLines(includePrecedingNewlines)) {
294 l.remove();
295 mf.lastLine.insertAfter(l);
296 }
297 }
298 }
300 Map<String, Set<String>> runExamples(File examplesDir, boolean verbose) {
301 Map<String, Set<String>> map = new TreeMap<String, Set<String>>();
302 for (Example e: getExamples(examplesDir)) {
303 StringWriter sw = new StringWriter();
304 PrintWriter pw = new PrintWriter(sw);
305 e.run(pw, true, verbose);
306 pw.close();
307 String[] lines = sw.toString().split("\n");
308 for (String line: lines) {
309 if (!line.startsWith("compiler."))
310 continue;
311 int colon = line.indexOf(":");
312 if (colon == -1)
313 continue;
314 String key = line.substring(0, colon);
315 StringBuilder sb = new StringBuilder();
316 sb.append("# ");
317 int i = 0;
318 String[] descs = line.substring(colon + 1).split(", *");
319 for (String desc: descs) {
320 if (i > 0) sb.append(", ");
321 sb.append(i++);
322 sb.append(": ");
323 sb.append(desc.trim());
324 }
325 Set<String> set = map.get(key);
326 if (set == null)
327 map.put(key, set = new TreeSet<String>());
328 set.add(sb.toString());
329 }
330 }
332 return map;
333 }
335 /**
336 * Get the complete set of examples to be checked.
337 */
338 Set<Example> getExamples(File examplesDir) {
339 Set<Example> results = new TreeSet<Example>();
340 for (File f: examplesDir.listFiles()) {
341 if (isValidExample(f))
342 results.add(new Example(f));
343 }
344 return results;
345 }
347 boolean isValidExample(File f) {
348 return (f.isDirectory() && (!jtreg || f.list().length > 0)) ||
349 (f.isFile() && f.getName().endsWith(".java"));
350 }
352 /**
353 * Get the contents of the "not-yet" list.
354 */
355 Set<String> getNotYetList(File file) {
356 Set<String> results = new TreeSet<String>();
357 try {
358 String[] lines = read(file).split("[\r\n]");
359 for (String line: lines) {
360 int hash = line.indexOf("#");
361 if (hash != -1)
362 line = line.substring(0, hash).trim();
363 if (line.matches("[A-Za-z0-9-_.]+"))
364 results.add(line);
365 }
366 } catch (IOException e) {
367 throw new Error(e);
368 }
369 return results;
370 }
372 /**
373 * Read the contents of a file.
374 */
375 String read(File f) throws IOException {
376 byte[] bytes = new byte[(int) f.length()];
377 DataInputStream in = new DataInputStream(new FileInputStream(f));
378 try {
379 in.readFully(bytes);
380 } finally {
381 in.close();
382 }
383 return new String(bytes);
384 }
386 /**
387 * Report an error.
388 */
389 void error(String msg) {
390 System.err.println("Error: " + msg);
391 errors++;
392 }
394 static boolean jtreg;
396 int errors;
398 /**
399 * Clean the contents of a directory.
400 */
401 static boolean clean(File dir) {
402 boolean ok = true;
403 for (File f: dir.listFiles()) {
404 if (f.isDirectory())
405 ok &= clean(f);
406 ok &= f.delete();
407 }
408 return ok;
409 }
411 }