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