Package org.jetbrains.plugins.clojure.runner

Source Code of org.jetbrains.plugins.clojure.runner.ClojureScriptRunConfiguration

package org.jetbrains.plugins.clojure.runner;

import com.intellij.execution.CantRunException;
import com.intellij.execution.CommonProgramRunConfigurationParameters;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.Executor;
import com.intellij.execution.configurations.*;
import com.intellij.execution.filters.Filter;
import com.intellij.execution.filters.TextConsoleBuilderImpl;
import com.intellij.execution.impl.ConsoleViewImpl;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.ui.ConsoleView;
import com.intellij.execution.util.ProgramParametersUtil;
import com.intellij.openapi.components.PathMacroManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.module.Module;
import com.intellij.openapi.module.ModuleManager;
import com.intellij.openapi.options.SettingsEditor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.projectRoots.JavaSdkType;
import com.intellij.openapi.projectRoots.Sdk;
import com.intellij.openapi.roots.*;
import com.intellij.openapi.roots.ui.configuration.ClasspathEditor;
import com.intellij.openapi.roots.ui.configuration.ModulesConfigurator;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.JDOMExternalizer;
import com.intellij.openapi.util.WriteExternalException;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiManager;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.clojure.ClojureBundle;
import org.jetbrains.plugins.clojure.config.ClojureConfigUtil;
import org.jetbrains.plugins.clojure.file.ClojureFileType;
import org.jetbrains.plugins.clojure.psi.api.ClojureFile;
import org.jetbrains.plugins.clojure.utils.ClojureUtils;

import java.io.File;
import java.util.*;

public class ClojureScriptRunConfiguration extends ModuleBasedConfiguration<RunConfigurationModule> implements CommonProgramRunConfigurationParameters {
  private static final Logger LOG = Logger.getInstance("#org.jetbrains.plugins.clojure.runner.ClojureScriptRunConfiguration");
  private ClojureScriptConfigurationFactory factory;
  private String scriptPath;
  private String workDir;
  private String vmParams;
  private String scriptParams;
  private boolean runInREPL;
  private boolean runMainFunction;
  private final Map<String, String> envs = new com.intellij.util.containers.hash.LinkedHashMap<String, String>();
  public boolean passParentEnv = true;

  //  private static final String JLINE_CONSOLE_RUNNER = "jline.ConsoleRunner";

  public ClojureScriptRunConfiguration(ClojureScriptConfigurationFactory factory, Project project, String name) {
    super(name, new RunConfigurationModule(project), factory);
    this.factory = factory;
  }

  public Collection<Module> getValidModules() {
    Module[] modules = ModuleManager.getInstance(getProject()).getModules();
    ArrayList<Module> res = new ArrayList<Module>();
    for (Module module : modules) {
      res.add(module);
    }
    return res;
  }

  public void setWorkDir(String dir) {
    workDir = dir;
  }

  public String getWorkDir() {
    return workDir;
  }

  public void readExternal(Element element) throws InvalidDataException {
    PathMacroManager.getInstance(getProject()).expandPaths(element);
    super.readExternal(element);
    readModule(element);
    scriptPath = JDOMExternalizer.readString(element, "path");
    vmParams = JDOMExternalizer.readString(element, "vmparams");
    scriptParams = JDOMExternalizer.readString(element, "params");
    workDir = JDOMExternalizer.readString(element, "workDir");
    runInREPL = Boolean.parseBoolean(JDOMExternalizer.readString(element, "repl"));
    runMainFunction = Boolean.parseBoolean(JDOMExternalizer.readString(element, "main"));
    workDir = getWorkDir();

    envs.clear();
    JDOMExternalizer.readMap(element, envs, null, "env");
  }

  public void writeExternal(Element element) throws WriteExternalException {
    super.writeExternal(element);
    writeModule(element);
    JDOMExternalizer.write(element, "path", scriptPath);
    JDOMExternalizer.write(element, "vmparams", vmParams);
    JDOMExternalizer.write(element, "params", scriptParams);
    JDOMExternalizer.write(element, "workDir", workDir);
    JDOMExternalizer.write(element, "repl", runInREPL);
    JDOMExternalizer.write(element, "main", runMainFunction);
    JDOMExternalizer.writeMap(element, envs, null, "env");
    PathMacroManager.getInstance(getProject()).collapsePathsRecursively(element);
  }

  public void setEnvs(@NotNull Map<String, String> envs) {
    this.envs.clear();
    this.envs.putAll(envs);
  }

  @NotNull
  public Map<String, String> getEnvs() {
    return envs;
  }

  protected ModuleBasedConfiguration createInstance() {
    return new ClojureScriptRunConfiguration(factory, getConfigurationModule().getProject(), getName());
  }

  @NotNull
  public SettingsEditor<? extends RunConfiguration> getConfigurationEditor() {
    return new ClojureRunConfigurationEditor();
  }

  private static void configureScriptSystemClassPath(final ClojureConfigUtil.RunConfigurationParameters params, final Module module) throws CantRunException {
    params.setJdk(JavaParameters.getModuleJdk(module));
    params.configureByModule(module, JavaParameters.CLASSES_AND_TESTS);

    ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(module);
    OrderEntry[] entries = moduleRootManager.getOrderEntries();
    Set<VirtualFile> cpVFiles = new LinkedHashSet<VirtualFile>();
    for (OrderEntry orderEntry : entries) {
      // Add module sources to classpath
      if (orderEntry instanceof ModuleSourceOrderEntry) {
        cpVFiles.addAll(Arrays.asList(orderEntry.getFiles(OrderRootType.SOURCES)));
      }
    }

    for (VirtualFile file : cpVFiles) {
      params.getClassPath().add(file.getPath());
    }

    if (!ClojureConfigUtil.isClojureConfigured(module)) {
      params.getClassPath().add(ClojureConfigUtil.CLOJURE_SDK);
      params.setDefaultClojureJarUsed(true);
    }
  }

