7 files changed,
25 insertions(+),
27 deletions(-)
Author:
Oleksandr Smirnov
olexsmir@gmail.com
Committed at:
2026-08-16 16:32:29 +0300
Authored at:
2026-08-16 13:57:31 +0300
Change ID:
zzspnrqlporyzrpwvnmtnnypnxtsuqml
Parent:
2963f4c
M
internal/lsp/diagnostics.go
··· 40 40 return 41 41 } 42 42 43 - s.mu.Lock() 43 + s.mu.RLock() 44 44 var dirtyURIs []uri.URI 45 45 for u, state := range s.openDocs { 46 46 if state.dirty { 47 47 dirtyURIs = append(dirtyURIs, u) 48 48 } 49 49 } 50 - s.mu.Unlock() 50 + s.mu.RUnlock() 51 51 if len(dirtyURIs) == 0 { 52 52 s.log.Debug("no dirty files") 53 53 return
M
internal/lsp/lsp.go
··· 61 61 // bufferContent returns the open buffer text for a path, if any. 62 62 // called by the loader during include resolution; must NOT hold the loader lock. 63 63 func (s *server) bufferContent(path string) ([]byte, bool) { 64 - s.mu.Lock() 65 - defer s.mu.Unlock() 64 + s.mu.RLock() 65 + defer s.mu.RUnlock() 66 66 st, ok := s.openDocs[uri.File(path)] 67 67 return []byte(st.text), ok 68 68 }
M
internal/lsp/server.go
··· 26 26 loader *journal.Loader 27 27 printer *printer.Config 28 28 29 - mu sync.Mutex 30 - openDocs map[uri.URI]docState 31 - diagCancel context.CancelFunc 32 - supportsDynamicFileWatchers bool 33 - 34 - cfgMu sync.RWMutex 35 - config Config 29 + mu sync.RWMutex 30 + config Config 31 + openDocs map[uri.URI]docState 32 + diagCancel context.CancelFunc 33 + dynFileWather bool 36 34 } 37 35 38 36 // analysisFor returns the cached analysis for an open doc, rebuilds when the doc or a file it inclues changed. 39 37 func (s *server) analysisFor(u uri.URI) *analyzer.Analysis { 40 - s.mu.Lock() 38 + s.mu.RLock() 41 39 state, ok := s.openDocs[u] 42 40 if !ok { 43 - s.mu.Unlock() 41 + s.mu.RUnlock() 44 42 return nil 45 43 } 46 44 if !state.dirty { 47 45 an := state.analysis 48 - s.mu.Unlock() 46 + s.mu.RUnlock() 49 47 return an 50 48 } 51 49 text := state.text 52 50 version := state.version 53 - s.mu.Unlock() 51 + s.mu.RUnlock() 54 52 55 53 an := analyzer.Build(s.loader.ResolveBytes(u.Path(), []byte(text))) 56 54 ··· 75 73 func (s *server) Initialize(ctx context.Context, params *protocol.InitializeParams) (*protocol.InitializeResult, error) { 76 74 if w := params.Capabilities.Workspace; w != nil { 77 75 if wf := w.DidChangeWatchedFiles; wf != nil { 78 - s.supportsDynamicFileWatchers = wf.DynamicRegistration != nil && *wf.DynamicRegistration 76 + s.dynFileWather = wf.DynamicRegistration != nil && *wf.DynamicRegistration 79 77 } 80 78 } 81 79 ··· 112 110 } 113 111 114 112 func (s *server) Initialized(ctx context.Context, params *protocol.InitializedParams) error { 115 - if s.supportsDynamicFileWatchers { 113 + if s.dynFileWather { 116 114 go s.registerFileWatchers(context.Background()) 117 115 } 118 116 s.scheduleDiagnostics(ctx) ··· 173 171 } 174 172 175 173 func (s *server) applySettings(v protocol.LSPAny) { 176 - s.cfgMu.Lock() 174 + s.mu.Lock() 177 175 if err := s.config.merge(v); err != nil { 178 176 s.log.Error("failed to merge config", "err", err) 179 177 } 180 - s.cfgMu.Unlock() 178 + s.mu.Unlock() 181 179 }
M
internal/lsp/workspace_symbol.go
··· 17 17 return nil, nil 18 18 } 19 19 20 - s.mu.Lock() 20 + s.mu.RLock() 21 21 paths := make([]string, 0, len(s.openDocs)) 22 22 for u := range s.openDocs { 23 23 paths = append(paths, u.Path()) 24 24 } 25 - s.mu.Unlock() 25 + s.mu.RUnlock() 26 26 if len(paths) == 0 { 27 27 return nil, nil 28 28 }