[java-completion] IDEA-363369 Postfix completion for conversion

- implementation new templates
- tests

GitOrigin-RevId: 18d04d8d2eb87323feae2f5e2536ee619a7f6d15
This commit is contained in:
Mikhail Pyltsin
2024-11-15 19:02:58 +01:00
committed by intellij-monorepo-bot
parent f952929bb0
commit 0569ea733a
49 changed files with 629 additions and 25 deletions

View File

@@ -0,0 +1,28 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInsight.template.postfix.templates;
import com.intellij.codeInsight.template.postfix.templates.editable.JavaPostfixTemplateExpressionCondition;
import com.intellij.openapi.project.DumbAware;
import com.intellij.pom.java.LanguageLevel;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
public class AsListToListPostfixTemplate extends JavaEditableTaggedPostfixTemplate implements DumbAware {
public AsListToListPostfixTemplate(@NotNull JavaPostfixTemplateProvider provider) {
super("Arrays.asList(exp)",
"asList",
"java.util.Arrays.asList($EXPR$)$END$",
"Arrays.asList($EXPR$)",
Collections.singleton(
new JavaPostfixTemplateExpressionCondition.JavaPostfixTemplateArrayReferenceExpressionCondition()),
LanguageLevel.JDK_1_3, false, new String[]{".toList"}, provider);
}
@Override
public boolean isBuiltin() {
return true;
}
}

View File

@@ -0,0 +1,106 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInsight.template.postfix.templates;
import com.intellij.codeInsight.lookup.LookupElementPresentation;
import com.intellij.codeInsight.template.impl.TemplateImpl;
import com.intellij.codeInsight.template.postfix.templates.editable.JavaEditablePostfixTemplate;
import com.intellij.codeInsight.template.postfix.templates.editable.JavaPostfixTemplateExpressionCondition;
import com.intellij.java.JavaBundle;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.util.TextRange;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.*;
@SuppressWarnings("PostfixTemplateDescriptionNotFound")
public class JavaEditableTaggedPostfixTemplate extends JavaEditablePostfixTemplate implements CustomizableLookupElementTemplate {
@SuppressWarnings("RegExpUnexpectedAnchor") private static final String EXPR_$ = "$EXPR$";
@Nullable
private String myText;
@NotNull
private final String myExample;
@NotNull
private final String myTemplateName;
public @NotNull String @NotNull [] getTags() {
return myTags;
}
private final @NotNull String @NotNull [] myTags;
public JavaEditableTaggedPostfixTemplate(@NotNull String templateId,
@NotNull String templateName,
@NotNull String templateText,
@NotNull String example,
@NotNull Set<? extends JavaPostfixTemplateExpressionCondition> expressionConditions,
@NotNull LanguageLevel minimumLanguageLevel,
boolean useTopmostExpression,
@NotNull String @NotNull [] tags,
@NotNull PostfixTemplateProvider provider) {
this(templateId, templateName, createTemplate(templateText), example, expressionConditions, minimumLanguageLevel, useTopmostExpression,
tags, provider);
}
public JavaEditableTaggedPostfixTemplate(@NotNull String templateId,
@NotNull String templateName,
@NotNull TemplateImpl liveTemplate,
@NotNull String example,
@NotNull Set<? extends JavaPostfixTemplateExpressionCondition> expressionConditions,
@NotNull LanguageLevel minimumLanguageLevel,
boolean useTopmostExpression,
@NotNull String @NotNull [] tags,
@NotNull PostfixTemplateProvider provider) {
super(templateId, templateName, liveTemplate, example.replace(EXPR_$, "expr"), expressionConditions, minimumLanguageLevel, useTopmostExpression, provider);
myTags = tags;
myExample = example;
myTemplateName= templateName;
}
@Override
public boolean isApplicable(@NotNull PsiElement context, @NotNull Document copyDocument, int newOffset) {
List<PsiElement> expressions = getExpressions(context, copyDocument, newOffset);
if (expressions.size() != 1) return false;
PsiElement element = expressions.get(0);
myText = element.getText(); //not ideal, because the state is changed, but it needs for nice rendering
return true;
}
@Override
public void renderElement(@NotNull LookupElementPresentation presentation) {
String exp = myText;
String templateText = myExample;
if (exp == null || templateText.length() + exp.length() >= 50 || !templateText.contains(EXPR_$)) {
return;
}
String withExp = templateText.replace(EXPR_$, exp);
if (withExp.contains("$")) {
return;
}
ArrayList<String> allTags = new ArrayList<>(Arrays.asList(myTags));
allTags.add(getKey());
String message = JavaBundle.message("java.completion.tag", allTags.size());
String withTags = withExp + " " + message + String.join(", ", allTags);
presentation.setItemText(withTags);
int startOffset = templateText.indexOf(EXPR_$);
presentation.decorateItemTextRange(new TextRange(startOffset, startOffset + exp.length()),
LookupElementPresentation.LookupItemDecoration.GRAY);
startOffset = withExp.length();
presentation.decorateItemTextRange(new TextRange(startOffset, startOffset + 1 + message.length()),
LookupElementPresentation.LookupItemDecoration.GRAY);
presentation.setTypeText("");
}
@Override
public Collection<String> getAllLookupStrings() {
return Arrays.asList(myTags);
}
}

