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 imports = LinkedHashSet<String>()
|
||||
private val additionalContextForLambda: PsiElement? by lazy {
|
||||
this.getCopyableUserData(ADDITIONAL_CONTEXT_FOR_LAMBDA)?.invoke()
|
||||
}
|
||||
|
||||
init {
|
||||
getViewProvider().forceCachedPsi(this)
|
||||
@@ -69,7 +66,7 @@ public abstract class KtCodeFragment(
|
||||
|
||||
override fun isValid() = true
|
||||
|
||||
override fun getContext() = additionalContextForLambda ?: context
|
||||
override fun getContext() = context
|
||||
|
||||
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.CodeFragmentKind
|
||||
import com.intellij.debugger.engine.evaluation.TextWithImports
|
||||
import com.intellij.debugger.engine.events.DebuggerCommandImpl
|
||||
import com.intellij.debugger.jdi.StackFrameProxyImpl
|
||||
import com.intellij.openapi.application.ApplicationManager
|
||||
import com.intellij.openapi.diagnostic.Logger
|
||||
import com.intellij.openapi.progress.ProgressManager
|
||||
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.impl.XDebugSessionImpl
|
||||
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.eval4j.jdi.asValue
|
||||
import org.jetbrains.kotlin.asJava.KtLightClass
|
||||
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.core.refactoring.j2kText
|
||||
import org.jetbrains.kotlin.idea.core.refactoring.quoteIfNeeded
|
||||
import org.jetbrains.kotlin.idea.debugger.KotlinEditorTextProvider
|
||||
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
||||
import org.jetbrains.kotlin.load.java.JvmAbi
|
||||
import org.jetbrains.kotlin.name.Name
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
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.typeUtil.makeNullable
|
||||
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
|
||||
}
|
||||
|
||||
@@ -226,19 +166,6 @@ class KotlinCodeFragmentFactory: CodeFragmentFactory() {
|
||||
|
||||
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
|
||||
fun createCodeFragmentForLabeledObjects(project: Project, markupMap: Map<*, ValueMarkup>): Pair<String, Map<String, Value>> {
|
||||
val sb = StringBuilder()
|
||||
@@ -259,22 +186,6 @@ class KotlinCodeFragmentFactory: CodeFragmentFactory() {
|
||||
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? {
|
||||
val actualClassDescriptor = value.asValue().asmType.getClassDescriptor(project)
|
||||
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
|
||||
Connected to the target VM, address: '!HOST_NAME!:PORT_NAME!', transport: 'socket'
|
||||
parametersOfInlineFun.kt:8
|
||||
parametersOfInlineFun.kt:8
|
||||
parametersOfInlineFun.kt:15
|
||||
Compile bytecode for primitive
|
||||
Compile bytecode for it
|
||||
Compile bytecode for array
|
||||
Compile bytecode for str
|
||||
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'
|
||||
|
||||
Process finished with exit code 0
|
||||
|
||||
+1
-4
@@ -21,9 +21,6 @@ class A(val prop: Int)
|
||||
// EXPRESSION: primitive
|
||||
// RESULT: 1: I
|
||||
|
||||
// EXPRESSION: it
|
||||
// RESULT: 1: I
|
||||
|
||||
// EXPRESSION: array
|
||||
// RESULT: instance of java.lang.Integer[1] (id=ID): [Ljava/lang/Integer;
|
||||
|
||||
@@ -33,5 +30,5 @@ class A(val prop: Int)
|
||||
// EXPRESSION: list
|
||||
// RESULT: instance of java.util.Collections$SingletonList(id=ID): Ljava/util/Collections$SingletonList;
|
||||
|
||||
// EXPRESSION: `$receiver`.prop
|
||||
// EXPRESSION: this.prop
|
||||
// RESULT: 1: I
|
||||
Reference in New Issue
Block a user