Skip to content

Commit ebf79de

Browse files
committed
more variable show inline values
1 parent 2cb0437 commit ebf79de

File tree

4 files changed

+355
-58
lines changed

4 files changed

+355
-58
lines changed

src/main/java/com/tang/intellij/lua/debugger/LuaDebugVariableContext.kt

Lines changed: 116 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,20 @@
1616

1717
package com.tang.intellij.lua.debugger
1818

19+
import com.intellij.openapi.application.ReadAction
1920
import com.intellij.openapi.editor.Editor
2021
import com.intellij.openapi.util.TextRange
2122
import com.intellij.openapi.vfs.VirtualFile
23+
import com.intellij.psi.PsiDocumentManager
24+
import com.intellij.psi.PsiFile
2225
import com.intellij.xdebugger.XDebuggerUtil
2326
import com.intellij.xdebugger.XSourcePosition
2427
import com.intellij.xdebugger.frame.XStackFrame
2528
import com.tang.intellij.lua.debugger.emmy.EmmyDebugStackFrame
2629
import com.tang.intellij.lua.debugger.emmy.value.LuaXValue
2730
import com.tang.intellij.lua.editor.LuaEditorUtil
2831
import com.tang.intellij.lua.lang.LSPIJUtils
32+
import com.tang.intellij.lua.psi.LuaPsiFile
2933

3034
/**
3135
* Context for tracking variable positions during debugging
@@ -34,24 +38,41 @@ import com.tang.intellij.lua.lang.LSPIJUtils
3438
class LuaDebugVariableContext(
3539
private val stackFrame: XStackFrame
3640
) {
37-
private val variableRanges = mutableMapOf<String, TextRange>()
38-
private val variablePositions = mutableMapOf<String, XSourcePosition>()
41+
// Store multiple ranges for each variable (for multiple occurrences)
42+
private val variableRanges = mutableMapOf<String, MutableList<TextRange>>()
43+
private val variablePositions = mutableMapOf<String, MutableList<XSourcePosition>>()
3944
private val providers = mutableListOf<LuaDebugVariablePositionProvider>()
4045
private var editor: Editor? = null
4146
private var endLineOffset: Int = -1
47+
private var psiFile: PsiFile? = null
48+
private var sourcePosition: XSourcePosition? = null
4249

4350
init {
44-
// Register default provider
45-
providers.add(LuaHighlighterDebugVariablePositionProvider())
51+
// Register PSI-based provider (more accurate than highlighter-based)
52+
providers.add(LuaPsiDebugVariablePositionProvider())
53+
54+
println("LuaDebugVariableContext: Initializing...")
55+
56+
// Initialize editor and PSI file if available
57+
sourcePosition = stackFrame.sourcePosition
58+
println("LuaDebugVariableContext: sourcePosition = $sourcePosition")
4659

47-
// Initialize editor if available
48-
val sourcePosition = stackFrame.sourcePosition
4960
if (sourcePosition != null && stackFrame is EmmyDebugStackFrame) {
5061
val project = stackFrame.process.session.project
51-
val editors = LuaEditorUtil.findEditors(project, sourcePosition.file)
62+
val editors = LuaEditorUtil.findEditors(project, sourcePosition!!.file)
5263
editor = editors.firstOrNull()
64+
65+
println("LuaDebugVariableContext: Found ${editors.size} editors, using first: $editor")
66+
5367
if (editor != null) {
54-
endLineOffset = editor!!.document.getLineEndOffset(sourcePosition.line)
68+
endLineOffset = editor!!.document.getLineEndOffset(sourcePosition!!.line)
69+
println("LuaDebugVariableContext: endLineOffset = $endLineOffset")
70+
71+
// Get PSI file from document - must be done in ReadAction
72+
ReadAction.run<RuntimeException> {
73+
psiFile = PsiDocumentManager.getInstance(project).getPsiFile(editor!!.document)
74+
println("LuaDebugVariableContext: psiFile = $psiFile (${psiFile?.javaClass?.simpleName})")
75+
}
5576
}
5677
}
5778
}
@@ -79,52 +100,118 @@ class LuaDebugVariableContext(
79100
fun getEndLineOffset(): Int = endLineOffset
80101

81102
/**
82-
* Add a variable range
103+
* Get the PSI file for this context
104+
*/
105+
fun getPsiFile(): PsiFile? = psiFile
106+
107+
/**
108+
* Get the source position for this context
109+
*/
110+
fun getSourcePosition(): XSourcePosition? = sourcePosition
111+
112+
/**
113+
* Add a variable range (supports multiple occurrences of the same variable)
83114
*/
84115
fun addVariableRange(variableName: String, textRange: TextRange) {
85-
variableRanges[variableName] = textRange
116+
val ranges = variableRanges.getOrPut(variableName) { mutableListOf() }
117+
ranges.add(textRange)
86118
}
87119

