@Override
 public final void init(ProcessingEnvironment env) {
   super.init(env);
   JavacTask.instance(env).addTaskListener(listener);
   Context ctx = ((JavacProcessingEnvironment) processingEnv).getContext();
   JavaCompiler compiler = JavaCompiler.instance(ctx);
   compiler.shouldStopPolicyIfNoError =
       CompileState.max(compiler.shouldStopPolicyIfNoError, CompileState.FLOW);
 }
 /** Create the compiler to be used for the final compilation. */
 JavaCompiler finalCompiler(boolean errorStatus) {
   try {
     JavaCompiler c = JavaCompiler.instance(nextContext());
     c.log.nwarnings += compiler.log.nwarnings;
     if (errorStatus) {
       c.log.nerrors += compiler.log.nerrors;
     }
     return c;
   } finally {
     compiler.close(false);
   }
 }
예제 #3
0
 protected void flow(Env<AttrContext> env, Queue<Env<AttrContext>> results) {
   if (env.toplevel.sourcefile instanceof CeylonFileObject) {
     try {
       Context.SourceLanguage.push(Language.CEYLON);
       super.flow(env, results);
       return;
     } finally {
       Context.SourceLanguage.pop();
     }
   }
   super.flow(env, results);
 }
예제 #4
0
 protected void desugar(
     final Env<AttrContext> env, Queue<Pair<Env<AttrContext>, JCClassDecl>> results) {
   if (env.toplevel.sourcefile instanceof CeylonFileObject) {
     try {
       Context.SourceLanguage.push(Language.CEYLON);
       super.desugar(env, results);
       return;
     } finally {
       Context.SourceLanguage.pop();
     }
   }
   super.desugar(env, results);
 }
 /** Create the next round to be used. */
 Round next(Set<JavaFileObject> newSourceFiles, Map<String, JavaFileObject> newClassFiles) {
   try {
     return new Round(this, newSourceFiles, newClassFiles);
   } finally {
     compiler.close(false);
   }
 }
예제 #6
0
 @Override
 public void generate(
     Queue<Pair<Env<AttrContext>, JCClassDecl>> queue, Queue<JavaFileObject> results) {
   timer.startTask("Generate");
   super.generate(queue, results);
   timer.endTask();
 }
    /** Create a new round. */
    private Round(
        Round prev, Set<JavaFileObject> newSourceFiles, Map<String, JavaFileObject> newClassFiles) {
      this(prev.nextContext(), prev.number + 1, prev.nMessagerErrors, prev.compiler.log.nwarnings);
      this.genClassFiles = prev.genClassFiles;

      List<JCCompilationUnit> parsedFiles = compiler.parseFiles(newSourceFiles);
      roots = cleanTrees(prev.roots).appendList(parsedFiles);

      // Check for errors after parsing
      if (unrecoverableError()) return;

      enterClassFiles(genClassFiles);
      List<ClassSymbol> newClasses = enterClassFiles(newClassFiles);
      genClassFiles.putAll(newClassFiles);
      enterTrees(roots);

      if (unrecoverableError()) return;

      topLevelClasses =
          join(getTopLevelClasses(parsedFiles), getTopLevelClassesFromClasses(newClasses));

      packageInfoFiles =
          join(getPackageInfoFiles(parsedFiles), getPackageInfoFilesFromClasses(newClasses));

      findAnnotationsPresent();
    }
예제 #8
0
 @Override
 public void close(boolean disposeNames) {
   if (resourceFileObjects != null) {
     addResources();
     resourceFileObjects = null;
   }
   super.close(disposeNames);
 }
예제 #9
0
 @Override
 public void complete(ClassSymbol c) throws CompletionFailure {
   try {
     Context.SourceLanguage.push(Language.JAVA);
     super.complete(c);
   } finally {
     Context.SourceLanguage.pop();
   }
 }
