/**
   * Translate the given abstract syntax trees to elements.
   *
   * @param trees a list of abstract syntax trees.
   * @throws java.io.IOException TODO
   * @return a list of elements corresponding to the top level classes in the abstract syntax trees
   */
  public Iterable<? extends TypeElement> enter(Iterable<? extends CompilationUnitTree> trees)
      throws IOException {
    prepareCompiler();

    ListBuffer<JCCompilationUnit> roots = null;

    if (trees == null) {
      // If there are still files which were specified to be compiled
      // (i.e. in fileObjects) but which have not yet been entered,
      // then we make sure they have been parsed and add them to the
      // list to be entered.
      if (notYetEntered.size() > 0) {
        if (!parsed) parse(); // TODO would be nice to specify files needed to be parsed
        for (JavaFileObject file : fileObjects) {
          JCCompilationUnit unit = notYetEntered.remove(file);
          if (unit != null) {
            if (roots == null) roots = new ListBuffer<JCCompilationUnit>();
            roots.append(unit);
          }
        }
        notYetEntered.clear();
      }
    } else {
      for (CompilationUnitTree cu : trees) {
        if (cu instanceof JCCompilationUnit) {
          if (roots == null) roots = new ListBuffer<JCCompilationUnit>();
          roots.append((JCCompilationUnit) cu);
          notYetEntered.remove(cu.getSourceFile());
        } else throw new IllegalArgumentException(cu.toString());
      }
    }

    if (roots == null) return List.nil();

    try {
      List<JCCompilationUnit> units = compiler.enterTrees(roots.toList());

      if (notYetEntered.isEmpty()) compiler = compiler.processAnnotations(units);

      ListBuffer<TypeElement> elements = new ListBuffer<TypeElement>();
      for (JCCompilationUnit unit : units) {
        for (JCTree node : unit.defs) {
          if (node.getTag() == JCTree.CLASSDEF) {
            JCClassDecl cdef = (JCClassDecl) node;
            if (cdef.sym != null) // maybe null if errors in anno processing
            elements.append(cdef.sym);
          }
        }
      }
      return elements.toList();
    } finally {
      compiler.log.flush();
    }
  }
 /**
  * Format the arguments of a given diagnostic.
  *
  * @param d diagnostic whose arguments are to be formatted
  * @param l locale object to be used for i18n
  * @return a Collection whose elements are the formatted arguments of the diagnostic
  */
 protected Collection<String> formatArguments(JCDiagnostic d, Locale l) {
   ListBuffer<String> buf = new ListBuffer<String>();
   for (Object o : d.getArgs()) {
     buf.append(formatArgument(d, o, l));
   }
   return buf.toList();
 }
Beispiel #3
0
 /** Visitor method: enter classes of a list of trees, returning a list of types. */
 <T extends JCTree> List<Type> classEnter(List<T> trees, Env<AttrContext> env) {
   ListBuffer<Type> ts = new ListBuffer<Type>();
   for (List<T> l = trees; l.nonEmpty(); l = l.tail) {
     Type t = classEnter(l.head, env);
     if (t != null) ts.append(t);
   }
   return ts.toList();
 }
Beispiel #4
0
 public List<A> intersect(List<A> that) {
   ListBuffer<A> buf = ListBuffer.lb();
   for (A el : this) {
     if (that.contains(el)) {
       buf.append(el);
     }
   }
   return buf.toList();
 }
