/*
* Copyright 2013-2017 Grzegorz Ligas <ligasgr@gmail.com> and other contributors
* (see the CONTRIBUTORS file).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.intellij.xquery.psi.impl;
import com.intellij.lang.ASTNode;
import com.intellij.navigation.ItemPresentation;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiReference;
import com.intellij.psi.PsiWhiteSpace;
import com.intellij.psi.ResolveState;
import com.intellij.psi.TokenType;
import com.intellij.psi.impl.ResolveScopeManager;
import com.intellij.psi.scope.PsiScopeProcessor;
import com.intellij.psi.search.LocalSearchScope;
import com.intellij.psi.search.SearchScope;
import com.intellij.psi.tree.IElementType;
import com.intellij.psi.util.PsiElementFilter;
import com.intellij.psi.util.PsiTreeUtil;
import org.intellij.xquery.icons.XQueryIcons;
import org.intellij.xquery.psi.XQueryAnnotation;
import org.intellij.xquery.psi.XQueryArrowFunctionReference;
import org.intellij.xquery.psi.XQueryArrowFunctionSpecifier;
import org.intellij.xquery.psi.XQueryAttrLocalName;
import org.intellij.xquery.psi.XQueryAttrNamespace;
import org.intellij.xquery.psi.XQueryElementFactory;
import org.intellij.xquery.psi.XQueryExprSingle;
import org.intellij.xquery.psi.XQueryFile;
import org.intellij.xquery.psi.XQueryForBinding;
import org.intellij.xquery.psi.XQueryFunctionCall;
import org.intellij.xquery.psi.XQueryFunctionDecl;
import org.intellij.xquery.psi.XQueryFunctionInvocation;
import org.intellij.xquery.psi.XQueryFunctionLocalName;
import org.intellij.xquery.psi.XQueryFunctionName;
import org.intellij.xquery.psi.XQueryLetBinding;
import org.intellij.xquery.psi.XQueryMarklogicAnnotation;
import org.intellij.xquery.psi.XQueryModuleDecl;
import org.intellij.xquery.psi.XQueryModuleImport;
import org.intellij.xquery.psi.XQueryModuleImportPath;
import org.intellij.xquery.psi.XQueryNamedElement;
import org.intellij.xquery.psi.XQueryNamedFunctionRef;
import org.intellij.xquery.psi.XQueryNamespaceDecl;
import org.intellij.xquery.psi.XQueryNamespacePrefix;
import org.intellij.xquery.psi.XQueryPrefix;
import org.intellij.xquery.psi.XQueryPsiElement;
import org.intellij.xquery.psi.XQueryQueryBody;
import org.intellij.xquery.psi.XQueryTypes;
import org.intellij.xquery.psi.XQueryVarDecl;
import org.intellij.xquery.psi.XQueryVarLocalName;
import org.intellij.xquery.psi.XQueryVarName;
import org.intellij.xquery.psi.XQueryVarRef;
import org.intellij.xquery.psi.XQueryVersion;
import org.intellij.xquery.psi.XQueryXmlTagName;
import org.intellij.xquery.psi.XQueryXmlTagNamespace;
import org.intellij.xquery.reference.function.XQueryFunctionReference;
import org.intellij.xquery.reference.module.XQueryModuleReference;
import org.intellij.xquery.reference.namespace.XQueryAttrNamespaceReference;
import org.intellij.xquery.reference.namespace.XQueryNamespacePrefixReference;
import org.intellij.xquery.reference.namespace.XQueryXmlTagNamespaceReference;
import org.intellij.xquery.reference.variable.XQueryVariableReference;
import org.intellij.xquery.reference.xml.XQueryXmlTagNameReference;
import org.intellij.xquery.util.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.Icon;
import java.util.Collection;
import static org.intellij.xquery.util.StringUtils.EMPTY;
import static org.intellij.xquery.util.StringUtils.removeQuotOrApos;
/**
* User: ligasgr
* Date: 10/02/13
* Time: 18:59
*/
public class XQueryPsiImplUtil {
private static final int DOLLAR_CHAR_LENGTH = 1;
private static final int SEPARATOR_LENGTH = 1;
public static String getName(XQueryNamespacePrefix element) {
return element.getNameIdentifier().getText();
}
public static PsiElement setName(XQueryNamespacePrefix element, String newName) {
XQueryNamespacePrefix name = element;
if (name != null) {
name.replace(XQueryElementFactory.createModuleDeclarationName(element.getProject(), newName));
}
return element;
}
public static PsiElement getNameIdentifier(XQueryNamespacePrefix element) {
return element;
}
public static PsiReference getReference(XQueryVarRef element) {
int localNameOffset = DOLLAR_CHAR_LENGTH;
if (element.getVarName() != null) {
if (element.getVarName().getPrefix() != null) {
localNameOffset += element.getVarName().getPrefix().getTextLength() + SEPARATOR_LENGTH;
}
return new XQueryVariableReference(element, new TextRange(localNameOffset, element.getTextLength()));
}
return null;
}
public static String getName(XQueryVarName element) {
if (element.getNameIdentifier() != null) {
return element.getNameIdentifier().getText();
} else {
return null;
}
}
public static PsiElement setName(XQueryVarName element, String newName) {
XQueryVarName name = element;
if (name != null) {
XQueryVarLocalName localName = name.getVarLocalName();
if (localName != null) {
XQueryVarName newNameElement = XQueryElementFactory.createVariableReference(element.getProject(),
newName);
localName.replace(newNameElement.getVarLocalName());
}
}
return element;
}
public static PsiElement getNameIdentifier(XQueryVarName element) {
if (element == null) return null;
return element.getVarLocalName();
}
public static int getTextOffset(XQueryVarName element) {
if (element == null) return 0;
PsiElement nameIdentifier = getNameIdentifier(element);
if (nameIdentifier == null) return endOfColon(element);
return nameIdentifier.getTextOffset();
}
private static int endOfColon(XQueryVarName varName) {
if (varName.getPrefix() != null) {
String colon = XQueryTypes.COLON.toString();
int offset = varName.getText().indexOf(colon) + colon.length();
return varName.getNode().getStartOffset() + offset;
}
return 0;
}
public static PsiReference getReference(XQueryModuleImportPath element) {
String filename = stripApostrophes(element.getURILiteral().getText());
if (!StringUtil.isEmptyOrSpaces(filename)) {
return new XQueryModuleReference(element, filename, new TextRange(1,
element.getURILiteral().getTextLength() - 1));
}
return null;
}
public static String stripApostrophes(String text) {
return text.replaceAll("\"", "").replaceAll("'", "");
}
public static PsiReference getReference(XQueryFunctionInvocation element) {
if (element.getFunctionName() == null) return null;
int localNameOffset = 0;
if (element.getFunctionName().getPrefix() != null) {
localNameOffset += element.getFunctionName().getPrefix().getTextLength() + SEPARATOR_LENGTH;
}
return new XQueryFunctionReference(element, new TextRange(localNameOffset,
element.getFunctionName().getTextLength()));
}
public static String getName(XQueryFunctionName element) {
if (element.getNameIdentifier() != null) {
return element.getNameIdentifier().getText();
} else {
return null;
}
}
public static String getPrefixText(XQueryFunctionName element) {
if (element.getPrefix() != null) {
return element.getPrefix().getText();
} else {
return null;
}
}
public static String getLocalNameText(XQueryFunctionName element) {
if (element.getFunctionLocalName() != null) {
return element.getFunctionLocalName().getText();
} else {
return null;
}
}
public static PsiElement setName(XQueryFunctionName element, String newName) {
XQueryFunctionName name = element;
if (name != null) {
XQueryFunctionLocalName localName = name.getFunctionLocalName();
if (localName != null) {
XQueryFunctionName newNameElement = XQueryElementFactory.createFunctionReference(element.getProject()
, "dummy", newName);
localName.replace(newNameElement.getFunctionLocalName());
}
}
return element;
}
public static PsiElement getNameIdentifier(XQueryFunctionName element) {
if (element == null) return null;
return element.getFunctionLocalName();
}
public static int getTextOffset(XQueryFunctionName element) {
if (element == null) return 0;
PsiElement nameIdentifier = getNameIdentifier(element);
if (nameIdentifier == null) return endOfColon(element);
return nameIdentifier.getTextOffset();
}
private static int endOfColon(XQueryFunctionName functionName) {
if (functionName.getPrefix() != null) {
String colon = XQueryTypes.COLON.toString();
int offset = functionName.getText().indexOf(colon) + colon.length();
return functionName.getNode().getStartOffset() + offset;
}
return 0;
}
public static SearchScope getUseScope(XQueryVarName element) {
XQueryFunctionDecl function = PsiTreeUtil.getParentOfType(element, XQueryFunctionDecl.class, true);
if (function != null) {
return new LocalSearchScope(function);
}
XQueryQueryBody queryBody = PsiTreeUtil.getParentOfType(element, XQueryQueryBody.class, true);
if (queryBody != null) {
return new LocalSearchScope(queryBody);
}
return ResolveScopeManager.getElementUseScope(element);
}
public static ItemPresentation getPresentation(final XQueryFunctionDecl element) {
return new ItemPresentation() {
@Nullable
@Override
public String getPresentableText() {
String name = element.getFunctionName() != null ? element.getFunctionName().getText() : "";
String tailText = (element.getParamList() != null ? element.getParamList().getText() : "") + " as ";
String typeText = element.getSequenceType() != null ? element.getSequenceType()
.getText() : "item()*";
return StringUtils.compressWhitespaces(name + tailText + typeText);
}
@Nullable
@Override
public String getLocationString() {
return null;
}
@Nullable
@Override
public Icon getIcon(boolean unused) {
return element.isPublic() ? XQueryIcons.FUNCTION_PUBLIC_ICON : XQueryIcons.FUNCTION_PRIVATE_ICON;
}
};
}
public static ItemPresentation getPresentation(final XQueryVarDecl element) {
return new ItemPresentation() {
@Nullable
@Override
public String getPresentableText() {
String name = element.getVarName() != null ? element.getVarName().getText() : "";
String typeText = "item()*";
if (element.getTypeDeclaration() != null) {
typeText = element.getTypeDeclaration().getText();
}
return StringUtils.compressWhitespaces(name + " as " + typeText);
}
@Nullable
@Override
public String getLocationString() {
return null;
}
@Nullable
@Override
public Icon getIcon(boolean unused) {
return isPublic(element) ? XQueryIcons.VARIABLE_PUBLIC_ICON : XQueryIcons.VARIABLE_PRIVATE_ICON;
}
};
}
public static ItemPresentation getPresentation(final XQueryVarName element) {
if (element.getParent() instanceof XQueryVarDecl) {
return ((XQueryVarDecl) element.getParent()).getPresentation();
}
return null;
}
public static ItemPresentation getPresentation(final XQueryQueryBody element) {
return new ItemPresentation() {
@Nullable
@Override
public String getPresentableText() {
return "Query Body";
}
@Nullable
@Override
public String getLocationString() {
return null;
}
@Nullable
@Override
public Icon getIcon(boolean unused) {
return XQueryIcons.QUERY_BODY;
}
};
}
public static ItemPresentation getPresentation(final XQueryFunctionName element) {
if (element.getParent() instanceof XQueryFunctionDecl) {
return ((XQueryFunctionDecl) element.getParent()).getPresentation();
}
return null;
}
public static int getArity(XQueryArrowFunctionReference functionCall) {
return functionCall.getArgumentList().getArgumentList().size() + 1;
}
public static int getArity(XQueryFunctionCall functionCall) {
return functionCall.getArgumentList().getArgumentList().size();
}
public static int getArity(XQueryNamedFunctionRef functionCall) {
return StringUtil.parseInt(functionCall.getFunctionArity().getText(), 0);
}
public static int getArity(XQueryFunctionDecl functionDeclaration) {
if (functionDeclaration.getParamList() != null)
return functionDeclaration.getParamList().getParamList().size();
else
return 0;
}
public static boolean hasValidFunctionName(XQueryFunctionDecl functionDecl) {
return functionDecl.getFunctionName() != null && functionDecl.getFunctionName().getTextLength() > 0;
}
public static boolean isPublic(XQueryFunctionDecl functionDecl) {
for (XQueryAnnotation annotation : functionDecl.getAnnotationList()) {
if ("private".equals(annotation.getAnnotationName().getText()))
return false;
}
for (XQueryMarklogicAnnotation annotation : functionDecl.getMarklogicAnnotationList()) {
if ("private".equals(annotation.getText()))
return false;
}
return true;
}
public static boolean isPublic(XQueryVarDecl varDecl) {
for (XQueryAnnotation annotation : varDecl.getAnnotationList()) {
if ("private".equals(annotation.getAnnotationName().getText()))
return false;
}
for (XQueryMarklogicAnnotation annotation : varDecl.getMarklogicAnnotationList()) {
if ("private".equals(annotation.getText()))
return false;
}
return true;
}
public static void delete(XQueryAttrLocalName namedElement) {
PsiElement dirAttribute = namedElement.getParent().getParent();
deleteElement(dirAttribute);
}
public static void delete(XQueryVarName element) {
deleteDeclaration(element);
}
public static void delete(XQueryFunctionName element) {
deleteDeclaration(element);
}
public static void delete(XQueryNamespacePrefix element) {
deleteDeclaration(element);
}
private static void deleteDeclaration(XQueryNamedElement namedElement) {
PsiElement declarationElement = namedElement.getParent();
deleteElement(declarationElement);
}
private static void deleteElement(PsiElement element) {
final ASTNode parentNode = element.getParent().getNode();
assert parentNode != null;
ASTNode node = element.getNode();
ASTNode prev = node.getTreePrev();
ASTNode next = node.getTreeNext();
parentNode.removeChild(node);
if (prev == null || prev.getElementType() == TokenType.WHITE_SPACE) {
while (next != null && (next.getElementType() == TokenType.WHITE_SPACE || next.getElementType() ==
XQueryTypes.SEPARATOR)) {
parentNode.removeChild(next);
next = node.getTreeNext();
}
}
}
public static boolean isExternal(XQueryVarDecl variableDeclaration) {
return variableDeclaration.getExternalVarPart() != null;
}
public static String getNamespace(XQueryModuleDecl moduleDecl) {
if (moduleDecl.getURILiteral() != null) {
return removeQuotOrApos(moduleDecl.getURILiteral().getText());
}
return EMPTY;
}
public static String getNamespace(XQueryModuleImport moduleImport) {
if (moduleImport.getModuleImportNamespace() != null) {
return removeQuotOrApos(moduleImport.getModuleImportNamespace().getModuleImportPath().getURILiteral()
.getText());
}
return EMPTY;
}
public static String getNamespace(XQueryNamespaceDecl namespaceDecl) {
if (namespaceDecl.getURILiteral() != null) {
return removeQuotOrApos(namespaceDecl.getURILiteral().getText());
}
return EMPTY;
}
public static PsiReference getReference(XQueryPrefix prefix) {
return new XQueryNamespacePrefixReference(prefix, new TextRange(0, prefix.getTextLength()));
}
public static PsiReference getReference(XQueryXmlTagNamespace prefix) {
return new XQueryXmlTagNamespaceReference(prefix, new TextRange(0, prefix.getTextLength()));
}
public static PsiReference getReference(XQueryAttrNamespace prefix) {
return new XQueryAttrNamespaceReference(prefix, new TextRange(0, prefix.getTextLength()));
}
public static PsiReference getReference(XQueryXmlTagName element) {
int offset = 0;
if (element.getXmlTagNamespace() != null) {
offset += element.getXmlTagNamespace().getTextLength() + SEPARATOR_LENGTH;
}
return new XQueryXmlTagNameReference(element, new TextRange(offset, element.getTextLength()));
}
public static String getName(XQueryPrefix element) {
return element.getNameIdentifier().getText();
}
public static PsiElement setName(XQueryPrefix element, String newName) {
XQueryPrefix name = element;
if (name != null) {
name.replace(XQueryElementFactory.createFunctionReference(element.getProject(), newName, "any").getPrefix());
}
return element;
}
public static String getName(XQueryXmlTagNamespace element) {
return element.getNameIdentifier().getText();
}
public static PsiElement setName(XQueryXmlTagNamespace element, String newName) {
XQueryXmlTagNamespace name = element;
if (name != null) {
name.replace(XQueryElementFactory.createXmlTag(element.getProject(), newName, "any").getXmlTagName().getXmlTagNamespace());
}
return element;
}
public static String getName(XQueryAttrLocalName element) {
return element.getNameIdentifier().getText();
}
public static PsiElement setName(XQueryAttrLocalName element, String newName) {
XQueryAttrLocalName name = element;
if (name != null) {
name.replace(XQueryElementFactory.createAttributeName(element.getProject(), "any", newName).getAttrLocalName());
}
return element;
}
public static String getName(XQueryAttrNamespace element) {
return element.getNameIdentifier().getText();
}
public static PsiElement setName(XQueryAttrNamespace element, String newName) {
XQueryAttrNamespace name = element;
if (name != null) {
name.replace(XQueryElementFactory.createAttributeName(element.getProject(), newName, "any").getAttrNamespace());
}
return element;
}
public static String getName(XQueryXmlTagName element) {
return element.getNameIdentifier().getText();
}
public static PsiElement setName(XQueryXmlTagName element, String newName) {
XQueryXmlTagName name = element;
if (name != null) {
name.getXmlTagLocalName().replace(XQueryElementFactory.createXmlTag(element.getProject(), "any", newName).getXmlTagName().getXmlTagLocalName());
}
return element;
}
public static PsiElement getNameIdentifier(XQueryPrefix element) {
return element;
}
public static PsiElement getNameIdentifier(XQueryXmlTagNamespace element) {
return element;
}
public static PsiElement getNameIdentifier(XQueryAttrLocalName element) {
return element;
}
public static PsiElement getNameIdentifier(XQueryAttrNamespace element) {
return element;
}
public static PsiElement getNameIdentifier(XQueryXmlTagName element) {
if (element == null) return null;
return element.getXmlTagLocalName();
}
public static int getTextOffset(XQueryXmlTagName element) {
if (element == null) return 0;
PsiElement nameIdentifier = getNameIdentifier(element);
if (nameIdentifier == null) return endOfColon(element);
return nameIdentifier.getTextOffset();
}
private static int endOfColon(XQueryXmlTagName tagName) {
if (tagName.getXmlTagNamespace() != null) {
String colon = XQueryTypes.COLON.toString();
int offset = tagName.getText().indexOf(colon) + colon.length();
return tagName.getNode().getStartOffset() + offset;
}
return 0;
}
public static boolean isEquivalentTo(XQueryPrefix element, PsiElement another) {
return isEquivalentPrefix(element, another);
}
public static boolean isEquivalentTo(XQueryXmlTagNamespace element, PsiElement another) {
return isEquivalentPrefix(element, another);
}
public static boolean isEquivalentTo(XQueryAttrNamespace element, PsiElement another) {
return isEquivalentPrefix(element, another);
}
private static boolean isEquivalentPrefix(XQueryPsiElement element, PsiElement another) {
boolean isElementContainingNamespace = another instanceof XQueryPrefix
|| another instanceof XQueryXmlTagNamespace
|| another instanceof XQueryAttrNamespace;
if (!isElementContainingNamespace) {
return false;
}
if (element.getContainingFile() instanceof XQueryFile && another.getContainingFile() instanceof XQueryFile) {
XQueryFile elementFile = (XQueryFile) element.getContainingFile();
XQueryFile anotherFile = (XQueryFile) another.getContainingFile();
String elementNamespace = elementFile.mapFunctionPrefixToNamespace(element.getText());
String anotherNamespace = anotherFile.mapFunctionPrefixToNamespace(another.getText());
return elementFile.equals(anotherFile) && elementNamespace.equals(anotherNamespace);
}
return false;
}
public static PsiElement getTopmostElementWithTheSameOffset(PsiElement element) {
if (element == null) return null;
PsiElement lastElement = element;
int offset = element.getTextOffset();
while (element != null) {
if (offset == element.getTextOffset() && !(element instanceof PsiFile)) {
lastElement = element;
element = element.getParent();
} else {
return lastElement;
}
}
return lastElement;
}
public static PsiElement getNextNonWhiteSpaceElement(PsiElement element) {
if (isNotWhitespace(element)) {
return element;
}
PsiElement nextSibling = element.getNextSibling();
while (nextSibling != null) {
if (isNotWhitespace(nextSibling)) {
return nextSibling;
}
nextSibling = element.getNextSibling();
}
return null;
}
public static PsiElement getPrevNonWhiteSpaceElement(PsiElement element) {
PsiElement previousLeaf = previousLeaf(element);
while (previousLeaf != null && (previousLeaf.getTextLength() == 0 || isWhitespace(previousLeaf))) {
previousLeaf = previousLeaf(previousLeaf);
}
return previousLeaf;
}
public static PsiElement previousLeaf(@NotNull PsiElement current) {
final PsiElement prevSibling = current.getPrevSibling();
if (prevSibling != null) return PsiTreeUtil.lastChild(prevSibling);
final PsiElement parent = current.getParent();
if (parent == null || parent instanceof PsiFile) return null;
PsiElement previousOfParent = previousLeaf(parent);
if (previousOfParent == null) return null;
return PsiTreeUtil.lastChild(previousOfParent);
}
private static boolean isNotWhitespace(PsiElement element) {
return !isWhitespace(element);
}
private static boolean isWhitespace(PsiElement element) {
return element instanceof PsiWhiteSpace;
}
public static PsiElement[] findChildrenOfType(PsiElement startingElement, final IElementType elementType) {
return PsiTreeUtil.collectElements(startingElement, new PsiElementFilter() {
@Override
public boolean isAccepted(PsiElement element) {
return element.getNode() != null && element.getNode().getElementType() == elementType;
}
});
}
public static int getTextOffset(XQueryFunctionDecl functionDecl) {
if (functionDecl.getFunctionName() == null) return endOfFunctionKeyword(functionDecl);
return functionDecl.getFunctionName().getTextOffset();
}
private static int endOfFunctionKeyword(XQueryFunctionDecl functionDecl) {
String keyword = XQueryTypes.K_FUNCTION.toString();
int namePositionOffset = functionDecl.getText().indexOf(keyword) + keyword.length();
return functionDecl.getNode().getStartOffset() + namePositionOffset;
}
public static int getTextOffset(XQueryVarDecl varDecl) {
if (varDecl.getVarName() == null) return endOfDollarOrVariableKeyword(varDecl);
;
return varDecl.getVarName().getTextOffset();
}
private static int endOfDollarOrVariableKeyword(XQueryVarDecl varDecl) {
String dollarSign = XQueryTypes.DOLLAR_SIGN.toString();
int indexOfDollar = varDecl.getText().indexOf(dollarSign);
int dollarOffset = varDecl.getNode().getStartOffset() + indexOfDollar + dollarSign.length();
String keyword = XQueryTypes.K_VARIABLE.toString();
int namePositionOffset = varDecl.getText().indexOf(keyword) + keyword.length();
int variableOffset = varDecl.getNode().getStartOffset() + namePositionOffset;
return indexOfDollar > -1 ? dollarOffset : variableOffset;
}
public static String getVersionString(XQueryVersion version) {
return stripApostrophes(version.getText());
}
public static boolean isEquivalentTo(XQueryFunctionName functionName, PsiElement another) {
if (another instanceof XQueryFunctionName) {
if (functionName.getContainingFile() instanceof XQueryFile && another.getContainingFile() instanceof XQueryFile) {
XQueryFunctionName anotherFunctionName = (XQueryFunctionName) another;
XQueryFile elementFile = (XQueryFile) functionName.getContainingFile();
XQueryFile anotherFile = (XQueryFile) another.getContainingFile();
String elementNamespace = elementFile.mapFunctionPrefixToNamespace(functionName.getPrefixText());
String anotherNamespace = anotherFile.mapFunctionPrefixToNamespace(anotherFunctionName.getPrefixText());
String elementName = functionName.getLocalNameText();
String anotherName = anotherFunctionName.getLocalNameText();
return elementFile.equals(anotherFile)
&& elementNamespace.equals(anotherNamespace)
&& elementName != null && elementName.equals(anotherName);
}
}
return false;
}
public static boolean processDeclarations(XQueryForBinding module, @NotNull PsiScopeProcessor processor, @NotNull ResolveState state, PsiElement lastParent, @NotNull PsiElement place) {
return processChildrenIfPlaceIsNotPartOfSameBinding(module, processor, state, lastParent, place, XQueryForBinding.class, XQueryExprSingle.class);
}
public static boolean processDeclarations(XQueryLetBinding module, @NotNull PsiScopeProcessor processor, @NotNull ResolveState state, PsiElement lastParent, @NotNull PsiElement place) {
return processChildrenIfPlaceIsNotPartOfSameBinding(module, processor, state, lastParent, place, XQueryLetBinding.class, XQueryExprSingle.class);
}
public static XQueryFunctionName getFunctionName(XQueryArrowFunctionReference functionReference) {
if (functionReference.getArrowFunctionSpecifier().getFunctionName() != null) {
return functionReference.getArrowFunctionSpecifier().getFunctionName();
}
return null;
}
private static <T extends XQueryPsiElement, U extends XQueryPsiElement>boolean processChildrenIfPlaceIsNotPartOfSameBinding(T module,
@NotNull PsiScopeProcessor processor, @NotNull ResolveState state, PsiElement lastParent,
@NotNull PsiElement place, Class<T> bindingClass, Class<U>... childClassesToSkip) {
PsiElement commonParent = PsiTreeUtil.findCommonParent(place, module);
T parentBinding = PsiTreeUtil.getParentOfType(place, bindingClass, true);
XQueryExprSingle expressionInModule = PsiTreeUtil.getChildOfType(module, XQueryExprSingle.class);
boolean inSameBinding = commonParent != null && commonParent.equals(module) && parentBinding != null && parentBinding.equals(module);
Collection<T> childBindings = PsiTreeUtil.findChildrenOfType(expressionInModule, bindingClass);
boolean partOfExpressionInBinding = childBindings.contains(parentBinding);
if (inSameBinding || partOfExpressionInBinding) {
return processor.execute(module, state);
} else {
if (!processor.execute(module, state)) {
return false;
} else {
return ResolveUtil.processChildren(module, processor, state, lastParent, place, childClassesToSkip);
}
}
}
}