package org.dlangplugin.run; import com.intellij.execution.ExecutionException; import com.intellij.execution.ExecutionResult; import com.intellij.execution.Executor; import com.intellij.execution.configurations.CommandLineState; import com.intellij.execution.configurations.CommandLineTokenizer; import com.intellij.execution.configurations.GeneralCommandLine; import com.intellij.execution.filters.TextConsoleBuilder; import com.intellij.execution.filters.TextConsoleBuilderImpl; import com.intellij.execution.process.OSProcessHandler; import com.intellij.execution.process.ProcessHandler; import com.intellij.execution.runners.ExecutionEnvironment; import com.intellij.execution.runners.ProgramRunner; import com.intellij.notification.Notification; import com.intellij.notification.NotificationType; import com.intellij.notification.Notifications; import com.intellij.openapi.module.Module; import com.intellij.openapi.projectRoots.Sdk; import com.intellij.openapi.roots.CompilerModuleExtension; import com.intellij.openapi.roots.ModuleRootManager; import com.intellij.openapi.util.SystemInfo; import com.intellij.openapi.util.text.StringUtil; import com.intellij.openapi.vfs.VfsUtilCore; import com.intellij.openapi.vfs.VirtualFile; import org.dlangplugin.run.exception.ModuleNotFoundException; import org.dlangplugin.run.exception.NoValidDLangSdkFound; import org.dlangplugin.sdk.DLangSdkType; import org.jetbrains.annotations.NotNull; import java.io.File; import java.util.LinkedList; import java.util.List; public class DLangRunAppState extends CommandLineState { private DLangRunAppConfiguration config; private Executor executor; protected DLangRunAppState(@NotNull ExecutionEnvironment environment, @NotNull DLangRunAppConfiguration config) { super(environment); this.config = config; } @NotNull @Override public ExecutionResult execute(@NotNull Executor executor, @NotNull ProgramRunner runner) throws ExecutionException { TextConsoleBuilder consoleBuilder = new TextConsoleBuilderImpl(config.getProject()); setConsoleBuilder(consoleBuilder); this.executor = executor; return super.execute(executor, runner); } @NotNull @Override protected ProcessHandler startProcess() throws ExecutionException { try { GeneralCommandLine appCommandLine = getExecutableCommandLine(config); return new OSProcessHandler(appCommandLine.createProcess(), appCommandLine.getCommandLineString()); } catch (NoValidDLangSdkFound e) { throw new ExecutionException("No valid DMD SDK found!"); } catch (ModuleNotFoundException e) { throw new ExecutionException("Run configuration has no module selected."); } catch (ExecutionException e) { String message = e.getMessage(); boolean isEmpty = message.equals("Executable is not specified"); boolean notCorrect = message.startsWith("Cannot run program"); if (isEmpty || notCorrect) { Notifications.Bus.notify( new Notification("D App run configuration", "D App settings", "D application executable path is " + (isEmpty ? "empty" : "not specified correctly") + "<br/><a href='configure'>Configure</a> output folder", NotificationType.ERROR), config.getProject()); } throw e; } } /* Build command line to start compiled executable **/ private GeneralCommandLine getExecutableCommandLine(DLangRunAppConfiguration config) throws ModuleNotFoundException, NoValidDLangSdkFound { Module module = config.getConfigurationModule().getModule(); if(module == null) { throw new ModuleNotFoundException(); } ModuleRootManager moduleRootManager = ModuleRootManager.getInstance(module); Sdk sdk = moduleRootManager.getSdk(); if(sdk==null || !(sdk.getSdkType() instanceof DLangSdkType) ){ throw new NoValidDLangSdkFound(); } VirtualFile sourcesRoot = getSourceRoot(module); GeneralCommandLine commandLine = new GeneralCommandLine(); commandLine.setExePath(getOutputFilePath(module)); if( StringUtil.isEmptyOrSpaces( config.getWorkDir()) ) { commandLine.withWorkDirectory(config.getWorkDir()); } else { commandLine.withWorkDirectory(sourcesRoot.getPath()); } if( StringUtil.isEmptyOrSpaces(config.getAdditionalParams()) ) { commandLine.addParameters(splitArguments(config.getAdditionalParams())); } return commandLine; } private String[] splitArguments(String arguments) { List<String> argsLst = new LinkedList<String>(); CommandLineTokenizer tokenizer = new CommandLineTokenizer(arguments); while(tokenizer.hasMoreTokens()) { argsLst.add(tokenizer.nextToken()); } if(argsLst.size()>0) { return (String[]) argsLst.toArray(); } else { return new String[0]; } } private VirtualFile getSourceRoot(Module module) { if (module != null) { VirtualFile[] sourcesRoots = ModuleRootManager.getInstance(module).getSourceRoots(); if (sourcesRoots.length >= 1) { return sourcesRoots[0]; } } return null; } @NotNull private String getOutputFilePath(Module module) { String filename = module.getName(); if(SystemInfo.isWindows) { filename += ".exe"; } String outputDirUrl = getOutputDir(module); File outputFile = new File(VfsUtilCore.urlToPath(outputDirUrl), filename); return outputFile.getPath(); } private String getOutputDir(Module module) { return ModuleRootManager.getInstance(module).getModuleExtension(CompilerModuleExtension.class).getCompilerOutputUrl(); } }