Allow '$this$label$<somethingElse>' for extension receivers

Our mangling works poorly with nested inline function calls (saying, `apply()` inside an another `apply()`). In that case, the generated local variable name for both cases will be `$this$apply`. As the debugger sees only the last (the closest) variable with the same name, we loose the ability to get the first one.
This means we might want to add some additional information to the mangling (e.g. add the trailing indices `$this$apply$1`). This commit supports this case.
This commit is contained in:
Yan Zhulanow
2019-02-05 17:57:41 +03:00
parent 34b03c45d7
commit 11dfbd5d3d
@@ -237,7 +237,8 @@ class VariableFinder private constructor(private val context: ExecutionContext,
val variables = frameProxy.safeVisibleVariables()
// Local variables direct search
findLocalVariable(variables, kind, kind.parameterName)?.let { return it }
val namePredicate = fun(name: String) = name == kind.parameterName || name.startsWith(kind.parameterName + '$')
findLocalVariable(variables, kind, namePredicate)?.let { return it }
// Recursive search in local receiver variables
findCapturedVariableInReceiver(variables, kind)?.let { return it }
@@ -311,19 +312,43 @@ class VariableFinder private constructor(private val context: ExecutionContext,
}
private fun findLocalVariable(variables: List<LocalVariableProxyImpl>, kind: VariableKind, name: String): Result? {
return findLocalVariable(variables, kind) { it == name }
}
private fun findLocalVariable(
variables: List<LocalVariableProxyImpl>,
kind: VariableKind,
namePredicate: (String) -> Boolean
): Result? {
val inlineDepth = getInlineDepth(variables)
if (inlineDepth > 0) {
val nameInlineAwareRegex = getLocalVariableNameRegexInlineAware(name)
val inlineAwareNamePredicate = fun(name: String): Boolean {
var endIndex = name.length
var depth = 0
val suffixLen = INLINE_FUN_VAR_SUFFIX.length
while (endIndex >= suffixLen) {
if (name.substring(endIndex - suffixLen, endIndex) != INLINE_FUN_VAR_SUFFIX) {
break
}
depth++
endIndex -= suffixLen
}
return namePredicate(name.take(endIndex))
}
variables.namedEntitySequence()
.filter { it.name.matches(nameInlineAwareRegex) && getInlineDepth(it.name) == inlineDepth && kind.typeMatches(it.type) }
.filter { inlineAwareNamePredicate(it.name) && getInlineDepth(it.name) == inlineDepth && kind.typeMatches(it.type) }
.mapNotNull { it.unwrapAndCheck(kind) }
.firstOrNull()
?.let { return it }
}
variables.namedEntitySequence()
.filter { it.name == name && kind.typeMatches(it.type) }
.filter { namePredicate(it.name) && kind.typeMatches(it.type) }
.mapNotNull { it.unwrapAndCheck(kind) }
.firstOrNull()
?.let { return it }