@@ -118,12 +118,51 @@ local autoopen_fn = nil
118118
119119local FOCUS_AUGROUP = vim .api .nvim_create_augroup (' LeanInfoviewFocus' , {})
120120
121- --- URIs whose language server has died (and not yet been restarted) .
121+ --- Track death of the Lean language server in each buffer it was attached to .
122122---
123- --- Consulted when rendering so that asynchronous updates racing with the
124- --- server's death can't resurrect stale contents from it.
125- --- @type table<string , true>
126- local dead_uris = {}
123+ --- Sets a buffer-local flag which is consulted at render time (rather than
124+ --- eagerly mutating pin contents here) so that asynchronous updates racing
125+ --- with the server's death can't resurrect stale contents from it.
126+ local DEATH_AUGROUP = vim .api .nvim_create_augroup (' LeanInfoviewDeath' , {})
127+
128+ --- The `leanls` client for an autocmd's client ID, if that's who it is.
129+ --- @param args table autocmd callback args
130+ --- @return vim.lsp.Client ?
131+ local function leanls_from (args )
132+ local client = vim .lsp .get_client_by_id (args .data .client_id )
133+ return client and client .name == ' leanls' and client or nil
134+ end
135+
136+ vim .api .nvim_create_autocmd (' LspDetach' , {
137+ group = DEATH_AUGROUP ,
138+ callback = function (args )
139+ if not leanls_from (args ) then
140+ return
141+ end
142+ vim .b [args .buf ].lean_lsp_died = true
143+ local uri = vim .uri_from_bufnr (args .buf )
144+ -- The server certainly isn't processing anything anymore.
145+ progress .proc_infos [uri ] = {}
146+ -- LspDetach can fire in contexts where text changes aren't allowed
147+ -- (e.g. during `:edit`), so delay the re-render until it's safe.
148+ vim .schedule (function ()
149+ infoview .__update_pin_by_uri (uri )
150+ end )
151+ end ,
152+ })
153+
154+ vim .api .nvim_create_autocmd (' LspAttach' , {
155+ group = DEATH_AUGROUP ,
156+ callback = function (args )
157+ if not leanls_from (args ) then
158+ return
159+ end
160+ if vim .b [args .buf ].lean_lsp_died then
161+ vim .b [args .buf ].lean_lsp_died = nil
162+ infoview .__update_pin_by_uri (vim .uri_from_bufnr (args .buf ))
163+ end
164+ end ,
165+ })
127166
128167--- @class InfoviewViewOptions
129168--- @field use_widgets boolean use interactive widgets (true ) or plain text (false )
790829--- @param sw std.Stopwatch
791830--- @return Element
792831function Infoview :render_contents (params , sw )
793- if dead_uris [params .textDocument .uri ] then
832+ local bufnr = vim .uri_to_bufnr (params .textDocument .uri )
833+ if vim .b [bufnr ].lean_lsp_died then
794834 return components .LSP_HAS_DIED
795835 end
796836 return self .__contents_for (params , self .view_options , sw )
@@ -941,31 +981,6 @@ function Infoview:__update()
941981 self .pin :request_update ()
942982end
943983
944- --- Directly mark that the infoview has died. What a shame.
945- function Infoview :died ()
946- local params = self .pin .__position_params
947- progress .proc_infos [params .textDocument .uri ] = {
948- {
949- kind = progress .Kind .fatal_error ,
950- range = { start = params .position , [' end' ] = params .position },
951- },
952- }
953- -- Invalidate any in-flight (async) update so it can't land after us and
954- -- resurrect stale contents from the now-dead server.
955- self .pin .__tick = self .pin .__tick + 1
956- self .pin .loading = false
957- self .pin .__data_element = components .LSP_HAS_DIED
958- self .pin .__element :set_children { self .pin .__data_element }
959- -- LspDetach can fire in contexts where text changes aren't allowed
960- -- (e.g. during `:edit`), so delay the re-render until it's safe.
961- vim .schedule (function ()
962- self .pin :render ()
963- end )
964- if self .window then
965- self .window .o .winhighlight = ' NormalNC:leanInfoLSPDead'
966- end
967- end
968-
969984--- Either open or close a diff window for this infoview depending on whether it has a diff pin.
970985function Infoview :__refresh_diff ()
971986 if not self .window then
@@ -1940,27 +1955,6 @@ function infoview.init(bufnr)
19401955 -- in case we are re-entering a buffer, clear old autocmds first
19411956 vim .api .nvim_clear_autocmds { group = FOCUS_AUGROUP , buffer = bufnr }
19421957
1943- vim .api .nvim_create_autocmd (' LspDetach' , {
1944- callback = function (args )
1945- dead_uris [vim .uri_from_bufnr (args .buf )] = true
1946- local current_infoview = infoview .get_current_infoview ()
1947- if not current_infoview then
1948- return
1949- end
1950- current_infoview :died ()
1951- end ,
1952- buffer = bufnr ,
1953- group = FOCUS_AUGROUP ,
1954- })
1955-
1956- vim .api .nvim_create_autocmd (' LspAttach' , {
1957- callback = function (args )
1958- dead_uris [vim .uri_from_bufnr (args .buf )] = nil
1959- end ,
1960- buffer = bufnr ,
1961- group = FOCUS_AUGROUP ,
1962- })
1963-
19641958 vim .api .nvim_create_autocmd (' BufEnter' , {
19651959 callback = infoview_bufenter ,
19661960 buffer = bufnr ,
0 commit comments