View File

@@ -71,7 +71,12 @@ public class JavaPostfixTemplateProvider implements PostfixTemplateProvider {
new SwitchStatementPostfixTemplate(),
new TryStatementPostfixTemplate(),
new TryWithResourcesPostfixTemplate(),
new StreamPostfixTemplate()
new StreamPostfixTemplate(),
new AsListToListPostfixTemplate(this),
new ListOfToListPostfixTemplate(this),
new NewArrayListToListPostfixTemplate(this),
new NewHashSetToSetPostfixTemplate(this)
);
@Override
@@ -173,6 +178,9 @@ public class JavaPostfixTemplateProvider implements PostfixTemplateProvider {
if (JavaPostfixTemplateExpressionCondition.JavaPostfixTemplateArrayExpressionCondition.ID.equals(id)) {
return new JavaPostfixTemplateExpressionCondition.JavaPostfixTemplateArrayExpressionCondition();
}
if (JavaPostfixTemplateExpressionCondition.JavaPostfixTemplateArrayReferenceExpressionCondition.ID.equals(id)) {
return new JavaPostfixTemplateExpressionCondition.JavaPostfixTemplateArrayReferenceExpressionCondition();
}
if (JavaPostfixTemplateExpressionCondition.JavaPostfixTemplateNonVoidExpressionCondition.ID.equals(id)) {
return new JavaPostfixTemplateExpressionCondition.JavaPostfixTemplateNonVoidExpressionCondition();
}

View File

@@ -0,0 +1,26 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInsight.template.postfix.templates;
import com.intellij.codeInsight.template.postfix.templates.editable.JavaPostfixTemplateExpressionCondition;
import com.intellij.openapi.project.DumbAware;
import com.intellij.pom.java.LanguageLevel;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
public class ListOfToListPostfixTemplate extends JavaEditableTaggedPostfixTemplate implements DumbAware {
public ListOfToListPostfixTemplate(@NotNull JavaPostfixTemplateProvider provider) {
super("List.of(exp)",
"listOf",
"java.util.List.of($EXPR$)$END$",
"List.of($EXPR$)",
Collections.singleton(
new JavaPostfixTemplateExpressionCondition.JavaPostfixTemplateArrayReferenceExpressionCondition()),
LanguageLevel.JDK_1_9, false, new String[]{".asList", ".toList"}, provider);
}
@Override
public boolean isBuiltin() {
return true;
}
}

View File

@@ -0,0 +1,28 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInsight.template.postfix.templates;
import com.intellij.codeInsight.template.postfix.templates.editable.JavaPostfixTemplateExpressionCondition;
import com.intellij.openapi.project.DumbAware;
import com.intellij.pom.java.LanguageLevel;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
public class NewArrayListToListPostfixTemplate extends JavaEditableTaggedPostfixTemplate implements DumbAware {
public NewArrayListToListPostfixTemplate(@NotNull JavaPostfixTemplateProvider provider) {
super("new ArrayList<>(exp)",
"toList",
"new java.util.ArrayList<>($EXPR$)$END$",
"new ArrayList<>($EXPR$)",
Collections.singleton(
new JavaPostfixTemplateExpressionCondition.JavaPostfixTemplateExpressionFqnCondition("java.util.Collection")),
LanguageLevel.JDK_1_7, false, new String[]{".asList"}, provider);
}
@Override
public boolean isBuiltin() {
return true;
}
}

View File

@@ -0,0 +1,28 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInsight.template.postfix.templates;
import com.intellij.codeInsight.template.postfix.templates.editable.JavaPostfixTemplateExpressionCondition;
import com.intellij.openapi.project.DumbAware;
import com.intellij.pom.java.LanguageLevel;
import org.jetbrains.annotations.NotNull;
import java.util.Collections;
public class NewHashSetToSetPostfixTemplate extends JavaEditableTaggedPostfixTemplate implements DumbAware {
public NewHashSetToSetPostfixTemplate(@NotNull JavaPostfixTemplateProvider provider) {
super("new HashSet<>(exp)",
"toSet",
"new java.util.HashSet<>($EXPR$)$END$",
"new HashSet<>($EXPR$)",
Collections.singleton(
new JavaPostfixTemplateExpressionCondition.JavaPostfixTemplateExpressionFqnCondition("java.util.Collection")),
LanguageLevel.JDK_1_7, false, new String[]{".asSet"}, provider);
}
@Override
public boolean isBuiltin() {
return true;
}
}

View File

@@ -4,6 +4,7 @@ package com.intellij.codeInsight.template.postfix.templates.editable;
import com.intellij.codeInsight.daemon.DaemonCodeAnalyzer;
import com.intellij.codeInsight.template.Template;
import com.intellij.codeInsight.template.postfix.settings.PostfixTemplateEditorBase;
import com.intellij.codeInsight.template.postfix.templates.JavaEditableTaggedPostfixTemplate;
import com.intellij.codeInsight.template.postfix.templates.PostfixTemplate;
import com.intellij.codeInsight.template.postfix.templates.PostfixTemplateProvider;
import com.intellij.ide.util.TreeClassChooser;
@@ -19,6 +20,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectManager;
import com.intellij.openapi.ui.ComboBox;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.text.Strings;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.psi.JavaCodeFragment;
import com.intellij.psi.JavaCodeFragmentFactory;
@@ -26,6 +28,7 @@ import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.ui.SimpleListCellRenderer;
import com.intellij.ui.components.JBCheckBox;
import com.intellij.ui.components.JBTextField;
import com.intellij.util.ObjectUtils;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.ui.FormBuilder;
@@ -34,6 +37,7 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.Set;
@@ -42,17 +46,19 @@ public class JavaPostfixTemplateEditor extends PostfixTemplateEditorBase<JavaPos
private final @NotNull JPanel myPanel;
private final @NotNull ComboBox<LanguageLevel> myLanguageLevelCombo;
private final @NotNull JBCheckBox myStaticImportCheckBox;
private final @NotNull JBTextField myTagsField;
public JavaPostfixTemplateEditor(@NotNull PostfixTemplateProvider provider) {
super(provider, createEditor(), true);
myStaticImportCheckBox = new JBCheckBox(JavaBundle.message("dialog.edit.template.checkbox.use.static.import"));
myLanguageLevelCombo = new ComboBox<>(LanguageLevel.values());
myLanguageLevelCombo.setRenderer(SimpleListCellRenderer.create("", LanguageLevel::getPresentableText));
myTagsField = new JBTextField();
myPanel = FormBuilder.createFormBuilder()
.addLabeledComponent(JavaBundle.message("postfix.template.language.level.title"), myLanguageLevelCombo)
.addComponentFillVertically(myEditTemplateAndConditionsPanel, UIUtil.DEFAULT_VGAP)
.addComponent(myStaticImportCheckBox)
.addLabeledComponent("Tags: ", myTagsField)
.getPanel();
}
@@ -69,9 +75,17 @@ public class JavaPostfixTemplateEditor extends PostfixTemplateEditorBase<JavaPos
String templateText = myTemplateEditor.getDocument().getText();
boolean useTopmostExpression = myApplyToTheTopmostJBCheckBox.isSelected();
boolean useStaticImport = myStaticImportCheckBox.isSelected();
JavaEditablePostfixTemplate template =
new JavaEditablePostfixTemplate(templateId, templateName, templateText, "", conditions, languageLevel, useTopmostExpression,
myProvider);
String tagText = myTagsField.getText();
JavaEditablePostfixTemplate template;
if (tagText != null && !tagText.isBlank()) {
String[] tags = tagText.split("[,;]");
template =
new JavaEditableTaggedPostfixTemplate(templateId, templateName, templateText, "", conditions, languageLevel, useTopmostExpression, tags, myProvider);
} else{
template =
new JavaEditablePostfixTemplate(templateId, templateName, templateText, "", conditions, languageLevel, useTopmostExpression,
myProvider);
}
template.getLiveTemplate().setValue(Template.Property.USE_STATIC_IMPORT_IF_POSSIBLE, useStaticImport);
return template;
}
@@ -99,6 +113,7 @@ public class JavaPostfixTemplateEditor extends PostfixTemplateEditorBase<JavaPos
group.add(new AddConditionAction(new JavaPostfixTemplateExpressionCondition.JavaPostfixTemplateNumberExpressionCondition()));
group.add(new AddConditionAction(new JavaPostfixTemplateExpressionCondition.JavaPostfixTemplateNotPrimitiveTypeExpressionCondition()));
group.add(new AddConditionAction(new JavaPostfixTemplateExpressionCondition.JavaPostfixTemplateArrayExpressionCondition()));
group.add(new AddConditionAction(new JavaPostfixTemplateExpressionCondition.JavaPostfixTemplateArrayReferenceExpressionCondition()));
Project[] projects = ProjectManager.getInstance().getOpenProjects();
for (Project project : projects) {
group.add(new ChooseClassAction(project));
@@ -112,6 +127,9 @@ public class JavaPostfixTemplateEditor extends PostfixTemplateEditorBase<JavaPos
if (template instanceof JavaEditablePostfixTemplate javaTemplate) {
myLanguageLevelCombo.setSelectedItem(javaTemplate.getMinimumLanguageLevel());
myStaticImportCheckBox.setSelected(javaTemplate.getLiveTemplate().getValue(Template.Property.USE_STATIC_IMPORT_IF_POSSIBLE));
if(template instanceof JavaEditableTaggedPostfixTemplate javaTaggedTemplate) {
myTagsField.setText(Strings.join(Arrays.asList(javaTaggedTemplate.getTags()), ";"));
}
}
}