예제 #10
0
    /** Create a round (common code). */
    private Round(Context context, int number, int priorErrors, int priorWarnings) {
      this.context = context;
      this.number = number;

      compiler = JavaCompiler.instance(context);
      log = Log.instance(context);
      log.nerrors = priorErrors;
      log.nwarnings += priorWarnings;
      log.deferDiagnostics = true;

      // the following is for the benefit of JavacProcessingEnvironment.getContext()
      JavacProcessingEnvironment.this.context = context;

      // the following will be populated as needed
      topLevelClasses = List.nil();
      packageInfoFiles = List.nil();
    }
예제 #11
0
 @Override
 public void compile(
     List<JavaFileObject> fileObjects,
     List<String> classnames,
     Iterable<? extends Processor> processors) {
   // Now we first split the files into sources/modules and resources
   List<JavaFileObject> sourceFiles = List.nil();
   List<JavaFileObject> resourceFiles = List.nil();
   for (JavaFileObject fo : fileObjects) {
     if (isResource(fo)) {
       resourceFiles = resourceFiles.append(fo);
     } else {
       sourceFiles = sourceFiles.append(fo);
     }
   }
   this.resourceFileObjects = resourceFiles;
   // Add any module files for the resources (if needed)
   sourceFiles = addModuleDescriptors(sourceFiles, resourceFiles);
   // And then continue to the compilation of the source files
   super.compile(sourceFiles, classnames, processors);
 }
예제 #12
0
  public boolean delombok() throws IOException {
    Options options = Options.instance(context);
    options.put(OptionName.ENCODING, charset.name());
    if (classpath != null) options.put(OptionName.CLASSPATH, classpath);
    if (sourcepath != null) options.put(OptionName.SOURCEPATH, sourcepath);
    options.put("compilePolicy", "attr");
    CommentCollectingScanner.Factory.preRegister(context);

    JavaCompiler compiler = new JavaCompiler(context);
    compiler.keepComments = true;
    compiler.genEndPos = true;

    List<JCCompilationUnit> roots = new ArrayList<JCCompilationUnit>();
    Map<JCCompilationUnit, Comments> commentsMap =
        new IdentityHashMap<JCCompilationUnit, Comments>();
    Map<JCCompilationUnit, File> baseMap = new IdentityHashMap<JCCompilationUnit, File>();

    compiler.initProcessAnnotations(Collections.singleton(new lombok.javac.apt.Processor()));

    for (File fileToParse : filesToParse) {
      Comments comments = new Comments();
      context.put(Comments.class, comments);

      @SuppressWarnings("deprecation")
      JCCompilationUnit unit = compiler.parse(fileToParse.getAbsolutePath());

      commentsMap.put(unit, comments);
      baseMap.put(unit, fileToBase.get(fileToParse));
      roots.add(unit);
    }

    if (compiler.errorCount() > 0) {
      // At least one parse error. No point continuing (a real javac run doesn't either).
      return false;
    }

    TrackChangedAsts tca = new TrackChangedAsts();

    context.put(TrackChangedAsts.class, tca);

    JavaCompiler delegate = compiler.processAnnotations(compiler.enterTrees(toJavacList(roots)));
    for (JCCompilationUnit unit : roots) {
      DelombokResult result =
          new DelombokResult(
              commentsMap.get(unit).comments.toList(), unit, force || tca.changed.contains(unit));
      if (verbose)
        feedback.printf(
            "File: %s [%s]\n",
            unit.sourcefile.getName(), result.isChanged() ? "delomboked" : "unchanged");
      Writer rawWriter;
      if (presetWriter != null) rawWriter = presetWriter;
      else if (output == null) rawWriter = createStandardOutWriter();
      else rawWriter = createFileWriter(output, baseMap.get(unit), unit.sourcefile.toUri());
      BufferedWriter writer = new BufferedWriter(rawWriter);
      try {
        result.print(writer);
      } finally {
        writer.close();
      }
    }
    delegate.close();

    return true;
  }
