Skip to content

Commit 3e4da7f

Browse files
committed
Test cases for shared resolutions and effective type roots calculation
1 parent 0de256f commit 3e4da7f

File tree

30 files changed

+16792
-292
lines changed

30 files changed

+16792
-292
lines changed

src/testRunner/unittests/helpers/resolutionCache.ts

Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { emptyArray } from "../../_namespaces/ts.js";
22
import { dedent } from "../../_namespaces/Utils.js";
33
import { jsonToReadableText } from "../helpers.js";
4+
import { compilerOptionsToConfigJson } from "./contents.js";
45
import { forEachPackageJsonScopeScenario } from "./packageJsonScope.js";
56
import { solutionBuildWithBaseline } from "./solutionBuilder.js";
67
import { TscWatchCompileChange } from "./tscWatch.js";
@@ -452,3 +453,153 @@ export function forEachResolutionCacheLifeTimeScenario(
452453
);
453454
});
454455
}
456+
457+
export function forEachModuleCacheScenario(
458+
forTsserver: boolean,
459+
action: (scenario: string, sys: () => TestServerHost) => void,
460+
): void {
461+
[
462+
{
463+
scenario: "sharing across references",
464+
},
465+
{
466+
scenario: "not sharing across references",
467+
appExtraOptions: { typeRoots: emptyArray },
468+
},
469+
{
470+
scenario: "across references with typeRoots",
471+
commonExtraOptions: { typeRoots: emptyArray },
472+
appExtraOptions: { typeRoots: emptyArray },
473+
},
474+
{
475+
scenario: "across references with individual @types",
476+
moduleZ: true,
477+
},
478+
].forEach(({ scenario, commonExtraOptions, appExtraOptions, moduleZ }) =>
479+
action(scenario, () =>
480+
TestServerHost.getCreateWatchedSystem(forTsserver)({
481+
"/home/src/workspaces/project/node_modules/moduleX/index.d.ts": "export const x = 10;",
482+
"/home/src/workspaces/project/common/tsconfig.json": jsonToReadableText({
483+
compilerOptions: compilerOptionsToConfigJson({
484+
composite: true,
485+
traceResolution: true,
486+
...commonExtraOptions,
487+
}),
488+
}),
489+
"/home/src/workspaces/project/common/moduleA.ts": "export const a = 10;",
490+
"/home/src/workspaces/project/common/moduleB.ts": dedent`
491+
import { x } from "moduleX";
492+
export const b = x;
493+
`,
494+
"/home/src/workspaces/project/app/tsconfig.json": jsonToReadableText({
495+
compilerOptions: compilerOptionsToConfigJson({
496+
composite: true,
497+
traceResolution: true,
498+
...appExtraOptions,
499+
}),
500+
references: [{ path: "../common" }],
501+
}),
502+
"/home/src/workspaces/project/app/appA.ts": dedent`
503+
import { x } from "moduleX";
504+
export const y = x;
505+
`,
506+
"/home/src/workspaces/project/app/appB.ts": dedent`
507+
import { b } from "../common/moduleB";
508+
export const y = b;
509+
`,
510+
...(moduleZ ? {
511+
"/home/src/workspaces/project/common/node_modules/@types/moduleZ/index.d.ts": "export const mz = 10;",
512+
"/home/src/workspaces/project/app/node_modules/@types/moduleZ/index.d.ts": "export const mz = 10;",
513+
} : {}),
514+
}))
515+
);
516+
}
517+
518+
export function forEachTypeReferenceResolutionScenario(
519+
forTsserver: boolean,
520+
action: (scenario: string, sys: () => TestServerHost, edits: () => readonly TscWatchCompileChange[]) => void,
521+
): void {
522+
[undefined, ["responselike"]].forEach(
523+
types =>
524+
[
525+
{
526+
scenario: "typeRef resolutions with typeRoots unspecified",
527+
},
528+
{
529+
scenario: "typeRef resolutions with typeRoots",
530+
tsRequireOptions: { typeRoots: emptyArray },
531+
tsOptions: { typeRoots: emptyArray },
532+
},
533+
{
534+
scenario: "typeRef resolutions only one with typeRoots",
535+
tsRequireOptions: { typeRoots: emptyArray },
536+
},
537+
{
538+
scenario: "typeRef resolutions with common @types",
539+
commonAtTypes: true,
540+
},
541+
].forEach(
542+
({ scenario, tsRequireOptions, tsOptions, commonAtTypes }) =>
543+
action(
544+
`${scenario}${types ? " with types" : ""}`,
545+
() =>
546+
TestServerHost.getCreateWatchedSystem(forTsserver)({
547+
"/home/src/workspaces/project/test/module/ts-require/tsconfig.json": jsonToReadableText({
548+
compilerOptions: compilerOptionsToConfigJson({
549+
incremental: true,
550+
traceResolution: true,
551+
...tsRequireOptions,
552+
types,
553+
}),
554+
}),
555+
"/home/src/workspaces/project/test/module/ts-require/index.ts": "export const tsRequireIndex= 10;",
556+
"/home/src/workspaces/project/test/module/ts-require/main.ts": "export const tsRequireMain= 10;",
557+
"/home/src/workspaces/project/node_modules/@types/responselike/index.d.ts": dedent`
558+
/// <reference types="node" />
559+
export const z = 10;
560+
`,
561+
"/home/src/workspaces/project/test/module/ts/tsconfig.json": jsonToReadableText({
562+
compilerOptions: compilerOptionsToConfigJson({
563+
incremental: true,
564+
traceResolution: true,
565+
...tsOptions,
566+
types,
567+
}),
568+
}),
569+
"/home/src/workspaces/project/test/module/ts/index.ts": "export const tsIndex= 10;",
570+
"/home/src/workspaces/project/test/module/ts/main.ts": "export const tsMain = 10;",
571+
...(
572+
commonAtTypes ?
573+
{
574+
"/home/src/workspaces/project/test/node_modules/@types/node/index.d.ts": "declare const tsRequireGlobal = 10;",
575+
} :
576+
{
577+
"/home/src/workspaces/project/test/module/ts-require/node_modules/@types/node/index.d.ts": "declare const tsRequireGlobal = 10;",
578+
"/home/src/workspaces/project/test/module/ts/node_modules/@types/node/index.d.ts": "declare const tsRequireGlobal = 10;",
579+
}
580+
),
581+
}),
582+
() => [
583+
{
584+
caption: "build ts project with edit",
585+
edit: sys => sys.appendFile("/home/src/workspaces/project/test/module/ts/main.ts", `export const z = 10;`),
586+
timeouts: sys => {
587+
sys.runQueuedTimeoutCallbacks();
588+
sys.runQueuedTimeoutCallbacks();
589+
sys.runQueuedTimeoutCallbacks();
590+
},
591+
},
592+
{
593+
caption: "build ts-require project with edit",
594+
edit: sys => sys.appendFile("/home/src/workspaces/project/test/module/ts-require/main.ts", `export const z = 10;`),
595+
timeouts: sys => {
596+
sys.runQueuedTimeoutCallbacks();
597+
sys.runQueuedTimeoutCallbacks();
598+
sys.runQueuedTimeoutCallbacks();
599+
},
600+
},
601+
],
602+
),
603+
),
604+
);
605+
}

