public List<ClassSymbol> compile(List<String> filenames,
                                     Map<String, String> origOptions,
                                     ClassLoader aptCL,
                                     AnnotationProcessorFactory providedFactory,
                                     java.util.Set<Class<? extends AnnotationProcessorFactory> > productiveFactories,
                                     java.util.Set<java.io.File> aggregateGenFiles)
        throws Throwable {
        // as a JavaCompiler can only be used once, throw an exception if
        // it has been used before.
        assert !hasBeenUsed : "attempt to reuse JavaCompiler";
        hasBeenUsed = true;

        this.aggregateGenFiles = aggregateGenFiles;

        long msec = System.currentTimeMillis();

        ListBuffer<ClassSymbol> classes = new ListBuffer<ClassSymbol>();
        try {
            JavacFileManager fm = (JavacFileManager)fileManager;
            //parse all files
            ListBuffer<JCCompilationUnit> trees = new ListBuffer<JCCompilationUnit>();
            for (List<String> l = filenames; l.nonEmpty(); l = l.tail) {
                if (classesAsDecls) {
                    if (! l.head.endsWith(".java") ) { // process as class file
                        ClassSymbol cs = reader.enterClass(names.fromString(l.head));
                        try {
                            cs.complete();
                        } catch(Symbol.CompletionFailure cf) {
                            bark.aptError("CantFindClass", l);
                            continue;
                        }

                        classes.append(cs); // add to list of classes
                        continue;
                    }
                }
                JavaFileObject fo = fm.getJavaFileObjectsFromStrings(List.of(l.head)).iterator().next();
                trees.append(parse(fo));
            }

            //enter symbols for all files
            List<JCCompilationUnit> roots = trees.toList();

            if (errorCount() == 0) {
                boolean prev = bark.setDiagnosticsIgnored(true);
                try {
                    enter.main(roots);
                }
                finally {
                    bark.setDiagnosticsIgnored(prev);
                }
            }

            if (errorCount() == 0) {
                apt.main(roots,
                         classes,
                         origOptions, aptCL,
                         providedFactory,
                         productiveFactories);
                genSourceFileNames.addAll(apt.getSourceFileNames());
                genClassFileNames.addAll(apt.getClassFileNames());
            }

        } catch (Abort ex) {
        }

        if (verbose)
            log.printVerbose("total", Long.toString(System.currentTimeMillis() - msec));

        chk.reportDeferredDiagnostics();

        printCount("error", errorCount());
        printCount("warn", warningCount());

        return classes.toList();
    }