From e8fc23793b1eb4c5ec084747e018da6c15202bc9 Mon Sep 17 00:00:00 2001 From: Tagir Valeev Date: Fri, 15 May 2026 17:45:23 +0200 Subject: [PATCH] IDEA-389301 [java-completion] JavaMethodHandleCompletionContributor -> JavaMethodHandleCompletionItemProvider (part of) Convert reflection completion to ModCommand API GitOrigin-RevId: 682a50d03da61d88cb6c7ace97aaf3c060bdbced --- .../resources/META-INF/JavaPlugin.xml | 4 +- .../modcommand/JavaModCompletionUtils.java | 7 +- ...vaMethodHandleCompletionItemProvider.java} | 114 ++++++++++-------- 3 files changed, 74 insertions(+), 51 deletions(-) rename java/java-impl/src/com/intellij/psi/impl/source/resolve/reference/impl/{JavaMethodHandleCompletionContributor.java => JavaMethodHandleCompletionItemProvider.java} (68%) diff --git a/java/java-backend/resources/META-INF/JavaPlugin.xml b/java/java-backend/resources/META-INF/JavaPlugin.xml index 6c7c94741cbf..e62023397a89 100644 --- a/java/java-backend/resources/META-INF/JavaPlugin.xml +++ b/java/java-backend/resources/META-INF/JavaPlugin.xml @@ -1144,8 +1144,8 @@ - + METHOD_HANDLE_FACTORY_NAMES = Set.of( @@ -81,12 +86,12 @@ public final class JavaMethodHandleCompletionContributor extends CompletionContr psiExpression().methodCallParameter(2, methodPattern(ArrayUtilRt.toStringArray(FIELD_HANDLE_FACTORY_NAMES)))); - private static @NotNull PsiMethodPattern methodPattern(String... methodNames) { + private static PsiMethodPattern methodPattern(String... methodNames) { return psiMethod().withName(methodNames).definedInClass(JAVA_LANG_INVOKE_METHOD_HANDLES_LOOKUP); } @Override - public void fillCompletionVariants(@NotNull CompletionParameters parameters, @NotNull CompletionResultSet result) { + public void provideItems(CompletionContext parameters, ModCompletionResult result) { final PsiElement position = parameters.getPosition(); if (!isInJavaContext(position)) { return; @@ -100,7 +105,7 @@ public final class JavaMethodHandleCompletionContributor extends CompletionContr } } - private static void addMethodHandleVariants(@NotNull PsiElement position, @NotNull Consumer result) { + private static void addMethodHandleVariants(PsiElement position, ModCompletionResult result) { final PsiMethodCallExpression methodCall = PsiTreeUtil.getParentOfType(position, PsiMethodCallExpression.class); if (methodCall != null) { final String methodName = methodCall.getMethodExpression().getReferenceName(); @@ -123,23 +128,23 @@ public final class JavaMethodHandleCompletionContributor extends CompletionContr } } - private static void addConstructorSignatures(@NotNull ReflectiveClass ownerClass, - @NotNull PsiElement context, - @NotNull Consumer result) { + private static void addConstructorSignatures(ReflectiveClass ownerClass, + PsiElement context, + ModCompletionResult result) { final PsiMethod[] constructors = ownerClass.getPsiClass().getConstructors(); if (constructors.length != 0) { lookupMethodTypes(Arrays.stream(constructors), context, result); } else { - result.consume(lookupSignature(ReflectiveSignature.NO_ARGUMENT_CONSTRUCTOR_SIGNATURE, context)); + result.accept(lookupSignature(ReflectiveSignature.NO_ARGUMENT_CONSTRUCTOR_SIGNATURE, context)); } } - private static void addMethodSignatures(@NotNull ReflectiveClass psiClass, - @NotNull String methodName, + private static void addMethodSignatures(ReflectiveClass psiClass, + String methodName, boolean isStaticExpected, - @NotNull PsiElement context, - @NotNull Consumer result) { + PsiElement context, + ModCompletionResult result) { final PsiMethod[] methods = psiClass.getPsiClass().findMethodsByName(methodName, false); if (methods.length != 0) { final Stream methodStream = Arrays.stream(methods) @@ -148,18 +153,18 @@ public final class JavaMethodHandleCompletionContributor extends CompletionContr } } - private static void lookupMethodTypes(@NotNull Stream methods, - @NotNull PsiElement context, - @NotNull Consumer result) { + private static void lookupMethodTypes(Stream methods, + PsiElement context, + ModCompletionResult result) { methods .map(JavaReflectionReferenceUtil::getMethodSignature) .filter(Objects::nonNull) .sorted(ReflectiveSignature::compareTo) .map(signature -> lookupSignature(signature, context)) - .forEach(result::consume); + .forEach(result); } - private static @NotNull LookupElement lookupSignature(@NotNull ReflectiveSignature signature, @NotNull PsiElement context) { + private static ModCompletionItem lookupSignature(ReflectiveSignature signature, PsiElement context) { final String expressionText = getMethodTypeExpressionText(signature); final PsiElementFactory factory = JavaPsiFacade.getElementFactory(context.getProject()); final PsiExpression expression = factory.createExpressionFromText(expressionText, context); @@ -168,10 +173,10 @@ public final class JavaMethodHandleCompletionContributor extends CompletionContr final String presentableText = PsiNameHelper.getShortClassName(JAVA_LANG_INVOKE_METHOD_TYPE) + "." + METHOD_TYPE + shortTypes; final String lookupText = METHOD_TYPE + signature.getText(true, PsiNameHelper::getShortClassName); - return lookupExpression(expression, IconManager.getInstance().getPlatformIcon(com.intellij.ui.PlatformIcons.Method), presentableText, lookupText); + return lookupExpression(expression, IconManager.getInstance().getPlatformIcon(PlatformIcons.Method), presentableText, lookupText); } - private static void addFieldHandleVariants(@NotNull PsiElement position, @NotNull Consumer result) { + private static void addFieldHandleVariants(PsiElement position, ModCompletionResult result) { final PsiMethodCallExpression methodCall = PsiTreeUtil.getParentOfType(position, PsiMethodCallExpression.class); if (methodCall != null) { final String methodName = methodCall.getMethodExpression().getReferenceName(); @@ -190,10 +195,10 @@ public final class JavaMethodHandleCompletionContributor extends CompletionContr } } - private static void addFieldType(@NotNull ReflectiveClass ownerClass, - @NotNull String fieldName, - @NotNull PsiElement context, - @NotNull Consumer result) { + private static void addFieldType(ReflectiveClass ownerClass, + String fieldName, + PsiElement context, + ModCompletionResult result) { final PsiField field = ownerClass.getPsiClass().findFieldByName(fieldName, false); if (field != null) { final String typeText = getTypeText(field.getType()); @@ -201,22 +206,37 @@ public final class JavaMethodHandleCompletionContributor extends CompletionContr final PsiExpression expression = factory.createExpressionFromText(typeText + ".class", context); final String shortType = PsiNameHelper.getShortClassName(typeText); - result.consume(lookupExpression(expression, IconManager.getInstance().getPlatformIcon(com.intellij.ui.PlatformIcons.Class), shortType + ".class", shortType)); + result.accept(lookupExpression(expression, IconManager.getInstance().getPlatformIcon(PlatformIcons.Class), shortType + ".class", shortType)); } } - private static @NotNull LookupElement lookupExpression(@NotNull PsiExpression expression, - @Nullable Icon icon, - @NotNull String presentableText, - @NotNull String lookupText) { - final LookupElement element = new ExpressionLookupItem(expression, icon, presentableText, lookupText) { - @Override - public void handleInsert(@NotNull InsertionContext context) { - context.getDocument().deleteString(context.getStartOffset(), context.getTailOffset()); - context.commitDocument(); - replaceText(context, getObject().getText()); - } - }; - return PrioritizedLookupElement.withPriority(element, 1); + private static ModCompletionItem lookupExpression(PsiExpression expression, + @Nullable Icon icon, + @NlsSafe String presentableText, + String lookupText) { + String text = expression.getText(); + return new CommonCompletionItem(lookupText) + .withPresentation(new ModCompletionItemPresentation(MarkupText.plainText(presentableText)) + .withMainIcon(() -> icon) + .withDetailText(JavaModCompletionUtils.typeMarkup(expression.getType()))) + .withPriority(1) + .withAdditionalUpdater(((completionStart, updater) -> { + Document document = updater.getDocument(); + document.deleteString(completionStart, updater.getCaretOffset()); + PsiDocumentManager.getInstance(updater.getProject()).commitDocument(document); + PsiElement newElement = PsiUtilCore.getElementAtOffset(updater.getPsiFile(), completionStart); + PsiElement params = newElement.getParent().getParent(); + int end = params.getTextRange().getEndOffset() - 1; + int start = Math.min(newElement.getTextRange().getEndOffset(), end); + + document.replaceString(start, end, text); + PsiDocumentManager.getInstance(updater.getProject()).commitDocument(document); + shortenArgumentsClassReferences(updater); + })); + } + + @Override + public boolean isEnabled() { + return true; } }