WEB-20340 JavaScript debugger doesn't show "this" reference with ES6 fat arrows

This commit is contained in:
Vladimir Krivosheev
2016-03-26 17:52:31 +01:00
parent 9f4d5f85ae
commit b70405b25f
4 changed files with 38 additions and 17 deletions
@@ -15,12 +15,8 @@
*/
package org.jetbrains.debugger
open class MemberFilterWithNameMappings(rawNameToSource: Map<String, String>?) : MemberFilter {
protected val rawNameToSource = rawNameToSource ?: emptyMap<String, String>()
override fun hasNameMappings(): Boolean {
return !rawNameToSource.isEmpty()
}
open class MemberFilterWithNameMappings(protected val rawNameToSource: Map<String, String> = emptyMap()) : MemberFilter {
override fun hasNameMappings() = !rawNameToSource.isEmpty()
override fun rawNameToSource(variable: Variable): String {
val name = variable.name
@@ -28,9 +24,7 @@ open class MemberFilterWithNameMappings(rawNameToSource: Map<String, String>?) :
return sourceName ?: normalizeMemberName(name)
}
protected open fun normalizeMemberName(name: String): String {
return name
}
protected open fun normalizeMemberName(name: String) = name
override fun sourceNameToRaw(name: String): String? {
if (!hasNameMappings()) {
@@ -19,8 +19,10 @@ import com.intellij.xdebugger.XDebuggerBundle
import com.intellij.xdebugger.frame.XCompositeNode
import com.intellij.xdebugger.frame.XValueChildrenList
import com.intellij.xdebugger.frame.XValueGroup
import org.jetbrains.concurrency.Promise
import org.jetbrains.concurrency.done
import org.jetbrains.concurrency.rejected
import org.jetbrains.concurrency.thenAsyncAccept
class ScopeVariablesGroup(val scope: Scope, parentContext: VariableContext, callFrame: CallFrame?) : XValueGroup(scope.createScopeNodeName()) {
private val context = createVariableContext(scope, parentContext, callFrame)
@@ -42,15 +44,35 @@ class ScopeVariablesGroup(val scope: Scope, parentContext: VariableContext, call
promise
.done(node) {
callFrame.receiverVariable
.done(node) {
node.addChildren(if (it == null) XValueChildrenList.EMPTY else XValueChildrenList.singleton(VariableView(it, context)), true)
context.memberFilter
.thenAsyncAccept(node) { memberFilter ->
if (memberFilter.hasNameMappings()) {
memberFilter.sourceNameToRaw(RECEIVER_NAME)?.let {
return@thenAsyncAccept callFrame.evaluateContext.evaluate(it)
.done(node) {
VariableImpl(RECEIVER_NAME, it.value, null)
node.addChildren(XValueChildrenList.singleton(VariableView(VariableImpl(RECEIVER_NAME, it.value, null), context)), true)
}
}
}
computeReceiverVariable(callFrame, node)
}
.rejected(node) {
node.addChildren(XValueChildrenList.EMPTY, true)
computeReceiverVariable(callFrame, node)
}
}
}
private fun computeReceiverVariable(callFrame: CallFrame, node: XCompositeNode): Promise<*> {
return callFrame.receiverVariable
.done(node) {
node.addChildren(if (it == null) XValueChildrenList.EMPTY else XValueChildrenList.singleton(VariableView(it, context)), true)
}
.rejected(node) {
node.addChildren(XValueChildrenList.EMPTY, true)
}
}
}
fun createAndAddScopeList(node: XCompositeNode, scopes: List<Scope>, context: VariableContext, callFrame: CallFrame?) {
@@ -34,13 +34,13 @@ private val OPERATOR_TRIMMER = CharMatcher.INVISIBLE.or(CharMatcher.anyOf(S1))
val NAME_TRIMMER = CharMatcher.INVISIBLE.or(CharMatcher.anyOf(S1 + ".&:"))
// generateVirtualFile only for debug purposes
open class NameMapper(private val document: Document, private val transpiledDocument: Document, private val sourceMappings: MappingList, private val sourceMap: SourceMap, private val transpiledFile: VirtualFile? = null) {
open class NameMapper(private val document: Document, private val transpiledDocument: Document, private val sourceMappings: MappingList, protected val sourceMap: SourceMap, private val transpiledFile: VirtualFile? = null) {
var rawNameToSource: MutableMap<String, String>? = null
private set
// PsiNamedElement, JSVariable for example
// returns generated name
fun map(identifierOrNamedElement: PsiElement): String? {
open fun map(identifierOrNamedElement: PsiElement): String? {
val offset = identifierOrNamedElement.textOffset
val line = document.getLineNumber(offset)
@@ -67,15 +67,19 @@ open class NameMapper(private val document: Document, private val transpiledDocu
}
var sourceName = sourceEntry.name
if (sourceName == null || Registry.`is`("js.debugger.name.mappings.by.source.code", false)) {
if (sourceName == null || (Registry.`is`("js.debugger.name.mappings.by.source.code", false) || Registry.`is`("js.debugger.map.this.by.source.code", false))) {
sourceName = (identifierOrNamedElement as? PsiNamedElement)?.name ?: identifierOrNamedElement.text ?: sourceName ?: return null
}
addMapping(generatedName, sourceName)
return generatedName
}
fun addMapping(generatedName: String, sourceName: String) {
if (rawNameToSource == null) {
rawNameToSource = THashMap<String, String>()
}
rawNameToSource!!.put(generatedName, sourceName)
return generatedName
}
protected open fun extractName(rawGeneratedName: CharSequence) = NAME_TRIMMER.trimFrom(rawGeneratedName)
@@ -554,6 +554,7 @@ js.debugger.v8.use.any.breakpoint=true
js.debugger.chrome.use.any.breakpoint=true
nodejs.debugger.use.jb.support=true
js.debugger.name.mappings.by.source.code=false
js.debugger.map.this.by.source.code=false
js.debugger.v8.log=
js.debugger.wip.log=
js.debugger.fix.jspm.source.maps=false