public ExitCode build()

in jps-plugin/src/org/jetbrains/jps/clojure/build/ClojureBuilder.java [59:200]


  public ExitCode build(final CompileContext context, final ModuleChunk chunk,
                        DirtyFilesHolder<JavaSourceRootDescriptor, ModuleBuildTarget> dirtyFilesHolder,
                        final OutputConsumer outputConsumer) throws ProjectBuildException, IOException {
    JpsProject project = context.getProjectDescriptor().getProject();
    JpsClojureCompilerSettingsExtension extension = JpsClojureExtensionService.getExtension(project);
    if (myBeforeJava && (extension == null || !extension.isClojureBefore())) return ExitCode.NOTHING_DONE;
    if (!myBeforeJava && extension != null && extension.isClojureBefore()) return ExitCode.NOTHING_DONE;
    if (extension != null && !extension.isCompileClojure()) return ExitCode.NOTHING_DONE;

    final LinkedHashSet<JpsModule> javaModules = new LinkedHashSet<JpsModule>();
    for (JpsModule module : chunk.getModules()) {
      if (module.getModuleType().equals(JpsJavaModuleType.INSTANCE)) {
        javaModules.add(module);
      }
    }

    final List<File> toCompile = new ArrayList<File>();
    final HashMap<File, String> toCompileNamespace = new HashMap<File, String>();
    dirtyFilesHolder.processDirtyFiles(new FileProcessor<JavaSourceRootDescriptor, ModuleBuildTarget>() {
      public boolean apply(ModuleBuildTarget target, File file, JavaSourceRootDescriptor sourceRoot) throws IOException {
        if (javaModules.contains(target.getModule()) && file.getName().endsWith(".clj")) {
          if (!hasGenClass(file)) {
            return true;
          }
          
          toCompile.add(file);
          
          String filePath = file.getAbsolutePath();
          File rootFile = sourceRoot.getRootFile();
          String relPath = filePath.substring(rootFile.getAbsolutePath().length() + 1, filePath.length() - ".clj".length());
          toCompileNamespace.put(file, relPath.replace(File.separator, "."));
        }
        return true;
      }
    });

    if (toCompile.isEmpty()) return ExitCode.NOTHING_DONE;

    JpsSdk<JpsDummyElement> sdk = chunk.representativeTarget().getModule().getSdk(JpsJavaSdkType.INSTANCE);
    if (sdk == null) {
      context.processMessage(new CompilerMessage(COMPILER_NAME, BuildMessage.Kind.ERROR, "JDK is not specified"));
      return ExitCode.ABORT;
    }

    String javaExecutable = JpsJavaSdkType.getJavaExecutable(sdk);

    List<String> classpath = new ArrayList<String>();
    for (File root : JpsJavaExtensionService.getInstance().enumerateDependencies(javaModules).classes().getRoots()) {
      classpath.add(root.getAbsolutePath());
    }
    for (JpsModule module : javaModules) {
      for (JpsModuleSourceRoot sourceRoot : module.getSourceRoots()) {
        classpath.add(sourceRoot.getFile().getAbsolutePath());
      }
    }

    List<String> vmParams = new ArrayList<String>();
//    vmParams.add("-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=5239");
    List<String> programParams = new ArrayList<String>();
    File outputDir = chunk.representativeTarget().getOutputDir();
    outputDir.mkdirs();
    
    File fileWithCompileScript = FileUtil.createTempFile("clojurekul", ".clj");
    fillFileWithClojureCompilerParams(toCompile, toCompileNamespace, fileWithCompileScript, outputDir);
    programParams.add(fileWithCompileScript.getAbsolutePath());
    List<String> commandLine =
        ExternalProcessUtil.buildJavaCommandLine(javaExecutable, CLOJURE_MAIN, Collections.<String>emptyList(), classpath, vmParams, programParams);

    Process process = Runtime.getRuntime().exec(ArrayUtil.toStringArray(commandLine));

    BaseOSProcessHandler handler = new BaseOSProcessHandler(process, null, null) {
      @Override
      protected Future<?> executeOnPooledThread(Runnable task) {
        return SharedThreadPool.getInstance().executeOnPooledThread(task);
      }
    };

    final SourceToOutputMapping sourceToOutputMap = context.getProjectDescriptor().dataManager.getSourceToOutputMap(chunk.representativeTarget());

    final HashSet<String> outputs = new HashSet<String>();

    handler.addProcessListener(new ProcessAdapter() {
      @Override
      public void onTextAvailable(ProcessEvent event, Key outputType) {
        if (outputType != ProcessOutputTypes.STDERR) return;
        String text = event.getText().trim();
        context.processMessage(new ProgressMessage(text));
//        context.processMessage(new CompilerMessage(COMPILER_NAME, BuildMessage.Kind.WARNING, text));
        if (text.startsWith(ERROR_PREFIX)) {
          String errorDescription = text.substring(ERROR_PREFIX.length());
          Pattern pattern = Pattern.compile("(.*)@@((.*) compiling:[(](.*):([\\d]*)(:([\\d]*))?[)])");
          Matcher matcher = pattern.matcher(errorDescription);
          if (matcher.matches()) {
            String sourceName = matcher.group(1);
            String lineNumber = matcher.group(5);
            String columnNumber = matcher.group(6);
            Long locationLine = -1L;
            Long column = 0L;
            try {
              locationLine = Long.parseLong(lineNumber);
              if (columnNumber != null) {
                column = Long.parseLong(columnNumber);
              }
            } catch (Exception ignore) {}
            String errorMessage = matcher.group(2);
            context.processMessage(new CompilerMessage(COMPILER_NAME, BuildMessage.Kind.ERROR, errorMessage,
                sourceName, -1L, -1L, -1L, locationLine, column));
          } else {
            matcher = Pattern.compile("(.*)@@(.*)").matcher(errorDescription);
            if (matcher.matches()) {
              context.processMessage(new CompilerMessage(COMPILER_NAME, BuildMessage.Kind.ERROR, matcher.group(2), matcher.group(1)));
            } else {
              context.processMessage(new CompilerMessage(COMPILER_NAME, BuildMessage.Kind.ERROR, text));
            }
          }
        } else if (text.startsWith(COMPILING_PREFIX)) {
          //we don't need to do anything
        } else if (text.startsWith(WRITING_PREFIX)) {
          outputs.add(text.substring(WRITING_PREFIX.length()));
        } else if (text.startsWith(COMPILED_PREFIX)) {
          for (String output : outputs) {
            try {
              outputConsumer.registerOutputFile(chunk.representativeTarget(),
                  new File(output),
                  Collections.singleton(text.substring(COMPILED_PREFIX.length())));
            } catch (IOException e) {
              context.processMessage(new BuildMessage(e.getMessage(), BuildMessage.Kind.ERROR) {});
            }
          }
          outputs.clear();
        }
      }
    });

    handler.startNotify();
    handler.waitFor();
    if (process.exitValue() != 0) {
      context.processMessage(new CompilerMessage(COMPILER_NAME, BuildMessage.Kind.ERROR, "Clojure compiler returned code " + process.exitValue()));
    }

    return ExitCode.OK;
  }