From 41dd12d46be4c901167ca5ddcadb29b237e56d53 Mon Sep 17 00:00:00 2001 From: "Pavel V. Talanov" Date: Mon, 23 Jun 2014 19:17:59 +0400 Subject: [PATCH] Fix invalid usage of descriptorToDeclaration in QuickFixFactoryForTypeMismatchError --- .../QuickFixFactoryForTypeMismatchError.java | 33 ++++++++++++++----- .../beforeMultiFakeOverride.kt | 19 +++++++++++ ...eMultiFakeOverrideForOperatorConvention.kt | 22 +++++++++++++ .../quickfix/QuickFixTestGenerated.java | 10 ++++++ 4 files changed, 75 insertions(+), 9 deletions(-) create mode 100644 idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeMultiFakeOverride.kt create mode 100644 idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeMultiFakeOverrideForOperatorConvention.kt diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixFactoryForTypeMismatchError.java b/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixFactoryForTypeMismatchError.java index cc9a9ff1f49..623e0c49c2e 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixFactoryForTypeMismatchError.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixFactoryForTypeMismatchError.java @@ -20,6 +20,7 @@ import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.psi.PsiElement; import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.diagnostics.Diagnostic; import org.jetbrains.jet.lang.diagnostics.DiagnosticWithParameters2; import org.jetbrains.jet.lang.diagnostics.Errors; @@ -71,9 +72,9 @@ public class QuickFixFactoryForTypeMismatchError implements JetIntentionActionsF ResolvedCall resolvedCall = context.get(BindingContext.RESOLVED_CALL, ((JetOperationExpression) expression).getOperationReference()); if (resolvedCall != null) { - PsiElement declaration = BindingContextUtils.descriptorToDeclaration(context, resolvedCall.getResultingDescriptor()); - if (declaration instanceof JetFunction) { - actions.add(new ChangeFunctionReturnTypeFix((JetFunction) declaration, expectedType)); + JetFunction declaration = getFunctionDeclaration(context, resolvedCall); + if (declaration != null) { + actions.add(new ChangeFunctionReturnTypeFix(declaration, expectedType)); } } } @@ -82,9 +83,9 @@ public class QuickFixFactoryForTypeMismatchError implements JetIntentionActionsF if (parentBinary.getRight() == expression) { ResolvedCall resolvedCall = context.get(BindingContext.RESOLVED_CALL, parentBinary.getOperationReference()); if (resolvedCall != null) { - PsiElement declaration = BindingContextUtils.descriptorToDeclaration(context, resolvedCall.getResultingDescriptor()); - if (declaration instanceof JetFunction) { - JetParameter binaryOperatorParameter = ((JetFunction) declaration).getValueParameterList().getParameters().get(0); + JetFunction declaration = getFunctionDeclaration(context, resolvedCall); + if (declaration != null) { + JetParameter binaryOperatorParameter = declaration.getValueParameterList().getParameters().get(0); actions.add(new ChangeParameterTypeFix(binaryOperatorParameter, expressionType)); } } @@ -96,9 +97,9 @@ public class QuickFixFactoryForTypeMismatchError implements JetIntentionActionsF ResolvedCall resolvedCall = context.get(BindingContext.RESOLVED_CALL, ((JetCallExpression) expression).getCalleeExpression()); if (resolvedCall != null) { - PsiElement declaration = BindingContextUtils.descriptorToDeclaration(context, resolvedCall.getResultingDescriptor()); - if (declaration instanceof JetFunction) { - actions.add(new ChangeFunctionReturnTypeFix((JetFunction) declaration, expectedType)); + JetFunction declaration = getFunctionDeclaration(context, resolvedCall); + if (declaration != null) { + actions.add(new ChangeFunctionReturnTypeFix(declaration, expectedType)); } } } @@ -128,4 +129,18 @@ public class QuickFixFactoryForTypeMismatchError implements JetIntentionActionsF } return actions; } + + @Nullable + private static JetFunction getFunctionDeclaration(@NotNull BindingContext context, @NotNull ResolvedCall resolvedCall) { + List declarations = BindingContextUtils.descriptorToDeclarations(context, resolvedCall.getResultingDescriptor()); + //do not create fix if descriptor has more than one overridden declarations + //TODO: use change signature to deal with this case correctly + if (declarations.size() == 1) { + PsiElement result = declarations.iterator().next(); + if (result instanceof JetFunction) { + return (JetFunction) result; + } + } + return null; + } } diff --git a/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeMultiFakeOverride.kt b/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeMultiFakeOverride.kt new file mode 100644 index 00000000000..dbcb8365484 --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeMultiFakeOverride.kt @@ -0,0 +1,19 @@ +// "Change 'AA.f' function return type to 'Boolean'" "false" +// ACTION: Change 'AAA.g' function return type to 'Int' +// ACTION: Convert to expression body +// ACTION: Disable 'Convert to Expression Body' +// ACTION: Edit intention settings +// ERROR: Type mismatch.
Required:kotlin.Boolean
Found:kotlin.Int
+trait A { + fun f(): Int +} + +open class AA { + fun f() = 3 +} + +class AAA: AA(), A { + fun g(): Boolean { + return f() + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeMultiFakeOverrideForOperatorConvention.kt b/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeMultiFakeOverrideForOperatorConvention.kt new file mode 100644 index 00000000000..ae55376a13e --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeMultiFakeOverrideForOperatorConvention.kt @@ -0,0 +1,22 @@ +// "Change 'AA.contains' function return type to 'Int'" "false" +// ACTION: Change 'AAA.g' function return type to 'Boolean' +// ACTION: Convert to expression body +// ACTION: Disable 'Convert to Expression Body' +// ACTION: Disable 'Replace Overloaded Operator With Function Call' +// ACTION: Edit intention settings +// ACTION: Edit intention settings +// ACTION: Replace overloaded operator with function call +// ERROR: Type mismatch.
Required:kotlin.Int
Found:kotlin.Boolean
+trait A { + fun contains(i: Int): Boolean +} + +open class AA { + fun contains(i: Int) = true +} + +class AAA: AA(), A { + fun g(): Int { + return 3 in this + } +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/jet/plugin/quickfix/QuickFixTestGenerated.java b/idea/tests/org/jetbrains/jet/plugin/quickfix/QuickFixTestGenerated.java index 7f93f8f37ed..657e6dffeb0 100644 --- a/idea/tests/org/jetbrains/jet/plugin/quickfix/QuickFixTestGenerated.java +++ b/idea/tests/org/jetbrains/jet/plugin/quickfix/QuickFixTestGenerated.java @@ -2306,6 +2306,16 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { doTest("idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeExpectedTypeMismatch.kt"); } + @TestMetadata("beforeMultiFakeOverride.kt") + public void testMultiFakeOverride() throws Exception { + doTest("idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeMultiFakeOverride.kt"); + } + + @TestMetadata("beforeMultiFakeOverrideForOperatorConvention.kt") + public void testMultiFakeOverrideForOperatorConvention() throws Exception { + doTest("idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforeMultiFakeOverrideForOperatorConvention.kt"); + } + @TestMetadata("beforePropertyGetterInitializerTypeMismatch.kt") public void testPropertyGetterInitializerTypeMismatch() throws Exception { doTest("idea/testData/quickfix/typeMismatch/typeMismatchOnReturnedExpression/beforePropertyGetterInitializerTypeMismatch.kt");