src/testRunner/unittests/tsbuild/moduleResolution.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
import * as ts from "../../_namespaces/ts.js";
22
import { dedent } from "../../_namespaces/Utils.js";
33
import { jsonToReadableText } from "../helpers.js";
4+
import {
5+
forEachModuleCacheScenario,
6+
forEachTypeReferenceResolutionScenario,
7+
} from "../helpers/resolutionCache.js";
48
import {
59
noChangeOnlyRuns,
610
verifyTsc,
@@ -189,3 +193,24 @@ describe("unittests:: tsbuild:: moduleResolution:: resolution sharing", () => {
189193
}],
190194
});
191195
});
196+
197+
describe("unittests:: tsbuild:: moduleResolution:: reusing type reference directives", () => {
198+
forEachTypeReferenceResolutionScenario(/*forTsserver*/ false, (subScenario, sys, edits) =>
199+
verifyTsc({
200+
scenario: "moduleResolution",
201+
subScenario,
202+
sys,
203+
commandLineArgs: ["-b", "test/module/ts-require", "test/module/ts", "--verbose", "--explainFiles"],
204+
edits: edits(),
205+
}));
206+
});
207+
208+
describe("unittests:: tsbuild:: moduleResolution:: sharing resolutions across references", () => {
209+
forEachModuleCacheScenario(/*forTsserver*/ false, (subScenario, sys) =>
210+
verifyTsc({
211+
scenario: "moduleResolution",
212+
subScenario,
213+
sys,
214+
commandLineArgs: ["-b", "app", "--verbose", "--traceResolution"],
215+
}));
216+
});