Beispiel #5
0
  private <T extends Attribute.Compound> List<T> getAttributesForCompletion(
      final Annotate.AnnotateRepeatedContext<T> ctx) {

    Map<Symbol.TypeSymbol, ListBuffer<T>> annotated = ctx.annotated;
    boolean atLeastOneRepeated = false;
    List<T> buf = List.<T>nil();
    for (ListBuffer<T> lb : annotated.values()) {
      if (lb.size() == 1) {
        buf = buf.prepend(lb.first());
      } else { // repeated
        // This will break when other subtypes of Attributs.Compound
        // are introduced, because PlaceHolder is a subtype of TypeCompound.
        T res;
        @SuppressWarnings("unchecked")
        T ph = (T) new Placeholder<T>(ctx, lb.toList(), sym);
        res = ph;
        buf = buf.prepend(res);
        atLeastOneRepeated = true;
      }
    }

    if (atLeastOneRepeated) {
      // The Symbol s is now annotated with a combination of
      // finished non-repeating annotations and placeholders for
      // repeating annotations.
      //
      // We need to do this in two passes because when creating
      // a container for a repeating annotation we must
      // guarantee that the @Repeatable on the
      // contained annotation is fully annotated
      //
      // The way we force this order is to do all repeating
      // annotations in a pass after all non-repeating are
      // finished. This will work because @Repeatable
      // is non-repeating and therefore will be annotated in the
      // fist pass.

      // Queue a pass that will replace Attribute.Placeholders
      // with Attribute.Compound (made from synthesized containers).
      ctx.annotateRepeated(
          new Annotate.Annotator() {
            @Override
            public String toString() {
              return "repeated annotation pass of: " + sym + " in: " + sym.owner;
            }

            @Override
            public void enterAnnotation() {
              complete(ctx);
            }
          });
    }
    // Add non-repeating attributes
    return buf.reverse();
  }
Beispiel #6
0
  // where
  private DeclaredType getDeclaredType0(Type outer, ClassSymbol sym, TypeMirror... typeArgs) {
    if (typeArgs.length != sym.type.getTypeArguments().length())
      throw new IllegalArgumentException("Incorrect number of type arguments");

    ListBuffer<Type> targs = new ListBuffer<Type>();
    for (TypeMirror t : typeArgs) {
      if (!(t instanceof ReferenceType || t instanceof WildcardType))
        throw new IllegalArgumentException(t.toString());
      targs.append((Type) t);
    }
    // TODO: Would like a way to check that type args match formals.

    return (DeclaredType) new Type.ClassType(outer, targs.toList(), sym);
  }
Beispiel #7
0
  /**
   * Programmatic interface for main function.
   *
   * @param args The command line parameters.
   */
  public int compile(
      String[] args,
      Context context,
      List<JavaFileObject> fileObjects,
      Iterable<? extends Processor> processors) {
    if (options == null) options = Options.instance(context); // creates a new one

    filenames = new ListBuffer<File>();
    classnames = new ListBuffer<String>();
    JavaCompiler comp = null;
    /*
     * TODO: Logic below about what is an acceptable command line
     * should be updated to take annotation processing semantics
     * into account.
     */
    try {
      if (args.length == 0 && fileObjects.isEmpty()) {
        help();
        return EXIT_CMDERR;
      }

      List<File> files;
      try {
        files = processArgs(CommandLine.parse(args));
        if (files == null) {
          // null signals an error in options, abort
          return EXIT_CMDERR;
        } else if (files.isEmpty() && fileObjects.isEmpty() && classnames.isEmpty()) {
          // it is allowed to compile nothing if just asking for help or version info
          if (options.get("-help") != null
              || options.get("-X") != null
              || options.get("-version") != null
              || options.get("-fullversion") != null) return EXIT_OK;
          error("err.no.source.files");
          return EXIT_CMDERR;
        }
      } catch (java.io.FileNotFoundException e) {
        Log.printLines(
            out, ownName + ": " + getLocalizedString("err.file.not.found", e.getMessage()));
        return EXIT_SYSERR;
      }

      boolean forceStdOut = options.get("stdout") != null;
      if (forceStdOut) {
        out.flush();
        out = new PrintWriter(System.out, true);
      }

      context.put(Log.outKey, out);

      // allow System property in following line as a Mustang legacy
      boolean batchMode =
          (options.get("nonBatchMode") == null && System.getProperty("nonBatchMode") == null);
      if (batchMode) CacheFSInfo.preRegister(context);

      fileManager = context.get(JavaFileManager.class);

      comp = JavaCompiler.instance(context);
      if (comp == null) return EXIT_SYSERR;

      if (!files.isEmpty()) {
        // add filenames to fileObjects
        comp = JavaCompiler.instance(context);
        List<JavaFileObject> otherFiles = List.nil();
        JavacFileManager dfm = (JavacFileManager) fileManager;
        for (JavaFileObject fo : dfm.getJavaFileObjectsFromFiles(files))
          otherFiles = otherFiles.prepend(fo);
        for (JavaFileObject fo : otherFiles) fileObjects = fileObjects.prepend(fo);
      }
      comp.compile(fileObjects, classnames.toList(), processors);

      if (comp.errorCount() != 0) return EXIT_ERROR;
    } catch (IOException ex) {
      ioMessage(ex);
      return EXIT_SYSERR;
    } catch (OutOfMemoryError ex) {
      resourceMessage(ex);
      return EXIT_SYSERR;
    } catch (StackOverflowError ex) {
      resourceMessage(ex);
      return EXIT_SYSERR;
    } catch (FatalError ex) {
      feMessage(ex);
      return EXIT_SYSERR;
    } catch (AnnotationProcessingError ex) {
      apMessage(ex);
      return EXIT_SYSERR;
    } catch (ClientCodeException ex) {
      // as specified by javax.tools.JavaCompiler#getTask
      // and javax.tools.JavaCompiler.CompilationTask#call
      throw new RuntimeException(ex.getCause());
    } catch (PropagatedException ex) {
      throw ex.getCause();
    } catch (Throwable ex) {
      // Nasty.  If we've already reported an error, compensate
      // for buggy compiler error recovery by swallowing thrown
      // exceptions.
      if (comp == null || comp.errorCount() == 0 || options == null || options.get("dev") != null)
        bugMessage(ex);
      return EXIT_ABNORMAL;
    } finally {
      if (comp != null) comp.close();
      filenames = null;
      options = null;
    }
    return EXIT_OK;
  }
