Fix look up for breakpoint in crossinline lambdas in android (KT-15282)
#KT-15282 Fixed
This commit is contained in:
Generated
+1
@@ -2,6 +2,7 @@
|
||||
<dictionary name="Nikolay.Krasko">
|
||||
<words>
|
||||
<w>accessors</w>
|
||||
<w>crossinline</w>
|
||||
<w>fqname</w>
|
||||
<w>goto</w>
|
||||
<w>gradle</w>
|
||||
|
||||
@@ -30,6 +30,7 @@ import com.intellij.util.containers.ContainerUtil
|
||||
import com.sun.jdi.Location
|
||||
import com.sun.jdi.ReferenceType
|
||||
import org.jetbrains.kotlin.codegen.inline.InlineCodegenUtil
|
||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||
import org.jetbrains.kotlin.idea.debugger.evaluate.KotlinDebuggerCaches
|
||||
import org.jetbrains.kotlin.idea.refactoring.getLineCount
|
||||
import org.jetbrains.kotlin.idea.refactoring.getLineStartOffset
|
||||
@@ -42,11 +43,13 @@ import org.jetbrains.kotlin.name.ClassId
|
||||
import org.jetbrains.kotlin.name.FqName
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.name.tail
|
||||
import org.jetbrains.kotlin.psi.KtFile
|
||||
import org.jetbrains.kotlin.psi.KtFunction
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.parents
|
||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil
|
||||
import org.jetbrains.kotlin.resolve.jvm.JvmClassName
|
||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.check
|
||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
|
||||
import org.jetbrains.kotlin.utils.getOrPutNullable
|
||||
import org.jetbrains.org.objectweb.asm.*
|
||||
import java.io.File
|
||||
@@ -254,9 +257,17 @@ internal fun getLocationsOfInlinedLine(type: ReferenceType, position: SourcePosi
|
||||
|
||||
val lineStartOffset = file.getLineStartOffset(line) ?: return listOf()
|
||||
val element = file.findElementAt(lineStartOffset) ?: return listOf()
|
||||
val ktElement = element.parents.firstIsInstanceOrNull<KtElement>() ?: return listOf()
|
||||
|
||||
val isInInline = runReadAction { element.parents.any { it is KtFunction && it.hasModifier(KtTokens.INLINE_KEYWORD) } }
|
||||
if (!isInInline) return listOf()
|
||||
|
||||
if (!isInInline) {
|
||||
// Lambdas passed to crossinline arguments are inlined when they are used in non-inlined lambdas
|
||||
val isInCrossinlineArgument = isInCrossinlineArgument(ktElement)
|
||||
if (!isInCrossinlineArgument) {
|
||||
return listOf()
|
||||
}
|
||||
}
|
||||
|
||||
val lines = inlinedLinesNumbers(line + 1, position.file.name, FqName(type.name()), type.sourceName(), project, sourceSearchScope)
|
||||
val inlineLocations = lines.flatMap { type.locationsOfLine(it) }
|
||||
@@ -264,6 +275,25 @@ internal fun getLocationsOfInlinedLine(type: ReferenceType, position: SourcePosi
|
||||
return inlineLocations
|
||||
}
|
||||
|
||||
fun isInCrossinlineArgument(ktElement: KtElement): Boolean {
|
||||
val argumentFunctions = runReadAction {
|
||||
ktElement.parents.filter {
|
||||
when (it) {
|
||||
is KtFunctionLiteral -> it.parent is KtLambdaExpression && (it.parent.parent is KtValueArgument || it.parent.parent is KtLambdaArgument)
|
||||
is KtFunction -> it.parent is KtValueArgument
|
||||
else -> false
|
||||
}
|
||||
}.filterIsInstance<KtFunction>()
|
||||
}
|
||||
|
||||
val bindingContext = ktElement.analyze(BodyResolveMode.PARTIAL)
|
||||
return argumentFunctions.any {
|
||||
val argumentDescriptor = InlineUtil.getInlineArgumentDescriptor(it, bindingContext)
|
||||
argumentDescriptor?.isCrossinline ?: false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun inlinedLinesNumbers(
|
||||
inlineLineNumber: Int, inlineFileName: String,
|
||||
destinationTypeFqName: FqName, destinationFileName: String,
|
||||
@@ -281,7 +311,7 @@ private fun inlinedLinesNumbers(
|
||||
|
||||
val smap = smapData.kotlinStrata ?: return listOf()
|
||||
|
||||
val mappingsToInlinedFile = smap.fileMappings.filter() { it.name == inlineFileName }
|
||||
val mappingsToInlinedFile = smap.fileMappings.filter { it.name == inlineFileName }
|
||||
val mappingIntervals = mappingsToInlinedFile.flatMap { it.lineMappings }
|
||||
|
||||
val mappedLines = mappingIntervals.asSequence().
|
||||
|
||||
+1
-1
@@ -188,7 +188,7 @@ private fun getInlineFunctionsIfAny(file: KtFile, offset: Int): List<KtNamedFunc
|
||||
private fun getInlineArgumentsIfAny(inlineFunctionCalls: List<KtCallExpression>): List<KtFunction> {
|
||||
return inlineFunctionCalls.flatMap {
|
||||
it.valueArguments
|
||||
.map { getArgumentExpression(it) }
|
||||
.map(::getArgumentExpression)
|
||||
.filterIsInstance<KtFunction>()
|
||||
}
|
||||
}
|
||||
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
LineBreakpoint created at stopInLambdaInInlinedCallWithCrossInline.kt:8
|
||||
!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! stopInLambdaInInlinedCallWithCrossInline.StopInLambdaInInlinedCallWithCrossInlineKt
|
||||
Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
||||
stopInLambdaInInlinedCallWithCrossInline.kt:8
|
||||
stopInLambdaInInlinedCallWithCrossInline.kt:18
|
||||
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
||||
|
||||
Process finished with exit code 0
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
LineBreakpoint created at stopInLambdaInInlinedCallWithCrossInlineDex.kt:8
|
||||
!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! stopInLambdaInInlinedCallWithCrossInlineDex.StopInLambdaInInlinedCallWithCrossInlineDexKt
|
||||
Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
||||
stopInLambdaInInlinedCallWithCrossInlineDex.kt:8
|
||||
stopInLambdaInInlinedCallWithCrossInlineDex.kt:19
|
||||
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
||||
|
||||
Process finished with exit code 0
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package stopInAnonymousFunctionInInlinedCallWithCrossInline
|
||||
|
||||
// KT-15282
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
foo(fun () {
|
||||
//Breakpoint!
|
||||
12
|
||||
})
|
||||
}
|
||||
|
||||
fun bar(f: () -> Unit) {
|
||||
f()
|
||||
}
|
||||
|
||||
inline fun foo(crossinline func: () -> Int) {
|
||||
bar {
|
||||
func()
|
||||
}
|
||||
}
|
||||
+20
@@ -0,0 +1,20 @@
|
||||
package stopInAnonymousFunctionInInlinedCallWithCrossInlineDex
|
||||
|
||||
// KT-15282
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
foo(fun () {
|
||||
//Breakpoint!
|
||||
12
|
||||
})
|
||||
}
|
||||
|
||||
fun bar(f: () -> Unit) {
|
||||
f()
|
||||
}
|
||||
|
||||
inline fun foo(crossinline func: () -> Int) {
|
||||
bar {
|
||||
func()
|
||||
}
|
||||
}
|
||||
Vendored
+20
@@ -0,0 +1,20 @@
|
||||
package stopInLambdaInInlinedCallWithCrossInline
|
||||
|
||||
// KT-15282
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
foo {
|
||||
//Breakpoint!
|
||||
12
|
||||
}
|
||||
}
|
||||
|
||||
fun bar(f: () -> Unit) {
|
||||
f()
|
||||
}
|
||||
|
||||
inline fun foo(crossinline func: () -> Int) {
|
||||
bar {
|
||||
func()
|
||||
}
|
||||
}
|
||||
Vendored
+20
@@ -0,0 +1,20 @@
|
||||
package stopInLambdaInInlinedCallWithCrossInlineDex
|
||||
|
||||
// KT-15282
|
||||
|
||||
fun main(args: Array<String>) {
|
||||
foo {
|
||||
//Breakpoint!
|
||||
12
|
||||
}
|
||||
}
|
||||
|
||||
fun bar(f: () -> Unit) {
|
||||
f()
|
||||
}
|
||||
|
||||
inline fun foo(crossinline func: () -> Int) {
|
||||
bar {
|
||||
func()
|
||||
}
|
||||
}
|
||||
@@ -704,6 +704,18 @@ public class KotlinSteppingTestGenerated extends AbstractKotlinSteppingTest {
|
||||
doStepOverTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("stopInAnonymousFunctionInInlinedCallWithCrossInline.kt")
|
||||
public void testStopInAnonymousFunctionInInlinedCallWithCrossInline() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/stepOver/stopInAnonymousFunctionInInlinedCallWithCrossInline.kt");
|
||||
doStepOverTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("stopInAnonymousFunctionInInlinedCallWithCrossInlineDex.kt")
|
||||
public void testStopInAnonymousFunctionInInlinedCallWithCrossInlineDex() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/stepOver/stopInAnonymousFunctionInInlinedCallWithCrossInlineDex.kt");
|
||||
doStepOverTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("stopInInlineCallLocalFunLambda.kt")
|
||||
public void testStopInInlineCallLocalFunLambda() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/stepOver/stopInInlineCallLocalFunLambda.kt");
|
||||
@@ -746,6 +758,18 @@ public class KotlinSteppingTestGenerated extends AbstractKotlinSteppingTest {
|
||||
doStepOverTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("stopInLambdaInInlinedCallWithCrossInline.kt")
|
||||
public void testStopInLambdaInInlinedCallWithCrossInline() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/stepOver/stopInLambdaInInlinedCallWithCrossInline.kt");
|
||||
doStepOverTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("stopInLambdaInInlinedCallWithCrossInlineDex.kt")
|
||||
public void testStopInLambdaInInlinedCallWithCrossInlineDex() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/stepOver/stopInLambdaInInlinedCallWithCrossInlineDex.kt");
|
||||
doStepOverTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("stopInLambdaInlineCallLambda.kt")
|
||||
public void testStopInLambdaInlineCallLambda() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/debugger/tinyApp/src/stepping/stepOver/stopInLambdaInlineCallLambda.kt");
|
||||
|
||||
Reference in New Issue
Block a user