Esempio n. 1
0
 private void prepareCompiler() throws IOException {
   if (used.getAndSet(true)) {
     if (compiler == null) throw new IllegalStateException();
   } else {
     initContext();
     compilerMain.setOptions(Options.instance(context));
     compilerMain.filenames = new LinkedHashSet<File>();
     Collection<File> filenames = compilerMain.processArgs(CommandLine.parse(args), classNames);
     if (!filenames.isEmpty())
       throw new IllegalArgumentException("Malformed arguments " + toString(filenames, " "));
     compiler = JavaCompiler.instance(context);
     compiler.keepComments = true;
     compiler.genEndPos = true;
     // NOTE: this value will be updated after annotation processing
     compiler.initProcessAnnotations(processors);
     notYetEntered = new HashMap<JavaFileObject, JCCompilationUnit>();
     for (JavaFileObject file : fileObjects) notYetEntered.put(file, null);
     genList = new ListBuffer<Env<AttrContext>>();
     // endContext will be called when all classes have been generated
     // TODO: should handle the case after each phase if errors have occurred
     args = null;
     classNames = null;
   }
 }
  private ExitCode compile(
      final CompileContext context,
      ModuleChunk chunk,
      DirtyFilesHolder<JavaSourceRootDescriptor, ModuleBuildTarget> dirtyFilesHolder,
      Collection<File> files,
      OutputConsumer outputConsumer)
      throws Exception {
    ExitCode exitCode = ExitCode.NOTHING_DONE;

    final boolean hasSourcesToCompile = !files.isEmpty();

    if (!hasSourcesToCompile && !dirtyFilesHolder.hasRemovedFiles()) {
      return exitCode;
    }

    final ProjectDescriptor pd = context.getProjectDescriptor();

    JavaBuilderUtil.ensureModuleHasJdk(
        chunk.representativeTarget().getModule(), context, BUILDER_NAME);
    final Collection<File> classpath =
        ProjectPaths.getCompilationClasspath(chunk, false /*context.isProjectRebuild()*/);
    final Collection<File> platformCp =
        ProjectPaths.getPlatformCompilationClasspath(chunk, false /*context.isProjectRebuild()*/);

    // begin compilation round
    final DiagnosticSink diagnosticSink = new DiagnosticSink(context);
    final Mappings delta = pd.dataManager.getMappings().createDelta();
    final Callbacks.Backend mappingsCallback = delta.getCallback();
    final OutputFilesSink outputSink =
        new OutputFilesSink(context, outputConsumer, mappingsCallback, chunk.getName());
    try {
      if (hasSourcesToCompile) {
        final AtomicReference<String> ref = COMPILER_VERSION_INFO.get(context);
        final String versionInfo =
            ref.getAndSet(null); // display compiler version info only once per compile session
        if (versionInfo != null) {
          LOG.info(versionInfo);
          context.processMessage(new CompilerMessage("", BuildMessage.Kind.INFO, versionInfo));
        }
        exitCode = ExitCode.OK;

        final Set<File> srcPath = new HashSet<File>();
        final BuildRootIndex index = pd.getBuildRootIndex();
        for (ModuleBuildTarget target : chunk.getTargets()) {
          for (JavaSourceRootDescriptor rd : index.getTempTargetRoots(target, context)) {
            srcPath.add(rd.root);
          }
        }

        final String chunkName = chunk.getName();
        context.processMessage(new ProgressMessage("Parsing java... [" + chunkName + "]"));

        final int filesCount = files.size();
        boolean compiledOk = true;
        if (filesCount > 0) {
          LOG.info(
              "Compiling "
                  + filesCount
                  + " java files; module: "
                  + chunkName
                  + (chunk.containsTests() ? " (tests)" : ""));
          if (LOG.isDebugEnabled()) {
            for (File file : files) {
              LOG.debug("Compiling " + file.getPath());
            }
            LOG.debug(" classpath for " + chunkName + ":");
            for (File file : classpath) {
              LOG.debug("  " + file.getAbsolutePath());
            }
            LOG.debug(" platform classpath for " + chunkName + ":");
            for (File file : platformCp) {
              LOG.debug("  " + file.getAbsolutePath());
            }
          }
          compiledOk =
              compileJava(
                  context,
                  chunk,
                  files,
                  classpath,
                  platformCp,
                  srcPath,
                  diagnosticSink,
                  outputSink);
        }

        context.checkCanceled();

        if (!compiledOk && diagnosticSink.getErrorCount() == 0) {
          diagnosticSink.report(
              new PlainMessageDiagnostic(
                  Diagnostic.Kind.ERROR, "Compilation failed: internal java compiler error"));
        }
        if (!Utils.PROCEED_ON_ERROR_KEY.get(context, Boolean.FALSE)
            && diagnosticSink.getErrorCount() > 0) {
          if (!compiledOk) {
            diagnosticSink.report(
                new PlainMessageDiagnostic(
                    Diagnostic.Kind.OTHER,
                    "Errors occurred while compiling module '" + chunkName + "'"));
          }
          throw new ProjectBuildException(
              "Compilation failed: errors: "
                  + diagnosticSink.getErrorCount()
                  + "; warnings: "
                  + diagnosticSink.getWarningCount());
        }
      }
    } finally {
      if (JavaBuilderUtil.updateMappings(
          context, delta, dirtyFilesHolder, chunk, files, outputSink.getSuccessfullyCompiled())) {
        exitCode = ExitCode.ADDITIONAL_PASS_REQUIRED;
      }
    }

    return exitCode;
  }
