Add custom templates to completion list if corresponding Registry-key is enabled

This commit is contained in:
Alexander Zolotov
2014-02-06 17:20:31 +04:00
parent f00e6c62f7
commit d9fb5143ca
7 changed files with 130 additions and 40 deletions

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
* 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.
@@ -22,6 +22,7 @@ import com.intellij.codeInsight.template.CustomTemplateCallback;
import com.intellij.codeInsight.template.postfix.settings.PostfixTemplatesSettings;
import com.intellij.codeInsight.template.postfix.templates.PostfixLiveTemplate;
import com.intellij.codeInsight.template.postfix.templates.PostfixTemplate;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.patterns.StandardPatterns;
import com.intellij.psi.PsiFile;
import com.intellij.util.ProcessingContext;
@@ -32,7 +33,10 @@ import static com.intellij.codeInsight.template.postfix.completion.PostfixTempla
class PostfixTemplatesCompletionProvider extends CompletionProvider<CompletionParameters> {
@Override
protected void addCompletions(@NotNull CompletionParameters parameters, ProcessingContext context, @NotNull CompletionResultSet result) {
if (!isCompletionEnabled(parameters)) {
if (!isCompletionEnabled(parameters) || Registry.is("show.live.templates.in.completion")) {
/**
* disabled or covered with {@link com.intellij.codeInsight.template.impl.LiveTemplateCompletionContributor}
*/
return;
}

View File

@@ -0,0 +1,7 @@
import java.lang.Object;
public class Foo {
void m() {
new Object().<caret>
}
}

View File

@@ -0,0 +1,7 @@
import java.lang.Object;
public class Foo {
void m() {
new Object().<caret>
}
}

View File

@@ -21,11 +21,57 @@ import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.impl.LookupImpl;
import com.intellij.codeInsight.template.postfix.settings.PostfixTemplatesSettings;
import com.intellij.codeInsight.template.postfix.templates.*;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.registry.RegistryValue;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
public class TemplatesCompletionTest extends CompletionAutoPopupTestCase {
private boolean oldRegistryValue;
@Override
public void setUp() {
super.setUp();
RegistryValue registryValue = Registry.get("show.live.templates.in.completion");
oldRegistryValue = registryValue.asBoolean();
registryValue.setValue(false);
}
@Override
public void tearDown() throws Exception {
RegistryValue registryValue = Registry.get("show.live.templates.in.completion");
registryValue.setValue(oldRegistryValue);
PostfixTemplatesSettings settings = PostfixTemplatesSettings.getInstance();
assertNotNull(settings);
settings.setTemplatesState(ContainerUtil.<String, Boolean>newHashMap());
settings.setPostfixTemplatesEnabled(true);
settings.setTemplatesCompletionEnabled(true);
super.tearDown();
}
public void testSimpleCompletionList() {
Registry.get("show.live.templates.in.completion").setValue(true);
doAutoPopupTest("ins", InstanceofExpressionPostfixTemplate.class);
}
public void testAutopopupWithEnabledLiveTemplatesInCompletion() {
Registry.get("show.live.templates.in.completion").setValue(true);
configureByFile();
type("instanceof");
LookupImpl lookup = getLookup();
assertNotNull(lookup);
assertEquals(1, lookup.getItems().size());
LookupElement item = lookup.getCurrentItem();
assertNotNull(item);
assertInstanceOf(item, PostfixTemplateLookupElement.class);
assertInstanceOf(((PostfixTemplateLookupElement)item).getPostfixTemplate(), InstanceofExpressionPostfixTemplate.class);
}
public void testDoNotShowTemplateInInappropriateContext() {
doAutoPopupTest("instanceof", null);
}
@@ -42,7 +88,7 @@ public class TemplatesCompletionTest extends CompletionAutoPopupTestCase {
public void testShowAutoPopupForAliases() {
doAutoPopupTest("nn", NotNullCheckPostfixTemplate.class);
}
public void testShowAutoPopupForFloatLiterals() {
doAutoPopupTest("fori", ForAscendingPostfixTemplate.class);
}
@@ -53,7 +99,7 @@ public class TemplatesCompletionTest extends CompletionAutoPopupTestCase {
settings.setPostfixTemplatesEnabled(false);
doAutoPopupTest("instanceof", null);
}
public void testDoNotShowTemplateIfTemplateCompletionIsDisabled() {
PostfixTemplatesSettings settings = PostfixTemplatesSettings.getInstance();
assertNotNull(settings);
@@ -110,16 +156,6 @@ public class TemplatesCompletionTest extends CompletionAutoPopupTestCase {
myFixture.assertPreferredCompletionItems(selectedIndex, ".par", "parents");
}
@Override
public void tearDown() throws Exception {
PostfixTemplatesSettings settings = PostfixTemplatesSettings.getInstance();
assertNotNull(settings);
settings.setTemplatesState(ContainerUtil.<String, Boolean>newHashMap());
settings.setPostfixTemplatesEnabled(true);
settings.setTemplatesCompletionEnabled(true);
super.tearDown();
}
@Override
protected String getBasePath() {
return JavaTestUtil.getRelativeJavaTestDataPath() + "/codeInsight/template/postfix/completion";

View File

@@ -1,8 +1,23 @@
/*
* 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.lookup.LookupElement;
import com.intellij.patterns.ElementPattern;
import com.intellij.patterns.PlatformPatterns;
import com.intellij.patterns.StandardPatterns;
import com.intellij.util.Consumer;
import org.jetbrains.annotations.NotNull;
@@ -54,7 +69,7 @@ public abstract class CompletionResultSet implements Consumer<LookupElement> {
myConsumer.consume(result);
}
public void addAllElements(@NotNull final Iterable<LookupElement> elements) {
public void addAllElements(@NotNull final Iterable<? extends LookupElement> elements) {
for (LookupElement element : elements) {
addElement(element);
}
@@ -118,7 +133,7 @@ public abstract class CompletionResultSet implements Consumer<LookupElement> {
}
public void restartCompletionOnPrefixChange(String prefix) {
restartCompletionOnPrefixChange(PlatformPatterns.string().equalTo(prefix));
restartCompletionOnPrefixChange(StandardPatterns.string().equalTo(prefix));
}
public abstract void restartCompletionOnPrefixChange(ElementPattern<String> prefixCondition);

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
* 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.
@@ -39,6 +39,7 @@ import com.intellij.openapi.util.Pair;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.MultiMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -70,12 +71,7 @@ public class ListTemplatesHandler implements CodeInsightActionHandler {
}
}
List<CustomLiveTemplateLookupElement> customTemplatesLookupElements = ContainerUtil.newArrayList();
for (CustomLiveTemplate customLiveTemplate : CustomLiveTemplate.EP_NAME.getExtensions()) {
if (customLiveTemplate instanceof CustomLiveTemplateBase && TemplateManagerImpl.isApplicable(customLiveTemplate, editor, file)) {
customTemplatesLookupElements.addAll(((CustomLiveTemplateBase)customLiveTemplate).getLookupElements(file, editor, offset));
}
}
MultiMap<String,CustomLiveTemplateLookupElement> customTemplatesLookupElements = listApplicableCustomTemplates(editor, file, offset);
if (matchingTemplates.isEmpty()) {
matchingTemplates.addAll(applicableTemplates);
@@ -99,7 +95,7 @@ public class ListTemplatesHandler implements CodeInsightActionHandler {
final PsiFile file,
@NotNull String prefix,
@NotNull List<TemplateImpl> matchingTemplates,
@NotNull List<CustomLiveTemplateLookupElement> customTemplatesLookupElements) {
@NotNull MultiMap<String, CustomLiveTemplateLookupElement> customTemplatesLookupElements) {
final LookupImpl lookup = (LookupImpl)LookupManager.getInstance(project).createLookup(editor, LookupElement.EMPTY_ARRAY, prefix,
new TemplatesArranger());
@@ -107,15 +103,29 @@ public class ListTemplatesHandler implements CodeInsightActionHandler {
lookup.addItem(createTemplateElement(template), new PlainPrefixMatcher(prefix));
}
CustomTemplateCallback customTemplateCallback = new CustomTemplateCallback(editor, file, false);
for (CustomLiveTemplateLookupElement element : customTemplatesLookupElements) {
String customTemplatePrefix = element.getCustomLiveTemplate().computeTemplateKeyWithoutContextChecking(customTemplateCallback);
lookup.addItem(element, new PlainPrefixMatcher(customTemplatePrefix));
for (Map.Entry<String, Collection<CustomLiveTemplateLookupElement>> entry : customTemplatesLookupElements.entrySet()) {
for (CustomLiveTemplateLookupElement lookupElement : entry.getValue()) {
lookup.addItem(lookupElement, new PlainPrefixMatcher(entry.getKey()));
}
}
showLookup(lookup, file);
}
public static MultiMap<String, CustomLiveTemplateLookupElement> listApplicableCustomTemplates(@NotNull Editor editor, @NotNull PsiFile file, int offset) {
final MultiMap<String, CustomLiveTemplateLookupElement> result = MultiMap.create();
CustomTemplateCallback customTemplateCallback = new CustomTemplateCallback(editor, file, false);
for (CustomLiveTemplate customLiveTemplate : CustomLiveTemplate.EP_NAME.getExtensions()) {
if (customLiveTemplate instanceof CustomLiveTemplateBase && TemplateManagerImpl.isApplicable(customLiveTemplate, editor, file)) {
String customTemplatePrefix = ((CustomLiveTemplateBase)customLiveTemplate).computeTemplateKeyWithoutContextChecking(customTemplateCallback);
if (customTemplatePrefix != null) {
result.putValues(customTemplatePrefix, ((CustomLiveTemplateBase)customLiveTemplate).getLookupElements(file, editor, offset));
}
}
}
return result;
}
private static LiveTemplateLookupElement createTemplateElement(final TemplateImpl template) {
return new LiveTemplateLookupElementImpl(template, false) {
@Override

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
* 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.
@@ -29,12 +29,13 @@ import com.intellij.psi.PsiFile;
import com.intellij.util.Consumer;
import com.intellij.util.ProcessingContext;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.MultiMap;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.*;
import static com.intellij.codeInsight.template.impl.ListTemplatesHandler.listApplicableCustomTemplates;
/**
* @author peter
@@ -43,31 +44,32 @@ public class LiveTemplateCompletionContributor extends CompletionContributor {
public LiveTemplateCompletionContributor() {
extend(CompletionType.BASIC, PlatformPatterns.psiElement(), new CompletionProvider<CompletionParameters>() {
@Override
protected void addCompletions(@NotNull CompletionParameters parameters,
protected void addCompletions(@NotNull final CompletionParameters parameters,
ProcessingContext context,
@NotNull CompletionResultSet result) {
final PsiFile file = parameters.getPosition().getContainingFile();
final int offset = parameters.getOffset();
final List<TemplateImpl> templates = listApplicableTemplates(file, offset);
Editor editor = parameters.getEditor();
if (showAllTemplates()) {
final MultiMap<String, CustomLiveTemplateLookupElement> customTemplates = listApplicableCustomTemplates(editor, file, offset);
final Ref<Boolean> templatesShown = Ref.create(false);
final CompletionResultSet finalResult = result;
result.runRemainingContributors(parameters, new Consumer<CompletionResult>() {
@Override
public void consume(CompletionResult completionResult) {
finalResult.passResult(completionResult);
ensureTemplatesShown(templatesShown, templates, finalResult);
ensureTemplatesShown(templatesShown, templates, customTemplates, finalResult);
}
});
ensureTemplatesShown(templatesShown, templates, result);
ensureTemplatesShown(templatesShown, templates, customTemplates, result);
return;
}
if (parameters.getInvocationCount() > 0) return; //only in autopopups for now
String templatePrefix = findLiveTemplatePrefix(file, parameters.getEditor(), result.getPrefixMatcher().getPrefix());
String templatePrefix = findLiveTemplatePrefix(file, editor, result.getPrefixMatcher().getPrefix());
final TemplateImpl template = findApplicableTemplate(file, offset, templatePrefix);
if (template != null) {
result = result.withPrefixMatcher(template.getKey());
@@ -76,7 +78,6 @@ public class LiveTemplateCompletionContributor extends CompletionContributor {
for (final TemplateImpl possible : templates) {
result.restartCompletionOnPrefixChange(possible.getKey());
}
}
});
}
@@ -86,12 +87,22 @@ public class LiveTemplateCompletionContributor extends CompletionContributor {
return Registry.is("show.live.templates.in.completion");
}
private static void ensureTemplatesShown(Ref<Boolean> templatesShown, List<TemplateImpl> templates, CompletionResultSet result) {
private static void ensureTemplatesShown(Ref<Boolean> templatesShown,
List<TemplateImpl> templates,
MultiMap<String, CustomLiveTemplateLookupElement> customTemplates,
CompletionResultSet result) {
if (!templatesShown.get()) {
templatesShown.set(true);
for (final TemplateImpl possible : templates) {
result.addElement(new LiveTemplateLookupElementImpl(possible, false));
}
for (Map.Entry<String, Collection<CustomLiveTemplateLookupElement>> entry : customTemplates.entrySet()) {
Collection<CustomLiveTemplateLookupElement> value = entry.getValue();
if (!value.isEmpty()) {
result.withPrefixMatcher(entry.getKey()).addAllElements(value);
}
}
}
}