All Downloads are FREE. Search and download functionalities are using the official Maven repository.

sbt_inc.SbtIncrementalCompiler Maven / Gradle / Ivy

package sbt_inc;

import com.typesafe.zinc.Compiler;
import com.typesafe.zinc.*;
import org.apache.maven.plugin.logging.Log;
import scala.Option;
import scala_maven_executions.MainHelper;

import java.io.File;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class SbtIncrementalCompiler {

    public static final String SBT_GROUP_ID = "com.typesafe.sbt";
    public static final String COMPILER_INTEGRATION_ARTIFACT_ID = "incremental-compiler";
    public static final String COMPILER_INTERFACE_ARTIFACT_ID = "compiler-interface";
    public static final String COMPILER_INTERFACE_CLASSIFIER = "sources";
    public static final String XSBTI_ARTIFACT_ID = "sbt-interface";

    private static final String ANALYSIS_MAP_ARG_SEPARATOR = ",";
    private static final String ANALYSIS_MAP_PAIR_SEPARATOR = File.pathSeparator;

    private Log log;

    private ZincClient zinc;

    private boolean useServer = false;

    private File compilerJar;

    private File libraryJar;

    private List extraJars;

    private List extraArgs;

    private xsbti.Logger logger;

    private Compiler compiler;

    public SbtIncrementalCompiler(boolean useZincServer, int zincPort, File libraryJar, File compilerJar, List extraJars, File xsbtiJar, File interfaceJar, Log l, List args) throws Exception {
        this.log = l;
        if (useZincServer) {
            this.zinc = new ZincClient(zincPort);
            if (zinc.serverAvailable()) {
                l.info("Using zinc server for incremental compilation");
                this.useServer = true;
                this.compilerJar = compilerJar;
                this.libraryJar = libraryJar;
                this.extraJars = extraJars;
                this.extraArgs = args;
            } else {
                l.warn("Zinc server is not available at port " + zincPort + " - reverting to normal incremental compile");
                this.useServer = false;
            }
        }
        if (!useServer) {
            l.info("Using incremental compilation");
            if (args.size() > 0) l.warn("extra args for zinc are ignored in non-server mode");
            this.logger = new SbtLogger(l);
            Setup setup = Setup.create(compilerJar, libraryJar, extraJars, xsbtiJar, interfaceJar, null, false);
            if (l.isDebugEnabled()) Setup.debug(setup, logger);
            this.compiler = Compiler.create(setup, logger);
        }
    }

    private IncOptions defaultOptions() {
        sbt.inc.IncOptions defaultSbtOptions = sbt.inc.IncOptions.Default();
        return new IncOptions(
                defaultSbtOptions.transitiveStep(),
                defaultSbtOptions.recompileAllFraction(),
                defaultSbtOptions.relationsDebug(),
                defaultSbtOptions.apiDebug(),
                defaultSbtOptions.apiDiffContextSize(),
                defaultSbtOptions.apiDumpDirectory(),
                false,
                Option.empty(),
                defaultSbtOptions.recompileOnMacroDef(),
                defaultSbtOptions.nameHashing());
    }

    public void compile(File baseDir, List classpathElements, List sources, File classesDirectory, List scalacOptions, List javacOptions, File cacheFile, Map cacheMap, String compileOrder) throws Exception {
        if (useServer) {
            zincCompile(baseDir, classpathElements, sources, classesDirectory, scalacOptions, javacOptions, cacheFile, cacheMap, compileOrder);
        } else {
            if (log.isDebugEnabled()) log.debug("Incremental compiler = " + compiler + " [" + Integer.toHexString(compiler.hashCode()) + "]");
            List classpath = pathsToFiles(classpathElements);
            Inputs inputs = Inputs.create(classpath, sources, classesDirectory, scalacOptions, javacOptions, cacheFile, cacheMap, compileOrder, defaultOptions(), true);
            if (log.isDebugEnabled()) Inputs.debug(inputs, logger);
            compiler.compile(inputs, logger);
        }
    }

    private void zincCompile(File baseDir, List classpathElements, List sources, File classesDirectory, List scalacOptions, List javacOptions, File cacheFile, Map cacheMap, String compileOrder) throws Exception {
        List arguments = new ArrayList(extraArgs);
        arguments.add("-log-level");
        arguments.add(logLevelToString(log));
        arguments.add("-scala-compiler");
        arguments.add(compilerJar.getAbsolutePath());
        arguments.add("-scala-library");
        arguments.add(libraryJar.getAbsolutePath());
        arguments.add("-scala-extra");
        List extraPaths = new ArrayList();
        for (File extraJar : extraJars) {
            extraPaths.add(extraJar.getAbsolutePath());
        }
        arguments.add(MainHelper.toMultiPath(extraPaths));
        if (!classpathElements.isEmpty()) {
          arguments.add("-classpath");
          arguments.add(MainHelper.toMultiPath(classpathElements));
        }
        arguments.add("-d");
        arguments.add(classesDirectory.getAbsolutePath());
        for (String scalacOption : scalacOptions) {
            arguments.add("-S" + scalacOption);
        }
        for (String javacOption : javacOptions) {
            arguments.add("-C" + javacOption);
        }
        arguments.add("-compile-order");
        arguments.add(compileOrder);
        arguments.add("-analysis-cache");
        arguments.add(cacheFile.getAbsolutePath());
        arguments.add("-analysis-map");
        arguments.add(cacheMapToString(cacheMap));
        for (File source : sources) {
            arguments.add(source.getAbsolutePath());
        }

        int exitCode = zinc.run(arguments, baseDir, System.out, System.err);

        if (exitCode != 0) {
            xsbti.Problem[] problems = null;
            throw new sbt.compiler.CompileFailed(arguments.toArray(new String[arguments.size()]), "Compile failed via zinc server", problems);
        }
    }

    private List pathsToFiles(List paths) {
        List files = new ArrayList(paths.size());
        for (String path : paths) {
            files.add(new File(path));
        }
        return files;
    }

    private String logLevelToString(Log l) {
        if (l.isDebugEnabled()) return "debug";
        else if (l.isInfoEnabled()) return "info";
        else if (l.isWarnEnabled()) return "warn";
        else if (l.isErrorEnabled()) return "error";
        else return "info";
    }

    private String cacheMapToString(Map cacheMap) throws Exception {
        String analysisMap = "";
        boolean addArgSeparator = false;
        for (Map.Entry entry : cacheMap.entrySet()) {
            if (addArgSeparator) analysisMap += ANALYSIS_MAP_ARG_SEPARATOR;
            analysisMap += entry.getKey().getAbsolutePath();
            analysisMap += ANALYSIS_MAP_PAIR_SEPARATOR;
            analysisMap += entry.getValue().getAbsolutePath();
            addArgSeparator = true;
        }
        return analysisMap;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy