From 595f84902315778023c9ae064d80353602f2c7aa Mon Sep 17 00:00:00 2001 From: Andreas Louv Date: Thu, 9 Mar 2023 10:06:56 +0100 Subject: [PATCH] Add support for "capabilities.*.linkSupport" This commit should be backward compatible, but allow us to use all the properties from "LocationLink" in other commits, as long the language server replies with "LocationLink" --- autoload/lsp/lspserver.vim | 19 ++++++++++++++++++- autoload/lsp/symbol.vim | 20 +++++++++++--------- autoload/lsp/util.vim | 17 ++++++++++++++--- 3 files changed, 43 insertions(+), 13 deletions(-) diff --git a/autoload/lsp/lspserver.vim b/autoload/lsp/lspserver.vim index fd78974..16d9838 100644 --- a/autoload/lsp/lspserver.vim +++ b/autoload/lsp/lspserver.vim @@ -425,7 +425,11 @@ def InitServer(lspserver: dict) inlayHint: {dynamicRegistration: false}, synchronization: { didSave: true - } + }, + declaration: {linkSupport: true}, + definition: {linkSupport: true}, + typeDefinition: {linkSupport: true}, + implementation: {linkSupport: true} }, window: {}, general: {} @@ -886,6 +890,11 @@ def GotoSymbolLoc(lspserver: dict, msg: string, peekSymbol: bool, location = reply.result endif + # Convert to 'LocationLink' + if !location->has_key('targetUri') + location = util.LspLocationToLocationLink(location) + endif + symbol.GotoSymbol(lspserver, location, peekSymbol, cmdmods) enddef @@ -1586,6 +1595,14 @@ def TagFunc(lspserver: dict, pat: string, flags: string, info: dict): taglocations = [reply.result] endif + taglocations = taglocations->map((key, location) => { + # Already a 'LocationLink' + if location->has_key('targetUri') + return location + endif + return util.LspLocationToLocationLink(location) + }) + return symbol.TagFunc(lspserver, taglocations, pat) enddef diff --git a/autoload/lsp/symbol.vim b/autoload/lsp/symbol.vim index ab167e4..6bddbff 100644 --- a/autoload/lsp/symbol.vim +++ b/autoload/lsp/symbol.vim @@ -394,10 +394,10 @@ def SymbolFilterCB(lspserver: dict, id: number, key: string): bool return false enddef -# Display the file specified by LSP 'location' in a popup window and highlight -# the range in 'location'. +# Display the file specified by LSP 'LocationLink' in a popup window and +# highlight the range in 'location'. def PeekSymbolLocation(lspserver: dict, location: dict) - var fname = util.LspUriToFile(location.uri) + var fname = util.LspUriToFile(location.targetUri) var bnum = fname->bufadd() if bnum == 0 # Failed to create or find a buffer @@ -431,13 +431,13 @@ def PeekSymbolLocation(lspserver: dict, location: dict) var pos: list = [] var start_col: number var end_col: number - start_col = util.GetLineByteFromPos(pwbuf, location.range.start) + 1 - end_col = util.GetLineByteFromPos(pwbuf, location.range.end) + 1 - pos->add(location.range.start.line + 1) + start_col = util.GetLineByteFromPos(pwbuf, location.targetSelectionRange.start) + 1 + end_col = util.GetLineByteFromPos(pwbuf, location.targetSelectionRange.end) + 1 + pos->add(location.targetSelectionRange.start.line + 1) pos->extend([start_col, end_col - start_col]) matchaddpos('Search', [pos], 10, 101, {window: pwid}) var cmds =<< trim eval END - [{location.range.start.line + 1}, 1]->cursor() + [{location.targetSelectionRange.start.line + 1}, 1]->cursor() normal! z. END win_execute(pwid, cmds, 'silent!') @@ -467,8 +467,10 @@ export def TagFunc(lspserver: dict, for tagloc in taglocations var tagitem = {} tagitem.name = pat - tagitem.filename = util.LspUriToFile(tagloc.uri) - tagitem.cmd = $"/\\%{tagloc.range.start.line + 1}l\\%{tagloc.range.start.character + 1}c" + + tagitem.filename = util.LspUriToFile(tagloc.targetUri) + tagitem.cmd = $"/\\%{tagloc.targetSelectionRange.start.line + 1}l\\%{tagloc.targetSelectionRange.start.character + 1}c" + retval->add(tagitem) endfor diff --git a/autoload/lsp/util.vim b/autoload/lsp/util.vim index 556430f..11b1606 100644 --- a/autoload/lsp/util.vim +++ b/autoload/lsp/util.vim @@ -50,6 +50,17 @@ export def ClearTraceLogs() writefile([], $'{lsp_log_dir}lsp-server.err') enddef +# Convert a 'Location' to a dict that looks a lot like a 'LocationLink' but with +# the caveat that 'targetRange' is null. +export def LspLocationToLocationLink(location: dict): dict + return { + targetUri: location.uri, + targetSelectionRange: location.range, + targetRange: null, + originSelectionRange: null + } +enddef + # Convert a LSP file URI (file://) to a Vim file name export def LspUriToFile(uri: string): string # Replace all the %xx numbers (e.g. %20 for space) in the URI to character @@ -154,7 +165,7 @@ enddef # number and character number. The user specified window command modifiers # (e.g. topleft) are in 'cmdmods'. export def JumpToLspLocation(location: dict, cmdmods: string) - var fname = LspUriToFile(location.uri) + var fname = LspUriToFile(location.targetUri) # jump to the file and line containing the symbol if cmdmods == '' @@ -191,8 +202,8 @@ export def JumpToLspLocation(location: dict, cmdmods: string) # Set the previous cursor location mark. Instead of using setpos(), m' is # used so that the current location is added to the jump list. normal m' - setcursorcharpos(location.range.start.line + 1, - location.range.start.character + 1) + setcursorcharpos(location.targetSelectionRange.start.line + 1, + location.targetSelectionRange.start.character + 1) enddef # vim: tabstop=8 shiftwidth=2 softtabstop=2 -- 2.48.1