Skip to content

Commit ba79e84

Browse files
committed
general callback api, start resolver wrapper
1 parent 366bf8a commit ba79e84

File tree

2 files changed

+113
-31
lines changed

2 files changed

+113
-31
lines changed

internal/lsp/lsproto/lsp_generated.go

Lines changed: 12 additions & 18 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/lsp/server.go

Lines changed: 101 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@ import (
2020
"github.com/microsoft/typescript-go/internal/collections"
2121
"github.com/microsoft/typescript-go/internal/compiler"
2222
"github.com/microsoft/typescript-go/internal/core"
23+
"github.com/microsoft/typescript-go/internal/diagnostics"
24+
"github.com/microsoft/typescript-go/internal/module"
2325
"github.com/microsoft/typescript-go/internal/format"
2426
"github.com/microsoft/typescript-go/internal/jsonutil"
2527
"github.com/microsoft/typescript-go/internal/locale"
@@ -241,13 +243,6 @@ func NewDenoVFS(server *Server, ctx context.Context, compilerOptionsKey string,
241243
}
242244
}
243245

244-
func (v *DenoVFS) baseParams() lsproto.DenoHostBaseParams {
245-
return lsproto.DenoHostBaseParams{
246-
CompilerOptionsKey: v.compilerOptionsKey,
247-
NotebookUri: v.notebookUri,
248-
}
249-
}
250-
251246
func (v *DenoVFS) UseCaseSensitiveFileNames() bool {
252247
return true
253248
}
@@ -271,12 +266,13 @@ func (v *DenoVFS) GetDocument(path string) *lsproto.DenoDocumentData {
271266
return data
272267
}
273268
}
274-
params := lsproto.DenoHostGetDocumentParams{
275-
DenoHostBaseParams: v.baseParams(),
276-
Uri: uri,
269+
params := lsproto.DenoCallbackParams{
270+
GetDocument: &lsproto.DenoGetDocumentParams{
271+
Uri: uri,
272+
},
277273
}
278274
var response lsproto.DenoDocumentData
279-
err := v.server.sendRequestSync(v.ctx, lsproto.MethodDenoHostGetDocument, params, &response)
275+
err := v.server.sendRequestSync(v.ctx, lsproto.MethodDenoCallback, params, &response)
280276
if err != nil || response.Text == nil {
281277
return nil
282278
}
@@ -367,6 +363,94 @@ func (h *denoAutoImportHost) GetSourceFile(fileName string, path tspath.Path) *a
367363
func (h *denoAutoImportHost) Dispose() {
368364
}
369365

366+
// denoCompilerHost wraps a CompilerHost to intercept resolver creation for Deno LSP
367+
type denoCompilerHost struct {
368+
inner compiler.CompilerHost
369+
server *Server
370+
}
371+
372+
var _ compiler.CompilerHost = (*denoCompilerHost)(nil)
373+
374+
func (h *denoCompilerHost) FS() vfs.FS {
375+
return h.inner.FS()
376+
}
377+
378+
func (h *denoCompilerHost) DefaultLibraryPath() string {
379+
return h.inner.DefaultLibraryPath()
380+
}
381+
382+
func (h *denoCompilerHost) GetCurrentDirectory() string {
383+
return h.inner.GetCurrentDirectory()
384+
}
385+
386+
func (h *denoCompilerHost) Trace(msg *diagnostics.Message, args ...any) {
387+
h.inner.Trace(msg, args...)
388+
}
389+
390+
func (h *denoCompilerHost) GetSourceFile(opts ast.SourceFileParseOptions) *ast.SourceFile {
391+
return h.inner.GetSourceFile(opts)
392+
}
393+
394+
func (h *denoCompilerHost) GetResolvedProjectReference(fileName string, path tspath.Path) *tsoptions.ParsedCommandLine {
395+
return h.inner.GetResolvedProjectReference(fileName, path)
396+
}
397+
398+
func (h *denoCompilerHost) IsNodeSourceFile(path tspath.Path) bool {
399+
return h.inner.IsNodeSourceFile(path)
400+
}
401+
402+
func (h *denoCompilerHost) GetDenoForkContextInfo() ast.DenoForkContextInfo {
403+
return h.inner.GetDenoForkContextInfo()
404+
}
405+
406+
// MakeResolver overrides the inner host's MakeResolver to return a wrapped resolver
407+
func (h *denoCompilerHost) MakeResolver(host module.ResolutionHost, options *core.CompilerOptions,
408+
typingsLocation string, projectName string) module.ResolverInterface {
409+
baseResolver := h.inner.MakeResolver(host, options, typingsLocation, projectName)
410+
return &denoResolverWrapper{inner: baseResolver, server: h.server}
411+
}
412+
413+
// denoResolverWrapper wraps a ResolverInterface to intercept module resolution for Deno LSP
414+
type denoResolverWrapper struct {
415+
inner module.ResolverInterface
416+
server *Server
417+
}
418+
419+
var _ module.ResolverInterface = (*denoResolverWrapper)(nil)
420+
421+
func (r *denoResolverWrapper) ResolveModuleName(moduleName string, containingFile string,
422+
importAttributeType *string, resolutionMode core.ResolutionMode,
423+
redirectedReference module.ResolvedProjectReference) (*module.ResolvedModule, []module.DiagAndArgs) {
424+
// Hook point: Call Deno's custom resolution via LSP or callback
425+
// if result := r.server.denoResolveModule(...); result != nil { return result, nil }
426+
return r.inner.ResolveModuleName(moduleName, containingFile, importAttributeType, resolutionMode, redirectedReference)
427+
}
428+
429+
func (r *denoResolverWrapper) ResolveTypeReferenceDirective(name string, containingFile string,
430+
resolutionMode core.ResolutionMode,
431+
redirectedReference module.ResolvedProjectReference) (*module.ResolvedTypeReferenceDirective, []module.DiagAndArgs) {
432+
// Hook point: Call Deno's custom resolution
433+
return r.inner.ResolveTypeReferenceDirective(name, containingFile, resolutionMode, redirectedReference)
434+
}
435+
436+
func (r *denoResolverWrapper) ResolvePackageDirectory(moduleName string, containingFile string,
437+
resolutionMode core.ResolutionMode,
438+
redirectedReference module.ResolvedProjectReference) *module.ResolvedModule {
439+
return r.inner.ResolvePackageDirectory(moduleName, containingFile, resolutionMode, redirectedReference)
440+
}
441+
442+
func (r *denoResolverWrapper) ResolveJsxImportSource(referrer string) string {
443+
return r.inner.ResolveJsxImportSource(referrer)
444+
}
445+
446+
func (r *denoResolverWrapper) GetPackageScopeForPath(directory string) *packagejson.InfoCacheEntry {
447+
return r.inner.GetPackageScopeForPath(directory)
448+
}
449+
450+
func (r *denoResolverWrapper) GetImpliedNodeFormatForFile(path string, packageJsonType string) core.ModuleKind {
451+
return r.inner.GetImpliedNodeFormatForFile(path, packageJsonType)
452+
}
453+
370454
type Server struct {
371455
r Reader
372456
w Writer
@@ -1166,13 +1250,15 @@ func (s *Server) handleDenoRequest(ctx context.Context, params *lsproto.DenoRequ
11661250
updateProgram := func(pe *DenoProgramEntry) {
11671251
if pe.program.GetSourceFileByPath(filePath) != nil {
11681252
wrappedFS := bundled.WrapFS(pe.vfs)
1169-
newHost := compiler.NewCompilerHost(
1253+
baseHost := compiler.NewCompilerHost(
11701254
s.cwd,
11711255
wrappedFS,
11721256
bundled.LibPath(),
11731257
nil,
11741258
nil,
11751259
)
1260+
// Wrap the host to intercept resolution
1261+
newHost := &denoCompilerHost{inner: baseHost, server: s}
11761262
newProgram, _ := pe.program.UpdateProgram(filePath, newHost)
11771263
pe.program = newProgram
11781264
}
@@ -1361,13 +1447,15 @@ func (s *Server) getDenoLanguageService(ctx context.Context, compilerOptionsKey
13611447
func (s *Server) createDenoProgramEntry(ctx context.Context, compilerOptionsKey string, notebookUri *string, projectConfig *lsproto.DenoProjectConfig) (*DenoProgramEntry, error) {
13621448
denoVFS := NewDenoVFS(s, ctx, compilerOptionsKey, notebookUri)
13631449
wrappedFS := bundled.WrapFS(denoVFS)
1364-
compilerHost := compiler.NewCompilerHost(
1450+
baseHost := compiler.NewCompilerHost(
13651451
s.cwd,
13661452
wrappedFS,
13671453
bundled.LibPath(),
13681454
nil, // extendedConfigCache
13691455
nil, // trace
13701456
)
1457+
// Wrap the host to intercept resolution
1458+
compilerHost := &denoCompilerHost{inner: baseHost, server: s}
13711459
fileNames := make([]string, len(projectConfig.Files))
13721460
for i, file := range projectConfig.Files {
13731461
fileNames[i] = file.FileName()

0 commit comments

Comments
 (0)