Android Studio 4.2.2 - 为什么调试器不评估内部函数中的参数?

Pau*_*aum 5 debugging android android-studio

Android Studio 4.2.2计算局部变量和全局变量,但在内部函数内部时不计算参数函数。

在之前的版本之前,这一切都工作得很好。

fun a(p:param) {
fun b(){
var v = p+1 // Here
}
}
Run Code Online (Sandbox Code Playgroud)

假设尝试评估带有p注释的行中的 参数// HereAlt F8

评估窗口中的消息是

Cannot find the local variable 'p' with type
Run Code Online (Sandbox Code Playgroud)

这很麻烦,因为它迫使您将参数复制为每个例程中的局部变量,以便在调试器中可见。

变量 p = p

有人注意到这一点吗?有什么解决方法吗?

请注意,变量窗口显示带有前缀的参数,但它在评估$窗口中也不起作用。

我已在 JetBrains 中发布了此问题。

在此输入图像描述

Kri*_*ris 1

首先要做的事情是:

有什么解决方法吗?

是的,将参数 p 绑定到内部的局部变量b

fun a(p: Param) {
  fun b() {
    val p = p
    var v = p + 1
  }
}
Run Code Online (Sandbox Code Playgroud)

一切都会按预期进行。


根本原因稍微复杂一些。

Kotlin 是在与 Kotlin IntelliJ 语言插件密切相关的语言工具链上发展起来的。最初的 JVM 编译器是一个代码生成器,它使用 IntelliJ 语言插件用于诊断、快速修复等的语义信息的数据结构。

这种架构非常适合为 IDE 提供语言支持,但对于构​​建快速批处理编译器则不太适用。

在 Kotlin 1.5 中,“IR 后端”被启用为 JVM 的默认代码生成器。它使用更传统的编译方法,在输出 JVM 字节代码之前逐渐将抽象语法树 (AST) 转换为更简单的中间语言。

随着这一变化,实施了许多新的编译策略。特别是,在旧策略中,局部函数被视为绑定到局部变量的 lambda。Function它们的自由变量被记录在声明站点的已分配对象的状态中。invoke当调用本地函数时,它会转换为对该函数对象的调用。故事结局。

在新方法中,局部函数被提升为外部函数位于同一类上的私有静态函数。本地函数中的自由变量由该提升函数的参数封闭,并且不是将它们记录在 lambda 对象的声明位置,而是在调用位置作为参数传递。

在你的例子中。p内部函数中的 是空闲的,b因此$p添加了一个额外的参数b

虽然这适用于“发布版本”,但周围的工具直到最近才跟上。“评估表达式...”机制受到的打击尤其严重,因为它对生成的 JVM 字节代码的布局和形状非常敏感。

在这种特定情况下,需要调整调试器中的机制,将片段的自由变量映射到断点处的局部变量。通过针对 2022.3 的这一更改,您应该希望不再注意到这个特定的错误,以及随着评估机制的新修订版本的发布而进行的许多其他改进。