Drop unnecesary logic about additional context for lambda in debugger

This commit is contained in:
Natalia Ukhorskaya
2015-11-30 18:22:16 +03:00
parent f34f7556bc
commit 29778311e8
4 changed files with 8 additions and 105 deletions
@@ -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
@@ -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