3 # Functions for managing the per-buffer LSP server information
7 # A buffer can have one or more attached language servers. The
8 # "bufnrToServers" Dict contains the list of language servers attached to a
9 # buffer. The buffer number is the key for the "bufnrToServers" Dict. The
10 # value is the List of attached language servers.
11 var bufnrToServers: dict<list<dict<any>>> = {}
13 # Add "lspserver" to "bufnrToServers" map for buffer "bnr".
14 export def BufLspServerSet(bnr: number, lspserver: dict<any>)
15 if !bufnrToServers->has_key(bnr)
16 bufnrToServers[bnr] = []
19 bufnrToServers[bnr]->add(lspserver)
22 # Remove "lspserver" from "bufnrToServers" map for buffer "bnr".
23 export def BufLspServerRemove(bnr: number, lspserver: dict<any>)
24 if !bufnrToServers->has_key(bnr)
28 var servers: list<dict<any>> = bufnrToServers[bnr]
29 servers = servers->filter((key, srv) => srv.id != lspserver.id)
32 bufnrToServers->remove(bnr)
34 bufnrToServers[bnr] = servers
38 var SupportedCheckFns = {
39 callHierarchy: (lspserver) => lspserver.isCallHierarchyProvider,
40 codeAction: (lspserver) => lspserver.isCodeActionProvider,
41 codeLens: (lspserver) => lspserver.isCodeLensProvider,
42 completion: (lspserver) => lspserver.isCompletionProvider,
43 declaration: (lspserver) => lspserver.isDeclarationProvider,
44 definition: (lspserver) => lspserver.isDefinitionProvider,
45 documentFormatting: (lspserver) => lspserver.isDocumentFormattingProvider,
46 documentHighlight: (lspserver) => lspserver.isDocumentHighlightProvider,
47 documentSymbol: (lspserver) => lspserver.isDocumentSymbolProvider,
48 foldingRange: (lspserver) => lspserver.isFoldingRangeProvider,
49 hover: (lspserver) => lspserver.isHoverProvider,
50 implementation: (lspserver) => lspserver.isImplementationProvider,
51 inlayHint: (lspserver) => lspserver.isInlayHintProvider ||
52 lspserver.isClangdInlayHintsProvider,
53 references: (lspserver) => lspserver.isReferencesProvider,
54 rename: (lspserver) => lspserver.isRenameProvider,
55 selectionRange: (lspserver) => lspserver.isSelectionRangeProvider,
56 signatureHelp: (lspserver) => lspserver.isSignatureHelpProvider,
57 typeDefinition: (lspserver) => lspserver.isTypeDefinitionProvider,
58 typeHierarchy: (lspserver) => lspserver.isTypeHierarchyProvider,
59 workspaceSymbol: (lspserver) => lspserver.isWorkspaceSymbolProvider
62 # Returns the LSP server for the buffer "bnr". If "feature" is specified,
63 # then returns the LSP server that provides the "feature".
64 # Returns an empty dict if the server is not found.
65 export def BufLspServerGet(bnr: number, feature: string = null_string): dict<any>
66 if !bufnrToServers->has_key(bnr)
70 if bufnrToServers[bnr]->empty()
74 if feature == null_string
75 return bufnrToServers[bnr][0]
78 if !SupportedCheckFns->has_key(feature)
79 # If this happns it is a programming error, and should be fixed in the
81 :throw $'Error: ''{feature}'' is not a valid feature'
84 var SupportedCheckFn = SupportedCheckFns[feature]
86 var possibleLSPs: list<dict<any>> = []
88 for lspserver in bufnrToServers[bnr]
89 if !lspserver.ready || !SupportedCheckFn(lspserver)
93 possibleLSPs->add(lspserver)
96 if possibleLSPs->empty()
100 # LSP server is configured to be a provider for "feature"
101 for lspserver in possibleLSPs
102 var has_feature: bool = lspserver.features->get(feature, false)
108 # Return the first LSP server that supports "feature" and doesn't have it
110 for lspserver in possibleLSPs
111 if lspserver.featureEnabled(feature)
119 # Returns the LSP server for the buffer "bnr" and with ID "id". Returns an empty
120 # dict if the server is not found.
121 export def BufLspServerGetById(bnr: number, id: number): dict<any>
122 if !bufnrToServers->has_key(bnr)
126 for lspserver in bufnrToServers[bnr]
127 if lspserver.id == id
135 # Returns the LSP servers for the buffer "bnr". Returns an empty list if the
136 # servers are not found.
137 export def BufLspServersGet(bnr: number): list<dict<any>>
138 if !bufnrToServers->has_key(bnr)
142 return bufnrToServers[bnr]
145 # Returns the LSP server for the current buffer with the optionally "feature".
146 # Returns an empty dict if the server is not found.
147 export def CurbufGetServer(feature: string = null_string): dict<any>
148 return BufLspServerGet(bufnr(), feature)
151 # Returns the LSP servers for the current buffer. Returns an empty list if the
152 # servers are not found.
153 export def CurbufGetServers(): list<dict<any>>
154 return BufLspServersGet(bufnr())
157 export def BufHasLspServer(bnr: number): bool
158 var lspserver = BufLspServerGet(bnr)
160 return !lspserver->empty()
163 # Returns the LSP server for the current buffer with the optinally "feature" if
164 # it is running and is ready.
165 # Returns an empty dict if the server is not found or is not ready.
166 export def CurbufGetServerChecked(feature: string = null_string): dict<any>
167 var fname: string = @%
168 if fname->empty() || &filetype->empty()
172 var lspserver: dict<any> = CurbufGetServer(feature)
173 if lspserver->empty()
174 if feature == null_string
175 util.ErrMsg($'Language server for "{&filetype}" file type is not found')
177 util.ErrMsg($'Language server for "{&filetype}" file type supporting "{feature}" feature is not found')
181 if !lspserver.running
182 util.ErrMsg($'Language server for "{&filetype}" file type is not running')
186 util.ErrMsg($'Language server for "{&filetype}" file type is not ready')
193 # vim: tabstop=8 shiftwidth=2 softtabstop=2