vendor tsgo

This commit is contained in:
2026-07-09 16:50:43 -04:00
parent c06ea2e5a4
commit 98978e4930
5804 changed files with 1556156 additions and 101 deletions

View File

@@ -0,0 +1,127 @@
package lsp
import (
"context"
"io"
"testing"
"github.com/microsoft/typescript-go/internal/bundled"
"github.com/microsoft/typescript-go/internal/lsp/lsproto"
"github.com/microsoft/typescript-go/internal/project"
"github.com/microsoft/typescript-go/internal/vfs/vfstest"
)
type shutdownTestReader struct{}
func (shutdownTestReader) Read() (*lsproto.Message, error) { return nil, io.EOF }
type shutdownTestWriter struct{}
func (shutdownTestWriter) Write(*lsproto.Message) error { return nil }
// TestServerShutdownNoDeadlock verifies that operations after shutdown
// don't block.
func TestServerShutdownNoDeadlock(t *testing.T) {
t.Parallel()
if !bundled.Embedded {
t.Skip("bundled files are not embedded")
}
fs := bundled.WrapFS(vfstest.FromMap(map[string]string{
"/test/tsconfig.json": "{}",
"/test/index.ts": "const x = 1;",
}, false))
server := NewServer(&ServerOptions{
In: shutdownTestReader{},
Out: shutdownTestWriter{},
Err: io.Discard,
Cwd: "/test",
FS: fs,
DefaultLibraryPath: bundled.LibPath(),
})
ctx, cancel := context.WithCancel(context.Background())
server.backgroundCtx = ctx
// Start write loop to drain queue
writeLoopDone := make(chan struct{})
go func() {
_ = server.writeLoop(ctx)
close(writeLoopDone)
}()
// Create session with the server's lifecycle context
server.initStarted.Store(true)
server.session = project.NewSession(&project.SessionInit{
BackgroundCtx: ctx,
Options: &project.SessionOptions{
CurrentDirectory: "/test",
DefaultLibraryPath: bundled.LibPath(),
PositionEncoding: lsproto.PositionEncodingKindUTF8,
WatchEnabled: false,
LoggingEnabled: true,
},
FS: fs,
Logger: server.logger,
})
// Open a file to establish a project
server.session.DidOpenFile(ctx, "file:///test/index.ts", 1, "const x = 1;", lsproto.LanguageKindTypeScript)
server.session.WaitForBackgroundTasks()
// Shutdown (cancel context and wait for write loop to exit)
cancel()
<-writeLoopDone
// Trigger operations that would log (these should not block)
server.session.DidChangeFile(ctx, "file:///test/index.ts", 2, []lsproto.TextDocumentContentChangePartialOrWholeDocument{
{
WholeDocument: &lsproto.TextDocumentContentChangeWholeDocument{
Text: "const x = 2;",
},
},
})
_, _ = server.session.GetLanguageService(ctx, "file:///test/index.ts")
server.session.WaitForBackgroundTasks()
server.session.Close()
}
func TestServerOutgoingQueueDoesNotBlockWithoutWriter(t *testing.T) {
t.Parallel()
server := NewServer(&ServerOptions{
In: shutdownTestReader{},
Out: shutdownTestWriter{},
Err: io.Discard,
Cwd: "/test",
})
server.backgroundCtx = t.Context()
msg := lsproto.WindowLogMessageInfo.NewNotificationMessage(&lsproto.LogMessageParams{
Type: lsproto.MessageTypeInfo,
Message: "queued",
}).Message()
done := make(chan error, 1)
go func() {
for range 1000 {
if err := server.send(msg); err != nil {
done <- err
return
}
}
done <- nil
}()
select {
case err := <-done:
if err != nil {
t.Fatal(err)
}
case <-t.Context().Done():
t.Fatal("sending outgoing messages blocked without a writer")
}
}