diff --git a/platform/analysis-impl/resources/META-INF/AnalysisImpl.xml b/platform/analysis-impl/resources/META-INF/AnalysisImpl.xml
index 93d3d5b91e08..0f93f587b8f6 100644
--- a/platform/analysis-impl/resources/META-INF/AnalysisImpl.xml
+++ b/platform/analysis-impl/resources/META-INF/AnalysisImpl.xml
@@ -17,6 +17,8 @@
+
) {
+ myApiCompletionProcess = parameters.process as CompletionProcessEx
+ try {
+ super.performCompletion(parameters, consumer)
+ }
+ finally {
+ myApiCompletionProcess = null
+ }
+ }
+
+ override fun createResultSet(parameters: CompletionParameters,
+ consumer: Consumer,
+ contributor: CompletionContributor,
+ matcher: PrefixMatcher): CompletionResultSet {
+ return BaseCompletionResultSet(consumer, matcher, contributor, parameters, defaultSorter(parameters, matcher), null)
+ }
+
+ override fun suggestPrefix(parameters: CompletionParameters): String {
+ val position = parameters.position
+ val offset = parameters.offset
+ val range = position.textRange
+ assert(range.containsOffset(offset)) { "$position; $offset not in $range" }
+ @Suppress("DEPRECATION")
+ return CompletionData.findPrefixStatic(position, offset)
+ }
+
+ override fun createMatcher(prefix: String, typoTolerant: Boolean): PrefixMatcher = createMatcher(prefix, true, typoTolerant)
+
+ override fun getCurrentCompletion(): CompletionProcess? = myApiCompletionProcess
+
+ override fun defaultSorter(parameters: CompletionParameters?, matcher: PrefixMatcher?): CompletionSorterImpl {
+ val location = CompletionLocation(parameters)
+
+ var sorter = emptySorter()
+ sorter = addWeighersBefore(sorter)
+ //sorter = sorter.withClassifier(CompletionSorterImpl.weighingFactory(LiveTemplateWeigher()))
+ sorter = sorter.withClassifier(CompletionSorterImpl.weighingFactory(PreferStartMatching()))
+
+ for (weigher in WeighingService.getWeighers(RELEVANCE_KEY)) {
+ val id = weigher.toString()
+ sorter = when (id) {
+ "prefix" -> {
+ sorter.withClassifier(CompletionSorterImpl.weighingFactory(RealPrefixMatchingWeigher()))
+ }
+ "stats" -> {
+ processStatsWeigher(sorter, weigher, location)
+ }
+ else -> {
+ sorter.weigh(object : LookupElementWeigher(id, true, false) {
+ override fun weigh(element: LookupElement): Comparable<*>? {
+ return weigher.weigh(element, location)
+ }
+ })
+ }
+ }
+ }
+
+ return sorter.withClassifier("priority", true, object : ClassifierFactory("liftShorter") {
+ override fun createClassifier(next: Classifier): Classifier {
+ return LiftShorterItemsClassifier("liftShorter", next, LiftingCondition(), false)
+ }
+ })
+ }
+
+ protected open fun addWeighersBefore(sorter: CompletionSorterImpl): CompletionSorterImpl = sorter
+
+ protected open fun processStatsWeigher(sorter: CompletionSorterImpl,
+ weigher: Weigher,
+ location: CompletionLocation): CompletionSorterImpl = sorter
+
+ override fun emptySorter(): CompletionSorterImpl = CompletionSorterImpl(listOf())
+
+ protected open class BaseCompletionResultSet(consumer: Consumer,
+ matcher: PrefixMatcher,
+ contributor: CompletionContributor,
+ @JvmField protected val myParameters: CompletionParameters,
+ @JvmField protected val mySorter: CompletionSorterImpl,
+ @JvmField protected val myOriginal: BaseCompletionResultSet?) :
+ CompletionResultSet(matcher, consumer, contributor) {
+ override fun addElement(element: LookupElement) {
+ ProgressManager.checkCanceled()
+ if (!element.isValid) {
+ LOG.error("Invalid lookup element: " + element + " of " + element.javaClass +
+ " in " + myParameters.originalFile + " of " + myParameters.originalFile.javaClass)
+ return
+ }
+
+ val matched = CompletionResult.wrap(element, prefixMatcher, mySorter)
+ matched?.let { passResult(it) }
+ }
+
+ override fun withPrefixMatcher(matcher: PrefixMatcher): CompletionResultSet =
+ if (matcher == prefixMatcher) this
+ else BaseCompletionResultSet(consumer, matcher, myContributor, myParameters, mySorter, this)
+
+ override fun withPrefixMatcher(prefix: String): CompletionResultSet = withPrefixMatcher(prefixMatcher.cloneWithPrefix(prefix))
+
+ override fun stopHere() {
+ if (LOG.isTraceEnabled) {
+ LOG.trace("Completion stopped\n" + DebugUtil.currentStackTrace())
+ }
+ super.stopHere()
+ myOriginal?.stopHere()
+ }
+
+ override fun withRelevanceSorter(sorter: CompletionSorter): CompletionResultSet =
+ BaseCompletionResultSet(consumer, prefixMatcher, myContributor, myParameters, sorter as CompletionSorterImpl, this)
+
+ override fun addLookupAdvertisement(text: String) {
+ (getCompletionService().currentCompletion as CompletionProcessEx?)?.addAdvertisement(text, null)
+ }
+
+ override fun caseInsensitive(): CompletionResultSet {
+ val matcher = prefixMatcher
+ val typoTolerant = matcher is CamelHumpMatcher && matcher.isTypoTolerant
+ return withPrefixMatcher(createMatcher(matcher.prefix, false, typoTolerant))
+ }
+
+ override fun restartCompletionOnPrefixChange(prefixCondition: ElementPattern?) {
+ }
+
+ override fun restartCompletionWhenNothingMatches() {
+ }
+ }
+
+ companion object {
+ private val LOG = logger()
+
+ private fun createMatcher(prefix: String, caseSensitive: Boolean, typoTolerant: Boolean): CamelHumpMatcher {
+ return CamelHumpMatcher(prefix, caseSensitive, typoTolerant)
+ }
+ }
+}
\ No newline at end of file
diff --git a/platform/analysis-impl/src/com/intellij/codeInsight/completion/impl/CamelHumpMatcher.java b/platform/analysis-impl/src/com/intellij/codeInsight/completion/impl/CamelHumpMatcher.java
index 8cc0281f8914..206599f5e95a 100644
--- a/platform/analysis-impl/src/com/intellij/codeInsight/completion/impl/CamelHumpMatcher.java
+++ b/platform/analysis-impl/src/com/intellij/codeInsight/completion/impl/CamelHumpMatcher.java
@@ -65,7 +65,8 @@ public class CamelHumpMatcher extends PrefixMatcher {
return false;
}
- boolean isTypoTolerant() {
+ @ApiStatus.Internal
+ public boolean isTypoTolerant() {
return myTypoTolerant;
}
diff --git a/platform/analysis-impl/src/com/intellij/codeInsight/completion/impl/CompletionSorterImpl.java b/platform/analysis-impl/src/com/intellij/codeInsight/completion/impl/CompletionSorterImpl.java
index 8a87de201f09..bfabb9cd4e4d 100644
--- a/platform/analysis-impl/src/com/intellij/codeInsight/completion/impl/CompletionSorterImpl.java
+++ b/platform/analysis-impl/src/com/intellij/codeInsight/completion/impl/CompletionSorterImpl.java
@@ -1,23 +1,10 @@
-/*
- * 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.
- */
+// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.codeInsight.completion.impl;
import com.intellij.codeInsight.completion.CompletionSorter;
import com.intellij.codeInsight.lookup.*;
import com.intellij.util.containers.ContainerUtil;
+import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import java.util.ArrayList;
@@ -30,7 +17,8 @@ public class CompletionSorterImpl extends CompletionSorter {
private final List extends ClassifierFactory> myMembers;
private final int myHashCode;
- CompletionSorterImpl(List extends ClassifierFactory> members) {
+ @ApiStatus.Internal
+ public CompletionSorterImpl(List extends ClassifierFactory> members) {
myMembers = members;
myHashCode = myMembers.hashCode();
}
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CompletionServiceImpl.java b/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CompletionServiceImpl.java
index de82d9cc305c..881c72a3ceb3 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CompletionServiceImpl.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/completion/impl/CompletionServiceImpl.java
@@ -5,38 +5,29 @@ 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.openapi.application.ApplicationManager;
import com.intellij.openapi.diagnostic.Logger;
-import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.project.ProjectManagerListener;
import com.intellij.openapi.util.Disposer;
-import com.intellij.openapi.util.TextRange;
import com.intellij.patterns.ElementPattern;
-import com.intellij.psi.PsiElement;
import com.intellij.psi.Weigher;
-import com.intellij.psi.WeighingService;
-import com.intellij.psi.impl.DebugUtil;
import com.intellij.util.Consumer;
import com.intellij.util.ExceptionUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
-import java.util.ArrayList;
-
/**
* @author peter
*/
-public final class CompletionServiceImpl extends CompletionService {
+public final class CompletionServiceImpl extends BaseCompletionService {
private static final Logger LOG = Logger.getInstance(CompletionServiceImpl.class);
private static volatile CompletionPhase ourPhase = CompletionPhase.NoCompletion;
private static Throwable ourPhaseTrace;
- @Nullable private CompletionProcess myApiCompletionProcess;
-
public CompletionServiceImpl() {
+ super();
ApplicationManager.getApplication().getMessageBus().connect().subscribe(ProjectManager.TOPIC, new ProjectManagerListener() {
@Override
public void projectClosing(@NotNull Project project) {
@@ -44,27 +35,17 @@ public final class CompletionServiceImpl extends CompletionService {
if (indicator != null && indicator.getProject() == project) {
indicator.closeAndFinish(true);
setCompletionPhase(CompletionPhase.NoCompletion);
- } else if (indicator == null) {
+ }
+ else if (indicator == null) {
setCompletionPhase(CompletionPhase.NoCompletion);
}
}
});
}
- @Override
- public void performCompletion(final CompletionParameters parameters, final Consumer super CompletionResult> consumer) {
- myApiCompletionProcess = parameters.getProcess();
- try {
- super.performCompletion(parameters, consumer);
- }
- finally {
- myApiCompletionProcess = null;
- }
- }
-
@SuppressWarnings({"MethodOverridesStaticMethodOfSuperclass"})
public static CompletionServiceImpl getCompletionService() {
- return (CompletionServiceImpl) CompletionService.getCompletionService();
+ return (CompletionServiceImpl)CompletionService.getCompletionService();
}
@Override
@@ -77,29 +58,10 @@ public final class CompletionServiceImpl extends CompletionService {
}
@Override
- protected String suggestPrefix(CompletionParameters parameters) {
- final PsiElement position = parameters.getPosition();
- final int offset = parameters.getOffset();
- TextRange range = position.getTextRange();
- assert range.containsOffset(offset) : position + "; " + offset + " not in " + range;
- //noinspection deprecation
- return CompletionData.findPrefixStatic(position, offset);
- }
-
- @Override
- @NotNull
- protected PrefixMatcher createMatcher(String prefix, boolean typoTolerant) {
- return createMatcher(prefix, true, typoTolerant);
- }
-
- @NotNull
- private static CamelHumpMatcher createMatcher(String prefix, boolean caseSensitive, boolean typoTolerant) {
- return new CamelHumpMatcher(prefix, caseSensitive, typoTolerant);
- }
-
- @Override
- protected CompletionResultSet createResultSet(CompletionParameters parameters, Consumer super CompletionResult> consumer,
- @NotNull CompletionContributor contributor, PrefixMatcher matcher) {
+ protected CompletionResultSet createResultSet(@NotNull CompletionParameters parameters,
+ @NotNull Consumer super CompletionResult> consumer,
+ @NotNull CompletionContributor contributor,
+ @NotNull PrefixMatcher matcher) {
return new CompletionResultSetImpl(consumer, matcher, contributor, parameters, defaultSorter(parameters, matcher), null);
}
@@ -117,19 +79,11 @@ public final class CompletionServiceImpl extends CompletionService {
return null;
}
- private static class CompletionResultSetImpl extends CompletionResultSet {
- private final CompletionParameters myParameters;
- private final CompletionSorterImpl mySorter;
- @Nullable
- private final CompletionResultSetImpl myOriginal;
-
+ private static class CompletionResultSetImpl extends BaseCompletionResultSet {
CompletionResultSetImpl(Consumer super CompletionResult> consumer, PrefixMatcher prefixMatcher,
CompletionContributor contributor, CompletionParameters parameters,
@NotNull CompletionSorterImpl sorter, @Nullable CompletionResultSetImpl original) {
- super(prefixMatcher, consumer, contributor);
- myParameters = parameters;
- mySorter = sorter;
- myOriginal = original;
+ super(consumer, prefixMatcher, contributor, parameters, sorter, original);
}
@Override
@@ -137,52 +91,20 @@ public final class CompletionServiceImpl extends CompletionService {
CompletionThreadingBase.withBatchUpdate(() -> super.addAllElements(elements), myParameters.getProcess());
}
- @Override
- public void addElement(@NotNull final LookupElement element) {
- ProgressManager.checkCanceled();
- if (!element.isValid()) {
- LOG.error("Invalid lookup element: " + element + " of " + element.getClass() +
- " in " + myParameters.getOriginalFile() + " of " + myParameters.getOriginalFile().getClass());
- return;
- }
-
- CompletionResult matched = CompletionResult.wrap(element, getPrefixMatcher(), mySorter);
- if (matched != null) {
- passResult(matched);
- }
- }
-
@Override
@NotNull
public CompletionResultSet withPrefixMatcher(@NotNull final PrefixMatcher matcher) {
if (matcher.equals(getPrefixMatcher())) {
return this;
}
-
+
return new CompletionResultSetImpl(getConsumer(), matcher, myContributor, myParameters, mySorter, this);
}
- @Override
- public void stopHere() {
- if (LOG.isTraceEnabled()) {
- LOG.trace("Completion stopped\n" + DebugUtil.currentStackTrace());
- }
- super.stopHere();
- if (myOriginal != null) {
- myOriginal.stopHere();
- }
- }
-
- @Override
- @NotNull
- public CompletionResultSet withPrefixMatcher(@NotNull final String prefix) {
- return withPrefixMatcher(getPrefixMatcher().cloneWithPrefix(prefix));
- }
-
@NotNull
@Override
public CompletionResultSet withRelevanceSorter(@NotNull CompletionSorter sorter) {
- return new CompletionResultSetImpl(getConsumer(), getPrefixMatcher(), myContributor, myParameters, (CompletionSorterImpl) sorter,
+ return new CompletionResultSetImpl(getConsumer(), getPrefixMatcher(), myContributor, myParameters, (CompletionSorterImpl)sorter,
this);
}
@@ -191,19 +113,12 @@ public final class CompletionServiceImpl extends CompletionService {
getCompletionService().setAdvertisementText(text);
}
- @NotNull
- @Override
- public CompletionResultSet caseInsensitive() {
- PrefixMatcher matcher = getPrefixMatcher();
- boolean typoTolerant = matcher instanceof CamelHumpMatcher && ((CamelHumpMatcher)matcher).isTypoTolerant();
- return withPrefixMatcher(createMatcher(matcher.getPrefix(), false, typoTolerant));
- }
-
@Override
public void restartCompletionOnPrefixChange(ElementPattern prefixCondition) {
CompletionProcess process = myParameters.getProcess();
if (process instanceof CompletionProgressIndicator) {
- ((CompletionProgressIndicator)process).addWatchedPrefix(myParameters.getOffset() - getPrefixMatcher().getPrefix().length(), prefixCondition);
+ ((CompletionProgressIndicator)process)
+ .addWatchedPrefix(myParameters.getOffset() - getPrefixMatcher().getPrefix().length(), prefixCondition);
}
}
@@ -239,12 +154,14 @@ public final class CompletionServiceImpl extends CompletionService {
CompletionPhase oldPhase = getCompletionPhase();
CompletionProgressIndicator oldIndicator = oldPhase.indicator;
if (oldIndicator != null && !(phase instanceof CompletionPhase.BgCalculation)) {
- LOG.assertTrue(!oldIndicator.isRunning() || oldIndicator.isCanceled(), "don't change phase during running completion: oldPhase=" + oldPhase);
+ LOG.assertTrue(!oldIndicator.isRunning() || oldIndicator.isCanceled(),
+ "don't change phase during running completion: oldPhase=" + oldPhase);
}
boolean wasCompletionRunning = isRunningPhase(oldPhase);
boolean isCompletionRunning = isRunningPhase(phase);
if (isCompletionRunning != wasCompletionRunning) {
- ApplicationManager.getApplication().getMessageBus().syncPublisher(CompletionPhaseListener.TOPIC).completionPhaseChanged(isCompletionRunning);
+ ApplicationManager.getApplication().getMessageBus().syncPublisher(CompletionPhaseListener.TOPIC)
+ .completionPhaseChanged(isCompletionRunning);
}
Disposer.dispose(oldPhase);
@@ -262,46 +179,24 @@ public final class CompletionServiceImpl extends CompletionService {
return ourPhase;
}
+ @NotNull
@Override
- public CompletionSorterImpl defaultSorter(CompletionParameters parameters, final PrefixMatcher matcher) {
- final CompletionLocation location = new CompletionLocation(parameters);
+ protected CompletionSorterImpl addWeighersBefore(@NotNull CompletionSorterImpl sorter) {
+ CompletionSorterImpl processed = super.addWeighersBefore(sorter);
+ return processed.withClassifier(CompletionSorterImpl.weighingFactory(new LiveTemplateWeigher()));
+ }
- CompletionSorterImpl sorter = emptySorter();
- sorter = sorter.withClassifier(CompletionSorterImpl.weighingFactory(new LiveTemplateWeigher()));
- sorter = sorter.withClassifier(CompletionSorterImpl.weighingFactory(new PreferStartMatching()));
-
- for (final Weigher weigher : WeighingService.getWeighers(CompletionService.RELEVANCE_KEY)) {
- final String id = weigher.toString();
- if ("prefix".equals(id)) {
- sorter = sorter.withClassifier(CompletionSorterImpl.weighingFactory(new RealPrefixMatchingWeigher()));
- } else if ("stats".equals(id)) {
- sorter = sorter.withClassifier(new ClassifierFactory("stats") {
- @Override
- public Classifier createClassifier(Classifier next) {
- return new StatisticsWeigher.LookupStatisticsWeigher(location, next);
- }
- });
- } else {
- sorter = sorter.weigh(new LookupElementWeigher(id, true, false) {
- @Override
- public Comparable weigh(@NotNull LookupElement element) {
- //noinspection unchecked
- return weigher.weigh(element, location);
- }
- });
- }
- }
-
- return sorter.withClassifier("priority", true, new ClassifierFactory("liftShorter") {
+ @NotNull
+ @Override
+ protected CompletionSorterImpl processStatsWeigher(@NotNull CompletionSorterImpl sorter,
+ @NotNull Weigher