| /* |
| * Copyright 2000-2011 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.impl; |
| |
| import com.intellij.codeInsight.completion.CompletionSorter; |
| import com.intellij.codeInsight.lookup.*; |
| import com.intellij.openapi.util.Condition; |
| import com.intellij.util.containers.ContainerUtil; |
| import org.jetbrains.annotations.NotNull; |
| |
| import java.util.ArrayList; |
| import java.util.List; |
| |
| /** |
| * @author peter |
| */ |
| public class CompletionSorterImpl extends CompletionSorter { |
| private final List<ClassifierFactory<LookupElement>> myMembers; |
| private final int myHashCode; |
| |
| CompletionSorterImpl(List<ClassifierFactory<LookupElement>> members) { |
| myMembers = members; |
| myHashCode = myMembers.hashCode(); |
| } |
| |
| public static ClassifierFactory<LookupElement> weighingFactory(final LookupElementWeigher weigher) { |
| final String id = weigher.toString(); |
| return new ClassifierFactory<LookupElement>(id) { |
| @Override |
| public Classifier<LookupElement> createClassifier(Classifier<LookupElement> next) { |
| return new CachingComparingClassifier(next, weigher); |
| } |
| }; |
| } |
| |
| @Override public CompletionSorterImpl weighBefore(@NotNull final String beforeId, LookupElementWeigher... weighers) { |
| if (weighers.length == 0) return this; |
| |
| CompletionSorterImpl result = this; |
| for (LookupElementWeigher weigher : weighers) { |
| result = result.withClassifier(beforeId, true, weighingFactory(weigher)); |
| } |
| return result; |
| } |
| |
| @Override public CompletionSorterImpl weighAfter(@NotNull final String afterId, LookupElementWeigher... weighers) { |
| if (weighers.length == 0) return this; |
| |
| CompletionSorterImpl result = this; |
| for (int i = weighers.length - 1; i >= 0; i--) { |
| LookupElementWeigher weigher = weighers[i]; |
| result = result.withClassifier(afterId, false, weighingFactory(weigher)); |
| } |
| return result; |
| } |
| |
| @Override public CompletionSorterImpl weigh(final LookupElementWeigher weigher) { |
| return withClassifier(weighingFactory(weigher)); |
| } |
| |
| public CompletionSorterImpl withClassifier(ClassifierFactory<LookupElement> classifierFactory) { |
| return enhanced(classifierFactory, myMembers.size()); |
| } |
| |
| public CompletionSorterImpl withClassifier(@NotNull String anchorId, |
| boolean beforeAnchor, ClassifierFactory<LookupElement> classifierFactory) { |
| final int i = idIndex(anchorId); |
| return enhanced(classifierFactory, beforeAnchor ? Math.max(0, i) : i + 1); |
| } |
| |
| private CompletionSorterImpl enhanced(ClassifierFactory<LookupElement> classifierFactory, int index) { |
| final List<ClassifierFactory<LookupElement>> copy = new ArrayList<ClassifierFactory<LookupElement>>(myMembers); |
| copy.add(index, classifierFactory); |
| return new CompletionSorterImpl(copy); |
| } |
| |
| |
| private int idIndex(final String id) { |
| return ContainerUtil.indexOf(myMembers, new Condition<ClassifierFactory<LookupElement>>() { |
| @Override |
| public boolean value(ClassifierFactory<LookupElement> factory) { |
| return id.equals(factory.getId()); |
| } |
| }); |
| } |
| |
| @Override |
| public boolean equals(Object o) { |
| if (this == o) return true; |
| if (!(o instanceof CompletionSorterImpl)) return false; |
| |
| CompletionSorterImpl that = (CompletionSorterImpl)o; |
| |
| if (!myMembers.equals(that.myMembers)) return false; |
| |
| return true; |
| } |
| |
| @Override |
| public int hashCode() { |
| return myHashCode; |
| } |
| |
| private static Classifier<LookupElement> createClassifier(final int index, |
| final List<ClassifierFactory<LookupElement>> components, |
| Classifier<LookupElement> tail) { |
| if (index == components.size()) { |
| return tail; |
| } |
| |
| return components.get(index).createClassifier(createClassifier(index + 1, components, tail)); |
| } |
| |
| public Classifier<LookupElement> buildClassifier(Classifier<LookupElement> tail) { |
| return createClassifier(0, myMembers, tail); |
| } |
| } |