Debugger: Fix evaluation for local extension functions (KT-13188)
This commit is contained in:
+14
-14
@@ -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
|
||||
)
|
||||
}
|
||||
+4
-3
@@ -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<Smart>,
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
Vendored
+17
@@ -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;
|
||||
Vendored
+9
@@ -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
|
||||
Generated
+5
@@ -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");
|
||||
|
||||
Reference in New Issue
Block a user