Skip to content

Commit 2aa4804

Browse files
committed
Optimize LSP mixin loading and updates
- Store and track mixin filenames per URI in storage - Avoid reading files that are already cached in storage (opened by editor or loaded previously) - Only read newly added mixins during updates - Bump document refresh debounce to 500ms to reduce index jitter
1 parent a13fc3f commit 2aa4804

5 files changed

Lines changed: 46 additions & 4 deletions

File tree

internal/lsp/debounce.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ func (d *documentDebouncer) Schedule(uri string) {
3030
}
3131

3232
var timer *time.Timer
33+
3334
timer = time.AfterFunc(d.delay, func() {
3435
d.fire(uri, timer)
3536
})
@@ -49,6 +50,7 @@ func (d *documentDebouncer) Stop() {
4950

5051
func (d *documentDebouncer) fire(uri string, timer *time.Timer) {
5152
d.mu.Lock()
53+
5254
current, ok := d.timers[uri]
5355
if !ok || current != timer {
5456
d.mu.Unlock()

internal/lsp/handlers.go

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ func (s *lspServer) shutdown(context *glsp.Context) error {
4040
}
4141

4242
lsp.SetTraceValue(lsp.TraceValueOff)
43+
4344
return nil
4445
}
4546

@@ -57,8 +58,25 @@ func (s *lspServer) loadMixins(uri string) {
5758

5859
path := normalizePath(uri)
5960

60-
for _, filename := range s.parser.getMixinFilenames(doc) {
61+
currentMixins := s.parser.getMixinFilenames(doc)
62+
previousMixins := s.storage.GetMixins(uri)
63+
64+
s.storage.SetMixins(uri, currentMixins)
65+
66+
for _, filename := range currentMixins {
67+
if slices.Contains(previousMixins, filename) {
68+
continue
69+
}
70+
6171
mixinPath := replacePathFilename(path, strings.TrimPrefix(filename, "-"))
72+
mixinURI := pathToURI(mixinPath)
73+
74+
// skip if the document is already managed by the storage
75+
// e.g. opened manually in the editor or already loaded
76+
if s.storage.GetDocument(mixinURI) != nil {
77+
continue
78+
}
79+
6280
if !util.FileExists(mixinPath) {
6381
s.log.Debugf("mixin target does not exist: %s", mixinPath)
6482
continue
@@ -70,7 +88,8 @@ func (s *lspServer) loadMixins(uri string) {
7088
continue
7189
}
7290

73-
mixinURI := pathToURI(mixinPath)
91+
s.log.Debugf("load mixin %s", mixinPath)
92+
7493
text := string(data)
7594

7695
s.storage.AddDocument(mixinURI, text)
@@ -101,6 +120,7 @@ func (s *lspServer) textDocumentDidChange(context *glsp.Context, params *lsp.Did
101120
switch c := change.(type) {
102121
case lsp.TextDocumentContentChangeEventWhole:
103122
s.storage.AddDocument(params.TextDocument.URI, c.Text)
123+
104124
if s.refresh != nil {
105125
s.refresh.Schedule(params.TextDocument.URI)
106126
} else {

internal/lsp/server.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@ import (
1111
"github.com/tliron/glsp/server"
1212
)
1313

14-
const lsName = "lets_ls"
15-
const documentRefreshDebounce = 200 * time.Millisecond
14+
const (
15+
lsName = "lets_ls"
16+
documentRefreshDebounce = 500 * time.Millisecond
17+
)
1618

1719
var handler lsp.Handler
1820

internal/lsp/storage.go

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@ import "sync"
55
type storage struct {
66
mu sync.RWMutex
77
documents map[string]*string
8+
mixins map[string][]string
89
}
910

1011
func newStorage() *storage {
1112
return &storage{
1213
documents: make(map[string]*string),
14+
mixins: make(map[string][]string),
1315
}
1416
}
1517

@@ -26,3 +28,17 @@ func (s *storage) AddDocument(uri string, text string) {
2628

2729
s.documents[uri] = &text
2830
}
31+
32+
func (s *storage) SetMixins(uri string, mixins []string) {
33+
s.mu.Lock()
34+
defer s.mu.Unlock()
35+
36+
s.mixins[uri] = mixins
37+
}
38+
39+
func (s *storage) GetMixins(uri string) []string {
40+
s.mu.RLock()
41+
defer s.mu.RUnlock()
42+
43+
return s.mixins[uri]
44+
}

internal/settings/settings.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,10 @@ func LoadFile(path string) (Settings, error) {
5151
defer file.Close()
5252

5353
var fileSettings FileSettings
54+
5455
decoder := yaml.NewDecoder(file)
5556
decoder.KnownFields(true)
57+
5658
if err := decoder.Decode(&fileSettings); err != nil {
5759
return Settings{}, fmt.Errorf("failed to decode settings file: %w", err)
5860
}

0 commit comments

Comments
 (0)