Skip to content

Commit 7ca900a

Browse files
committed
refactor debugger
1 parent fb4c65a commit 7ca900a

File tree

11 files changed

+1569
-904
lines changed

11 files changed

+1569
-904
lines changed
Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
/*
2+
* Copyright (c) 2017. tangzx([email protected])
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package com.tang.intellij.lua.debugger.breakpoint
18+
19+
import com.intellij.openapi.application.ApplicationManager
20+
import com.intellij.openapi.diagnostic.Logger
21+
import com.intellij.openapi.project.Project
22+
import com.intellij.openapi.util.Key
23+
import com.intellij.xdebugger.XDebuggerManager
24+
import com.intellij.xdebugger.XSourcePosition
25+
import com.intellij.xdebugger.breakpoints.XLineBreakpoint
26+
import com.tang.intellij.lua.debugger.LuaLineBreakpointType
27+
import com.tang.intellij.lua.debugger.model.AddBreakpointRequest
28+
import com.tang.intellij.lua.debugger.model.DebugBreakpoint
29+
import com.tang.intellij.lua.debugger.model.RemoveBreakpointRequest
30+
import java.util.concurrent.ConcurrentHashMap
31+
import java.util.concurrent.atomic.AtomicInteger
32+
33+
/**
34+
* Manages breakpoints for Emmy debugger
35+
*
36+
* Responsibilities:
37+
* - Track breakpoints and assign unique IDs
38+
* - Convert between IntelliJ breakpoints and Emmy protocol breakpoints
39+
* - Synchronize breakpoints with the debugger
40+
*/
41+
class DebugBreakpointManager(private val project: Project) {
42+
43+
private val logger = Logger.getInstance(javaClass)
44+
45+
// Breakpoint ID management
46+
private val idCounter = AtomicInteger(0)
47+
private val breakpointById = ConcurrentHashMap<Int, DebugBreakpoint>()
48+
private val idByBreakpoint = ConcurrentHashMap<XLineBreakpoint<*>, Int>()
49+
50+
// Callback for sending breakpoint requests
51+
var onSendRequest: ((request: Any) -> Unit)? = null
52+
53+
companion object {
54+
/**
55+
* User data key for storing breakpoint ID
56+
*/
57+
private val BREAKPOINT_ID_KEY = Key.create<Int>("lua.debugger.breakpoint.id")
58+
}
59+
60+
/**
61+
* Initialize breakpoints - send all existing breakpoints to debugger
62+
* This should be called after the debugger connects
63+
*/
64+
fun initializeBreakpoints() {
65+
ApplicationManager.getApplication().runReadAction {
66+
val breakpoints = getAllLuaBreakpoints()
67+
68+
logger.info("Initializing ${breakpoints.size} breakpoints")
69+
70+
val debugBreakpoints = mutableListOf<DebugBreakpoint>()
71+
72+
breakpoints.forEach { xBreakpoint ->
73+
xBreakpoint.sourcePosition?.let { position ->
74+
convertToDebugBreakpoint(position, xBreakpoint)?.let { debugBp ->
75+
val id = registerBreakpoint(xBreakpoint, debugBp)
76+
xBreakpoint.putUserData(BREAKPOINT_ID_KEY, id)
77+
debugBreakpoints.add(debugBp)
78+
79+
logger.info("Registered breakpoint: ${debugBp.file}:${debugBp.line} (ID: $id)")
80+
}
81+
}
82+
}
83+
84+
if (debugBreakpoints.isNotEmpty()) {
85+
sendAddRequest(debugBreakpoints)
86+
}
87+
}
88+
}
89+
90+
/**
91+
* Register a new breakpoint
92+
*/
93+
fun onBreakpointAdded(position: XSourcePosition, xBreakpoint: XLineBreakpoint<*>) {
94+
convertToDebugBreakpoint(position, xBreakpoint)?.let { debugBp ->
95+
val id = registerBreakpoint(xBreakpoint, debugBp)
96+
xBreakpoint.putUserData(BREAKPOINT_ID_KEY, id)
97+
98+
logger.info("Added breakpoint: ${debugBp.file}:${debugBp.line} (ID: $id)")
99+
100+
sendAddRequest(listOf(debugBp))
101+
}
102+
}
103+
104+
/**
105+
* Unregister a breakpoint
106+
*/
107+
fun onBreakpointRemoved(position: XSourcePosition, xBreakpoint: XLineBreakpoint<*>) {
108+
val id = xBreakpoint.getUserData(BREAKPOINT_ID_KEY) ?: return
109+
val debugBp = breakpointById.remove(id) ?: return
110+
idByBreakpoint.remove(xBreakpoint)
111+
112+
logger.info("Removed breakpoint: ${debugBp.file}:${debugBp.line} (ID: $id)")
113+
114+
sendRemoveRequest(listOf(debugBp))
115+
}
116+
117+
/**
118+
* Clear all breakpoints
119+
*/
120+
fun clear() {
121+
breakpointById.clear()
122+
idByBreakpoint.clear()
123+
idCounter.set(0)
124+
}
125+
126+
/**
127+
* Get breakpoint by source position
128+
*/
129+
fun getBreakpoint(position: XSourcePosition): XLineBreakpoint<*>? {
130+
return getAllLuaBreakpoints().find { bp ->
131+
bp.sourcePosition?.let { pos ->
132+
pos.file == position.file && pos.line == position.line
133+
} ?: false
134+
}
135+
}
136+
137+
// Private helper methods
138+
139+
private fun registerBreakpoint(xBreakpoint: XLineBreakpoint<*>, debugBp: DebugBreakpoint): Int {
140+
val id = idCounter.getAndIncrement()
141+
breakpointById[id] = debugBp
142+
idByBreakpoint[xBreakpoint] = id
143+
return id
144+
}
145+
146+
private fun getAllLuaBreakpoints(): Collection<XLineBreakpoint<*>> {
147+
return XDebuggerManager.getInstance(project)
148+
.breakpointManager
149+
.getBreakpoints(LuaLineBreakpointType::class.java)
150+
}
151+
152+
private fun convertToDebugBreakpoint(
153+
position: XSourcePosition,
154+
xBreakpoint: XLineBreakpoint<*>
155+
): DebugBreakpoint? {
156+
val file = position.file.canonicalPath ?: return null
157+
val line = position.line + 1 // Convert to 1-based
158+
159+
return if (xBreakpoint.isLogMessage) {
160+
// Log point
161+
DebugBreakpoint(
162+
file = file,
163+
line = line,
164+
condition = null,
165+
logMessage = xBreakpoint.logExpressionObject?.expression
166+
)
167+
} else {
168+
// Regular breakpoint with optional condition
169+
DebugBreakpoint(
170+
file = file,
171+
line = line,
172+
condition = xBreakpoint.conditionExpression?.expression
173+
)
174+
}
175+
}
176+
177+
private fun sendAddRequest(breakpoints: List<DebugBreakpoint>) {
178+
onSendRequest?.invoke(AddBreakpointRequest(breakpoints))
179+
}
180+
181+
private fun sendRemoveRequest(breakpoints: List<DebugBreakpoint>) {
182+
onSendRequest?.invoke(RemoveBreakpointRequest(breakpoints))
183+
}
184+
}

0 commit comments

Comments
 (0)