Debugger: Pass files with inline functions to backend (KT-36404)

This commit is contained in:
Yan Zhulanow
2020-02-13 22:23:00 +09:00
parent 85a5e5241f
commit 0afd73b95c
5 changed files with 87 additions and 7 deletions
@@ -221,7 +221,7 @@ class KotlinEvaluator(val codeFragment: KtCodeFragment, private val sourcePositi
analysisResult = analyze(codeFragment, status, debugProcess)
}
val (bindingContext) = runReadAction {
val (bindingContext, filesToCompile) = runReadAction {
val resolutionFacade = getResolutionFacadeForCodeFragment(codeFragment)
DebuggerUtils.analyzeInlinedFunctions(resolutionFacade, codeFragment, false, analysisResult.bindingContext)
}
@@ -229,7 +229,7 @@ class KotlinEvaluator(val codeFragment: KtCodeFragment, private val sourcePositi
val moduleDescriptor = analysisResult.moduleDescriptor
try {
val result = CodeFragmentCompiler(context, status).compile(codeFragment, bindingContext, moduleDescriptor)
val result = CodeFragmentCompiler(context, status).compile(codeFragment, filesToCompile, bindingContext, moduleDescriptor)
return createCompiledDataDescriptor(result, sourcePosition)
} catch (e: Throwable) {
status.error(EvaluationError.BackendException)
@@ -52,12 +52,16 @@ class CodeFragmentCompiler(private val executionContext: ExecutionContext, priva
val mainMethodSignature: MethodSignature
)
fun compile(codeFragment: KtCodeFragment, bindingContext: BindingContext, moduleDescriptor: ModuleDescriptor): CompilationResult {
return runReadAction { doCompile(codeFragment, bindingContext, moduleDescriptor) }
fun compile(
codeFragment: KtCodeFragment, filesToCompile: List<KtFile>,
bindingContext: BindingContext, moduleDescriptor: ModuleDescriptor
): CompilationResult {
return runReadAction { doCompile(codeFragment, filesToCompile, bindingContext, moduleDescriptor) }
}
private fun doCompile(
codeFragment: KtCodeFragment, bindingContext: BindingContext, moduleDescriptor: ModuleDescriptor
codeFragment: KtCodeFragment, filesToCompile: List<KtFile>,
bindingContext: BindingContext, moduleDescriptor: ModuleDescriptor
): CompilationResult {
require(codeFragment is KtBlockCodeFragment || codeFragment is KtExpressionCodeFragment) {
"Unsupported code fragment type: $codeFragment"
@@ -76,8 +80,8 @@ class CodeFragmentCompiler(private val executionContext: ExecutionContext, priva
val generationState = GenerationState.Builder(
project, ClassBuilderFactories.BINARIES, moduleDescriptorWrapper,
bindingContext, listOf(codeFragment), compilerConfiguration
).build()
bindingContext, filesToCompile, compilerConfiguration
).generateDeclaredClassFilter(GeneratedClassFilterForCodeFragment(codeFragment)).build()
val parameterInfo = CodeFragmentParameterAnalyzer(executionContext, codeFragment, bindingContext, status).analyze()
val (classDescriptor, methodDescriptor) = createDescriptorsForCodeFragment(
@@ -105,6 +109,14 @@ class CodeFragmentCompiler(private val executionContext: ExecutionContext, priva
}
}
private class GeneratedClassFilterForCodeFragment(private val codeFragment: KtCodeFragment) : GenerationState.GenerateClassFilter() {
override fun shouldGeneratePackagePart(@Suppress("PARAMETER_NAME_CHANGED_ON_OVERRIDE") file: KtFile) = file == codeFragment
override fun shouldAnnotateClass(processingClassOrObject: KtClassOrObject) = true
override fun shouldGenerateClass(processingClassOrObject: KtClassOrObject) = processingClassOrObject.containingFile == codeFragment
override fun shouldGenerateCodeFragment(codeFragment: KtCodeFragment) = codeFragment == this.codeFragment
override fun shouldGenerateScript(script: KtScript) = false
}
private fun getLocalFunctionSuffixes(
parameters: List<CodeFragmentParameter.Smart>,
typeMapper: KotlinTypeMapper
@@ -310,6 +310,11 @@ public class KotlinEvaluateExpressionTestGenerated extends AbstractKotlinEvaluat
runTest("idea/jvm-debugger/jvm-debugger-test/testData/evaluation/singleBreakpoint/kt31709.kt");
}
@TestMetadata("kt36404.kt")
public void testKt36404() throws Exception {
runTest("idea/jvm-debugger/jvm-debugger-test/testData/evaluation/singleBreakpoint/kt36404.kt");
}
@TestMetadata("kt5554OnlyIntsShouldBeCoerced.kt")
public void testKt5554OnlyIntsShouldBeCoerced() throws Exception {
runTest("idea/jvm-debugger/jvm-debugger-test/testData/evaluation/singleBreakpoint/kt5554OnlyIntsShouldBeCoerced.kt");
@@ -0,0 +1,53 @@
// FILE: lib/Application.java
package lib;
import org.jetbrains.annotations.NotNull;
import java.util.function.Supplier;
public interface Application {
static Application getInstance() {
return new Application() {
@Override
public void runReadAction(@NotNull Runnable runnable) {
runnable.run();
}
@Override
public <T> T runReadAction(@NotNull Fun<T> computation) {
return computation.invoke();
}
};
}
void runReadAction(@NotNull Runnable runnable);
<T> T runReadAction(@NotNull Fun<T> computation);
}
// FILE: lib/Fun.java
package lib;
public interface Fun<T> {
T invoke();
}
// FILE: lib/foo.kt
package lib
inline fun <R> runReadAction(crossinline runnable: () -> R): R {
return Application.getInstance().runReadAction(Fun { runnable() })
}
// FILE: test.kt
package test
import lib.*
fun main() {
//Breakpoint!
println(runReadAction { "hello" })
}
// EXPRESSION: runReadAction { "hello" }
// RESULT: "hello": Ljava/lang/String;
@@ -0,0 +1,10 @@
LineBreakpoint created at test.kt:8
Run Java
Connected to the target VM
test.kt:8
Compile bytecode for runReadAction { "hello" }
test.kt:8
Disconnected from the target VM
Process finished with exit code 0
hello