/* * 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.completion.variable; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupElementBuilder; import com.intellij.icons.AllIcons; import com.intellij.psi.PsiElement; import com.intellij.psi.ResolveState; import com.intellij.psi.util.PsiTreeUtil; import org.intellij.xquery.icons.XQueryIcons; import org.intellij.xquery.model.XQueryQName; import org.intellij.xquery.psi.XQueryFile; import org.intellij.xquery.psi.XQueryModuleImport; import org.intellij.xquery.psi.XQueryParam; import org.intellij.xquery.psi.XQueryVarDecl; import org.intellij.xquery.psi.XQueryVarName; import org.intellij.xquery.psi.impl.XQueryPsiImplUtil; import javax.swing.*; import java.util.ArrayList; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Set; import static org.intellij.xquery.completion.XQueryCompletionContributor.EXTERNAL_VARIABLES_PRIORITY; import static org.intellij.xquery.completion.XQueryCompletionContributor.VARIABLES_PRIORITY; import static org.intellij.xquery.completion.XQueryCompletionContributor.prioritized; import static org.intellij.xquery.model.XQueryQNameBuilder.aXQueryQName; import static org.intellij.xquery.psi.XQueryUtil.getReferencesToExistingFilesInImport; /** * User: ligasgr * Date: 14/08/13 * Time: 22:28 */ public class VariableCollector { private PsiElement sourceOfReference; private Set<XQueryQName<XQueryVarName>> collectedNames; private LinkedList<LookupElement> proposedReferences; public VariableCollector(PsiElement sourceOfReference) { this.sourceOfReference = sourceOfReference; } public List<LookupElement> getProposedLookUpItems() { XQueryFile file = (XQueryFile) sourceOfReference.getContainingFile(); collectedNames = new HashSet<XQueryQName<XQueryVarName>>(); proposedReferences = new LinkedList<LookupElement>(); addProposedReferencesFromLocalScopes(); addProposedReferencesFromFile(file); addProposedReferencesFromModuleImports(file); return proposedReferences; } private void addProposedReferencesFromLocalScopes() { VariableVariantsScopeProcessor processor = new VariableVariantsScopeProcessor(); PsiTreeUtil.treeWalkUp(processor, sourceOfReference, null, ResolveState.initial()); List<XQueryQName<XQueryVarName>> references = processor.getProposedReferences(); proposedReferences.addAll(convertToLookupElements(references, VARIABLES_PRIORITY)); collectedNames.addAll(references); } private void addProposedReferencesFromFile(XQueryFile file) { for (final XQueryVarDecl varDecl : file.getVariableDeclarations()) { if (variableNameExists(varDecl)) { XQueryQName<XQueryVarName> qName = aXQueryQName(varDecl.getVarName()).build(); addProposedReferenceIfNotAlreadyAdded(qName, VARIABLES_PRIORITY); } } } private boolean variableNameExists(XQueryVarDecl variableDeclaration) { return variableDeclaration.getVarName() != null && variableDeclaration.getVarName().getTextLength() > 0; } private void addProposedReferenceIfNotAlreadyAdded(XQueryQName<XQueryVarName> qName, int priority) { if (! collectedNames.contains(qName)) { collectedNames.add(qName); proposedReferences.add(convertToLookupElement(qName, priority)); } } private void addProposedReferencesFromModuleImports(XQueryFile file) { for (XQueryModuleImport moduleImport : file.getModuleImports()) { if (moduleImport.getNamespacePrefix() != null) { String targetPrefix = moduleImport.getNamespacePrefix().getName(); addProposedReferencesFromImport(targetPrefix, moduleImport); } } } private void addProposedReferencesFromImport(String targetPrefix, XQueryModuleImport moduleImport) { for (XQueryFile file : getReferencesToExistingFilesInImport(moduleImport)) { addProposedReferencesFromImportedFile(targetPrefix, file); } } private void addProposedReferencesFromImportedFile(String targetPrefix, XQueryFile file) { for (final XQueryVarDecl variableDeclaration : file.getVariableDeclarations()) { if (variableNameExists(variableDeclaration) && XQueryPsiImplUtil.isPublic(variableDeclaration)) { XQueryQName<XQueryVarName> qName = aXQueryQName(variableDeclaration.getVarName()).withPrefix (targetPrefix) .build(); addProposedReferenceIfNotAlreadyAdded(qName, EXTERNAL_VARIABLES_PRIORITY); } } } private List<LookupElement> convertToLookupElements(List<XQueryQName<XQueryVarName>> proposedReferences, int priority) { List<LookupElement> lookupElements = new ArrayList<LookupElement>(proposedReferences.size()); for (int i = 0; i < proposedReferences.size(); i++) { lookupElements.add(convertToLookupElement(proposedReferences.get(i), priority)); } return lookupElements; } private LookupElement convertToLookupElement(XQueryQName<XQueryVarName> qName, int priority) { XQueryVarName variableName = qName.getNamedObject(); return prioritized(createLookupElement(variableName, qName.getTextRepresentation()), priority); } private LookupElement createLookupElement(XQueryVarName psiElement, String key) { Icon icon = XQueryIcons.VARIABLE_ICON; String typeText = "item()*"; if (psiElement.getParent() instanceof XQueryParam) { icon = AllIcons.Nodes.Parameter; XQueryParam param = (XQueryParam) psiElement.getParent(); if (param.getTypeDeclaration() != null) { typeText = param.getTypeDeclaration().getSequenceType().getText(); } } if (psiElement.getParent() instanceof XQueryVarDecl) { icon = AllIcons.Nodes.Field; XQueryVarDecl varDecl = (XQueryVarDecl) psiElement.getParent(); if (varDecl.getTypeDeclaration() != null) { typeText = varDecl.getTypeDeclaration().getSequenceType().getText(); } } return LookupElementBuilder.create(psiElement, key) .withIcon(icon) .withTypeText(typeText) .withInsertHandler(new VariableInsertHandler()) .withLookupString(psiElement.getVarLocalName().getText()) ; } }