/* * Copyright 2013-2014 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.reference.variable; import com.intellij.openapi.util.Condition; import com.intellij.psi.PsiElementResolveResult; import com.intellij.psi.ResolveResult; import com.intellij.psi.ResolveState; import com.intellij.psi.util.PsiTreeUtil; import org.intellij.xquery.model.XQueryQName; import org.intellij.xquery.psi.*; import org.jetbrains.annotations.NotNull; import java.util.ArrayList; import java.util.Collection; import java.util.List; import static org.intellij.xquery.model.XQueryQNameBuilder.aXQueryQName; /** * User: ligasgr * Date: 14/08/13 * Time: 22:00 */ public class XQueryVariableReferenceResolver { private final String checkedNamespacePrefix; private List<XQueryVarName> matchingVariableNames; private XQueryVarRef myElement; public XQueryVariableReferenceResolver(XQueryVarRef myElement) { this.myElement = myElement; checkedNamespacePrefix = myElement.getVarName().getPrefix() != null ? myElement.getVarName() .getPrefix().getText() : null; } @NotNull public ResolveResult[] getResolutionResults() { XQueryFile file = (XQueryFile) myElement.getContainingFile(); matchingVariableNames = new ArrayList<XQueryVarName>(); addReferencesFromLocalScopes(); if (matchingVariableNames.size() > 0) { return convertToResolveResults(matchingVariableNames); } addVariableDeclarationReferencesFromFile(file, checkedNamespacePrefix); addVariableDeclarationReferencesFromImportedFiles(file); return convertToResolveResults(matchingVariableNames); } private void addReferencesFromLocalScopes() { VariableReferenceScopeProcessor processor = new VariableReferenceScopeProcessor(myElement); PsiTreeUtil.treeWalkUp(processor, myElement, null, ResolveState.initial()); if (processor.getResult() != null) matchingVariableNames.add(processor.getResult()); } private void addVariableDeclarationReferencesFromFile(XQueryFile file, String checkedNamespace) { for (XQueryVarDecl varDecl : file.getVariableDeclarations()) { addVariableAsTargetIfMatches(varDecl, checkedNamespace); } } private void addVariableAsTargetIfMatches(XQueryVarDecl variableDeclaration, String checkedNamespace) { if (variableDeclarationWithValidName(variableDeclaration)) { XQueryQName<XQueryVarName> source = aXQueryQName(myElement.getVarName()) .withPrefix(checkedNamespace) .build(); XQueryQName<XQueryVarName> checkedQName = aXQueryQName(variableDeclaration.getVarName()) .build(); if (source.equals(checkedQName)) { matchingVariableNames.add(checkedQName.getNamedObject()); } } } private void addVariableDeclarationReferencesFromImportedFiles(XQueryFile file) { if (variableHasNamespacePrefix()) { for (XQueryFile importedFile : getFilesFromImportWithMatchingNamespacePrefix(file)) { addVariableDeclarationReferencesFromFile(importedFile, importedFile.getModuleNamespaceName().getText()); } } } private boolean variableHasNamespacePrefix() { return myElement.getVarName().getPrefix() != null; } private Collection<XQueryFile> getFilesFromImportWithMatchingNamespacePrefix(XQueryFile file) { return file.getImportedFilesThatExist(new Condition<XQueryModuleImport>() { @Override public boolean value(XQueryModuleImport moduleImport) { String namespacePrefix = myElement.getVarName().getPrefix().getText(); String prefixFromImport = moduleImport.getNamespacePrefix() != null ? moduleImport.getNamespacePrefix().getText() : null; return namespacePrefix.equals(prefixFromImport); } }); } private ResolveResult[] convertToResolveResults(List<XQueryVarName> resolveResults) { ResolveResult[] convertedResults = new ResolveResult[resolveResults.size()]; for (int i = 0; i < resolveResults.size(); i++) { convertedResults[i] = new PsiElementResolveResult(resolveResults.get(i)); } return convertedResults; } private boolean variableDeclarationWithValidName(XQueryVarDecl varDecl) { return varDecl.getVarName() != null && varDecl.getVarName().getTextLength() > 0; } }