Skip to content

Commit 6b1ffb6

Browse files
committed
feat(debugger): simple keyword completion in debugger
1 parent 26ee516 commit 6b1ffb6

File tree

4 files changed

+146
-3
lines changed

4 files changed

+146
-3
lines changed

packages/debugger/src/robotcode/debugger/dap_types.py

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1092,3 +1092,67 @@ class SetExceptionBreakpointsResponseBody(Model):
10921092
@dataclass
10931093
class SetExceptionBreakpointsResponse(Response):
10941094
body: Optional[SetExceptionBreakpointsResponseBody] = None
1095+
1096+
1097+
@dataclass
1098+
class _CompletionsRequest:
1099+
arguments: CompletionsArguments
1100+
1101+
1102+
@dataclass
1103+
class CompletionsRequest(Request, _CompletionsRequest):
1104+
arguments: CompletionsArguments = field()
1105+
command: str = "completions"
1106+
1107+
1108+
@dataclass
1109+
class CompletionsArguments(Model):
1110+
text: str
1111+
column: int
1112+
line: Optional[int] = None
1113+
frame_id: Optional[int] = None
1114+
1115+
1116+
class CompletionItemType(Enum):
1117+
METHOD = "method"
1118+
FUNCTION = "function"
1119+
CONSTRUCTOR = "constructor"
1120+
FIELD = "field"
1121+
VARIABLE = "variable"
1122+
CLASS = "class"
1123+
INTERFACE = "interface"
1124+
MODULE = "module"
1125+
PROPERTY = "property"
1126+
UNIT = "unit"
1127+
VALUE = "value"
1128+
ENUM = "enum"
1129+
KEYWORD = "keyword"
1130+
SNIPPET = "snippet"
1131+
TEXT = "text"
1132+
COLOR = "color"
1133+
FILE = "file"
1134+
REFERENCE = "reference"
1135+
CUSTOMCOLOR = "customcolor"
1136+
1137+
1138+
@dataclass
1139+
class CompletionItem(Model):
1140+
label: str
1141+
text: Optional[str] = None
1142+
sort_text: Optional[str] = None
1143+
detail: Optional[str] = None
1144+
type: Optional[CompletionItemType] = None
1145+
start: Optional[int] = None
1146+
length: Optional[int] = None
1147+
selection_start: Optional[int] = None
1148+
selection_length: Optional[int] = None
1149+
1150+
1151+
@dataclass
1152+
class CompletionsResponseBody(Model):
1153+
targets: List[CompletionItem]
1154+
1155+
1156+
@dataclass
1157+
class CompletionsResponse(Response):
1158+
body: Optional[CompletionsResponseBody] = None

packages/debugger/src/robotcode/debugger/debugger.py

Lines changed: 64 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@
4040

4141
from .dap_types import (
4242
Breakpoint,
43+
CompletionItem,
44+
CompletionItemType,
4345
ContinuedEvent,
4446
ContinuedEventBody,
4547
EvaluateArgumentContext,
@@ -289,9 +291,8 @@ def state(self) -> State:
289291

290292
@state.setter
291293
def state(self, value: State) -> None:
292-
if self._state == value:
293-
# if state is not changed, do nothing and wait a little bit to avoid busy loop
294-
time.sleep(0.01)
294+
# if state is changed, do nothing and wait a little bit to avoid busy loop
295+
time.sleep(0.01)
295296

296297
self._state = value
297298

@@ -1516,3 +1517,63 @@ def set_exception_breakpoints(
15161517
result.append(Breakpoint(verified=False))
15171518

15181519
return result or None
1520+
1521+
def completions(
1522+
self, text: str, column: int, line: Optional[int] = None, frame_id: Optional[int] = None
1523+
) -> List[CompletionItem]:
1524+
if self.expression_mode:
1525+
return []
1526+
1527+
stack_frame = next((v for v in self.full_stack_frames if v.id == frame_id), None)
1528+
1529+
evaluate_context = stack_frame.context() if stack_frame else None
1530+
1531+
if evaluate_context is None:
1532+
evaluate_context = EXECUTION_CONTEXTS.current
1533+
1534+
if evaluate_context is None:
1535+
return []
1536+
1537+
result = []
1538+
1539+
for library in evaluate_context.namespace._kw_store.libraries.values():
1540+
result.append(
1541+
CompletionItem(
1542+
label=library.name,
1543+
text=library.name,
1544+
sort_text=f"010_{library.name}",
1545+
type=CompletionItemType.MODULE,
1546+
)
1547+
)
1548+
for kw in library.handlers:
1549+
result.append(
1550+
CompletionItem(
1551+
label=kw.name,
1552+
text=kw.name,
1553+
sort_text=f"001_{kw.name}",
1554+
type=CompletionItemType.FUNCTION,
1555+
detail=kw.shortdoc,
1556+
)
1557+
)
1558+
1559+
for resource in evaluate_context.namespace._kw_store.resources.values():
1560+
result.append(
1561+
CompletionItem(
1562+
label=resource.name,
1563+
text=resource.name,
1564+
sort_text=f"010_{resource.name}",
1565+
type=CompletionItemType.MODULE,
1566+
)
1567+
)
1568+
for kw in resource.handlers:
1569+
result.append(
1570+
CompletionItem(
1571+
label=kw.name,
1572+
text=kw.name,
1573+
sort_text=f"001_{kw.name}",
1574+
type=CompletionItemType.FUNCTION,
1575+
detail=kw.shortdoc,
1576+
)
1577+
)
1578+
1579+
return result

packages/debugger/src/robotcode/debugger/launcher/server.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ async def _initialize(self, arguments: InitializeRequestArguments, *args: Any, *
131131
],
132132
supports_exception_options=True,
133133
supports_exception_filter_options=True,
134+
supports_completions_request=True,
134135
)
135136

136137
@rpc_method(name="launch", param_type=LaunchRequestArguments)

packages/debugger/src/robotcode/debugger/server.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,8 @@
1111
from .dap_types import (
1212
AttachRequestArguments,
1313
Capabilities,
14+
CompletionsArguments,
15+
CompletionsResponseBody,
1416
ConfigurationDoneArguments,
1517
ContinueArguments,
1618
ContinueResponseBody,
@@ -178,6 +180,7 @@ async def _initialize(self, arguments: InitializeRequestArguments, *args: Any, *
178180
],
179181
supports_exception_options=True,
180182
supports_exception_filter_options=True,
183+
supports_completions_request=True,
181184
)
182185

183186
@rpc_method(name="attach", param_type=AttachRequestArguments)
@@ -376,6 +379,20 @@ async def _set_exception_breakpoints(
376379
)
377380
return SetExceptionBreakpointsResponseBody(breakpoints=result) if result else None
378381

382+
@rpc_method(name="completions", param_type=CompletionsArguments)
383+
async def _completions(
384+
self,
385+
arguments: CompletionsArguments,
386+
text: str,
387+
column: int,
388+
line: Optional[int] = None,
389+
frame_id: Optional[int] = None,
390+
*args: Any,
391+
**kwargs: Any,
392+
) -> CompletionsResponseBody:
393+
result = Debugger.instance().completions(text, column, line, frame_id)
394+
return CompletionsResponseBody(targets=result)
395+
379396

380397
class DebugAdapterServer(JsonRPCServer[DebugAdapterServerProtocol]):
381398
def __init__(

0 commit comments

Comments
 (0)