mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[java-completion] IDEA-363488 Completion for similar methods: propose more often
- restart if there are not matched items, but tags can be used GitOrigin-RevId: 9620630c72759450e0c4b2c375da4784bee8f088
This commit is contained in:
committed by
intellij-monorepo-bot
parent
691b94da97
commit
732018d4f2
@@ -482,6 +482,13 @@ public final class JavaCompletionContributor extends CompletionContributor imple
|
||||
}
|
||||
else {
|
||||
refSuggestions = completeReference(parameters, parentRef, session, expectedInfos, matcher::prefixMatches);
|
||||
if (refSuggestions
|
||||
.stream()
|
||||
.map(lookupElement -> MethodTags.collectTags(lookupElement, matcher::prefixMatches))
|
||||
.anyMatch(t -> t != null && !t.isEmpty())) {
|
||||
//it is possible to propose some tags, let's try to do this
|
||||
_result.restartCompletionWhenNothingMatches();
|
||||
}
|
||||
}
|
||||
}
|
||||
List<LookupElement> filtered = filterReferenceSuggestions(parameters, expectedInfos, refSuggestions);
|
||||
|
||||
@@ -8,6 +8,7 @@ import com.intellij.codeInsight.lookup.impl.LookupCellRenderer;
|
||||
import com.intellij.java.JavaBundle;
|
||||
import com.intellij.openapi.util.Condition;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.text.Strings;
|
||||
import com.intellij.psi.CommonClassNames;
|
||||
import com.intellij.psi.PsiClass;
|
||||
import com.intellij.psi.PsiElement;
|
||||
@@ -36,20 +37,28 @@ public final class MethodTags {
|
||||
if (matcher.value(element.getLookupString())) {
|
||||
return null;
|
||||
}
|
||||
Set<String> tags = collectTags(element, matcher);
|
||||
if (tags == null) return null;
|
||||
if (tags.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return new TagLookupElementDecorator(element, tags, prefix, completionType == CompletionType.SMART);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Set of tags, which can be used for this element, can return null if an element is not for PsiMember
|
||||
*/
|
||||
static @Nullable Set<String> collectTags(@NotNull LookupElement element, @NotNull Condition<? super String> matcher) {
|
||||
String lookupString = element.getLookupString();
|
||||
PsiElement psiElement = element.getPsiElement();
|
||||
if (!(psiElement instanceof PsiMember psiMember)) {
|
||||
return null;
|
||||
}
|
||||
PsiClass psiClass = psiMember.getContainingClass();
|
||||
Set<String> tags = tags(lookupString).stream()
|
||||
return tags(lookupString).stream()
|
||||
.filter(t -> matcher.value(t.name()) && t.matcher().test(psiClass))
|
||||
.map(t -> t.name())
|
||||
.collect(Collectors.toSet());
|
||||
if (tags.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
return new TagLookupElementDecorator(element, tags, prefix, completionType == CompletionType.SMART);
|
||||
}
|
||||
|
||||
@ApiStatus.Experimental
|
||||
@@ -89,7 +98,22 @@ public final class MethodTags {
|
||||
@Override
|
||||
public void renderElement(@NotNull LookupElementPresentation presentation) {
|
||||
super.renderElement(presentation);
|
||||
if (myTags.size() == 1) {
|
||||
String itemText = presentation.getItemText();
|
||||
String tailText = presentation.getTailText();
|
||||
if (itemText != null && (tailText == null || tailText.isBlank() || (tailText.startsWith("(") && tailText.endsWith(")")))) {
|
||||
if (tailText == null) {
|
||||
tailText = "";
|
||||
}
|
||||
String tagMessage = JavaBundle.message("java.completion.tag", myTags.size());
|
||||
String fullItemText = itemText + tailText + " " + tagMessage + " ";
|
||||
String allTags = Strings.join(myTags, ", ");
|
||||
fullItemText += allTags;
|
||||
presentation.setItemText(fullItemText);
|
||||
presentation.decorateItemTextRange(new TextRange(itemText.length(), itemText.length() + tailText.length() + 1 + tagMessage.length()),
|
||||
LookupElementPresentation.LookupItemDecoration.GRAY);
|
||||
presentation.setTailText("");
|
||||
}
|
||||
else if (myTags.size() == 1) {
|
||||
presentation.appendTailText(" " + JavaBundle.message("java.completion.tag", myTags.size()) + " ", true);
|
||||
int startOffset = getStartOffset(presentation);
|
||||
String text = myTags.iterator().next();
|
||||
|
||||
+62
-39
@@ -1837,7 +1837,7 @@ public class NormalCompletionTest extends NormalCompletionTestCase {
|
||||
myFixture.complete(CompletionType.BASIC, 2);
|
||||
myFixture.checkResult("""
|
||||
import foo.myClass;
|
||||
|
||||
|
||||
class Foo extends myClass
|
||||
""");
|
||||
}
|
||||
@@ -1865,7 +1865,7 @@ public class NormalCompletionTest extends NormalCompletionTestCase {
|
||||
void foo(Foo f) {
|
||||
f.<caret>
|
||||
}
|
||||
}
|
||||
}
|
||||
""");
|
||||
myFixture.completeBasic();
|
||||
assertFalse(myFixture.getLookupElementStrings().contains("Inner"));
|
||||
@@ -1929,7 +1929,7 @@ public class NormalCompletionTest extends NormalCompletionTestCase {
|
||||
UIUtil.dispatchAllInvocationEvents();
|
||||
myFixture.checkResult("""
|
||||
class Foo {int i;
|
||||
|
||||
|
||||
public int getI() {
|
||||
return this.i;
|
||||
}
|
||||
@@ -2836,28 +2836,28 @@ public class NormalCompletionTest extends NormalCompletionTestCase {
|
||||
public void testPackagePrivateConstantInInterface() {
|
||||
myFixture.addClass("""
|
||||
package com.example.x;
|
||||
|
||||
|
||||
public interface Exposed extends PackPrivate {
|
||||
int value();
|
||||
}
|
||||
""");
|
||||
myFixture.addClass("""
|
||||
package com.example.x;
|
||||
|
||||
|
||||
interface PackPrivate {
|
||||
Exposed CONSTANT = () -> 5;
|
||||
}
|
||||
""");
|
||||
myFixture.configureByText("Main.java", """
|
||||
package com.example;
|
||||
|
||||
|
||||
import com.example.x.Exposed;
|
||||
|
||||
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
test(CONST<caret>);
|
||||
}
|
||||
|
||||
|
||||
private static void test(Exposed exposed) {
|
||||
}
|
||||
}""");
|
||||
@@ -2865,14 +2865,14 @@ public class NormalCompletionTest extends NormalCompletionTestCase {
|
||||
myFixture.type('\n');
|
||||
myFixture.checkResult("""
|
||||
package com.example;
|
||||
|
||||
|
||||
import com.example.x.Exposed;
|
||||
|
||||
|
||||
public class Main {
|
||||
public static void main(String[] args) {
|
||||
test(Exposed.CONSTANT);
|
||||
}
|
||||
|
||||
|
||||
private static void test(Exposed exposed) {
|
||||
}
|
||||
}""");
|
||||
@@ -2894,10 +2894,10 @@ public class NormalCompletionTest extends NormalCompletionTestCase {
|
||||
public void testEnumMapNoTypeParams() {
|
||||
myFixture.configureByText("Test.java", """
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
public abstract class SuperClass {
|
||||
enum X {A, B, C}
|
||||
|
||||
|
||||
void run() {
|
||||
Map<X, String> map = new EnumM<caret>
|
||||
}
|
||||
@@ -2908,10 +2908,10 @@ public class NormalCompletionTest extends NormalCompletionTestCase {
|
||||
myFixture.checkResult("""
|
||||
import java.util.EnumMap;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
public abstract class SuperClass {
|
||||
enum X {A, B, C}
|
||||
|
||||
|
||||
void run() {
|
||||
Map<X, String> map = new EnumMap<>()
|
||||
}
|
||||
@@ -2923,9 +2923,9 @@ public class NormalCompletionTest extends NormalCompletionTestCase {
|
||||
Registry.get("java.completion.methods.use.tags").setValue(true, getTestRootDisposable());
|
||||
myFixture.configureByText("Test.java", """
|
||||
import java.util.HashSet;
|
||||
|
||||
|
||||
public abstract class SuperClass {
|
||||
|
||||
|
||||
void run() {
|
||||
HashSet<Object> objects = new HashSet<>();
|
||||
objects.len<caret>;
|
||||
@@ -2936,9 +2936,9 @@ public class NormalCompletionTest extends NormalCompletionTestCase {
|
||||
myFixture.type('\n');
|
||||
myFixture.checkResult("""
|
||||
import java.util.HashSet;
|
||||
|
||||
|
||||
public abstract class SuperClass {
|
||||
|
||||
|
||||
void run() {
|
||||
HashSet<Object> objects = new HashSet<>();
|
||||
objects.size();
|
||||
@@ -2952,14 +2952,14 @@ public class NormalCompletionTest extends NormalCompletionTestCase {
|
||||
Registry.get("java.completion.methods.use.tags").setValue(true, getTestRootDisposable());
|
||||
myFixture.configureByText("Test.java", """
|
||||
import java.util.HashSet;
|
||||
|
||||
|
||||
public abstract class SuperClass {
|
||||
|
||||
|
||||
void run() {
|
||||
HashSet<Object> objects = new HashSet<>();
|
||||
objects.len<caret>;
|
||||
}
|
||||
|
||||
|
||||
static void len(HashSet<Object> o){}
|
||||
}
|
||||
""");
|
||||
@@ -2967,14 +2967,14 @@ public class NormalCompletionTest extends NormalCompletionTestCase {
|
||||
myFixture.type('\n');
|
||||
myFixture.checkResult("""
|
||||
import java.util.HashSet;
|
||||
|
||||
|
||||
public abstract class SuperClass {
|
||||
|
||||
|
||||
void run() {
|
||||
HashSet<Object> objects = new HashSet<>();
|
||||
objects.size();
|
||||
}
|
||||
|
||||
|
||||
static void len(HashSet<Object> o){}
|
||||
}
|
||||
""");
|
||||
@@ -2985,9 +2985,9 @@ public class NormalCompletionTest extends NormalCompletionTestCase {
|
||||
Registry.get("java.completion.methods.use.tags").setValue(true, getTestRootDisposable());
|
||||
myFixture.configureByText("Test.java", """
|
||||
import java.util.HashSet;
|
||||
|
||||
|
||||
public abstract class SuperClass {
|
||||
|
||||
|
||||
void run() {
|
||||
HashSet<Object> objects = new HashSet<>();
|
||||
objects.le<caret>;
|
||||
@@ -3001,6 +3001,29 @@ public class NormalCompletionTest extends NormalCompletionTestCase {
|
||||
assertTrue(ContainerUtil.exists(lookupElements, t -> t.getLookupString().equals("size")));
|
||||
}
|
||||
|
||||
@NeedsIndex.Full
|
||||
public void testTagAddInvocationRestart() {
|
||||
Registry.get("java.completion.methods.use.tags").setValue(true, getTestRootDisposable());
|
||||
myFixture.configureByText("Test.java", """
|
||||
import java.util.HashSet;
|
||||
|
||||
public abstract class SuperClass {
|
||||
|
||||
void run() {
|
||||
HashSet<Object> objects = new HashSet<>();
|
||||
objects.<caret>;
|
||||
}
|
||||
}
|
||||
""");
|
||||
myFixture.complete(CompletionType.BASIC, 1);
|
||||
myFixture.type("l");
|
||||
myFixture.type("e");
|
||||
myFixture.type("n");
|
||||
myFixture.type("g");
|
||||
myFixture.type("t");
|
||||
assertTrue(ContainerUtil.exists(myFixture.getLookupElements(), t -> t.getLookupString().equals("size")));
|
||||
}
|
||||
|
||||
@NeedsIndex.Full
|
||||
public void testResolveToSubclassMethod() {
|
||||
myFixture.configureByText("Test.java", """
|
||||
@@ -3107,9 +3130,9 @@ public class NormalCompletionTest extends NormalCompletionTestCase {
|
||||
public void testNestedImplicitClass() {
|
||||
myFixture.configureByText("Test.java", """
|
||||
public static class NestedClass{
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
NestedCla<caret>
|
||||
}
|
||||
@@ -3117,9 +3140,9 @@ public class NormalCompletionTest extends NormalCompletionTestCase {
|
||||
myFixture.complete(CompletionType.BASIC);
|
||||
myFixture.checkResult("""
|
||||
public static class NestedClass{
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static void main(String[] args) {
|
||||
NestedClass
|
||||
}
|
||||
@@ -3132,14 +3155,14 @@ public class NormalCompletionTest extends NormalCompletionTestCase {
|
||||
public static class Nested2ClassMore {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public void main(String[] args) {
|
||||
Nested nested = new Nested();
|
||||
}
|
||||
|
||||
|
||||
public void t(Nested2ClassMo<caret> nested2) {
|
||||
|
||||
|
||||
}
|
||||
""");
|
||||
myFixture.complete(CompletionType.BASIC);
|
||||
@@ -3149,14 +3172,14 @@ public class NormalCompletionTest extends NormalCompletionTestCase {
|
||||
public static class Nested2ClassMore {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public void main(String[] args) {
|
||||
Nested nested = new Nested();
|
||||
}
|
||||
|
||||
|
||||
public void t(Nested.Nested2ClassMore nested2) {
|
||||
|
||||
|
||||
}
|
||||
"""); }
|
||||
|
||||
|
||||
Reference in New Issue
Block a user