1616
1717package com.tang.intellij.lua.debugger
1818
19+ import com.intellij.openapi.application.ReadAction
1920import com.intellij.openapi.editor.Editor
2021import com.intellij.openapi.util.TextRange
2122import com.intellij.openapi.vfs.VirtualFile
23+ import com.intellij.psi.PsiDocumentManager
24+ import com.intellij.psi.PsiFile
2225import com.intellij.xdebugger.XDebuggerUtil
2326import com.intellij.xdebugger.XSourcePosition
2427import com.intellij.xdebugger.frame.XStackFrame
2528import com.tang.intellij.lua.debugger.emmy.EmmyDebugStackFrame
2629import com.tang.intellij.lua.debugger.emmy.value.LuaXValue
2730import com.tang.intellij.lua.editor.LuaEditorUtil
2831import 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
3438class 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}
0 commit comments