1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/test/tools/javac/diags/MessageInfo.java Wed Jan 26 13:45:25 2011 -0800 1.3 @@ -0,0 +1,406 @@ 1.4 +/* 1.5 + * Copyright (c) 2010, 2011, Oracle and/or its affiliates. All rights reserved. 1.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 1.7 + * 1.8 + * This code is free software; you can redistribute it and/or modify it 1.9 + * under the terms of the GNU General Public License version 2 only, as 1.10 + * published by the Free Software Foundation. 1.11 + * 1.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 1.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1.15 + * version 2 for more details (a copy is included in the LICENSE file that 1.16 + * accompanied this code). 1.17 + * 1.18 + * You should have received a copy of the GNU General Public License version 1.19 + * 2 along with this work; if not, write to the Free Software Foundation, 1.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 1.21 + * 1.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 1.23 + * or visit www.oracle.com if you need additional information or have any 1.24 + * questions. 1.25 + */ 1.26 + 1.27 +/** 1.28 + * @test 1.29 + * @bug 7013272 1.30 + * @summary Automatically generate info about how compiler resource keys are used 1.31 + * @build Example ArgTypeCompilerFactory MessageFile MessageInfo 1.32 + * @run main MessageInfo 1.33 + */ 1.34 + 1.35 +import java.io.*; 1.36 +import java.text.SimpleDateFormat; 1.37 +import java.util.*; 1.38 + 1.39 +/** 1.40 + * Utility to manipulate compiler.properties, and suggest info comments based 1.41 + * on information derived from running examples. 1.42 + * 1.43 + * Options: 1.44 + * -examples dir location of examples directory 1.45 + * -o file output file 1.46 + * -check just check message file 1.47 + * -ensureNewlines ensure newline after each entry 1.48 + * -fixIndent fix indentation of continuation lines 1.49 + * -sort sort messages 1.50 + * -verbose verbose output 1.51 + * -replace replace comments instead of merging comments 1.52 + * file javac compiler.properties file 1.53 + * 1.54 + */ 1.55 +public class MessageInfo { 1.56 + public static void main(String... args) throws Exception { 1.57 + jtreg = (System.getProperty("test.src") != null); 1.58 + File tmpDir; 1.59 + if (jtreg) { 1.60 + // use standard jtreg scratch directory: the current directory 1.61 + tmpDir = new File(System.getProperty("user.dir")); 1.62 + } else { 1.63 + tmpDir = new File(System.getProperty("java.io.tmpdir"), 1.64 + MessageInfo.class.getName() 1.65 + + (new SimpleDateFormat("yyMMddHHmmss")).format(new Date())); 1.66 + } 1.67 + Example.setTempDir(tmpDir); 1.68 + Example.Compiler.factory = new ArgTypeCompilerFactory(); 1.69 + 1.70 + MessageInfo mi = new MessageInfo(); 1.71 + 1.72 + try { 1.73 + if (mi.run(args)) 1.74 + return; 1.75 + } finally { 1.76 + /* VERY IMPORTANT NOTE. In jtreg mode, tmpDir is set to the 1.77 + * jtreg scratch directory, which is the current directory. 1.78 + * In case someone is faking jtreg mode, make sure to only 1.79 + * clean tmpDir when it is reasonable to do so. 1.80 + */ 1.81 + if (tmpDir.isDirectory() && 1.82 + tmpDir.getName().startsWith(MessageInfo.class.getName())) { 1.83 + if (clean(tmpDir)) 1.84 + tmpDir.delete(); 1.85 + } 1.86 + } 1.87 + 1.88 + if (jtreg) 1.89 + throw new Exception(mi.errors + " errors occurred"); 1.90 + else 1.91 + System.exit(1); 1.92 + } 1.93 + 1.94 + void usage() { 1.95 + System.out.println("Usage:"); 1.96 + System.out.println(" java MessageInfo [options] [file]"); 1.97 + System.out.println("where options include"); 1.98 + System.out.println(" -examples dir location of examples directory"); 1.99 + System.out.println(" -o file output file"); 1.100 + System.out.println(" -check just check message file"); 1.101 + System.out.println(" -ensureNewlines ensure newline after each entry"); 1.102 + System.out.println(" -fixIndent fix indentation of continuation lines"); 1.103 + System.out.println(" -sort sort messages"); 1.104 + System.out.println(" -verbose verbose output"); 1.105 + System.out.println(" -replace replace comments instead of merging comments"); 1.106 + System.out.println(" file javac compiler.properties file"); 1.107 + } 1.108 + 1.109 + boolean run(String... args) { 1.110 + File testSrc = new File(System.getProperty("test.src", ".")); 1.111 + File examplesDir = new File(testSrc, "examples"); 1.112 + File notYetFile = null; 1.113 + File msgFile = null; 1.114 + File outFile = null; 1.115 + boolean verbose = false; 1.116 + boolean ensureNewlines = false; 1.117 + boolean fixIndent = false; 1.118 + boolean sort = false; 1.119 + boolean replace = false; 1.120 + boolean check = jtreg; // default true in jtreg mode 1.121 + 1.122 + for (int i = 0; i < args.length; i++) { 1.123 + String arg = args[i]; 1.124 + if (arg.equals("-examples") && (i + 1) < args.length) 1.125 + examplesDir = new File(args[++i]); 1.126 + else if(arg.equals("-notyet") && (i + 1) < args.length) 1.127 + notYetFile = new File(args[++i]); 1.128 + else if (arg.equals("-ensureNewlines")) 1.129 + ensureNewlines = true; 1.130 + else if (arg.equals("-fixIndent")) 1.131 + fixIndent = true; 1.132 + else if (arg.equals("-sort")) 1.133 + sort = true; 1.134 + else if (arg.equals("-verbose")) 1.135 + verbose = true; 1.136 + else if (arg.equals("-replace")) 1.137 + replace = true; 1.138 + else if (arg.equals("-check")) 1.139 + check = true; 1.140 + else if (arg.equals("-o") && (i + 1) < args.length) 1.141 + outFile = new File(args[++i]); 1.142 + else if (arg.startsWith("-")) { 1.143 + error("unknown option: " + arg); 1.144 + return false; 1.145 + } else if (i == args.length - 1) { 1.146 + msgFile = new File(arg); 1.147 + } else { 1.148 + error("unknown arg: " + arg); 1.149 + return false; 1.150 + } 1.151 + } 1.152 + 1.153 + if (!check && outFile == null) { 1.154 + usage(); 1.155 + return true; 1.156 + } 1.157 + 1.158 + if ((ensureNewlines || fixIndent || sort) && outFile == null) { 1.159 + error("must set output file for these options"); 1.160 + return false; 1.161 + } 1.162 + 1.163 + if (notYetFile == null) { 1.164 + notYetFile = new File(examplesDir.getParentFile(), "examples.not-yet.txt"); 1.165 + } 1.166 + 1.167 + if (msgFile == null) { 1.168 + for (File d = testSrc; d != null; d = d.getParentFile()) { 1.169 + if (new File(d, "TEST.ROOT").exists()) { 1.170 + d = d.getParentFile(); 1.171 + File f = new File(d, "src/share/classes/com/sun/tools/javac/resources/compiler.properties"); 1.172 + if (f.exists()) { 1.173 + msgFile = f; 1.174 + break; 1.175 + } 1.176 + } 1.177 + } 1.178 + if (msgFile == null) { 1.179 + error("no message file available"); 1.180 + return false; 1.181 + } 1.182 + } 1.183 + 1.184 + MessageFile mf; 1.185 + try { 1.186 + mf = new MessageFile(msgFile); 1.187 + } catch (IOException e) { 1.188 + error("problem reading message file: " + e); 1.189 + return false; 1.190 + } 1.191 + 1.192 + Map<String, Set<String>> msgInfo = runExamples(examplesDir, verbose); 1.193 + 1.194 + if (ensureNewlines) 1.195 + ensureNewlines(mf); 1.196 + 1.197 + if (fixIndent) 1.198 + fixIndent(mf); 1.199 + 1.200 + if (sort) 1.201 + sort(mf, true); 1.202 + 1.203 + for (Map.Entry<String, Set<String>> e: msgInfo.entrySet()) { 1.204 + String k = e.getKey(); 1.205 + Set<String> suggestions = e.getValue(); 1.206 + MessageFile.Message m = mf.messages.get(k); 1.207 + if (m == null) { 1.208 + error("Can't find message for " + k + " in message file"); 1.209 + continue; 1.210 + } 1.211 + 1.212 + MessageFile.Info info = m.getInfo(); 1.213 + Set<Integer> placeholders = m.getPlaceholders(); 1.214 + MessageFile.Info suggestedInfo = new MessageFile.Info(suggestions); 1.215 + suggestedInfo.markUnused(placeholders); 1.216 + 1.217 + if (!info.isEmpty()) { 1.218 + if (info.contains(suggestedInfo)) 1.219 + continue; 1.220 + if (!replace) { 1.221 + if (info.fields.size() != suggestedInfo.fields.size()) 1.222 + error("Cannot merge info for " + k); 1.223 + else 1.224 + suggestedInfo.merge(info); 1.225 + } 1.226 + } 1.227 + 1.228 + if (outFile == null) { 1.229 + System.err.println("suggest for " + k); 1.230 + System.err.println(suggestedInfo.toComment()); 1.231 + } else 1.232 + m.setInfo(suggestedInfo); 1.233 + } 1.234 + 1.235 + if (check) 1.236 + check(mf, notYetFile); 1.237 + 1.238 + try { 1.239 + if (outFile != null) 1.240 + mf.write(outFile); 1.241 + } catch (IOException e) { 1.242 + error("problem writing file: " + e); 1.243 + return false; 1.244 + } 1.245 + 1.246 + return (errors == 0); 1.247 + } 1.248 + 1.249 + void check(MessageFile mf, File notYetFile) { 1.250 + Set<String> notYetList = null; 1.251 + for (Map.Entry<String, MessageFile.Message> e: mf.messages.entrySet()) { 1.252 + String key = e.getKey(); 1.253 + MessageFile.Message m = e.getValue(); 1.254 + if (m.needInfo() && m.getInfo().isEmpty()) { 1.255 + if (notYetList == null) 1.256 + notYetList = getNotYetList(notYetFile); 1.257 + if (notYetList.contains(key)) 1.258 + System.err.println("Warning: no info for " + key); 1.259 + else 1.260 + error("no info for " + key); 1.261 + } 1.262 + } 1.263 + 1.264 + } 1.265 + 1.266 + void ensureNewlines(MessageFile mf) { 1.267 + for (MessageFile.Message m: mf.messages.values()) { 1.268 + MessageFile.Line l = m.firstLine; 1.269 + while (l.text.endsWith("\\")) 1.270 + l = l.next; 1.271 + if (l.next != null && !l.next.text.isEmpty()) 1.272 + l.insertAfter(""); 1.273 + } 1.274 + } 1.275 + 1.276 + void fixIndent(MessageFile mf) { 1.277 + for (MessageFile.Message m: mf.messages.values()) { 1.278 + MessageFile.Line l = m.firstLine; 1.279 + while (l.text.endsWith("\\") && l.next != null) { 1.280 + if (!l.next.text.matches("^ \\S.*")) 1.281 + l.next.text = " " + l.next.text.trim(); 1.282 + l = l.next; 1.283 + } 1.284 + } 1.285 + } 1.286 + 1.287 + void sort(MessageFile mf, boolean includePrecedingNewlines) { 1.288 + for (MessageFile.Message m: mf.messages.values()) { 1.289 + for (MessageFile.Line l: m.getLines(includePrecedingNewlines)) { 1.290 + l.remove(); 1.291 + mf.lastLine.insertAfter(l); 1.292 + } 1.293 + } 1.294 + } 1.295 + 1.296 + Map<String, Set<String>> runExamples(File examplesDir, boolean verbose) { 1.297 + Map<String, Set<String>> map = new TreeMap<String, Set<String>>(); 1.298 + for (Example e: getExamples(examplesDir)) { 1.299 + StringWriter sw = new StringWriter(); 1.300 + PrintWriter pw = new PrintWriter(sw); 1.301 + e.run(pw, true, verbose); 1.302 + pw.close(); 1.303 + String[] lines = sw.toString().split("\n"); 1.304 + for (String line: lines) { 1.305 + if (!line.startsWith("compiler.")) 1.306 + continue; 1.307 + int colon = line.indexOf(":"); 1.308 + if (colon == -1) 1.309 + continue; 1.310 + String key = line.substring(0, colon); 1.311 + StringBuilder sb = new StringBuilder(); 1.312 + sb.append("# "); 1.313 + int i = 0; 1.314 + String[] descs = line.substring(colon + 1).split(", *"); 1.315 + for (String desc: descs) { 1.316 + if (i > 0) sb.append(", "); 1.317 + sb.append(i++); 1.318 + sb.append(": "); 1.319 + sb.append(desc.trim()); 1.320 + } 1.321 + Set<String> set = map.get(key); 1.322 + if (set == null) 1.323 + map.put(key, set = new TreeSet<String>()); 1.324 + set.add(sb.toString()); 1.325 + } 1.326 + } 1.327 + 1.328 + return map; 1.329 + } 1.330 + 1.331 + /** 1.332 + * Get the complete set of examples to be checked. 1.333 + */ 1.334 + Set<Example> getExamples(File examplesDir) { 1.335 + Set<Example> results = new TreeSet<Example>(); 1.336 + for (File f: examplesDir.listFiles()) { 1.337 + if (isValidExample(f)) 1.338 + results.add(new Example(f)); 1.339 + } 1.340 + return results; 1.341 + } 1.342 + 1.343 + boolean isValidExample(File f) { 1.344 + return (f.isDirectory() && (!jtreg || f.list().length > 0)) || 1.345 + (f.isFile() && f.getName().endsWith(".java")); 1.346 + } 1.347 + 1.348 + /** 1.349 + * Get the contents of the "not-yet" list. 1.350 + */ 1.351 + Set<String> getNotYetList(File file) { 1.352 + Set<String> results = new TreeSet<String>(); 1.353 + try { 1.354 + String[] lines = read(file).split("[\r\n]"); 1.355 + for (String line: lines) { 1.356 + int hash = line.indexOf("#"); 1.357 + if (hash != -1) 1.358 + line = line.substring(0, hash).trim(); 1.359 + if (line.matches("[A-Za-z0-9-_.]+")) 1.360 + results.add(line); 1.361 + } 1.362 + } catch (IOException e) { 1.363 + throw new Error(e); 1.364 + } 1.365 + return results; 1.366 + } 1.367 + 1.368 + /** 1.369 + * Read the contents of a file. 1.370 + */ 1.371 + String read(File f) throws IOException { 1.372 + byte[] bytes = new byte[(int) f.length()]; 1.373 + DataInputStream in = new DataInputStream(new FileInputStream(f)); 1.374 + try { 1.375 + in.readFully(bytes); 1.376 + } finally { 1.377 + in.close(); 1.378 + } 1.379 + return new String(bytes); 1.380 + } 1.381 + 1.382 + /** 1.383 + * Report an error. 1.384 + */ 1.385 + void error(String msg) { 1.386 + System.err.println("Error: " + msg); 1.387 + errors++; 1.388 + } 1.389 + 1.390 + static boolean jtreg; 1.391 + 1.392 + int errors; 1.393 + 1.394 + /** 1.395 + * Clean the contents of a directory. 1.396 + */ 1.397 + static boolean clean(File dir) { 1.398 + boolean ok = true; 1.399 + for (File f: dir.listFiles()) { 1.400 + if (f.isDirectory()) 1.401 + ok &= clean(f); 1.402 + ok &= f.delete(); 1.403 + } 1.404 + return ok; 1.405 + } 1.406 + 1.407 +} 1.408 + 1.409 +