From 9882e2bca746acb186cfae8e67d30d91dc211647 Mon Sep 17 00:00:00 2001 From: oltolm Date: Fri, 28 Feb 2025 19:57:39 +0100 Subject: gdb/dap - Add CompletionsRequest Use GDB/MI command "-complete" to implement. Co-authored-by: Simon Farre Bug: https://sourceware.org/bugzilla/show_bug.cgi?id=31140 Approved-By: Tom Tromey Reviewed-By: Eli Zaretskii --- gdb/python/lib/gdb/dap/__init__.py | 1 + gdb/python/lib/gdb/dap/completions.py | 60 +++++++++++++++++++++++++++++++++++ gdb/python/lib/gdb/dap/server.py | 21 ++++++++++-- 3 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 gdb/python/lib/gdb/dap/completions.py (limited to 'gdb/python') diff --git a/gdb/python/lib/gdb/dap/__init__.py b/gdb/python/lib/gdb/dap/__init__.py index 145aeb6..08ca33f 100644 --- a/gdb/python/lib/gdb/dap/__init__.py +++ b/gdb/python/lib/gdb/dap/__init__.py @@ -26,6 +26,7 @@ from . import startup # server object. "F401" is the flake8 "imported but unused" code. from . import breakpoint # noqa: F401 from . import bt # noqa: F401 +from . import completions # noqa: F401 from . import disassemble # noqa: F401 from . import evaluate # noqa: F401 from . import launch # noqa: F401 diff --git a/gdb/python/lib/gdb/dap/completions.py b/gdb/python/lib/gdb/dap/completions.py new file mode 100644 index 0000000..85acc43 --- /dev/null +++ b/gdb/python/lib/gdb/dap/completions.py @@ -0,0 +1,60 @@ +# Copyright 2025 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +from typing import Optional + +from .frames import select_frame +from .server import capability, import_column, import_line, request +from .startup import exec_mi_and_log + + +@request("completions") +@capability("supportsCompletionsRequest") +@capability("completionTriggerCharacters", [" ", "."]) +def completions( + *, + frameId: Optional[int] = None, + text: str, + column: int, + line: Optional[int] = None, + **extra, +): + if frameId is not None: + select_frame(frameId) + + column = import_column(column) + if line is None: + line = 1 + else: + line = import_line(line) + text = text.splitlines()[line - 1] + text = text[: column - 1] + mi_result = exec_mi_and_log("-complete", text) + result = [] + completion = None + if "completion" in mi_result: + completion = mi_result["completion"] + result.append({"label": completion, "length": len(completion)}) + # If `-complete' finds one match then `completion' and `matches' + # will contain the same one match. + if ( + completion is not None + and len(mi_result["matches"]) == 1 + and completion == mi_result["matches"][0] + ): + return {"targets": result} + for match in mi_result["matches"]: + result.append({"label": match, "length": len(match)}) + return {"targets": result} diff --git a/gdb/python/lib/gdb/dap/server.py b/gdb/python/lib/gdb/dap/server.py index 8fdf029..7139c79 100644 --- a/gdb/python/lib/gdb/dap/server.py +++ b/gdb/python/lib/gdb/dap/server.py @@ -49,6 +49,7 @@ _server = None # This is set by the initialize request and is used when rewriting # line numbers. _lines_start_at_1 = False +_columns_start_at_1 = False class DeferredRequest: @@ -593,6 +594,8 @@ def initialize(**args): _server.send_event_later("initialized") global _lines_start_at_1 _lines_start_at_1 = client_bool_capability("linesStartAt1", True) + global _columns_start_at_1 + _columns_start_at_1 = client_bool_capability("columnsStartAt1", True) return _capabilities.copy() @@ -698,7 +701,7 @@ def send_gdb_with_response(fn): return val -def export_line(line): +def export_line(line: int) -> int: """Rewrite LINE according to client capability. This applies the linesStartAt1 capability as needed, when sending a line number from gdb to the client.""" @@ -710,7 +713,7 @@ def export_line(line): return line -def import_line(line): +def import_line(line: int) -> int: """Rewrite LINE according to client capability. This applies the linesStartAt1 capability as needed, when the client sends a line number to gdb.""" @@ -720,3 +723,17 @@ def import_line(line): # the client starts at 0. line = line + 1 return line + + +def export_column(column: int) -> int: + """Rewrite COLUMN according to client capability. + This applies the columnsStartAt1 capability as needed, + when sending a column number from gdb to the client.""" + return column if _columns_start_at_1 else column - 1 + + +def import_column(column: int) -> int: + """Rewrite COLUMN according to client capability. + This applies the columnsStartAt1 capability as needed, + when the client sends a column number to gdb.""" + return column if _columns_start_at_1 else column + 1 -- cgit v1.1