From 9f240e11506277d0dec92ed851253a39465f8751 Mon Sep 17 00:00:00 2001 From: Megadash452 Date: Tue, 25 Oct 2022 21:52:42 -0400 Subject: [PATCH] LSP: created command for goto widget definition. Is incomplete --- blueprintcompiler/lsp.py | 57 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/blueprintcompiler/lsp.py b/blueprintcompiler/lsp.py index bbe4c1d..06d2da0 100644 --- a/blueprintcompiler/lsp.py +++ b/blueprintcompiler/lsp.py @@ -169,6 +169,7 @@ class LanguageServer: "completionProvider": {}, "codeActionProvider": {}, "hoverProvider": True, + "declarationProvider": True, }, "serverInfo": { "name": "Blueprint", @@ -212,6 +213,62 @@ class LanguageServer: else: self._send_response(id, None) + @command("textDocument/declaration") + def gotoDeclaration(self, id, params): + """Triggered when `Ctrl+LClick` over anything that references a widget + object by ID (e.g. the param in signal handler, the value token of a + property with type Widget, the id of the source widget in a property + binding, ...)""" + open_file = self._open_files[params["textDocument"]["uri"]] + # TODO: request only has a start Position of the reference id. how to get the end Position to get id string?? + # obj_id = open_file.text[utils.pos_to_idx(params["position"]["line"], params["position"]["character"], open_file.text):].split()[0] + + full_range = { + "start": { "line": 0, "character": 0 }, + "end": { "line": 0, "character": 0 }, + } + id_range = None # { + # "start": { "line": 0, "character": 0 }, + # "end": { "line": 0, "character": 0 }, + # } + for obj in open_file.ast.objects_by_id(): + # TODO: how to get the token's string representation? + if obj.tokens["id"] == obj_id: + # TODO: get span of widget class and span of closing } + tokens = list(obj.get_semantic_tokens()) + + # Gets the first token of the widget object + position = utils.idx_to_pos(tokens[0], open_file.text) + full_range["start"]["line"] = position[0] + full_range["start"]["character"] = position[1] + + # Goes through all the tokens (starting from the 2nd) of the widget object + for token in tokens[1:]: + position = utils.idx_to_pos(obj.get_semantic_tokens(), open_file.text) + full_range["end"]["line"] = position[0] + full_range["end"]["character"] = position[1] # + len(token) + + # TODO: how to get the token's string representation? + if token == obj_id and id_range == None: + id_range = { + "start": { "line": position[0], "character": position[1] }, + "end": { "line": position[0], "character": position[1] + len(obj_id) }, + } + + break + + if id_range: + # result: LocationLink array + self._send_response(id, [{ + "targetUri": params["textDocument"]["uri"], + # contains from widget class to the closing curly bracket `}` + "targetRange": full_range, + # only contains widget's id + "targetSelectionRange": id_range + }]) + else: + self._send_response(id, None) + @command("textDocument/completion") def completion(self, id, params): open_file = self._open_files[params["textDocument"]["uri"]]