예제 #13
0
  private static void openAnnotatedJava() {
    // Create list with source code names
    @SuppressWarnings("unchecked")
    Vector<String> myfilelist = new Vector<String>(cmd.getArgList());

    // Table that stores parsed compilation units
    Hashtable<String, CompilationUnit> myjpunitlist = new Hashtable<String, CompilationUnit>();

    // Declare outside, so filename can be used in case of exception.

    // Generate AST with JavaParser
    for (Enumeration<String> e = myfilelist.elements(); e.hasMoreElements(); ) {
      String mysource = "";
      CompilationUnit mycunit = null;

      try {
        // read filename
        mysource = e.nextElement();

        // Compile it with java parser.
        mycunit = JavaParser.parse(new FileInputStream(mysource));

        // Then fix the AST following the JC requirements
        ComplyToJCVisitor myfixervisitor = new ComplyToJCVisitor();
        mycunit = (CompilationUnit) myfixervisitor.visit(mycunit, new Integer(0));

        // creates an input stream and parse it using Java Parser
        myjpunitlist.put(mysource, mycunit);

        if (cmd.hasOption("d")) {
          // ASTDumpVisitor myjpvisitor = new ASTDumpVisitor();
          DumpVisitor myjpvisitor = new DumpVisitor();
          myjpvisitor.visit(myjpunitlist.get(mysource), null);
          System.out.print(myjpvisitor.getSource());
        }
      } catch (com.github.javaparser.ParseException ex) {
        System.out.println("Error: Parsing of Java file failed: " + mysource + ". Exiting...");
        System.exit(1);
      } catch (FileNotFoundException ex) {
        System.out.println("Error: File not found: " + mysource + ". Exiting...");
        System.exit(1);
      }
    }

    // Building internals from Java Compiler
    Context mycontext = new Context();
    JavaCompiler myjcompiler = new JavaCompiler(mycontext);
    JavaFileManager myfilemanager = mycontext.get(JavaFileManager.class);
    // Phase that Javac may go to: Setting code generation
    myjcompiler.shouldStopPolicyIfNoError = CompileState.GENERATE;

    // Table that stores the Java Compiler's ASTs
    List<JCCompilationUnit> ljctreelist = List.<JCCompilationUnit>nil();

    // Convert to Java Parser AST to JCTree AST's
    for (Enumeration<String> e = myjpunitlist.keys(); e.hasMoreElements(); ) {

      // read filename
      String mysource = e.nextElement();

      CompilationUnit myjpunit = myjpunitlist.get(mysource);

      JavaParser2JCTree translator = new JavaParser2JCTree(mycontext);
      AJCCompilationUnit myjctreeunit = (AJCCompilationUnit) translator.visit(myjpunit, myjpunit);

      // Setting additional information for Javac:
      // - Source file. Otherwise it throws a NullPointerException
      myjctreeunit.sourcefile = ((JavacFileManager) myfilemanager).getFileForInput(mysource);

      // Storing in the list
      ljctreelist = ljctreelist.append(myjctreeunit);

      // Debug: Shows how the JCTree AST was generated. Output node types.
      if (cmd.hasOption("d")) {
        try {
          Writer mystdout = new OutputStreamWriter(System.out);
          (new PrintAstVisitor(mystdout, true)).visitTopLevel(myjctreeunit);
          mystdout.flush();
        } catch (Exception z) {
        }
      }
    }

    // Enter (phase I): starting to build symtable
    Enter myenter = Enter.instance(mycontext);
    myenter.main(ljctreelist);
    // Enter (phase II): Finishing to build symtable
    /* MemberEnter mymemberenter = MemberEnter.instance(mycontext);
    mymemberenter.visitTopLevel(myjctreeunit); */

    // Get the todo list generated by Enter phase
    // From now on, the output of a phase is the input of the other.
    Todo mytodo = Todo.instance(mycontext);

    // atrribute: type-checking, name resolution, constant folding
    // flow: deadcode elimination
    // desugar: removes synctactic sugar: inner classes, class literals, assertions, foreachs
    myjcompiler.desugar(myjcompiler.flow(myjcompiler.attribute(mytodo)));

    // generate: produce bytecode or source code. Erases the whole AST
    // myjcompiler.generate(myjcompiler.desugar(myjcompiler.flow(myjcompiler.attribute( mytodo))));

    // Prints the Java program to output files and leave
    for (ListIterator<JCCompilationUnit> i = ljctreelist.listIterator(); i.hasNext(); ) {
      JCCompilationUnit myjctreeunit = i.next();
      try {
        Writer myoutputfile;

        if (cmd.getOptionValue("o") == null) {
          myoutputfile = new FileWriter(FileDescriptor.out);
        } else {
          myoutputfile = new FileWriter(myjctreeunit.sourcefile + ".new");
        }

        (new APretty(myoutputfile, true)).visitTopLevel(myjctreeunit);
        myoutputfile.flush();

      } catch (Exception e) {
        // TODO - Check what to report in case of error.
      }
    }
  }
