@@ -11,6 +11,7 @@ import (
1111 "github.com/microsoft/typescript-go/internal/core"
1212 "github.com/microsoft/typescript-go/internal/diagnostics"
1313 "github.com/microsoft/typescript-go/internal/packagejson"
14+ "github.com/microsoft/typescript-go/internal/pnp"
1415 "github.com/microsoft/typescript-go/internal/semver"
1516 "github.com/microsoft/typescript-go/internal/tspath"
1617)
@@ -474,7 +475,7 @@ func (r *resolutionState) resolveNodeLikeWorker() *ResolvedModule {
474475 resolved := r .nodeLoadModuleByRelativeName (r .extensions , candidate , false , true )
475476 return r .createResolvedModule (
476477 resolved ,
477- resolved != nil && strings . Contains (resolved .path , "/node_modules/" ),
478+ resolved != nil && ( tspath . IsExternalLibraryImport (resolved .path ) ),
478479 )
479480 }
480481 return r .createResolvedModule (nil , false )
@@ -913,6 +914,12 @@ func (r *resolutionState) loadModuleFromNearestNodeModulesDirectory(typesScopeOn
913914}
914915
915916func (r * resolutionState ) loadModuleFromNearestNodeModulesDirectoryWorker (ext extensions , mode core.ResolutionMode , typesScopeOnly bool ) * resolved {
917+ pnpApi := pnp .GetPnpApi (r .containingDirectory )
918+ if pnpApi != nil {
919+ // !!! stop at global cache
920+ return r .loadModuleFromImmediateNodeModulesDirectoryPnP (ext , r .containingDirectory , typesScopeOnly )
921+ }
922+
916923 result , _ := tspath .ForEachAncestorDirectory (
917924 r .containingDirectory ,
918925 func (directory string ) (result * resolved , stop bool ) {
@@ -952,11 +959,52 @@ func (r *resolutionState) loadModuleFromImmediateNodeModulesDirectory(extensions
952959 return continueSearching ()
953960}
954961
962+ /*
963+ With Plug and Play, we directly resolve the path of the moduleName using the PnP API, instead of searching for it in the node_modules directory
964+
965+ See github.com/microsoft/typescript-go/internal/pnp package for more details
966+ */
967+ func (r * resolutionState ) loadModuleFromImmediateNodeModulesDirectoryPnP (extensions extensions , directory string , typesScopeOnly bool ) * resolved {
968+ if ! typesScopeOnly {
969+ if packageResult := r .loadModuleFromPnpResolution (extensions , r .name , directory ); ! packageResult .shouldContinueSearching () {
970+ return packageResult
971+ }
972+ }
973+
974+ if extensions & extensionsDeclaration != 0 {
975+ result := r .loadModuleFromPnpResolution (extensionsDeclaration , "@types/" + r .mangleScopedPackageName (r .name ), directory )
976+
977+ return result
978+ }
979+
980+ return nil
981+ }
982+
983+ func (r * resolutionState ) loadModuleFromPnpResolution (ext extensions , moduleName string , issuer string ) * resolved {
984+ pnpApi := pnp .GetPnpApi (issuer )
985+
986+ if pnpApi != nil {
987+ packageName , rest := ParsePackageName (moduleName )
988+ // TODO: bubble up yarn resolution errors, instead of _
989+ packageDirectory , _ := pnpApi .ResolveToUnqualified (packageName , issuer )
990+ if packageDirectory != "" {
991+ candidate := tspath .NormalizePath (tspath .CombinePaths (packageDirectory , rest ))
992+ return r .loadModuleFromSpecificNodeModulesDirectoryImpl (ext , true /* nodeModulesDirectoryExists */ , candidate , rest , packageDirectory )
993+ }
994+ }
995+
996+ return nil
997+ }
998+
955999func (r * resolutionState ) loadModuleFromSpecificNodeModulesDirectory (ext extensions , moduleName string , nodeModulesDirectory string , nodeModulesDirectoryExists bool ) * resolved {
9561000 candidate := tspath .NormalizePath (tspath .CombinePaths (nodeModulesDirectory , moduleName ))
9571001 packageName , rest := ParsePackageName (moduleName )
9581002 packageDirectory := tspath .CombinePaths (nodeModulesDirectory , packageName )
9591003
1004+ return r .loadModuleFromSpecificNodeModulesDirectoryImpl (ext , nodeModulesDirectoryExists , candidate , rest , packageDirectory )
1005+ }
1006+
1007+ func (r * resolutionState ) loadModuleFromSpecificNodeModulesDirectoryImpl (ext extensions , nodeModulesDirectoryExists bool , candidate string , rest string , packageDirectory string ) * resolved {
9601008 var rootPackageInfo * packagejson.InfoCacheEntry
9611009 // First look for a nested package.json, as in `node_modules/foo/bar/package.json`
9621010 packageInfo := r .getPackageJsonInfo (candidate , ! nodeModulesDirectoryExists )
@@ -1035,7 +1083,7 @@ func (r *resolutionState) loadModuleFromSpecificNodeModulesDirectory(ext extensi
10351083}
10361084
10371085func (r * resolutionState ) createResolvedModuleHandlingSymlink (resolved * resolved ) * ResolvedModule {
1038- isExternalLibraryImport := resolved != nil && strings . Contains (resolved .path , "/node_modules/" )
1086+ isExternalLibraryImport := resolved != nil && ( tspath . IsExternalLibraryImport (resolved .path ) )
10391087 if r .compilerOptions .PreserveSymlinks != core .TSTrue &&
10401088 isExternalLibraryImport &&
10411089 resolved .originalPath == "" &&
@@ -1083,7 +1131,7 @@ func (r *resolutionState) createResolvedTypeReferenceDirective(resolved *resolve
10831131 resolvedTypeReferenceDirective .ResolvedFileName = resolved .path
10841132 resolvedTypeReferenceDirective .Primary = primary
10851133 resolvedTypeReferenceDirective .PackageId = resolved .packageId
1086- resolvedTypeReferenceDirective .IsExternalLibraryImport = strings . Contains (resolved .path , "/node_modules/" )
1134+ resolvedTypeReferenceDirective .IsExternalLibraryImport = tspath . IsExternalLibraryImport (resolved .path )
10871135
10881136 if r .compilerOptions .PreserveSymlinks != core .TSTrue {
10891137 originalPath , resolvedFileName := r .getOriginalAndResolvedFileName (resolved .path )
@@ -1739,8 +1787,19 @@ func (r *resolutionState) readPackageJsonPeerDependencies(packageJsonInfo *packa
17391787 }
17401788 nodeModules := packageDirectory [:nodeModulesIndex + len ("/node_modules" )] + "/"
17411789 builder := strings.Builder {}
1790+ pnpApi := pnp .GetPnpApi (packageJsonInfo .PackageDirectory )
17421791 for name := range peerDependencies .Value {
1743- peerPackageJson := r .getPackageJsonInfo (nodeModules + name /*onlyRecordFailures*/ , false )
1792+ var peerDependencyPath string
1793+
1794+ if pnpApi != nil {
1795+ peerDependencyPath , _ = pnpApi .ResolveToUnqualified (name , packageDirectory )
1796+ }
1797+
1798+ if peerDependencyPath == "" {
1799+ peerDependencyPath = nodeModules + name
1800+ }
1801+
1802+ peerPackageJson := r .getPackageJsonInfo (peerDependencyPath , false /*onlyRecordFailures*/ )
17441803 if peerPackageJson != nil {
17451804 version := peerPackageJson .Contents .Version .Value
17461805 builder .WriteString ("+" )
0 commit comments