Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
c315580
add pnp resolution support
gun-yu Oct 11, 2025
99dc36c
remove fmt
gun-yu Oct 11, 2025
25b13ac
pnp internalize
gun-yu Oct 11, 2025
f24a170
remove useless code
gun-yu Oct 11, 2025
b4aaac8
remove useless code
gun-yu Oct 11, 2025
2373552
use go-json-experiment/json
gun-yu Oct 11, 2025
f09cda5
lint fix
gun-yu Oct 12, 2025
d00e36b
Merge branch 'main' into feat/add-pnp-resolver
gun-yu Oct 12, 2025
0a0f050
change test data path
gun-yu Oct 12, 2025
94a15b7
fix hereby format
gun-yu Oct 12, 2025
35d6188
fix hereby check:format
gun-yu Oct 13, 2025
35ee2ef
fix window test
gun-yu Oct 13, 2025
9463e11
Merge branch 'feat/add-pnp-resolver' of https://github.com/gun-yu/typ…
gun-yu Oct 13, 2025
dd08ae5
Merge branch 'main' into feat/add-pnp-resolver
gun-yu Oct 14, 2025
b368c1c
add License
gun-yu Oct 14, 2025
688455e
Merge branch 'feat/add-pnp-resolver' of https://github.com/gun-yu/typ…
gun-yu Oct 14, 2025
305fd49
remove filepath and utils
gun-yu Oct 16, 2025
f0ee55b
make regex more efficient
gun-yu Oct 16, 2025
ef6d713
fix lint
gun-yu Oct 16, 2025
8d165ca
Merge branch 'main' into feat/add-pnp-resolver
gun-yu Oct 16, 2025
ae272f1
apply codereview
gun-yu Oct 18, 2025
67752dc
generate error message
gun-yu Oct 18, 2025
1f06041
add error message
gun-yu Oct 18, 2025
a9dbc68
parse pnp.cjs file, regex to ast
gun-yu Oct 18, 2025
df40d62
make go version 1.25.0
gun-yu Oct 18, 2025
1485fe3
remove useless test
gun-yu Oct 18, 2025
bfa05c3
apply UnmarshalJSONFrom
gun-yu Oct 21, 2025
e697dce
apply UnmarshalJSONFrom in manifest
gun-yu Oct 21, 2025
1041038
os to vfs
gun-yu Oct 23, 2025
baf7d5a
Merge branch 'main' into feat/add-pnp-resolver
gun-yu Oct 24, 2025
01b7670
inject pnpResolutionConfig
gun-yu Oct 24, 2025
707270b
Merge branch 'feat/add-pnp-resolver' of https://github.com/gun-yu/typ…
gun-yu Oct 24, 2025
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
6 changes: 3 additions & 3 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{}, host, nil)
assert.Equal(t, len(errors), 0, "Expected no errors in parsed command line")
Expand Down Expand Up @@ -70,7 +70,7 @@ func TestCheckSrcCompiler(t *testing.T) {

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{}, host, nil)
assert.Equal(t, len(errors), 0, "Expected no errors in parsed command line")
p := compiler.NewProgram(compiler.ProgramOptions{
Expand All @@ -87,7 +87,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{}, host, nil)
assert.Equal(b, len(errors), 0, "Expected no errors in parsed command line")
p := compiler.NewProgram(compiler.ProgramOptions{
Expand Down
2 changes: 1 addition & 1 deletion internal/compiler/fileloader.go
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ func processAllProgramFiles(
includeProcessor: &includeProcessor{},
}
loader.addProjectReferenceTasks(singleThreaded)
loader.resolver = module.NewResolver(loader.projectReferenceFileMapper.host, compilerOptions, opts.TypingsLocation, opts.ProjectName)
loader.resolver = module.NewResolver(loader.projectReferenceFileMapper.host, compilerOptions, opts.TypingsLocation, opts.ProjectName, opts.Host.GetPNPResolutionConfig())
for index, rootFile := range rootFiles {
loader.addRootTask(rootFile, nil, &fileIncludeReason{kind: fileIncludeKindRootFile, data: index})
}
Expand Down
13 changes: 12 additions & 1 deletion internal/compiler/host.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package compiler
import (
"github.com/microsoft/typescript-go/internal/ast"
"github.com/microsoft/typescript-go/internal/core"
"github.com/microsoft/typescript-go/internal/module/pnp"
"github.com/microsoft/typescript-go/internal/parser"
"github.com/microsoft/typescript-go/internal/tsoptions"
"github.com/microsoft/typescript-go/internal/tspath"
Expand All @@ -17,6 +18,7 @@ type CompilerHost interface {
Trace(msg string)
GetSourceFile(opts ast.SourceFileParseOptions) *ast.SourceFile
GetResolvedProjectReference(fileName string, path tspath.Path) *tsoptions.ParsedCommandLine
GetPNPResolutionConfig() *pnp.ResolutionConfig
}

var _ CompilerHost = (*compilerHost)(nil)
Expand All @@ -27,6 +29,7 @@ type compilerHost struct {
defaultLibraryPath string
extendedConfigCache tsoptions.ExtendedConfigCache
trace func(msg string)
pnpResolutionConfig *pnp.ResolutionConfig
}

func NewCachedFSCompilerHost(
Expand All @@ -35,8 +38,9 @@ func NewCachedFSCompilerHost(
defaultLibraryPath string,
extendedConfigCache tsoptions.ExtendedConfigCache,
trace func(msg string),
pnpResolutionConfig *pnp.ResolutionConfig,
) CompilerHost {
return NewCompilerHost(currentDirectory, cachedvfs.From(fs), defaultLibraryPath, extendedConfigCache, trace)
return NewCompilerHost(currentDirectory, cachedvfs.From(fs), defaultLibraryPath, extendedConfigCache, trace, pnpResolutionConfig)
}

func NewCompilerHost(
Expand All @@ -45,16 +49,19 @@ func NewCompilerHost(
defaultLibraryPath string,
extendedConfigCache tsoptions.ExtendedConfigCache,
trace func(msg string),
pnpResolutionConfig *pnp.ResolutionConfig,
) CompilerHost {
if trace == nil {
trace = func(msg string) {}
}

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

Expand Down Expand Up @@ -86,3 +93,7 @@ func (h *compilerHost) GetResolvedProjectReference(fileName string, path tspath.
commandLine, _ := tsoptions.GetParsedCommandLineOfConfigFilePath(fileName, path, nil, h, h.extendedConfigCache)
return commandLine
}

func (h *compilerHost) GetPNPResolutionConfig() *pnp.ResolutionConfig {
return h.pnpResolutionConfig
}
21 changes: 21 additions & 0 deletions internal/compiler/pnp.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package compiler

import (
"github.com/microsoft/typescript-go/internal/module/pnp"
"github.com/microsoft/typescript-go/internal/vfs"
)

func TryGetPnpResolutionConfig(path string, fs vfs.FS) *pnp.ResolutionConfig {
pnpManifest, err := pnp.FindPNPManifest(path, fs)
if err != nil {
return nil
}

return &pnp.ResolutionConfig{
Host: pnp.PNPResolutionHost{
FindPNPManifest: func(_ string) (*pnp.Manifest, error) {
return pnpManifest, nil
},
},
}
}
6 changes: 3 additions & 3 deletions internal/compiler/program_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,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 @@ -280,7 +280,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 @@ -297,7 +297,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, host, nil)
assert.Equal(b, len(errors), 0, "Expected no errors in parsed command line")
Expand Down
30 changes: 30 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.

60 changes: 60 additions & 0 deletions internal/diagnostics/extraDiagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,5 +38,65 @@
"Project '{0}' is out of date because it has errors.": {
"category": "Message",
"code": 6423
},
"Invalid specifier": {
"category": "Error",
"code": 100010
},
"assertion failed: should have a top-level name key": {
"category": "Error",
"code": 100011
},
"assertion failed: should have a top-level range key": {
"category": "Error",
"code": 100012
},
"We failed to read the content of the manifest: {0}": {
"category": "Error",
"code": 100013
},
"We failed to locate the PnP data payload inside its manifest file. Did you manually edit the file?": {
"category": "Error",
"code": 100014
},
"We failed to parse the PnP data payload as proper JSON; Did you manually edit the file?: {0}": {
"category": "Error",
"code": 100015
},
"We failed to init the PnP manifest: {0}": {
"category": "Error",
"code": 100016
},
"should have an entry in the package registry for {0}": {
"category": "Error",
"code": 100017
},
" (via \"{0}\")": {
"category": "Error",
"code": 100018
},
"Your application tried to access {0}. While this module is usually interpreted as a Node builtin, your resolver is running inside a non-Node resolution context where such builtins are ignored. Since {0} isn't otherwise declared in your dependencies, this makes the require call ambiguous and unsound.\n\nRequired package: {0}{1}\nRequired by: {2}": {
"category": "Error",
"code": 100019
},
"{0} tried to access {1}. While this module is usually interpreted as a Node builtin, your resolver is running inside a non-Node resolution context where such builtins are ignored. Since {1} isn't otherwise declared in {0}'s dependencies, this makes the require call ambiguous and unsound.\n\nRequired package: {1}{2}\nRequired by: {3}": {
"category": "Error",
"code": 100020
},
"Your application tried to access {0}, but it isn't declared in your dependencies; this makes the require call ambiguous and unsound.\n\nRequired package: {0}{1}\nRequired by: {2}": {
"category": "Error",
"code": 100021
},
"{0} tried to access {1} (a peer dependency) but it isn't provided by your application; this makes the require call ambiguous and unsound.\n\nRequired package: {1}{2}\nRequired by: {0}@{3} (via {4})": {
"category": "Error",
"code": 100022
},
"{0} tried to access {1} (a peer dependency) but it isn't provided by its ancestors; this makes the require call ambiguous and unsound.\n\nRequired package: {1}{2}\nRequired by: {0}@{3} (via {4})": {
"category": "Error",
"code": 100023
},
"no host configured": {
"category": "Error",
"code": 100024
}
}
5 changes: 5 additions & 0 deletions internal/execute/build/compilerHost.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package build
import (
"github.com/microsoft/typescript-go/internal/ast"
"github.com/microsoft/typescript-go/internal/compiler"
"github.com/microsoft/typescript-go/internal/module/pnp"
"github.com/microsoft/typescript-go/internal/tsoptions"
"github.com/microsoft/typescript-go/internal/tspath"
"github.com/microsoft/typescript-go/internal/vfs"
Expand Down Expand Up @@ -38,3 +39,7 @@ func (h *compilerHost) GetSourceFile(opts ast.SourceFileParseOptions) *ast.Sourc
func (h *compilerHost) GetResolvedProjectReference(fileName string, path tspath.Path) *tsoptions.ParsedCommandLine {
return h.host.GetResolvedProjectReference(fileName, path)
}

func (h *compilerHost) GetPNPResolutionConfig() *pnp.ResolutionConfig {
return h.host.GetPNPResolutionConfig()
}
10 changes: 8 additions & 2 deletions internal/execute/build/host.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/microsoft/typescript-go/internal/compiler"
"github.com/microsoft/typescript-go/internal/execute/incremental"
"github.com/microsoft/typescript-go/internal/execute/tsc"
"github.com/microsoft/typescript-go/internal/module/pnp"
"github.com/microsoft/typescript-go/internal/tsoptions"
"github.com/microsoft/typescript-go/internal/tspath"
"github.com/microsoft/typescript-go/internal/vfs"
Expand All @@ -23,8 +24,9 @@ type host struct {
configTimes collections.SyncMap[tspath.Path, time.Duration]

// caches that stay as long as they are needed
resolvedReferences parseCache[tspath.Path, *tsoptions.ParsedCommandLine]
mTimes *collections.SyncMap[tspath.Path, time.Time]
resolvedReferences parseCache[tspath.Path, *tsoptions.ParsedCommandLine]
mTimes *collections.SyncMap[tspath.Path, time.Time]
pnpResolutionConfig *pnp.ResolutionConfig
}

var (
Expand Down Expand Up @@ -111,3 +113,7 @@ func (h *host) storeMTimeFromOldCache(file string, oldCache *collections.SyncMap
h.mTimes.Store(path, mTime)
}
}

func (h *host) GetPNPResolutionConfig() *pnp.ResolutionConfig {
return h.pnpResolutionConfig
}
9 changes: 8 additions & 1 deletion internal/execute/build/orchestrator.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/microsoft/typescript-go/internal/tsoptions"
"github.com/microsoft/typescript-go/internal/tspath"
"github.com/microsoft/typescript-go/internal/vfs/cachedvfs"
"github.com/microsoft/typescript-go/internal/vfs/zipvfs"
)

type Options struct {
Expand Down Expand Up @@ -380,14 +381,20 @@ func NewOrchestrator(opts Options) *Orchestrator {
},
tasks: &collections.SyncMap[tspath.Path, *buildTask]{},
}
pnpResolutionConfig := compiler.TryGetPnpResolutionConfig(orchestrator.opts.Sys.GetCurrentDirectory(), orchestrator.opts.Sys.FS())
fs := orchestrator.opts.Sys.FS()
if pnpResolutionConfig != nil {
fs = zipvfs.From(fs)
}
orchestrator.host = &host{
orchestrator: orchestrator,
host: compiler.NewCachedFSCompilerHost(
orchestrator.opts.Sys.GetCurrentDirectory(),
orchestrator.opts.Sys.FS(),
fs,
orchestrator.opts.Sys.DefaultLibraryPath(),
nil,
nil,
pnpResolutionConfig,
),
mTimes: &collections.SyncMap[tspath.Path, time.Time]{},
}
Expand Down
15 changes: 13 additions & 2 deletions internal/execute/tsc.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"github.com/microsoft/typescript-go/internal/pprof"
"github.com/microsoft/typescript-go/internal/tsoptions"
"github.com/microsoft/typescript-go/internal/tspath"
"github.com/microsoft/typescript-go/internal/vfs/zipvfs"
)

func CommandLine(sys tsc.System, commandLineArgs []string, testing tsc.CommandLineTesting) tsc.CommandLineResult {
Expand Down Expand Up @@ -245,7 +246,12 @@ func performIncrementalCompilation(
compileTimes *tsc.CompileTimes,
testing tsc.CommandLineTesting,
) tsc.CommandLineResult {
host := compiler.NewCachedFSCompilerHost(sys.GetCurrentDirectory(), sys.FS(), sys.DefaultLibraryPath(), extendedConfigCache, getTraceFromSys(sys, testing))
pnpResolutionConfig := compiler.TryGetPnpResolutionConfig(sys.GetCurrentDirectory(), sys.FS())
fs := sys.FS()
if pnpResolutionConfig != nil {
fs = zipvfs.From(fs)
}
host := compiler.NewCachedFSCompilerHost(sys.GetCurrentDirectory(), fs, sys.DefaultLibraryPath(), extendedConfigCache, getTraceFromSys(sys, testing), pnpResolutionConfig)
buildInfoReadStart := sys.Now()
oldProgram := incremental.ReadBuildInfoProgram(config, incremental.NewBuildInfoReader(host), host)
compileTimes.BuildInfoReadTime = sys.Now().Sub(buildInfoReadStart)
Expand Down Expand Up @@ -288,7 +294,12 @@ func performCompilation(
compileTimes *tsc.CompileTimes,
testing tsc.CommandLineTesting,
) tsc.CommandLineResult {
host := compiler.NewCachedFSCompilerHost(sys.GetCurrentDirectory(), sys.FS(), sys.DefaultLibraryPath(), extendedConfigCache, getTraceFromSys(sys, testing))
pnpResolutionConfig := compiler.TryGetPnpResolutionConfig(sys.GetCurrentDirectory(), sys.FS())
fs := sys.FS()
if pnpResolutionConfig != nil {
fs = zipvfs.From(fs)
}
host := compiler.NewCachedFSCompilerHost(sys.GetCurrentDirectory(), fs, sys.DefaultLibraryPath(), extendedConfigCache, getTraceFromSys(sys, testing), pnpResolutionConfig)
// todo: cache, statistics, tracing
parseStart := sys.Now()
program := compiler.NewProgram(compiler.ProgramOptions{
Expand Down
Loading