예제 #14
0
    /**
     * Get the context for the next round of processing. Important values are propogated from round
     * to round; other values are implicitly reset.
     */
    private Context nextContext() {
      Context next = new Context(context);

      Options options = Options.instance(context);
      Assert.checkNonNull(options);
      next.put(Options.optionsKey, options);

      PrintWriter out = context.get(Log.outKey);
      Assert.checkNonNull(out);
      next.put(Log.outKey, out);
      Locale locale = context.get(Locale.class);
      if (locale != null) next.put(Locale.class, locale);
      Assert.checkNonNull(messages);
      next.put(JavacMessages.messagesKey, messages);

      final boolean shareNames = true;
      if (shareNames) {
        Names names = Names.instance(context);
        Assert.checkNonNull(names);
        next.put(Names.namesKey, names);
      }

      DiagnosticListener<?> dl = context.get(DiagnosticListener.class);
      if (dl != null) next.put(DiagnosticListener.class, dl);

      TaskListener tl = context.get(TaskListener.class);
      if (tl != null) next.put(TaskListener.class, tl);

      FSInfo fsInfo = context.get(FSInfo.class);
      if (fsInfo != null) next.put(FSInfo.class, fsInfo);

      JavaFileManager jfm = context.get(JavaFileManager.class);
      Assert.checkNonNull(jfm);
      next.put(JavaFileManager.class, jfm);
      if (jfm instanceof JavacFileManager) {
        ((JavacFileManager) jfm).setContext(next);
      }

      Names names = Names.instance(context);
      Assert.checkNonNull(names);
      next.put(Names.namesKey, names);

      Keywords keywords = Keywords.instance(context);
      Assert.checkNonNull(keywords);
      next.put(Keywords.keywordsKey, keywords);

      JavaCompiler oldCompiler = JavaCompiler.instance(context);
      JavaCompiler nextCompiler = JavaCompiler.instance(next);
      nextCompiler.initRound(oldCompiler);

      filer.newRound(next);
      messager.newRound(next);
      elementUtils.setContext(next);
      typeUtils.setContext(next);

      JavacTaskImpl task = context.get(JavacTaskImpl.class);
      if (task != null) {
        next.put(JavacTaskImpl.class, task);
        task.updateContext(next);
      }

      JavacTrees trees = context.get(JavacTrees.class);
      if (trees != null) {
        next.put(JavacTrees.class, trees);
        trees.updateContext(next);
      }

      context.clear();
      return next;
    }
예제 #15
0
 /** Enter a set of syntax trees. */
 private void enterTrees(List<JCCompilationUnit> roots) {
   compiler.enterTrees(roots);
 }
예제 #16
0
 /** Return the number of warnings found so far in this round. */
 int warningCount() {
   return compiler.warningCount();
 }
예제 #17
0
 /**
  * Return the number of errors found so far in this round. This may include uncoverable errors,
  * such as parse errors, and transient errors, such as missing symbols.
  */
 int errorCount() {
   return compiler.errorCount();
 }
