diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/AddReturnToLastExpressionInFunctionFix.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/AddReturnToLastExpressionInFunctionFix.kt index 7303abfe2e0..b1ca83dcca7 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/AddReturnToLastExpressionInFunctionFix.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/AddReturnToLastExpressionInFunctionFix.kt @@ -18,6 +18,7 @@ import org.jetbrains.kotlin.psi.KtNamedFunction import org.jetbrains.kotlin.psi.KtPsiFactory import org.jetbrains.kotlin.resolve.calls.callUtil.getType import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode +import org.jetbrains.kotlin.types.isError import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf class AddReturnToLastExpressionInFunctionFix(element: KtDeclarationWithBody) : KotlinQuickFixAction(element) { @@ -31,8 +32,9 @@ class AddReturnToLastExpressionInFunctionFix(element: KtDeclarationWithBody) : K val context = last.analyze(BodyResolveMode.PARTIAL) val lastType = last.getType(context) ?: return false + if (lastType.isError) return false val expectedType = element.resolveToDescriptorIfAny()?.returnType ?: return false - if (!lastType.isSubtypeOf(expectedType)) return false + if (expectedType.isError || !lastType.isSubtypeOf(expectedType)) return false return true } diff --git a/idea/src/org/jetbrains/kotlin/idea/quickfix/AddReturnToUnusedLastExpressionInFunctionFix.kt b/idea/src/org/jetbrains/kotlin/idea/quickfix/AddReturnToUnusedLastExpressionInFunctionFix.kt index 36c58355c7d..e9f4aa93ba1 100644 --- a/idea/src/org/jetbrains/kotlin/idea/quickfix/AddReturnToUnusedLastExpressionInFunctionFix.kt +++ b/idea/src/org/jetbrains/kotlin/idea/quickfix/AddReturnToUnusedLastExpressionInFunctionFix.kt @@ -13,10 +13,9 @@ import org.jetbrains.kotlin.diagnostics.Errors import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptorIfAny import org.jetbrains.kotlin.psi.* -import org.jetbrains.kotlin.resolve.BindingContext -import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsStatement import org.jetbrains.kotlin.resolve.calls.callUtil.getType import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode +import org.jetbrains.kotlin.types.isError import org.jetbrains.kotlin.types.typeUtil.isSubtypeOf class AddReturnToUnusedLastExpressionInFunctionFix(element: KtElement) : KotlinQuickFixAction(element) { @@ -29,9 +28,11 @@ class AddReturnToUnusedLastExpressionInFunctionFix(element: KtElement) : KotlinQ if (!expr.isLastStatementInFunctionBody()) return false val exprType = expr.getType(context) ?: return false + if (exprType.isError) return false + val function = expr.parent.parent as? KtNamedFunction ?: return false val functionReturnType = function.resolveToDescriptorIfAny()?.returnType ?: return false - if (!exprType.isSubtypeOf(functionReturnType)) return false + if (functionReturnType.isError || !exprType.isSubtypeOf(functionReturnType)) return false return true } diff --git a/idea/testData/quickfix/addReturnToLastExpressionInFunction/typeError.kt b/idea/testData/quickfix/addReturnToLastExpressionInFunction/typeError.kt new file mode 100644 index 00000000000..8682054c1f2 --- /dev/null +++ b/idea/testData/quickfix/addReturnToLastExpressionInFunction/typeError.kt @@ -0,0 +1,10 @@ +// "Add 'return' to last expression" "false" +// WITH_RUNTIME +// ACTION: Introduce local variable +// ACTION: Remove explicitly specified return type of enclosing function 'some' +// ERROR: A 'return' expression required in a function with a block body ('{...}') +// ERROR: Unresolved reference: FunctionReference + +fun some(): FunctionReference { + Int::class +} diff --git a/idea/testData/quickfix/addReturnToLastExpressionInFunction/typeError2.kt b/idea/testData/quickfix/addReturnToLastExpressionInFunction/typeError2.kt new file mode 100644 index 00000000000..74dc6aeecbe --- /dev/null +++ b/idea/testData/quickfix/addReturnToLastExpressionInFunction/typeError2.kt @@ -0,0 +1,10 @@ +// "Add 'return' to last expression" "false" +// WITH_RUNTIME +// ACTION: Introduce local variable +// ACTION: Remove explicitly specified return type of enclosing function 'some' +// ERROR: A 'return' expression required in a function with a block body ('{...}') +// ERROR: Unresolved reference: FunctionReference + +fun some(): Any { + FunctionReference::class +} diff --git a/idea/testData/quickfix/addReturnToUnusedLastExpressionInFunction/typeError.kt b/idea/testData/quickfix/addReturnToUnusedLastExpressionInFunction/typeError.kt new file mode 100644 index 00000000000..937b9e3b769 --- /dev/null +++ b/idea/testData/quickfix/addReturnToUnusedLastExpressionInFunction/typeError.kt @@ -0,0 +1,10 @@ +// "Add 'return' before the expression" "false" +// WITH_RUNTIME +// ACTION: Introduce import alias +// ACTION: Introduce local variable +// ERROR: A 'return' expression required in a function with a block body ('{...}') +// ERROR: Unresolved reference: FunctionReference + +fun some(): FunctionReference { + Int::class +} diff --git a/idea/testData/quickfix/addReturnToUnusedLastExpressionInFunction/typeError2.kt b/idea/testData/quickfix/addReturnToUnusedLastExpressionInFunction/typeError2.kt new file mode 100644 index 00000000000..7be9768711d --- /dev/null +++ b/idea/testData/quickfix/addReturnToUnusedLastExpressionInFunction/typeError2.kt @@ -0,0 +1,17 @@ +// "Add 'return' before the expression" "false" +// WITH_RUNTIME +// ACTION: Create local variable 'FunctionReference' +// ACTION: Create object 'FunctionReference' +// ACTION: Create parameter 'FunctionReference' +// ACTION: Create property 'FunctionReference' +// ACTION: Create annotation 'FunctionReference' +// ACTION: Create class 'FunctionReference' +// ACTION: Create enum 'FunctionReference' +// ACTION: Create interface 'FunctionReference' +// ACTION: Introduce local variable +// ACTION: Rename reference +// ERROR: Unresolved reference: FunctionReference + +fun some() { + FunctionReference::class +} diff --git a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java index a5efab23eab..f699c6664ba 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/quickfix/QuickFixTestGenerated.java @@ -933,6 +933,16 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { public void testSubtype() throws Exception { runTest("idea/testData/quickfix/addReturnToLastExpressionInFunction/subtype.kt"); } + + @TestMetadata("typeError.kt") + public void testTypeError() throws Exception { + runTest("idea/testData/quickfix/addReturnToLastExpressionInFunction/typeError.kt"); + } + + @TestMetadata("typeError2.kt") + public void testTypeError2() throws Exception { + runTest("idea/testData/quickfix/addReturnToLastExpressionInFunction/typeError2.kt"); + } } @TestMetadata("idea/testData/quickfix/addReturnToUnusedLastExpressionInFunction") @@ -966,6 +976,16 @@ public class QuickFixTestGenerated extends AbstractQuickFixTest { public void testSubtype() throws Exception { runTest("idea/testData/quickfix/addReturnToUnusedLastExpressionInFunction/subtype.kt"); } + + @TestMetadata("typeError.kt") + public void testTypeError() throws Exception { + runTest("idea/testData/quickfix/addReturnToUnusedLastExpressionInFunction/typeError.kt"); + } + + @TestMetadata("typeError2.kt") + public void testTypeError2() throws Exception { + runTest("idea/testData/quickfix/addReturnToUnusedLastExpressionInFunction/typeError2.kt"); + } } @TestMetadata("idea/testData/quickfix/addRunBeforeLambda")