all repos

clerk @ ed49a0d4be8464b112ec67f299693424d1f89bb7

missing tooling for ledger/hledger
7 files changed, 25 insertions(+), 27 deletions(-)
lsp: refactor: drop cfgMu
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/config.go
···
        35
        35
         }

      
        36
        36
         

      
        37
        37
         func (s *server) semanticHighlightingEnabled() bool {

      
        38
        
        -	s.cfgMu.RLock()

      
        39
        
        -	defer s.cfgMu.RUnlock()

      
        
        38
        +	s.mu.RLock()

      
        
        39
        +	defer s.mu.RUnlock()

      
        40
        40
         	return s.config.SemanticHighlighting

      
        41
        41
         }

      
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/textdocument_semantic_tokens.go
···
        47
        47
         }

      
        48
        48
         

      
        49
        49
         func (s *server) tokensForDoc(doc uri.URI) ([]semanticToken, bool) {

      
        50
        
        -	s.mu.Lock()

      
        
        50
        +	s.mu.RLock()

      
        51
        51
         	st, ok := s.openDocs[doc]

      
        52
        
        -	s.mu.Unlock()

      
        
        52
        +	s.mu.RUnlock()

      
        53
        53
         	if !ok {

      
        54
        54
         		return nil, false

      
        55
        55
         	}

      
M internal/lsp/textdocument_sync.go
···
        113
        113
         }

      
        114
        114
         

      
        115
        115
         func (s *server) getDocState(u uri.URI) (docState, bool) {

      
        116
        
        -	s.mu.Lock()

      
        
        116
        +	s.mu.RLock()

      
        117
        117
         	state, ok := s.openDocs[u]

      
        118
        
        -	s.mu.Unlock()

      
        
        118
        +	s.mu.RUnlock()

      
        119
        119
         	return state, ok

      
        120
        120
         }

      
        121
        121
         

      
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
         	}