Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
2ae52e9
Implement yarn pnp api
GGomez99 Oct 29, 2025
134f3dc
Add pnpVFS + tests
GGomez99 Oct 29, 2025
fad87fa
Insert pnpApi in Host for LSP and CLI usages
GGomez99 Oct 29, 2025
f086507
Handle zip paths for LSP
GGomez99 Oct 29, 2025
e4a3c4b
Add pnp tests
GGomez99 Oct 29, 2025
9aa7f3e
Fix pnpvfs test in windows
GGomez99 Oct 31, 2025
6e2eaff
add pnp error handling and test (#3)
gun-yu Nov 2, 2025
f3c6477
Merge branch 'main' into guyllian.gomez/yarn-pnp
GGomez99 Nov 3, 2025
b382639
Apply lint on last pnp changes
GGomez99 Nov 3, 2025
f8dd02f
Add pnp import completion
GGomez99 Nov 5, 2025
2f17744
Apply new lint fixes
GGomez99 Nov 6, 2025
993103b
Mark any external pnp dependency as isExternalLibraryImport=true
GGomez99 Nov 6, 2025
0665cd8
Handle empty strings for FindLocator
GGomez99 Nov 12, 2025
c343dca
Merge branch 'main' into guyllian.gomez/yarn-pnp
GGomez99 Nov 20, 2025
781b5de
Use strings.Cut instead of string.Index for pnp
GGomez99 Nov 20, 2025
68db04a
Fix completion issue for pnp packages
GGomez99 Nov 20, 2025
a5024e3
Merge branch 'main' into guyllian.gomez/yarn-pnp
GGomez99 Dec 5, 2025
151d26b
Use updated diagnostic messages in pnpapi + fix autocomplete tests
GGomez99 Dec 5, 2025
9d4c544
Fix tests after main merge
GGomez99 Dec 5, 2025
21d0050
Merge branch 'main' into guyllian.gomez/yarn-pnp
GGomez99 Jan 16, 2026
f46e24d
Fix autocomplete for pnp to support autoimport new infra
GGomez99 Jan 16, 2026
e21901d
Merge branch 'main' into guyllian.gomez/yarn-pnp
GGomez99 Feb 3, 2026
44c1f30
Fix yarn patch implementation by returning resolved paths on transiti…
GGomez99 Feb 17, 2026
b10a0dc
Make IsInPnpModule stricter by only matching valid dependencies
GGomez99 Feb 18, 2026
252e851
Merge branch 'main' into guyllian.gomez/yarn-pnp
GGomez99 Feb 18, 2026
5cb7feb
Fix tests and lint after main merge + revert submodule hash diff
GGomez99 Feb 19, 2026
49a92c0
Merge branch 'main' into guyllian.gomez/yarn-pnp
GGomez99 Mar 23, 2026
88120df
Merge branch 'main' into guyllian.gomez/yarn-pnp
GGomez99 Mar 30, 2026
f4c7635
Remove usages of regexp2 in yarn pnp
GGomez99 Mar 30, 2026
4acc00f
Fix tests for pnp
GGomez99 Mar 30, 2026
446cca0
Merge branch 'main' into guyllian.gomez/yarn-pnp
GGomez99 Apr 13, 2026
66f802d
Fix yarn-pnp initialization ordering
hegrec Apr 13, 2026
515e20b
Merge pull request #4 from hegrec/fix/callbackfs-pnp-panic
GGomez99 Apr 13, 2026
3e87b7f
Merge branch 'main' into guyllian.gomez/yarn-pnp
GGomez99 Apr 15, 2026
5e25a5e
Yarn-pnp: Attach to session and hoist filesystem overrides
hegrec Apr 15, 2026
06c8485
Merge pull request #5 from hegrec/fix_yarn_2
GGomez99 Apr 16, 2026
daac702
Merge branch 'main' into guyllian.gomez/yarn-pnp
GGomez99 May 12, 2026
0ed2b6f
Always return a case sensitive iovfs when pnpfs is active
GGomez99 May 18, 2026
3261a7b
Assess expected and unexpected errors in pnpapi tests
GGomez99 May 18, 2026
e3641b3
Set missing pnpapi in NewVFSParseConfigHost
GGomez99 May 18, 2026
3041395
Plug pnpvfs cache clearing to cachedvfs
GGomez99 May 18, 2026
653433f
Merge branch 'main' into guyllian.gomez/yarn-pnp
GGomez99 Jun 9, 2026
24a3ef8
Fix tests after merge
GGomez99 Jun 9, 2026
088c3f1
Merge branch 'main' into guyllian.gomez/yarn-pnp
GGomez99 Jun 19, 2026
74e9dee
Fix missing pnpapi method in aliasresolver test
GGomez99 Jun 19, 2026
3954f78
Merge branch 'main' into guyllian.gomez/yarn-pnp
GGomez99 Jul 2, 2026
f3fa6ef
Fix test fixtures for pnp
GGomez99 Jul 2, 2026
ff6ade7
Invalidate all projects if .pnp.cjs changes
GGomez99 Jul 2, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions _extension/src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ export class Client implements vscode.Disposable {
this.documentSelector = [
...jsTsLanguageModes.map(language => ({ scheme: "file", language })),
...jsTsLanguageModes.map(language => ({ scheme: "untitled", language })),
...jsTsLanguageModes.map(language => ({ scheme: "zip", language })),
];
this.clientOptions = {
documentSelector: this.documentSelector,
Expand Down
17 changes: 16 additions & 1 deletion cmd/tsgo/sys.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,11 @@ import (

"github.com/microsoft/typescript-go/internal/bundled"
"github.com/microsoft/typescript-go/internal/execute/tsc"
"github.com/microsoft/typescript-go/internal/pnp"
"github.com/microsoft/typescript-go/internal/tspath"
"github.com/microsoft/typescript-go/internal/vfs"
"github.com/microsoft/typescript-go/internal/vfs/osvfs"
"github.com/microsoft/typescript-go/internal/vfs/pnpvfs"
"golang.org/x/term"
)

Expand All @@ -20,6 +22,7 @@ type osSys struct {
defaultLibraryPath string
cwd string
start time.Time
pnpApi *pnp.PnpApi
}

func (s *osSys) SinceStart() time.Duration {
Expand Down Expand Up @@ -59,18 +62,30 @@ func (s *osSys) GetEnvironmentVariable(name string) string {
return os.Getenv(name)
}

func (s *osSys) PnpApi() *pnp.PnpApi {
return s.pnpApi
}

func newSystem() *osSys {
cwd, err := os.Getwd()
if err != nil {
fmt.Fprintf(os.Stderr, "Error getting current directory: %v\n", err)
os.Exit(int(tsc.ExitStatusInvalidProject_OutputsSkipped))
}

var fs vfs.FS = osvfs.FS()

pnpApi := pnp.InitPnpApi(fs, tspath.NormalizePath(cwd))
if pnpApi != nil {
fs = pnpvfs.From(fs)
}

return &osSys{
cwd: tspath.NormalizePath(cwd),
fs: bundled.WrapFS(osvfs.FS()),
fs: bundled.WrapFS(fs),
defaultLibraryPath: bundled.LibPath(),
writer: os.Stdout,
start: time.Now(),
pnpApi: pnpApi,
}
}
15 changes: 13 additions & 2 deletions internal/api/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,11 @@ import (

"github.com/microsoft/typescript-go/internal/bundled"
"github.com/microsoft/typescript-go/internal/lsp/lsproto"
"github.com/microsoft/typescript-go/internal/pnp"
"github.com/microsoft/typescript-go/internal/project"
"github.com/microsoft/typescript-go/internal/vfs"
"github.com/microsoft/typescript-go/internal/vfs/osvfs"
"github.com/microsoft/typescript-go/internal/vfs/pnpvfs"
)

// StdioServerOptions configures the STDIO-based API server.
Expand Down Expand Up @@ -63,7 +66,14 @@ func (s *StdioServer) Run(ctx context.Context) error {
transport = t
}

fs := bundled.WrapFS(osvfs.FS())
var fs vfs.FS = osvfs.FS()

pnpApi := pnp.InitPnpApi(fs, s.options.Cwd)
if pnpApi != nil {
fs = pnpvfs.From(fs)
}

fs = bundled.WrapFS(fs)

// Wrap the base FS with callbackFS if callbacks are requested
var callbackFS *callbackFS
Expand All @@ -75,7 +85,8 @@ func (s *StdioServer) Run(ctx context.Context) error {
projectSession := project.NewSession(&project.SessionInit{
BackgroundCtx: ctx,
Logger: nil, // TODO: Add logging support
FS: fs,
FS: fs,
PnpApi: pnpApi,
Options: &project.SessionOptions{
CurrentDirectory: s.options.Cwd,
DefaultLibraryPath: s.options.DefaultLibraryPath,
Expand Down
4 changes: 2 additions & 2 deletions internal/checker/checker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ foo.bar;`
fs = bundled.WrapFS(fs)

cd := "/"
host := compiler.NewCompilerHost(cd, fs, bundled.LibPath(), nil, nil)
host := compiler.NewCompilerHost(cd, fs, bundled.LibPath(), nil, nil, nil)

parsed, errors := tsoptions.GetParsedCommandLineOfConfigFile("/tsconfig.json", &core.CompilerOptions{}, nil, host, nil)
assert.Equal(t, len(errors), 0, "Expected no errors in parsed command line")
Expand Down Expand Up @@ -68,7 +68,7 @@ func BenchmarkNewChecker(b *testing.B) {

rootPath := tspath.CombinePaths(tspath.NormalizeSlashes(repo.TypeScriptSubmodulePath()), "src", "compiler")

host := compiler.NewCompilerHost(rootPath, fs, bundled.LibPath(), nil, nil)
host := compiler.NewCompilerHost(rootPath, fs, bundled.LibPath(), nil, nil, nil)
parsed, errors := tsoptions.GetParsedCommandLineOfConfigFile(tspath.CombinePaths(rootPath, "tsconfig.json"), &core.CompilerOptions{}, nil, host, nil)
assert.Equal(b, len(errors), 0, "Expected no errors in parsed command line")
p := compiler.NewProgram(compiler.ProgramOptions{
Expand Down
5 changes: 4 additions & 1 deletion internal/compiler/emitHost.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/microsoft/typescript-go/internal/module"
"github.com/microsoft/typescript-go/internal/outputpaths"
"github.com/microsoft/typescript-go/internal/packagejson"
"github.com/microsoft/typescript-go/internal/pnp"
"github.com/microsoft/typescript-go/internal/printer"
"github.com/microsoft/typescript-go/internal/symlinks"
"github.com/microsoft/typescript-go/internal/transformers/declarations"
Expand All @@ -25,6 +26,7 @@ type EmitHost interface {
GetCurrentDirectory() string
CommonSourceDirectory() string
IsEmitBlocked(file string) bool
PnpApi() *pnp.PnpApi
}

var _ EmitHost = (*emitHost)(nil)
Expand Down Expand Up @@ -108,11 +110,12 @@ func (host *emitHost) Options() *core.CompilerOptions { return host.program.Opti
func (host *emitHost) SourceFiles() []*ast.SourceFile { return host.program.SourceFiles() }
func (host *emitHost) GetCurrentDirectory() string { return host.program.GetCurrentDirectory() }
func (host *emitHost) CommonSourceDirectory() string { return host.program.CommonSourceDirectory() }

func (host *emitHost) UseCaseSensitiveFileNames() bool {
return host.program.UseCaseSensitiveFileNames()
}

func (host *emitHost) PnpApi() *pnp.PnpApi { return host.program.PnpApi() }

func (host *emitHost) IsEmitBlocked(file string) bool {
return host.program.IsEmitBlocked(file)
}
Expand Down
6 changes: 3 additions & 3 deletions internal/compiler/emit_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ func BenchmarkEmitLongLines(b *testing.B) {
OutDir: "/dev/out",
}

host := compiler.NewCompilerHost("/dev/src", fs, bundled.LibPath(), nil, nil)
host := compiler.NewCompilerHost("/dev/src", fs, bundled.LibPath(), nil, nil, nil)

p := compiler.NewProgram(compiler.ProgramOptions{
Config: &tsoptions.ParsedCommandLine{
Expand Down Expand Up @@ -106,7 +106,7 @@ func BenchmarkEmitManyFiles(b *testing.B) {
OutDir: "/dev/out",
}

host := compiler.NewCompilerHost("/dev/src", fs, bundled.LibPath(), nil, nil)
host := compiler.NewCompilerHost("/dev/src", fs, bundled.LibPath(), nil, nil, nil)

p := compiler.NewProgram(compiler.ProgramOptions{
Config: &tsoptions.ParsedCommandLine{
Expand Down Expand Up @@ -164,7 +164,7 @@ func BenchmarkEmitLongLinesWithLineBreaks(b *testing.B) {
OutDir: "/dev/out",
}

host := compiler.NewCompilerHost("/dev/src", fs, bundled.LibPath(), nil, nil)
host := compiler.NewCompilerHost("/dev/src", fs, bundled.LibPath(), nil, nil, nil)

p := compiler.NewProgram(compiler.ProgramOptions{
Config: &tsoptions.ParsedCommandLine{
Expand Down
13 changes: 12 additions & 1 deletion internal/compiler/host.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"github.com/microsoft/typescript-go/internal/core"
"github.com/microsoft/typescript-go/internal/diagnostics"
"github.com/microsoft/typescript-go/internal/parser"
"github.com/microsoft/typescript-go/internal/pnp"
"github.com/microsoft/typescript-go/internal/tsoptions"
"github.com/microsoft/typescript-go/internal/tspath"
"github.com/microsoft/typescript-go/internal/vfs"
Expand All @@ -18,6 +19,7 @@ type CompilerHost interface {
Trace(msg *diagnostics.Message, args ...any)
GetSourceFile(opts ast.SourceFileParseOptions) *ast.SourceFile
GetResolvedProjectReference(fileName string, path tspath.Path) *tsoptions.ParsedCommandLine
PnpApi() *pnp.PnpApi
}

var _ CompilerHost = (*compilerHost)(nil)
Expand All @@ -27,6 +29,7 @@ type compilerHost struct {
fs vfs.FS
defaultLibraryPath string
extendedConfigCache tsoptions.ExtendedConfigCache
pnpApi *pnp.PnpApi
trace func(msg *diagnostics.Message, args ...any)
}

Expand All @@ -35,27 +38,31 @@ func NewCachedFSCompilerHost(
fs vfs.FS,
defaultLibraryPath string,
extendedConfigCache tsoptions.ExtendedConfigCache,
pnpApi *pnp.PnpApi,
trace func(msg *diagnostics.Message, args ...any),
) CompilerHost {
return NewCompilerHost(currentDirectory, cachedvfs.From(fs), defaultLibraryPath, extendedConfigCache, trace)
return NewCompilerHost(currentDirectory, cachedvfs.From(fs), defaultLibraryPath, extendedConfigCache, pnpApi, trace)
}

func NewCompilerHost(
currentDirectory string,
fs vfs.FS,
defaultLibraryPath string,
extendedConfigCache tsoptions.ExtendedConfigCache,
pnpApi *pnp.PnpApi,
trace func(msg *diagnostics.Message, args ...any),
) CompilerHost {
if trace == nil {
trace = func(msg *diagnostics.Message, args ...any) {}
}

return &compilerHost{
currentDirectory: currentDirectory,
fs: fs,
defaultLibraryPath: defaultLibraryPath,
extendedConfigCache: extendedConfigCache,
trace: trace,
pnpApi: pnpApi,
}
}

Expand All @@ -71,6 +78,10 @@ func (h *compilerHost) GetCurrentDirectory() string {
return h.currentDirectory
}

func (h *compilerHost) PnpApi() *pnp.PnpApi {
return h.pnpApi
}

func (h *compilerHost) Trace(msg *diagnostics.Message, args ...any) {
h.trace(msg, args...)
}
Expand Down
6 changes: 6 additions & 0 deletions internal/compiler/program.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"github.com/microsoft/typescript-go/internal/outputpaths"
"github.com/microsoft/typescript-go/internal/packagejson"
"github.com/microsoft/typescript-go/internal/parser"
"github.com/microsoft/typescript-go/internal/pnp"
"github.com/microsoft/typescript-go/internal/printer"
"github.com/microsoft/typescript-go/internal/scanner"
"github.com/microsoft/typescript-go/internal/sourcemap"
Expand Down Expand Up @@ -128,6 +129,11 @@ func (p *Program) GetCurrentDirectory() string {
return p.Host().GetCurrentDirectory()
}

// PnpApi implements checker.Program.
func (p *Program) PnpApi() *pnp.PnpApi {
return p.Host().PnpApi()
}

// GetGlobalTypingsCacheLocation implements checker.Program.
func (p *Program) GetGlobalTypingsCacheLocation() string {
return p.opts.TypingsLocation
Expand Down
8 changes: 4 additions & 4 deletions internal/compiler/program_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,7 @@ func TestProgram(t *testing.T) {
CompilerOptions: &opts,
},
},
Host: compiler.NewCompilerHost("c:/dev/src", fs, bundled.LibPath(), nil, nil),
Host: compiler.NewCompilerHost("c:/dev/src", fs, bundled.LibPath(), nil, nil, nil),
})

actualFiles := []string{}
Expand Down Expand Up @@ -291,7 +291,7 @@ func TestIncludeProcessorDiagnosticsWithMissingFileCasing(t *testing.T) {
CompilerOptions: &opts,
},
},
Host: compiler.NewCompilerHost("/", fs, bundled.LibPath(), nil, nil),
Host: compiler.NewCompilerHost("/", fs, bundled.LibPath(), nil, nil, nil),
})

// GetProgramDiagnostics triggers getDiagnostics which processes all
Expand Down Expand Up @@ -333,7 +333,7 @@ func BenchmarkNewProgram(b *testing.B) {
CompilerOptions: &opts,
},
},
Host: compiler.NewCompilerHost("c:/dev/src", fs, bundled.LibPath(), nil, nil),
Host: compiler.NewCompilerHost("c:/dev/src", fs, bundled.LibPath(), nil, nil, nil),
}

for b.Loop() {
Expand All @@ -350,7 +350,7 @@ func BenchmarkNewProgram(b *testing.B) {
fs := osvfs.FS()
fs = bundled.WrapFS(fs)

host := compiler.NewCompilerHost(rootPath, fs, bundled.LibPath(), nil, nil)
host := compiler.NewCompilerHost(rootPath, fs, bundled.LibPath(), nil, nil, nil)

parsed, errors := tsoptions.GetParsedCommandLineOfConfigFile(tspath.CombinePaths(rootPath, "tsconfig.json"), nil, nil, host, nil)
assert.Equal(b, len(errors), 0, "Expected no errors in parsed command line")
Expand Down
6 changes: 6 additions & 0 deletions internal/compiler/projectreferencedtsfakinghost.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"github.com/microsoft/typescript-go/internal/collections"
"github.com/microsoft/typescript-go/internal/core"
"github.com/microsoft/typescript-go/internal/module"
"github.com/microsoft/typescript-go/internal/pnp"
"github.com/microsoft/typescript-go/internal/symlinks"
"github.com/microsoft/typescript-go/internal/tspath"
"github.com/microsoft/typescript-go/internal/vfs"
Expand Down Expand Up @@ -43,6 +44,11 @@ func (h *projectReferenceDtsFakingHost) GetCurrentDirectory() string {
return h.host.GetCurrentDirectory()
}

// PnpApi implements module.ResolutionHost.
func (h *projectReferenceDtsFakingHost) PnpApi() *pnp.PnpApi {
return h.host.PnpApi()
}

type projectReferenceDtsFakingVfs struct {
projectReferenceFileMapper *projectReferenceFileMapper
dtsDirectories collections.Set[tspath.Path]
Expand Down
10 changes: 10 additions & 0 deletions internal/core/compileroptions.go
Original file line number Diff line number Diff line change
Expand Up @@ -302,6 +302,13 @@ func (options *CompilerOptions) GetEffectiveTypeRoots(currentDirectory string) (
if options.TypeRoots != nil {
return options.TypeRoots, true
}
baseDir := options.GetBaseDirFromOptions(currentDirectory)

nmTypes, nmFromConfig := options.GetNodeModulesTypeRoots(baseDir)
return nmTypes, nmFromConfig
}

func (options *CompilerOptions) GetBaseDirFromOptions(currentDirectory string) string {
var baseDir string
if options.ConfigFilePath != "" {
baseDir = tspath.GetDirectoryPath(options.ConfigFilePath)
Expand All @@ -313,7 +320,10 @@ func (options *CompilerOptions) GetEffectiveTypeRoots(currentDirectory string) (
panic("cannot get effective type roots without a config file path or current directory")
}
}
return baseDir
}

func (options *CompilerOptions) GetNodeModulesTypeRoots(baseDir string) (result []string, fromConfig bool) {
typeRoots := make([]string, 0, strings.Count(baseDir, "/"))
tspath.ForEachAncestorDirectory(baseDir, func(dir string) (any, bool) {
typeRoots = append(typeRoots, tspath.CombinePaths(dir, "node_modules", "@types"))
Expand Down
32 changes: 32 additions & 0 deletions internal/diagnostics/diagnostics_generated.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading