test/tools/javac/diags/Example.java

Sat, 07 Nov 2020 10:30:02 +0800

author
aoqi
date
Sat, 07 Nov 2020 10:30:02 +0800
changeset 3938
93012e2a5d1d
parent 2525
2eb010b6cb22
permissions
-rw-r--r--

Added tag mips-jdk8u275-b01 for changeset eb6ee6a5f2fe

     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 import java.io.*;
    25 import java.net.URL;
    26 import java.net.URLClassLoader;
    27 import java.util.*;
    28 import java.util.regex.*;
    29 import javax.annotation.processing.Processor;
    30 import javax.tools.Diagnostic;
    31 import javax.tools.DiagnosticCollector;
    32 import javax.tools.JavaCompiler;
    33 import javax.tools.JavaCompiler.CompilationTask;
    34 import javax.tools.JavaFileObject;
    35 import javax.tools.StandardJavaFileManager;
    36 import javax.tools.ToolProvider;
    38 // The following two classes are both used, but cannot be imported directly
    39 // import com.sun.tools.javac.Main
    40 // import com.sun.tools.javac.main.Main
    42 import com.sun.tools.javac.api.ClientCodeWrapper;
    43 import com.sun.tools.javac.file.JavacFileManager;
    44 import com.sun.tools.javac.main.Main;
    45 import com.sun.tools.javac.util.Context;
    46 import com.sun.tools.javac.util.JavacMessages;
    47 import com.sun.tools.javac.util.JCDiagnostic;
    49 /**
    50  * Class to handle example code designed to illustrate javac diagnostic messages.
    51  */
    52 class Example implements Comparable<Example> {
    53     /* Create an Example from the files found at path.
    54      * The head of the file, up to the first Java code, is scanned
    55      * for information about the test, such as what resource keys it
    56      * generates when run, what options are required to run it, and so on.
    57      */
    58     Example(File file) {
    59         this.file = file;
    60         declaredKeys = new TreeSet<String>();
    61         srcFiles = new ArrayList<File>();
    62         procFiles = new ArrayList<File>();
    63         supportFiles = new ArrayList<File>();
    64         srcPathFiles = new ArrayList<File>();
    66         findFiles(file, srcFiles);
    67         for (File f: srcFiles) {
    68             parse(f);
    69         }
    71         if (infoFile == null)
    72             throw new Error("Example " + file + " has no info file");
    73     }
    75     private void findFiles(File f, List<File> files) {
    76         if (f.isDirectory()) {
    77             for (File c: f.listFiles()) {
    78                 if (files == srcFiles && c.getName().equals("processors"))
    79                     findFiles(c, procFiles);
    80                 else if (files == srcFiles && c.getName().equals("sourcepath")) {
    81                     srcPathDir = c;
    82                     findFiles(c, srcPathFiles);
    83                 } else if (files == srcFiles && c.getName().equals("support"))
    84                     findFiles(c, supportFiles);
    85                 else
    86                     findFiles(c, files);
    87             }
    88         } else if (f.isFile() && f.getName().endsWith(".java")) {
    89             files.add(f);
    90         }
    91     }
    93     private void parse(File f) {
    94         Pattern keyPat = Pattern.compile(" *// *key: *([^ ]+) *");
    95         Pattern optPat = Pattern.compile(" *// *options: *(.*)");
    96         Pattern runPat = Pattern.compile(" *// *run: *(.*)");
    97         Pattern javaPat = Pattern.compile(" *@?[A-Za-z].*");
    98         try {
    99             String[] lines = read(f).split("[\r\n]+");
   100             for (String line: lines) {
   101                 Matcher keyMatch = keyPat.matcher(line);
   102                 if (keyMatch.matches()) {
   103                     foundInfo(f);
   104                     declaredKeys.add(keyMatch.group(1));
   105                     continue;
   106                 }
   107                 Matcher optMatch = optPat.matcher(line);
   108                 if (optMatch.matches()) {
   109                     foundInfo(f);
   110                     options = Arrays.asList(optMatch.group(1).trim().split(" +"));
   111                     continue;
   112                 }
   113                 Matcher runMatch = runPat.matcher(line);
   114                 if (runMatch.matches()) {
   115                     foundInfo(f);
   116                     runOpts = Arrays.asList(runMatch.group(1).trim().split(" +"));
   117                 }
   118                 if (javaPat.matcher(line).matches())
   119                     break;
   120             }
   121         } catch (IOException e) {
   122             throw new Error(e);
   123         }
   124     }
   126     private void foundInfo(File file) {
   127         if (infoFile != null && !infoFile.equals(file))
   128             throw new Error("multiple info files found: " + infoFile + ", " + file);
   129         infoFile = file;
   130     }
   132     String getName() {
   133         return file.getName();
   134     }
   136     /**
   137      * Get the set of resource keys that this test declares it will generate
   138      * when it is run.
   139      */
   140     Set<String> getDeclaredKeys() {
   141         return declaredKeys;
   142     }
   144     /**
   145      * Get the set of resource keys that this test generates when it is run.
   146      * The test will be run if it has not already been run.
   147      */
   148     Set<String> getActualKeys() {
   149         if (actualKeys == null)
   150             actualKeys = run(false);
   151         return actualKeys;
   152     }
   154     /**
   155      * Run the test.  Information in the test header is used to determine
   156      * how to run the test.
   157      */
   158     void run(PrintWriter out, boolean raw, boolean verbose) {
   159         if (out == null)
   160             throw new NullPointerException();
   161         try {
   162             run(out, null, raw, verbose);
   163         } catch (IOException e) {
   164             e.printStackTrace(out);
   165         }
   166     }
   168     Set<String> run(boolean verbose) {
   169         Set<String> keys = new TreeSet<String>();
   170         try {
   171             run(null, keys, true, verbose);
   172         } catch (IOException e) {
   173             e.printStackTrace(System.err);
   174         }
   175         return keys;
   176     }
   178     /**
   179      * Run the test.  Information in the test header is used to determine
   180      * how to run the test.
   181      */
   182     private void run(PrintWriter out, Set<String> keys, boolean raw, boolean verbose)
   183             throws IOException {
   184         ClassLoader loader = getClass().getClassLoader();
   185         if (supportFiles.size() > 0) {
   186             File supportDir = new File(tempDir, "support");
   187             supportDir.mkdirs();
   188             clean(supportDir);
   189             List<String> sOpts = Arrays.asList("-d", supportDir.getPath());
   190             new Jsr199Compiler(verbose).run(null, null, false, sOpts, procFiles);
   191             URLClassLoader ucl =
   192                     new URLClassLoader(new URL[] { supportDir.toURI().toURL() }, loader);
   193             loader = ucl;
   194         }
   196         File classesDir = new File(tempDir, "classes");
   197         classesDir.mkdirs();
   198         clean(classesDir);
   200         List<String> opts = new ArrayList<String>();
   201         opts.add("-d");
   202         opts.add(classesDir.getPath());
   203         if (options != null)
   204             opts.addAll(options);
   206         if (procFiles.size() > 0) {
   207             List<String> pOpts = Arrays.asList("-d", classesDir.getPath());
   208             new Jsr199Compiler(verbose).run(null, null, false, pOpts, procFiles);
   209             opts.add("-classpath"); // avoid using -processorpath for now
   210             opts.add(classesDir.getPath());
   211             createAnnotationServicesFile(classesDir, procFiles);
   212         } else if (options != null) {
   213             int i = options.indexOf("-processor");
   214             // check for built-in anno-processor(s)
   215             if (i != -1 && options.get(i + 1).equals("DocCommentProcessor")) {
   216                 opts.add("-classpath");
   217                 opts.add(System.getProperty("test.classes"));
   218             }
   219         }
   221         if (srcPathDir != null) {
   222             opts.add("-sourcepath");
   223             opts.add(srcPathDir.getPath());
   224         }
   226         try {
   227             Compiler c = Compiler.getCompiler(runOpts, verbose);
   228             c.run(out, keys, raw, opts, srcFiles);
   229         } catch (IllegalArgumentException e) {
   230             if (out != null) {
   231                 out.println("Invalid value for run tag: " + runOpts);
   232             }
   233         }
   234     }
   236     void createAnnotationServicesFile(File dir, List<File> procFiles) throws IOException {
   237         File servicesDir = new File(new File(dir, "META-INF"), "services");
   238         servicesDir.mkdirs();
   239         File annoServices = new File(servicesDir, Processor.class.getName());
   240         Writer out = new FileWriter(annoServices);
   241         try {
   242             for (File f: procFiles) {
   243                 out.write(f.getName().toString().replace(".java", ""));
   244             }
   245         } finally {
   246             out.close();
   247         }
   248     }
   250     @Override
   251     public int compareTo(Example e) {
   252         return file.compareTo(e.file);
   253     }
   255     @Override
   256     public String toString() {
   257         return file.getPath();
   258     }
   260     /**
   261      * Read the contents of a file.
   262      */
   263     private String read(File f) throws IOException {
   264         byte[] bytes = new byte[(int) f.length()];
   265         DataInputStream in = new DataInputStream(new FileInputStream(f));
   266         try {
   267             in.readFully(bytes);
   268         } finally {
   269             in.close();
   270         }
   271         return new String(bytes);
   272     }
   274     /**
   275      * Clean the contents of a directory.
   276      */
   277     boolean clean(File dir) {
   278         boolean ok = true;
   279         for (File f: dir.listFiles()) {
   280             if (f.isDirectory())
   281                 ok &= clean(f);
   282             ok &= f.delete();
   283         }
   284         return ok;
   285     }
   287     File file;
   288     List<File> srcFiles;
   289     List<File> procFiles;
   290     File srcPathDir;
   291     List<File> srcPathFiles;
   292     List<File> supportFiles;
   293     File infoFile;
   294     private List<String> runOpts;
   295     private List<String> options;
   296     private Set<String> actualKeys;
   297     private Set<String> declaredKeys;
   299     static File tempDir = (System.getProperty("test.src") != null) ?
   300             new File(System.getProperty("user.dir")):
   301             new File(System.getProperty("java.io.tmpdir"));
   303     static void setTempDir(File tempDir) {
   304         Example.tempDir = tempDir;
   305     }
   307     abstract static class Compiler {
   308         interface Factory {
   309             Compiler getCompiler(List<String> opts, boolean verbose);
   310         }
   312         static class DefaultFactory implements Factory {
   313             public Compiler getCompiler(List<String> opts, boolean verbose) {
   314             String first;
   315             String[] rest;
   316                 if (opts == null || opts.isEmpty()) {
   317                 first = null;
   318                 rest = new String[0];
   319             } else {
   320                 first = opts.get(0);
   321                 rest = opts.subList(1, opts.size()).toArray(new String[opts.size() - 1]);
   322             }
   323             if (first == null || first.equals("jsr199"))
   324                 return new Jsr199Compiler(verbose, rest);
   325             else if (first.equals("simple"))
   326                 return new SimpleCompiler(verbose);
   327             else if (first.equals("backdoor"))
   328                 return new BackdoorCompiler(verbose);
   329             else
   330                 throw new IllegalArgumentException(first);
   331                 }
   332         }
   334         static Factory factory;
   336         static Compiler getCompiler(List<String> opts, boolean verbose) {
   337             if (factory == null)
   338                 factory = new DefaultFactory();
   340             return factory.getCompiler(opts, verbose);
   341         }
   343         protected Compiler(boolean verbose) {
   344             this.verbose = verbose;
   345         }
   347         abstract boolean run(PrintWriter out, Set<String> keys, boolean raw,
   348                 List<String> opts,  List<File> files);
   350         void setSupportClassLoader(ClassLoader cl) {
   351             loader = cl;
   352         }
   354         protected ClassLoader loader;
   355         protected boolean verbose;
   356     }
   358     /**
   359      * Compile using the JSR 199 API.  The diagnostics generated are
   360      * scanned for resource keys.   Not all diagnostic keys are generated
   361      * via the JSR 199 API -- for example, rich diagnostics are not directly
   362      * accessible, and some diagnostics generated by the file manager may
   363      * not be generated (for example, the JSR 199 file manager does not see
   364      * -Xlint:path).
   365      */
   366     static class Jsr199Compiler extends Compiler {
   367         List<String> fmOpts;
   369         Jsr199Compiler(boolean verbose, String... args) {
   370             super(verbose);
   371             for (int i = 0; i < args.length; i++) {
   372                 String arg = args[i];
   373                 if (arg.equals("-filemanager") && (i + 1 < args.length)) {
   374                     fmOpts = Arrays.asList(args[++i].split(","));
   375                 } else
   376                     throw new IllegalArgumentException(arg);
   377             }
   378         }
   380         @Override
   381         boolean run(PrintWriter out, Set<String> keys, boolean raw, List<String> opts, List<File> files) {
   382             if (out != null && keys != null)
   383                 throw new IllegalArgumentException();
   385             if (verbose)
   386                 System.err.println("run_jsr199: " + opts + " " + files);
   388             DiagnosticCollector<JavaFileObject> dc = null;
   389             if (keys != null)
   390                 dc = new DiagnosticCollector<JavaFileObject>();
   392             if (raw) {
   393                 List<String> newOpts = new ArrayList<String>();
   394                 newOpts.add("-XDrawDiagnostics");
   395                 newOpts.addAll(opts);
   396                 opts = newOpts;
   397             }
   399             JavaCompiler c = ToolProvider.getSystemJavaCompiler();
   401             StandardJavaFileManager fm = c.getStandardFileManager(dc, null, null);
   402             if (fmOpts != null)
   403                 fm = new FileManager(fm, fmOpts);
   405             Iterable<? extends JavaFileObject> fos = fm.getJavaFileObjectsFromFiles(files);
   407             CompilationTask t = c.getTask(out, fm, dc, opts, null, fos);
   408             Boolean ok = t.call();
   410             if (keys != null) {
   411                 for (Diagnostic<? extends JavaFileObject> d: dc.getDiagnostics()) {
   412                     scanForKeys(unwrap(d), keys);
   413                 }
   414             }
   416             return ok;
   417         }
   419         /**
   420          * Scan a diagnostic for resource keys.  This will not detect additional
   421          * sub diagnostics that might be generated by a rich diagnostic formatter.
   422          */
   423         private static void scanForKeys(JCDiagnostic d, Set<String> keys) {
   424             keys.add(d.getCode());
   425             for (Object o: d.getArgs()) {
   426                 if (o instanceof JCDiagnostic) {
   427                     scanForKeys((JCDiagnostic) o, keys);
   428                 }
   429             }
   430             for (JCDiagnostic sd: d.getSubdiagnostics())
   431                 scanForKeys(sd, keys);
   432         }
   434         private JCDiagnostic unwrap(Diagnostic<? extends JavaFileObject> diagnostic) {
   435             if (diagnostic instanceof JCDiagnostic)
   436                 return (JCDiagnostic) diagnostic;
   437             if (diagnostic instanceof ClientCodeWrapper.DiagnosticSourceUnwrapper)
   438                 return ((ClientCodeWrapper.DiagnosticSourceUnwrapper)diagnostic).d;
   439             throw new IllegalArgumentException();
   440         }
   441     }
   443     /**
   444      * Run the test using the standard simple entry point.
   445      */
   446     static class SimpleCompiler extends Compiler {
   447         SimpleCompiler(boolean verbose) {
   448             super(verbose);
   449         }
   451         @Override
   452         boolean run(PrintWriter out, Set<String> keys, boolean raw, List<String> opts, List<File> files) {
   453             if (out != null && keys != null)
   454                 throw new IllegalArgumentException();
   456             if (verbose)
   457                 System.err.println("run_simple: " + opts + " " + files);
   459             List<String> args = new ArrayList<String>();
   461             if (keys != null || raw)
   462                 args.add("-XDrawDiagnostics");
   464             args.addAll(opts);
   465             for (File f: files)
   466                 args.add(f.getPath());
   468             StringWriter sw = null;
   469             PrintWriter pw;
   470             if (keys != null) {
   471                 sw = new StringWriter();
   472                 pw = new PrintWriter(sw);
   473             } else
   474                 pw = out;
   476             int rc = com.sun.tools.javac.Main.compile(args.toArray(new String[args.size()]), pw);
   478             if (keys != null) {
   479                 pw.close();
   480                 scanForKeys(sw.toString(), keys);
   481             }
   483             return (rc == 0);
   484         }
   486         private static void scanForKeys(String text, Set<String> keys) {
   487             StringTokenizer st = new StringTokenizer(text, " ,\r\n():");
   488             while (st.hasMoreElements()) {
   489                 String t = st.nextToken();
   490                 if (t.startsWith("compiler."))
   491                     keys.add(t);
   492             }
   493         }
   494     }
   496     static class BackdoorCompiler extends Compiler {
   497         BackdoorCompiler(boolean verbose) {
   498             super(verbose);
   499         }
   501         @Override
   502         boolean run(PrintWriter out, Set<String> keys, boolean raw, List<String> opts, List<File> files) {
   503             if (out != null && keys != null)
   504                 throw new IllegalArgumentException();
   506             if (verbose)
   507                 System.err.println("run_simple: " + opts + " " + files);
   509             List<String> args = new ArrayList<String>();
   511             if (out != null && raw)
   512                 args.add("-XDrawDiagnostics");
   514             args.addAll(opts);
   515             for (File f: files)
   516                 args.add(f.getPath());
   518             StringWriter sw = null;
   519             PrintWriter pw;
   520             if (keys != null) {
   521                 sw = new StringWriter();
   522                 pw = new PrintWriter(sw);
   523             } else
   524                 pw = out;
   526             Context c = new Context();
   527             JavacFileManager.preRegister(c); // can't create it until Log has been set up
   528             MessageTracker.preRegister(c, keys);
   529             Main m = new Main("javac", pw);
   530             Main.Result rc = m.compile(args.toArray(new String[args.size()]), c);
   532             if (keys != null) {
   533                 pw.close();
   534             }
   536             return rc.isOK();
   537         }
   539         static class MessageTracker extends JavacMessages {
   541             MessageTracker(Context context) {
   542                 super(context);
   543             }
   545             static void preRegister(Context c, final Set<String> keys) {
   546                 if (keys != null) {
   547                     c.put(JavacMessages.messagesKey, new Context.Factory<JavacMessages>() {
   548                         public JavacMessages make(Context c) {
   549                             return new MessageTracker(c) {
   550                                 @Override
   551                                 public String getLocalizedString(Locale l, String key, Object... args) {
   552                                     keys.add(key);
   553                                     return super.getLocalizedString(l, key, args);
   554                                 }
   555                             };
   556                         }
   557                     });
   558                 }
   559             }
   560         }
   562     }
   563 }

mercurial