3 # Functions for dealing with inlay hints
6 import './buffer.vim' as buf
7 import './options.vim' as opt
9 # Initialize the highlight group and the text property type used for
12 hlset([{name: 'LspInlayHintsType', default: true, linksto: 'Label'}])
13 hlset([{name: 'LspInlayHintsParam', default: true, linksto: 'Conceal'}])
14 prop_type_add('LspInlayHintsType', {highlight: 'LspInlayHintsType'})
15 prop_type_add('LspInlayHintsParam', {highlight: 'LspInlayHintsParam'})
18 # Clear all the inlay hints text properties in the current buffer
19 def InlayHintsClear(lspserver: dict<any>)
20 prop_remove({type: 'LspInlayHintsType', bufnr: bufnr('%'), all: true})
21 prop_remove({type: 'LspInlayHintsParam', bufnr: bufnr('%'), all: true})
24 # LSP inlay hints reply message handler
25 export def InlayHintsReply(lspserver: dict<any>, inlayHints: any)
26 if inlayHints->empty()
30 InlayHintsClear(lspserver)
33 # Update inlay hints only in normal mode
38 for hint in inlayHints
40 if hint.label->type() == v:t_list
41 label = hint.label->copy()->map((_, v) => v.value)->join(', ')
46 var kind = hint->has_key('kind') ? hint.kind->string() : '1'
48 lspserver.decodePosition(bnr, hint.position)
49 var byteIdx = util.GetLineByteFromPos(bnr, hint.position)
50 if kind == "'type'" || kind == '1'
51 prop_add(hint.position.line + 1, byteIdx + 1,
52 {type: 'LspInlayHintsType', text: label, bufnr: bnr})
53 elseif kind == "'parameter'" || kind == '2'
54 prop_add(hint.position.line + 1, byteIdx + 1,
55 {type: 'LspInlayHintsParam', text: label, bufnr: bnr})
57 catch /E966\|E964/ # Invalid lnum | Invalid col
58 # Inlay hints replies arrive asynchronously and the document might have
59 # been modified in the mean time. As the reply is stale, ignore invalid
60 # line number and column number errors.
65 # Timer callback to display the inlay hints.
66 def InlayHintsCallback(lspserver: dict<any>, timerid: number)
67 lspserver.inlayHintsShow()
68 b:LspInlayHintsNeedsUpdate = false
71 # Update all the inlay hints. A timer is used to throttle the updates.
72 def LspInlayHintsUpdate()
73 if !get(b:, 'LspInlayHintsNeedsUpdate', true)
77 var timerid = get(b:, 'LspInlayHintsTimer', -1)
80 b:LspInlayHintsTimer = -1
83 var lspserver: dict<any> = buf.CurbufGetServerChecked()
88 timerid = timer_start(300, function('InlayHintsCallback', [lspserver]))
89 b:LspInlayHintsTimer = timerid
92 # Text is modified. Need to update the inlay hints.
93 def LspInlayHintsChanged()
94 b:LspInlayHintsNeedsUpdate = true
97 # Trigger an update of the inlay hints in the current buffer.
98 export def LspInlayHintsUpdateNow()
99 b:LspInlayHintsNeedsUpdate = true
100 LspInlayHintsUpdate()
103 # Stop updating the inlay hints.
104 def LspInlayHintsUpdateStop()
105 var timerid = get(b:, 'LspInlayHintsTimer', -1)
107 timerid->timer_stop()
108 b:LspInlayHintsTimer = -1
112 # Do buffer-local initialization for displaying inlay hints
113 export def BufferInit(lspserver: dict<any>, bnr: number)
114 if !lspserver.isInlayHintProvider && !lspserver.isClangdInlayHintsProvider
115 # no support for inley hints
119 # Inlays hints are disabled
120 if !opt.lspOptions.showInlayHints
124 var acmds: list<dict<any>> = []
126 # Update the inlay hints (if needed) when the cursor is not moved for some
128 acmds->add({bufnr: bnr,
129 event: ['CursorHold'],
130 group: 'LSPBufferAutocmds',
131 cmd: 'LspInlayHintsUpdate()'})
132 # After the text in the current buffer is modified, the inlay hints need to
134 acmds->add({bufnr: bnr,
135 event: ['TextChanged'],
136 group: 'LSPBufferAutocmds',
137 cmd: 'LspInlayHintsChanged()'})
138 # Editing a file should trigger an inlay hint update.
139 acmds->add({bufnr: bnr,
140 event: ['BufReadPost'],
141 group: 'LSPBufferAutocmds',
142 cmd: 'LspInlayHintsUpdateNow()'})
143 # Inlay hints need not be updated if a buffer is no longer active.
144 acmds->add({bufnr: bnr,
146 group: 'LSPBufferAutocmds',
147 cmd: 'LspInlayHintsUpdateStop()'})
152 # vim: tabstop=8 shiftwidth=2 softtabstop=2