@@ -178,24 +178,38 @@ func (s *Manager) startServer(ctx context.Context, name, filepath string, server
return
}
- // check again in case another goroutine started it in the meantime
- var err error
- client := s.clients.GetOrSet(name, func() *Client {
- var cli *Client
- cli, err = New(
- ctx,
- name,
- cfg,
- s.cfg.Resolver(),
- s.cfg.WorkingDir(),
- s.cfg.Options.DebugLSP,
- )
- return cli
- })
+ // Check again in case another goroutine started it in the meantime.
+ if client, ok := s.clients.Get(name); ok {
+ switch client.GetServerState() {
+ case StateReady, StateStarting, StateDisabled:
+ s.callback(name, client)
+ return
+ }
+ }
+
+ client, err := New(
+ ctx,
+ name,
+ cfg,
+ s.cfg.Resolver(),
+ s.cfg.WorkingDir(),
+ s.cfg.Options.DebugLSP,
+ )
if err != nil {
slog.Error("Failed to create LSP client", "name", name, "error", err)
return
}
+ // Only store non-nil clients. If another goroutine raced us,
+ // prefer the already-stored client.
+ if existing, ok := s.clients.Get(name); ok {
+ switch existing.GetServerState() {
+ case StateReady, StateStarting, StateDisabled:
+ client.Close(ctx)
+ s.callback(name, existing)
+ return
+ }
+ }
+ s.clients.Set(name, client)
defer func() {
s.callback(name, client)
}()