Skip to content

Commit dffbe0f

Browse files
committed
Count JVM class name for inlined function from base declaration
Drop code with naive removing all anonymous classes. Breakpoints now works when inline call is in anonymous call.
1 parent cd92e3f commit dffbe0f

File tree

4 files changed

+47
-25
lines changed

4 files changed

+47
-25
lines changed

idea/src/org/jetbrains/kotlin/idea/debugger/DebuggerClassNameProvider.kt

Lines changed: 10 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ import org.jetbrains.kotlin.idea.search.usagesSearch.isImportUsage
4646
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
4747
import org.jetbrains.kotlin.idea.util.application.runReadAction
4848
import org.jetbrains.kotlin.load.java.JvmAbi
49+
import org.jetbrains.kotlin.name.Name
4950
import org.jetbrains.kotlin.psi.*
5051
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
5152
import org.jetbrains.kotlin.psi.psiUtil.parents
@@ -187,7 +188,7 @@ class DebuggerClassNameProvider(val myDebugProcess: DebugProcess, val scopes: Li
187188
private fun inlineCallClassPatterns(typeMapper: KotlinTypeMapper, element: KtElement): List<String> {
188189
val context = typeMapper.bindingContext
189190

190-
val (inlineCall, ktAnonymousClassElementProducer) = runReadAction {
191+
val inlineCall = runReadAction {
191192
element.parents.map {
192193
val ktCallExpression: KtCallExpression = when(it) {
193194
is KtFunctionLiteral -> {
@@ -210,31 +211,26 @@ class DebuggerClassNameProvider(val myDebugProcess: DebugProcess, val scopes: Li
210211
ktCallExpression to (it as KtElement)
211212
}.lastOrNull {
212213
it != null && isInlineCall(context, it.component1())
213-
}
214+
}?.first
214215
} ?: return emptyList()
215216

216217
val lexicalScope = context[BindingContext.LEXICAL_SCOPE, inlineCall] ?: return emptyList()
218+
val baseClassName = classNamesForPosition(inlineCall, false).firstOrNull() ?: return emptyList()
217219

218220
val resolvedCall = runReadAction { inlineCall.getResolvedCall(context) } ?: return emptyList()
219221
val inlineFunctionName = resolvedCall.resultingDescriptor.name
220222

221-
val originalInternalClassName = CodegenBinding.asmTypeForAnonymousClass(
222-
typeMapper.bindingContext, ktAnonymousClassElementProducer).internalName
223-
224223
val ownerDescriptor = lexicalScope.ownerDescriptor
225-
226-
val className = if (isFunctionWithSuspendStateMachine(ownerDescriptor, typeMapper.bindingContext)) {
227-
originalInternalClassName.replaceAfterLast("$", DO_RESUME_METHOD_NAME)
224+
val ownerDescriptorName = if (isFunctionWithSuspendStateMachine(ownerDescriptor, typeMapper.bindingContext)) {
225+
Name.identifier(DO_RESUME_METHOD_NAME)
228226
}
229227
else {
230-
originalInternalClassName.funPrefix()
228+
ownerDescriptor.name
231229
}
232230

231+
val ownerJvmName = if (ownerDescriptorName.isSpecial) InlineCodegenUtil.SPECIAL_TRANSFORMATION_NAME else ownerDescriptorName.asString()
233232
val mangledInternalClassName =
234-
className +
235-
(if (ownerDescriptor.name.isSpecial) "$" + InlineCodegenUtil.SPECIAL_TRANSFORMATION_NAME else "") +
236-
InlineCodegenUtil.INLINE_CALL_TRANSFORMATION_SUFFIX + "$" +
237-
inlineFunctionName
233+
baseClassName + "$" + ownerJvmName + InlineCodegenUtil.INLINE_CALL_TRANSFORMATION_SUFFIX + "$" + inlineFunctionName
238234

239235
return listOf("$mangledInternalClassName*")
240236
}
@@ -254,7 +250,7 @@ class DebuggerClassNameProvider(val myDebugProcess: DebugProcess, val scopes: Li
254250
KtSecondaryConstructor::class.java)
255251

256252
private fun getElementToCalculateClassName(notPositionedElement: PsiElement?): KtElement? {
257-
if (notPositionedElement?.javaClass as Class<*> in TYPES_TO_CALCULATE_CLASSNAME) return notPositionedElement as KtElement
253+
if (notPositionedElement?.let { it::class.java } as Class<*> in TYPES_TO_CALCULATE_CLASSNAME) return notPositionedElement as KtElement
258254

259255
return readAction { PsiTreeUtil.getParentOfType(notPositionedElement, *TYPES_TO_CALCULATE_CLASSNAME) }
260256
}
@@ -411,17 +407,6 @@ private fun isInlineCall(context: BindingContext, expr: KtCallExpression): Boole
411407

412408
private inline fun <reified T : PsiElement> PsiElement.typedParent(): T? = getStrictParentOfType()
413409

414-
private fun String.funPrefix(): String {
415-
if (lastIndexOf("$") < 0) return this
416-
417-
val trimmed = trimEnd { it == '$' || it.isDigit() } // Can accidentally trim end of function name if it ends with a number
418-
val nextDollarIndex = indexOf('$', startIndex = trimmed.length - 1)
419-
420-
if (nextDollarIndex < 0) return this
421-
422-
return this.substring(0, nextDollarIndex)
423-
}
424-
425410
private fun String.substringIndex(): String {
426411
if (lastIndexOf("$") < 0) return this
427412

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
LineBreakpoint created at stopInObjectLiteralInInlineCallWithClosureInAnonymous.kt:11
2+
!JDK_HOME!\bin\java -agentlib:jdwp=transport=dt_socket,address=!HOST_NAME!:!HOST_PORT!,suspend=y,server=n -Dfile.encoding=!FILE_ENCODING! -classpath !OUTPUT_PATH!;!KOTLIN_RUNTIME!;!CUSTOM_LIBRARY!;!RT_JAR! stopInObjectLiteralInInlineCallWithClosureInAnonymous.StopInObjectLiteralInInlineCallWithClosureInAnonymousKt
3+
Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
4+
stopInObjectLiteralInInlineCallWithClosureInAnonymous.kt:11
5+
stopInObjectLiteralInInlineCallWithClosureInAnonymous.kt:12
6+
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
7+
8+
Process finished with exit code 0
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package stopInObjectLiteralInInlineCallWithClosureInAnonymous
2+
3+
fun main(args: Array<String>) {
4+
val a = 12
5+
6+
{
7+
inlineF {
8+
val s = object : () -> Unit {
9+
override fun invoke() {
10+
//Breakpoint!
11+
nop(a)
12+
nop(a)
13+
}
14+
}
15+
16+
s()
17+
}
18+
}()
19+
}
20+
21+
inline fun <R> inlineF(block: () -> R): R = block()
22+
23+
fun nop(a: Any) {}

idea/tests/org/jetbrains/kotlin/idea/debugger/KotlinSteppingTestGenerated.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -824,6 +824,12 @@ public void testStopInObjectLiteralInInlineCallWithClosure() throws Exception {
824824
doStepOverTest(fileName);
825825
}
826826

827+
@TestMetadata("stopInObjectLiteralInInlineCallWithClosureInAnonymous.kt")
828+
public void testStopInObjectLiteralInInlineCallWithClosureInAnonymous() throws Exception {
829+
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/stepOver/stopInObjectLiteralInInlineCallWithClosureInAnonymous.kt");
830+
doStepOverTest(fileName);
831+
}
832+
827833
@TestMetadata("stopInSuspendFunctionWithSuspendPoints.kt")
828834
public void testStopInSuspendFunctionWithSuspendPoints() throws Exception {
829835
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/stepOver/stopInSuspendFunctionWithSuspendPoints.kt");

0 commit comments

Comments
 (0)