Skip to content

Commit 52f2ee4

Browse files
authored
Snapshots: more logging, fix memory leak (#1641)
1 parent bcb8510 commit 52f2ee4

File tree

9 files changed

+202
-102
lines changed

9 files changed

+202
-102
lines changed

internal/lsp/server.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -445,6 +445,7 @@ var handlers = sync.OnceValue(func() handlerMap {
445445
registerNotificationHandler(handlers, lsproto.TextDocumentDidSaveInfo, (*Server).handleDidSave)
446446
registerNotificationHandler(handlers, lsproto.TextDocumentDidCloseInfo, (*Server).handleDidClose)
447447
registerNotificationHandler(handlers, lsproto.WorkspaceDidChangeWatchedFilesInfo, (*Server).handleDidChangeWatchedFiles)
448+
registerNotificationHandler(handlers, lsproto.SetTraceInfo, (*Server).handleSetTrace)
448449

449450
registerLanguageServiceDocumentRequestHandler(handlers, lsproto.TextDocumentDiagnosticInfo, (*Server).handleDocumentDiagnostic)
450451
registerLanguageServiceDocumentRequestHandler(handlers, lsproto.TextDocumentHoverInfo, (*Server).handleHover)
@@ -558,6 +559,10 @@ func (s *Server) handleInitialize(ctx context.Context, params *lsproto.Initializ
558559
s.locale = locale
559560
}
560561

562+
if s.initializeParams.Trace != nil && *s.initializeParams.Trace == "verbose" {
563+
s.logger.SetVerbose(true)
564+
}
565+
561566
response := &lsproto.InitializeResult{
562567
ServerInfo: &lsproto.ServerInfo{
563568
Name: "typescript-go",
@@ -690,6 +695,21 @@ func (s *Server) handleDidChangeWatchedFiles(ctx context.Context, params *lsprot
690695
return nil
691696
}
692697

698+
func (s *Server) handleSetTrace(ctx context.Context, params *lsproto.SetTraceParams) error {
699+
switch params.Value {
700+
case "verbose":
701+
s.logger.SetVerbose(true)
702+
case "messages":
703+
s.logger.SetVerbose(false)
704+
case "off":
705+
// !!! logging cannot be completely turned off for now
706+
s.logger.SetVerbose(false)
707+
default:
708+
return fmt.Errorf("unknown trace value: %s", params.Value)
709+
}
710+
return nil
711+
}
712+
693713
func (s *Server) handleDocumentDiagnostic(ctx context.Context, ls *ls.LanguageService, params *lsproto.DocumentDiagnosticParams) (lsproto.DocumentDiagnosticResponse, error) {
694714
return ls.ProvideDiagnostics(ctx, params.TextDocument.Uri)
695715
}

internal/project/ata/ata_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -382,6 +382,8 @@ func TestATA(t *testing.T) {
382382
Type: lsproto.FileChangeTypeChanged,
383383
Uri: lsproto.DocumentUri("file:///user/username/projects/project/package.json"),
384384
}})
385+
// diagnostics refresh triggered - simulate by getting the language service
386+
_, _ = session.GetLanguageService(context.Background(), uri)
385387
session.WaitForBackgroundTasks()
386388

387389
calls = utils.NpmExecutor().NpmInstallCalls()

internal/project/compilerhost.go

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"time"
55

66
"github.com/microsoft/typescript-go/internal/ast"
7+
"github.com/microsoft/typescript-go/internal/collections"
78
"github.com/microsoft/typescript-go/internal/compiler"
89
"github.com/microsoft/typescript-go/internal/ls"
910
"github.com/microsoft/typescript-go/internal/project/logging"
@@ -22,24 +23,49 @@ type compilerHost struct {
2223
fs *snapshotFSBuilder
2324
compilerFS *compilerFS
2425
configFileRegistry *ConfigFileRegistry
26+
seenFiles *collections.SyncSet[tspath.Path]
2527

2628
project *Project
2729
builder *projectCollectionBuilder
2830
logger *logging.LogTree
2931
}
3032

33+
type builderFileSource struct {
34+
seenFiles *collections.SyncSet[tspath.Path]
35+
snapshotFSBuilder *snapshotFSBuilder
36+
}
37+
38+
func (c *builderFileSource) GetFile(fileName string) FileHandle {
39+
path := c.snapshotFSBuilder.toPath(fileName)
40+
c.seenFiles.Add(path)
41+
return c.snapshotFSBuilder.GetFileByPath(fileName, path)
42+
}
43+
44+
func (c *builderFileSource) FS() vfs.FS {
45+
return c.snapshotFSBuilder.FS()
46+
}
47+
3148
func newCompilerHost(
3249
currentDirectory string,
3350
project *Project,
3451
builder *projectCollectionBuilder,
3552
logger *logging.LogTree,
3653
) *compilerHost {
54+
seenFiles := &collections.SyncSet[tspath.Path]{}
55+
compilerFS := &compilerFS{
56+
source: &builderFileSource{
57+
seenFiles: seenFiles,
58+
snapshotFSBuilder: builder.fs,
59+
},
60+
}
61+
3762
return &compilerHost{
3863
configFilePath: project.configFilePath,
3964
currentDirectory: currentDirectory,
4065
sessionOptions: builder.sessionOptions,
4166

42-
compilerFS: &compilerFS{source: builder.fs},
67+
compilerFS: compilerFS,
68+
seenFiles: seenFiles,
4369

4470
fs: builder.fs,
4571
project: project,
@@ -88,6 +114,7 @@ func (c *compilerHost) GetResolvedProjectReference(fileName string, path tspath.
88114
if c.builder == nil {
89115
return c.configFileRegistry.GetConfig(path)
90116
} else {
117+
c.seenFiles.Add(path)
91118
return c.builder.configFileRegistryBuilder.acquireConfigForProject(fileName, path, c.project, c.logger)
92119
}
93120
}
@@ -97,6 +124,7 @@ func (c *compilerHost) GetResolvedProjectReference(fileName string, path tspath.
97124
// be a corresponding release for each call made.
98125
func (c *compilerHost) GetSourceFile(opts ast.SourceFileParseOptions) *ast.SourceFile {
99126
c.ensureAlive()
127+
c.seenFiles.Add(opts.Path)
100128
if fh := c.fs.GetFileByPath(opts.FileName, opts.Path); fh != nil {
101129
return c.builder.parseCache.Acquire(fh, opts, fh.Kind())
102130
}

internal/project/filechange.go

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,8 +38,6 @@ type FileChangeSummary struct {
3838
Created collections.Set[lsproto.DocumentUri]
3939
// Only set when file watching is enabled
4040
Deleted collections.Set[lsproto.DocumentUri]
41-
42-
IncludesWatchChangesOnly bool
4341
}
4442

4543
func (f FileChangeSummary) IsEmpty() bool {

internal/project/overlayfs.go

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,6 @@ func (fs *overlayFS) processChanges(changes []FileChange) (FileChangeSummary, ma
197197
fs.mu.Lock()
198198
defer fs.mu.Unlock()
199199

200-
var includesNonWatchChange bool
201200
var result FileChangeSummary
202201
newOverlays := maps.Clone(fs.overlays)
203202

@@ -283,7 +282,6 @@ func (fs *overlayFS) processChanges(changes []FileChange) (FileChangeSummary, ma
283282
if result.Opened != "" {
284283
panic("can only process one file open event at a time")
285284
}
286-
includesNonWatchChange = true
287285
result.Opened = uri
288286
newOverlays[path] = newOverlay(
289287
uri.FileName(),
@@ -295,7 +293,6 @@ func (fs *overlayFS) processChanges(changes []FileChange) (FileChangeSummary, ma
295293
}
296294

297295
if events.closeChange != nil {
298-
includesNonWatchChange = true
299296
if result.Closed == nil {
300297
result.Closed = make(map[lsproto.DocumentUri]xxh3.Uint128)
301298
}
@@ -316,7 +313,6 @@ func (fs *overlayFS) processChanges(changes []FileChange) (FileChangeSummary, ma
316313
}
317314

318315
if len(events.changes) > 0 {
319-
includesNonWatchChange = true
320316
result.Changed.Add(uri)
321317
if o == nil {
322318
panic("overlay not found for changed file: " + uri)
@@ -361,6 +357,5 @@ func (fs *overlayFS) processChanges(changes []FileChange) (FileChangeSummary, ma
361357
}
362358

363359
fs.overlays = newOverlays
364-
result.IncludesWatchChangesOnly = !includesNonWatchChange
365360
return result, newOverlays
366361
}

internal/project/projectcollectionbuilder.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -772,12 +772,16 @@ func (b *projectCollectionBuilder) updateProgram(entry dirty.Value[*Project], lo
772772
}
773773
if updateProgram {
774774
entry.Change(func(project *Project) {
775+
oldHost := project.host
775776
project.host = newCompilerHost(project.currentDirectory, project, b, logger.Fork("CompilerHost"))
776777
result := project.CreateProgram()
777778
project.Program = result.Program
778779
project.checkerPool = result.CheckerPool
779780
project.ProgramUpdateKind = result.UpdateKind
780781
project.ProgramLastUpdate = b.newSnapshotID
782+
if result.UpdateKind == ProgramUpdateKindCloned {
783+
project.host.seenFiles = oldHost.seenFiles
784+
}
781785
if result.UpdateKind == ProgramUpdateKindNewFiles {
782786
filesChanged = true
783787
if b.sessionOptions.WatchEnabled {

0 commit comments

Comments
 (0)