/* * Copyright 2000-2014 JetBrains s.r.o. * * 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 com.intellij.codeInsight.completion; import com.intellij.codeInsight.TailType; import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.codeInsight.lookup.LookupItem; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiReference; import com.intellij.psi.filters.ElementFilter; import com.intellij.util.ReflectionUtil; import com.intellij.util.containers.HashMap; import org.jetbrains.annotations.NonNls; import java.util.*; /** * @author ik */ public class CompletionVariant { protected static final TailType DEFAULT_TAIL_TYPE = TailType.SPACE; private final Set<Scope> myScopeClasses = new HashSet<>(); private ElementFilter myPosition; private final List<CompletionVariantItem> myCompletionsList = new ArrayList<>(); private InsertHandler myInsertHandler = null; private final Map<Object, Object> myItemProperties = new HashMap<>(); public CompletionVariant() { } public CompletionVariant(Class scopeClass, ElementFilter position){ includeScopeClass(scopeClass); myPosition = position; } public CompletionVariant(ElementFilter position){ myPosition = position; } boolean isScopeAcceptable(PsiElement scope){ return isScopeClassAcceptable(scope.getClass()); } boolean isScopeFinal(PsiElement scope){ return isScopeClassFinal(scope.getClass()); } InsertHandler getInsertHandler(){ return myInsertHandler; } public void setInsertHandler(InsertHandler handler){ myInsertHandler = handler; } Map<Object, Object> getItemProperties() { return myItemProperties; } private boolean isScopeClassFinal(Class scopeClass){ for (final Object myScopeClass : myScopeClasses) { Scope scope = (Scope)myScopeClass; if (ReflectionUtil.isAssignable(scope.myClass, scopeClass) && scope.myIsFinalScope) { return true; } } return false; } private boolean isScopeClassAcceptable(Class scopeClass){ boolean ret = false; for (final Object myScopeClass : myScopeClasses) { final Class aClass = ((Scope)myScopeClass).myClass; if (ReflectionUtil.isAssignable(aClass, scopeClass)) { ret = true; break; } } return ret; } public void includeScopeClass(Class<?> aClass){ myScopeClasses.add(new Scope(aClass, false)); } public void includeScopeClass(Class<?> aClass, boolean isFinalScope){ myScopeClasses.add(new Scope(aClass, isFinalScope)); } public void addCompletionFilter(ElementFilter filter, TailType tailType){ addCompletion(filter, tailType); } public void addCompletionFilter(ElementFilter filter){ addCompletionFilter(filter, TailType.NONE); } public void addCompletion(@NonNls String keyword){ addCompletion(keyword, DEFAULT_TAIL_TYPE); } public void addCompletion(@NonNls String keyword, TailType tailType){ addCompletion((Object)keyword, tailType); } private void addCompletion(Object completion, TailType tail){ myCompletionsList.add(new CompletionVariantItem(completion, tail)); } boolean isVariantApplicable(PsiElement position, PsiElement scope){ return isScopeAcceptable(scope) && myPosition.isAcceptable(position, scope); } void addReferenceCompletions(PsiReference reference, PsiElement position, Set<LookupElement> set, final PsiFile file, final CompletionData completionData){ for (final CompletionVariantItem ce : myCompletionsList) { if(ce.myCompletion instanceof ElementFilter){ final ElementFilter filter = (ElementFilter)ce.myCompletion; completionData.completeReference(reference, position, set, ce.myTailType, filter, this); } } } void addKeywords(Set<LookupElement> set, final CompletionData completionData) { for (final CompletionVariantItem ce : myCompletionsList) { completionData.addKeywords(set, this, ce.myCompletion, ce.myTailType); } } boolean hasReferenceFilter(){ for (final CompletionVariantItem item: myCompletionsList) { if (item.myCompletion instanceof ElementFilter) { return true; } } return false; } boolean hasKeywordCompletions(){ for (final CompletionVariantItem item : myCompletionsList) { if (!(item.myCompletion instanceof ElementFilter)) { return true; } } return false; } private static class Scope{ Class myClass; boolean myIsFinalScope; Scope(Class aClass, boolean isFinalScope){ myClass = aClass; myIsFinalScope = isFinalScope; } } private static class CompletionVariantItem{ public Object myCompletion; public TailType myTailType; public CompletionVariantItem(Object completion, TailType tailtype){ myCompletion = completion; myTailType = tailtype; } public String toString(){ return myCompletion.toString(); } } @SuppressWarnings({"HardCodedStringLiteral"}) public String toString(){ return "completion variant at " + myPosition.toString() + " completions: " + myCompletionsList; } public void setCaseInsensitive(boolean caseInsensitive) { myItemProperties.put(LookupItem.CASE_INSENSITIVE, caseInsensitive); } }