package com.jetbrains.lang.dart.ide.runner;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.ExecutionResult;
import com.intellij.execution.configurations.RunProfile;
import com.intellij.execution.configurations.RunProfileState;
import com.intellij.execution.configurations.RuntimeConfigurationError;
import com.intellij.execution.executors.DefaultDebugExecutor;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.execution.runners.GenericProgramRunner;
import com.intellij.execution.ui.RunContentDescriptor;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.fileEditor.FileDocumentManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.xdebugger.XDebugProcess;
import com.intellij.xdebugger.XDebugProcessStarter;
import com.intellij.xdebugger.XDebugSession;
import com.intellij.xdebugger.XDebuggerManager;
import com.jetbrains.lang.dart.analyzer.DartAnalysisServerService;
import com.jetbrains.lang.dart.ide.runner.base.DartRunConfigurationBase;
import com.jetbrains.lang.dart.ide.runner.server.DartCommandLineRunConfiguration;
import com.jetbrains.lang.dart.ide.runner.server.DartCommandLineRunningState;
import com.jetbrains.lang.dart.ide.runner.server.DartRemoteDebugConfiguration;
import com.jetbrains.lang.dart.ide.runner.server.vmService.DartVmServiceDebugProcess;
import com.jetbrains.lang.dart.ide.runner.test.DartTestRunConfiguration;
import com.jetbrains.lang.dart.sdk.DartSdk;
import com.jetbrains.lang.dart.util.DartUrlResolver;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class DartRunner extends GenericProgramRunner {
private static final Logger LOG = Logger.getInstance(DartRunner.class.getName());
@NotNull
@Override
public String getRunnerId() {
return "DartRunner";
}
@Override
public boolean canRun(final @NotNull String executorId, final @NotNull RunProfile profile) {
return DefaultDebugExecutor.EXECUTOR_ID.equals(executorId) &&
(profile instanceof DartCommandLineRunConfiguration ||
profile instanceof DartTestRunConfiguration ||
profile instanceof DartRemoteDebugConfiguration);
}
@Override
protected RunContentDescriptor doExecute(@NotNull RunProfileState state, @NotNull ExecutionEnvironment env) throws ExecutionException {
final String executorId = env.getExecutor().getId();
if (!DefaultDebugExecutor.EXECUTOR_ID.equals(executorId)) {
LOG.error("Unexpected executor id: " + executorId);
return null;
}
try {
final String dasExecutionContextId;
final RunProfile runConfig = env.getRunProfile();
if (runConfig instanceof DartRunConfigurationBase &&
DartAnalysisServerService.getInstance(env.getProject()).serverReadyForRequest(env.getProject())) {
final String path = ((DartRunConfigurationBase)runConfig).getRunnerParameters().getFilePath();
assert path != null; // already checked
dasExecutionContextId = DartAnalysisServerService.getInstance(env.getProject()).execution_createContext(path);
}
else {
dasExecutionContextId = null; // remote debug or can't start DAS
}
return doExecuteDartDebug(state, env, dasExecutionContextId);
}
catch (RuntimeConfigurationError e) {
throw new ExecutionException(e);
}
}
protected int getTimeout() {
return 5000; // Allow 5 seconds to connect to the observatory.
}
private RunContentDescriptor doExecuteDartDebug(final @NotNull RunProfileState state,
final @NotNull ExecutionEnvironment env,
final @Nullable String dasExecutionContextId) throws RuntimeConfigurationError,
ExecutionException {
final DartSdk sdk = DartSdk.getDartSdk(env.getProject());
assert (sdk != null); // already checked
final RunProfile runConfiguration = env.getRunProfile();
final VirtualFile contextFileOrDir;
VirtualFile currentWorkingDirectory;
final ExecutionResult executionResult;
final String debuggingHost;
final int observatoryPort;
if (runConfiguration instanceof DartRunConfigurationBase) {
contextFileOrDir = ((DartRunConfigurationBase)runConfiguration).getRunnerParameters().getDartFileOrDirectory();
final String cwd =
((DartRunConfigurationBase)runConfiguration).getRunnerParameters().computeProcessWorkingDirectory(env.getProject());
currentWorkingDirectory = LocalFileSystem.getInstance().findFileByPath((cwd));
executionResult = state.execute(env.getExecutor(), this);
if (executionResult == null) {
return null;
}
debuggingHost = null;
observatoryPort = ((DartCommandLineRunningState)state).getObservatoryPort();
}
else if (runConfiguration instanceof DartRemoteDebugConfiguration) {
final String path = ((DartRemoteDebugConfiguration)runConfiguration).getParameters().getDartProjectPath();
contextFileOrDir = LocalFileSystem.getInstance().findFileByPath(path);
if (contextFileOrDir == null) {
throw new RuntimeConfigurationError("Folder not found: " + FileUtil.toSystemDependentName(path));
}
currentWorkingDirectory = contextFileOrDir;
executionResult = null;
debuggingHost = ((DartRemoteDebugConfiguration)runConfiguration).getParameters().getHost();
observatoryPort = ((DartRemoteDebugConfiguration)runConfiguration).getParameters().getPort();
}
else {
LOG.error("Unexpected run configuration: " + runConfiguration.getClass().getName());
return null;
}
FileDocumentManager.getInstance().saveAllDocuments();
final XDebuggerManager debuggerManager = XDebuggerManager.getInstance(env.getProject());
final XDebugSession debugSession = debuggerManager.startSession(env, new XDebugProcessStarter() {
@Override
@NotNull
public XDebugProcess start(@NotNull final XDebugSession session) {
final DartUrlResolver dartUrlResolver = getDartUrlResolver(env.getProject(), contextFileOrDir);
return new DartVmServiceDebugProcess(session,
StringUtil.notNullize(debuggingHost, "localhost"),
observatoryPort,
executionResult,
dartUrlResolver,
dasExecutionContextId,
runConfiguration instanceof DartRemoteDebugConfiguration,
getTimeout(),
currentWorkingDirectory);
}
});
return debugSession.getRunContentDescriptor();
}
protected DartUrlResolver getDartUrlResolver(@NotNull final Project project, @NotNull final VirtualFile contextFileOrDir) {
return DartUrlResolver.getInstance(project, contextFileOrDir);
}
}