Drop unnecesary logic about additional context for lambda in debugger
This commit is contained in:
@@ -40,9 +40,6 @@ public abstract class KtCodeFragment(
|
|||||||
|
|
||||||
private var viewProvider = super<KtFile>.getViewProvider() as SingleRootFileViewProvider
|
private var viewProvider = super<KtFile>.getViewProvider() as SingleRootFileViewProvider
|
||||||
private var imports = LinkedHashSet<String>()
|
private var imports = LinkedHashSet<String>()
|
||||||
private val additionalContextForLambda: PsiElement? by lazy {
|
|
||||||
this.getCopyableUserData(ADDITIONAL_CONTEXT_FOR_LAMBDA)?.invoke()
|
|
||||||
}
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
getViewProvider().forceCachedPsi(this)
|
getViewProvider().forceCachedPsi(this)
|
||||||
@@ -69,7 +66,7 @@ public abstract class KtCodeFragment(
|
|||||||
|
|
||||||
override fun isValid() = true
|
override fun isValid() = true
|
||||||
|
|
||||||
override fun getContext() = additionalContextForLambda ?: context
|
override fun getContext() = context
|
||||||
|
|
||||||
override fun getResolveScope() = context?.getResolveScope() ?: super<KtFile>.getResolveScope()
|
override fun getResolveScope() = context?.getResolveScope() ?: super<KtFile>.getResolveScope()
|
||||||
|
|
||||||
|
|||||||
@@ -20,9 +20,7 @@ import com.intellij.debugger.DebuggerManagerEx
|
|||||||
import com.intellij.debugger.engine.evaluation.CodeFragmentFactory
|
import com.intellij.debugger.engine.evaluation.CodeFragmentFactory
|
||||||
import com.intellij.debugger.engine.evaluation.CodeFragmentKind
|
import com.intellij.debugger.engine.evaluation.CodeFragmentKind
|
||||||
import com.intellij.debugger.engine.evaluation.TextWithImports
|
import com.intellij.debugger.engine.evaluation.TextWithImports
|
||||||
import com.intellij.debugger.engine.events.DebuggerCommandImpl
|
|
||||||
import com.intellij.debugger.jdi.StackFrameProxyImpl
|
import com.intellij.debugger.jdi.StackFrameProxyImpl
|
||||||
import com.intellij.openapi.application.ApplicationManager
|
|
||||||
import com.intellij.openapi.diagnostic.Logger
|
import com.intellij.openapi.diagnostic.Logger
|
||||||
import com.intellij.openapi.progress.ProgressManager
|
import com.intellij.openapi.progress.ProgressManager
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
@@ -34,24 +32,21 @@ import com.intellij.util.concurrency.Semaphore
|
|||||||
import com.intellij.xdebugger.XDebuggerManager
|
import com.intellij.xdebugger.XDebuggerManager
|
||||||
import com.intellij.xdebugger.impl.XDebugSessionImpl
|
import com.intellij.xdebugger.impl.XDebugSessionImpl
|
||||||
import com.intellij.xdebugger.impl.ui.tree.ValueMarkup
|
import com.intellij.xdebugger.impl.ui.tree.ValueMarkup
|
||||||
import com.sun.jdi.*
|
import com.sun.jdi.ArrayReference
|
||||||
|
import com.sun.jdi.PrimitiveValue
|
||||||
|
import com.sun.jdi.Value
|
||||||
import org.jetbrains.annotations.TestOnly
|
import org.jetbrains.annotations.TestOnly
|
||||||
import org.jetbrains.eval4j.jdi.asValue
|
import org.jetbrains.eval4j.jdi.asValue
|
||||||
import org.jetbrains.kotlin.asJava.KtLightClass
|
import org.jetbrains.kotlin.asJava.KtLightClass
|
||||||
import org.jetbrains.kotlin.idea.KotlinFileType
|
import org.jetbrains.kotlin.idea.KotlinFileType
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
|
||||||
import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils
|
import org.jetbrains.kotlin.idea.codeInsight.CodeInsightUtils
|
||||||
import org.jetbrains.kotlin.idea.core.refactoring.j2kText
|
import org.jetbrains.kotlin.idea.core.refactoring.j2kText
|
||||||
import org.jetbrains.kotlin.idea.core.refactoring.quoteIfNeeded
|
import org.jetbrains.kotlin.idea.core.refactoring.quoteIfNeeded
|
||||||
import org.jetbrains.kotlin.idea.debugger.KotlinEditorTextProvider
|
import org.jetbrains.kotlin.idea.debugger.KotlinEditorTextProvider
|
||||||
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
||||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
|
||||||
import org.jetbrains.kotlin.name.Name
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext
|
import org.jetbrains.kotlin.psi.psiUtil.getElementTextWithContext
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
|
|
||||||
import org.jetbrains.kotlin.resolve.inline.InlineUtil
|
|
||||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
import org.jetbrains.kotlin.types.typeUtil.makeNullable
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.check
|
import org.jetbrains.kotlin.utils.addToStdlib.check
|
||||||
@@ -115,61 +110,6 @@ class KotlinCodeFragmentFactory: CodeFragmentFactory() {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
if (contextElement != null) {
|
|
||||||
val lambda = getInlineLambdaIfInside(contextElement)
|
|
||||||
if (lambda != null) {
|
|
||||||
codeFragment.putCopyableUserData(KtCodeFragment.ADDITIONAL_CONTEXT_FOR_LAMBDA, lamdba@ {
|
|
||||||
val debuggerContext = DebuggerManagerEx.getInstanceEx(project).context
|
|
||||||
|
|
||||||
val semaphore = Semaphore()
|
|
||||||
semaphore.down()
|
|
||||||
|
|
||||||
var visibleVariables: Map<LocalVariable, Value>? = null
|
|
||||||
|
|
||||||
val worker = object : DebuggerCommandImpl() {
|
|
||||||
override fun action() {
|
|
||||||
try {
|
|
||||||
val frame = if (ApplicationManager.getApplication().isUnitTestMode)
|
|
||||||
context?.getCopyableUserData(DEBUG_FRAME_FOR_TESTS)?.stackFrame
|
|
||||||
else
|
|
||||||
debuggerContext.frameProxy?.stackFrame
|
|
||||||
|
|
||||||
visibleVariables = frame?.let {
|
|
||||||
f ->
|
|
||||||
val variables = f.visibleVariables().filter {
|
|
||||||
!it.name().startsWith(JvmAbi.LOCAL_VARIABLE_NAME_PREFIX_INLINE_ARGUMENT) &&
|
|
||||||
!it.name().startsWith(JvmAbi.LOCAL_VARIABLE_NAME_PREFIX_INLINE_FUNCTION)
|
|
||||||
}
|
|
||||||
f.getValues(variables)
|
|
||||||
} ?: emptyMap<LocalVariable, Value>()
|
|
||||||
}
|
|
||||||
catch(ignored: AbsentInformationException) {
|
|
||||||
// Debug info unavailable
|
|
||||||
}
|
|
||||||
finally {
|
|
||||||
semaphore.up()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
debuggerContext.debugProcess?.managerThread?.invoke(worker)
|
|
||||||
|
|
||||||
for (i in 0..50) {
|
|
||||||
if (semaphore.waitFor(20)) break
|
|
||||||
}
|
|
||||||
|
|
||||||
if (visibleVariables == null) return@lamdba null
|
|
||||||
|
|
||||||
val fragmentForVisibleVariables = createCodeFragmentForVisibleVariables(lambda.project, visibleVariables!!)
|
|
||||||
return@lamdba createWrappingContext(
|
|
||||||
fragmentForVisibleVariables.first,
|
|
||||||
fragmentForVisibleVariables.second,
|
|
||||||
lambda.bodyExpression,
|
|
||||||
lambda.project)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return codeFragment
|
return codeFragment
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -226,19 +166,6 @@ class KotlinCodeFragmentFactory: CodeFragmentFactory() {
|
|||||||
|
|
||||||
private fun KtElement?.check(): Boolean = this != null && this.check { KotlinEditorTextProvider.isAcceptedAsCodeFragmentContext(it) } != null
|
private fun KtElement?.check(): Boolean = this != null && this.check { KotlinEditorTextProvider.isAcceptedAsCodeFragmentContext(it) } != null
|
||||||
|
|
||||||
private fun getInlineLambdaIfInside(contextElement: KtElement): KtFunction? {
|
|
||||||
val parentLambda = contextElement.getParentOfType<KtFunction>(false) ?: return null
|
|
||||||
|
|
||||||
if (!parentLambda.isLocal) return null
|
|
||||||
if (KtPsiUtil.getParentCallIfPresent(parentLambda) == null) return null
|
|
||||||
|
|
||||||
val bindingContext = contextElement.analyze(BodyResolveMode.PARTIAL)
|
|
||||||
if (InlineUtil.isInlinedArgument(parentLambda, bindingContext, false)) {
|
|
||||||
return parentLambda
|
|
||||||
}
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
//internal for tests
|
//internal for tests
|
||||||
fun createCodeFragmentForLabeledObjects(project: Project, markupMap: Map<*, ValueMarkup>): Pair<String, Map<String, Value>> {
|
fun createCodeFragmentForLabeledObjects(project: Project, markupMap: Map<*, ValueMarkup>): Pair<String, Map<String, Value>> {
|
||||||
val sb = StringBuilder()
|
val sb = StringBuilder()
|
||||||
@@ -259,22 +186,6 @@ class KotlinCodeFragmentFactory: CodeFragmentFactory() {
|
|||||||
return sb.toString() to labeledObjects
|
return sb.toString() to labeledObjects
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createCodeFragmentForVisibleVariables(project: Project, visibleVariables: Map<LocalVariable, Value>): Pair<String, Map<String, Value>> {
|
|
||||||
val sb = StringBuilder()
|
|
||||||
val labeledObjects = HashMap<String, Value>()
|
|
||||||
for ((variable, value) in visibleVariables) {
|
|
||||||
val variableName = variable.name()
|
|
||||||
if (!Name.isValidIdentifier(variableName)) continue
|
|
||||||
|
|
||||||
val kotlinProperty = createKotlinProperty(project, variableName, variable.typeName(), value) ?: continue
|
|
||||||
sb.append("$kotlinProperty\n")
|
|
||||||
|
|
||||||
labeledObjects.put(variableName, value)
|
|
||||||
}
|
|
||||||
sb.append("val _debug_context_val = 1")
|
|
||||||
return sb.toString() to labeledObjects
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun createKotlinProperty(project: Project, variableName: String, variableTypeName: String, value: Value): String? {
|
private fun createKotlinProperty(project: Project, variableName: String, variableTypeName: String, value: Value): String? {
|
||||||
val actualClassDescriptor = value.asValue().asmType.getClassDescriptor(project)
|
val actualClassDescriptor = value.asValue().asmType.getClassDescriptor(project)
|
||||||
if (actualClassDescriptor != null && actualClassDescriptor.defaultType.arguments.isEmpty()) {
|
if (actualClassDescriptor != null && actualClassDescriptor.defaultType.arguments.isEmpty()) {
|
||||||
|
|||||||
@@ -1,14 +1,12 @@
|
|||||||
LineBreakpoint created at parametersOfInlineFun.kt:8
|
LineBreakpoint created at parametersOfInlineFun.kt:15
|
||||||
!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! parametersOfInlineFun.ParametersOfInlineFunKt
|
!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! parametersOfInlineFun.ParametersOfInlineFunKt
|
||||||
Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
||||||
parametersOfInlineFun.kt:8
|
parametersOfInlineFun.kt:15
|
||||||
parametersOfInlineFun.kt:8
|
|
||||||
Compile bytecode for primitive
|
Compile bytecode for primitive
|
||||||
Compile bytecode for it
|
|
||||||
Compile bytecode for array
|
Compile bytecode for array
|
||||||
Compile bytecode for str
|
Compile bytecode for str
|
||||||
Compile bytecode for list
|
Compile bytecode for list
|
||||||
Compile bytecode for `$receiver`.prop
|
Compile bytecode for this.prop
|
||||||
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
Disconnected from the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
||||||
|
|
||||||
Process finished with exit code 0
|
Process finished with exit code 0
|
||||||
|
|||||||
+1
-4
@@ -21,9 +21,6 @@ class A(val prop: Int)
|
|||||||
// EXPRESSION: primitive
|
// EXPRESSION: primitive
|
||||||
// RESULT: 1: I
|
// RESULT: 1: I
|
||||||
|
|
||||||
// EXPRESSION: it
|
|
||||||
// RESULT: 1: I
|
|
||||||
|
|
||||||
// EXPRESSION: array
|
// EXPRESSION: array
|
||||||
// RESULT: instance of java.lang.Integer[1] (id=ID): [Ljava/lang/Integer;
|
// RESULT: instance of java.lang.Integer[1] (id=ID): [Ljava/lang/Integer;
|
||||||
|
|
||||||
@@ -33,5 +30,5 @@ class A(val prop: Int)
|
|||||||
// EXPRESSION: list
|
// EXPRESSION: list
|
||||||
// RESULT: instance of java.util.Collections$SingletonList(id=ID): Ljava/util/Collections$SingletonList;
|
// RESULT: instance of java.util.Collections$SingletonList(id=ID): Ljava/util/Collections$SingletonList;
|
||||||
|
|
||||||
// EXPRESSION: `$receiver`.prop
|
// EXPRESSION: this.prop
|
||||||
// RESULT: 1: I
|
// RESULT: 1: I
|
||||||
Reference in New Issue
Block a user