@@ -793,6 +793,92 @@ namespace ts {
793
793
}
794
794
} ) ;
795
795
796
+ it ( "can reuse module resolutions within project references" , ( ) => {
797
+ const commonOptions = {
798
+ composite : true ,
799
+ declaration : true ,
800
+ target : ScriptTarget . ES2015 ,
801
+ traceResolution : true ,
802
+ moduleResolution : ModuleResolutionKind . Classic ,
803
+ } ;
804
+ const tsconfigA = {
805
+ compilerOptions : commonOptions ,
806
+ include : [ "src" ]
807
+ } ;
808
+ const tsconfigB = {
809
+ compilerOptions : {
810
+ ...commonOptions ,
811
+ paths : {
812
+ a : [ "/a/src/index.ts" ]
813
+ }
814
+ } ,
815
+ projectReferences : [
816
+ { path : "/a" }
817
+ ]
818
+ } ;
819
+
820
+ const files = [
821
+ { name : "/a/src/x.ts" , text : SourceText . New ( "" , "export const x = 1;" , "" ) } ,
822
+ { name : "/a/src/index.ts" , text : SourceText . New ( "" , "export { x } from './x';" , "" ) } ,
823
+ { name : "/a/tsconfig.json" , text : SourceText . New ( "" , "" , JSON . stringify ( tsconfigA ) ) } ,
824
+ { name : "/b/src/b.ts" , text : SourceText . New ( "" , "import { x } from 'a';" , "" ) } ,
825
+ ] ;
826
+ const rootNamesA = [ "/a/src/index.ts" , "/a/src/x.ts" ] ;
827
+ const rootNamesB = [ "/b/src/b.ts" ] ;
828
+
829
+ const host = createTestCompilerHost ( files , commonOptions . target ) ;
830
+
831
+ // Instead of hard-coding file system entries for this test, we could also write a function that more
832
+ // generally transforms a list of files into a tree of FileSystemEntries.
833
+ function getFileSystemEntries ( path : string ) {
834
+ const mapPathToFileSystemEntries : { [ path : string ] : FileSystemEntries | undefined } = {
835
+ "/a" : { files : [ ] , directories : [ "src" ] } ,
836
+ "/a/src" : { files : [ "index.ts" , "x.ts" ] , directories : [ ] }
837
+ } ;
838
+
839
+ const entries = mapPathToFileSystemEntries [ path ] ;
840
+ if ( ! entries ) {
841
+ throw new Error ( `Unexpected path "${ path } " requested from readDirectory. Test is broken.` ) ;
842
+ }
843
+ return entries ;
844
+ }
845
+
846
+ host . readDirectory = ( rootDir , extensions , excludes , includes , depth ) =>
847
+ matchFiles (
848
+ rootDir ,
849
+ extensions ,
850
+ excludes ,
851
+ includes ,
852
+ /*useCaseSensitiveFileNames*/ true ,
853
+ /*currentDirectory*/ "/" ,
854
+ depth ,
855
+ getFileSystemEntries ,
856
+ /*realpath*/ path => path ) ;
857
+
858
+ createProgram ( rootNamesA , tsconfigA . compilerOptions , host ) ;
859
+ createProgram ( {
860
+ rootNames : rootNamesB ,
861
+ options : tsconfigB . compilerOptions ,
862
+ host,
863
+ projectReferences : tsconfigB . projectReferences
864
+ } ) ;
865
+
866
+ // Resolution should not be performed for "./x" from "/a/src/index.ts" multiple times.
867
+ assert . deepEqual ( host . getTrace ( ) , [
868
+ "======== Resolving module './x' from '/a/src/index.ts'. ========" ,
869
+ "Explicitly specified module resolution kind: 'Classic'." ,
870
+ "File '/a/src/x.ts' exist - use it as a name resolution result." ,
871
+ "======== Module name './x' was successfully resolved to '/a/src/x.ts'. ========" ,
872
+ "======== Resolving module 'a' from '/b/src/b.ts'. ========" ,
873
+ "Explicitly specified module resolution kind: 'Classic'." ,
874
+ "'paths' option is specified, looking for a pattern to match module name 'a'." ,
875
+ "Module name 'a', matched pattern 'a'." ,
876
+ "Trying substitution '/a/src/index.ts', candidate module location: '/a/src/index.ts'." ,
877
+ "File '/a/src/index.ts' exist - use it as a name resolution result." ,
878
+ "======== Module name 'a' was successfully resolved to '/a/src/index.ts'. ========" ,
879
+ ] , "should reuse resolution to /a/src/x.ts" ) ;
880
+ } ) ;
881
+
796
882
describe ( "redirects" , ( ) => {
797
883
const axIndex = "/node_modules/a/node_modules/x/index.d.ts" ;
798
884
const axPackage = "/node_modules/a/node_modules/x/package.json" ;
0 commit comments