package org.jetbrains.plugins.cucumber;
import com.intellij.codeInsight.template.Template;
import com.intellij.codeInsight.template.TemplateManager;
import com.intellij.codeInsight.template.impl.TemplateManagerImpl;
import com.intellij.codeInsight.template.impl.TemplateState;
import com.intellij.openapi.command.WriteCommandAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.OpenFileDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.roots.ProjectRootManager;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiFile;
import com.intellij.util.ObjectUtils;
import com.intellij.util.StringBuilderSpinAllocator;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.plugins.cucumber.psi.GherkinStep;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
/**
* User: Andrey.Vokin
* Date: 11/28/13
*/
public abstract class AbstractStepDefinitionCreator implements StepDefinitionCreator {
@NotNull
public String getStepDefinitionFilePath(@NotNull final PsiFile psiFile) {
final VirtualFile file = psiFile.getVirtualFile();
assert file != null;
VirtualFile parent = file.getParent();
// if file is direct child of step definitions dir
if (parent != null && CucumberUtil.STEP_DEFINITIONS_DIR_NAME.equals(parent.getName())) {
return file.getName();
}
// in subfolder
final List<String> dirsReversed = new ArrayList<String>();
while (parent != null) {
final String name = parent.getName();
if (CucumberUtil.STEP_DEFINITIONS_DIR_NAME.equals(name)) {
break;
}
dirsReversed.add(name);
parent = parent.getParent();
}
final StringBuilder buf = StringBuilderSpinAllocator.alloc();
try {
for (int i = dirsReversed.size() - 1; i >= 0; i--) {
buf.append(dirsReversed.get(i)).append(File.separatorChar);
}
buf.append(file.getName());
return buf.toString();
}
finally {
StringBuilderSpinAllocator.dispose(buf);
}
}
@NotNull
@Override
public PsiDirectory getDefaultStepDefinitionFolder(@NotNull GherkinStep step) {
PsiFile featureFile = step.getContainingFile();
final PsiDirectory dir = findStepDefinitionDirectory(featureFile);
if (dir == null) {
final PsiDirectory featureParentDir = featureFile.getParent();
assert featureParentDir != null;
final Ref<PsiDirectory> dirRef = new Ref<PsiDirectory>();
new WriteCommandAction.Simple(step.getProject(),
CucumberBundle.message("cucumber.quick.fix.create.step.command.name.add")) {
@Override
protected void run() throws Throwable {
// create steps_definitions directory
dirRef.set(featureParentDir.createSubdirectory(CucumberUtil.STEP_DEFINITIONS_DIR_NAME));
}
}.execute();
return dirRef.get();
}
return dir;
}
@Nullable
private static PsiDirectory findStepDefinitionDirectory(@NotNull final PsiFile featureFile) {
final PsiDirectory psiFeatureDir = featureFile.getContainingDirectory();
assert psiFeatureDir != null;
VirtualFile featureDir = psiFeatureDir.getVirtualFile();
VirtualFile contentRoot = ProjectRootManager.getInstance(featureFile.getProject()).getFileIndex().getContentRootForFile(featureDir);
while (featureDir != null &&
!Comparing.equal(featureDir, contentRoot) &&
featureDir.findChild(CucumberUtil.STEP_DEFINITIONS_DIR_NAME) == null) {
featureDir = featureDir.getParent();
}
if (featureDir != null) {
VirtualFile stepsDir = featureDir.findChild(CucumberUtil.STEP_DEFINITIONS_DIR_NAME);
if (stepsDir != null) {
return featureFile.getManager().findDirectory(stepsDir);
}
}
return null;
}
protected void closeActiveTemplateBuilders(PsiFile file) {
final Project project = file.getProject();
final VirtualFile vFile = ObjectUtils.assertNotNull(file.getVirtualFile());
final OpenFileDescriptor descriptor = new OpenFileDescriptor(project, vFile);
FileEditorManager.getInstance(project).getAllEditors(vFile);
FileEditorManager.getInstance(project).openTextEditor(descriptor, true);
final Editor editor = FileEditorManager.getInstance(project).getSelectedTextEditor();
assert editor != null;
final TemplateManager templateManager = TemplateManager.getInstance(file.getProject());
final TemplateState templateState = TemplateManagerImpl.getTemplateState(editor);
final Template template = templateManager.getActiveTemplate(editor);
if (templateState != null && template != null) {
templateState.gotoEnd(false);
}
}
}