src/jdk.compiler/share/classes/com/sun/tools/javac/processing/JavacProcessingEnvironment.java
changeset 47216 71c04702a3d5
parent 45744 db6aedca2c8c
child 48054 702043a4cdeb
equal deleted inserted replaced
47215:4ebc2e2fb97c 47216:71c04702a3d5
       
     1 /*
       
     2  * Copyright (c) 2005, 2017, 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  */
       
    25 
       
    26 package com.sun.tools.javac.processing;
       
    27 
       
    28 import java.io.Closeable;
       
    29 import java.io.IOException;
       
    30 import java.io.PrintWriter;
       
    31 import java.io.StringWriter;
       
    32 import java.lang.reflect.Method;
       
    33 import java.net.MalformedURLException;
       
    34 import java.net.URL;
       
    35 import java.nio.file.Path;
       
    36 import java.util.*;
       
    37 import java.util.Map.Entry;
       
    38 import java.util.regex.*;
       
    39 import java.util.stream.Collectors;
       
    40 
       
    41 import javax.annotation.processing.*;
       
    42 import javax.lang.model.SourceVersion;
       
    43 import javax.lang.model.element.*;
       
    44 import javax.lang.model.util.*;
       
    45 import javax.tools.JavaFileManager;
       
    46 import javax.tools.JavaFileObject;
       
    47 import javax.tools.JavaFileObject.Kind;
       
    48 import javax.tools.StandardJavaFileManager;
       
    49 
       
    50 import static javax.tools.StandardLocation.*;
       
    51 
       
    52 import com.sun.source.util.TaskEvent;
       
    53 import com.sun.tools.javac.api.MultiTaskListener;
       
    54 import com.sun.tools.javac.code.*;
       
    55 import com.sun.tools.javac.code.Scope.WriteableScope;
       
    56 import com.sun.tools.javac.code.Symbol.*;
       
    57 import com.sun.tools.javac.code.Type.ClassType;
       
    58 import com.sun.tools.javac.code.Types;
       
    59 import com.sun.tools.javac.comp.AttrContext;
       
    60 import com.sun.tools.javac.comp.Check;
       
    61 import com.sun.tools.javac.comp.Enter;
       
    62 import com.sun.tools.javac.comp.Env;
       
    63 import com.sun.tools.javac.comp.Modules;
       
    64 import com.sun.tools.javac.file.JavacFileManager;
       
    65 import com.sun.tools.javac.main.JavaCompiler;
       
    66 import com.sun.tools.javac.main.Option;
       
    67 import com.sun.tools.javac.model.JavacElements;
       
    68 import com.sun.tools.javac.model.JavacTypes;
       
    69 import com.sun.tools.javac.platform.PlatformDescription;
       
    70 import com.sun.tools.javac.platform.PlatformDescription.PluginInfo;
       
    71 import com.sun.tools.javac.resources.CompilerProperties.Errors;
       
    72 import com.sun.tools.javac.resources.CompilerProperties.Warnings;
       
    73 import com.sun.tools.javac.tree.*;
       
    74 import com.sun.tools.javac.tree.JCTree.*;
       
    75 import com.sun.tools.javac.util.Abort;
       
    76 import com.sun.tools.javac.util.Assert;
       
    77 import com.sun.tools.javac.util.ClientCodeException;
       
    78 import com.sun.tools.javac.util.Context;
       
    79 import com.sun.tools.javac.util.Convert;
       
    80 import com.sun.tools.javac.util.DefinedBy;
       
    81 import com.sun.tools.javac.util.DefinedBy.Api;
       
    82 import com.sun.tools.javac.util.Iterators;
       
    83 import com.sun.tools.javac.util.JCDiagnostic;
       
    84 import com.sun.tools.javac.util.JDK9Wrappers.Module;
       
    85 import com.sun.tools.javac.util.JavacMessages;
       
    86 import com.sun.tools.javac.util.List;
       
    87 import com.sun.tools.javac.util.Log;
       
    88 import com.sun.tools.javac.util.MatchingUtils;
       
    89 import com.sun.tools.javac.util.ModuleHelper;
       
    90 import com.sun.tools.javac.util.Name;
       
    91 import com.sun.tools.javac.util.Names;
       
    92 import com.sun.tools.javac.util.Options;
       
    93 
       
    94 import static com.sun.tools.javac.code.Lint.LintCategory.PROCESSING;
       
    95 import static com.sun.tools.javac.code.Kinds.Kind.*;
       
    96 import com.sun.tools.javac.comp.Annotate;
       
    97 import static com.sun.tools.javac.comp.CompileStates.CompileState;
       
    98 import static com.sun.tools.javac.util.JCDiagnostic.DiagnosticFlag.*;
       
    99 
       
   100 /**
       
   101  * Objects of this class hold and manage the state needed to support
       
   102  * annotation processing.
       
   103  *
       
   104  * <p><b>This is NOT part of any supported API.
       
   105  * If you write code that depends on this, you do so at your own risk.
       
   106  * This code and its internal interfaces are subject to change or
       
   107  * deletion without notice.</b>
       
   108  */
       
   109 public class JavacProcessingEnvironment implements ProcessingEnvironment, Closeable {
       
   110     private final Options options;
       
   111 
       
   112     private final boolean printProcessorInfo;
       
   113     private final boolean printRounds;
       
   114     private final boolean verbose;
       
   115     private final boolean lint;
       
   116     private final boolean fatalErrors;
       
   117     private final boolean werror;
       
   118     private final boolean showResolveErrors;
       
   119     private final boolean allowModules;
       
   120 
       
   121     private final JavacFiler filer;
       
   122     private final JavacMessager messager;
       
   123     private final JavacElements elementUtils;
       
   124     private final JavacTypes typeUtils;
       
   125     private final JavaCompiler compiler;
       
   126     private final Modules modules;
       
   127     private final Types types;
       
   128     private final Annotate annotate;
       
   129 
       
   130     /**
       
   131      * Holds relevant state history of which processors have been
       
   132      * used.
       
   133      */
       
   134     private DiscoveredProcessors discoveredProcs;
       
   135 
       
   136     /**
       
   137      * Map of processor-specific options.
       
   138      */
       
   139     private final Map<String, String> processorOptions;
       
   140 
       
   141     /**
       
   142      */
       
   143     private final Set<String> unmatchedProcessorOptions;
       
   144 
       
   145     /**
       
   146      * Annotations implicitly processed and claimed by javac.
       
   147      */
       
   148     private final Set<String> platformAnnotations;
       
   149 
       
   150     /**
       
   151      * Set of packages given on command line.
       
   152      */
       
   153     private Set<PackageSymbol> specifiedPackages = Collections.emptySet();
       
   154 
       
   155     /** The log to be used for error reporting.
       
   156      */
       
   157     final Log log;
       
   158 
       
   159     /** Diagnostic factory.
       
   160      */
       
   161     JCDiagnostic.Factory diags;
       
   162 
       
   163     /**
       
   164      * Source level of the compile.
       
   165      */
       
   166     Source source;
       
   167 
       
   168     private ClassLoader processorClassLoader;
       
   169     private ServiceLoader<Processor> serviceLoader;
       
   170     private SecurityException processorLoaderException;
       
   171 
       
   172     private final JavaFileManager fileManager;
       
   173 
       
   174     /**
       
   175      * JavacMessages object used for localization
       
   176      */
       
   177     private JavacMessages messages;
       
   178 
       
   179     private MultiTaskListener taskListener;
       
   180     private final Symtab symtab;
       
   181     private final Names names;
       
   182     private final Enter enter;
       
   183     private final Completer initialCompleter;
       
   184     private final Check chk;
       
   185 
       
   186     private final Context context;
       
   187 
       
   188     /** Get the JavacProcessingEnvironment instance for this context. */
       
   189     public static JavacProcessingEnvironment instance(Context context) {
       
   190         JavacProcessingEnvironment instance = context.get(JavacProcessingEnvironment.class);
       
   191         if (instance == null)
       
   192             instance = new JavacProcessingEnvironment(context);
       
   193         return instance;
       
   194     }
       
   195 
       
   196     protected JavacProcessingEnvironment(Context context) {
       
   197         this.context = context;
       
   198         context.put(JavacProcessingEnvironment.class, this);
       
   199         log = Log.instance(context);
       
   200         source = Source.instance(context);
       
   201         diags = JCDiagnostic.Factory.instance(context);
       
   202         options = Options.instance(context);
       
   203         printProcessorInfo = options.isSet(Option.XPRINTPROCESSORINFO);
       
   204         printRounds = options.isSet(Option.XPRINTROUNDS);
       
   205         verbose = options.isSet(Option.VERBOSE);
       
   206         lint = Lint.instance(context).isEnabled(PROCESSING);
       
   207         compiler = JavaCompiler.instance(context);
       
   208         if (options.isSet(Option.PROC, "only") || options.isSet(Option.XPRINT)) {
       
   209             compiler.shouldStopPolicyIfNoError = CompileState.PROCESS;
       
   210         }
       
   211         fatalErrors = options.isSet("fatalEnterError");
       
   212         showResolveErrors = options.isSet("showResolveErrors");
       
   213         werror = options.isSet(Option.WERROR);
       
   214         fileManager = context.get(JavaFileManager.class);
       
   215         platformAnnotations = initPlatformAnnotations();
       
   216 
       
   217         // Initialize services before any processors are initialized
       
   218         // in case processors use them.
       
   219         filer = new JavacFiler(context);
       
   220         messager = new JavacMessager(context, this);
       
   221         elementUtils = JavacElements.instance(context);
       
   222         typeUtils = JavacTypes.instance(context);
       
   223         modules = Modules.instance(context);
       
   224         types = Types.instance(context);
       
   225         annotate = Annotate.instance(context);
       
   226         processorOptions = initProcessorOptions();
       
   227         unmatchedProcessorOptions = initUnmatchedProcessorOptions();
       
   228         messages = JavacMessages.instance(context);
       
   229         taskListener = MultiTaskListener.instance(context);
       
   230         symtab = Symtab.instance(context);
       
   231         names = Names.instance(context);
       
   232         enter = Enter.instance(context);
       
   233         initialCompleter = ClassFinder.instance(context).getCompleter();
       
   234         chk = Check.instance(context);
       
   235         initProcessorLoader();
       
   236 
       
   237         allowModules = source.allowModules();
       
   238     }
       
   239 
       
   240     public void setProcessors(Iterable<? extends Processor> processors) {
       
   241         Assert.checkNull(discoveredProcs);
       
   242         initProcessorIterator(processors);
       
   243     }
       
   244 
       
   245     private Set<String> initPlatformAnnotations() {
       
   246         Set<String> platformAnnotations = new HashSet<>();
       
   247         platformAnnotations.add("java.lang.Deprecated");
       
   248         platformAnnotations.add("java.lang.Override");
       
   249         platformAnnotations.add("java.lang.SuppressWarnings");
       
   250         platformAnnotations.add("java.lang.annotation.Documented");
       
   251         platformAnnotations.add("java.lang.annotation.Inherited");
       
   252         platformAnnotations.add("java.lang.annotation.Retention");
       
   253         platformAnnotations.add("java.lang.annotation.Target");
       
   254         return Collections.unmodifiableSet(platformAnnotations);
       
   255     }
       
   256 
       
   257     private void initProcessorLoader() {
       
   258         try {
       
   259             if (fileManager.hasLocation(ANNOTATION_PROCESSOR_MODULE_PATH)) {
       
   260                 try {
       
   261                     serviceLoader = fileManager.getServiceLoader(ANNOTATION_PROCESSOR_MODULE_PATH, Processor.class);
       
   262                 } catch (IOException e) {
       
   263                     throw new Abort(e);
       
   264                 }
       
   265             } else {
       
   266                 // If processorpath is not explicitly set, use the classpath.
       
   267                 processorClassLoader = fileManager.hasLocation(ANNOTATION_PROCESSOR_PATH)
       
   268                     ? fileManager.getClassLoader(ANNOTATION_PROCESSOR_PATH)
       
   269                     : fileManager.getClassLoader(CLASS_PATH);
       
   270 
       
   271                 if (options.isSet("accessInternalAPI"))
       
   272                     ModuleHelper.addExports(Module.getModule(getClass()), Module.getUnnamedModule(processorClassLoader));
       
   273 
       
   274                 if (processorClassLoader != null && processorClassLoader instanceof Closeable) {
       
   275                     compiler.closeables = compiler.closeables.prepend((Closeable) processorClassLoader);
       
   276                 }
       
   277             }
       
   278         } catch (SecurityException e) {
       
   279             processorLoaderException = e;
       
   280         }
       
   281     }
       
   282 
       
   283     private void initProcessorIterator(Iterable<? extends Processor> processors) {
       
   284         Iterator<? extends Processor> processorIterator;
       
   285 
       
   286         if (options.isSet(Option.XPRINT)) {
       
   287             try {
       
   288                 processorIterator = List.of(new PrintingProcessor()).iterator();
       
   289             } catch (Throwable t) {
       
   290                 AssertionError assertError =
       
   291                     new AssertionError("Problem instantiating PrintingProcessor.");
       
   292                 assertError.initCause(t);
       
   293                 throw assertError;
       
   294             }
       
   295         } else if (processors != null) {
       
   296             processorIterator = processors.iterator();
       
   297         } else {
       
   298             if (processorLoaderException == null) {
       
   299                 /*
       
   300                  * If the "-processor" option is used, search the appropriate
       
   301                  * path for the named class.  Otherwise, use a service
       
   302                  * provider mechanism to create the processor iterator.
       
   303                  */
       
   304                 String processorNames = options.get(Option.PROCESSOR);
       
   305                 if (fileManager.hasLocation(ANNOTATION_PROCESSOR_MODULE_PATH)) {
       
   306                     processorIterator = (processorNames == null) ?
       
   307                             new ServiceIterator(serviceLoader, log) :
       
   308                             new NameServiceIterator(serviceLoader, log, processorNames);
       
   309                 } else if (processorNames != null) {
       
   310                     processorIterator = new NameProcessIterator(processorNames, processorClassLoader, log);
       
   311                 } else {
       
   312                     processorIterator = new ServiceIterator(processorClassLoader, log);
       
   313                 }
       
   314             } else {
       
   315                 /*
       
   316                  * A security exception will occur if we can't create a classloader.
       
   317                  * Ignore the exception if, with hindsight, we didn't need it anyway
       
   318                  * (i.e. no processor was specified either explicitly, or implicitly,
       
   319                  * in service configuration file.) Otherwise, we cannot continue.
       
   320                  */
       
   321                 processorIterator = handleServiceLoaderUnavailability("proc.cant.create.loader",
       
   322                         processorLoaderException);
       
   323             }
       
   324         }
       
   325         PlatformDescription platformProvider = context.get(PlatformDescription.class);
       
   326         java.util.List<Processor> platformProcessors = Collections.emptyList();
       
   327         if (platformProvider != null) {
       
   328             platformProcessors = platformProvider.getAnnotationProcessors()
       
   329                                                  .stream()
       
   330                                                  .map(PluginInfo::getPlugin)
       
   331                                                  .collect(Collectors.toList());
       
   332         }
       
   333         List<Iterator<? extends Processor>> iterators = List.of(processorIterator,
       
   334                                                                 platformProcessors.iterator());
       
   335         Iterator<? extends Processor> compoundIterator =
       
   336                 Iterators.createCompoundIterator(iterators, i -> i);
       
   337         discoveredProcs = new DiscoveredProcessors(compoundIterator);
       
   338     }
       
   339 
       
   340     public <S> ServiceLoader<S> getServiceLoader(Class<S> service) {
       
   341         if (fileManager.hasLocation(ANNOTATION_PROCESSOR_MODULE_PATH)) {
       
   342             try {
       
   343                 return fileManager.getServiceLoader(ANNOTATION_PROCESSOR_MODULE_PATH, service);
       
   344             } catch (IOException e) {
       
   345                 throw new Abort(e);
       
   346             }
       
   347         } else {
       
   348             return ServiceLoader.load(service, getProcessorClassLoader());
       
   349         }
       
   350     }
       
   351 
       
   352     /**
       
   353      * Returns an empty processor iterator if no processors are on the
       
   354      * relevant path, otherwise if processors are present, logs an
       
   355      * error.  Called when a service loader is unavailable for some
       
   356      * reason, either because a service loader class cannot be found
       
   357      * or because a security policy prevents class loaders from being
       
   358      * created.
       
   359      *
       
   360      * @param key The resource key to use to log an error message
       
   361      * @param e   If non-null, pass this exception to Abort
       
   362      */
       
   363     private Iterator<Processor> handleServiceLoaderUnavailability(String key, Exception e) {
       
   364         if (fileManager instanceof JavacFileManager) {
       
   365             StandardJavaFileManager standardFileManager = (JavacFileManager) fileManager;
       
   366             Iterable<? extends Path> workingPath = fileManager.hasLocation(ANNOTATION_PROCESSOR_PATH)
       
   367                 ? standardFileManager.getLocationAsPaths(ANNOTATION_PROCESSOR_PATH)
       
   368                 : standardFileManager.getLocationAsPaths(CLASS_PATH);
       
   369 
       
   370             if (needClassLoader(options.get(Option.PROCESSOR), workingPath) )
       
   371                 handleException(key, e);
       
   372 
       
   373         } else {
       
   374             handleException(key, e);
       
   375         }
       
   376 
       
   377         java.util.List<Processor> pl = Collections.emptyList();
       
   378         return pl.iterator();
       
   379     }
       
   380 
       
   381     /**
       
   382      * Handle a security exception thrown during initializing the
       
   383      * Processor iterator.
       
   384      */
       
   385     private void handleException(String key, Exception e) {
       
   386         if (e != null) {
       
   387             log.error(key, e.getLocalizedMessage());
       
   388             throw new Abort(e);
       
   389         } else {
       
   390             log.error(key);
       
   391             throw new Abort();
       
   392         }
       
   393     }
       
   394 
       
   395     /**
       
   396      * Use a service loader appropriate for the platform to provide an
       
   397      * iterator over annotations processors; fails if a loader is
       
   398      * needed but unavailable.
       
   399      */
       
   400     private class ServiceIterator implements Iterator<Processor> {
       
   401         Iterator<Processor> iterator;
       
   402         Log log;
       
   403         ServiceLoader<Processor> loader;
       
   404 
       
   405         ServiceIterator(ClassLoader classLoader, Log log) {
       
   406             this.log = log;
       
   407             try {
       
   408                 try {
       
   409                     loader = ServiceLoader.load(Processor.class, classLoader);
       
   410                     this.iterator = loader.iterator();
       
   411                 } catch (Exception e) {
       
   412                     // Fail softly if a loader is not actually needed.
       
   413                     this.iterator = handleServiceLoaderUnavailability("proc.no.service", null);
       
   414                 }
       
   415             } catch (Throwable t) {
       
   416                 log.error(Errors.ProcServiceProblem);
       
   417                 throw new Abort(t);
       
   418             }
       
   419         }
       
   420 
       
   421         ServiceIterator(ServiceLoader<Processor> loader, Log log) {
       
   422             this.log = log;
       
   423             this.loader = loader;
       
   424             this.iterator = loader.iterator();
       
   425         }
       
   426 
       
   427         @Override
       
   428         public boolean hasNext() {
       
   429             try {
       
   430                 return internalHasNext();
       
   431             } catch(ServiceConfigurationError sce) {
       
   432                 log.error(Errors.ProcBadConfigFile(sce.getLocalizedMessage()));
       
   433                 throw new Abort(sce);
       
   434             } catch (Throwable t) {
       
   435                 throw new Abort(t);
       
   436             }
       
   437         }
       
   438 
       
   439         boolean internalHasNext() {
       
   440             return iterator.hasNext();
       
   441         }
       
   442 
       
   443         @Override
       
   444         public Processor next() {
       
   445             try {
       
   446                 return internalNext();
       
   447             } catch (ServiceConfigurationError sce) {
       
   448                 log.error(Errors.ProcBadConfigFile(sce.getLocalizedMessage()));
       
   449                 throw new Abort(sce);
       
   450             } catch (Throwable t) {
       
   451                 throw new Abort(t);
       
   452             }
       
   453         }
       
   454 
       
   455         Processor internalNext() {
       
   456             return iterator.next();
       
   457         }
       
   458 
       
   459         @Override
       
   460         public void remove() {
       
   461             throw new UnsupportedOperationException();
       
   462         }
       
   463 
       
   464         public void close() {
       
   465             if (loader != null) {
       
   466                 try {
       
   467                     loader.reload();
       
   468                 } catch(Exception e) {
       
   469                     // Ignore problems during a call to reload.
       
   470                 }
       
   471             }
       
   472         }
       
   473     }
       
   474 
       
   475     private class NameServiceIterator extends ServiceIterator {
       
   476         private Map<String, Processor> namedProcessorsMap = new HashMap<>();;
       
   477         private Iterator<String> processorNames = null;
       
   478         private Processor nextProc = null;
       
   479 
       
   480         public NameServiceIterator(ServiceLoader<Processor> loader, Log log, String theNames) {
       
   481             super(loader, log);
       
   482             this.processorNames = Arrays.asList(theNames.split(",")).iterator();
       
   483         }
       
   484 
       
   485         @Override
       
   486         boolean internalHasNext() {
       
   487             if (nextProc != null) {
       
   488                 return true;
       
   489             }
       
   490             if (!processorNames.hasNext()) {
       
   491                 namedProcessorsMap = null;
       
   492                 return false;
       
   493             }
       
   494             String processorName = processorNames.next();
       
   495             Processor theProcessor = namedProcessorsMap.get(processorName);
       
   496             if (theProcessor != null) {
       
   497                 namedProcessorsMap.remove(processorName);
       
   498                 nextProc = theProcessor;
       
   499                 return true;
       
   500             } else {
       
   501                 while (iterator.hasNext()) {
       
   502                     theProcessor = iterator.next();
       
   503                     String name = theProcessor.getClass().getName();
       
   504                     if (name.equals(processorName)) {
       
   505                         nextProc = theProcessor;
       
   506                         return true;
       
   507                     } else {
       
   508                         namedProcessorsMap.put(name, theProcessor);
       
   509                     }
       
   510                 }
       
   511                 log.error(Errors.ProcProcessorNotFound(processorName));
       
   512                 return false;
       
   513             }
       
   514         }
       
   515 
       
   516         @Override
       
   517         Processor internalNext() {
       
   518             if (hasNext()) {
       
   519                 Processor p = nextProc;
       
   520                 nextProc = null;
       
   521                 return p;
       
   522             } else {
       
   523                 throw new NoSuchElementException();
       
   524             }
       
   525         }
       
   526     }
       
   527 
       
   528     private static class NameProcessIterator implements Iterator<Processor> {
       
   529         Processor nextProc = null;
       
   530         Iterator<String> names;
       
   531         ClassLoader processorCL;
       
   532         Log log;
       
   533 
       
   534         NameProcessIterator(String names, ClassLoader processorCL, Log log) {
       
   535             this.names = Arrays.asList(names.split(",")).iterator();
       
   536             this.processorCL = processorCL;
       
   537             this.log = log;
       
   538         }
       
   539 
       
   540         public boolean hasNext() {
       
   541             if (nextProc != null)
       
   542                 return true;
       
   543             else {
       
   544                 if (!names.hasNext()) {
       
   545                     return false;
       
   546                 } else {
       
   547                     Processor processor = getNextProcessor(names.next());
       
   548                     if (processor == null) {
       
   549                         return false;
       
   550                     } else {
       
   551                         nextProc = processor;
       
   552                         return true;
       
   553                     }
       
   554                 }
       
   555             }
       
   556         }
       
   557 
       
   558         private Processor getNextProcessor(String processorName) {
       
   559             try {
       
   560                 try {
       
   561                     Class<?> processorClass = processorCL.loadClass(processorName);
       
   562                     ensureReadable(processorClass);
       
   563                     return (Processor) processorClass.getConstructor().newInstance();
       
   564                 } catch (ClassNotFoundException cnfe) {
       
   565                     log.error(Errors.ProcProcessorNotFound(processorName));
       
   566                     return null;
       
   567                 } catch (ClassCastException cce) {
       
   568                     log.error(Errors.ProcProcessorWrongType(processorName));
       
   569                     return null;
       
   570                 } catch (Exception e ) {
       
   571                     log.error(Errors.ProcProcessorCantInstantiate(processorName));
       
   572                     return null;
       
   573                 }
       
   574             } catch (ClientCodeException e) {
       
   575                 throw e;
       
   576             } catch (Throwable t) {
       
   577                 throw new AnnotationProcessingError(t);
       
   578             }
       
   579         }
       
   580 
       
   581         public Processor next() {
       
   582             if (hasNext()) {
       
   583                 Processor p = nextProc;
       
   584                 nextProc = null;
       
   585                 return p;
       
   586             } else
       
   587                 throw new NoSuchElementException();
       
   588         }
       
   589 
       
   590         public void remove () {
       
   591             throw new UnsupportedOperationException();
       
   592         }
       
   593 
       
   594         /**
       
   595          * Ensures that the module of the given class is readable to this
       
   596          * module.
       
   597          */
       
   598         private void ensureReadable(Class<?> targetClass) {
       
   599             try {
       
   600                 Method getModuleMethod = Class.class.getMethod("getModule");
       
   601                 Object thisModule = getModuleMethod.invoke(this.getClass());
       
   602                 Object targetModule = getModuleMethod.invoke(targetClass);
       
   603 
       
   604                 Class<?> moduleClass = getModuleMethod.getReturnType();
       
   605                 Method addReadsMethod = moduleClass.getMethod("addReads", moduleClass);
       
   606                 addReadsMethod.invoke(thisModule, targetModule);
       
   607             } catch (NoSuchMethodException e) {
       
   608                 // ignore
       
   609             } catch (Exception e) {
       
   610                 throw new InternalError(e);
       
   611             }
       
   612         }
       
   613     }
       
   614 
       
   615     public boolean atLeastOneProcessor() {
       
   616         return discoveredProcs.iterator().hasNext();
       
   617     }
       
   618 
       
   619     private Map<String, String> initProcessorOptions() {
       
   620         Set<String> keySet = options.keySet();
       
   621         Map<String, String> tempOptions = new LinkedHashMap<>();
       
   622 
       
   623         for(String key : keySet) {
       
   624             if (key.startsWith("-A") && key.length() > 2) {
       
   625                 int sepIndex = key.indexOf('=');
       
   626                 String candidateKey = null;
       
   627                 String candidateValue = null;
       
   628 
       
   629                 if (sepIndex == -1)
       
   630                     candidateKey = key.substring(2);
       
   631                 else if (sepIndex >= 3) {
       
   632                     candidateKey = key.substring(2, sepIndex);
       
   633                     candidateValue = (sepIndex < key.length()-1)?
       
   634                         key.substring(sepIndex+1) : null;
       
   635                 }
       
   636                 tempOptions.put(candidateKey, candidateValue);
       
   637             }
       
   638         }
       
   639 
       
   640         PlatformDescription platformProvider = context.get(PlatformDescription.class);
       
   641 
       
   642         if (platformProvider != null) {
       
   643             for (PluginInfo<Processor> ap : platformProvider.getAnnotationProcessors()) {
       
   644                 tempOptions.putAll(ap.getOptions());
       
   645             }
       
   646         }
       
   647 
       
   648         return Collections.unmodifiableMap(tempOptions);
       
   649     }
       
   650 
       
   651     private Set<String> initUnmatchedProcessorOptions() {
       
   652         Set<String> unmatchedProcessorOptions = new HashSet<>();
       
   653         unmatchedProcessorOptions.addAll(processorOptions.keySet());
       
   654         return unmatchedProcessorOptions;
       
   655     }
       
   656 
       
   657     /**
       
   658      * State about how a processor has been used by the tool.  If a
       
   659      * processor has been used on a prior round, its process method is
       
   660      * called on all subsequent rounds, perhaps with an empty set of
       
   661      * annotations to process.  The {@code annotationSupported} method
       
   662      * caches the supported annotation information from the first (and
       
   663      * only) getSupportedAnnotationTypes call to the processor.
       
   664      */
       
   665     static class ProcessorState {
       
   666         public Processor processor;
       
   667         public boolean   contributed;
       
   668         private ArrayList<Pattern> supportedAnnotationPatterns;
       
   669         private ArrayList<String>  supportedOptionNames;
       
   670 
       
   671         ProcessorState(Processor p, Log log, Source source, boolean allowModules, ProcessingEnvironment env) {
       
   672             processor = p;
       
   673             contributed = false;
       
   674 
       
   675             try {
       
   676                 processor.init(env);
       
   677 
       
   678                 checkSourceVersionCompatibility(source, log);
       
   679 
       
   680                 supportedAnnotationPatterns = new ArrayList<>();
       
   681                 for (String importString : processor.getSupportedAnnotationTypes()) {
       
   682                     supportedAnnotationPatterns.add(importStringToPattern(allowModules,
       
   683                                                                           importString,
       
   684                                                                           processor,
       
   685                                                                           log));
       
   686                 }
       
   687 
       
   688                 supportedOptionNames = new ArrayList<>();
       
   689                 for (String optionName : processor.getSupportedOptions() ) {
       
   690                     if (checkOptionName(optionName, log))
       
   691                         supportedOptionNames.add(optionName);
       
   692                 }
       
   693 
       
   694             } catch (ClientCodeException e) {
       
   695                 throw e;
       
   696             } catch (Throwable t) {
       
   697                 throw new AnnotationProcessingError(t);
       
   698             }
       
   699         }
       
   700 
       
   701         /**
       
   702          * Checks whether or not a processor's source version is
       
   703          * compatible with the compilation source version.  The
       
   704          * processor's source version needs to be greater than or
       
   705          * equal to the source version of the compile.
       
   706          */
       
   707         private void checkSourceVersionCompatibility(Source source, Log log) {
       
   708             SourceVersion procSourceVersion = processor.getSupportedSourceVersion();
       
   709 
       
   710             if (procSourceVersion.compareTo(Source.toSourceVersion(source)) < 0 )  {
       
   711                 log.warning(Warnings.ProcProcessorIncompatibleSourceVersion(procSourceVersion,
       
   712                                                                             processor.getClass().getName(),
       
   713                                                                             source.name));
       
   714             }
       
   715         }
       
   716 
       
   717         private boolean checkOptionName(String optionName, Log log) {
       
   718             boolean valid = isValidOptionName(optionName);
       
   719             if (!valid)
       
   720                 log.error(Errors.ProcProcessorBadOptionName(optionName,
       
   721                                                             processor.getClass().getName()));
       
   722             return valid;
       
   723         }
       
   724 
       
   725         public boolean annotationSupported(String annotationName) {
       
   726             for(Pattern p: supportedAnnotationPatterns) {
       
   727                 if (p.matcher(annotationName).matches())
       
   728                     return true;
       
   729             }
       
   730             return false;
       
   731         }
       
   732 
       
   733         /**
       
   734          * Remove options that are matched by this processor.
       
   735          */
       
   736         public void removeSupportedOptions(Set<String> unmatchedProcessorOptions) {
       
   737             unmatchedProcessorOptions.removeAll(supportedOptionNames);
       
   738         }
       
   739     }
       
   740 
       
   741     // TODO: These two classes can probably be rewritten better...
       
   742     /**
       
   743      * This class holds information about the processors that have
       
   744      * been discovered so far as well as the means to discover more, if
       
   745      * necessary.  A single iterator should be used per round of
       
   746      * annotation processing.  The iterator first visits already
       
   747      * discovered processors then fails over to the service provider
       
   748      * mechanism if additional queries are made.
       
   749      */
       
   750     class DiscoveredProcessors implements Iterable<ProcessorState> {
       
   751 
       
   752         class ProcessorStateIterator implements Iterator<ProcessorState> {
       
   753             DiscoveredProcessors psi;
       
   754             Iterator<ProcessorState> innerIter;
       
   755             boolean onProcInterator;
       
   756 
       
   757             ProcessorStateIterator(DiscoveredProcessors psi) {
       
   758                 this.psi = psi;
       
   759                 this.innerIter = psi.procStateList.iterator();
       
   760                 this.onProcInterator = false;
       
   761             }
       
   762 
       
   763             public ProcessorState next() {
       
   764                 if (!onProcInterator) {
       
   765                     if (innerIter.hasNext())
       
   766                         return innerIter.next();
       
   767                     else
       
   768                         onProcInterator = true;
       
   769                 }
       
   770 
       
   771                 if (psi.processorIterator.hasNext()) {
       
   772                     ProcessorState ps = new ProcessorState(psi.processorIterator.next(),
       
   773                                                            log, source, allowModules,
       
   774                                                            JavacProcessingEnvironment.this);
       
   775                     psi.procStateList.add(ps);
       
   776                     return ps;
       
   777                 } else
       
   778                     throw new NoSuchElementException();
       
   779             }
       
   780 
       
   781             public boolean hasNext() {
       
   782                 if (onProcInterator)
       
   783                     return  psi.processorIterator.hasNext();
       
   784                 else
       
   785                     return innerIter.hasNext() || psi.processorIterator.hasNext();
       
   786             }
       
   787 
       
   788             public void remove () {
       
   789                 throw new UnsupportedOperationException();
       
   790             }
       
   791 
       
   792             /**
       
   793              * Run all remaining processors on the procStateList that
       
   794              * have not already run this round with an empty set of
       
   795              * annotations.
       
   796              */
       
   797             public void runContributingProcs(RoundEnvironment re) {
       
   798                 if (!onProcInterator) {
       
   799                     Set<TypeElement> emptyTypeElements = Collections.emptySet();
       
   800                     while(innerIter.hasNext()) {
       
   801                         ProcessorState ps = innerIter.next();
       
   802                         if (ps.contributed)
       
   803                             callProcessor(ps.processor, emptyTypeElements, re);
       
   804                     }
       
   805                 }
       
   806             }
       
   807         }
       
   808 
       
   809         Iterator<? extends Processor> processorIterator;
       
   810         ArrayList<ProcessorState>  procStateList;
       
   811 
       
   812         public ProcessorStateIterator iterator() {
       
   813             return new ProcessorStateIterator(this);
       
   814         }
       
   815 
       
   816         DiscoveredProcessors(Iterator<? extends Processor> processorIterator) {
       
   817             this.processorIterator = processorIterator;
       
   818             this.procStateList = new ArrayList<>();
       
   819         }
       
   820 
       
   821         /**
       
   822          * Free jar files, etc. if using a service loader.
       
   823          */
       
   824         public void close() {
       
   825             if (processorIterator != null &&
       
   826                 processorIterator instanceof ServiceIterator) {
       
   827                 ((ServiceIterator) processorIterator).close();
       
   828             }
       
   829         }
       
   830     }
       
   831 
       
   832     private void discoverAndRunProcs(Set<TypeElement> annotationsPresent,
       
   833                                      List<ClassSymbol> topLevelClasses,
       
   834                                      List<PackageSymbol> packageInfoFiles,
       
   835                                      List<ModuleSymbol> moduleInfoFiles) {
       
   836         Map<String, TypeElement> unmatchedAnnotations = new HashMap<>(annotationsPresent.size());
       
   837 
       
   838         for(TypeElement a  : annotationsPresent) {
       
   839             ModuleElement mod = elementUtils.getModuleOf(a);
       
   840             String moduleSpec = allowModules && mod != null ? mod.getQualifiedName() + "/" : "";
       
   841             unmatchedAnnotations.put(moduleSpec + a.getQualifiedName().toString(),
       
   842                                      a);
       
   843         }
       
   844 
       
   845         // Give "*" processors a chance to match
       
   846         if (unmatchedAnnotations.size() == 0)
       
   847             unmatchedAnnotations.put("", null);
       
   848 
       
   849         DiscoveredProcessors.ProcessorStateIterator psi = discoveredProcs.iterator();
       
   850         // TODO: Create proper argument values; need past round
       
   851         // information to fill in this constructor.  Note that the 1
       
   852         // st round of processing could be the last round if there
       
   853         // were parse errors on the initial source files; however, we
       
   854         // are not doing processing in that case.
       
   855 
       
   856         Set<Element> rootElements = new LinkedHashSet<>();
       
   857         rootElements.addAll(topLevelClasses);
       
   858         rootElements.addAll(packageInfoFiles);
       
   859         rootElements.addAll(moduleInfoFiles);
       
   860         rootElements = Collections.unmodifiableSet(rootElements);
       
   861 
       
   862         RoundEnvironment renv = new JavacRoundEnvironment(false,
       
   863                                                           false,
       
   864                                                           rootElements,
       
   865                                                           JavacProcessingEnvironment.this);
       
   866 
       
   867         while(unmatchedAnnotations.size() > 0 && psi.hasNext() ) {
       
   868             ProcessorState ps = psi.next();
       
   869             Set<String>  matchedNames = new HashSet<>();
       
   870             Set<TypeElement> typeElements = new LinkedHashSet<>();
       
   871 
       
   872             for (Map.Entry<String, TypeElement> entry: unmatchedAnnotations.entrySet()) {
       
   873                 String unmatchedAnnotationName = entry.getKey();
       
   874                 if (ps.annotationSupported(unmatchedAnnotationName) ) {
       
   875                     matchedNames.add(unmatchedAnnotationName);
       
   876                     TypeElement te = entry.getValue();
       
   877                     if (te != null)
       
   878                         typeElements.add(te);
       
   879                 }
       
   880             }
       
   881 
       
   882             if (matchedNames.size() > 0 || ps.contributed) {
       
   883                 boolean processingResult = callProcessor(ps.processor, typeElements, renv);
       
   884                 ps.contributed = true;
       
   885                 ps.removeSupportedOptions(unmatchedProcessorOptions);
       
   886 
       
   887                 if (printProcessorInfo || verbose) {
       
   888                     log.printLines("x.print.processor.info",
       
   889                             ps.processor.getClass().getName(),
       
   890                             matchedNames.toString(),
       
   891                             processingResult);
       
   892                 }
       
   893 
       
   894                 if (processingResult) {
       
   895                     unmatchedAnnotations.keySet().removeAll(matchedNames);
       
   896                 }
       
   897 
       
   898             }
       
   899         }
       
   900         unmatchedAnnotations.remove("");
       
   901 
       
   902         if (lint && unmatchedAnnotations.size() > 0) {
       
   903             // Remove annotations processed by javac
       
   904             unmatchedAnnotations.keySet().removeAll(platformAnnotations);
       
   905             if (unmatchedAnnotations.size() > 0) {
       
   906                 log.warning(Warnings.ProcAnnotationsWithoutProcessors(unmatchedAnnotations.keySet()));
       
   907             }
       
   908         }
       
   909 
       
   910         // Run contributing processors that haven't run yet
       
   911         psi.runContributingProcs(renv);
       
   912     }
       
   913 
       
   914     /**
       
   915      * Computes the set of annotations on the symbol in question.
       
   916      * Leave class public for external testing purposes.
       
   917      */
       
   918     public static class ComputeAnnotationSet extends
       
   919         ElementScanner9<Set<TypeElement>, Set<TypeElement>> {
       
   920         final Elements elements;
       
   921 
       
   922         public ComputeAnnotationSet(Elements elements) {
       
   923             super();
       
   924             this.elements = elements;
       
   925         }
       
   926 
       
   927         @Override @DefinedBy(Api.LANGUAGE_MODEL)
       
   928         public Set<TypeElement> visitPackage(PackageElement e, Set<TypeElement> p) {
       
   929             // Don't scan enclosed elements of a package
       
   930             return p;
       
   931         }
       
   932 
       
   933         @Override @DefinedBy(Api.LANGUAGE_MODEL)
       
   934         public Set<TypeElement> visitType(TypeElement e, Set<TypeElement> p) {
       
   935             // Type parameters are not considered to be enclosed by a type
       
   936             scan(e.getTypeParameters(), p);
       
   937             return super.visitType(e, p);
       
   938         }
       
   939 
       
   940         @Override @DefinedBy(Api.LANGUAGE_MODEL)
       
   941         public Set<TypeElement> visitExecutable(ExecutableElement e, Set<TypeElement> p) {
       
   942             // Type parameters are not considered to be enclosed by an executable
       
   943             scan(e.getTypeParameters(), p);
       
   944             return super.visitExecutable(e, p);
       
   945         }
       
   946 
       
   947         void addAnnotations(Element e, Set<TypeElement> p) {
       
   948             for (AnnotationMirror annotationMirror :
       
   949                      elements.getAllAnnotationMirrors(e) ) {
       
   950                 Element e2 = annotationMirror.getAnnotationType().asElement();
       
   951                 p.add((TypeElement) e2);
       
   952             }
       
   953         }
       
   954 
       
   955         @Override @DefinedBy(Api.LANGUAGE_MODEL)
       
   956         public Set<TypeElement> scan(Element e, Set<TypeElement> p) {
       
   957             addAnnotations(e, p);
       
   958             return super.scan(e, p);
       
   959         }
       
   960     }
       
   961 
       
   962     private boolean callProcessor(Processor proc,
       
   963                                          Set<? extends TypeElement> tes,
       
   964                                          RoundEnvironment renv) {
       
   965         try {
       
   966             return proc.process(tes, renv);
       
   967         } catch (ClassFinder.BadClassFile ex) {
       
   968             log.error(Errors.ProcCantAccess1(ex.sym, ex.getDetailValue()));
       
   969             return false;
       
   970         } catch (CompletionFailure ex) {
       
   971             StringWriter out = new StringWriter();
       
   972             ex.printStackTrace(new PrintWriter(out));
       
   973             log.error(Errors.ProcCantAccess(ex.sym, ex.getDetailValue(), out.toString()));
       
   974             return false;
       
   975         } catch (ClientCodeException e) {
       
   976             throw e;
       
   977         } catch (Throwable t) {
       
   978             throw new AnnotationProcessingError(t);
       
   979         }
       
   980     }
       
   981 
       
   982     /**
       
   983      * Helper object for a single round of annotation processing.
       
   984      */
       
   985     class Round {
       
   986         /** The round number. */
       
   987         final int number;
       
   988         /** The diagnostic handler for the round. */
       
   989         final Log.DeferredDiagnosticHandler deferredDiagnosticHandler;
       
   990 
       
   991         /** The ASTs to be compiled. */
       
   992         List<JCCompilationUnit> roots;
       
   993         /** The trees that need to be cleaned - includes roots and implicitly parsed trees. */
       
   994         Set<JCCompilationUnit> treesToClean;
       
   995         /** The classes to be compiler that have were generated. */
       
   996         Map<ModuleSymbol, Map<String, JavaFileObject>> genClassFiles;
       
   997 
       
   998         /** The set of annotations to be processed this round. */
       
   999         Set<TypeElement> annotationsPresent;
       
  1000         /** The set of top level classes to be processed this round. */
       
  1001         List<ClassSymbol> topLevelClasses;
       
  1002         /** The set of package-info files to be processed this round. */
       
  1003         List<PackageSymbol> packageInfoFiles;
       
  1004         /** The set of module-info files to be processed this round. */
       
  1005         List<ModuleSymbol> moduleInfoFiles;
       
  1006 
       
  1007         /** Create a round (common code). */
       
  1008         private Round(int number, Set<JCCompilationUnit> treesToClean,
       
  1009                 Log.DeferredDiagnosticHandler deferredDiagnosticHandler) {
       
  1010             this.number = number;
       
  1011 
       
  1012             if (number == 1) {
       
  1013                 Assert.checkNonNull(deferredDiagnosticHandler);
       
  1014                 this.deferredDiagnosticHandler = deferredDiagnosticHandler;
       
  1015             } else {
       
  1016                 this.deferredDiagnosticHandler = new Log.DeferredDiagnosticHandler(log);
       
  1017                 compiler.setDeferredDiagnosticHandler(this.deferredDiagnosticHandler);
       
  1018             }
       
  1019 
       
  1020             // the following will be populated as needed
       
  1021             topLevelClasses  = List.nil();
       
  1022             packageInfoFiles = List.nil();
       
  1023             moduleInfoFiles = List.nil();
       
  1024             this.treesToClean = treesToClean;
       
  1025         }
       
  1026 
       
  1027         /** Create the first round. */
       
  1028         Round(List<JCCompilationUnit> roots,
       
  1029               List<ClassSymbol> classSymbols,
       
  1030               Set<JCCompilationUnit> treesToClean,
       
  1031               Log.DeferredDiagnosticHandler deferredDiagnosticHandler) {
       
  1032             this(1, treesToClean, deferredDiagnosticHandler);
       
  1033             this.roots = roots;
       
  1034             genClassFiles = new HashMap<>();
       
  1035 
       
  1036             // The reverse() in the following line is to maintain behavioural
       
  1037             // compatibility with the previous revision of the code. Strictly speaking,
       
  1038             // it should not be necessary, but a javah golden file test fails without it.
       
  1039             topLevelClasses =
       
  1040                 getTopLevelClasses(roots).prependList(classSymbols.reverse());
       
  1041 
       
  1042             packageInfoFiles = getPackageInfoFiles(roots);
       
  1043 
       
  1044             moduleInfoFiles = getModuleInfoFiles(roots);
       
  1045 
       
  1046             findAnnotationsPresent();
       
  1047         }
       
  1048 
       
  1049         /** Create a new round. */
       
  1050         private Round(Round prev,
       
  1051                 Set<JavaFileObject> newSourceFiles, Map<ModuleSymbol, Map<String,JavaFileObject>> newClassFiles) {
       
  1052             this(prev.number+1, prev.treesToClean, null);
       
  1053             prev.newRound();
       
  1054             this.genClassFiles = prev.genClassFiles;
       
  1055 
       
  1056             List<JCCompilationUnit> parsedFiles = compiler.parseFiles(newSourceFiles);
       
  1057             roots = prev.roots.appendList(parsedFiles);
       
  1058 
       
  1059             // Check for errors after parsing
       
  1060             if (unrecoverableError()) {
       
  1061                 compiler.initModules(List.nil());
       
  1062                 return;
       
  1063             }
       
  1064 
       
  1065             roots = compiler.initModules(roots);
       
  1066 
       
  1067             enterClassFiles(genClassFiles);
       
  1068             List<ClassSymbol> newClasses = enterClassFiles(newClassFiles);
       
  1069             for (Entry<ModuleSymbol, Map<String, JavaFileObject>> moduleAndClassFiles : newClassFiles.entrySet()) {
       
  1070                 genClassFiles.computeIfAbsent(moduleAndClassFiles.getKey(), m -> new LinkedHashMap<>()).putAll(moduleAndClassFiles.getValue());
       
  1071             }
       
  1072             enterTrees(roots);
       
  1073 
       
  1074             if (unrecoverableError())
       
  1075                 return;
       
  1076 
       
  1077             topLevelClasses = join(
       
  1078                     getTopLevelClasses(parsedFiles),
       
  1079                     getTopLevelClassesFromClasses(newClasses));
       
  1080 
       
  1081             packageInfoFiles = join(
       
  1082                     getPackageInfoFiles(parsedFiles),
       
  1083                     getPackageInfoFilesFromClasses(newClasses));
       
  1084 
       
  1085             moduleInfoFiles = List.nil(); //module-info cannot be generated
       
  1086 
       
  1087             findAnnotationsPresent();
       
  1088         }
       
  1089 
       
  1090         /** Create the next round to be used. */
       
  1091         Round next(Set<JavaFileObject> newSourceFiles, Map<ModuleSymbol, Map<String, JavaFileObject>> newClassFiles) {
       
  1092             return new Round(this, newSourceFiles, newClassFiles);
       
  1093         }
       
  1094 
       
  1095         /** Prepare the compiler for the final compilation. */
       
  1096         void finalCompiler() {
       
  1097             newRound();
       
  1098         }
       
  1099 
       
  1100         /** Return the number of errors found so far in this round.
       
  1101          * This may include uncoverable errors, such as parse errors,
       
  1102          * and transient errors, such as missing symbols. */
       
  1103         int errorCount() {
       
  1104             return compiler.errorCount();
       
  1105         }
       
  1106 
       
  1107         /** Return the number of warnings found so far in this round. */
       
  1108         int warningCount() {
       
  1109             return compiler.warningCount();
       
  1110         }
       
  1111 
       
  1112         /** Return whether or not an unrecoverable error has occurred. */
       
  1113         boolean unrecoverableError() {
       
  1114             if (messager.errorRaised())
       
  1115                 return true;
       
  1116 
       
  1117             for (JCDiagnostic d: deferredDiagnosticHandler.getDiagnostics()) {
       
  1118                 switch (d.getKind()) {
       
  1119                     case WARNING:
       
  1120                         if (werror)
       
  1121                             return true;
       
  1122                         break;
       
  1123 
       
  1124                     case ERROR:
       
  1125                         if (fatalErrors || !d.isFlagSet(RECOVERABLE))
       
  1126                             return true;
       
  1127                         break;
       
  1128                 }
       
  1129             }
       
  1130 
       
  1131             return false;
       
  1132         }
       
  1133 
       
  1134         /** Find the set of annotations present in the set of top level
       
  1135          *  classes and package info files to be processed this round. */
       
  1136         void findAnnotationsPresent() {
       
  1137             ComputeAnnotationSet annotationComputer = new ComputeAnnotationSet(elementUtils);
       
  1138             // Use annotation processing to compute the set of annotations present
       
  1139             annotationsPresent = new LinkedHashSet<>();
       
  1140             for (ClassSymbol classSym : topLevelClasses)
       
  1141                 annotationComputer.scan(classSym, annotationsPresent);
       
  1142             for (PackageSymbol pkgSym : packageInfoFiles)
       
  1143                 annotationComputer.scan(pkgSym, annotationsPresent);
       
  1144             for (ModuleSymbol mdlSym : moduleInfoFiles)
       
  1145                 annotationComputer.scan(mdlSym, annotationsPresent);
       
  1146         }
       
  1147 
       
  1148         /** Enter a set of generated class files. */
       
  1149         private List<ClassSymbol> enterClassFiles(Map<ModuleSymbol, Map<String, JavaFileObject>> modulesAndClassFiles) {
       
  1150             List<ClassSymbol> list = List.nil();
       
  1151 
       
  1152             for (Entry<ModuleSymbol, Map<String, JavaFileObject>> moduleAndClassFiles : modulesAndClassFiles.entrySet()) {
       
  1153                 for (Map.Entry<String,JavaFileObject> entry : moduleAndClassFiles.getValue().entrySet()) {
       
  1154                     Name name = names.fromString(entry.getKey());
       
  1155                     JavaFileObject file = entry.getValue();
       
  1156                     if (file.getKind() != JavaFileObject.Kind.CLASS)
       
  1157                         throw new AssertionError(file);
       
  1158                     ClassSymbol cs;
       
  1159                     if (isPkgInfo(file, JavaFileObject.Kind.CLASS)) {
       
  1160                         Name packageName = Convert.packagePart(name);
       
  1161                         PackageSymbol p = symtab.enterPackage(moduleAndClassFiles.getKey(), packageName);
       
  1162                         if (p.package_info == null)
       
  1163                             p.package_info = symtab.enterClass(moduleAndClassFiles.getKey(), Convert.shortName(name), p);
       
  1164                         cs = p.package_info;
       
  1165                         cs.reset();
       
  1166                         if (cs.classfile == null)
       
  1167                             cs.classfile = file;
       
  1168                         cs.completer = initialCompleter;
       
  1169                     } else {
       
  1170                         cs = symtab.enterClass(moduleAndClassFiles.getKey(), name);
       
  1171                         cs.reset();
       
  1172                         cs.classfile = file;
       
  1173                         cs.completer = initialCompleter;
       
  1174                         cs.owner.members().enter(cs); //XXX - OverwriteBetweenCompilations; syms.getClass is not sufficient anymore
       
  1175                     }
       
  1176                     list = list.prepend(cs);
       
  1177                 }
       
  1178             }
       
  1179             return list.reverse();
       
  1180         }
       
  1181 
       
  1182         /** Enter a set of syntax trees. */
       
  1183         private void enterTrees(List<JCCompilationUnit> roots) {
       
  1184             compiler.enterTrees(roots);
       
  1185         }
       
  1186 
       
  1187         /** Run a processing round. */
       
  1188         void run(boolean lastRound, boolean errorStatus) {
       
  1189             printRoundInfo(lastRound);
       
  1190 
       
  1191             if (!taskListener.isEmpty())
       
  1192                 taskListener.started(new TaskEvent(TaskEvent.Kind.ANNOTATION_PROCESSING_ROUND));
       
  1193 
       
  1194             try {
       
  1195                 if (lastRound) {
       
  1196                     filer.setLastRound(true);
       
  1197                     Set<Element> emptyRootElements = Collections.emptySet(); // immutable
       
  1198                     RoundEnvironment renv = new JavacRoundEnvironment(true,
       
  1199                             errorStatus,
       
  1200                             emptyRootElements,
       
  1201                             JavacProcessingEnvironment.this);
       
  1202                     discoveredProcs.iterator().runContributingProcs(renv);
       
  1203                 } else {
       
  1204                     discoverAndRunProcs(annotationsPresent, topLevelClasses, packageInfoFiles, moduleInfoFiles);
       
  1205                 }
       
  1206             } catch (Throwable t) {
       
  1207                 // we're specifically expecting Abort here, but if any Throwable
       
  1208                 // comes by, we should flush all deferred diagnostics, rather than
       
  1209                 // drop them on the ground.
       
  1210                 deferredDiagnosticHandler.reportDeferredDiagnostics();
       
  1211                 log.popDiagnosticHandler(deferredDiagnosticHandler);
       
  1212                 compiler.setDeferredDiagnosticHandler(null);
       
  1213                 throw t;
       
  1214             } finally {
       
  1215                 if (!taskListener.isEmpty())
       
  1216                     taskListener.finished(new TaskEvent(TaskEvent.Kind.ANNOTATION_PROCESSING_ROUND));
       
  1217             }
       
  1218         }
       
  1219 
       
  1220         void showDiagnostics(boolean showAll) {
       
  1221             Set<JCDiagnostic.Kind> kinds = EnumSet.allOf(JCDiagnostic.Kind.class);
       
  1222             if (!showAll) {
       
  1223                 // suppress errors, which are all presumed to be transient resolve errors
       
  1224                 kinds.remove(JCDiagnostic.Kind.ERROR);
       
  1225             }
       
  1226             deferredDiagnosticHandler.reportDeferredDiagnostics(kinds);
       
  1227             log.popDiagnosticHandler(deferredDiagnosticHandler);
       
  1228             compiler.setDeferredDiagnosticHandler(null);
       
  1229         }
       
  1230 
       
  1231         /** Print info about this round. */
       
  1232         private void printRoundInfo(boolean lastRound) {
       
  1233             if (printRounds || verbose) {
       
  1234                 List<ClassSymbol> tlc = lastRound ? List.nil() : topLevelClasses;
       
  1235                 Set<TypeElement> ap = lastRound ? Collections.emptySet() : annotationsPresent;
       
  1236                 log.printLines("x.print.rounds",
       
  1237                         number,
       
  1238                         "{" + tlc.toString(", ") + "}",
       
  1239                         ap,
       
  1240                         lastRound);
       
  1241             }
       
  1242         }
       
  1243 
       
  1244         /** Prepare for new round of annotation processing. Cleans trees, resets symbols, and
       
  1245          * asks selected services to prepare to a new round of annotation processing.
       
  1246          */
       
  1247         private void newRound() {
       
  1248             //ensure treesToClean contains all trees, including implicitly parsed ones
       
  1249             for (Env<AttrContext> env : enter.getEnvs()) {
       
  1250                 treesToClean.add(env.toplevel);
       
  1251             }
       
  1252             for (JCCompilationUnit node : treesToClean) {
       
  1253                 treeCleaner.scan(node);
       
  1254             }
       
  1255             chk.newRound();
       
  1256             enter.newRound();
       
  1257             filer.newRound();
       
  1258             messager.newRound();
       
  1259             compiler.newRound();
       
  1260             modules.newRound();
       
  1261             types.newRound();
       
  1262             annotate.newRound();
       
  1263 
       
  1264             boolean foundError = false;
       
  1265 
       
  1266             for (ClassSymbol cs : symtab.getAllClasses()) {
       
  1267                 if (cs.kind == ERR) {
       
  1268                     foundError = true;
       
  1269                     break;
       
  1270                 }
       
  1271             }
       
  1272 
       
  1273             if (foundError) {
       
  1274                 for (ClassSymbol cs : symtab.getAllClasses()) {
       
  1275                     if (cs.classfile != null || cs.kind == ERR) {
       
  1276                         cs.reset();
       
  1277                         cs.type = new ClassType(cs.type.getEnclosingType(), null, cs);
       
  1278                         if (cs.isCompleted()) {
       
  1279                             cs.completer = initialCompleter;
       
  1280                         }
       
  1281                     }
       
  1282                 }
       
  1283             }
       
  1284         }
       
  1285     }
       
  1286 
       
  1287 
       
  1288     // TODO: internal catch clauses?; catch and rethrow an annotation
       
  1289     // processing error
       
  1290     public boolean doProcessing(List<JCCompilationUnit> roots,
       
  1291                                 List<ClassSymbol> classSymbols,
       
  1292                                 Iterable<? extends PackageSymbol> pckSymbols,
       
  1293                                 Log.DeferredDiagnosticHandler deferredDiagnosticHandler) {
       
  1294         final Set<JCCompilationUnit> treesToClean =
       
  1295                 Collections.newSetFromMap(new IdentityHashMap<JCCompilationUnit, Boolean>());
       
  1296 
       
  1297         //fill already attributed implicit trees:
       
  1298         for (Env<AttrContext> env : enter.getEnvs()) {
       
  1299             treesToClean.add(env.toplevel);
       
  1300         }
       
  1301 
       
  1302         Set<PackageSymbol> specifiedPackages = new LinkedHashSet<>();
       
  1303         for (PackageSymbol psym : pckSymbols)
       
  1304             specifiedPackages.add(psym);
       
  1305         this.specifiedPackages = Collections.unmodifiableSet(specifiedPackages);
       
  1306 
       
  1307         Round round = new Round(roots, classSymbols, treesToClean, deferredDiagnosticHandler);
       
  1308 
       
  1309         boolean errorStatus;
       
  1310         boolean moreToDo;
       
  1311         do {
       
  1312             // Run processors for round n
       
  1313             round.run(false, false);
       
  1314 
       
  1315             // Processors for round n have run to completion.
       
  1316             // Check for errors and whether there is more work to do.
       
  1317             errorStatus = round.unrecoverableError();
       
  1318             moreToDo = moreToDo();
       
  1319 
       
  1320             round.showDiagnostics(errorStatus || showResolveErrors);
       
  1321 
       
  1322             // Set up next round.
       
  1323             // Copy mutable collections returned from filer.
       
  1324             round = round.next(
       
  1325                     new LinkedHashSet<>(filer.getGeneratedSourceFileObjects()),
       
  1326                     new LinkedHashMap<>(filer.getGeneratedClasses()));
       
  1327 
       
  1328              // Check for errors during setup.
       
  1329             if (round.unrecoverableError())
       
  1330                 errorStatus = true;
       
  1331 
       
  1332         } while (moreToDo && !errorStatus);
       
  1333 
       
  1334         // run last round
       
  1335         round.run(true, errorStatus);
       
  1336         round.showDiagnostics(true);
       
  1337 
       
  1338         filer.warnIfUnclosedFiles();
       
  1339         warnIfUnmatchedOptions();
       
  1340 
       
  1341         /*
       
  1342          * If an annotation processor raises an error in a round,
       
  1343          * that round runs to completion and one last round occurs.
       
  1344          * The last round may also occur because no more source or
       
  1345          * class files have been generated.  Therefore, if an error
       
  1346          * was raised on either of the last *two* rounds, the compile
       
  1347          * should exit with a nonzero exit code.  The current value of
       
  1348          * errorStatus holds whether or not an error was raised on the
       
  1349          * second to last round; errorRaised() gives the error status
       
  1350          * of the last round.
       
  1351          */
       
  1352         if (messager.errorRaised()
       
  1353                 || werror && round.warningCount() > 0 && round.errorCount() > 0)
       
  1354             errorStatus = true;
       
  1355 
       
  1356         Set<JavaFileObject> newSourceFiles =
       
  1357                 new LinkedHashSet<>(filer.getGeneratedSourceFileObjects());
       
  1358         roots = round.roots;
       
  1359 
       
  1360         errorStatus = errorStatus || (compiler.errorCount() > 0);
       
  1361 
       
  1362         round.finalCompiler();
       
  1363 
       
  1364         if (newSourceFiles.size() > 0)
       
  1365             roots = roots.appendList(compiler.parseFiles(newSourceFiles));
       
  1366 
       
  1367         errorStatus = errorStatus || (compiler.errorCount() > 0);
       
  1368 
       
  1369         // Free resources
       
  1370         this.close();
       
  1371 
       
  1372         if (errorStatus && compiler.errorCount() == 0) {
       
  1373             compiler.log.nerrors++;
       
  1374         }
       
  1375 
       
  1376         compiler.enterTreesIfNeeded(roots);
       
  1377 
       
  1378         if (!taskListener.isEmpty())
       
  1379             taskListener.finished(new TaskEvent(TaskEvent.Kind.ANNOTATION_PROCESSING));
       
  1380 
       
  1381         return true;
       
  1382     }
       
  1383 
       
  1384     private void warnIfUnmatchedOptions() {
       
  1385         if (!unmatchedProcessorOptions.isEmpty()) {
       
  1386             log.warning(Warnings.ProcUnmatchedProcessorOptions(unmatchedProcessorOptions.toString()));
       
  1387         }
       
  1388     }
       
  1389 
       
  1390     /**
       
  1391      * Free resources related to annotation processing.
       
  1392      */
       
  1393     public void close() {
       
  1394         filer.close();
       
  1395         if (discoveredProcs != null) // Make calling close idempotent
       
  1396             discoveredProcs.close();
       
  1397         discoveredProcs = null;
       
  1398     }
       
  1399 
       
  1400     private List<ClassSymbol> getTopLevelClasses(List<? extends JCCompilationUnit> units) {
       
  1401         List<ClassSymbol> classes = List.nil();
       
  1402         for (JCCompilationUnit unit : units) {
       
  1403             for (JCTree node : unit.defs) {
       
  1404                 if (node.hasTag(JCTree.Tag.CLASSDEF)) {
       
  1405                     ClassSymbol sym = ((JCClassDecl) node).sym;
       
  1406                     Assert.checkNonNull(sym);
       
  1407                     classes = classes.prepend(sym);
       
  1408                 }
       
  1409             }
       
  1410         }
       
  1411         return classes.reverse();
       
  1412     }
       
  1413 
       
  1414     private List<ClassSymbol> getTopLevelClassesFromClasses(List<? extends ClassSymbol> syms) {
       
  1415         List<ClassSymbol> classes = List.nil();
       
  1416         for (ClassSymbol sym : syms) {
       
  1417             if (!isPkgInfo(sym)) {
       
  1418                 classes = classes.prepend(sym);
       
  1419             }
       
  1420         }
       
  1421         return classes.reverse();
       
  1422     }
       
  1423 
       
  1424     private List<PackageSymbol> getPackageInfoFiles(List<? extends JCCompilationUnit> units) {
       
  1425         List<PackageSymbol> packages = List.nil();
       
  1426         for (JCCompilationUnit unit : units) {
       
  1427             if (isPkgInfo(unit.sourcefile, JavaFileObject.Kind.SOURCE)) {
       
  1428                 packages = packages.prepend(unit.packge);
       
  1429             }
       
  1430         }
       
  1431         return packages.reverse();
       
  1432     }
       
  1433 
       
  1434     private List<PackageSymbol> getPackageInfoFilesFromClasses(List<? extends ClassSymbol> syms) {
       
  1435         List<PackageSymbol> packages = List.nil();
       
  1436         for (ClassSymbol sym : syms) {
       
  1437             if (isPkgInfo(sym)) {
       
  1438                 packages = packages.prepend((PackageSymbol) sym.owner);
       
  1439             }
       
  1440         }
       
  1441         return packages.reverse();
       
  1442     }
       
  1443 
       
  1444     private List<ModuleSymbol> getModuleInfoFiles(List<? extends JCCompilationUnit> units) {
       
  1445         List<ModuleSymbol> modules = List.nil();
       
  1446         for (JCCompilationUnit unit : units) {
       
  1447             if (isModuleInfo(unit.sourcefile, JavaFileObject.Kind.SOURCE) &&
       
  1448                 unit.defs.nonEmpty() &&
       
  1449                 unit.defs.head.hasTag(Tag.MODULEDEF)) {
       
  1450                 modules = modules.prepend(unit.modle);
       
  1451             }
       
  1452         }
       
  1453         return modules.reverse();
       
  1454     }
       
  1455 
       
  1456     // avoid unchecked warning from use of varargs
       
  1457     private static <T> List<T> join(List<T> list1, List<T> list2) {
       
  1458         return list1.appendList(list2);
       
  1459     }
       
  1460 
       
  1461     private boolean isPkgInfo(JavaFileObject fo, JavaFileObject.Kind kind) {
       
  1462         return fo.isNameCompatible("package-info", kind);
       
  1463     }
       
  1464 
       
  1465     private boolean isPkgInfo(ClassSymbol sym) {
       
  1466         return isPkgInfo(sym.classfile, JavaFileObject.Kind.CLASS) && (sym.packge().package_info == sym);
       
  1467     }
       
  1468 
       
  1469     private boolean isModuleInfo(JavaFileObject fo, JavaFileObject.Kind kind) {
       
  1470         return fo.isNameCompatible("module-info", kind);
       
  1471     }
       
  1472 
       
  1473     /*
       
  1474      * Called retroactively to determine if a class loader was required,
       
  1475      * after we have failed to create one.
       
  1476      */
       
  1477     private boolean needClassLoader(String procNames, Iterable<? extends Path> workingpath) {
       
  1478         if (procNames != null)
       
  1479             return true;
       
  1480 
       
  1481         URL[] urls = new URL[1];
       
  1482         for(Path pathElement : workingpath) {
       
  1483             try {
       
  1484                 urls[0] = pathElement.toUri().toURL();
       
  1485                 if (ServiceProxy.hasService(Processor.class, urls))
       
  1486                     return true;
       
  1487             } catch (MalformedURLException ex) {
       
  1488                 throw new AssertionError(ex);
       
  1489             }
       
  1490             catch (ServiceProxy.ServiceConfigurationError e) {
       
  1491                 log.error(Errors.ProcBadConfigFile(e.getLocalizedMessage()));
       
  1492                 return true;
       
  1493             }
       
  1494         }
       
  1495 
       
  1496         return false;
       
  1497     }
       
  1498 
       
  1499     class ImplicitCompleter implements Completer {
       
  1500 
       
  1501         private final JCCompilationUnit topLevel;
       
  1502 
       
  1503         public ImplicitCompleter(JCCompilationUnit topLevel) {
       
  1504             this.topLevel = topLevel;
       
  1505         }
       
  1506 
       
  1507         @Override public void complete(Symbol sym) throws CompletionFailure {
       
  1508             compiler.readSourceFile(topLevel, (ClassSymbol) sym);
       
  1509         }
       
  1510     }
       
  1511 
       
  1512     private final TreeScanner treeCleaner = new TreeScanner() {
       
  1513             public void scan(JCTree node) {
       
  1514                 super.scan(node);
       
  1515                 if (node != null)
       
  1516                     node.type = null;
       
  1517             }
       
  1518             JCCompilationUnit topLevel;
       
  1519             public void visitTopLevel(JCCompilationUnit node) {
       
  1520                 if (node.packge != null) {
       
  1521                     if (node.packge.package_info != null) {
       
  1522                         node.packge.package_info.reset();
       
  1523                     }
       
  1524                     node.packge.reset();
       
  1525                 }
       
  1526                 boolean isModuleInfo = node.sourcefile.isNameCompatible("module-info", Kind.SOURCE);
       
  1527                 if (isModuleInfo) {
       
  1528                     node.modle.reset();
       
  1529                     node.modle.completer = sym -> modules.enter(List.of(node), node.modle.module_info);
       
  1530                     node.modle.module_info.reset();
       
  1531                     node.modle.module_info.members_field = WriteableScope.create(node.modle.module_info);
       
  1532                 }
       
  1533                 node.packge = null;
       
  1534                 topLevel = node;
       
  1535                 try {
       
  1536                     super.visitTopLevel(node);
       
  1537                 } finally {
       
  1538                     topLevel = null;
       
  1539                 }
       
  1540             }
       
  1541             public void visitClassDef(JCClassDecl node) {
       
  1542                 super.visitClassDef(node);
       
  1543                 // remove generated constructor that may have been added during attribution:
       
  1544                 List<JCTree> beforeConstructor = List.nil();
       
  1545                 List<JCTree> defs = node.defs;
       
  1546                 while (defs.nonEmpty() && !defs.head.hasTag(Tag.METHODDEF)) {
       
  1547                     beforeConstructor = beforeConstructor.prepend(defs.head);
       
  1548                     defs = defs.tail;
       
  1549                 }
       
  1550                 if (defs.nonEmpty() &&
       
  1551                     (((JCMethodDecl) defs.head).mods.flags & Flags.GENERATEDCONSTR) != 0) {
       
  1552                     defs = defs.tail;
       
  1553                     while (beforeConstructor.nonEmpty()) {
       
  1554                         defs = defs.prepend(beforeConstructor.head);
       
  1555                         beforeConstructor = beforeConstructor.tail;
       
  1556                     }
       
  1557                     node.defs = defs;
       
  1558                 }
       
  1559                 if (node.sym != null) {
       
  1560                     node.sym.completer = new ImplicitCompleter(topLevel);
       
  1561                 }
       
  1562                 node.sym = null;
       
  1563             }
       
  1564             public void visitMethodDef(JCMethodDecl node) {
       
  1565                 // remove super constructor call that may have been added during attribution:
       
  1566                 if (TreeInfo.isConstructor(node) && node.sym != null && node.sym.owner.isEnum() &&
       
  1567                     node.body.stats.nonEmpty() && TreeInfo.isSuperCall(node.body.stats.head) &&
       
  1568                     node.body.stats.head.pos == node.body.pos) {
       
  1569                     node.body.stats = node.body.stats.tail;
       
  1570                 }
       
  1571                 node.sym = null;
       
  1572                 super.visitMethodDef(node);
       
  1573             }
       
  1574             public void visitVarDef(JCVariableDecl node) {
       
  1575                 node.sym = null;
       
  1576                 super.visitVarDef(node);
       
  1577             }
       
  1578             public void visitNewClass(JCNewClass node) {
       
  1579                 node.constructor = null;
       
  1580                 super.visitNewClass(node);
       
  1581             }
       
  1582             public void visitAssignop(JCAssignOp node) {
       
  1583                 node.operator = null;
       
  1584                 super.visitAssignop(node);
       
  1585             }
       
  1586             public void visitUnary(JCUnary node) {
       
  1587                 node.operator = null;
       
  1588                 super.visitUnary(node);
       
  1589             }
       
  1590             public void visitBinary(JCBinary node) {
       
  1591                 node.operator = null;
       
  1592                 super.visitBinary(node);
       
  1593             }
       
  1594             public void visitSelect(JCFieldAccess node) {
       
  1595                 node.sym = null;
       
  1596                 super.visitSelect(node);
       
  1597             }
       
  1598             public void visitIdent(JCIdent node) {
       
  1599                 node.sym = null;
       
  1600                 super.visitIdent(node);
       
  1601             }
       
  1602             public void visitAnnotation(JCAnnotation node) {
       
  1603                 node.attribute = null;
       
  1604                 super.visitAnnotation(node);
       
  1605             }
       
  1606         };
       
  1607 
       
  1608 
       
  1609     private boolean moreToDo() {
       
  1610         return filer.newFiles();
       
  1611     }
       
  1612 
       
  1613     /**
       
  1614      * {@inheritDoc}
       
  1615      *
       
  1616      * Command line options suitable for presenting to annotation
       
  1617      * processors.
       
  1618      * {@literal "-Afoo=bar"} should be {@literal "-Afoo" => "bar"}.
       
  1619      */
       
  1620     @DefinedBy(Api.ANNOTATION_PROCESSING)
       
  1621     public Map<String,String> getOptions() {
       
  1622         return processorOptions;
       
  1623     }
       
  1624 
       
  1625     @DefinedBy(Api.ANNOTATION_PROCESSING)
       
  1626     public Messager getMessager() {
       
  1627         return messager;
       
  1628     }
       
  1629 
       
  1630     @DefinedBy(Api.ANNOTATION_PROCESSING)
       
  1631     public JavacFiler getFiler() {
       
  1632         return filer;
       
  1633     }
       
  1634 
       
  1635     @DefinedBy(Api.ANNOTATION_PROCESSING)
       
  1636     public JavacElements getElementUtils() {
       
  1637         return elementUtils;
       
  1638     }
       
  1639 
       
  1640     @DefinedBy(Api.ANNOTATION_PROCESSING)
       
  1641     public JavacTypes getTypeUtils() {
       
  1642         return typeUtils;
       
  1643     }
       
  1644 
       
  1645     @DefinedBy(Api.ANNOTATION_PROCESSING)
       
  1646     public SourceVersion getSourceVersion() {
       
  1647         return Source.toSourceVersion(source);
       
  1648     }
       
  1649 
       
  1650     @DefinedBy(Api.ANNOTATION_PROCESSING)
       
  1651     public Locale getLocale() {
       
  1652         return messages.getCurrentLocale();
       
  1653     }
       
  1654 
       
  1655     public Set<Symbol.PackageSymbol> getSpecifiedPackages() {
       
  1656         return specifiedPackages;
       
  1657     }
       
  1658 
       
  1659     public static final Pattern noMatches  = Pattern.compile("(\\P{all})+");
       
  1660 
       
  1661     /**
       
  1662      * Convert import-style string for supported annotations into a
       
  1663      * regex matching that string.  If the string is not a valid
       
  1664      * import-style string, return a regex that won't match anything.
       
  1665      */
       
  1666     private static Pattern importStringToPattern(boolean allowModules, String s, Processor p, Log log) {
       
  1667         String module;
       
  1668         String pkg;
       
  1669         int slash = s.indexOf('/');
       
  1670         if (slash == (-1)) {
       
  1671             if (s.equals("*")) {
       
  1672                 return MatchingUtils.validImportStringToPattern(s);
       
  1673             }
       
  1674             module = allowModules ? ".*/" : "";
       
  1675             pkg = s;
       
  1676         } else {
       
  1677             module = Pattern.quote(s.substring(0, slash + 1));
       
  1678             pkg = s.substring(slash + 1);
       
  1679         }
       
  1680         if (MatchingUtils.isValidImportString(pkg)) {
       
  1681             return Pattern.compile(module + MatchingUtils.validImportStringToPatternString(pkg));
       
  1682         } else {
       
  1683             log.warning(Warnings.ProcMalformedSupportedString(s, p.getClass().getName()));
       
  1684             return noMatches; // won't match any valid identifier
       
  1685         }
       
  1686     }
       
  1687 
       
  1688     /**
       
  1689      * For internal use only.  This method may be removed without warning.
       
  1690      */
       
  1691     public Context getContext() {
       
  1692         return context;
       
  1693     }
       
  1694 
       
  1695     /**
       
  1696      * For internal use only.  This method may be removed without warning.
       
  1697      */
       
  1698     public ClassLoader getProcessorClassLoader() {
       
  1699         return processorClassLoader;
       
  1700     }
       
  1701 
       
  1702     public String toString() {
       
  1703         return "javac ProcessingEnvironment";
       
  1704     }
       
  1705 
       
  1706     public static boolean isValidOptionName(String optionName) {
       
  1707         for(String s : optionName.split("\\.", -1)) {
       
  1708             if (!SourceVersion.isIdentifier(s))
       
  1709                 return false;
       
  1710         }
       
  1711         return true;
       
  1712     }
       
  1713 }