View File

@@ -248,4 +248,34 @@ public interface JavaPostfixTemplateExpressionCondition extends PostfixTemplateE
return getClass().hashCode();
}
}
class JavaPostfixTemplateArrayReferenceExpressionCondition implements JavaPostfixTemplateExpressionCondition {
public static final @NonNls String ID = "arrayReference";
@Override
public boolean value(@NotNull PsiExpression element) {
return JavaPostfixTemplatesUtils.isArrayReference(element.getType());
}
@Override
public @NotNull String getId() {
return ID;
}
@Override
public @NotNull @Nls String getPresentableName() {
return JavaBundle.message("postfix.template.condition.array.reference.name");
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
return o != null && getClass() == o.getClass();
}
@Override
public int hashCode() {
return getClass().hashCode();
}
}
}

View File

@@ -175,6 +175,11 @@ public final class JavaPostfixTemplatesUtils {
return type instanceof PsiArrayType;
}
@Contract("null -> false")
public static boolean isArrayReference(@Nullable PsiType type) {
return type instanceof PsiArrayType arrayType && !(arrayType.getComponentType() instanceof PsiPrimitiveType);
}
@Contract("null -> false")
public static boolean isBoolean(@Nullable PsiType type) {
return type != null && (PsiTypes.booleanType().equals(type) || type.equalsToText(CommonClassNames.JAVA_LANG_BOOLEAN));

View File

@@ -0,0 +1,3 @@
public void m(Integer[] value) {
Arrays.asList(value)<spot></spot>
}

View File

@@ -0,0 +1,3 @@
public void m(Integer[] value) {
<spot>value</spot>$key
}

View File

@@ -0,0 +1,7 @@
<html>
<body>
Creates a <code>Arrays.asList</code> call,
which returns an unmodifiable list
</body>
</html>

View File

@@ -0,0 +1,3 @@
public void m(Integer[] value) {
List.of(value)<spot></spot>
}

View File

@@ -0,0 +1,3 @@
public void m(Integer[] value) {
<spot>value</spot>$key
}

View File

@@ -0,0 +1,7 @@
<html>
<body>
Creates a <code>List.of</code> call,
which returns an unmodifiable list
</body>
</html>

View File

@@ -0,0 +1,3 @@
public void m(Set<String> value) {
new ArrayList<>(value)<spot></spot>
}

View File

@@ -0,0 +1,3 @@
public void m(Set<String> value) {
<spot>value</spot>$key
}

View File

@@ -0,0 +1,6 @@
<html>
<body>
Creates ArrayList with <code>new ArrayList<>()</code> call
</body>
</html>

View File

@@ -0,0 +1,3 @@
public void m(List<String> value) {
new HashSet<>(value)<spot></spot>
}

View File

@@ -0,0 +1,3 @@
public void m(List<String> value) {
<spot>value</spot>$key
}

View File

@@ -0,0 +1,6 @@
<html>
<body>
Creates HashSet with <code>new HashSet<>()</code> call
</body>
</html>

View File

@@ -0,0 +1,5 @@
public class Foo {
void m(Integer[] o) {
o.toList<caret>
}
}

View File

@@ -0,0 +1,5 @@
public class Foo {
void m(Integer[] o) {
o.asList<caret>
}
}

View File

@@ -0,0 +1,7 @@
import java.util.Arrays;
public class Foo {
void m(Integer[] o) {
Arrays.asList(o)<caret>
}
}

View File

@@ -0,0 +1,7 @@
import java.util.Arrays;
public class Foo {
void m(Integer[] o) {
Arrays.asList(o)<caret>
}
}

View File

@@ -0,0 +1,5 @@
public class Foo {
void m(Integer[] o) {
o.toList<caret>
}
}

View File

@@ -0,0 +1,5 @@
public class Foo {
void m(Integer[] o) {
o.asList<caret>
}
}

View File

@@ -0,0 +1,7 @@
import java.util.List;
public class Foo {
void m(Integer[] o) {
List.of(o)<caret>
}
}

View File

@@ -0,0 +1,7 @@
import java.util.List;
public class Foo {
void m(Integer[] o) {
List.of(o)<caret>
}
}

View File

@@ -0,0 +1,7 @@
import java.util.Set;
public class Foo {
void m(Set<String> o) {
o.toList<caret>
}
}

View File

@@ -0,0 +1,7 @@
import java.util.Set;
public class Foo {
void m(Set<String> o) {
o.asList<caret>
}
}

View File

@@ -0,0 +1,8 @@
import java.util.ArrayList;
import java.util.Set;
public class Foo {
void m(Set<String> o) {
new ArrayList<>(o)<caret>
}
}

View File

@@ -0,0 +1,8 @@
import java.util.ArrayList;
import java.util.Set;
public class Foo {
void m(Set<String> o) {
new ArrayList<>(o)<caret>
}
}

View File

@@ -0,0 +1,7 @@
import java.util.Set;
public class Foo {
void m(Set<String> o) {
o.toSet<caret>
}
}

View File

@@ -0,0 +1,7 @@
import java.util.Set;
public class Foo {
void m(Set<String> o) {
o.asSet<caret>
}
}

View File

@@ -0,0 +1,8 @@
import java.util.HashSet;
import java.util.Set;
public class Foo {
void m(Set<String> o) {
new HashSet<>(o)<caret>
}
}

View File

@@ -0,0 +1,8 @@
import java.util.HashSet;
import java.util.Set;
public class Foo {
void m(Set<String> o) {
new HashSet<>(o)<caret>
}
}

View File

@@ -1,4 +1,4 @@
// Copyright 2000-2018 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.
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.java.codeInsight.template.postfix.editable;
import com.intellij.codeInsight.template.postfix.settings.PostfixTemplateStorage;
@@ -108,6 +108,12 @@ public class JavaEditablePostfixTemplateTest extends LightPlatformTestCase {
assertSameElements(reloadConditions(templateWithCondition(condition)), condition);
}
public void testArrayNotPrimitiveTypeCondition() {
JavaPostfixTemplateExpressionCondition condition =
new JavaPostfixTemplateExpressionCondition.JavaPostfixTemplateArrayReferenceExpressionCondition();
assertSameElements(reloadConditions(templateWithCondition(condition)), condition);
}
public void testFqnCondition() {
JavaPostfixTemplateExpressionCondition condition =
new JavaPostfixTemplateExpressionCondition.JavaPostfixTemplateExpressionFqnCondition("test.class.Name");

View File

@@ -0,0 +1,28 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.java.codeInsight.template.postfix.templates;
import com.intellij.testFramework.LightProjectDescriptor;
import org.jetbrains.annotations.NotNull;
public class AsListToListPostfixTemplateTest extends PostfixTemplateTestCase {
@Override
protected @NotNull LightProjectDescriptor getProjectDescriptor() {
return JAVA_9;
}
@NotNull
@Override
protected String getSuffix() {
return "asList";
}
public void testSimple() {
doTestCompletion("asList");
}
public void testSimpleAsList() {
doTestCompletion("asList");
}
}

View File

@@ -0,0 +1,28 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.java.codeInsight.template.postfix.templates;
import com.intellij.testFramework.LightProjectDescriptor;
import org.jetbrains.annotations.NotNull;
public class ListOfToListPostfixTemplateTest extends PostfixTemplateTestCase {
@Override
protected @NotNull LightProjectDescriptor getProjectDescriptor() {
return JAVA_9;
}
@NotNull
@Override
protected String getSuffix() {
return "listOfToList";
}
public void testSimple() {
doTestCompletion("listOf");
}
public void testSimpleAsList() {
doTestCompletion("listOf");
}
}

View File

@@ -0,0 +1,28 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.java.codeInsight.template.postfix.templates;
import com.intellij.testFramework.LightProjectDescriptor;
import org.jetbrains.annotations.NotNull;
public class NewArrayListToListPostfixTemplateTest extends PostfixTemplateTestCase {
@Override
protected @NotNull LightProjectDescriptor getProjectDescriptor() {
return JAVA_8;
}
@NotNull
@Override
protected String getSuffix() {
return "toListNewArrayList";
}
public void testSimple() {
doTestCompletion(null);
}
public void testSimpleAsList() {
doTestCompletion(null);
}
}

View File

@@ -0,0 +1,28 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.java.codeInsight.template.postfix.templates;
import com.intellij.testFramework.LightProjectDescriptor;
import org.jetbrains.annotations.NotNull;
public class NewHashSetToSetPostfixTemplateTest extends PostfixTemplateTestCase {
@Override
protected @NotNull LightProjectDescriptor getProjectDescriptor() {
return JAVA_8;
}
@NotNull
@Override
protected String getSuffix() {
return "toSetNewHashSet";
}
public void testSimple() {
doTestCompletion(null);
}
public void testSimpleAsSet() {
doTestCompletion(null);
}
}

View File

@@ -1,24 +1,16 @@
/*
* Copyright 2000-2017 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-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.java.codeInsight.template.postfix.templates;
import com.intellij.JavaTestUtil;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.openapi.application.impl.NonBlockingReadActionImpl;
import com.intellij.testFramework.fixtures.LightJavaCodeInsightFixtureTestCase;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Locale;
import static com.intellij.codeInsight.template.impl.LiveTemplateCompletionContributor.setShowTemplatesInTests;
abstract public class PostfixTemplateTestCase extends LightJavaCodeInsightFixtureTestCase {
@Override
@@ -36,6 +28,23 @@ abstract public class PostfixTemplateTestCase extends LightJavaCodeInsightFixtur
myFixture.checkResultByFile(getTestName(true) + "_after.java", true);
}
protected void doTestCompletion(@Nullable String text) {
setShowTemplatesInTests(true, getTestRootDisposable());
myFixture.configureByFile(getTestName(true) + ".java");
LookupElement[] elements = myFixture.completeBasic();
if (text != null) {
for (LookupElement element : elements) {
if(element.getLookupString().toLowerCase(Locale.ROOT).contains(text.toLowerCase(Locale.ROOT))) {
myFixture.getLookup().setCurrentItem(element);
break;
}
}
}
myFixture.type('\n');
NonBlockingReadActionImpl.waitForAsyncTaskCompletion();
myFixture.checkResultByFile(getTestName(true) + "_after.java", true);
}
@Override
protected void setUp() throws Exception {
super.setUp();

View File

@@ -1759,6 +1759,7 @@ postfix.template.condition.boolean.name=boolean
postfix.template.condition.number.name=number
postfix.template.condition.not.primitive.type.name=not primitive type
postfix.template.condition.array.name=array
postfix.template.condition.array.reference.name=array of non-primitive types
inspection.redundant.unmodifiable.call.display.name=Redundant usage of the ''{0}'' wrapper
inspection.redundant.unmodifiable.call.description=Redundant usage of unmodifiable collection wrappers
inspection.redundant.unmodifiable.call.unwrap.argument.quickfix=Unwrap argument

View File

@@ -1,4 +1,4 @@
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInsight.lookup;
import com.intellij.openapi.util.TextRange;
@@ -342,7 +342,12 @@ public class LookupElementPresentation {
/**
* Indicates that some parts of the specified range will be highlighted according to an item pattern.
*/
HIGHLIGHT_MATCHED
HIGHLIGHT_MATCHED,
/**
* Will be gray
*/
GRAY
}
/**

View File

@@ -5614,6 +5614,7 @@ c:com.intellij.codeInsight.template.postfix.completion.PostfixTemplateLookupElem
- com.intellij.codeInsight.template.impl.CustomLiveTemplateLookupElement
- <init>(com.intellij.codeInsight.template.postfix.templates.PostfixLiveTemplate,com.intellij.codeInsight.template.postfix.templates.PostfixTemplate,java.lang.String,com.intellij.codeInsight.template.postfix.templates.PostfixTemplateProvider,Z):V
- expandTemplate(com.intellij.openapi.editor.Editor,com.intellij.psi.PsiFile):V
- getAllLookupStrings():java.util.Set
- getPostfixTemplate():com.intellij.codeInsight.template.postfix.templates.PostfixTemplate
- getProvider():com.intellij.codeInsight.template.postfix.templates.PostfixTemplateProvider
- renderElement(com.intellij.codeInsight.lookup.LookupElementPresentation):V

View File

@@ -54,7 +54,6 @@ import java.awt.*
import java.util.function.Supplier
import javax.swing.*
import javax.swing.border.EmptyBorder
import kotlin.concurrent.Volatile
import kotlin.math.max
class LookupCellRenderer(lookup: LookupImpl, editorComponent: JComponent) : ListCellRenderer<LookupElement> {
@@ -765,7 +764,10 @@ private fun renderItemNameDecoration(
TextAttributesEffectsBuilder.create().coverWith(EffectType.WAVE_UNDERSCORE, color).applyTo(newAttributes)
iterator.textAttributes = SimpleTextAttributes.fromTextAttributes(newAttributes)
}
if (decoration == LookupItemDecoration.GRAY) {
newAttributes.foregroundColor = UIUtil.getContextHelpForeground()
iterator.textAttributes = SimpleTextAttributes.fromTextAttributes(newAttributes)
}
// must be the last
if (decoration == LookupItemDecoration.HIGHLIGHT_MATCHED) {
iterator.textAttributes = SimpleTextAttributes(iterator.textAttributes.style, MATCHED_FOREGROUND_COLOR)

View File

@@ -4,6 +4,7 @@ package com.intellij.codeInsight.template.postfix.completion;
import com.intellij.codeInsight.lookup.LookupElementPresentation;
import com.intellij.codeInsight.template.CustomTemplateCallback;
import com.intellij.codeInsight.template.impl.CustomLiveTemplateLookupElement;
import com.intellij.codeInsight.template.postfix.templates.CustomizableLookupElementTemplate;
import com.intellij.codeInsight.template.postfix.templates.PostfixLiveTemplate;
import com.intellij.codeInsight.template.postfix.templates.PostfixTemplate;
import com.intellij.codeInsight.template.postfix.templates.PostfixTemplateProvider;
@@ -12,6 +13,9 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull;
import java.util.HashSet;
import java.util.Set;
public class PostfixTemplateLookupElement extends CustomLiveTemplateLookupElement {
private final @NotNull PostfixTemplate myTemplate;
private final @NotNull String myTemplateKey;
@@ -37,11 +41,24 @@ public class PostfixTemplateLookupElement extends CustomLiveTemplateLookupElemen
return myProvider;
}
@Override
public Set<String> getAllLookupStrings() {
Set<String> allLookupStrings = super.getAllLookupStrings();
if (myTemplate instanceof CustomizableLookupElementTemplate customizableRenderPresentation) {
allLookupStrings = new HashSet<>(allLookupStrings);
allLookupStrings.addAll(customizableRenderPresentation.getAllLookupStrings());
}
return allLookupStrings;
}
@Override
public void renderElement(@NotNull LookupElementPresentation presentation) {
super.renderElement(presentation);
presentation.setTypeText(myTemplate.getExample());
presentation.setTypeGrayed(true);
if (myTemplate instanceof CustomizableLookupElementTemplate customizableRenderPresentation) {
customizableRenderPresentation.renderElement(presentation);
}
}
@Override

View File

@@ -0,0 +1,16 @@
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
package com.intellij.codeInsight.template.postfix.templates;
import com.intellij.codeInsight.lookup.LookupElementPresentation;
import org.jetbrains.annotations.ApiStatus;
import org.jetbrains.annotations.NotNull;
import java.util.Collection;
@ApiStatus.Internal
@ApiStatus.Experimental
public interface CustomizableLookupElementTemplate {
void renderElement(@NotNull LookupElementPresentation presentation);
Collection<String> getAllLookupStrings();
}