Beispiel #8
0
  /**
   * Process command line arguments: store all command line options in `options' table and return
   * all source filenames.
   *
   * @param flags The array of command line arguments.
   */
  public List<File> processArgs(String[] flags) { // XXX sb protected
    int ac = 0;
    while (ac < flags.length) {
      String flag = flags[ac];
      ac++;

      int j;
      // quick hack to speed up file processing:
      // if the option does not begin with '-', there is no need to check
      // most of the compiler options.
      int firstOptionToCheck = flag.charAt(0) == '-' ? 0 : recognizedOptions.length - 1;
      for (j = firstOptionToCheck; j < recognizedOptions.length; j++)
        if (recognizedOptions[j].matches(flag)) break;

      if (j == recognizedOptions.length) {
        error("err.invalid.flag", flag);
        return null;
      }

      Option option = recognizedOptions[j];
      if (option.hasArg()) {
        if (ac == flags.length) {
          error("err.req.arg", flag);
          return null;
        }
        String operand = flags[ac];
        ac++;
        if (option.process(options, flag, operand)) return null;
      } else {
        if (option.process(options, flag)) return null;
      }
    }

    if (!checkDirectory("-d")) return null;
    if (!checkDirectory("-s")) return null;

    String sourceString = options.get("-source");
    Source source = (sourceString != null) ? Source.lookup(sourceString) : Source.DEFAULT;
    String targetString = options.get("-target");
    Target target = (targetString != null) ? Target.lookup(targetString) : Target.DEFAULT;
    // We don't check source/target consistency for CLDC, as J2ME
    // profiles are not aligned with J2SE targets; moreover, a
    // single CLDC target may have many profiles.  In addition,
    // this is needed for the continued functioning of the JSR14
    // prototype.
    if (Character.isDigit(target.name.charAt(0))) {
      if (target.compareTo(source.requiredTarget()) < 0) {
        if (targetString != null) {
          if (sourceString == null) {
            warning(
                "warn.target.default.source.conflict", targetString, source.requiredTarget().name);
          } else {
            warning("warn.source.target.conflict", sourceString, source.requiredTarget().name);
          }
          return null;
        } else {
          options.put("-target", source.requiredTarget().name);
        }
      } else {
        if (targetString == null && !source.allowGenerics()) {
          options.put("-target", Target.JDK1_4.name);
        }
      }
    }
    return filenames.toList();
  }
  /**
   * Main method: compile a list of files, return all compiled classes
   *
   * @param filenames The names of all files to be compiled.
   */
  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();
  }
 private static List<JavaFileObject> toList(Iterable<? extends JavaFileObject> fileObjects) {
   if (fileObjects == null) return List.nil();
   ListBuffer<JavaFileObject> result = new ListBuffer<JavaFileObject>();
   for (JavaFileObject fo : fileObjects) result.append(fo);
   return result.toList();
 }
Beispiel #11
0
 /** Append given list buffer at length, forming and returning a new list. */
 public List<A> appendList(ListBuffer<A> x) {
   return appendList(x.toList());
 }