test/tools/javac/diags/MessageInfo.java

Wed, 06 Apr 2011 20:33:44 -0700

author
ohair
date
Wed, 06 Apr 2011 20:33:44 -0700
changeset 962
0ff2bbd38f10
parent 843
92ab09ed59fd
child 1179
1e2f4f4fb9f7
permissions
-rw-r--r--

7033660: Update copyright year to 2011 on any files changed in 2011
Reviewed-by: dholmes

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

mercurial