  private void configureJavaParams(ClojureConfigUtil.RunConfigurationParameters params, Module module) throws CantRunException {

    // Setting up classpath
    configureScriptSystemClassPath(params, module);

    // add user parameters
    params.getVMParametersList().addParametersString(vmParams);

    params.setMainClass(ClojureUtils.CLOJURE_MAIN);
  }

  private void configureScript(ParametersList list) {
    if (runInREPL) list.add("-i");
    list.add(scriptPath);

    if (runInREPL) list.add("-r");
    list.addParametersString(scriptParams);
  }

  private void configureMainFunction(ParametersList list, String namespace) {
    list.add("--main");
    list.add(namespace);
  }

  public Module getModule() {
    return getConfigurationModule().getModule();
  }

  public RunProfileState getState(@NotNull Executor executor, @NotNull ExecutionEnvironment environment) throws ExecutionException {
    final Module module = getModule();
    if (module == null) {
      throw new ExecutionException("Module is not specified");
    }

    final ModuleRootManager rootManager = ModuleRootManager.getInstance(module);
    final Sdk sdk = rootManager.getSdk();
    if (sdk == null || !(sdk.getSdkType() instanceof JavaSdkType)) {
      throw CantRunException.noJdkForModule(getModule());
    }

    final Project project = module.getProject();
    if (!org.jetbrains.plugins.clojure.config.ClojureConfigUtil.isClojureConfigured(module)) {
      Messages.showErrorDialog(project,
          ClojureBundle.message("error.running.configuration.with.error.error.message", getName(),
              ClojureBundle.message("clojure.lib.is.not.attached")),
          ClojureBundle.message("run.error.message.title"));

      ModulesConfigurator.showDialog(project, module.getName(), ClasspathEditor.NAME);
      return null;
    }

    final ClojureConfigUtil.RunConfigurationParameters params =
        new ClojureConfigUtil.RunConfigurationParameters();

    final String namespace;

    if (runMainFunction) {
      final VirtualFile virtualFile = VfsUtil.findFileByIoFile(new File(scriptPath), true);
      if (virtualFile == null) {
        showCannotDetermineNamespaceError();
        return null;
      }

      final PsiFile file = PsiManager.getInstance(getProject()).findFile(virtualFile);
      if (!(file instanceof ClojureFile)) {
        showCannotDetermineNamespaceError();
        return null;
      }

      final String ns = ((ClojureFile) file).getNamespace();
      if (ns == null) {
        showCannotDetermineNamespaceError();
        return null;
      }

      namespace = ns;
    } else {
      namespace = null;
    }

    final JavaCommandLineState state = new JavaCommandLineState(environment) {
      protected JavaParameters createJavaParameters() throws ExecutionException {
        ProgramParametersUtil.configureConfiguration(params, ClojureScriptRunConfiguration.this);

        configureJavaParams(params, module);

        final ParametersList list = params.getProgramParametersList();

        if (runMainFunction) {
          configureMainFunction(list, namespace);
        } else {
          configureScript(list);
        }

        return params;
      }
    };

    final TextConsoleBuilderImpl builder = new TextConsoleBuilderImpl(project) {
      private final ArrayList<Filter> filters = new ArrayList<Filter>();

      @Override
      public ConsoleView getConsole() {
        final ConsoleViewImpl view = new ConsoleViewImpl(project, false);
        for (Filter filter : filters) {
          view.addMessageFilter(filter);
        }
        return view;
      }

      @Override
      public void addFilter(Filter filter) {
        filters.add(filter);
      }
    };

    state.setConsoleBuilder(builder);

    if (params.isDefaultClojureJarUsed()) {
      ClojureConfigUtil.warningDefaultClojureJar(module);
    }
    return state;

  }

  private void showCannotDetermineNamespaceError() {
    Messages.showErrorDialog(getProject(),
        ClojureBundle.message("error.running.configuration.with.error.error.message", getName(),
            ClojureBundle.message("cannot.determine.namespace", scriptPath)),
        ClojureBundle.message("run.error.message.title"));
  }

  public void setScriptPath(String path) {
    this.scriptPath = path;
  }

  public String getScriptPath() {
    return scriptPath;
  }

  public String getVmParams() {
    return vmParams;
  }

  public String getScriptParams() {
    return scriptParams;
  }

  public void setVmParams(String params) {
    vmParams = params;
  }

  public void setRunInREPL(boolean isEnabled) {
    runInREPL = isEnabled;
  }

  public void setScriptParams(String params) {
    scriptParams = params;
  }

  public boolean getRunInREPL() {
    return runInREPL;
  }

  public boolean getRunMainFunction() {
    return runMainFunction;
  }

  public void setRunMainFunction(boolean b) {
    runMainFunction = b;
  }

  public void setPassParentEnvs(boolean passParentEnvs) {
    this.passParentEnv = passParentEnvs;
  }

  public boolean isPassParentEnvs() {
    return passParentEnv;
  }

  public void setProgramParameters(@Nullable String s) {
    LOG.error("Don't add program parameters to Clojure script run configuration. Use Script parameters instead");
  }

  @Nullable
  public String getProgramParameters() {
    return null;
  }

  public void setWorkingDirectory(@Nullable String value) {
    workDir = value;
  }

  public String getWorkingDirectory() {
    return workDir;
  }

}
TOP

Related Classes of org.jetbrains.plugins.clojure.runner.ClojureScriptRunConfiguration

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.