IDEA-53352 Completing multiple parameters inside if statement inserts semicolon incorrectly

This commit is contained in:
peter
2010-04-06 14:25:53 +04:00
parent e7caa62de3
commit 8ea4bb8771
5 changed files with 59 additions and 21 deletions
@@ -84,21 +84,21 @@ public class ExpectedTypesProvider {
return new ExpectedTypeInfoImpl(type, kind, dims, defaultType, tailType);
}
public ExpectedTypeInfo[] getExpectedTypes(PsiExpression expr, boolean forCompletion) {
public static ExpectedTypeInfo[] getExpectedTypes(PsiExpression expr, boolean forCompletion) {
return getExpectedTypes(expr, forCompletion, false);
}
public ExpectedTypeInfo[] getExpectedTypes(PsiExpression expr, boolean forCompletion, final boolean voidable) {
public static ExpectedTypeInfo[] getExpectedTypes(PsiExpression expr, boolean forCompletion, final boolean voidable) {
return getExpectedTypes(expr, forCompletion, ourGlobalScopeClassProvider, voidable);
}
public ExpectedTypeInfo[] getExpectedTypes(PsiExpression expr,
public static ExpectedTypeInfo[] getExpectedTypes(PsiExpression expr,
boolean forCompletion,
ExpectedClassProvider classProvider) {
return getExpectedTypes(expr, forCompletion, classProvider, false);
}
public ExpectedTypeInfo[] getExpectedTypes(PsiExpression expr, boolean forCompletion, ExpectedClassProvider classProvider,
public static ExpectedTypeInfo[] getExpectedTypes(PsiExpression expr, boolean forCompletion, ExpectedClassProvider classProvider,
final boolean voidable) {
if (expr == null) return null;
PsiElement parent = expr.getParent();
@@ -193,7 +193,7 @@ public class ExpectedTypesProvider {
}
}
private class MyParentVisitor extends JavaElementVisitor {
private static class MyParentVisitor extends JavaElementVisitor {
private PsiExpression myExpr;
private final boolean myForCompletion;
private final ExpectedClassProvider myClassProvider;
@@ -280,7 +280,7 @@ public class ExpectedTypesProvider {
}
@Nullable
private PsiType getAnnotationMethodType(final PsiNameValuePair pair) {
private static PsiType getAnnotationMethodType(final PsiNameValuePair pair) {
final PsiReference reference = pair.getReference();
if (reference != null) {
final PsiElement method = reference.resolve();
@@ -458,7 +458,7 @@ public class ExpectedTypesProvider {
}
}
private TailType getAssignmentRValueTailType(PsiAssignmentExpression assignment) {
private static TailType getAssignmentRValueTailType(PsiAssignmentExpression assignment) {
if (assignment.getParent() instanceof PsiExpressionStatement) {
if (!(assignment.getParent().getParent() instanceof PsiForStatement)) {
return TailType.SEMICOLON;
@@ -897,7 +897,7 @@ public class ExpectedTypesProvider {
return array.toArray(new ExpectedTypeInfo[array.size()]);
}
private TailType getMethodArgumentTailType(final PsiExpression argument, final int index, final PsiMethod method, final PsiSubstitutor substitutor,
private static TailType getMethodArgumentTailType(final PsiExpression argument, final int index, final PsiMethod method, final PsiSubstitutor substitutor,
final PsiParameter[] parms) {
if (index >= parms.length) {
return TailType.NONE;
@@ -909,9 +909,7 @@ public class ExpectedTypesProvider {
PsiType returnType = method.getReturnType();
if (returnType != null) returnType = substitutor.substitute(returnType);
return (PsiType.VOID.equals(returnType) || returnType == null) && call.getParent() instanceof PsiStatement
? TailTypes.CALL_RPARENTH_SEMICOLON
: TailTypes.CALL_RPARENTH;
return getFinalCallParameterTailType(call, returnType, method);
}
return TailType.COMMA;
}
@@ -956,7 +954,7 @@ public class ExpectedTypesProvider {
}
@Nullable
private PsiType getTypeParameterValue(PsiClass rootClass, PsiClass derivedClass, PsiSubstitutor substitutor, int index) {
private static PsiType getTypeParameterValue(PsiClass rootClass, PsiClass derivedClass, PsiSubstitutor substitutor, int index) {
final PsiTypeParameter[] typeParameters = rootClass.getTypeParameters();
if (typeParameters.length > index) {
final PsiSubstitutor psiSubstitutor = TypeConversionUtil.getClassSubstitutor(rootClass, derivedClass, substitutor);
@@ -969,7 +967,7 @@ public class ExpectedTypesProvider {
}
@Nullable
protected PsiType checkMethod(PsiMethod method, @NonNls String className, NullableFunction<PsiClass,PsiType> function) {
protected static PsiType checkMethod(PsiMethod method, @NonNls String className, NullableFunction<PsiClass,PsiType> function) {
final PsiClass containingClass = method.getContainingClass();
if (containingClass == null) return null;
@@ -1151,4 +1149,23 @@ public class ExpectedTypesProvider {
PsiMethod[] findDeclaredMethods(final PsiManager manager, String name);
}
public static TailType getFinalCallParameterTailType(PsiElement call, PsiType returnType, PsiMethod method) {
if (method.isConstructor() &&
call instanceof PsiMethodCallExpression && ((PsiMethodCallExpression)call).getMethodExpression() instanceof PsiSuperExpression) {
return TailTypes.CALL_RPARENTH_SEMICOLON;
}
final boolean chainable = !PsiType.VOID.equals(returnType) && returnType != null;
final PsiElement parent = call.getParent();
final boolean statementContext = parent instanceof PsiExpressionStatement || parent instanceof PsiVariable ||
parent instanceof PsiCodeBlock || parent instanceof PsiThrowStatement;
if (statementContext && !chainable) {
return TailTypes.CALL_RPARENTH_SEMICOLON;
}
return TailTypes.CALL_RPARENTH;
}
}
@@ -15,8 +15,7 @@
*/
package com.intellij.codeInsight.completion;
import com.intellij.codeInsight.TailTypes;
import com.intellij.codeInsight.TailType;
import com.intellij.codeInsight.ExpectedTypesProvider;
import com.intellij.codeInsight.lookup.LookupElement;
import com.intellij.codeInsight.lookup.LookupElementBuilder;
import com.intellij.codeInsight.lookup.TailTypeDecorator;
@@ -53,7 +52,7 @@ class SameSignatureCallParametersProvider extends CompletionProvider<CompletionP
while (container != null) {
for (final Pair<PsiMethod, PsiSubstitutor> candidate : candidates) {
if (container.getParameterList().getParametersCount() > 1 && isSuperMethod(container, candidate.first, candidate.second)) {
result.addElement(createParametersLookupElement(container));
result.addElement(createParametersLookupElement(container, methodCall));
return;
}
}
@@ -63,7 +62,7 @@ class SameSignatureCallParametersProvider extends CompletionProvider<CompletionP
}
}
private static LookupElement createParametersLookupElement(PsiMethod method) {
private static LookupElement createParametersLookupElement(PsiMethod method, PsiElement call) {
final String lookupString = StringUtil.join(method.getParameterList().getParameters(), new Function<PsiParameter, String>() {
public String fun(PsiParameter psiParameter) {
return psiParameter.getName();
@@ -78,10 +77,7 @@ class SameSignatureCallParametersProvider extends CompletionProvider<CompletionP
final LookupElement element = LookupElementBuilder.create(lookupString).setIcon(icon);
element.putUserData(JavaCompletionUtil.SUPER_METHOD_PARAMETERS, Boolean.TRUE);
final TailType tail = method.isConstructor() || method.getReturnType() instanceof PsiPrimitiveType
? TailTypes.CALL_RPARENTH_SEMICOLON
: TailTypes.CALL_RPARENTH;
return TailTypeDecorator.withTail(element, tail);
return TailTypeDecorator.withTail(element, ExpectedTypesProvider.getFinalCallParameterTailType(call, method.getReturnType(), method));
}
private static List<Pair<PsiMethod, PsiSubstitutor>> getSuperMethodCandidates(PsiReferenceExpression expression) {
@@ -0,0 +1,9 @@
public class Foo {
public void handleInsert(InsertionContext context, LookupElement item) {
if (hasParams(context, item)<caret>)
}
private static boolean hasParams(InsertionContext context, LookupElement item) {
return false;
}
}
@@ -0,0 +1,9 @@
public class Foo {
public void handleInsert(InsertionContext context, LookupElement item) {
if (hasParams(<caret>))
}
private static boolean hasParams(InsertionContext context, LookupElement item) {
return false;
}
}
@@ -720,6 +720,13 @@ public class SmartTypeCompletionTest extends LightCompletionTestCase {
checkResultByTestName();
}
public void testSameMethodArgumentsInIf() throws Throwable {
configureByTestName();
getLookup().setCurrentItem(getLookup().getItems().get(1));
select();
checkResultByTestName();
}
public void testSuperConstructorArguments() throws Throwable {
configureByTestName();
getLookup().setCurrentItem(getLookup().getItems().get(2));