Esempio n. 3
0
  public static boolean compile(
      Collection<String> options,
      final Collection<File> sources,
      Collection<File> classpath,
      Collection<File> platformClasspath,
      Collection<File> sourcePath,
      Map<File, Set<File>> outputDirToRoots,
      final DiagnosticOutputConsumer outConsumer,
      final OutputFileConsumer outputSink,
      CanceledStatus canceledStatus,
      boolean useEclipseCompiler) {
    JavaCompiler compiler = null;
    if (useEclipseCompiler) {
      for (JavaCompiler javaCompiler : ServiceLoader.load(JavaCompiler.class)) {
        compiler = javaCompiler;
        break;
      }
      if (compiler == null) {
        outConsumer.report(
            new PlainMessageDiagnostic(
                Diagnostic.Kind.ERROR, "Eclipse Batch Compiler was not found in classpath"));
        return false;
      }
    }

    final boolean nowUsingJavac;
    if (compiler == null) {
      compiler = ToolProvider.getSystemJavaCompiler();
      if (compiler == null) {
        outConsumer.report(
            new PlainMessageDiagnostic(
                Diagnostic.Kind.ERROR, "System Java Compiler was not found in classpath"));
        return false;
      }
      nowUsingJavac = true;
    } else {
      nowUsingJavac = false;
    }

    for (File outputDir : outputDirToRoots.keySet()) {
      outputDir.mkdirs();
    }

    final List<JavaSourceTransformer> transformers = getSourceTransformers();

    final JavacFileManager fileManager =
        new JavacFileManager(
            new ContextImpl(compiler, outConsumer, outputSink, canceledStatus, nowUsingJavac),
            transformers);

    fileManager.handleOption(
        "-bootclasspath", Collections.singleton("").iterator()); // this will clear cached stuff
    fileManager.handleOption(
        "-extdirs", Collections.singleton("").iterator()); // this will clear cached stuff

    try {
      fileManager.setOutputDirectories(outputDirToRoots);
    } catch (IOException e) {
      fileManager.getContext().reportMessage(Diagnostic.Kind.ERROR, e.getMessage());
      return false;
    }

    if (!classpath.isEmpty()) {
      try {
        fileManager.setLocation(StandardLocation.CLASS_PATH, classpath);
        if (!nowUsingJavac && !isOptionSet(options, "-processorpath")) {
          // for non-javac file manager ensure annotation processor path defaults to classpath
          fileManager.setLocation(StandardLocation.ANNOTATION_PROCESSOR_PATH, classpath);
        }
      } catch (IOException e) {
        fileManager.getContext().reportMessage(Diagnostic.Kind.ERROR, e.getMessage());
        return false;
      }
    }
    if (!platformClasspath.isEmpty()) {
      try {
        fileManager.setLocation(StandardLocation.PLATFORM_CLASS_PATH, platformClasspath);
      } catch (IOException e) {
        fileManager.getContext().reportMessage(Diagnostic.Kind.ERROR, e.getMessage());
        return false;
      }
    }
    try {
      // ensure the source path is set;
      // otherwise, if not set, javac attempts to search both classes and sources in classpath;
      // so if some classpath jars contain sources, it will attempt to compile them
      fileManager.setLocation(StandardLocation.SOURCE_PATH, sourcePath);
    } catch (IOException e) {
      fileManager.getContext().reportMessage(Diagnostic.Kind.ERROR, e.getMessage());
      return false;
    }

    //noinspection IOResourceOpenedButNotSafelyClosed
    final LineOutputWriter out =
        new LineOutputWriter() {
          protected void lineAvailable(String line) {
            if (nowUsingJavac) {
              outConsumer.outputLineAvailable(line);
            } else {
              // todo: filter too verbose eclipse output?
            }
          }
        };

    try {
      final Collection<String> _options = prepareOptions(options, nowUsingJavac);

      // to be on the safe side, we'll have to apply all options _before_ calling any of manager's
      // methods
      // i.e. getJavaFileObjectsFromFiles()
      // This way the manager will be properly initialized. Namely, the encoding will be set
      // correctly
      for (Iterator<String> iterator = _options.iterator(); iterator.hasNext(); ) {
        fileManager.handleOption(iterator.next(), iterator);
      }

      final JavaCompiler.CompilationTask task =
          compiler.getTask(
              out,
              fileManager,
              outConsumer,
              _options,
              null,
              fileManager.getJavaFileObjectsFromFiles(sources));

      // if (!IS_VM_6_VERSION) { //todo!
      //  // Do not add the processor for JDK 1.6 because of the bugs in javac
      //  // The processor's presence may lead to NPE and resolve bugs in compiler
      //  final JavacASTAnalyser analyzer = new JavacASTAnalyser(outConsumer,
      // !annotationProcessingEnabled);
      //  task.setProcessors(Collections.singleton(analyzer));
      // }
      return task.call();
    } catch (IllegalArgumentException e) {
      outConsumer.report(new PlainMessageDiagnostic(Diagnostic.Kind.ERROR, e.getMessage()));
    } catch (CompilationCanceledException ignored) {
      outConsumer.report(
          new PlainMessageDiagnostic(Diagnostic.Kind.OTHER, "Compilation was canceled"));
    } finally {
      fileManager.close();
      if (nowUsingJavac) {
        cleanupJavacNameTable();
      }
    }
    return false;
  }