/** Enter a set of generated class files. */
    private List<ClassSymbol> enterClassFiles(Map<String, JavaFileObject> classFiles) {
      ClassReader reader = ClassReader.instance(context);
      Names names = Names.instance(context);
      List<ClassSymbol> list = List.nil();

      for (Map.Entry<String, JavaFileObject> entry : classFiles.entrySet()) {
        Name name = names.fromString(entry.getKey());
        JavaFileObject file = entry.getValue();
        if (file.getKind() != JavaFileObject.Kind.CLASS) throw new AssertionError(file);
        ClassSymbol cs;
        if (isPkgInfo(file, JavaFileObject.Kind.CLASS)) {
          Name packageName = Convert.packagePart(name);
          PackageSymbol p = reader.enterPackage(packageName);
          if (p.package_info == null)
            p.package_info = reader.enterClass(Convert.shortName(name), p);
          cs = p.package_info;
          if (cs.classfile == null) cs.classfile = file;
        } else cs = reader.enterClass(name, file);
        list = list.prepend(cs);
      }
      return list.reverse();
    }
  private void discoverAndRunProcs(
      Context context,
      Set<TypeElement> annotationsPresent,
      List<ClassSymbol> topLevelClasses,
      List<PackageSymbol> packageInfoFiles) {
    Map<String, TypeElement> unmatchedAnnotations =
        new HashMap<String, TypeElement>(annotationsPresent.size());

    for (TypeElement a : annotationsPresent) {
      unmatchedAnnotations.put(a.getQualifiedName().toString(), a);
    }

    // Give "*" processors a chance to match
    if (unmatchedAnnotations.size() == 0) unmatchedAnnotations.put("", null);

    DiscoveredProcessors.ProcessorStateIterator psi = discoveredProcs.iterator();
    // TODO: Create proper argument values; need past round
    // information to fill in this constructor.  Note that the 1
    // st round of processing could be the last round if there
    // were parse errors on the initial source files; however, we
    // are not doing processing in that case.

    Set<Element> rootElements = new LinkedHashSet<Element>();
    rootElements.addAll(topLevelClasses);
    rootElements.addAll(packageInfoFiles);
    rootElements = Collections.unmodifiableSet(rootElements);

    RoundEnvironment renv =
        new JavacRoundEnvironment(false, false, rootElements, JavacProcessingEnvironment.this);

    while (unmatchedAnnotations.size() > 0 && psi.hasNext()) {
      ProcessorState ps = psi.next();
      Set<String> matchedNames = new HashSet<String>();
      Set<TypeElement> typeElements = new LinkedHashSet<TypeElement>();

      for (Map.Entry<String, TypeElement> entry : unmatchedAnnotations.entrySet()) {
        String unmatchedAnnotationName = entry.getKey();
        if (ps.annotationSupported(unmatchedAnnotationName)) {
          matchedNames.add(unmatchedAnnotationName);
          TypeElement te = entry.getValue();
          if (te != null) typeElements.add(te);
        }
      }

      if (matchedNames.size() > 0 || ps.contributed) {
        boolean processingResult = callProcessor(ps.processor, typeElements, renv);
        ps.contributed = true;
        ps.removeSupportedOptions(unmatchedProcessorOptions);

        if (printProcessorInfo || verbose) {
          log.printNoteLines(
              "x.print.processor.info",
              ps.processor.getClass().getName(),
              matchedNames.toString(),
              processingResult);
        }

        if (processingResult) {
          unmatchedAnnotations.keySet().removeAll(matchedNames);
        }
      }
    }
    unmatchedAnnotations.remove("");

    if (lint && unmatchedAnnotations.size() > 0) {
      // Remove annotations processed by javac
      unmatchedAnnotations.keySet().removeAll(platformAnnotations);
      if (unmatchedAnnotations.size() > 0) {
        log = Log.instance(context);
        log.warning("proc.annotations.without.processors", unmatchedAnnotations.keySet());
      }
    }

    // Run contributing processors that haven't run yet
    psi.runContributingProcs(renv);

    // Debugging
    if (options.isSet("displayFilerState")) filer.displayState();
  }