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()
|
val functionalTypeExpected = expectedType.isBuiltinFunctionalType()
|
||||||
|
|
||||||
// We forbid anonymous function expressions to suspend type coercion for now, until `suspend fun` syntax is supported
|
// 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)
|
if (components.languageVersionSettings.supportsFeature(LanguageFeature.NewInference) && functionalTypeExpected && !expectedType.isSuspendFunctionType)
|
||||||
createTypeInfo(resultType, context)
|
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? {
|
override fun visitLambdaExpression(expression: KtLambdaExpression, context: ExpressionTypingContext): KotlinTypeInfo? {
|
||||||
checkReservedYieldBeforeLambda(expression, context.trace)
|
checkReservedYieldBeforeLambda(expression, context.trace)
|
||||||
if (!expression.functionLiteral.hasBody()) return null
|
if (!expression.functionLiteral.hasBody()) return null
|
||||||
@@ -159,7 +147,7 @@ internal class FunctionsTypingVisitor(facade: ExpressionTypingInternals) : Expre
|
|||||||
val safeReturnType = computeReturnType(expression, context, functionDescriptor, functionTypeExpected)
|
val safeReturnType = computeReturnType(expression, context, functionDescriptor, functionTypeExpected)
|
||||||
functionDescriptor.setReturnType(safeReturnType)
|
functionDescriptor.setReturnType(safeReturnType)
|
||||||
|
|
||||||
val resultType = functionDescriptor.createFunctionType(suspendFunctionTypeExpected)!!
|
val resultType = functionDescriptor.createFunctionType(components.builtIns, suspendFunctionTypeExpected)!!
|
||||||
if (functionTypeExpected) {
|
if (functionTypeExpected) {
|
||||||
// all checks were done before
|
// all checks were done before
|
||||||
return createTypeInfo(resultType, context)
|
return createTypeInfo(resultType, context)
|
||||||
@@ -365,3 +353,15 @@ internal class FunctionsTypingVisitor(facade: ExpressionTypingInternals) : Expre
|
|||||||
return returns
|
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.safeLocation
|
||||||
import org.jetbrains.kotlin.idea.debugger.safeMethod
|
import org.jetbrains.kotlin.idea.debugger.safeMethod
|
||||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
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.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.*
|
import org.jetbrains.kotlin.psi.psiUtil.*
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext
|
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.checkers.COROUTINE_CONTEXT_1_3_FQ_NAME
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall
|
||||||
import org.jetbrains.kotlin.resolve.calls.model.VariableAsFunctionResolvedCall
|
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.descriptorUtil.fqNameSafe
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExtensionReceiver
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ExtensionReceiver
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitClassReceiver
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver
|
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver
|
||||||
import org.jetbrains.kotlin.resolve.source.getPsi
|
import org.jetbrains.kotlin.resolve.source.getPsi
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
|
import org.jetbrains.kotlin.types.expressions.createFunctionType
|
||||||
|
|
||||||
class CodeFragmentParameterInfo(
|
class CodeFragmentParameterInfo(
|
||||||
val parameters: List<Smart>,
|
val parameters: List<Smart>,
|
||||||
@@ -262,8 +263,8 @@ class CodeFragmentParameterAnalyzer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
return when (target) {
|
return when (target) {
|
||||||
is FunctionDescriptor -> {
|
is SimpleFunctionDescriptor -> {
|
||||||
val type = SingleAbstractMethodUtils.getFunctionTypeForAbstractMethod(target, false)
|
val type = target.createFunctionType(target.builtIns, target.isSuspend) ?: return null
|
||||||
parameters.getOrPut(target) {
|
parameters.getOrPut(target) {
|
||||||
Smart(Dumb(Kind.LOCAL_FUNCTION, target.name.asString()), type, 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");
|
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")
|
@TestMetadata("localVariables.kt")
|
||||||
public void testLocalVariables() throws Exception {
|
public void testLocalVariables() throws Exception {
|
||||||
runTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/localVariables.kt");
|
runTest("idea/testData/debugger/tinyApp/src/evaluate/singleBreakpoint/localVariables.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user