11namespace ts . projectSystem {
2+ interface SetupHostOutput {
3+ host : TestServerHost ;
4+ openFiles : readonly File [ ] ;
5+ config : File ;
6+ }
7+
8+ function setupHostWithSavedResolutions < T extends SetupHostOutput > ( setupHost : ( ) => T ) : T {
9+ const result = setupHost ( ) ;
10+ const exit = result . host . exit ;
11+ result . host . exit = noop ;
12+ fakes . withTemporaryPatchingForBuildinfoReadWrite ( result . host , sys => executeCommandLine ( sys , noop , [ "--b" , result . config . path ] ) ) ;
13+ result . host . clearOutput ( ) ;
14+ result . host . exit = exit ;
15+ return result ;
16+ }
17+
18+ function setupHostWithClearedResolutions < T extends SetupHostOutput > ( setupHost : ( ) => T ) : T {
19+ const result = setupHost ( ) ;
20+ const exit = result . host . exit ;
21+ result . host . exit = noop ;
22+ fakes . withTemporaryPatchingForBuildinfoReadWrite ( result . host , sys => {
23+ executeCommandLine ( sys , noop , [ "--b" , result . config . path ] ) ;
24+ executeCommandLine ( sys , noop , [ "--b" , result . config . path , "--cleanPersistedProgram" ] ) ;
25+ } ) ;
26+ result . host . clearOutput ( ) ;
27+ result . host . exit = exit ;
28+ return result ;
29+ }
30+
31+ function setup < T extends SetupHostOutput > ( { host, openFiles, config } : T ) {
32+ fakes . patchHostForBuildInfoReadWrite ( host ) ;
33+ const session = createSession ( host , { logger : createLoggerWithInMemoryLogs ( ) } ) ;
34+ openFilesForSession ( openFiles , session ) ;
35+ const project = session . getProjectService ( ) . configuredProjects . get ( config . path ) ! ;
36+ return { session, project } ;
37+ }
38+
39+ function persistResolutions ( file : File ) {
40+ const content = JSON . parse ( file . content ) ;
41+ content . compilerOptions = {
42+ ...content . compilerOptions || { } ,
43+ persistResolutions : false ,
44+ traceResolution : true ,
45+ } ;
46+ file . content = JSON . stringify ( content , /*replacer*/ undefined , 4 ) ;
47+ return file ;
48+ }
49+
250 describe ( "unittests:: tsserver:: persistResolutions" , ( ) => {
351 function setupHost ( ) {
452 const { main, anotherFileReusingResolution, filePresent, fileWithRef, types, globalMain, globalAnotherFileWithSameReferenes, globalFilePresent, externalThing, someType, config } = tscWatch . PersistentResolutionsTests . getFiles ( ) ;
553 const host = createServerHost (
654 [ main , anotherFileReusingResolution , filePresent , fileWithRef , types , globalMain , globalAnotherFileWithSameReferenes , globalFilePresent , externalThing , someType , config , libFile ] ,
755 { currentDirectory : tscWatch . projectRoot , useCaseSensitiveFileNames : true }
856 ) ;
9- return { host, main, globalMain, config } ;
10- }
11-
12- function setupHostWithSavedResolutions ( ) {
13- const result = setupHost ( ) ;
14- const exit = result . host . exit ;
15- result . host . exit = noop ;
16- fakes . withTemporaryPatchingForBuildinfoReadWrite ( result . host , sys => executeCommandLine ( sys , noop , [ "--p" , "." ] ) ) ;
17- result . host . exit = exit ;
18- result . host . clearOutput ( ) ;
19- return result ;
20- }
21-
22- function setupHostWithClearedResolutions ( ) {
23- const result = setupHost ( ) ;
24- const exit = result . host . exit ;
25- result . host . exit = noop ;
26- fakes . withTemporaryPatchingForBuildinfoReadWrite ( result . host , sys => {
27- executeCommandLine ( sys , noop , [ "--p" , "." ] ) ;
28- executeCommandLine ( sys , noop , [ "--p" , "." , "--cleanPersistedProgram" ] ) ;
29- } ) ;
30- result . host . exit = exit ;
31- result . host . clearOutput ( ) ;
32- return result ;
33- }
34-
35- function setup ( { host, main, globalMain, config } : ReturnType < typeof setupHost > ) {
36- fakes . patchHostForBuildInfoReadWrite ( host ) ;
37- const session = createSession ( host , { logger : createLoggerWithInMemoryLogs ( ) } ) ;
38- openFilesForSession ( [ main , globalMain ] , session ) ;
39- const project = session . getProjectService ( ) . configuredProjects . get ( config . path ) ! ;
40- return { session, project } ;
57+ return { host, main, globalMain, config, openFiles : [ main , globalMain ] } ;
4158 }
4259
4360 function modifyGlobalMain ( session : TestSession , project : server . ConfiguredProject , globalMain : File ) {
@@ -190,7 +207,7 @@ namespace ts.projectSystem {
190207 }
191208
192209 it ( "uses saved resolution for program" , ( ) => {
193- const result = setupHostWithSavedResolutions ( ) ;
210+ const result = setupHostWithSavedResolutions ( setupHost ) ;
194211 const { project, session } = setup ( result ) ;
195212 const { host, main, globalMain } = result ;
196213 appendProjectFileText ( project , session ) ;
@@ -236,7 +253,7 @@ namespace ts.projectSystem {
236253 } ) ;
237254
238255 it ( "creates new resolutions for program if tsbuildinfo is present but program is not persisted" , ( ) => {
239- const result = setupHostWithClearedResolutions ( ) ;
256+ const result = setupHostWithClearedResolutions ( setupHost ) ;
240257 const { project, session } = setup ( result ) ;
241258 const { host, main, globalMain } = result ;
242259 appendProjectFileText ( project , session ) ;
@@ -258,4 +275,117 @@ namespace ts.projectSystem {
258275 baselineTsserverLogs ( "persistResolutions" , "creates new resolutions for program if tsbuildinfo is present but program is not persisted" , session ) ;
259276 } ) ;
260277 } ) ;
278+
279+ describe ( "unittests:: tsserver:: persistResolutions on sample project" , ( ) => {
280+ function setupHost ( ) {
281+ const coreConfig = persistResolutions ( TestFSWithWatch . getTsBuildProjectFile ( "sample1" , "core/tsconfig.json" ) ) ;
282+ const coreIndex = TestFSWithWatch . getTsBuildProjectFile ( "sample1" , "core/index.ts" ) ;
283+ const coreAnotherModule = TestFSWithWatch . getTsBuildProjectFile ( "sample1" , "core/anotherModule.ts" ) ;
284+ const coreSomeDecl = TestFSWithWatch . getTsBuildProjectFile ( "sample1" , "core/some_decl.d.ts" ) ;
285+ const logicConfig = persistResolutions ( TestFSWithWatch . getTsBuildProjectFile ( "sample1" , "logic/tsconfig.json" ) ) ;
286+ const logicIndex = TestFSWithWatch . getTsBuildProjectFile ( "sample1" , "logic/index.ts" ) ;
287+ const testsConfig = persistResolutions ( TestFSWithWatch . getTsBuildProjectFile ( "sample1" , "tests/tsconfig.json" ) ) ;
288+ const testsIndex = TestFSWithWatch . getTsBuildProjectFile ( "sample1" , "tests/index.ts" ) ;
289+ const host = createServerHost ( [ libFile , coreConfig , coreIndex , coreAnotherModule , coreSomeDecl , logicConfig , logicIndex , testsConfig , testsIndex ] ) ;
290+ return { host, config : testsConfig , openFiles : [ testsIndex ] } ;
291+ }
292+
293+
294+ it ( "uses saved resolution for program" , ( ) => {
295+ const result = setupHostWithSavedResolutions ( setupHost ) ;
296+ const { project, session } = setup ( result ) ;
297+ appendProjectFileText ( project , session ) ;
298+ baselineTsserverLogs ( "persistResolutions" , "uses saved resolution for program with sample project" , session ) ;
299+ } ) ;
300+
301+ it ( "creates new resolutions for program if tsbuildinfo is not present" , ( ) => {
302+ const result = setupHost ( ) ;
303+ const { project, session } = setup ( result ) ;
304+ appendProjectFileText ( project , session ) ;
305+ baselineTsserverLogs ( "persistResolutions" , "creates new resolutions for program if tsbuildinfo is not present with sample project" , session ) ;
306+ } ) ;
307+
308+ it ( "creates new resolutions for program if tsbuildinfo is present but program is not persisted" , ( ) => {
309+ const result = setupHostWithClearedResolutions ( setupHost ) ;
310+ const { project, session } = setup ( result ) ;
311+ appendProjectFileText ( project , session ) ;
312+ baselineTsserverLogs ( "persistResolutions" , "creates new resolutions for program if tsbuildinfo is present but program is not persisted with sample project" , session ) ;
313+ } ) ;
314+ } ) ;
315+
316+ describe ( "unittests:: tsserver:: persistResolutions on project where d.ts file contains fewer modules than original file" , ( ) => {
317+ function setupHost ( ) {
318+ const coreConfig : File = {
319+ path : `${ tscWatch . projectRoot } /core/tsconfig.json` ,
320+ content : JSON . stringify ( { compilerOptions : { composite : true , persistResolutions : false , traceResolution : true } } )
321+ } ;
322+ const coreIndex : File = {
323+ path : `${ tscWatch . projectRoot } /core/index.ts` ,
324+ content : `export function bar() { return 10; }`
325+ } ;
326+ const coreMyClass : File = {
327+ path : `${ tscWatch . projectRoot } /core/myClass.ts` ,
328+ content : `export class myClass { }`
329+ } ;
330+ const coreAnotherClass : File = {
331+ path : `${ tscWatch . projectRoot } /core/anotherClass.ts` ,
332+ content : `export class anotherClass { }`
333+ } ;
334+ const logicConfig : File = {
335+ path : `${ tscWatch . projectRoot } /logic/tsconfig.json` ,
336+ content : JSON . stringify ( {
337+ compilerOptions : { composite : true , persistResolutions : false , traceResolution : true } ,
338+ references : [ { path : "../core" } ]
339+ } )
340+ } ;
341+ const logicIndex : File = {
342+ path : `${ tscWatch . projectRoot } /logic/index.ts` ,
343+ content : `import { myClass } from "../core/myClass";
344+ import { bar } from "../core";
345+ import { anotherClass } from "../core/anotherClass";
346+ export function returnMyClass() {
347+ bar();
348+ return new myClass();
349+ }
350+ export function returnAnotherClass() {
351+ return new anotherClass();
352+ }`
353+ } ;
354+ const testsConfig : File = {
355+ path : `${ tscWatch . projectRoot } /tests/tsconfig.json` ,
356+ content : JSON . stringify ( {
357+ compilerOptions : { composite : true , persistResolutions : false , traceResolution : true } ,
358+ references : [ { path : "../logic" } ]
359+ } )
360+ } ;
361+ const testsIndex : File = {
362+ path : `${ tscWatch . projectRoot } /tests/index.ts` ,
363+ content : `import { returnMyClass } from "../logic";
364+ returnMyClass();`
365+ } ;
366+ const host = createServerHost ( [ libFile , coreConfig , coreIndex , coreMyClass , coreAnotherClass , logicConfig , logicIndex , testsConfig , testsIndex ] ) ;
367+ return { host, config : testsConfig , openFiles : [ testsIndex ] } ;
368+ }
369+
370+ it ( "uses saved resolution for program" , ( ) => {
371+ const result = setupHostWithSavedResolutions ( setupHost ) ;
372+ const { project, session } = setup ( result ) ;
373+ appendProjectFileText ( project , session ) ;
374+ baselineTsserverLogs ( "persistResolutions" , "uses saved resolution for program with project where dts file contains fewer modules than original file" , session ) ;
375+ } ) ;
376+
377+ it ( "creates new resolutions for program if tsbuildinfo is not present" , ( ) => {
378+ const result = setupHost ( ) ;
379+ const { project, session } = setup ( result ) ;
380+ appendProjectFileText ( project , session ) ;
381+ baselineTsserverLogs ( "persistResolutions" , "creates new resolutions for program if tsbuildinfo is not present with project where dts file contains fewer modules than original file" , session ) ;
382+ } ) ;
383+
384+ it ( "creates new resolutions for program if tsbuildinfo is present but program is not persisted" , ( ) => {
385+ const result = setupHostWithClearedResolutions ( setupHost ) ;
386+ const { project, session } = setup ( result ) ;
387+ appendProjectFileText ( project , session ) ;
388+ baselineTsserverLogs ( "persistResolutions" , "creates new resolutions for program if tsbuildinfo is present but program is not persisted with project where dts file contains fewer modules than original file" , session ) ;
389+ } ) ;
390+ } ) ;
261391}
0 commit comments