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