package org.jetbrains.plugins.cucumber.steps.reference; import com.intellij.openapi.extensions.Extensions; import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiPolyVariantReference; import com.intellij.psi.ResolveResult; import com.intellij.util.ArrayUtil; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.plugins.cucumber.CucumberJvmExtensionPoint; import org.jetbrains.plugins.cucumber.psi.impl.GherkinStepImpl; import org.jetbrains.plugins.cucumber.steps.AbstractStepDefinition; import org.jetbrains.plugins.cucumber.steps.CucumberStepsIndex; import java.util.ArrayList; import java.util.Collection; import java.util.List; /** * @author yole */ public class CucumberStepReference implements PsiPolyVariantReference { private final PsiElement myStep; private final TextRange myRange; public CucumberStepReference(PsiElement step, TextRange range) { myStep = step; myRange = range; } public PsiElement getElement() { return myStep; } public TextRange getRangeInElement() { return myRange; } public PsiElement resolve() { final ResolveResult[] result = multiResolve(true); return result.length == 1 ? result[0].getElement() : null; } @NotNull public String getCanonicalText() { return myStep.getText(); } public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException { return myStep; } public PsiElement bindToElement(@NotNull PsiElement element) throws IncorrectOperationException { return myStep; } public boolean isReferenceTo(PsiElement element) { ResolveResult[] resolvedResults = multiResolve(false); for (ResolveResult rr : resolvedResults) { if (getElement().getManager().areElementsEquivalent(rr.getElement(), element)) { return true; } } return false; } @NotNull public Object[] getVariants() { return ArrayUtil.EMPTY_OBJECT_ARRAY; } public boolean isSoft() { return false; } @NotNull @Override public ResolveResult[] multiResolve(boolean incompleteCode) { final List<ResolveResult> result = new ArrayList<>(); final List<PsiElement> resolvedElements = new ArrayList<>(); final CucumberJvmExtensionPoint[] extensionList = Extensions.getExtensions(CucumberJvmExtensionPoint.EP_NAME); for (CucumberJvmExtensionPoint e : extensionList) { final List<PsiElement> extensionResult = e.resolveStep(myStep); for (final PsiElement element : extensionResult) { if (element != null && !resolvedElements.contains(element)) { resolvedElements.add(element); result.add(new ResolveResult() { @Override public PsiElement getElement() { return element; } @Override public boolean isValidResult() { return true; } }); } } } return result.toArray(new ResolveResult[result.size()]); } /** * @return first definition (if any) or null if no definition found * @see #resolveToDefinitions() */ @Nullable public AbstractStepDefinition resolveToDefinition() { final Collection<AbstractStepDefinition> definitions = resolveToDefinitions(); return (definitions.isEmpty() ? null : definitions.iterator().next()); } /** * @return step definitions * @see #resolveToDefinition() */ @NotNull public Collection<AbstractStepDefinition> resolveToDefinitions() { final CucumberStepsIndex index = CucumberStepsIndex.getInstance(myStep.getProject()); return index.findStepDefinitions(myStep.getContainingFile(), ((GherkinStepImpl)myStep)); } }