package com.intellij.javascript.karma.execution;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.Executor;
import com.intellij.execution.RunManager;
import com.intellij.execution.RunnerAndConfigurationSettings;
import com.intellij.execution.configurations.*;
import com.intellij.execution.runners.ExecutionEnvironment;
import com.intellij.javascript.karma.scope.KarmaScopeKind;
import com.intellij.javascript.karma.util.KarmaUtil;
import com.intellij.javascript.nodejs.interpreter.NodeJsInterpreter;
import com.intellij.javascript.nodejs.interpreter.local.NodeJsLocalInterpreter;
import com.intellij.javascript.nodejs.util.NodePackage;
import com.intellij.javascript.testFramework.PreferableRunConfiguration;
import com.intellij.javascript.testFramework.util.JsTestFqn;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.WriteExternalException;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.refactoring.listeners.RefactoringElementListener;
import com.intellij.util.ObjectUtils;
import com.intellij.util.PathUtil;
import com.intellij.util.containers.ContainerUtil;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
public class KarmaRunConfiguration extends LocatableConfigurationBase implements RefactoringListenerProvider,
PreferableRunConfiguration {
private static final Logger LOG = Logger.getInstance(KarmaRunConfiguration.class);
private KarmaRunSettings myRunSettings = new KarmaRunSettings.Builder().build();
protected KarmaRunConfiguration(@NotNull Project project, @NotNull ConfigurationFactory factory, @NotNull String name) {
super(project, factory, name);
}
@NotNull
@Override
public KarmaRunConfigurationEditor getConfigurationEditor() {
return new KarmaRunConfigurationEditor(getProject());
}
@Override
public void readExternal(Element element) throws InvalidDataException {
super.readExternal(element);
myRunSettings = KarmaRunSettingsSerializationUtil.readXml(element);
NodePackage karmaPackage = myRunSettings.getKarmaPackage();
if ("true".equals(element.getAttributeValue("default")) && karmaPackage != null && karmaPackage.isEmptyPath()) {
myRunSettings = myRunSettings.toBuilder().setKarmaPackage(null).build();
}
}
@Override
public void writeExternal(Element element) throws WriteExternalException {
super.writeExternal(element);
KarmaRunSettingsSerializationUtil.writeXml(element, myRunSettings);
}
@NotNull
public NodePackage getKarmaPackage() {
if (isTemplate()) {
NodePackage pkg = myRunSettings.getKarmaPackage();
return pkg != null ? pkg : new NodePackage("");
}
NodePackage karmaPackage = getOrInitKarmaPackage();
if (karmaPackage.isEmptyPath()) {
karmaPackage = KarmaProjectSettings.getKarmaPackage(getProject());
}
return karmaPackage;
}
@NotNull
private NodePackage getOrInitKarmaPackage() {
NodePackage pkg = myRunSettings.getKarmaPackage();
if (pkg == null) {
Project project = getProject();
NodeJsLocalInterpreter interpreter = NodeJsLocalInterpreter.tryCast(myRunSettings.getInterpreterRef().resolve(project));
pkg = NodePackage.findPreferredPackage(project, KarmaUtil.NODE_PACKAGE_NAME, interpreter);
if (!pkg.isEmptyPath() && !KarmaUtil.isPathUnderContentRoots(project, pkg)) {
NodePackage projectKarmaPackage = KarmaProjectSettings.getKarmaPackage(project);
if (projectKarmaPackage.isEmptyPath()) {
KarmaProjectSettings.setKarmaPackage(project, pkg);
}
pkg = new NodePackage("");
}
myRunSettings = myRunSettings.toBuilder().setKarmaPackage(pkg).build();
}
return pkg;
}
private boolean isTemplate() {
return getTemplateRunConfiguration(getProject()) == this;
}
@Nullable
private static KarmaRunConfiguration getTemplateRunConfiguration(@NotNull Project project) {
if (project.isDisposed()) {
return null;
}
RunManager runManager = RunManager.getInstance(project);
RunnerAndConfigurationSettings templateSettings = runManager.getConfigurationTemplate(KarmaConfigurationType.getFactory());
RunConfiguration rc = templateSettings.getConfiguration();
if (rc instanceof KarmaRunConfiguration) {
return (KarmaRunConfiguration)rc;
}
LOG.warn("No Karma template run configuration found: " + rc);
return null;
}
@Nullable
@Override
public RunProfileState getState(@NotNull Executor executor, @NotNull ExecutionEnvironment env) throws ExecutionException {
return new KarmaRunProfileState(getProject(),
this,
env,
getKarmaPackage());
}
@Override
public void checkConfiguration() throws RuntimeConfigurationException {
check(getKarmaPackage());
}
private void check(@NotNull NodePackage karmaPackage) throws RuntimeConfigurationException {
NodeJsInterpreter interpreter = myRunSettings.getInterpreterRef().resolve(getProject());
NodeJsLocalInterpreter.checkForRunConfiguration(interpreter);
karmaPackage.validateForRunConfiguration(KarmaUtil.NODE_PACKAGE_NAME);
String configPath = myRunSettings.getConfigPath();
if (configPath.trim().isEmpty()) {
throw new RuntimeConfigurationError("Please specify config file path");
}
File configFile = new File(configPath);
if (!configFile.exists()) {
throw new RuntimeConfigurationError("Configuration file does not exist");
}
if (!configFile.isFile()) {
throw new RuntimeConfigurationError("Please specify config file path correctly");
}
}
@NotNull
public KarmaRunSettings getRunSettings() {
return myRunSettings;
}
public void setRunSettings(@NotNull KarmaRunSettings runSettings) {
NodePackage newKarmaPackage = runSettings.getKarmaPackage();
NodePackage oldKarmaPackage = myRunSettings.getKarmaPackage();
if (newKarmaPackage == null || newKarmaPackage.equals(oldKarmaPackage)) {
myRunSettings = runSettings;
return;
}
Project project = getProject();
if (!KarmaUtil.isPathUnderContentRoots(project, newKarmaPackage)) {
KarmaProjectSettings.setKarmaPackage(project, newKarmaPackage);
newKarmaPackage = new NodePackage("");
}
if (newKarmaPackage.isEmptyPath() && isTemplate()) {
newKarmaPackage = null;
}
myRunSettings = runSettings.toBuilder().setKarmaPackage(newKarmaPackage).build();
}
public void setConfigFilePath(@NotNull String configFilePath) {
myRunSettings = myRunSettings.toBuilder().setConfigPath(configFilePath).build();
}
@Override
public String suggestedName() {
KarmaRunSettings settings = myRunSettings;
KarmaScopeKind scopeKind = settings.getScopeKind();
if (scopeKind == KarmaScopeKind.ALL) {
return PathUtil.getFileName(settings.getConfigSystemIndependentPath());
}
if (scopeKind == KarmaScopeKind.SUITE || scopeKind == KarmaScopeKind.TEST) {
return JsTestFqn.getPresentableName(settings.getTestNames());
}
return super.suggestedName();
}
@Nullable
@Override
public String getActionName() {
KarmaScopeKind scopeKind = myRunSettings.getScopeKind();
if (scopeKind == KarmaScopeKind.SUITE || scopeKind == KarmaScopeKind.TEST) {
return StringUtil.notNullize(ContainerUtil.getLastItem(myRunSettings.getTestNames()));
}
return super.getActionName();
}
@Nullable
@Override
public RefactoringElementListener getRefactoringElementListener(PsiElement element) {
return KarmaRunConfigurationRefactoringHandler.getRefactoringElementListener(this, element);
}
@Override
public boolean isPreferredOver(@NotNull RunConfiguration otherRc, @NotNull PsiElement sourceElement) {
PsiFile psiFile = ObjectUtils.tryCast(sourceElement, PsiFile.class);
if (psiFile != null) {
VirtualFile virtualFile = psiFile.getVirtualFile();
if (virtualFile != null) {
return KarmaUtil.isKarmaConfigFile(virtualFile.getNameSequence(), true);
}
}
return false;
}
}