88120
/**
89121
* Add a variable position
90122
*/
91123
fun addVariablePosition(variableName: String, position: XSourcePosition) {
92-
variablePositions[variableName] = position
124+
val positions = variablePositions.getOrPut(variableName) { mutableListOf() }
125+
positions.add(position)
93126
}
94127

95128
/**
96-
* Get source position for a variable name
129+
* Get all source positions for a variable name
130+
* This is used to display inline values at all occurrences of the variable
97131
*/
98-
fun getSourcePosition(name: String): XSourcePosition? {
99-
// Return cached position if available
100-
variablePositions[name]?.let { return it }
132+
fun getAllSourcePositions(name: String): List<XSourcePosition> {
133+
println("LuaDebugVariableContext.getAllSourcePositions: Looking for all positions of '$name'")
101134

102-
// Try to create position from range
103-
val textRange = variableRanges[name] ?: return null
104-
val file = getFile() ?: return null
105-
val ed = editor ?: return null
135+
// Return cached positions if available
136+
variablePositions[name]?.let {
137+
if (it.isNotEmpty()) {
138+
println("LuaDebugVariableContext.getAllSourcePositions: Found ${it.size} cached positions for '$name'")
139+
return it
140+
}
141+
}
106142

107-
val range = com.tang.intellij.lua.lang.LSPIJUtils.toRange(textRange, ed.document)
108-
val position = XDebuggerUtil.getInstance()
109-
.createPosition(file, range.start.line, range.end.character)
143+
// Try to create positions from all ranges
144+
val ranges = variableRanges[name]
145+
if (ranges == null || ranges.isEmpty()) {
146+
println("LuaDebugVariableContext.getAllSourcePositions: No ranges found for '$name'")
147+
println("LuaDebugVariableContext.getAllSourcePositions: Available variables: ${variableRanges.keys}")
148+
return emptyList()
149+
}
110150

111-
if (position != null) {
112-
addVariablePosition(name, position)
151+
val file = getFile()
152+
if (file == null) {
153+
println("LuaDebugVariableContext.getAllSourcePositions: file is null")
154+
return emptyList()
113155
}
114156

115-
return position
157+
val ed = editor
158+
if (ed == null) {
159+
println("LuaDebugVariableContext.getAllSourcePositions: editor is null")
160+
return emptyList()
161+
}
162+
163+
// Create positions for all occurrences
164+
val positions = mutableListOf<XSourcePosition>()
165+
for (textRange in ranges) {
166+
val range = com.tang.intellij.lua.lang.LSPIJUtils.toRange(textRange, ed.document)
167+
println("LuaDebugVariableContext.getAllSourcePositions: Range for '$name': line ${range.start.line}, char ${range.start.character}-${range.end.character}")
168+
169+
val position = XDebuggerUtil.getInstance()
170+
.createPosition(file, range.start.line, range.start.character)
171+
172+
if (position != null) {
173+
println("LuaDebugVariableContext.getAllSourcePositions: Created position: $position")
174+
positions.add(position)
175+
}
176+
}
177+
178+
// Cache the positions
179+
if (positions.isNotEmpty()) {
180+
variablePositions[name] = positions.toMutableList()
181+
}
182+
183+
println("LuaDebugVariableContext.getAllSourcePositions: Returning ${positions.size} positions for '$name'")
184+
return positions
116185
}
117186

118187
/**
119-
* Get source position for a variable value
188+
* Get source position for a variable name
189+
* Returns the first occurrence position (can be extended to return all)
120190
*/
121-
fun getSourcePositionFor(value: LuaXValue): XSourcePosition? {
191+
fun getSourcePosition(name: String): XSourcePosition? {
192+
val positions = getAllSourcePositions(name)
193+
return positions.firstOrNull()
194+
}
195+
196+
/**
197+
* Get all source positions for a variable value
198+
*/
199+
fun getAllSourcePositionsFor(value: LuaXValue): List<XSourcePosition> {
122200
for (provider in providers) {
201+
// For now, use getSourcePosition - could be extended to support multiple positions from provider
123202
val position = provider.getSourcePosition(value, this)
124203
if (position != null) {
125-
return position
204+
// Return all positions for this variable name
205+
return getAllSourcePositions(value.name)
126206
}
127207
}
128-
return null
208+
return emptyList()
209+
}
210+
211+
/**
212+
* Get source position for a variable value
213+
*/
214+
fun getSourcePositionFor(value: LuaXValue): XSourcePosition? {
215+
return getAllSourcePositionsFor(value).firstOrNull()
129216
}
130217
}

src/main/java/com/tang/intellij/lua/debugger/LuaDebuggerEvaluator.kt

Lines changed: 34 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
package com.tang.intellij.lua.debugger
1818

19+
import com.intellij.openapi.application.ApplicationManager
1920
import com.intellij.openapi.editor.Document
2021
import com.intellij.openapi.project.IndexNotReadyException
2122
import com.intellij.openapi.project.Project
@@ -32,18 +33,27 @@ import com.tang.intellij.lua.psi.*
3233
* Created by tangzx on 2017/5/1.
3334
*/
3435
abstract class LuaDebuggerEvaluator : XDebuggerEvaluator() {
35-
override fun getExpressionRangeAtOffset(project: Project, document: Document, offset: Int, sideEffectsAllowed: Boolean): TextRange? {
36+
override fun getExpressionRangeAtOffset(
37+
project: Project,
38+
document: Document,
39+
offset: Int,
40+
sideEffectsAllowed: Boolean
41+
): TextRange? {
3642
var currentRange: TextRange? = null
37-
PsiDocumentManager.getInstance(project).commitAndRunReadAction {
43+
44+
val computeRange = computeRange@{
3845
try {
39-
val file = PsiDocumentManager.getInstance(project).getPsiFile(document) ?: return@commitAndRunReadAction
46+
val psiDocManager = PsiDocumentManager.getInstance(project)
47+
val file = psiDocManager.getPsiFile(document) ?: return@computeRange
48+
4049
if (currentRange == null) {
4150
val ele = file.findElementAt(offset)
4251
if (ele != null && ele.node.elementType == LuaTypes.ID) {
4352
val parent = ele.parent
4453
when (parent) {
4554
is LuaFuncDef,
4655
is LuaLocalFuncDef -> currentRange = ele.textRange
56+
4757
is LuaClassMethodName,
4858
is PsiNameIdentifierOwner -> currentRange = parent.textRange
4959
}
@@ -56,16 +66,31 @@ abstract class LuaDebuggerEvaluator : XDebuggerEvaluator() {
5666
is LuaCallExpr,
5767
is LuaClosureExpr,
5868
is LuaLiteralExpr -> null
69+
5970
else -> expr?.textRange
6071
}
6172
}
6273
} catch (ignored: IndexNotReadyException) {
6374
}
6475
}
76+
77+
// Check if we're already in a read action to avoid deadlock
78+
if (ApplicationManager.getApplication().isReadAccessAllowed) {
79+
// Already in read action, just execute directly
80+
computeRange()
81+
} else {
82+
// Not in read action, need to commit and run in read action
83+
PsiDocumentManager.getInstance(project).commitAndRunReadAction(computeRange)
84+
}
85+
6586
return currentRange
6687
}
6788

68-
override fun evaluate(express: String, xEvaluationCallback: XDebuggerEvaluator.XEvaluationCallback, xSourcePosition: XSourcePosition?) {
89+
override fun evaluate(
90+
express: String,
91+
xEvaluationCallback: XDebuggerEvaluator.XEvaluationCallback,
92+
xSourcePosition: XSourcePosition?
93+
) {
6994
var expr = express.trim()
7095
if (!expr.endsWith(')')) {
7196
val lastDot = express.lastIndexOf('.')
@@ -76,5 +101,9 @@ abstract class LuaDebuggerEvaluator : XDebuggerEvaluator() {
76101
eval(expr, xEvaluationCallback, xSourcePosition)
77102
}
78103

79-
protected abstract fun eval(express: String, xEvaluationCallback: XDebuggerEvaluator.XEvaluationCallback, xSourcePosition: XSourcePosition?)
104+
protected abstract fun eval(
105+
express: String,
106+
xEvaluationCallback: XDebuggerEvaluator.XEvaluationCallback,
107+
xSourcePosition: XSourcePosition?
108+
)
80109
}

0 commit comments

Comments
 (0)