--- /dev/null
+vim9script
+
+# Functions for dealing with inlay hints
+
+import './util.vim'
+import './buffer.vim' as buf
+
+# Initialize the highlight group and the text property type used for
+# inlay hints.
+export def InitOnce()
+ if !hlexists('LspInlayHintsType')
+ hlset([{name: 'LspInlayHintsType', linksto: 'Label'}])
+ endif
+ if !hlexists('LspInlayHintsParam')
+ hlset([{name: 'LspInlayHintsParam', linksto: 'Conceal'}])
+ endif
+ prop_type_add('LspInlayHintsType', {highlight: 'LspInlayHintsType'})
+ prop_type_add('LspInlayHintsParam', {highlight: 'LspInlayHintsParam'})
+enddef
+
+# Clear all the inlay hints text properties in the current buffer
+def InlayHintsClear(lspserver: dict<any>)
+ prop_remove({type: 'LspInlayHintsType', bufnr: bufnr('%'), all: true})
+ prop_remove({type: 'LspInlayHintsParam', bufnr: bufnr('%'), all: true})
+enddef
+
+# LSP inlay hints reply message handler
+export def InlayHintsReply(lspserver: dict<any>, inlayHints: any)
+ if inlayHints->empty()
+ return
+ endif
+
+ #echomsg inlayHints->string
+
+ InlayHintsClear(lspserver)
+
+ if mode() !=# 'n'
+ # Update inlay hints only in normal mode
+ return
+ endif
+
+ var bufnum = bufnr('%')
+ for hint in inlayHints
+ var label = ''
+ if hint.label->type() == v:t_list
+ label = hint.label->copy()->map((_, v) => v.value)->join(', ')
+ else
+ label = hint.label
+ endif
+
+ if hint.kind ==# 'type'
+ prop_add(hint.position.line + 1, hint.position.character + 1,
+ {type: 'LspInlayHintsType', text: label, bufnr: bufnum})
+ elseif hint.kind ==# 'parameter'
+ prop_add(hint.position.line + 1, hint.position.character + 1,
+ {type: 'LspInlayHintsParam', text: label, bufnr: bufnum})
+ endif
+ endfor
+enddef
+
+# Timer callback to display the inlay hints.
+def InlayHintsCallback(lspserver: dict<any>, timerid: number)
+ lspserver.inlayHintsShow()
+ b:LspInlayHintsNeedsUpdate = false
+enddef
+
+# Update all the inlay hints. A timer is used to throttle the updates.
+def InlayHintsUpdate()
+ if !get(b:, 'LspInlayHintsNeedsUpdate', true)
+ return
+ endif
+
+ var timerid = get(b:, 'LspInlayHintsTimer', -1)
+ if timerid != -1
+ timerid->timer_stop()
+ b:LspInlayHintsTimer = -1
+ endif
+
+ var lspserver: dict<any> = buf.CurbufGetServerChecked()
+ if lspserver->empty()
+ return
+ endif
+
+ timerid = timer_start(300, function('InlayHintsCallback', [lspserver]))
+ b:LspInlayHintsTimer = timerid
+enddef
+
+# Text is modified. Need to update the inlay hints.
+def InlayHintsChanged()
+ b:LspInlayHintsNeedsUpdate = true
+enddef
+
+# Stop updating the inlay hints.
+def InlayHintsUpdateStop()
+ var timerid = get(b:, 'LspInlayHintsTimer', -1)
+ if timerid != -1
+ timerid->timer_stop()
+ b:LspInlayHintsTimer = -1
+ endif
+enddef
+
+# Do buffer-local initialization for displaying inlay hints
+export def BufferInit(bnr: number)
+ var acmds: list<dict<any>> = []
+
+ acmds->add({bufnr: bnr,
+ event: ['CursorHold'],
+ group: 'LSPBufferAutocmds',
+ cmd: 'InlayHintsUpdate()'})
+ acmds->add({bufnr: bnr,
+ event: ['TextChanged'],
+ group: 'LSPBufferAutocmds',
+ cmd: 'InlayHintsChanged()'})
+ acmds->add({bufnr: bnr,
+ event: ['BufLeave'],
+ group: 'LSPBufferAutocmds',
+ cmd: 'InlayHintsUpdateStop()'})
+
+ autocmd_add(acmds)
+enddef
+
+# vim: tabstop=8 shiftwidth=2 softtabstop=2
import './outline.vim'
import './signature.vim'
import './codeaction.vim'
+import './inlayhints.vim'
# LSP server information
var lspServers: list<dict<any>> = []
{name: 'LspDiagHint', text: 'H>', texthl: 'Question',
linehl: 'MatchParen'}])
- prop_type_add('LspTextRef', {'highlight': 'Search'})
- prop_type_add('LspReadRef', {'highlight': 'DiffChange'})
- prop_type_add('LspWriteRef', {'highlight': 'DiffDelete'})
+ prop_type_add('LspTextRef', {highlight: 'Search'})
+ prop_type_add('LspReadRef', {highlight: 'DiffChange'})
+ prop_type_add('LspWriteRef', {highlight: 'DiffDelete'})
+
+ inlayhints.InitOnce()
:set ballooneval balloonevalterm
lspInitializedOnce = true
# Auto highlight all the occurrences of the current keyword
if opt.lspOptions.autoHighlight &&
lspserver.isDocumentHighlightProvider
- acmds->add({bufnr: bnr,
- event: 'CursorMoved',
- group: 'LSPBufferAutocmds',
- cmd: 'call LspDocHighlightClear() | call LspDocHighlight()'})
+ acmds->add({bufnr: bnr,
+ event: 'CursorMoved',
+ group: 'LSPBufferAutocmds',
+ cmd: 'call LspDocHighlightClear() | call LspDocHighlight()'})
endif
- autocmd_add(acmds)
+ # Displaying inlay hints needs the Vim virtual text support.
+ if has('patch-9.0.0178') && opt.lspOptions.showInlayHints
+ && (lspserver.isInlayHintProvider
+ || lspserver.isClangdInlayHintsProvider)
+ inlayhints.BufferInit(bnr)
+ endif
+ autocmd_add(acmds)
enddef
def BufferInit(bnr: number): void
import './codeaction.vim'
import './callhierarchy.vim' as callhier
import './typehierarchy.vim' as typehier
+import './inlayhints.vim'
# LSP server standard output handler
def Output_cb(lspserver: dict<any>, chan: channel, msg: any): void
lspserver.isFoldingRangeProvider = false
endif
+ # inlayHintProvider
+ if lspserver.caps->has_key('inlayHintProvider')
+ if lspserver.caps.inlayHintProvider->type() == v:t_bool
+ lspserver.isInlayHintProvider = lspserver.caps.inlayHintProvider
+ else
+ lspserver.isInlayHintProvider = true
+ endif
+ else
+ lspserver.isInlayHintProvider = false
+ endif
+
+ # clangdInlayHintsProvider
+ if lspserver.caps->has_key('clangdInlayHintsProvider')
+ lspserver.isClangdInlayHintsProvider =
+ lspserver.caps.clangdInlayHintsProvider
+ else
+ lspserver.isClangdInlayHintsProvider = false
+ endif
+
# textDocument/didSave notification
if lspserver.caps->has_key('textDocumentSync')
if lspserver.caps.textDocumentSync->type() == v:t_bool
contentFormat: ['plaintext', 'markdown']
},
foldingRange: {lineFoldingOnly: true},
+ inlayHint: {dynamicRegistration: false},
synchronization: {
didSave: true
}
return reply.result
enddef
+# Request: "textDocument/inlayHint"
+# Inlay hints.
+def InlayHintsShow(lspserver: dict<any>)
+ # Check whether LSP server supports type hierarchy
+ if !lspserver.isInlayHintProvider && !lspserver.isClangdInlayHintsProvider
+ util.ErrMsg("Error: LSP server does not support inlay hint")
+ return
+ endif
+
+ var lastlnum = line('$')
+ var param = {
+ textDocument: {uri: util.LspFileToUri(@%)},
+ range:
+ {
+ start: {line: 0, character: 0},
+ end: {line: lastlnum - 1, character: charcol([lastlnum, '$']) - 1}
+ }
+ }
+
+ var msg: string
+ if lspserver.isClangdInlayHintsProvider
+ # clangd-style inlay hints
+ msg = 'clangd/inlayHints'
+ else
+ msg = 'textDocument/inlayHint'
+ endif
+ var reply = lspserver.rpc_a(msg, param, inlayhints.InlayHintsReply)
+enddef
+
# Request: "textDocument/typehierarchy"
# Support the clangd version of type hierarchy retrieval method.
# The method described in the LSP 3.17.0 standard is not supported as clangd
getIncomingCalls: function(GetIncomingCalls, [lspserver]),
outgoingCalls: function(OutgoingCalls, [lspserver]),
getOutgoingCalls: function(GetOutgoingCalls, [lspserver]),
+ inlayHintsShow: function(InlayHintsShow, [lspserver]),
typeHierarchy: function(TypeHiearchy, [lspserver]),
renameSymbol: function(RenameSymbol, [lspserver]),
codeAction: function(CodeAction, [lspserver]),
# Use a floating menu to show the code action menu instead of asking for input
usePopupInCodeAction: false,
# enable snippet completion support
- snippetSupport: false
+ snippetSupport: false,
+ # enable inlay hints
+ showInlayHints: false
}
# set the LSP plugin options from the user provided option values
Author: Yegappan Lakshmanan (yegappan AT yahoo DOT com)
For Vim version 9.0 and above
-Last change: Nov 24, 2022
+Last change: Nov 26, 2022
==============================================================================
*lsp-license*
<
To add a language server, the following information is needed:
- filetype One or more file types supported by the language
- server. This can be a |String| or a |List|. To specify
- multiple multiple file types, use a List.
- path complete path to the language server executable
- (without any arguments).
args a list of command-line arguments passed to the
language server. Each argument is a separate List
item.
+ filetype One or more file types supported by the language
+ server. This can be a |String| or a |List|. To specify
+ multiple multiple file types, use a List.
+ initializationOptions
+ (Optional) for lsp servers (e.g. intelephense) some
+ additional initialization options may be required
+ or useful for initialization. Those can be provided in
+ this dictionary and if present will be transmitted to
+ the lsp server.
omnicompl (Optional) a boolean value that enables (true)
or disables (false) omni-completion for this file
types. By default this is set to 'v:true'.
+ path complete path to the language server executable
+ (without any arguments).
syncInit (Optional) for language servers (e.g. rust analyzer,
gopls, etc.) that take time to initialize and reply to
a 'initialize' request message this should be set to
call is used to initialize the language server,
otherwise the server is initialized asynchronously.
By default this is set to 'v:false'.
- initializationOptions
- (Optional) for lsp servers (e.g. intelephense) some
- additional initialization options may be required
- or useful for initialization. Those can be provided in
- this dictionary and if present will be transmitted to
- the lsp server.
The language servers are added using the LspAddServer() function. This function
accepts a list of language servers with the above information.
true.
showDiagOnStatusLine Show a diagnostic message on a status line.
By default this is set to false.
+showInlayHints Show inlay hints from the language server. By default
+ this is set to false. The inlay hint text is
+ displayed as a virtual text.
showSignature In insert mode, automatically show the current symbol
signature in a popup. By default this is set to true.
snippetSupport Enable snippet completion support. Need a snippet
has processed the diagnostics.
==============================================================================
-11. Debugging *lsp-debug*
+11. Highlight Groups *lsp-highlight-groups*
+
+The following highlight groups are used by the LSP plugin. You can define
+these highlight groups in your .vimrc file before sourcing this plugin to
+override them.
+
+LspInlayHintsParam Used to highlight inlay hints of kind
+ "parameter".
+LspInlayHintsType Used to highlight inlay hints of kind "type".
+
+==============================================================================
+12. Debugging *lsp-debug*
To debug this plugin, you can log the language server protocol messages sent
and received by the plugin from the language server. The following command