cleanup, don't cache matchers

This commit is contained in:
peter
2012-04-27 20:18:08 +02:00
parent d2dbbe50b8
commit f9de08d149
10 changed files with 25 additions and 171 deletions
@@ -241,7 +241,7 @@ public class JavaCompletionContributor extends CompletionContributor {
public static void addAllClasses(CompletionParameters parameters,
final CompletionResultSet result,
final InheritorsHolder inheritors) {
if (!isClassNamePossible(parameters.getPosition()) || !mayStartClassName(result, parameters.isRelaxedMatching())) return;
if (!isClassNamePossible(parameters.getPosition()) || !mayStartClassName(result)) return;
if (mayShowAllClasses(parameters)) {
JavaClassNameCompletionContributor.addAllClasses(parameters, parameters.getInvocationCount() <= 2, result.getPrefixMatcher(), new Consumer<LookupElement>() {
@@ -385,14 +385,13 @@ public class JavaCompletionContributor extends CompletionContributor {
return Registry.is("show.all.classes.on.first.completion") || parameters.getInvocationCount() >= 2;
}
public static boolean mayStartClassName(CompletionResultSet result, final boolean relaxedMatching) {
public static boolean mayStartClassName(CompletionResultSet result) {
String prefix = result.getPrefixMatcher().getPrefix();
if (StringUtil.isEmpty(prefix)) {
return false;
}
return StringUtil.isCapitalized(prefix) ||
relaxedMatching ||
CodeInsightSettings.getInstance().COMPLETION_CASE_SENSITIVE == CodeInsightSettings.NONE;
}
@@ -63,7 +63,7 @@ public class JavaNoVariantsDelegator extends CompletionContributor {
suggestCollectionUtilities(parameters, result, position);
if (parameters.getInvocationCount() <= 1 &&
JavaCompletionContributor.mayStartClassName(result, false) &&
JavaCompletionContributor.mayStartClassName(result) &&
JavaCompletionContributor.isClassNamePossible(position)) {
suggestNonImportedClasses(parameters, result);
return;
@@ -28,7 +28,7 @@ public class XmlBasicToClassNameDelegator extends AbstractBasicToClassNameDelega
@Override
protected boolean isClassNameCompletionSupported(CompletionResultSet result, PsiFile file, PsiElement position) {
if (!JavaCompletionContributor.mayStartClassName(result, false)) return false;
if (!JavaCompletionContributor.mayStartClassName(result)) return false;
return file.getLanguage().isKindOf(StdLanguages.XML);
}
@@ -24,17 +24,16 @@ import com.intellij.psi.PsiFile;
/**
* @author peter
*/
public class CompletionParameters {
public final class CompletionParameters {
private final PsiElement myPosition;
private final PsiFile myOriginalFile;
private final CompletionType myCompletionType;
private final Lookup myLookup;
private final int myOffset;
private final int myInvocationCount;
private final boolean myRelaxedMatching;
protected CompletionParameters(@NotNull final PsiElement position, @NotNull final PsiFile originalFile,
final CompletionType completionType, int offset, final int invocationCount, Lookup lookup, final boolean relaxedMatching) {
CompletionParameters(@NotNull final PsiElement position, @NotNull final PsiFile originalFile,
final CompletionType completionType, int offset, final int invocationCount, Lookup lookup) {
assert offset >= position.getTextRange().getStartOffset();
myPosition = position;
assert position.isValid();
@@ -42,20 +41,15 @@ public class CompletionParameters {
myCompletionType = completionType;
myOffset = offset;
myInvocationCount = invocationCount;
myRelaxedMatching = relaxedMatching;
myLookup = lookup;
}
public CompletionParameters withType(CompletionType type) {
return new CompletionParameters(myPosition, myOriginalFile, type, myOffset, myInvocationCount, myLookup, myRelaxedMatching);
return new CompletionParameters(myPosition, myOriginalFile, type, myOffset, myInvocationCount, myLookup);
}
public CompletionParameters withInvocationCount(int newCount) {
return new CompletionParameters(myPosition, myOriginalFile, myCompletionType, myOffset, newCount, myLookup, myRelaxedMatching);
}
public CompletionParameters withRelaxedMatching() {
return new CompletionParameters(myPosition, myOriginalFile, myCompletionType, myOffset, myInvocationCount, myLookup, true);
return new CompletionParameters(myPosition, myOriginalFile, myCompletionType, myOffset, newCount, myLookup);
}
@NotNull
@@ -101,11 +95,7 @@ public class CompletionParameters {
return myInvocationCount == 0;
}
public boolean isRelaxedMatching() {
return myRelaxedMatching;
}
public CompletionParameters withPosition(PsiElement element, int offset) {
return new CompletionParameters(element, myOriginalFile, myCompletionType, offset, myInvocationCount, myLookup, myRelaxedMatching);
return new CompletionParameters(element, myOriginalFile, myCompletionType, offset, myInvocationCount, myLookup);
}
}
@@ -379,7 +379,7 @@ public class CodeCompletionHandlerBase implements CodeInsightActionHandler {
PsiFile originalFile = fileCopy.getOriginalFile();
final PsiElement insertedElement = findCompletionPositionLeaf(newContext, offset, fileCopy, originalFile);
insertedElement.putUserData(CompletionContext.COMPLETION_CONTEXT_KEY, newContext);
return new CompletionParameters(insertedElement, originalFile, myCompletionType, offset, invocationCount, obtainLookup(initContext.getEditor()), false);
return new CompletionParameters(insertedElement, originalFile, myCompletionType, offset, invocationCount, obtainLookup(initContext.getEditor()));
}
@NotNull
@@ -1,77 +0,0 @@
/*
* 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;
import com.intellij.codeInsight.template.impl.LiveTemplateLookupElement;
import com.intellij.patterns.PatternCondition;
import com.intellij.patterns.StandardPatterns;
import com.intellij.util.Consumer;
import com.intellij.util.ProcessingContext;
import org.jetbrains.annotations.NotNull;
import java.util.HashSet;
import java.util.Set;
/**
* @author peter
*/
public class RelaxedMatchingContributor extends CompletionContributor {
@Override
public void fillCompletionVariants(CompletionParameters parameters, final CompletionResultSet result) {
final Set<CompletionResult> elements = result.runRemainingContributors(parameters, true);
if (!elements.isEmpty() && parameters.getInvocationCount() == 0) {
Set<String> prefixes = new HashSet<String>();
for (CompletionResult element : elements) {
prefixes.add(element.getPrefixMatcher().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 (CompletionResult element : elements) {
if (element.getPrefixMatcher().cloneWithPrefix(s).prefixMatches(element.getLookupElement())) {
return false;
}
}
return true;
}
}));
}
}
CompletionParameters relaxed;
if (parameters.getInvocationCount() == 0 && (elements.isEmpty() || elements.size() == 1 && elements.iterator().next().getLookupElement().as(
LiveTemplateLookupElement.class) != null)) {
relaxed = parameters.withRelaxedMatching();
}
else if (parameters.getInvocationCount() >= 2) {
relaxed = parameters.withRelaxedMatching().withInvocationCount(parameters.getInvocationCount() - 1);
}
else {
return;
}
result.runRemainingContributors(relaxed, new Consumer<CompletionResult>() {
@Override
public void consume(CompletionResult element) {
result.passResult(element);
}
});
}
}
@@ -7,90 +7,41 @@ import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.codeStyle.NameUtil;
import com.intellij.util.containers.hash.LinkedHashMap;
import com.intellij.util.text.Matcher;
import org.jetbrains.annotations.NotNull;
import java.util.Map;
/**
* @author peter
*/
public class CamelHumpMatcher extends PrefixMatcher {
private static int ourLastCompletionCaseSetting = -1;
private static final Map<String, Matcher> ourPatternCache = new LinkedHashMap<String, Matcher>() {
@Override
protected boolean removeEldestEntry(Map.Entry<String, Matcher> eldest) {
return size() > 10;
}
};
private Matcher myMatcher;
private final Matcher myMatcher;
private final boolean myCaseSensitive;
private final int currentSetting;
private final boolean myRelaxedMatching;
public CamelHumpMatcher(@NotNull final String prefix) {
this(prefix, true, false);
this(prefix, true);
}
public CamelHumpMatcher(String prefix, boolean caseSensitive, boolean relaxedMatching) {
public CamelHumpMatcher(String prefix, boolean caseSensitive) {
super(prefix);
myRelaxedMatching = relaxedMatching;
currentSetting = CodeInsightSettings.getInstance().COMPLETION_CASE_SENSITIVE;
myCaseSensitive = caseSensitive;
myMatcher = createMatcher(myCaseSensitive);
}
public boolean prefixMatches(@NotNull final String name) {
synchronized (ourPatternCache) {
if (myMatcher == null) {
if (ourLastCompletionCaseSetting != currentSetting) {
ourPatternCache.clear();
ourLastCompletionCaseSetting = currentSetting;
}
myMatcher = obtainMatcher(myRelaxedMatching, myCaseSensitive);
}
if (myMatcher.matches(name)) {
if (myRelaxedMatching && obtainMatcher(false, myCaseSensitive).matches(name)) {
return false;
}
return true;
}
return false;
}
return myMatcher.matches(name);
}
private Matcher obtainMatcher(final boolean relax, final boolean caseSensitive) {
String key = relax + myPrefix + caseSensitive;
Matcher pattern = ourPatternCache.get(key);
if (pattern == null) {
pattern = createCamelHumpsMatcher(relax, caseSensitive, myPrefix);
ourPatternCache.put(key, pattern);
}
return pattern;
}
public boolean prefixMatches(@NotNull final LookupElement element) {
return prefixMatchersInternal(element, !element.isCaseSensitive());
}
private boolean prefixMatchersInternal(final LookupElement element, final boolean itemCaseInsensitive) {
if (itemCaseInsensitive && myRelaxedMatching) {
return false;
}
for (final String name : element.getAllLookupStrings()) {
if (itemCaseInsensitive && StringUtil.startsWithIgnoreCase(name, myPrefix) || prefixMatches(name)) {
return true;
}
if (itemCaseInsensitive && CodeInsightSettings.ALL != CodeInsightSettings.getInstance().COMPLETION_CASE_SENSITIVE) {
Matcher matcher;
synchronized (ourPatternCache) {
matcher = obtainMatcher(false, false);
}
if (matcher.matches(name)) {
if (createMatcher(false).matches(name)) {
return true;
}
}
@@ -100,20 +51,16 @@ public class CamelHumpMatcher extends PrefixMatcher {
@NotNull
public PrefixMatcher cloneWithPrefix(@NotNull final String prefix) {
return new CamelHumpMatcher(prefix, myCaseSensitive, myRelaxedMatching);
return new CamelHumpMatcher(prefix, myCaseSensitive);
}
private static Matcher createCamelHumpsMatcher(final boolean relaxedMatching, final boolean caseSensitive, String prefix) {
prefix = applyMiddleMatching(prefix);
private Matcher createMatcher(final boolean caseSensitive) {
String prefix = applyMiddleMatching(myPrefix);
if (!caseSensitive) {
return NameUtil.buildCompletionMatcher(prefix, 0, true, true);
}
if (relaxedMatching) {
return NameUtil.buildCompletionMatcher(prefix, 0, true, true);
}
switch (CodeInsightSettings.getInstance().COMPLETION_CASE_SENSITIVE) {
case CodeInsightSettings.NONE:
return NameUtil.buildCompletionMatcher(prefix, 0, true, true);
@@ -139,7 +86,4 @@ public class CamelHumpMatcher extends PrefixMatcher {
return myPrefix;
}
public boolean isRelaxedMatching() {
return myRelaxedMatching;
}
}
@@ -90,7 +90,7 @@ public class CompletionServiceImpl extends CompletionService{
throw new AssertionError("createResultSet may be invoked only from completion thread: " + indicator + "!=" + getCurrentCompletion() + "; phase set at " + ourPhaseTrace);
}
CompletionProgressIndicator process = (CompletionProgressIndicator)indicator;
CamelHumpMatcher matcher = new CamelHumpMatcher(prefix, true, parameters.isRelaxedMatching());
CamelHumpMatcher matcher = new CamelHumpMatcher(prefix);
CompletionSorterImpl sorter = defaultSorter(parameters, matcher);
return new CompletionResultSetImpl(consumer, textBeforePosition, matcher, contributor,parameters, sorter, process, null);
}
@@ -157,8 +157,7 @@ public class CompletionServiceImpl extends CompletionService{
@NotNull
public CompletionResultSet withPrefixMatcher(@NotNull final String prefix) {
boolean relaxed = getPrefixMatcher() instanceof CamelHumpMatcher && ((CamelHumpMatcher)getPrefixMatcher()).isRelaxedMatching();
return withPrefixMatcher(new CamelHumpMatcher(prefix, true, relaxed));
return withPrefixMatcher(new CamelHumpMatcher(prefix));
}
@NotNull
@@ -170,8 +169,7 @@ public class CompletionServiceImpl extends CompletionService{
@NotNull
@Override
public CompletionResultSet caseInsensitive() {
boolean relaxed = getPrefixMatcher() instanceof CamelHumpMatcher && ((CamelHumpMatcher)getPrefixMatcher()).isRelaxedMatching();
return withPrefixMatcher(new CamelHumpMatcher(getPrefixMatcher().getPrefix(), false, relaxed));
return withPrefixMatcher(new CamelHumpMatcher(getPrefixMatcher().getPrefix(), false));
}
@Override
@@ -332,7 +332,7 @@ public class GroovyCompletionContributor extends CompletionContributor {
if (reference.getQualifier() == null) {
GroovySmartCompletionContributor.addExpectedClassMembers(parameters, result);
if (isClassNamePossible(position) && JavaCompletionContributor.mayStartClassName(result, parameters.isRelaxedMatching())) {
if (isClassNamePossible(position) && JavaCompletionContributor.mayStartClassName(result)) {
if (JavaCompletionContributor.mayShowAllClasses(parameters)) {
addAllClasses(parameters, result, inheritors);
} else {
@@ -51,7 +51,7 @@ public class GroovyNoVariantsDelegator extends CompletionContributor {
private static void delegate(CompletionParameters parameters, CompletionResultSet result) {
if (parameters.getCompletionType() == CompletionType.BASIC) {
if (parameters.getInvocationCount() <= 1 &&
JavaCompletionContributor.mayStartClassName(result, false) &&
JavaCompletionContributor.mayStartClassName(result) &&
GroovyCompletionContributor.isClassNamePossible(parameters.getPosition()) &&
!MapArgumentCompletionProvider.isMapKeyCompletion(parameters)) {
suggestNonImportedClasses(parameters, result);