src/share/classes/com/sun/tools/javah/JavahTask.java

Tue, 12 Oct 2010 13:19:47 -0700

author
jjg
date
Tue, 12 Oct 2010 13:19:47 -0700
changeset 712
a1d31ab7b525
parent 707
33603a5fa84d
child 728
895bea45a3e8
permissions
-rw-r--r--

4942232: missing param class processes without error
Reviewed-by: darcy

     1 /*
     2  * Copyright (c) 2002, 2010, 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.  Oracle designates this
     8  * particular file as subject to the "Classpath" exception as provided
     9  * by Oracle in the LICENSE file that accompanied this code.
    10  *
    11  * This code is distributed in the hope that it will be useful, but WITHOUT
    12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
    13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
    14  * version 2 for more details (a copy is included in the LICENSE file that
    15  * accompanied this code).
    16  *
    17  * You should have received a copy of the GNU General Public License version
    18  * 2 along with this work; if not, write to the Free Software Foundation,
    19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
    20  *
    21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
    22  * or visit www.oracle.com if you need additional information or have any
    23  * questions.
    24  */
    26 package com.sun.tools.javah;
    28 import java.io.File;
    29 import java.io.IOException;
    30 import java.io.OutputStream;
    31 import java.io.PrintWriter;
    32 import java.io.Writer;
    33 import java.text.MessageFormat;
    34 import java.util.ArrayList;
    35 import java.util.Arrays;
    36 import java.util.Collections;
    37 import java.util.HashMap;
    38 import java.util.Iterator;
    39 import java.util.LinkedHashSet;
    40 import java.util.List;
    41 import java.util.Locale;
    42 import java.util.Map;
    43 import java.util.MissingResourceException;
    44 import java.util.ResourceBundle;
    45 import java.util.Set;
    47 import javax.annotation.processing.AbstractProcessor;
    48 import javax.annotation.processing.Messager;
    49 import javax.annotation.processing.ProcessingEnvironment;
    50 import javax.annotation.processing.RoundEnvironment;
    51 import javax.annotation.processing.SupportedAnnotationTypes;
    53 import javax.lang.model.SourceVersion;
    54 import javax.lang.model.element.ExecutableElement;
    55 import javax.lang.model.element.TypeElement;
    56 import javax.lang.model.element.VariableElement;
    57 import javax.lang.model.type.ArrayType;
    58 import javax.lang.model.type.DeclaredType;
    59 import javax.lang.model.type.TypeMirror;
    60 import javax.lang.model.type.TypeVisitor;
    61 import javax.lang.model.util.ElementFilter;
    62 import javax.lang.model.util.SimpleTypeVisitor7;
    63 import javax.lang.model.util.Types;
    65 import javax.tools.Diagnostic;
    66 import javax.tools.DiagnosticListener;
    67 import javax.tools.JavaCompiler;
    68 import javax.tools.JavaCompiler.CompilationTask;
    69 import javax.tools.JavaFileManager;
    70 import javax.tools.JavaFileObject;
    71 import javax.tools.StandardJavaFileManager;
    72 import javax.tools.StandardLocation;
    73 import javax.tools.ToolProvider;
    74 import static javax.tools.Diagnostic.Kind.*;
    76 import com.sun.tools.javac.code.Symbol.CompletionFailure;
    78 /**
    79  * Javah generates support files for native methods.
    80  * Parse commandline options & Invokes javadoc to execute those commands.
    81  *
    82  * <p><b>This is NOT part of any supported API.
    83  * If you write code that depends on this, you do so at your own
    84  * risk.  This code and its internal interfaces are subject to change
    85  * or deletion without notice.</b></p>
    86  *
    87  * @author Sucheta Dambalkar
    88  * @author Jonathan Gibbons
    89  */
    90 public class JavahTask implements NativeHeaderTool.NativeHeaderTask {
    91     public class BadArgs extends Exception {
    92         private static final long serialVersionUID = 1479361270874789045L;
    93         BadArgs(String key, Object... args) {
    94             super(JavahTask.this.getMessage(key, args));
    95             this.key = key;
    96             this.args = args;
    97         }
    99         BadArgs showUsage(boolean b) {
   100             showUsage = b;
   101             return this;
   102         }
   104         final String key;
   105         final Object[] args;
   106         boolean showUsage;
   107     }
   109     static abstract class Option {
   110         Option(boolean hasArg, String... aliases) {
   111             this.hasArg = hasArg;
   112             this.aliases = aliases;
   113         }
   115         boolean isHidden() {
   116             return false;
   117         }
   119         boolean matches(String opt) {
   120             for (String a: aliases) {
   121                 if (a.equals(opt))
   122                     return true;
   123             }
   124             return false;
   125         }
   127         boolean ignoreRest() {
   128             return false;
   129         }
   131         abstract void process(JavahTask task, String opt, String arg) throws BadArgs;
   133         final boolean hasArg;
   134         final String[] aliases;
   135     }
   137     static abstract class HiddenOption extends Option {
   138         HiddenOption(boolean hasArg, String... aliases) {
   139             super(hasArg, aliases);
   140         }
   142         @Override
   143         boolean isHidden() {
   144             return true;
   145         }
   146     }
   148     static Option[] recognizedOptions = {
   149         new Option(true, "-o") {
   150             void process(JavahTask task, String opt, String arg) {
   151                 task.ofile = new File(arg);
   152             }
   153         },
   155         new Option(true, "-d") {
   156             void process(JavahTask task, String opt, String arg) {
   157                 task.odir = new File(arg);
   158             }
   159         },
   161         new HiddenOption(true, "-td") {
   162             void process(JavahTask task, String opt, String arg) {
   163                  // ignored; for backwards compatibility
   164             }
   165         },
   167         new HiddenOption(false, "-stubs") {
   168             void process(JavahTask task, String opt, String arg) {
   169                  // ignored; for backwards compatibility
   170             }
   171         },
   173         new Option(false, "-v", "-verbose") {
   174             void process(JavahTask task, String opt, String arg) {
   175                 task.verbose = true;
   176             }
   177         },
   179         new Option(false, "-h", "-help", "--help", "-?") {
   180             void process(JavahTask task, String opt, String arg) {
   181                 task.help = true;
   182             }
   183         },
   185         new HiddenOption(false, "-trace") {
   186             void process(JavahTask task, String opt, String arg) {
   187                 task.trace = true;
   188             }
   189         },
   191         new Option(false, "-version") {
   192             void process(JavahTask task, String opt, String arg) {
   193                 task.version = true;
   194             }
   195         },
   197         new HiddenOption(false, "-fullversion") {
   198             void process(JavahTask task, String opt, String arg) {
   199                 task.fullVersion = true;
   200             }
   201         },
   203         new Option(false, "-jni") {
   204             void process(JavahTask task, String opt, String arg) {
   205                 task.jni = true;
   206             }
   207         },
   209         new Option(false, "-force") {
   210             void process(JavahTask task, String opt, String arg) {
   211                 task.force = true;
   212             }
   213         },
   215         new HiddenOption(false, "-Xnew") {
   216             void process(JavahTask task, String opt, String arg) {
   217                 // we're already using the new javah
   218             }
   219         },
   221         new HiddenOption(false, "-old") {
   222             void process(JavahTask task, String opt, String arg) {
   223                 task.old = true;
   224             }
   225         },
   227         new HiddenOption(false, "-llni", "-Xllni") {
   228             void process(JavahTask task, String opt, String arg) {
   229                 task.llni = true;
   230             }
   231         },
   233         new HiddenOption(false, "-llnidouble") {
   234             void process(JavahTask task, String opt, String arg) {
   235                 task.llni = true;
   236                 task.doubleAlign = true;
   237             }
   238         },
   240         new HiddenOption(false) {
   241             boolean matches(String opt) {
   242                 return opt.startsWith("-XD");
   243             }
   244             void process(JavahTask task, String opt, String arg) {
   245                 task.javac_extras.add(opt);
   246             }
   247         },
   248     };
   250     JavahTask() {
   251     }
   253     JavahTask(Writer out,
   254             JavaFileManager fileManager,
   255             DiagnosticListener<? super JavaFileObject> diagnosticListener,
   256             Iterable<String> options,
   257             Iterable<String> classes) {
   258         this();
   259         this.log = getPrintWriterForWriter(out);
   260         this.fileManager = fileManager;
   261         this.diagnosticListener = diagnosticListener;
   263         try {
   264             handleOptions(options, false);
   265         } catch (BadArgs e) {
   266             throw new IllegalArgumentException(e.getMessage());
   267         }
   269         this.classes = new ArrayList<String>();
   270         if (classes != null) {
   271             for (String classname: classes) {
   272                 classname.getClass(); // null-check
   273                 this.classes.add(classname);
   274             }
   275         }
   276     }
   278     public void setLocale(Locale locale) {
   279         if (locale == null)
   280             locale = Locale.getDefault();
   281         task_locale = locale;
   282     }
   284     public void setLog(PrintWriter log) {
   285         this.log = log;
   286     }
   288     public void setLog(OutputStream s) {
   289         setLog(getPrintWriterForStream(s));
   290     }
   292     static PrintWriter getPrintWriterForStream(OutputStream s) {
   293         return new PrintWriter(s, true);
   294     }
   296     static PrintWriter getPrintWriterForWriter(Writer w) {
   297         if (w == null)
   298             return getPrintWriterForStream(null);
   299         else if (w instanceof PrintWriter)
   300             return (PrintWriter) w;
   301         else
   302             return new PrintWriter(w, true);
   303     }
   305     public void setDiagnosticListener(DiagnosticListener<? super JavaFileObject> dl) {
   306         diagnosticListener = dl;
   307     }
   309     public void setDiagnosticListener(OutputStream s) {
   310         setDiagnosticListener(getDiagnosticListenerForStream(s));
   311     }
   313     private DiagnosticListener<JavaFileObject> getDiagnosticListenerForStream(OutputStream s) {
   314         return getDiagnosticListenerForWriter(getPrintWriterForStream(s));
   315     }
   317     private DiagnosticListener<JavaFileObject> getDiagnosticListenerForWriter(Writer w) {
   318         final PrintWriter pw = getPrintWriterForWriter(w);
   319         return new DiagnosticListener<JavaFileObject> () {
   320             public void report(Diagnostic<? extends JavaFileObject> diagnostic) {
   321                 if (diagnostic.getKind() == Diagnostic.Kind.ERROR) {
   322                     pw.print(getMessage("err.prefix"));
   323                     pw.print(" ");
   324                 }
   325                 pw.println(diagnostic.getMessage(null));
   326             }
   327         };
   328     }
   330     int run(String[] args) {
   331         try {
   332             handleOptions(args);
   333             boolean ok = run();
   334             return ok ? 0 : 1;
   335         } catch (BadArgs e) {
   336             diagnosticListener.report(createDiagnostic(e.key, e.args));
   337             return 1;
   338         } catch (InternalError e) {
   339             diagnosticListener.report(createDiagnostic("err.internal.error", e.getMessage()));
   340             return 1;
   341         } catch (Util.Exit e) {
   342             return e.exitValue;
   343         } finally {
   344             log.flush();
   345         }
   346     }
   348     public void handleOptions(String[] args) throws BadArgs {
   349         handleOptions(Arrays.asList(args), true);
   350     }
   352     private void handleOptions(Iterable<String> args, boolean allowClasses) throws BadArgs {
   353         if (log == null) {
   354             log = getPrintWriterForStream(System.out);
   355             if (diagnosticListener == null)
   356               diagnosticListener = getDiagnosticListenerForStream(System.err);
   357         } else {
   358             if (diagnosticListener == null)
   359               diagnosticListener = getDiagnosticListenerForWriter(log);
   360         }
   362         if (fileManager == null)
   363             fileManager = getDefaultFileManager(diagnosticListener, log);
   365         Iterator<String> iter = args.iterator();
   366         noArgs = !iter.hasNext();
   368         while (iter.hasNext()) {
   369             String arg = iter.next();
   370             if (arg.startsWith("-"))
   371                 handleOption(arg, iter);
   372             else if (allowClasses) {
   373                 if (classes == null)
   374                     classes = new ArrayList<String>();
   375                 classes.add(arg);
   376                 while (iter.hasNext())
   377                     classes.add(iter.next());
   378             } else
   379                 throw new BadArgs("err.unknown.option", arg).showUsage(true);
   380         }
   382         if ((classes == null || classes.size() == 0) &&
   383                 !(noArgs || help || version || fullVersion)) {
   384             throw new BadArgs("err.no.classes.specified");
   385         }
   387         if (jni && llni)
   388             throw new BadArgs("jni.llni.mixed");
   390         if (odir != null && ofile != null)
   391             throw new BadArgs("dir.file.mixed");
   392     }
   394     private void handleOption(String name, Iterator<String> rest) throws BadArgs {
   395         for (Option o: recognizedOptions) {
   396             if (o.matches(name)) {
   397                 if (o.hasArg) {
   398                     if (rest.hasNext())
   399                         o.process(this, name, rest.next());
   400                     else
   401                         throw new BadArgs("err.missing.arg", name).showUsage(true);
   402                 } else
   403                     o.process(this, name, null);
   405                 if (o.ignoreRest()) {
   406                     while (rest.hasNext())
   407                         rest.next();
   408                 }
   409                 return;
   410             }
   411         }
   413         if (fileManager.handleOption(name, rest))
   414             return;
   416         throw new BadArgs("err.unknown.option", name).showUsage(true);
   417     }
   419     public Boolean call() {
   420         return run();
   421     }
   423     public boolean run() throws Util.Exit {
   425         Util util = new Util(log, diagnosticListener);
   427         if (noArgs || help) {
   428             showHelp();
   429             return help; // treat noArgs as an error for purposes of exit code
   430         }
   432         if (version || fullVersion) {
   433             showVersion(fullVersion);
   434             return true;
   435         }
   437         util.verbose = verbose;
   439         Gen g;
   441         if (llni)
   442             g = new LLNI(doubleAlign, util);
   443         else {
   444 //            if (stubs)
   445 //                throw new BadArgs("jni.no.stubs");
   446             g = new JNI(util);
   447         }
   449         if (ofile != null) {
   450             if (!(fileManager instanceof StandardJavaFileManager)) {
   451                 diagnosticListener.report(createDiagnostic("err.cant.use.option.for.fm", "-o"));
   452                 return false;
   453             }
   454             Iterable<? extends JavaFileObject> iter =
   455                     ((StandardJavaFileManager) fileManager).getJavaFileObjectsFromFiles(Collections.singleton(ofile));
   456             JavaFileObject fo = iter.iterator().next();
   457             g.setOutFile(fo);
   458         } else {
   459             if (odir != null) {
   460                 if (!(fileManager instanceof StandardJavaFileManager)) {
   461                     diagnosticListener.report(createDiagnostic("err.cant.use.option.for.fm", "-d"));
   462                     return false;
   463                 }
   465                 if (!odir.exists())
   466                     if (!odir.mkdirs())
   467                         util.error("cant.create.dir", odir.toString());
   468                 try {
   469                     ((StandardJavaFileManager) fileManager).setLocation(StandardLocation.CLASS_OUTPUT, Collections.singleton(odir));
   470                 } catch (IOException e) {
   471                     Object msg = e.getLocalizedMessage();
   472                     if (msg == null) {
   473                         msg = e;
   474                     }
   475                     diagnosticListener.report(createDiagnostic("err.ioerror", odir, msg));
   476                     return false;
   477                 }
   478             }
   479             g.setFileManager(fileManager);
   480         }
   482         /*
   483          * Force set to false will turn off smarts about checking file
   484          * content before writing.
   485          */
   486         g.setForce(force);
   488         if (fileManager instanceof JavahFileManager)
   489             ((JavahFileManager) fileManager).setIgnoreSymbolFile(true);
   491         JavaCompiler c = ToolProvider.getSystemJavaCompiler();
   492         List<String> opts = new ArrayList<String>();
   493         opts.add("-proc:only");
   494         opts.addAll(javac_extras);
   495         CompilationTask t = c.getTask(log, fileManager, diagnosticListener, opts, internalize(classes), null);
   496         JavahProcessor p = new JavahProcessor(g);
   497         t.setProcessors(Collections.singleton(p));
   499         boolean ok = t.call();
   500         if (p.exit != null)
   501             throw new Util.Exit(p.exit);
   502         return ok;
   503     }
   505     private List<String> internalize(List<String> classes) {
   506         List<String> l = new ArrayList<String>();
   507         for (String c: classes) {
   508             l.add(c.replace('$', '.'));
   509         }
   510         return l;
   511     }
   513     private List<File> pathToFiles(String path) {
   514         List<File> files = new ArrayList<File>();
   515         for (String f: path.split(File.pathSeparator)) {
   516             if (f.length() > 0)
   517                 files.add(new File(f));
   518         }
   519         return files;
   520     }
   522     static StandardJavaFileManager getDefaultFileManager(final DiagnosticListener<? super JavaFileObject> dl, PrintWriter log) {
   523         return JavahFileManager.create(dl, log);
   524     }
   526     private void showHelp() {
   527         log.println(getMessage("main.usage", progname));
   528         for (Option o: recognizedOptions) {
   529             if (o.isHidden())
   530                 continue;
   531             String name = o.aliases[0].substring(1); // there must always be at least one name
   532             log.println(getMessage("main.opt." + name));
   533         }
   534         String[] fmOptions = { "-classpath", "-bootclasspath" };
   535         for (String o: fmOptions) {
   536             if (fileManager.isSupportedOption(o) == -1)
   537                 continue;
   538             String name = o.substring(1);
   539             log.println(getMessage("main.opt." + name));
   540         }
   541         log.println(getMessage("main.usage.foot"));
   542     }
   544     private void showVersion(boolean full) {
   545         log.println(version(full));
   546     }
   548     private static final String versionRBName = "com.sun.tools.javah.resources.version";
   549     private static ResourceBundle versionRB;
   551     private String version(boolean full) {
   552         String msgKey = (full ? "javah.fullVersion" : "javah.version");
   553         String versionKey = (full ? "full" : "release");
   554         // versionKey=product:  mm.nn.oo[-milestone]
   555         // versionKey=full:     mm.mm.oo[-milestone]-build
   556         if (versionRB == null) {
   557             try {
   558                 versionRB = ResourceBundle.getBundle(versionRBName);
   559             } catch (MissingResourceException e) {
   560                 return getMessage("version.resource.missing", System.getProperty("java.version"));
   561             }
   562         }
   563         try {
   564             return getMessage(msgKey, "javah", versionRB.getString(versionKey));
   565         }
   566         catch (MissingResourceException e) {
   567             return getMessage("version.unknown", System.getProperty("java.version"));
   568         }
   569     }
   571     private Diagnostic<JavaFileObject> createDiagnostic(final String key, final Object... args) {
   572         return new Diagnostic<JavaFileObject>() {
   573             public Kind getKind() {
   574                 return Diagnostic.Kind.ERROR;
   575             }
   577             public JavaFileObject getSource() {
   578                 return null;
   579             }
   581             public long getPosition() {
   582                 return Diagnostic.NOPOS;
   583             }
   585             public long getStartPosition() {
   586                 return Diagnostic.NOPOS;
   587             }
   589             public long getEndPosition() {
   590                 return Diagnostic.NOPOS;
   591             }
   593             public long getLineNumber() {
   594                 return Diagnostic.NOPOS;
   595             }
   597             public long getColumnNumber() {
   598                 return Diagnostic.NOPOS;
   599             }
   601             public String getCode() {
   602                 return key;
   603             }
   605             public String getMessage(Locale locale) {
   606                 return JavahTask.this.getMessage(locale, key, args);
   607             }
   609         };
   611     }
   612     private String getMessage(String key, Object... args) {
   613         return getMessage(task_locale, key, args);
   614     }
   616     private String getMessage(Locale locale, String key, Object... args) {
   617         if (bundles == null) {
   618             // could make this a HashMap<Locale,SoftReference<ResourceBundle>>
   619             // and for efficiency, keep a hard reference to the bundle for the task
   620             // locale
   621             bundles = new HashMap<Locale, ResourceBundle>();
   622         }
   624         if (locale == null)
   625             locale = Locale.getDefault();
   627         ResourceBundle b = bundles.get(locale);
   628         if (b == null) {
   629             try {
   630                 b = ResourceBundle.getBundle("com.sun.tools.javah.resources.l10n", locale);
   631                 bundles.put(locale, b);
   632             } catch (MissingResourceException e) {
   633                 throw new InternalError("Cannot find javah resource bundle for locale " + locale, e);
   634             }
   635         }
   637         try {
   638             return MessageFormat.format(b.getString(key), args);
   639         } catch (MissingResourceException e) {
   640             return key;
   641             //throw new InternalError(e, key);
   642         }
   643     }
   645     File ofile;
   646     File odir;
   647     String bootcp;
   648     String usercp;
   649     List<String> classes;
   650     boolean verbose;
   651     boolean noArgs;
   652     boolean help;
   653     boolean trace;
   654     boolean version;
   655     boolean fullVersion;
   656     boolean jni;
   657     boolean llni;
   658     boolean doubleAlign;
   659     boolean force;
   660     boolean old;
   661     Set<String> javac_extras = new LinkedHashSet<String>();
   663     PrintWriter log;
   664     JavaFileManager fileManager;
   665     DiagnosticListener<? super JavaFileObject> diagnosticListener;
   666     Locale task_locale;
   667     Map<Locale, ResourceBundle> bundles;
   669     private static final String progname = "javah";
   671     @SupportedAnnotationTypes("*")
   672     class JavahProcessor extends AbstractProcessor {
   673         private Messager messager;
   675         JavahProcessor(Gen g) {
   676             this.g = g;
   677         }
   679         @Override
   680         public SourceVersion getSupportedSourceVersion() {
   681             // since this is co-bundled with javac, we can assume it supports
   682             // the latest source version
   683             return SourceVersion.latest();
   684         }
   686         @Override
   687         public void init(ProcessingEnvironment pEnv) {
   688             super.init(pEnv);
   689             messager  = processingEnv.getMessager();
   690         }
   692         public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
   693             try {
   694                 Set<TypeElement> classes = getAllClasses(ElementFilter.typesIn(roundEnv.getRootElements()));
   695                 if (classes.size() > 0) {
   696                     checkMethodParameters(classes);
   697                     g.setProcessingEnvironment(processingEnv);
   698                     g.setClasses(classes);
   699                     g.run();
   700                 }
   701             } catch (CompletionFailure cf) {
   702                 messager.printMessage(ERROR, getMessage("class.not.found", cf.sym.getQualifiedName().toString()));
   703             } catch (ClassNotFoundException cnfe) {
   704                 messager.printMessage(ERROR, getMessage("class.not.found", cnfe.getMessage()));
   705             } catch (IOException ioe) {
   706                 messager.printMessage(ERROR, getMessage("io.exception", ioe.getMessage()));
   707             } catch (Util.Exit e) {
   708                 exit = e;
   709             }
   711             return true;
   712         }
   714         private Set<TypeElement> getAllClasses(Set<? extends TypeElement> classes) {
   715             Set<TypeElement> allClasses = new LinkedHashSet<TypeElement>();
   716             getAllClasses0(classes, allClasses);
   717             return allClasses;
   718         }
   720         private void getAllClasses0(Iterable<? extends TypeElement> classes, Set<TypeElement> allClasses) {
   721             for (TypeElement c: classes) {
   722                 allClasses.add(c);
   723                 getAllClasses0(ElementFilter.typesIn(c.getEnclosedElements()), allClasses);
   724             }
   725         }
   727         // 4942232:
   728         // check that classes exist for all the parameters of native methods
   729         private void checkMethodParameters(Set<TypeElement> classes) {
   730             Types types = processingEnv.getTypeUtils();
   731             for (TypeElement te: classes) {
   732                 for (ExecutableElement ee: ElementFilter.methodsIn(te.getEnclosedElements())) {
   733                     for (VariableElement ve: ee.getParameters()) {
   734                         TypeMirror tm = ve.asType();
   735                         checkMethodParametersVisitor.visit(tm, types);
   736                     }
   737                 }
   738             }
   739         }
   741         private TypeVisitor<Void,Types> checkMethodParametersVisitor =
   742                 new SimpleTypeVisitor7<Void,Types>() {
   743             @Override
   744             public Void visitArray(ArrayType t, Types types) {
   745                 visit(t.getComponentType(), types);
   746                 return null;
   747             }
   748             @Override
   749             public Void visitDeclared(DeclaredType t, Types types) {
   750                 t.asElement().getKind(); // ensure class exists
   751                 for (TypeMirror st: types.directSupertypes(t))
   752                     visit(st, types);
   753                 return null;
   754             }
   755         };
   757         private Gen g;
   758         private Util.Exit exit;
   759     }
   760 }

mercurial