package com.jetbrains.lang.dart.ide.runner.base;
import com.intellij.execution.configurations.ConfigurationFactory;
import com.intellij.execution.configurations.LocatableConfigurationBase;
import com.intellij.execution.configurations.RefactoringListenerProvider;
import com.intellij.execution.configurations.RuntimeConfigurationException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.InvalidDataException;
import com.intellij.openapi.util.WriteExternalException;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiFileSystemItem;
import com.intellij.refactoring.listeners.RefactoringElementListener;
import com.intellij.refactoring.listeners.UndoRefactoringElementAdapter;
import com.intellij.util.PathUtil;
import com.intellij.util.xmlb.SkipDefaultValuesSerializationFilters;
import com.intellij.util.xmlb.XmlSerializer;
import com.jetbrains.lang.dart.ide.runner.server.DartCommandLineRunnerParameters;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public abstract class DartRunConfigurationBase extends LocatableConfigurationBase
implements RefactoringListenerProvider, DartRunConfiguration {
protected DartRunConfigurationBase(final Project project, final ConfigurationFactory factory, final String name) {
super(project, factory, name);
}
@NotNull
public abstract DartCommandLineRunnerParameters getRunnerParameters();
public void checkConfiguration() throws RuntimeConfigurationException {
getRunnerParameters().check(getProject());
}
@Override
public void writeExternal(final Element element) throws WriteExternalException {
super.writeExternal(element);
XmlSerializer.serializeInto(getRunnerParameters(), element, new SkipDefaultValuesSerializationFilters());
}
@Override
public void readExternal(final Element element) throws InvalidDataException {
super.readExternal(element);
XmlSerializer.deserializeInto(getRunnerParameters(), element);
}
@Nullable
@Override
public RefactoringElementListener getRefactoringElementListener(final PsiElement element) {
if (!(element instanceof PsiFileSystemItem)) return null;
final String filePath = getRunnerParameters().getFilePath();
final VirtualFile file = filePath == null ? null : ((PsiFileSystemItem)element).getVirtualFile();
if (file == null) return null;
final String affectedPath = file.getPath();
if (element instanceof PsiFile) {
if (filePath.equals(affectedPath)) {
return new RenameRefactoringListener(affectedPath);
}
}
if (element instanceof PsiDirectory) {
if (filePath.startsWith(affectedPath + "/")) {
return new RenameRefactoringListener(affectedPath);
}
}
return null;
}
private class RenameRefactoringListener extends UndoRefactoringElementAdapter {
private @NotNull String myAffectedPath;
private RenameRefactoringListener(final @NotNull String affectedPath) {
myAffectedPath = affectedPath;
}
private String getNewPathAndUpdateAffectedPath(final @NotNull PsiElement newElement) {
final String oldPath = getRunnerParameters().getFilePath();
final VirtualFile newFile = newElement instanceof PsiFileSystemItem ? ((PsiFileSystemItem)newElement).getVirtualFile() : null;
if (newFile != null && oldPath != null && oldPath.startsWith(myAffectedPath)) {
final String newPath = newFile.getPath() + oldPath.substring(myAffectedPath.length());
myAffectedPath = newFile.getPath(); // needed if refactoring will be undone
return newPath;
}
return oldPath;
}
@Override
protected void refactored(@NotNull final PsiElement element, @Nullable final String oldQualifiedName) {
final boolean generatedName = getName().equals(suggestedName());
final String filePath = getRunnerParameters().getFilePath();
final boolean updateWorkingDir = filePath != null &&
PathUtil.getParentPath(filePath).equals(getRunnerParameters().getWorkingDirectory());
final String newPath = getNewPathAndUpdateAffectedPath(element);
getRunnerParameters().setFilePath(newPath);
if (updateWorkingDir) {
getRunnerParameters().setWorkingDirectory(PathUtil.getParentPath(newPath));
}
if (generatedName) {
setGeneratedName();
}
}
}
}