IDEA-231373 Treat overloaded method calls as empty so IDEA doesn't introduce spaces within the parentheses

GitOrigin-RevId: eefb114de7e4f5864d1a3e1524417f1c93d319cc
This commit is contained in:
Peter Gromov
2020-02-04 11:06:36 +00:00
committed by intellij-monorepo-bot
parent e533356b14
commit 2ef829470b
10 changed files with 83 additions and 44 deletions
@@ -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<LookupElementDeco
final PsiElement place = context.getFile().findElementAt(context.getStartOffset());
assert place != null;
boolean hasParams = constructor != null ? !constructor.getParameterList().isEmpty() : hasConstructorParameters(psiClass, place);
ThreeState hasParams = constructor != null ? ThreeState.fromBoolean(!constructor.getParameterList().isEmpty())
: hasConstructorParameters(psiClass, place);
RangeMarker refEnd = context.getDocument().createRangeMarker(context.getTailOffset(), context.getTailOffset());
@@ -254,17 +258,10 @@ public class ConstructorInsertHandler implements InsertHandler<LookupElementDeco
return true;
}
static boolean hasConstructorParameters(PsiClass psiClass, @NotNull PsiElement place) {
final PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(place.getProject()).getResolveHelper();
boolean hasParams = false;
for (PsiMethod constructor : psiClass.getConstructors()) {
if (!resolveHelper.isAccessible(constructor, place, null)) continue;
if (!constructor.getParameterList().isEmpty()) {
hasParams = true;
break;
}
}
return hasParams;
static ThreeState hasConstructorParameters(PsiClass psiClass, @NotNull PsiElement place) {
PsiResolveHelper resolveHelper = JavaPsiFacade.getInstance(place.getProject()).getResolveHelper();
return MethodParenthesesHandler.hasParameters(ContainerUtil.filter(psiClass.getConstructors(),
c -> resolveHelper.isAccessible(c, place, null)));
}
@Nullable
@@ -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<LookupElement>(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());
}
@@ -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<PsiMethod> 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);
@@ -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();
@@ -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<CompletionParame
}
private static boolean hasParameters(PsiTypeParameterListOwner paramOwner, PsiElement context) {
return paramOwner instanceof PsiClass && ConstructorInsertHandler.hasConstructorParameters((PsiClass)paramOwner, context);
return paramOwner instanceof PsiClass && ConstructorInsertHandler.hasConstructorParameters((PsiClass)paramOwner, context) != ThreeState.NO;
}
private static void addInheritors(CompletionParameters parameters,
@@ -0,0 +1,8 @@
class A{
{
emptyMethod(<caret>);
}
void emptyMethod() {}
void emptyMethod(int a) {}
}
@@ -0,0 +1,8 @@
class A{
{
emptyM<caret>
}
void emptyMethod() {}
void emptyMethod(int a) {}
}
@@ -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");
@@ -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<LookupEle
@Override
protected boolean placeCaretInsideParentheses(final InsertionContext context, final LookupElement item) {
return hasParams(item, context.getElements(), myOverloadsMatter, myMethod);
return myOverloadsMatter
? overloadsHaveParameters(context.getElements(), myMethod) != ThreeState.NO
: !myMethod.getParameterList().isEmpty();
}
public static boolean hasParams(LookupElement item, LookupElement[] allItems, final boolean overloadsMatter, final PsiMethod method) {
boolean hasParams = !method.getParameterList().isEmpty();
if (overloadsMatter){
hasParams |= hasOverloads(allItems, method);
}
return hasParams;
public static ThreeState overloadsHaveParameters(LookupElement[] allItems, PsiMethod method) {
List<PsiMethod> 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<PsiMethod> 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;
}
}
@@ -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<LookupElement> {
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);