package com.jetbrains.lang.dart.ide.runner.server;
import com.intellij.execution.configurations.RuntimeConfigurationError;
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.util.xmlb.annotations.MapAnnotation;
import com.jetbrains.lang.dart.DartBundle;
import com.jetbrains.lang.dart.DartFileType;
import com.jetbrains.lang.dart.sdk.DartConfigurable;
import com.jetbrains.lang.dart.sdk.DartSdk;
import com.jetbrains.lang.dart.util.PubspecYamlUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.LinkedHashMap;
import java.util.Map;
public class DartCommandLineRunnerParameters implements Cloneable {
private @Nullable String myFilePath = null;
private @Nullable String myVMOptions = null;
private boolean myCheckedMode = true;
private @Nullable String myArguments = null;
private @Nullable String myWorkingDirectory = null;
private @NotNull Map<String, String> myEnvs = new LinkedHashMap<>();
private boolean myIncludeParentEnvs = true;
/**
* Get the Dart project directory for the given file (or folder) by looking for the first parent that contains a pubspec.
* In case none can be found, the file's parent (or the folder itself) is used instead.
*/
public static String suggestDartWorkingDir(@NotNull final Project project, @NotNull final VirtualFile dartFileOrFolder) {
final VirtualFile pubspec = PubspecYamlUtil.findPubspecYamlFile(project, dartFileOrFolder);
if (pubspec != null) {
final VirtualFile parent = pubspec.getParent();
if (parent != null) {
return parent.getPath();
}
}
if (dartFileOrFolder.isDirectory()) {
return dartFileOrFolder.getPath();
}
else {
return dartFileOrFolder.getParent().getPath();
}
}
@Nullable
public String getFilePath() {
return myFilePath;
}
public void setFilePath(final @Nullable String filePath) {
myFilePath = filePath;
}
@Nullable
public String getVMOptions() {
return myVMOptions;
}
public void setVMOptions(final @Nullable String vmOptions) {
myVMOptions = vmOptions;
}
public boolean isCheckedMode() {
return myCheckedMode;
}
public void setCheckedMode(final boolean checkedMode) {
myCheckedMode = checkedMode;
}
@Nullable
public String getArguments() {
return myArguments;
}
public void setArguments(final @Nullable String arguments) {
myArguments = arguments;
}
@Nullable
public String getWorkingDirectory() {
return myWorkingDirectory;
}
public void setWorkingDirectory(final @Nullable String workingDirectory) {
myWorkingDirectory = workingDirectory;
}
@NotNull
@MapAnnotation(surroundWithTag = false, surroundKeyWithTag = false, surroundValueWithTag = false)
public Map<String, String> getEnvs() {
return myEnvs;
}
public void setEnvs(@SuppressWarnings("NullableProblems") final Map<String, String> envs) {
if (envs != null) { // null comes from old projects or if storage corrupted
myEnvs = envs;
}
}
public boolean isIncludeParentEnvs() {
return myIncludeParentEnvs;
}
public void setIncludeParentEnvs(final boolean includeParentEnvs) {
myIncludeParentEnvs = includeParentEnvs;
}
@NotNull
public String computeProcessWorkingDirectory(@NotNull final Project project) {
if (!StringUtil.isEmptyOrSpaces(myWorkingDirectory)) return myWorkingDirectory;
try {
return suggestDartWorkingDir(project, getDartFileOrDirectory());
}
catch (RuntimeConfigurationError error) {
return "";
}
}
@NotNull
public VirtualFile getDartFile() throws RuntimeConfigurationError {
final VirtualFile dartFile = getDartFileOrDirectory();
if (dartFile.isDirectory()) {
assert myFilePath != null;
throw new RuntimeConfigurationError(DartBundle.message("dart.file.not.found", FileUtil.toSystemDependentName(myFilePath)));
}
return dartFile;
}
@NotNull
public VirtualFile getDartFileOrDirectory() throws RuntimeConfigurationError {
if (StringUtil.isEmptyOrSpaces(myFilePath)) {
throw new RuntimeConfigurationError(DartBundle.message("path.to.dart.file.not.set"));
}
final VirtualFile dartFile = LocalFileSystem.getInstance().findFileByPath(myFilePath);
if (dartFile == null) {
throw new RuntimeConfigurationError(DartBundle.message("dart.file.not.found", FileUtil.toSystemDependentName(myFilePath)));
}
if (dartFile.getFileType() != DartFileType.INSTANCE && !dartFile.isDirectory()) {
throw new RuntimeConfigurationError(DartBundle.message("not.a.dart.file.or.directory", FileUtil.toSystemDependentName(myFilePath)));
}
return dartFile;
}
public void check(final @NotNull Project project) throws RuntimeConfigurationError {
// check sdk
final DartSdk sdk = DartSdk.getDartSdk(project);
if (sdk == null) {
throw new RuntimeConfigurationError(DartBundle.message("dart.sdk.is.not.configured"),
() -> DartConfigurable.openDartSettings(project));
}
// check main dart file
getDartFileOrDirectory();
// check working directory
if (!StringUtil.isEmptyOrSpaces(myWorkingDirectory)) {
final VirtualFile workDir = LocalFileSystem.getInstance().findFileByPath(myWorkingDirectory);
if (workDir == null || !workDir.isDirectory()) {
throw new RuntimeConfigurationError(
DartBundle.message("work.dir.does.not.exist", FileUtil.toSystemDependentName(myWorkingDirectory)));
}
}
}
@Override
protected DartCommandLineRunnerParameters clone() {
try {
final DartCommandLineRunnerParameters clone = (DartCommandLineRunnerParameters)super.clone();
clone.myEnvs = new LinkedHashMap<>();
clone.myEnvs.putAll(myEnvs);
return clone;
}
catch (CloneNotSupportedException e) {
throw new RuntimeException(e);
}
}
}