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