package ee.edio.garmin.psi.impl; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.lang.ASTNode; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.Condition; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.UnfairTextRange; import com.intellij.psi.*; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.IncorrectOperationException; import com.intellij.util.containers.ContainerUtil; import ee.edio.garmin.MonkeyUtil; import ee.edio.garmin.psi.MonkeyId; import ee.edio.garmin.psi.MonkeyReference; import ee.edio.garmin.util.MonkeyElementGenerator; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.ArrayList; import java.util.List; public class MonkeyReferenceImpl extends MonkeyExpressionImpl implements MonkeyReference, PsiPolyVariantReference { public MonkeyReferenceImpl(ASTNode node) { super(node); } @Override public PsiElement getElement() { return this; } @Override public PsiReference getReference() { return this; } @Override public TextRange getRangeInElement() { final TextRange textRange = getTextRange(); //MonkeyReference[] monkeyReferences = PsiTreeUtil.getChildrenOfType(this, MonkeyReference.class); final MonkeyReference[] monkeyReferences = findReferences(); if (monkeyReferences != null && monkeyReferences.length > 0) { TextRange lastReferenceRange = monkeyReferences[monkeyReferences.length - 1].getTextRange(); return new UnfairTextRange( lastReferenceRange.getStartOffset() - textRange.getStartOffset(), lastReferenceRange.getEndOffset() - textRange.getEndOffset() ); } return new UnfairTextRange(0, textRange.getEndOffset() - textRange.getStartOffset()); } @NotNull @Override public String getCanonicalText() { return getText(); } @Override public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException { PsiElement element = this; if (getText().indexOf('.') != -1) { // libPrefix.name final PsiElement lastChild = getLastChild(); element = lastChild == null ? this : lastChild; } final MonkeyId identifier = PsiTreeUtil.getChildOfType(element, MonkeyId.class); final MonkeyId identifierNew = MonkeyElementGenerator.createIdentifierFromText(getProject(), newElementName); if (identifier != null && identifierNew != null) { element.getNode().replaceChild(identifier.getNode(), identifierNew.getNode()); } return this; } @Override public PsiElement bindToElement(@NotNull PsiElement element) throws IncorrectOperationException { return this; } private MonkeyReference[] findReferences() { return PsiTreeUtil.getChildrenOfType(this.getParent(), MonkeyReference.class); } @Override public boolean isReferenceTo(PsiElement element) { final MonkeyReference[] references = findReferences(); final boolean chain = references != null && references.length == 2; if (chain) { return false; } return true; //final PsiElement target = resolve(); /* if (element.getParent() instanceof MonkeyClass && target != null && MonkeyComponentType.typeOf(target.getParent()) == MonkeyComponentType.CONSTRUCTOR) { return true; }*/ //return target == element; } @Override public boolean isSoft() { return false; } @Override public PsiElement resolve() { ResolveResult[] resolveResults = multiResolve(false); return resolveResults.length == 1 ? resolveResults[0].getElement() : null; /* final ResolveResult[] resolveResults = multiResolve(true); return resolveResults.length == 0 || resolveResults.length > 1 || !resolveResults[0].isValidResult() ? null : resolveResults[0].getElement();*/ } @NotNull @Override public ResolveResult[] multiResolve(boolean incompleteCode) { Project project = getProject(); final List<? extends PsiElement> properties = MonkeyUtil.findReferences(project, this); List<ResolveResult> results = new ArrayList<>(); for (PsiElement property : properties) { results.add(new PsiElementResolveResult(property)); } return results.toArray(new ResolveResult[results.size()]); /* final List<? extends PsiElement> elements = new ArrayList<>(); *//*final List<? extends PsiElement> elements = ResolveCache.getInstance(getProject()) .resolveWithCaching(this, MonkeyResolver.INSTANCE, true, incompleteCode);*//* return toCandidateInfoArray(elements);*/ } private static ResolveResult[] toCandidateInfoArray(@Nullable List<? extends PsiElement> elements) { if (elements == null) { return ResolveResult.EMPTY_ARRAY; } elements = ContainerUtil.filter(elements, new Condition<PsiElement>() { @Override public boolean value(PsiElement element) { return element != null; } }); final ResolveResult[] result = new ResolveResult[elements.size()]; for (int i = 0, size = elements.size(); i < size; i++) { result[i] = new PsiElementResolveResult(elements.get(i)); } return result; } @NotNull @Override public Object[] getVariants() { return LookupElement.EMPTY_ARRAY; } }