mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-04-19 21:11:28 +07:00
[java-completion] IDEA-314367. Completion for similar methods
GitOrigin-RevId: ccce34749357dbd8b01625cc4b8322ae50445cf4
This commit is contained in:
committed by
intellij-monorepo-bot
parent
bfa4d04aca
commit
7129c6a6e2
@@ -25,7 +25,6 @@ import com.intellij.java.JavaBundle;
|
||||
import com.intellij.openapi.project.DumbAware;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.registry.Registry;
|
||||
import com.intellij.openapi.util.text.MethodTags;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.*;
|
||||
import com.intellij.psi.filters.ElementFilter;
|
||||
@@ -150,7 +149,15 @@ public class JavaNoVariantsDelegator extends CompletionContributor implements Du
|
||||
@Nullable
|
||||
private static LookupElement wrapLookup(@NotNull LookupElement element, @NotNull PrefixMatcher matcher) {
|
||||
String lookupString = element.getLookupString();
|
||||
Set<String> tags = MethodTags.tags(lookupString).stream().filter(t -> matcher.prefixMatches(t)).collect(Collectors.toSet());
|
||||
PsiElement psiElement = element.getPsiElement();
|
||||
if (!(psiElement instanceof PsiMember psiMember)) {
|
||||
return null;
|
||||
}
|
||||
PsiClass psiClass = psiMember.getContainingClass();
|
||||
Set<String> tags = MethodTags.tags(lookupString).stream()
|
||||
.filter(t -> matcher.prefixMatches(t.getName()) && t.getMatcher().test(psiClass))
|
||||
.map(t->t.getName())
|
||||
.collect(Collectors.toSet());
|
||||
if (tags.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
@@ -316,9 +323,9 @@ public class JavaNoVariantsDelegator extends CompletionContributor implements Du
|
||||
if (myMatcher.prefixMatches(name)) {
|
||||
return true;
|
||||
}
|
||||
Set<String> tags = MethodTags.tags(name);
|
||||
for (String tag : tags) {
|
||||
if (myMatcher.prefixMatches(tag)) {
|
||||
Set<MethodTags.Tag> tags = MethodTags.tags(name);
|
||||
for (MethodTags.Tag tag : tags) {
|
||||
if (myMatcher.prefixMatches(tag.getName())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -334,6 +341,7 @@ public class JavaNoVariantsDelegator extends CompletionContributor implements Du
|
||||
|
||||
static class TagLookupElementDecorator extends LookupElementDecorator<LookupElement> {
|
||||
|
||||
@NotNull
|
||||
private final Set<String> myTags;
|
||||
|
||||
protected TagLookupElementDecorator(@NotNull LookupElement delegate, @NotNull Set<String> tags) {
|
||||
@@ -341,6 +349,7 @@ public class JavaNoVariantsDelegator extends CompletionContributor implements Du
|
||||
myTags = tags;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public Set<String> getTags() {
|
||||
return myTags;
|
||||
}
|
||||
@@ -355,10 +364,20 @@ public class JavaNoVariantsDelegator extends CompletionContributor implements Du
|
||||
@Override
|
||||
public void renderElement(@NotNull LookupElementPresentation presentation) {
|
||||
super.renderElement(presentation);
|
||||
if (!myTags.isEmpty()) {
|
||||
if (myTags.size()==1) {
|
||||
presentation.appendTailText(" " + JavaBundle.message("java.completion.tag") + " ", true);
|
||||
presentation.appendTailText(myTags.iterator().next(), true, true);
|
||||
}
|
||||
else if (myTags.size() > 1) {
|
||||
presentation.appendTailText(" " + JavaBundle.message("java.completion.tags") + " ", true);
|
||||
Iterator<String> iterator = myTags.iterator();
|
||||
String firstTag = iterator.next();
|
||||
presentation.appendTailText(firstTag, true, true);
|
||||
while (iterator.hasNext()) {
|
||||
presentation.appendTailText(", ", true);
|
||||
presentation.appendTailText(iterator.next(), true, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,128 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.codeInsight.completion;
|
||||
|
||||
import com.intellij.psi.CommonClassNames;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.util.InheritanceUtil;
|
||||
import com.intellij.util.containers.ContainerUtil;
|
||||
import com.intellij.util.text.NameUtilCore;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import static com.intellij.codeInsight.completion.MethodTags.Tag.*;
|
||||
|
||||
public class MethodTags {
|
||||
|
||||
@ApiStatus.Experimental
|
||||
@NotNull
|
||||
public static Set<Tag> tags(@Nullable String referenceName) {
|
||||
if (referenceName == null) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
String[] strings = NameUtilCore.nameToWords(referenceName);
|
||||
if (strings.length == 0) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
Tag[] canBeFirst = getTags(strings[0]);
|
||||
Set<Tag> result = new HashSet<>();
|
||||
for (Tag firstPart : canBeFirst) {
|
||||
StringJoiner joiner = new StringJoiner("");
|
||||
joiner.add(firstPart.name);
|
||||
for (int i = 1; i < strings.length; i++) {
|
||||
String string = strings[i];
|
||||
joiner.add(string);
|
||||
}
|
||||
result.add(of(joiner.toString(), firstPart.matcher));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private static Tag[] getTags(String string) {
|
||||
return switch (string) {
|
||||
case "add" -> new Tag[]{of("put", childOf(CommonClassNames.JAVA_LANG_ITERABLE)),
|
||||
of("sum", childOf("java.math.BigDecimal", "java.math.BigInteger")),
|
||||
of("plus", childOf("java.math.BigDecimal", "java.math.BigInteger"))};
|
||||
case "append" -> anyFrom("add");
|
||||
case "apply" -> anyFrom("invoke", "do", "call");
|
||||
case "assert" -> anyFrom("expect", "verify", "test");
|
||||
case "build" -> anyFrom("create", "make", "generate");
|
||||
case "call" -> anyFrom("execute", "run");
|
||||
case "check" -> anyFrom("test", "match");
|
||||
case "count" -> anyFrom("size", "length");
|
||||
case "convert" -> anyFrom("map");
|
||||
case "create" -> anyFrom("build", "make", "generate");
|
||||
case "delete" -> anyFrom("remove");
|
||||
case "do" -> anyFrom("run", "execute", "call");
|
||||
case "execute" -> anyFrom("run", "do", "call");
|
||||
case "expect" -> anyFrom("verify", "assert", "test");
|
||||
case "from" -> anyFrom("of", "parse");
|
||||
case "generate" -> anyFrom("create", "build");
|
||||
case "invoke" -> anyFrom("apply", "do", "call");
|
||||
case "has" -> anyFrom("contains", "check");
|
||||
case "length" -> anyFrom("size", "count");
|
||||
case "load" -> anyFrom("read");
|
||||
case "match" -> anyFrom("test", "check");
|
||||
case "of" -> anyFrom("parse", "from");
|
||||
case "parse" -> anyFrom("of", "from");
|
||||
case "perform" -> anyFrom("execute", "run", "do");
|
||||
case "persist" -> anyFrom("save");
|
||||
case "print" -> anyFrom("write");
|
||||
case "put" -> new Tag[]{of("add", childOf(CommonClassNames.JAVA_UTIL_MAP))};
|
||||
case "remove" -> anyFrom("delete");
|
||||
case "run" -> anyFrom("start", "execute", "call");
|
||||
case "save" -> anyFrom("persist", "write");
|
||||
case "size" -> anyFrom("length", "count");
|
||||
case "start" -> anyFrom("call", "execute", "run");
|
||||
case "subtract" -> anyFrom("minus");
|
||||
case "test" -> anyFrom("check", "match");
|
||||
case "validate" -> anyFrom("test", "check");
|
||||
case "verify" -> anyFrom("expect", "assert", "test");
|
||||
case "write" -> anyFrom("print");
|
||||
default -> anyFrom();
|
||||
};
|
||||
}
|
||||
|
||||
static class Tag {
|
||||
|
||||
@NotNull
|
||||
private final String name;
|
||||
|
||||
@NotNull
|
||||
private final Predicate<PsiClass> matcher;
|
||||
|
||||
private Tag(@NotNull String name, @NotNull Predicate<PsiClass> matcher) {
|
||||
this.name = name;
|
||||
this.matcher = matcher;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
Predicate<PsiClass> getMatcher() {
|
||||
return matcher;
|
||||
}
|
||||
|
||||
static Tag of(@NotNull String name, @NotNull Predicate<PsiClass> matcher) {
|
||||
return new Tag(name, matcher);
|
||||
}
|
||||
|
||||
static Predicate<PsiClass> any() {
|
||||
return t -> true;
|
||||
}
|
||||
|
||||
static Predicate<PsiClass> childOf(String... classes) {
|
||||
return psiClass -> ContainerUtil.exists(classes, clazz -> InheritanceUtil.isInheritor(psiClass, clazz));
|
||||
}
|
||||
|
||||
public static Tag[] anyFrom(String... names) {
|
||||
return Arrays.stream(names).map(name -> of(name, any())).toArray(Tag[]::new);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
class C {
|
||||
void test(java.util.List<String> list) {
|
||||
list::fi<caret>
|
||||
list::ma<caret>
|
||||
}
|
||||
}
|
||||
@@ -1810,3 +1810,4 @@ vm.option.description.experimental=Experimental
|
||||
hint.text.not.valid.java.identifier=Not a valid Java identifier
|
||||
command.name.replace.type=Replace Type
|
||||
java.completion.tag=Tag:
|
||||
java.completion.tags=Tags:
|
||||
|
||||
@@ -1,117 +0,0 @@
|
||||
// Copyright 2000-2023 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.openapi.util.text;
|
||||
|
||||
import com.intellij.util.ArrayUtil;
|
||||
import com.intellij.util.text.NameUtilCore;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.StringJoiner;
|
||||
|
||||
public class MethodTags {
|
||||
@NotNull
|
||||
public static Set<String> tags(@Nullable String referenceName) {
|
||||
if (referenceName == null) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
String[] strings = NameUtilCore.nameToWords(referenceName);
|
||||
if (strings.length == 0) {
|
||||
return Collections.emptySet();
|
||||
}
|
||||
String[] canBeFirst = getTags(strings[0]);
|
||||
Set<String> result = new HashSet<>();
|
||||
for (String firstPart : canBeFirst) {
|
||||
StringJoiner joiner = new StringJoiner("");
|
||||
joiner.add(firstPart);
|
||||
for (int i = 1; i < strings.length; i++) {
|
||||
String string = strings[i];
|
||||
joiner.add(string);
|
||||
}
|
||||
result.add(joiner.toString());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@SuppressWarnings("DuplicateBranchesInSwitch")
|
||||
private static String[] getTags(String string) {
|
||||
switch (string) {
|
||||
case "add":
|
||||
return new String[]{"put", "sum"};
|
||||
case "append":
|
||||
return new String[]{"add"};
|
||||
case "apply":
|
||||
return new String[]{"invoke", "do", "call"};
|
||||
case "assert":
|
||||
return new String[]{"expect", "verify", "test"};
|
||||
case "call":
|
||||
return new String[]{"execute", "run"};
|
||||
case "check":
|
||||
return new String[]{"test", "match"};
|
||||
case "count":
|
||||
return new String[]{"size", "length"};
|
||||
case "convert":
|
||||
return new String[]{"map"};
|
||||
case "create":
|
||||
return new String[]{"build", "make", "generate"};
|
||||
case "delete":
|
||||
return new String[]{"remove"};
|
||||
case "do":
|
||||
return new String[]{"run", "execute", "call"};
|
||||
case "execute":
|
||||
return new String[]{"run", "do", "call"};
|
||||
case "expect":
|
||||
return new String[]{"verify", "assert", "test"};
|
||||
case "from":
|
||||
return new String[]{"of", "parse"};
|
||||
case "generate":
|
||||
return new String[]{"create", "build"};
|
||||
case "invoke":
|
||||
return new String[]{"apply", "do", "call"};
|
||||
case "has":
|
||||
return new String[]{"contains", "check"};
|
||||
case "length":
|
||||
return new String[]{"size"};
|
||||
case "load":
|
||||
return new String[]{"read"};
|
||||
case "match":
|
||||
return new String[]{"test", "check"};
|
||||
case "minus":
|
||||
return new String[]{"subtract"};
|
||||
case "of":
|
||||
return new String[]{"parse", "from"};
|
||||
case "parse":
|
||||
return new String[]{"of", "from"};
|
||||
case "perform":
|
||||
return new String[]{"execute", "run", "do"};
|
||||
case "persist":
|
||||
return new String[]{"save"};
|
||||
case "print":
|
||||
return new String[]{"write"};
|
||||
case "put":
|
||||
return new String[]{"add"};
|
||||
case "remove":
|
||||
return new String[]{"delete"};
|
||||
case "run":
|
||||
return new String[]{"start", "execute", "call"};
|
||||
case "save":
|
||||
return new String[]{"persist", "write"};
|
||||
case "size":
|
||||
return new String[]{"length"};
|
||||
case "start":
|
||||
return new String[]{"call", "execute", "run"};
|
||||
case "test":
|
||||
return new String[]{"check", "match"};
|
||||
case "validate":
|
||||
return new String[]{"test", "check"};
|
||||
case "verify":
|
||||
return new String[]{"expect", "assert", "test"};
|
||||
case "write":
|
||||
return new String[]{"print"};
|
||||
default:
|
||||
return ArrayUtil.EMPTY_STRING_ARRAY;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user