Package ideah.util

Source Code of ideah.util.AskUtil$HsCallback

package ideah.util;

import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.projectRoots.SdkAdditionalData;
import com.intellij.openapi.roots.ModuleRootManager;
import com.intellij.openapi.util.io.StreamUtil;
import com.intellij.openapi.vfs.VirtualFile;
import ideah.sdk.HaskellSdkAdditionalData;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.io.*;
import java.util.List;
import java.util.Map;
import java.util.SortedSet;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

/**
* Helper class to build ask_* executables
*/
final class AskUtil {

    private static final Logger LOG = Logger.getInstance("ideah.util.AskUtil");

    private static Long sourcesLastModified = null;

    @NotNull
    private final VirtualFile ghcHome;
    @NotNull
    private final String libDir;
    private final String cabalPath;
    private final String ghcOptions;
    @NotNull
    private final File pluginPath;
    @NotNull
    private final File exe;
    @NotNull
    private final String mainFile;
    private final HaskellSdkAdditionalData data;

    private AskUtil(@NotNull VirtualFile ghcHome, @NotNull String libDir, String cabalPath, String ghcOptions,
                    @NotNull File pluginPath, @NotNull File exe, @NotNull String mainFile, HaskellSdkAdditionalData data) {
        this.ghcHome = ghcHome;
        this.libDir = libDir;
        this.cabalPath = cabalPath;
        this.ghcOptions = ghcOptions;
        this.pluginPath = pluginPath;
        this.exe = exe;
        this.mainFile = mainFile;
        this.data = data;
    }

    @Nullable
    static AskUtil get(@Nullable Module module, String mainFile) {
        if (module == null)
            return null;
        Sdk sdk = ModuleRootManager.getInstance(module).getSdk();
        if (sdk == null)
            return null;
        VirtualFile ghcHome = sdk.getHomeDirectory();
        if (ghcHome == null)
            return null;
        SdkAdditionalData sdkAdditionalData = sdk.getSdkAdditionalData();
        if (!(sdkAdditionalData instanceof HaskellSdkAdditionalData))
            return null;
        HaskellSdkAdditionalData data = (HaskellSdkAdditionalData) sdkAdditionalData;
        String libDir = data.getLibPath();
        if (libDir == null)
            return null;
        File pluginPath = new File(new File(System.getProperty("user.home"), ".ideah"), sdk.getVersionString());
        pluginPath.mkdirs();
        File exe = new File(pluginPath, GHCUtil.getExeName(mainFile));
        return new AskUtil(ghcHome, libDir, data.getCabalPath(), data.getGhcOptions(), pluginPath, exe, mainFile, data);
    }

    String getLibDir() {
        return libDir;
    }

    String getCabalPath() {
        return cabalPath;
    }

    String getGhcOptions() {
        return ghcOptions;
    }

    File getExe() {
        if (exe.exists()) {
            return exe;
        } else {
            return null;
        }
    }

    private interface HsCallback {

        void run(ZipInputStream zis, ZipEntry entry) throws IOException;
    }

    private static void listHaskellSources(HsCallback callback) throws IOException {
        InputStream is = AskUtil.class.getResourceAsStream("/ask_ghc.jar");
        if (is == null)
            throw new FileNotFoundException("<classpath>/ask_ghc.jar");

        ZipInputStream zis = new ZipInputStream(is);
        while (true) {
            ZipEntry entry = zis.getNextEntry();
            if (entry == null)
                break;
            callback.run(zis, entry);
            zis.closeEntry();
        }
        zis.close();
    }

    boolean needRecompile() throws IOException {
        if (exe.exists()) {
            if (sourcesLastModified == null) {
                final Long[] maxModified = new Long[1];
                listHaskellSources(new HsCallback() {
                    public void run(ZipInputStream zis, ZipEntry entry) {
                        long lastModified = entry.getTime();
                        if (maxModified[0] == null) {
                            maxModified[0] = lastModified;
                        } else {
                            maxModified[0] = Math.max(maxModified[0].longValue(), lastModified);
                        }
                    }
                });
                sourcesLastModified = maxModified[0];
            }
            return sourcesLastModified != null && sourcesLastModified.longValue() > exe.lastModified();
        } else {
            return true;
        }
    }

    boolean compileHs(@Nullable ProgressIndicator indicator, double maxIndicatorFraction) throws IOException, InterruptedException {
        exe.delete();
        String ghcExe = GHCUtil.getGhcCommandPath(ghcHome);
        if (ghcExe == null)
            return false;
        double step = 0;
        if (indicator != null) {
            step = (maxIndicatorFraction - indicator.getFraction()) / 3;
        }
        updateIndicator(indicator, step, "Collecting source files...");
        listHaskellSources(new AskUtil.HsCallback() {
            public void run(ZipInputStream zis, ZipEntry entry) throws IOException {
                File outFile = new File(pluginPath, entry.getName());
                OutputStream os = new FileOutputStream(outFile);
                try {
                    StreamUtil.copyStreamContent(zis, os);
                } finally {
                    os.close();
                }
            }
        });
        updateIndicator(indicator, step, "Compiling " + mainFile + "...");
        String mainHs = mainFile + ".hs";
        ProcessLauncher launcher = new ProcessLauncher(true, null, ghcExe,
            "--make", "-cpp", "-O", "-package", "ghc",
            "-i" + pluginPath.getAbsolutePath(),
            new File(pluginPath, mainHs).getAbsolutePath()
        );
        updateIndicator(indicator, step, "Finishing compilation...");
        for (int i = 0; i < 3; i++) {
            if (exe.exists())
                return true;
            Thread.sleep(100);
        }
        String stdErr = launcher.getStdErr();
        LOG.error("Compiling " + mainHs + ":\n" + stdErr);
        return false;
    }

    static void increaseIndicatorFraction(@Nullable ProgressIndicator indicator, double step) {
        updateIndicator(indicator, step, null);
    }

    static void updateIndicatorText(@Nullable ProgressIndicator indicator, String message) {
        updateIndicator(indicator, 0, message);
    }

    private static void updateIndicator(@Nullable ProgressIndicator indicator, double step, String message) {
        if (indicator != null) {
            indicator.setFraction(indicator.getFraction() + step);
            if (message != null) {
                indicator.setText2(message);
            }
        }
    }

    void loadAutoImport(final CompilerLocation compiler) {
        if (data.getAutoImports() != null)
            return;
        ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
            public void run() {
                List<String> args = compiler.getCompileOptionsList(
                    "-m", "AutoImport"
                );
                try {
                    ProcessLauncher launcher = new ProcessLauncher(false, null, args);
                    String stdOut = launcher.getStdOut();
                    Map<String, SortedSet<String>> autoImports = ParseAutoImports.parseAutoImports(stdOut);
                    data.setAutoImports(autoImports);
                } catch (Exception ex) {
                    LOG.error(ex);
                }
            }
        });
    }
}
TOP

Related Classes of ideah.util.AskUtil$HsCallback

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.