예제 #18
0
  void createSymbols() throws IOException {
    Set<String> legacy = getLegacyPackages();
    Set<String> legacyProprietary = getLegacyPackages();
    Set<String> documented = new HashSet<String>();
    Set<PackageSymbol> packages =
        ((JavacProcessingEnvironment) processingEnv).getSpecifiedPackages();
    String jarName = processingEnv.getOptions().get("com.sun.tools.javac.sym.Jar");
    if (jarName == null)
      throw new RuntimeException("Must use -Acom.sun.tools.javac.sym.Jar=LOCATION_OF_JAR");
    String destName = processingEnv.getOptions().get("com.sun.tools.javac.sym.Dest");
    if (destName == null)
      throw new RuntimeException("Must use -Acom.sun.tools.javac.sym.Dest=LOCATION_OF_JAR");

    for (PackageSymbol psym : packages) {
      String name = psym.getQualifiedName().toString();
      legacyProprietary.remove(name);
      documented.add(name);
    }

    JavaCompiler tool = ToolProvider.getSystemJavaCompiler();
    StandardJavaFileManager fm = tool.getStandardFileManager(null, null, null);
    Location jarLocation = StandardLocation.locationFor(jarName);
    File jarFile = new File(jarName);
    fm.setLocation(jarLocation, List.of(jarFile));
    fm.setLocation(StandardLocation.CLASS_PATH, List.<File>nil());
    fm.setLocation(StandardLocation.SOURCE_PATH, List.<File>nil());
    {
      ArrayList<File> bootClassPath = new ArrayList<File>();
      bootClassPath.add(jarFile);
      for (File path : fm.getLocation(StandardLocation.PLATFORM_CLASS_PATH)) {
        if (!new File(path.getName()).equals(new File("rt.jar"))) bootClassPath.add(path);
      }
      System.err.println("Using boot class path = " + bootClassPath);
      fm.setLocation(StandardLocation.PLATFORM_CLASS_PATH, bootClassPath);
    }
    // System.out.println(fm.getLocation(StandardLocation.PLATFORM_CLASS_PATH));
    File destDir = new File(destName);
    if (!destDir.exists())
      if (!destDir.mkdirs()) throw new RuntimeException("Could not create " + destDir);
    fm.setLocation(StandardLocation.CLASS_OUTPUT, List.of(destDir));
    Set<String> hiddenPackages = new HashSet<String>();
    Set<String> crisp = new HashSet<String>();
    List<String> options = List.of("-XDdev");
    // options = options.prepend("-doe");
    // options = options.prepend("-verbose");
    JavacTaskImpl task = (JavacTaskImpl) tool.getTask(null, fm, null, options, null, null);
    com.sun.tools.javac.main.JavaCompiler compiler =
        com.sun.tools.javac.main.JavaCompiler.instance(task.getContext());
    ClassReader reader = ClassReader.instance(task.getContext());
    ClassWriter writer = ClassWriter.instance(task.getContext());
    Symtab syms = Symtab.instance(task.getContext());
    Attribute.Compound proprietary =
        new Attribute.Compound(
            syms.proprietaryType, List.<Pair<Symbol.MethodSymbol, Attribute>>nil());

    Type.moreInfo = true;
    Pool pool = new Pool();
    for (JavaFileObject file : fm.list(jarLocation, "", EnumSet.of(CLASS), true)) {
      String className = fm.inferBinaryName(jarLocation, file);
      int index = className.lastIndexOf('.');
      String pckName = index == -1 ? "" : className.substring(0, index);
      boolean addLegacyAnnotation = false;
      if (documented.contains(pckName)) {
        if (!legacy.contains(pckName)) crisp.add(pckName);
        // System.out.println("Documented: " + className);
      } else if (legacyProprietary.contains(pckName)) {
        addLegacyAnnotation = true;
        // System.out.println("Legacy proprietary: " + className);
      } else {
        // System.out.println("Hidden " + className);
        hiddenPackages.add(pckName);
        continue;
      }
      TypeSymbol sym = (TypeSymbol) compiler.resolveIdent(className);
      if (sym.kind != Kinds.TYP) {
        if (className.indexOf('$') < 0) {
          System.err.println("Ignoring (other) " + className + " : " + sym);
          System.err.println("   " + sym.getClass().getSimpleName() + " " + sym.type);
        }
        continue;
      }
      sym.complete();
      if (sym.getEnclosingElement().getKind() != ElementKind.PACKAGE) {
        System.err.println("Ignoring (bad) " + sym.getQualifiedName());
        continue;
      }
      ClassSymbol cs = (ClassSymbol) sym;
      if (addLegacyAnnotation) {
        cs.attributes_field =
            (cs.attributes_field == null)
                ? List.of(proprietary)
                : cs.attributes_field.prepend(proprietary);
      }
      writeClass(pool, cs, writer);
    }

    if (false) {
      for (String pckName : crisp) System.out.println("Crisp: " + pckName);
      for (String pckName : hiddenPackages) System.out.println("Hidden: " + pckName);
      for (String pckName : legacyProprietary) System.out.println("Legacy proprietary: " + pckName);
      for (String pckName : documented) System.out.println("Documented: " + pckName);
    }
  }
