diff --git a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ClosureExpressionsTypingVisitor.java b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ClosureExpressionsTypingVisitor.java index 052ce5f1aa4..68c21d8ce92 100644 --- a/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ClosureExpressionsTypingVisitor.java +++ b/compiler/frontend/src/org/jetbrains/jet/lang/types/expressions/ClosureExpressionsTypingVisitor.java @@ -215,7 +215,7 @@ public class ClosureExpressionsTypingVisitor extends ExpressionTypingVisitor { if (typeReference != null) { type = context.expressionTypingServices.getTypeResolver().resolveType(context.scope, typeReference, context.trace, true); if (expectedType != null) { - if (!JetTypeChecker.INSTANCE.isSubtypeOf(type, expectedType)) { + if (!JetTypeChecker.INSTANCE.isSubtypeOf(expectedType, type)) { context.trace.report(EXPECTED_PARAMETER_TYPE_MISMATCH.on(declaredParameter, expectedType)); } } @@ -280,7 +280,7 @@ public class ClosureExpressionsTypingVisitor extends ExpressionTypingVisitor { context.expressionTypingServices.checkFunctionReturnType(expression.getFunctionLiteral(), context.replaceScope(functionInnerScope). replaceExpectedType(returnType).replaceBindingTrace(temporaryTrace), temporaryTrace); if (expectedReturnType != null) { - if (!JetTypeChecker.INSTANCE.isSubtypeOf(expectedReturnType, returnType)) { + if (!JetTypeChecker.INSTANCE.isSubtypeOf(returnType, expectedReturnType)) { temporaryTrace.report(EXPECTED_RETURN_TYPE_MISMATCH.on(returnTypeRef, expectedReturnType)); } } diff --git a/compiler/testData/diagnostics/tests/functionLiterals/ExpectedParameterTypeMismatchVariance.kt b/compiler/testData/diagnostics/tests/functionLiterals/ExpectedParameterTypeMismatchVariance.kt index 26796bbb4d8..1cadc4052fc 100644 --- a/compiler/testData/diagnostics/tests/functionLiterals/ExpectedParameterTypeMismatchVariance.kt +++ b/compiler/testData/diagnostics/tests/functionLiterals/ExpectedParameterTypeMismatchVariance.kt @@ -8,12 +8,12 @@ fun foo(f: (Trait) -> Trait) = f fun test(s: Sub) { foo { - (t: Super): Sub -> s + (t: Super): Sub -> s } foo { (t: Trait): Trait -> s } foo { - (t: Sub): Super -> s + (t: Sub): Super -> s } } diff --git a/idea/src/org/jetbrains/jet/plugin/JetBundle.properties b/idea/src/org/jetbrains/jet/plugin/JetBundle.properties index 0a5afe1c34e..c46cae665bf 100644 --- a/idea/src/org/jetbrains/jet/plugin/JetBundle.properties +++ b/idea/src/org/jetbrains/jet/plugin/JetBundle.properties @@ -60,6 +60,7 @@ add.semicolon.family=Add Semicolon change.function.return.type=Change ''{0}'' function return type to ''{1}'' remove.function.return.type=Remove explicitly specified return type in ''{0}'' function change.element.type=Change ''{0}'' type to ''{1}'' +change.type=Change type from ''{0}'' to ''{1}'' change.type.family=Change Type add.kotlin.signature.action.family.name=Specify Custom Kotlin Signature diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeTypeFix.java b/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeTypeFix.java new file mode 100644 index 00000000000..fb4091e253a --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/ChangeTypeFix.java @@ -0,0 +1,89 @@ +/* + * Copyright 2010-2013 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.jet.plugin.quickfix; + +import com.intellij.codeInsight.intention.IntentionAction; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiFile; +import com.intellij.util.IncorrectOperationException; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; +import org.jetbrains.jet.lang.diagnostics.Diagnostic; +import org.jetbrains.jet.lang.diagnostics.DiagnosticWithParameters1; +import org.jetbrains.jet.lang.diagnostics.Errors; +import org.jetbrains.jet.lang.psi.JetParameter; +import org.jetbrains.jet.lang.psi.JetPsiFactory; +import org.jetbrains.jet.lang.psi.JetTypeReference; +import org.jetbrains.jet.lang.types.JetType; +import org.jetbrains.jet.plugin.JetBundle; + +public class ChangeTypeFix extends JetIntentionAction { + private final JetType type; + + public ChangeTypeFix(@NotNull JetTypeReference element, JetType type) { + super(element); + this.type = type; + } + + @NotNull + @Override + public String getText() { + return JetBundle.message("change.type", element.getText(), type); + } + + @NotNull + @Override + public String getFamilyName() { + return JetBundle.message("change.type.family"); + } + + @Override + public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { + element.replace(JetPsiFactory.createType(project, type.toString())); + } + + @NotNull + public static JetIntentionActionFactory createFactoryForExpectedParameterTypeMismatch() { + return new JetIntentionActionFactory() { + @Nullable + @Override + public IntentionAction createAction(Diagnostic diagnostic) { + assert diagnostic.getFactory() == Errors.EXPECTED_PARAMETER_TYPE_MISMATCH; + @SuppressWarnings("unchecked") + DiagnosticWithParameters1 diagnosticWithParameters = (DiagnosticWithParameters1) diagnostic; + JetTypeReference typeReference = diagnosticWithParameters.getPsiElement().getTypeReference(); + assert typeReference != null : "EXPECTED_PARAMETER_TYPE_MISMATCH reported on parameter without explicitly declared type"; + return new ChangeTypeFix(typeReference, diagnosticWithParameters.getA()); + } + }; + } + + @NotNull + public static JetIntentionActionFactory createFactoryForExpectedReturnTypeMismatch() { + return new JetIntentionActionFactory() { + @Nullable + @Override + public IntentionAction createAction(Diagnostic diagnostic) { + assert diagnostic.getFactory() == Errors.EXPECTED_RETURN_TYPE_MISMATCH; + @SuppressWarnings("unchecked") + DiagnosticWithParameters1 diagnosticWithParameters = (DiagnosticWithParameters1) diagnostic; + return new ChangeTypeFix(diagnosticWithParameters.getPsiElement(), diagnosticWithParameters.getA()); + } + }; + } +} diff --git a/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixes.java b/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixes.java index 07157915879..2e787aa2e41 100644 --- a/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixes.java +++ b/idea/src/org/jetbrains/jet/plugin/quickfix/QuickFixes.java @@ -220,6 +220,9 @@ public class QuickFixes { factories.put(HAS_NEXT_FUNCTION_TYPE_MISMATCH, ChangeFunctionReturnTypeFix.createFactoryForHasNextFunctionTypeMismatch()); factories.put(COMPARE_TO_TYPE_MISMATCH, ChangeFunctionReturnTypeFix.createFactoryForCompareToTypeMismatch()); + factories.put(EXPECTED_PARAMETER_TYPE_MISMATCH, ChangeTypeFix.createFactoryForExpectedParameterTypeMismatch()); + factories.put(EXPECTED_RETURN_TYPE_MISMATCH, ChangeTypeFix.createFactoryForExpectedReturnTypeMismatch()); + factories.put(PLATFORM_CLASS_MAPPED_TO_KOTLIN, MapPlatformClassToKotlinFix.createFactory()); factories.put(MANY_CLASSES_IN_SUPERTYPE_LIST, RemoveSupertypeFix.createFactory()); diff --git a/idea/testData/quickfix/typeMismatch/afterExpectedParameterTypeMismatch.kt b/idea/testData/quickfix/typeMismatch/afterExpectedParameterTypeMismatch.kt new file mode 100644 index 00000000000..339488f1d53 --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/afterExpectedParameterTypeMismatch.kt @@ -0,0 +1,6 @@ +// "Change type from 'String' to 'Int'" "true" +fun foo(f: (Int) -> String) { + foo { + (x: Int) -> "" + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/typeMismatch/afterExpectedReturnTypeMismatch.kt b/idea/testData/quickfix/typeMismatch/afterExpectedReturnTypeMismatch.kt new file mode 100644 index 00000000000..05be595bbcb --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/afterExpectedReturnTypeMismatch.kt @@ -0,0 +1,9 @@ +// "Change type from 'A' to 'B'" "true" +trait A {} +trait B : A {} + +fun foo(f: (B) -> B) { + foo { + (b: B): B -> b + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/typeMismatch/beforeExpectedParameterTypeMismatch.kt b/idea/testData/quickfix/typeMismatch/beforeExpectedParameterTypeMismatch.kt new file mode 100644 index 00000000000..df3397685ce --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/beforeExpectedParameterTypeMismatch.kt @@ -0,0 +1,6 @@ +// "Change type from 'String' to 'Int'" "true" +fun foo(f: (Int) -> String) { + foo { + (x: String) -> "" + } +} \ No newline at end of file diff --git a/idea/testData/quickfix/typeMismatch/beforeExpectedReturnTypeMismatch.kt b/idea/testData/quickfix/typeMismatch/beforeExpectedReturnTypeMismatch.kt new file mode 100644 index 00000000000..c55df3630ea --- /dev/null +++ b/idea/testData/quickfix/typeMismatch/beforeExpectedReturnTypeMismatch.kt @@ -0,0 +1,9 @@ +// "Change type from 'A' to 'B'" "true" +trait A {} +trait B : A {} + +fun foo(f: (B) -> B) { + foo { + (b: B): A -> b + } +} \ 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 8709164432d..27ed4fe997f 100644 --- a/idea/tests/org/jetbrains/jet/plugin/quickfix/QuickFixTestGenerated.java +++ b/idea/tests/org/jetbrains/jet/plugin/quickfix/QuickFixTestGenerated.java @@ -1033,6 +1033,16 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { doTest("idea/testData/quickfix/typeMismatch/beforeComponentFunctionReturnTypeMismatch5.kt"); } + @TestMetadata("beforeExpectedParameterTypeMismatch.kt") + public void testExpectedParameterTypeMismatch() throws Exception { + doTest("idea/testData/quickfix/typeMismatch/beforeExpectedParameterTypeMismatch.kt"); + } + + @TestMetadata("beforeExpectedReturnTypeMismatch.kt") + public void testExpectedReturnTypeMismatch() throws Exception { + doTest("idea/testData/quickfix/typeMismatch/beforeExpectedReturnTypeMismatch.kt"); + } + @TestMetadata("beforeHasNextFunctionReturnTypeMismatch.kt") public void testHasNextFunctionReturnTypeMismatch() throws Exception { doTest("idea/testData/quickfix/typeMismatch/beforeHasNextFunctionReturnTypeMismatch.kt");