From 2ef829470b266ff3d38f836e0f5072b589e85f1e Mon Sep 17 00:00:00 2001 From: Peter Gromov Date: Tue, 4 Feb 2020 11:50:23 +0100 Subject: [PATCH] IDEA-231373 Treat overloaded method calls as empty so IDEA doesn't introduce spaces within the parentheses GitOrigin-RevId: eefb114de7e4f5864d1a3e1524417f1c93d319cc --- .../completion/ConstructorInsertHandler.java | 21 ++++------ .../completion/JavaCompletionUtil.java | 18 ++++---- .../completion/JavaMethodCallElement.java | 6 +-- .../completion/SlowerTypeConversions.java | 2 +- .../TypeArgumentCompletionProvider.java | 3 +- .../SpaceWithinNonEmptyCallParens-out.java | 8 ++++ .../style/SpaceWithinNonEmptyCallParens.java | 8 ++++ .../completion/CompletionStyleTest.java | 12 ++++++ .../util/MethodParenthesesHandler.java | 41 +++++++++++-------- .../lang/completion/GroovyInsertHandler.java | 8 ++-- 10 files changed, 83 insertions(+), 44 deletions(-) create mode 100644 java/java-tests/testData/codeInsight/completion/style/SpaceWithinNonEmptyCallParens-out.java create mode 100644 java/java-tests/testData/codeInsight/completion/style/SpaceWithinNonEmptyCallParens.java diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/ConstructorInsertHandler.java b/java/java-impl/src/com/intellij/codeInsight/completion/ConstructorInsertHandler.java index 84f569ef0c13..fa9da310beb6 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/ConstructorInsertHandler.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/ConstructorInsertHandler.java @@ -3,6 +3,7 @@ package com.intellij.codeInsight.completion; import com.intellij.codeInsight.ExpectedTypeInfo; import com.intellij.codeInsight.ExpectedTypesProvider; +import com.intellij.codeInsight.completion.util.MethodParenthesesHandler; import com.intellij.codeInsight.generation.GenerateMembersUtil; import com.intellij.codeInsight.generation.OverrideImplementExploreUtil; import com.intellij.codeInsight.generation.OverrideImplementUtil; @@ -34,6 +35,8 @@ import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiTypesUtil; import com.intellij.psi.util.PsiUtilCore; import com.intellij.util.IncorrectOperationException; +import com.intellij.util.ThreeState; +import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.Contract; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -238,7 +241,8 @@ public class ConstructorInsertHandler implements InsertHandler resolveHelper.isAccessible(c, place, null))); } @Nullable diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java index d6884c72b873..b494c2361402 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaCompletionUtil.java @@ -43,6 +43,7 @@ import com.intellij.ui.JBColor; import com.intellij.util.IncorrectOperationException; import com.intellij.util.ObjectUtils; import com.intellij.util.PairFunction; +import com.intellij.util.ThreeState; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.JBIterable; import com.siyeh.ig.psiutils.SideEffectChecker; @@ -738,13 +739,13 @@ public class JavaCompletionUtil { @NotNull LookupElement item, boolean overloadsMatter, boolean hasParams) { - insertParentheses(context, item, overloadsMatter, hasParams, false); + insertParentheses(context, item, overloadsMatter, ThreeState.fromBoolean(hasParams), false); } public static void insertParentheses(@NotNull InsertionContext context, @NotNull LookupElement item, boolean overloadsMatter, - boolean hasParams, + ThreeState hasParams, // UNSURE if providing no arguments is a valid situation final boolean forceClosingParenthesis) { final Editor editor = context.getEditor(); final char completionChar = context.getCompletionChar(); @@ -761,24 +762,25 @@ public class JavaCompletionUtil { } if (hasTail) { - hasParams = false; + hasParams = ThreeState.NO; } final boolean needRightParenth = forceClosingParenthesis || !smart && (CodeInsightSettings.getInstance().AUTOINSERT_PAIR_BRACKET || - !hasParams && completionChar != '('); + hasParams == ThreeState.NO && completionChar != '('); context.commitDocument(); final CommonCodeStyleSettings styleSettings = CompletionStyleUtil.getCodeStyleSettings(context); final PsiElement elementAt = file.findElementAt(context.getStartOffset()); if (elementAt == null || !(elementAt.getParent() instanceof PsiMethodReferenceExpression)) { - final boolean hasParameters = hasParams; - final boolean spaceBetweenParentheses = styleSettings.SPACE_WITHIN_METHOD_CALL_PARENTHESES && hasParams; + ThreeState hasParameters = hasParams; + boolean spaceBetweenParentheses = hasParams == ThreeState.YES && styleSettings.SPACE_WITHIN_METHOD_CALL_PARENTHESES || + hasParams == ThreeState.UNSURE && styleSettings.SPACE_WITHIN_EMPTY_METHOD_CALL_PARENTHESES; new ParenthesesInsertHandler(styleSettings.SPACE_BEFORE_METHOD_CALL_PARENTHESES, spaceBetweenParentheses, needRightParenth, styleSettings.METHOD_PARAMETERS_LPAREN_ON_NEXT_LINE) { @Override protected boolean placeCaretInsideParentheses(InsertionContext context1, LookupElement item1) { - return hasParameters; + return hasParameters != ThreeState.NO; } @Override @@ -794,7 +796,7 @@ public class JavaCompletionUtil { }.handleInsert(context, item); } - if (hasParams) { + if (hasParams != ThreeState.NO) { // Invoke parameters popup AutoPopupController.getInstance(file.getProject()).autoPopupParameterInfo(editor, overloadsMatter ? null : (PsiElement)item.getObject()); } diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/JavaMethodCallElement.java b/java/java-impl/src/com/intellij/codeInsight/completion/JavaMethodCallElement.java index a5cc64ba9518..e0860654e1f8 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/JavaMethodCallElement.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/JavaMethodCallElement.java @@ -37,6 +37,7 @@ import com.intellij.psi.impl.PsiImplUtil; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiUtil; import com.intellij.psi.util.TypeConversionUtil; +import com.intellij.util.ThreeState; import com.intellij.util.containers.ContainerUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -160,9 +161,8 @@ public class JavaMethodCallElement extends LookupItem implements Type final PsiMethod method = getObject(); final LookupElement[] allItems = context.getElements(); - final boolean overloadsMatter = allItems.length == 1 && getUserData(JavaCompletionUtil.FORCE_SHOW_SIGNATURE_ATTR) == null; - final boolean hasParams = MethodParenthesesHandler.hasParams(this, allItems, overloadsMatter, method); - JavaCompletionUtil.insertParentheses(context, this, overloadsMatter, hasParams); + ThreeState hasParams = method.getParameterList().isEmpty() ? ThreeState.NO : MethodParenthesesHandler.overloadsHaveParameters(allItems, method); + JavaCompletionUtil.insertParentheses(context, this, false, hasParams, false); final int startOffset = context.getStartOffset(); final OffsetKey refStart = context.trackOffset(startOffset, true); diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/SlowerTypeConversions.java b/java/java-impl/src/com/intellij/codeInsight/completion/SlowerTypeConversions.java index 7a9e1a08b3b6..4622bb40fed2 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/SlowerTypeConversions.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/SlowerTypeConversions.java @@ -109,7 +109,7 @@ class SlowerTypeConversions implements Runnable { if (PsiType.VOID.equals(type) || PsiType.NULL.equals(type)) return null; if (!method.getParameterList().isEmpty()) return null; return method.getName() + "(" + - getSpace(CodeStyle.getLanguageSettings(file).SPACE_WITHIN_METHOD_CALL_PARENTHESES) + ")"; + getSpace(CodeStyle.getLanguageSettings(file).SPACE_WITHIN_EMPTY_METHOD_CALL_PARENTHESES) + ")"; } else if (o instanceof PsiVariable) { return ((PsiVariable)o).getName(); diff --git a/java/java-impl/src/com/intellij/codeInsight/completion/TypeArgumentCompletionProvider.java b/java/java-impl/src/com/intellij/codeInsight/completion/TypeArgumentCompletionProvider.java index 1fa806130caf..3e894e9c2f3b 100644 --- a/java/java-impl/src/com/intellij/codeInsight/completion/TypeArgumentCompletionProvider.java +++ b/java/java-impl/src/com/intellij/codeInsight/completion/TypeArgumentCompletionProvider.java @@ -14,6 +14,7 @@ import com.intellij.psi.util.PsiUtil; import com.intellij.psi.util.TypeConversionUtil; import com.intellij.util.Consumer; import com.intellij.util.ProcessingContext; +import com.intellij.util.ThreeState; import com.intellij.util.containers.ContainerUtil; import com.intellij.util.containers.JBIterable; import org.jetbrains.annotations.NotNull; @@ -100,7 +101,7 @@ class TypeArgumentCompletionProvider extends CompletionProvider); + } + + void emptyMethod() {} + void emptyMethod(int a) {} +} \ No newline at end of file diff --git a/java/java-tests/testData/codeInsight/completion/style/SpaceWithinNonEmptyCallParens.java b/java/java-tests/testData/codeInsight/completion/style/SpaceWithinNonEmptyCallParens.java new file mode 100644 index 000000000000..e1050f66d42e --- /dev/null +++ b/java/java-tests/testData/codeInsight/completion/style/SpaceWithinNonEmptyCallParens.java @@ -0,0 +1,8 @@ +class A{ + { + emptyM + } + + void emptyMethod() {} + void emptyMethod(int a) {} +} \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/CompletionStyleTest.java b/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/CompletionStyleTest.java index d4829dd53efa..d3d5ec2e2754 100644 --- a/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/CompletionStyleTest.java +++ b/java/java-tests/testSrc/com/intellij/java/codeInsight/completion/CompletionStyleTest.java @@ -264,6 +264,18 @@ public class CompletionStyleTest extends LightJavaCodeInsightTestCase { styleSettings.SPACE_WITHIN_METHOD_CALL_PARENTHESES = space_within_method_call_parentheses; } + public void testSpaceWithinNonEmptyCallParens() { + final String path = BASE_PATH; + CommonCodeStyleSettings styleSettings = getCodeStyleSettings(); + final boolean space_within_method_call_parentheses = styleSettings.SPACE_WITHIN_METHOD_CALL_PARENTHESES; + + styleSettings.SPACE_WITHIN_METHOD_CALL_PARENTHESES = true; + configureByFile(path + "/" + getTestName(false) + ".java"); + performNormalCompletion(); + checkResultByFile(path + "/" + getTestName(false) + "-out.java"); + styleSettings.SPACE_WITHIN_METHOD_CALL_PARENTHESES = space_within_method_call_parentheses; + } + /*public void testClassNameCompletion1() throws Exception{ final String path = BASE_PATH; configureByFile(path + "/before34.java"); diff --git a/java/openapi/src/com/intellij/codeInsight/completion/util/MethodParenthesesHandler.java b/java/openapi/src/com/intellij/codeInsight/completion/util/MethodParenthesesHandler.java index e9914a6d4bc2..746cf87e87df 100644 --- a/java/openapi/src/com/intellij/codeInsight/completion/util/MethodParenthesesHandler.java +++ b/java/openapi/src/com/intellij/codeInsight/completion/util/MethodParenthesesHandler.java @@ -17,8 +17,12 @@ package com.intellij.codeInsight.completion.util; import com.intellij.codeInsight.completion.InsertionContext; import com.intellij.codeInsight.lookup.LookupElement; -import com.intellij.psi.PsiElement; import com.intellij.psi.PsiMethod; +import com.intellij.util.ThreeState; +import com.intellij.util.containers.JBIterable; +import org.jetbrains.annotations.NotNull; + +import java.util.List; /** * @author peter @@ -34,26 +38,31 @@ public class MethodParenthesesHandler extends ParenthesesInsertHandler overloads = JBIterable.of(allItems) + .map(LookupElement::getPsiElement) + .filter(PsiMethod.class) + .filter(element -> element.getName().equals(method.getName())) + .toList(); + return overloads.isEmpty() ? ThreeState.fromBoolean(!method.getParameterList().isEmpty()) : hasParameters(overloads); } - private static boolean hasOverloads(LookupElement[] allItems, final PsiMethod method) { - String name = method.getName(); - for (LookupElement another : allItems) { - final PsiElement element = another.getPsiElement(); - if (method != element && element instanceof PsiMethod && ((PsiMethod)element).getName().equals(name)) { - return true; + @NotNull + public static ThreeState hasParameters(List methods) { + boolean hasEmpty = methods.isEmpty(); + boolean hasNonEmpty = false; + for (PsiMethod method : methods) { + if (!method.getParameterList().isEmpty()) { + hasNonEmpty = true; + } else { + hasEmpty = true; } } - return false; + return hasNonEmpty && hasEmpty ? ThreeState.UNSURE : hasNonEmpty ? ThreeState.YES : ThreeState.NO; } - } diff --git a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyInsertHandler.java b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyInsertHandler.java index f2a8e9773613..5cf69058980f 100644 --- a/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyInsertHandler.java +++ b/plugins/groovy/src/org/jetbrains/plugins/groovy/lang/completion/GroovyInsertHandler.java @@ -17,6 +17,7 @@ import com.intellij.openapi.editor.Editor; import com.intellij.psi.*; import com.intellij.psi.codeStyle.CommonCodeStyleSettings; import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.util.ThreeState; import com.intellij.util.text.CharArrayUtil; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -115,15 +116,16 @@ public class GroovyInsertHandler implements InsertHandler { context.commitDocument(); - if (context.getCompletionChar() == ' ' && MethodParenthesesHandler.hasParams(item, context.getElements(), true, method)) { + ThreeState hasParams = MethodParenthesesHandler.overloadsHaveParameters(context.getElements(), method); + if (context.getCompletionChar() == ' ' && hasParams != ThreeState.NO) { return; } CommonCodeStyleSettings settings = CompletionStyleUtil.getCodeStyleSettings(context); - ParenthesesInsertHandler.getInstance(MethodParenthesesHandler.hasParams(item, context.getElements(), true, method), + ParenthesesInsertHandler.getInstance(hasParams != ThreeState.NO, settings.SPACE_BEFORE_METHOD_CALL_PARENTHESES, - settings.SPACE_WITHIN_METHOD_CALL_PARENTHESES, + hasParams == ThreeState.UNSURE ? settings.SPACE_WITHIN_EMPTY_METHOD_CALL_PARENTHESES : settings.SPACE_WITHIN_METHOD_CALL_PARENTHESES, true, true).handleInsert(context, item); AutoPopupController.getInstance(context.getProject()).autoPopupParameterInfo(editor, method);