mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
immutable matcher via MatchedLookupElement
This commit is contained in:
+3
-2
@@ -34,8 +34,9 @@ public class BasicToClassNameDelegator extends AbstractBasicToClassNameDelegator
|
||||
|
||||
@Override
|
||||
protected void updateProperties(LookupElement lookupElement) {
|
||||
if (lookupElement instanceof JavaPsiClassReferenceElement) {
|
||||
((JavaPsiClassReferenceElement)lookupElement).setAutoCompletionPolicy(AutoCompletionPolicy.NEVER_AUTOCOMPLETE);
|
||||
JavaPsiClassReferenceElement classElement = lookupElement.as(JavaPsiClassReferenceElement.CLASS_CONDITION_KEY);
|
||||
if (classElement != null) {
|
||||
classElement.setAutoCompletionPolicy(AutoCompletionPolicy.NEVER_AUTOCOMPLETE);
|
||||
}
|
||||
lookupElement.putUserData(XmlCompletionContributor.WORD_COMPLETION_COMPATIBLE, Boolean.TRUE); //todo think of a less dirty interaction
|
||||
}
|
||||
|
||||
+2
@@ -20,6 +20,7 @@ import com.intellij.codeInsight.lookup.DefaultLookupItemRenderer;
|
||||
import com.intellij.codeInsight.lookup.LookupElementPresentation;
|
||||
import com.intellij.codeInsight.lookup.LookupItem;
|
||||
import com.intellij.codeInsight.lookup.impl.JavaElementLookupRenderer;
|
||||
import com.intellij.openapi.util.ClassConditionKey;
|
||||
import com.intellij.openapi.util.Comparing;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
@@ -33,6 +34,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
* @author peter
|
||||
*/
|
||||
public class JavaPsiClassReferenceElement extends LookupItem<Object> {
|
||||
public static final ClassConditionKey<JavaPsiClassReferenceElement> CLASS_CONDITION_KEY = ClassConditionKey.create(JavaPsiClassReferenceElement.class);
|
||||
private final Object myClass;
|
||||
private final String myQualifiedName;
|
||||
|
||||
|
||||
@@ -102,30 +102,6 @@ public abstract class CompletionService {
|
||||
@Nullable
|
||||
public abstract CompletionProcess getCurrentCompletion();
|
||||
|
||||
/**
|
||||
* Checks if a lookup element matches a given prefix matcher. If this element has already been matched successfully during this completion,
|
||||
* returns true. If it was matched successfully during another completion, forget about this and re-match with (possibly) new prefix.
|
||||
* @param element
|
||||
* @param matcher
|
||||
* @return should a lookup element be presented to user based on entered prefix?
|
||||
*/
|
||||
public boolean prefixMatches(@NotNull LookupElement element, @NotNull PrefixMatcher matcher) {
|
||||
final SoftReference<CompletionProcess> data = element.getUserData(INVOLVED_IN_COMPLETION_KEY);
|
||||
final CompletionProcess currentCompletion = getCurrentCompletion();
|
||||
if (currentCompletion != null) {
|
||||
element.putUserData(INVOLVED_IN_COMPLETION_KEY, new SoftReference<CompletionProcess>(currentCompletion));
|
||||
if (data != null) {
|
||||
final CompletionProcess oldCompletion = data.get();
|
||||
if (oldCompletion != null && oldCompletion != currentCompletion) {
|
||||
return element.setPrefixMatcher(matcher);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
element.putUserData(INVOLVED_IN_COMPLETION_KEY, null);
|
||||
}
|
||||
return element.isPrefixMatched() || element.setPrefixMatcher(matcher);
|
||||
}
|
||||
|
||||
/**
|
||||
* The main method that is invoked to collect all the completion variants
|
||||
* @param parameters Parameters specifying current completion environment
|
||||
|
||||
@@ -15,7 +15,6 @@
|
||||
*/
|
||||
package com.intellij.codeInsight.lookup;
|
||||
|
||||
import com.intellij.codeInsight.completion.CompletionService;
|
||||
import com.intellij.codeInsight.completion.InsertHandler;
|
||||
import com.intellij.codeInsight.completion.InsertionContext;
|
||||
import com.intellij.codeInsight.completion.PrefixMatcher;
|
||||
@@ -35,8 +34,8 @@ public abstract class LookupElementDecorator<T extends LookupElement> extends Lo
|
||||
myDelegate.copyUserDataTo(this);
|
||||
final PrefixMatcher matcher = delegate.getPrefixMatcher();
|
||||
if (matcher != PrefixMatcher.FALSE_MATCHER) {
|
||||
final boolean prefixStillMatches = CompletionService.getCompletionService().prefixMatches(this, matcher);
|
||||
assert prefixStillMatches;
|
||||
assert matcher.prefixMatches(this);
|
||||
setPrefixMatcher(matcher);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-1
@@ -19,6 +19,7 @@ package com.intellij.codeInsight.completion;
|
||||
import com.intellij.codeInsight.CodeInsightActionHandler;
|
||||
import com.intellij.codeInsight.CodeInsightSettings;
|
||||
import com.intellij.codeInsight.completion.impl.CompletionServiceImpl;
|
||||
import com.intellij.codeInsight.completion.impl.MatchedLookupElement;
|
||||
import com.intellij.codeInsight.editorActions.CompletionAutoPopupHandler;
|
||||
import com.intellij.codeInsight.lookup.*;
|
||||
import com.intellij.codeInsight.lookup.impl.LookupImpl;
|
||||
@@ -294,7 +295,7 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler {
|
||||
|
||||
Consumer<LookupElement> consumer = new Consumer<LookupElement>() {
|
||||
public void consume(final LookupElement lookupElement) {
|
||||
indicator.addItem(lookupElement);
|
||||
indicator.addItem((MatchedLookupElement)lookupElement);
|
||||
}
|
||||
};
|
||||
data.set(CompletionService.getCompletionService().performCompletion(parameters, consumer));
|
||||
|
||||
+30
-30
@@ -19,6 +19,7 @@ package com.intellij.codeInsight.completion;
|
||||
import com.intellij.codeInsight.CodeInsightSettings;
|
||||
import com.intellij.codeInsight.completion.impl.CompletionServiceImpl;
|
||||
import com.intellij.codeInsight.completion.impl.CompletionSorterImpl;
|
||||
import com.intellij.codeInsight.completion.impl.MatchedLookupElement;
|
||||
import com.intellij.codeInsight.editorActions.CompletionAutoPopupHandler;
|
||||
import com.intellij.codeInsight.hint.EditorHintListener;
|
||||
import com.intellij.codeInsight.hint.HintManager;
|
||||
@@ -190,12 +191,8 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement
|
||||
}
|
||||
}
|
||||
|
||||
public void setItemSorter(LookupElement element, CompletionSorterImpl sorter) {
|
||||
myItemSorters.putIfAbsent(element, sorter);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public CompletionSorterImpl getSorter(LookupElement element) {
|
||||
CompletionSorterImpl getSorter(LookupElement element) {
|
||||
return myItemSorters.get(element);
|
||||
}
|
||||
|
||||
@@ -215,15 +212,16 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement
|
||||
ApplicationManager.getApplication().executeOnPooledThread(new Runnable() {
|
||||
public void run() {
|
||||
if (isOutdated()) return; //tests?
|
||||
final List<CompletionContributor> list = ApplicationManager.getApplication().runReadAction(new Computable<List<CompletionContributor>>() {
|
||||
public List<CompletionContributor> compute() {
|
||||
if (isOutdated()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
final List<CompletionContributor> list =
|
||||
ApplicationManager.getApplication().runReadAction(new Computable<List<CompletionContributor>>() {
|
||||
public List<CompletionContributor> compute() {
|
||||
if (isOutdated()) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
return CompletionContributor.forParameters(myParameters);
|
||||
}
|
||||
});
|
||||
return CompletionContributor.forParameters(myParameters);
|
||||
}
|
||||
});
|
||||
for (final CompletionContributor contributor : list) {
|
||||
if (myLookup.getAdvertisementText() != null) return;
|
||||
if (!myLookup.isCalculating() && !myLookup.isVisible()) return;
|
||||
@@ -243,20 +241,20 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement
|
||||
if (s != null) {
|
||||
myLookup.setAdvertisementText(s);
|
||||
ApplicationManager.getApplication().invokeLater(new Runnable() {
|
||||
public void run() {
|
||||
if (isAutopopupCompletion() && !myLookup.isShown()) {
|
||||
return;
|
||||
}
|
||||
if (!CompletionServiceImpl.isPhase(CompletionPhase.BgCalculation.class, CompletionPhase.ItemsCalculated.class)) {
|
||||
return;
|
||||
}
|
||||
if (CompletionServiceImpl.getCompletionPhase().indicator != CompletionProgressIndicator.this) {
|
||||
return;
|
||||
}
|
||||
public void run() {
|
||||
if (isAutopopupCompletion() && !myLookup.isShown()) {
|
||||
return;
|
||||
}
|
||||
if (!CompletionServiceImpl.isPhase(CompletionPhase.BgCalculation.class, CompletionPhase.ItemsCalculated.class)) {
|
||||
return;
|
||||
}
|
||||
if (CompletionServiceImpl.getCompletionPhase().indicator != CompletionProgressIndicator.this) {
|
||||
return;
|
||||
}
|
||||
|
||||
updateLookup();
|
||||
}
|
||||
}, myQueue.getModalityState());
|
||||
updateLookup();
|
||||
}
|
||||
}, myQueue.getModalityState());
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -293,7 +291,8 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement
|
||||
final CompletionPhase phase = CompletionServiceImpl.getCompletionPhase();
|
||||
if (phase instanceof CompletionPhase.BgCalculation) {
|
||||
((CompletionPhase.BgCalculation)phase).modifiersChanged = true;
|
||||
} else if (phase instanceof CompletionPhase.InsertedSingleItem) {
|
||||
}
|
||||
else if (phase instanceof CompletionPhase.InsertedSingleItem) {
|
||||
CompletionServiceImpl.setCompletionPhase(CompletionPhase.NoCompletion);
|
||||
}
|
||||
}
|
||||
@@ -360,8 +359,7 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement
|
||||
return myOffsetMap.getOffset(CompletionInitializationContext.IDENTIFIER_END_OFFSET);
|
||||
}
|
||||
|
||||
|
||||
public synchronized void addItem(final LookupElement item) {
|
||||
public synchronized void addItem(final MatchedLookupElement item) {
|
||||
if (!isRunning()) return;
|
||||
ProgressManager.checkCanceled();
|
||||
|
||||
@@ -372,7 +370,9 @@ public class CompletionProgressIndicator extends ProgressIndicatorBase implement
|
||||
|
||||
LOG.assertTrue(myParameters.getPosition().isValid());
|
||||
|
||||
myLookup.addItem(item);
|
||||
LookupElement delegate = item.getDelegate();
|
||||
myItemSorters.put(delegate, item.getSorter());
|
||||
myLookup.addItem(delegate);
|
||||
myCount++;
|
||||
if (unitTestMode) return;
|
||||
|
||||
|
||||
+8
-7
@@ -15,6 +15,7 @@
|
||||
*/
|
||||
package com.intellij.codeInsight.completion;
|
||||
|
||||
import com.intellij.codeInsight.completion.impl.MatchedLookupElement;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.codeInsight.template.impl.LiveTemplateLookupElement;
|
||||
import com.intellij.patterns.PatternCondition;
|
||||
@@ -33,27 +34,27 @@ public class RelaxedMatchingContributor extends CompletionContributor {
|
||||
|
||||
@Override
|
||||
public void fillCompletionVariants(CompletionParameters parameters, final CompletionResultSet result) {
|
||||
final Set<LookupElement> elements = new HashSet<LookupElement>();
|
||||
final Set<MatchedLookupElement> elements = new HashSet<MatchedLookupElement>();
|
||||
result.runRemainingContributors(parameters, new Consumer<LookupElement>() {
|
||||
@Override
|
||||
public void consume(LookupElement element) {
|
||||
elements.add(element);
|
||||
elements.add((MatchedLookupElement)element);
|
||||
result.addElement(element);
|
||||
}
|
||||
});
|
||||
|
||||
if (!elements.isEmpty() && parameters.getInvocationCount() == 0) {
|
||||
Set<String> prefixes = new HashSet<String>();
|
||||
for (LookupElement element : elements) {
|
||||
prefixes.add(element.getPrefixMatcher().getPrefix());
|
||||
for (MatchedLookupElement element : elements) {
|
||||
prefixes.add(element.getMatcher().getPrefix());
|
||||
}
|
||||
for (String prefix : prefixes) {
|
||||
result.withPrefixMatcher(prefix)
|
||||
.restartCompletionOnPrefixChange(StandardPatterns.string().with(new PatternCondition<String>("noneMatch") {
|
||||
@Override
|
||||
public boolean accepts(@NotNull String s, ProcessingContext context) {
|
||||
for (LookupElement element : elements) {
|
||||
if (element.getPrefixMatcher().cloneWithPrefix(s).prefixMatches(element)) {
|
||||
for (MatchedLookupElement element : elements) {
|
||||
if (element.getMatcher().cloneWithPrefix(s).prefixMatches(element)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -64,7 +65,7 @@ public class RelaxedMatchingContributor extends CompletionContributor {
|
||||
}
|
||||
|
||||
CompletionParameters relaxed;
|
||||
if (parameters.getInvocationCount() == 0 && (elements.isEmpty() || elements.size() == 1 && elements.iterator().next() instanceof LiveTemplateLookupElement)) {
|
||||
if (parameters.getInvocationCount() == 0 && (elements.isEmpty() || elements.size() == 1 && elements.iterator().next().as(LiveTemplateLookupElement.class) != null)) {
|
||||
relaxed = parameters.withRelaxedMatching();
|
||||
}
|
||||
else if (parameters.getInvocationCount() >= 2) {
|
||||
|
||||
+15
-6
@@ -16,10 +16,7 @@
|
||||
package com.intellij.codeInsight.completion.impl;
|
||||
|
||||
import com.intellij.codeInsight.completion.*;
|
||||
import com.intellij.codeInsight.lookup.Classifier;
|
||||
import com.intellij.codeInsight.lookup.ClassifierFactory;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.codeInsight.lookup.LookupElementWeigher;
|
||||
import com.intellij.codeInsight.lookup.*;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
@@ -133,9 +130,21 @@ public class CompletionServiceImpl extends CompletionService{
|
||||
}
|
||||
|
||||
public void addElement(@NotNull final LookupElement element) {
|
||||
if (myCompletionService.prefixMatches(element, getPrefixMatcher())) {
|
||||
myProcess.setItemSorter(element, mySorter);
|
||||
if (element instanceof MatchedLookupElement) {
|
||||
getConsumer().consume(element);
|
||||
return;
|
||||
}
|
||||
|
||||
MatchedLookupElement matched = element.as(MatchedLookupElement.CLASS_CONDITION_KEY);
|
||||
if (matched != null) {
|
||||
getConsumer().consume(new MatchedLookupElement(element, matched.getMatcher(), matched.getSorter()));
|
||||
return;
|
||||
}
|
||||
|
||||
PrefixMatcher matcher = getPrefixMatcher();
|
||||
if (matcher.prefixMatches(element)) {
|
||||
element.setPrefixMatcher(matcher);
|
||||
getConsumer().consume(new MatchedLookupElement(element, matcher, mySorter));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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.PrefixMatcher;
|
||||
import com.intellij.codeInsight.lookup.LookupElement;
|
||||
import com.intellij.codeInsight.lookup.LookupElementDecorator;
|
||||
import com.intellij.openapi.util.ClassConditionKey;
|
||||
|
||||
/**
|
||||
* @author peter
|
||||
*/
|
||||
public class MatchedLookupElement extends LookupElementDecorator<LookupElement> {
|
||||
public static final ClassConditionKey<MatchedLookupElement> CLASS_CONDITION_KEY = ClassConditionKey.create(MatchedLookupElement.class);
|
||||
private final PrefixMatcher myMatcher;
|
||||
private final CompletionSorterImpl mySorter;
|
||||
|
||||
MatchedLookupElement(LookupElement delegate, PrefixMatcher matcher, CompletionSorterImpl sorter) {
|
||||
super(delegate);
|
||||
myMatcher = matcher;
|
||||
mySorter = sorter;
|
||||
}
|
||||
|
||||
public PrefixMatcher getMatcher() {
|
||||
return myMatcher;
|
||||
}
|
||||
|
||||
public CompletionSorterImpl getSorter() {
|
||||
return mySorter;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user