예제 #19
0
  // TODO: internal catch clauses?; catch and rethrow an annotation
  // processing error
  public JavaCompiler doProcessing(
      Context context,
      List<JCCompilationUnit> roots,
      List<ClassSymbol> classSymbols,
      Iterable<? extends PackageSymbol> pckSymbols) {

    TaskListener taskListener = context.get(TaskListener.class);
    log = Log.instance(context);

    Set<PackageSymbol> specifiedPackages = new LinkedHashSet<PackageSymbol>();
    for (PackageSymbol psym : pckSymbols) specifiedPackages.add(psym);
    this.specifiedPackages = Collections.unmodifiableSet(specifiedPackages);

    Round round = new Round(context, roots, classSymbols);

    boolean errorStatus;
    boolean moreToDo;
    do {
      // Run processors for round n
      round.run(false, false);

      // Processors for round n have run to completion.
      // Check for errors and whether there is more work to do.
      errorStatus = round.unrecoverableError();
      moreToDo = moreToDo();

      round.showDiagnostics(errorStatus || showResolveErrors);

      // Set up next round.
      // Copy mutable collections returned from filer.
      round =
          round.next(
              new LinkedHashSet<JavaFileObject>(filer.getGeneratedSourceFileObjects()),
              new LinkedHashMap<String, JavaFileObject>(filer.getGeneratedClasses()));

      // Check for errors during setup.
      if (round.unrecoverableError()) errorStatus = true;

    } while (moreToDo && !errorStatus);

    // run last round
    round.run(true, errorStatus);
    round.showDiagnostics(true);

    filer.warnIfUnclosedFiles();
    warnIfUnmatchedOptions();

    /*
     * If an annotation processor raises an error in a round,
     * that round runs to completion and one last round occurs.
     * The last round may also occur because no more source or
     * class files have been generated.  Therefore, if an error
     * was raised on either of the last *two* rounds, the compile
     * should exit with a nonzero exit code.  The current value of
     * errorStatus holds whether or not an error was raised on the
     * second to last round; errorRaised() gives the error status
     * of the last round.
     */
    if (messager.errorRaised() || werror && round.warningCount() > 0 && round.errorCount() > 0)
      errorStatus = true;

    Set<JavaFileObject> newSourceFiles =
        new LinkedHashSet<JavaFileObject>(filer.getGeneratedSourceFileObjects());
    roots = cleanTrees(round.roots);

    JavaCompiler compiler = round.finalCompiler(errorStatus);

    if (newSourceFiles.size() > 0) roots = roots.appendList(compiler.parseFiles(newSourceFiles));

    errorStatus = errorStatus || (compiler.errorCount() > 0);

    // Free resources
    this.close();

    if (taskListener != null)
      taskListener.finished(new TaskEvent(TaskEvent.Kind.ANNOTATION_PROCESSING));

    if (errorStatus) {
      if (compiler.errorCount() == 0) compiler.log.nerrors++;
      return compiler;
    }

    if (procOnly && !foundTypeProcessors) {
      compiler.todo.clear();
    } else {
      if (procOnly && foundTypeProcessors) compiler.shouldStopPolicy = CompileState.FLOW;

      compiler.enterTrees(roots);
    }

    return compiler;
  }