src/testRunner/unittests/tsserver/resolutionCache.ts

Lines changed: 77 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
import * as ts from "../../_namespaces/ts.js";
22
import { dedent } from "../../_namespaces/Utils.js";
33
import { jsonToReadableText } from "../helpers.js";
4+
import { getPathForTypeScriptTypingInstallerCacheTest } from "../helpers/contents.js";
45
import {
5-
compilerOptionsToConfigJson,
6-
getPathForTypeScriptTypingInstallerCacheTest,
7-
} from "../helpers/contents.js";
8-
import {
6+
forEachModuleCacheScenario,
97
forEachResolutionCacheLifeTimeScenario,
8+
forEachTypeReferenceResolutionScenario,
109
ResolutionCacheLifeTimeScenarios,
1110
} from "../helpers/resolutionCache.js";
1211
import {
@@ -627,72 +626,12 @@ export const x = 10;`,
627626
});
628627

629628
describe("unittests:: tsserver:: resolutionCache:: tsserverProjectSystem with project references", () => {
630-
it("sharing across references", () => {
631-
const host = TestServerHost.createServerHost({
632-
"/users/username/projects/node_modules/moduleX/index.d.ts": "export const x = 10;",
633-
"/users/username/projects/common/tsconfig.json": jsonToReadableText({
634-
compilerOptions: compilerOptionsToConfigJson({
635-
composite: true,
636-
traceResolution: true,
637-
}),
638-
}),
639-
"/users/username/projects/common/moduleA.ts": "export const a = 10;",
640-
"/users/username/projects/common/moduleB.ts": dedent`
641-
import { x } from "moduleX";
642-
export const b = x;
643-
`,
644-
"/users/username/projects/app/tsconfig.json": jsonToReadableText({
645-
compilerOptions: compilerOptionsToConfigJson({
646-
composite: true,
647-
traceResolution: true,
648-
}),
649-
references: [{ path: "../common" }],
650-
}),
651-
"/users/username/projects/app/appA.ts": dedent`
652-
import { x } from "moduleX";
653-
export const y = x;
654-
`,
655-
"/users/username/projects/app/appB.ts": dedent`
656-
import { x } from "../common/moduleB";
657-
export const y = x;
658-
`,
629+
forEachModuleCacheScenario(/*forTsserver*/ true, (scenario, getHost) => {
630+
it(scenario, () => {
631+
const session = new TestSession(getHost());
632+
openFilesForSession(["/home/src/workspaces/project/app/appB.ts"], session);
633+
baselineTsserverLogs("resolutionCache", scenario, session);
659634
});
660-
const session = new TestSession(host);
661-
openFilesForSession(["/users/username/projects/app/appB.ts"], session);
662-
baselineTsserverLogs("resolutionCache", "sharing across references", session);
663-
});
664-
665-
it("not sharing across references", () => {
666-
const host = TestServerHost.createServerHost({
667-
"/users/username/projects/node_modules/moduleX/index.d.ts": "export const x = 10;",
668-
"/users/username/projects/common/tsconfig.json": jsonToReadableText({
669-
compilerOptions: { composite: true, traceResolution: true },
670-
}),
671-
"/users/username/projects/common/moduleA.ts": "export const a = 10;",
672-
"/users/username/projects/common/moduleB.ts": dedent`
673-
import { x } from "moduleX";
674-
export const b = x;
675-
`,
676-
"/users/username/projects/app/tsconfig.json": jsonToReadableText({
677-
compilerOptions: {
678-
composite: true,
679-
traceResolution: true,
680-
typeRoots: [], // Just some sample option that is different across the projects
681-
},
682-
references: [{ path: "../common" }],
683-
}),
684-
"/users/username/projects/app/appA.ts": dedent`
685-
import { x } from "moduleX";
686-
export const y = x;
687-
`,
688-
"/users/username/projects/app/appB.ts": dedent`
689-
import { x } from "../common/moduleB";
690-
export const y = x;
691-
`,
692-
});
693-
const session = new TestSession(host);
694-
openFilesForSession(["/users/username/projects/app/appB.ts"], session);
695-
baselineTsserverLogs("resolutionCache", "not sharing across references", session);
696635
});
697636
});
698637

@@ -783,3 +722,72 @@ describe("unittests:: tsserver:: resolutionCache:: resolution lifetime", () => {
783722
}),
784723
);
785724
});
725+
726+
describe("unittests:: tsserver:: resolutionCache:: effective typeRoots", () => {
727+
it("effective type roots affect type reference directives", () => {
728+
const host = TestServerHost.createServerHost({
729+
"/users/username/projects/replay/axios-src/test/module/ts-require/index.js": dedent`
730+
export const a = 10;
731+
732+
`,
733+
"/users/username/projects/replay/axios-src/test/module/ts-require/node_modules/@types/node/index.d.ts": dedent`
734+
export const x = 10;
735+
`,
736+
"/users/username/projects/replay/axios-src/node_modules/@types/responselike/index.d.ts": dedent`
737+
/// <reference types="node" />
738+
export const z = 10;
739+
`,
740+
"/users/username/projects/replay/axios-src/test/module/ts/index.js": dedent`
741+
export const y = 10;
742+
`,
743+
"/users/username/projects/replay/axios-src/test/module/ts/node_modules/@types/node/index.d.ts": dedent`
744+
export const x = 10;
745+
`,
746+
});
747+
const session = new TestSession({ host, disableAutomaticTypingAcquisition: true });
748+
session.executeCommandSeq<ts.server.protocol.SetCompilerOptionsForInferredProjectsRequest>({
749+
command: ts.server.protocol.CommandTypes.CompilerOptionsForInferredProjects,
750+
arguments: {
751+
options: { traceResolution: true },
752+
},
753+
});
754+
// This will add responselike/index.d.ts and resolve the type ref "node" to "test/module/ts-require/node_modules/@types/node/index.d.ts" because of current directory
755+
openFilesForSession(["/users/username/projects/replay/axios-src/test/module/ts-require/index.js"], session);
756+
session.executeCommandSeq<ts.server.protocol.UpdateOpenRequest>({ // Schedule update
757+
command: ts.server.protocol.CommandTypes.UpdateOpen,
758+
arguments: {
759+
changedFiles: [{
760+
fileName: "/users/username/projects/replay/axios-src/test/module/ts-require/index.js",
761+
textChanges: [{
762+
newText: "//comment",
763+
start: { line: 2, offset: 1 },
764+
end: { line: 2, offset: 1 },
765+
}],
766+
}],
767+
},
768+
});
769+
// This will also use responselike/index.d.ts and needs to resolve node to "test/module/ts/node_modules/@types/node/index.d.ts" because of current directory
770+
openFilesForSession(["/users/username/projects/replay/axios-src/test/module/ts/index.js"], session);
771+
// Should not change any resolutions in inferredProject1
772+
session.executeCommandSeq<ts.server.protocol.NavtoRequest>({
773+
command: ts.server.protocol.CommandTypes.Navto,
774+
arguments: {
775+
searchValue: "a",
776+
maxResultCount: 256,
777+
},
778+
});
779+
baselineTsserverLogs("resolutionCache", "effective type roots affect type reference directives", session);
780+
});
781+
782+
forEachTypeReferenceResolutionScenario(/*forTsserver*/ true, (scenario, getHost, edits) => {
783+
it(scenario, () => {
784+
const session = new TestSession(getHost());
785+
openFilesForSession([
786+
"/home/src/workspaces/project/test/module/ts-require/index.ts",
787+
"/home/src/workspaces/project/test/module/ts/index.ts",
788+
], session);
789+
forEachTscWatchEdit(session, edits(), ts.noop);
790+
baselineTsserverLogs("resolutionCache", scenario, session);
791+
});
792+
});
793+
});

0 commit comments

Comments
 (0)