diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixFactoryForTypeMismatchError.java b/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixFactoryForTypeMismatchError.java index 7ba9769d05e..613136a1bd3 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixFactoryForTypeMismatchError.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixFactoryForTypeMismatchError.java @@ -17,13 +17,17 @@ package org.jetbrains.jet.plugin.quickfix; 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.jet.lang.descriptors.CallableDescriptor; import org.jetbrains.jet.lang.diagnostics.Diagnostic; import org.jetbrains.jet.lang.diagnostics.DiagnosticWithParameters2; import org.jetbrains.jet.lang.diagnostics.Errors; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.BindingContextUtils; +import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache; @@ -62,6 +66,31 @@ public class QuickFixFactoryForTypeMismatchError implements JetIntentionActionsF actions.add(new ChangeFunctionReturnTypeFix(function, expressionType)); } + // Fixing overloaded operators: + if (expression instanceof JetOperationExpression) { + 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)); + } + } + } + if (expression.getParent() instanceof JetBinaryExpression) { + JetBinaryExpression parentBinary = (JetBinaryExpression) expression.getParent(); + 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); + actions.add(new ChangeFunctionParameterTypeFix(binaryOperatorParameter, expressionType)); + } + } + } + } + // Change type of a function parameter in case TYPE_MISMATCH is reported on expression passed as value argument of call. // 1) When an argument is a dangling function literal: JetFunctionLiteralExpression functionLiteralExpression = diff --git a/idea/testData/quickfix/typeMismatch/fixOverloadedOperator/afterChangeNotFunctionReturnType.kt b/idea/testData/quickfix/typeMismatch/fixOverloadedOperator/afterChangeNotFunctionReturnType.kt new file mode 100644 index 00000000000..2e02e549264 --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/fixOverloadedOperator/afterChangeNotFunctionReturnType.kt @@ -0,0 +1,7 @@ +// "Change 'A.not' function return type to 'A'" "true" +trait A { + fun not(): A + fun times(a: A): A +} + +fun foo(a: A): A = a * !(if (true) a else a) \ No newline at end of file diff --git a/idea/testData/quickfix/typeMismatch/fixOverloadedOperator/afterChangePlusFunctionReturnType.kt b/idea/testData/quickfix/typeMismatch/fixOverloadedOperator/afterChangePlusFunctionReturnType.kt new file mode 100644 index 00000000000..5f841fe38b4 --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/fixOverloadedOperator/afterChangePlusFunctionReturnType.kt @@ -0,0 +1,8 @@ +// "Change 'A.plus' function return type to '() -> Int'" "true" +trait A { + fun plus(a: A): () -> Int +} + +fun foo(a: A): () -> Int { + return a + a +} \ No newline at end of file diff --git a/idea/testData/quickfix/typeMismatch/fixOverloadedOperator/afterChangeTimesFunctionParameterType.kt b/idea/testData/quickfix/typeMismatch/fixOverloadedOperator/afterChangeTimesFunctionParameterType.kt new file mode 100644 index 00000000000..a0178c297d5 --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/fixOverloadedOperator/afterChangeTimesFunctionParameterType.kt @@ -0,0 +1,6 @@ +// "Change parameter 'a' type of function 'A.times' to 'String'" "true" +trait A { + fun times(a: String): A +} + +fun foo(a: A): A = a * "" \ No newline at end of file diff --git a/idea/testData/quickfix/typeMismatch/fixOverloadedOperator/beforeChangeNotFunctionReturnType.kt b/idea/testData/quickfix/typeMismatch/fixOverloadedOperator/beforeChangeNotFunctionReturnType.kt new file mode 100644 index 00000000000..3fcbddff06c --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/fixOverloadedOperator/beforeChangeNotFunctionReturnType.kt @@ -0,0 +1,7 @@ +// "Change 'A.not' function return type to 'A'" "true" +trait A { + fun not(): String + fun times(a: A): A +} + +fun foo(a: A): A = a * !(if (true) a else a) \ No newline at end of file diff --git a/idea/testData/quickfix/typeMismatch/fixOverloadedOperator/beforeChangePlusFunctionReturnType.kt b/idea/testData/quickfix/typeMismatch/fixOverloadedOperator/beforeChangePlusFunctionReturnType.kt new file mode 100644 index 00000000000..c83d83f0c41 --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/fixOverloadedOperator/beforeChangePlusFunctionReturnType.kt @@ -0,0 +1,8 @@ +// "Change 'A.plus' function return type to '() -> Int'" "true" +trait A { + fun plus(a: A): String +} + +fun foo(a: A): () -> Int { + return a + a +} \ No newline at end of file diff --git a/idea/testData/quickfix/typeMismatch/fixOverloadedOperator/beforeChangeTimesFunctionParameterType.kt b/idea/testData/quickfix/typeMismatch/fixOverloadedOperator/beforeChangeTimesFunctionParameterType.kt new file mode 100644 index 00000000000..837fc7af446 --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/fixOverloadedOperator/beforeChangeTimesFunctionParameterType.kt @@ -0,0 +1,6 @@ +// "Change parameter 'a' type of function 'A.times' to 'String'" "true" +trait A { + fun times(a: A): A +} + +fun foo(a: A): A = a * "" \ 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 034c2451009..a4eb2f2f42a 100644 --- a/idea/tests/org/jetbrains/jet/plugin/quickfix/QuickFixTestGenerated.java +++ b/idea/tests/org/jetbrains/jet/plugin/quickfix/QuickFixTestGenerated.java @@ -1240,7 +1240,7 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { } @TestMetadata("idea/testData/quickfix/typeMismatch") - @InnerTestClasses({TypeMismatch.Casts.class, TypeMismatch.ComponentFunctionReturnTypeMismatch.class, TypeMismatch.FunctionParameterTypeMismatch.class, TypeMismatch.TypeMismatchOnReturnedExpression.class}) + @InnerTestClasses({TypeMismatch.Casts.class, TypeMismatch.ComponentFunctionReturnTypeMismatch.class, TypeMismatch.FixOverloadedOperator.class, TypeMismatch.FunctionParameterTypeMismatch.class, TypeMismatch.TypeMismatchOnReturnedExpression.class}) public static class TypeMismatch extends AbstractQuickFixTest { public void testAllFilesPresentInTypeMismatch() throws Exception { JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("idea/testData/quickfix/typeMismatch"), Pattern.compile("^before(\\w+)\\.kt$"), true); @@ -1382,6 +1382,29 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { } + @TestMetadata("idea/testData/quickfix/typeMismatch/fixOverloadedOperator") + public static class FixOverloadedOperator extends AbstractQuickFixTest { + public void testAllFilesPresentInFixOverloadedOperator() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.GenerateTests", new File("idea/testData/quickfix/typeMismatch/fixOverloadedOperator"), Pattern.compile("^before(\\w+)\\.kt$"), true); + } + + @TestMetadata("beforeChangeNotFunctionReturnType.kt") + public void testChangeNotFunctionReturnType() throws Exception { + doTest("idea/testData/quickfix/typeMismatch/fixOverloadedOperator/beforeChangeNotFunctionReturnType.kt"); + } + + @TestMetadata("beforeChangePlusFunctionReturnType.kt") + public void testChangePlusFunctionReturnType() throws Exception { + doTest("idea/testData/quickfix/typeMismatch/fixOverloadedOperator/beforeChangePlusFunctionReturnType.kt"); + } + + @TestMetadata("beforeChangeTimesFunctionParameterType.kt") + public void testChangeTimesFunctionParameterType() throws Exception { + doTest("idea/testData/quickfix/typeMismatch/fixOverloadedOperator/beforeChangeTimesFunctionParameterType.kt"); + } + + } + @TestMetadata("idea/testData/quickfix/typeMismatch/functionParameterTypeMismatch") public static class FunctionParameterTypeMismatch extends AbstractQuickFixTest { public void testAllFilesPresentInFunctionParameterTypeMismatch() throws Exception { @@ -1488,6 +1511,7 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { suite.addTestSuite(TypeMismatch.class); suite.addTestSuite(Casts.class); suite.addTestSuite(ComponentFunctionReturnTypeMismatch.class); + suite.addTestSuite(FixOverloadedOperator.class); suite.addTestSuite(FunctionParameterTypeMismatch.class); suite.addTestSuite(TypeMismatchOnReturnedExpression.class); return suite;