diff --git a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/FunctionsTypingVisitor.kt b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/FunctionsTypingVisitor.kt index a42933e3aa3..a4575dedcc4 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/FunctionsTypingVisitor.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/types/expressions/FunctionsTypingVisitor.kt @@ -122,7 +122,7 @@ internal class FunctionsTypingVisitor(facade: ExpressionTypingInternals) : Expre val functionalTypeExpected = expectedType.isBuiltinFunctionalType() // We forbid anonymous function expressions to suspend type coercion for now, until `suspend fun` syntax is supported - val resultType = functionDescriptor.createFunctionType(suspendFunction = false) + val resultType = functionDescriptor.createFunctionType(components.builtIns, suspendFunction = false) if (components.languageVersionSettings.supportsFeature(LanguageFeature.NewInference) && functionalTypeExpected && !expectedType.isSuspendFunctionType) createTypeInfo(resultType, context) @@ -131,18 +131,6 @@ internal class FunctionsTypingVisitor(facade: ExpressionTypingInternals) : Expre } } - private fun SimpleFunctionDescriptor.createFunctionType(suspendFunction: Boolean = false): KotlinType? { - return createFunctionType( - components.builtIns, - Annotations.EMPTY, - extensionReceiverParameter?.type, - valueParameters.map { it.type }, - null, - returnType ?: return null, - suspendFunction = suspendFunction - ) - } - override fun visitLambdaExpression(expression: KtLambdaExpression, context: ExpressionTypingContext): KotlinTypeInfo? { checkReservedYieldBeforeLambda(expression, context.trace) if (!expression.functionLiteral.hasBody()) return null @@ -159,7 +147,7 @@ internal class FunctionsTypingVisitor(facade: ExpressionTypingInternals) : Expre val safeReturnType = computeReturnType(expression, context, functionDescriptor, functionTypeExpected) functionDescriptor.setReturnType(safeReturnType) - val resultType = functionDescriptor.createFunctionType(suspendFunctionTypeExpected)!! + val resultType = functionDescriptor.createFunctionType(components.builtIns, suspendFunctionTypeExpected)!! if (functionTypeExpected) { // all checks were done before return createTypeInfo(resultType, context) @@ -365,3 +353,15 @@ internal class FunctionsTypingVisitor(facade: ExpressionTypingInternals) : Expre return returns } } + +fun SimpleFunctionDescriptor.createFunctionType(builtIns: KotlinBuiltIns, suspendFunction: Boolean = false): KotlinType? { + return createFunctionType( + builtIns, + Annotations.EMPTY, + extensionReceiverParameter?.type, + valueParameters.map { it.type }, + null, + returnType ?: return null, + suspendFunction = suspendFunction + ) +} \ No newline at end of file diff --git a/idea/jvm-debugger/jvm-debugger-evaluation/src/org/jetbrains/kotlin/idea/debugger/evaluate/compilation/CodeFragmentParameterAnalyzer.kt b/idea/jvm-debugger/jvm-debugger-evaluation/src/org/jetbrains/kotlin/idea/debugger/evaluate/compilation/CodeFragmentParameterAnalyzer.kt index e90f5ed92aa..ee9eeb5ed6e 100644 --- a/idea/jvm-debugger/jvm-debugger-evaluation/src/org/jetbrains/kotlin/idea/debugger/evaluate/compilation/CodeFragmentParameterAnalyzer.kt +++ b/idea/jvm-debugger/jvm-debugger-evaluation/src/org/jetbrains/kotlin/idea/debugger/evaluate/compilation/CodeFragmentParameterAnalyzer.kt @@ -20,7 +20,6 @@ import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinCodeFragmentFactory.Com import org.jetbrains.kotlin.idea.debugger.safeLocation import org.jetbrains.kotlin.idea.debugger.safeMethod import org.jetbrains.kotlin.idea.util.application.runReadAction -import org.jetbrains.kotlin.load.java.sam.SingleAbstractMethodUtils import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.psiUtil.* import org.jetbrains.kotlin.resolve.BindingContext @@ -28,12 +27,14 @@ import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.resolve.calls.checkers.COROUTINE_CONTEXT_1_3_FQ_NAME import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall +import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.resolve.scopes.receivers.ExtensionReceiver import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver import org.jetbrains.kotlin.resolve.source.getPsi import org.jetbrains.kotlin.types.KotlinType +import org.jetbrains.kotlin.types.expressions.createFunctionType class CodeFragmentParameterInfo( val parameters: List, @@ -262,8 +263,8 @@ class CodeFragmentParameterAnalyzer( } return when (target) { - is FunctionDescriptor -> { - val type = SingleAbstractMethodUtils.getFunctionTypeForAbstractMethod(target, false) + is SimpleFunctionDescriptor -> { + val type = target.createFunctionType(target.builtIns, target.isSuspend) ?: return null parameters.getOrPut(target) { Smart(Dumb(Kind.LOCAL_FUNCTION, target.name.asString()), type, target) } diff --git a/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/localFunctionsWithReceivers.kt b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/localFunctionsWithReceivers.kt new file mode 100644 index 00000000000..685ec68047a --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/localFunctionsWithReceivers.kt @@ -0,0 +1,17 @@ +package localFunctionsWithReceivers + +fun main() { + fun String.foo(s: String) = this + 1 + fun String.foo() = this + 2 + + val x = "a".foo("b") + val y = "b".foo() + //Breakpoint! + val a = x + y +} + +// EXPRESSION: "a".foo("b") +// RESULT: "a1": Ljava/lang/String; + +// EXPRESSION: "b".foo() +// RESULT: "b2": Ljava/lang/String; \ No newline at end of file diff --git a/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/localFunctionsWithReceivers.out b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/localFunctionsWithReceivers.out new file mode 100644 index 00000000000..b16f60e840f --- /dev/null +++ b/idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/localFunctionsWithReceivers.out @@ -0,0 +1,9 @@ +LineBreakpoint created at localFunctionsWithReceivers.kt:10 +Run Java +Connected to the target VM +localFunctionsWithReceivers.kt:10 +Compile bytecode for "a".foo("b") +Compile bytecode for "b".foo() +Disconnected from the target VM + +Process finished with exit code 0 diff --git a/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluateExpressionTestGenerated.java b/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluateExpressionTestGenerated.java index 9ec4c25514a..b16dd2596fe 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluateExpressionTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/idea/debugger/evaluate/KotlinEvaluateExpressionTestGenerated.java @@ -296,6 +296,11 @@ public class KotlinEvaluateExpressionTestGenerated extends AbstractKotlinEvaluat runTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/localClass.kt"); } + @TestMetadata("localFunctionsWithReceivers.kt") + public void testLocalFunctionsWithReceivers() throws Exception { + runTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/localFunctionsWithReceivers.kt"); + } + @TestMetadata("localVariables.kt") public void testLocalVariables() throws Exception { runTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/localVariables.kt");