test/tools/javac/diags/MessageInfo.java

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

mercurial