Skip to content

Commit b631850

Browse files
committed
Add option disableSourceOfProjectReferenceRedirect to disable using sources of project reference redirect from editor
1 parent 824c22c commit b631850

File tree

13 files changed

+112
-53
lines changed

13 files changed

+112
-53
lines changed

src/compiler/commandLineParser.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -751,6 +751,12 @@ namespace ts {
751751
category: Diagnostics.Advanced_Options,
752752
description: Diagnostics.Disable_size_limitations_on_JavaScript_projects
753753
},
754+
{
755+
name: "disableSourceOfProjectReferenceRedirect",
756+
type: "boolean",
757+
category: Diagnostics.Advanced_Options,
758+
description: Diagnostics.Disable_using_source_of_project_reference_redirect_files
759+
},
754760
{
755761
name: "noImplicitUseStrict",
756762
type: "boolean",

src/compiler/diagnosticMessages.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3967,6 +3967,10 @@
39673967
"category": "Message",
39683968
"code": 6220
39693969
},
3970+
"Disable using source of project reference redirect files.": {
3971+
"category": "Message",
3972+
"code": 6221
3973+
},
39703974

39713975
"Projects to reference": {
39723976
"category": "Message",

src/compiler/program.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -814,7 +814,7 @@ namespace ts {
814814
let projectReferenceRedirects: Map<ResolvedProjectReference | false> | undefined;
815815
let mapFromFileToProjectReferenceRedirects: Map<Path> | undefined;
816816
let mapFromToProjectReferenceRedirectSource: Map<SourceOfProjectReferenceRedirect> | undefined;
817-
const useSourceOfReference = !!host.useSourceInsteadOfReferenceRedirect && host.useSourceInsteadOfReferenceRedirect();
817+
const useSourceOfProjectReferenceRedirect = !!host.useSourceOfProjectReferenceRedirect && host.useSourceOfProjectReferenceRedirect();
818818

819819
const shouldCreateNewSourceFile = shouldProgramCreateNewSourceFiles(oldProgram, options);
820820
const structuralIsReused = tryReuseStructureFromOldProgram();
@@ -836,7 +836,7 @@ namespace ts {
836836
for (const parsedRef of resolvedProjectReferences) {
837837
if (!parsedRef) continue;
838838
const out = parsedRef.commandLine.options.outFile || parsedRef.commandLine.options.out;
839-
if (useSourceOfReference) {
839+
if (useSourceOfProjectReferenceRedirect) {
840840
if (out || getEmitModuleKind(parsedRef.commandLine.options) === ModuleKind.None) {
841841
for (const fileName of parsedRef.commandLine.fileNames) {
842842
processSourceFile(fileName, /*isDefaultLib*/ false, /*ignoreNoDefaultLib*/ false, /*packageId*/ undefined);
@@ -1418,7 +1418,7 @@ namespace ts {
14181418
for (const newSourceFile of newSourceFiles) {
14191419
const filePath = newSourceFile.path;
14201420
addFileToFilesByName(newSourceFile, filePath, newSourceFile.resolvedPath);
1421-
if (useSourceOfReference) {
1421+
if (useSourceOfProjectReferenceRedirect) {
14221422
const redirectProject = getProjectReferenceRedirectProject(newSourceFile.fileName);
14231423
if (redirectProject && !(redirectProject.commandLine.options.outFile || redirectProject.commandLine.options.out)) {
14241424
const redirect = getProjectReferenceOutputName(redirectProject, newSourceFile.fileName);
@@ -2252,7 +2252,7 @@ namespace ts {
22522252

22532253
// Get source file from normalized fileName
22542254
function findSourceFile(fileName: string, path: Path, isDefaultLib: boolean, ignoreNoDefaultLib: boolean, refFile: SourceFile, refPos: number, refEnd: number, packageId: PackageId | undefined): SourceFile | undefined {
2255-
if (useSourceOfReference) {
2255+
if (useSourceOfProjectReferenceRedirect) {
22562256
const source = getSourceOfProjectReferenceRedirect(fileName);
22572257
if (source) {
22582258
const file = isString(source) ?
@@ -2309,7 +2309,7 @@ namespace ts {
23092309
}
23102310

23112311
let redirectedPath: Path | undefined;
2312-
if (refFile && !useSourceOfReference) {
2312+
if (refFile && !useSourceOfProjectReferenceRedirect) {
23132313
const redirectProject = getProjectReferenceRedirectProject(fileName);
23142314
if (redirectProject) {
23152315
if (redirectProject.commandLine.options.outFile || redirectProject.commandLine.options.out) {
@@ -2498,7 +2498,7 @@ namespace ts {
24982498
}
24992499

25002500
function isSourceOfProjectReferenceRedirect(fileName: string) {
2501-
return useSourceOfReference && !!getResolvedProjectReferenceToRedirect(fileName);
2501+
return useSourceOfProjectReferenceRedirect && !!getResolvedProjectReferenceToRedirect(fileName);
25022502
}
25032503

25042504
function forEachProjectReference<T>(

src/compiler/types.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4645,6 +4645,7 @@ namespace ts {
46454645
/* @internal */ diagnostics?: boolean;
46464646
/* @internal */ extendedDiagnostics?: boolean;
46474647
disableSizeLimit?: boolean;
4648+
disableSourceOfProjectReferenceRedirect?: boolean;
46484649
downlevelIteration?: boolean;
46494650
emitBOM?: boolean;
46504651
emitDecoratorMetadata?: boolean;
@@ -5169,7 +5170,7 @@ namespace ts {
51695170
createHash?(data: string): string;
51705171
getParsedCommandLine?(fileName: string): ParsedCommandLine | undefined;
51715172
/* @internal */ setResolvedProjectReferenceCallbacks?(callbacks: ResolvedProjectReferenceCallbacks): void;
5172-
/* @internal */ useSourceInsteadOfReferenceRedirect?(): boolean;
5173+
/* @internal */ useSourceOfProjectReferenceRedirect?(): boolean;
51735174

51745175
// TODO: later handle this in better way in builder host instead once the api for tsbuild finalizes and doesn't use compilerHost as base
51755176
/*@internal*/createDirectory?(directory: string): void;

src/server/editorServices.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2583,7 +2583,7 @@ namespace ts.server {
25832583
if (!configFileName) return undefined;
25842584

25852585
const configuredProject = this.findConfiguredProjectByProjectName(configFileName) ||
2586-
this.createAndLoadConfiguredProject(configFileName, `Creating project for original file: ${originalFileInfo.fileName}${location !== originalLocation ? " for location " + location.fileName : ""}`);
2586+
this.createAndLoadConfiguredProject(configFileName, `Creating project for original file: ${originalFileInfo.fileName}${location !== originalLocation ? " for location: " + location.fileName : ""}`);
25872587
if (configuredProject === project) return originalLocation;
25882588
updateProjectIfDirty(configuredProject);
25892589
// Keep this configured project as referenced from project

src/server/project.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1540,11 +1540,12 @@ namespace ts.server {
15401540
}
15411541

15421542
/* @internal */
1543-
useSourceInsteadOfReferenceRedirect = () => !!this.languageServiceEnabled;
1543+
useSourceOfProjectReferenceRedirect = () => !!this.languageServiceEnabled &&
1544+
!this.getCompilerOptions().disableSourceOfProjectReferenceRedirect;
15441545

15451546
fileExists(file: string): boolean {
15461547
// Project references go to source file instead of .d.ts file
1547-
if (this.useSourceInsteadOfReferenceRedirect() && this.projectReferenceCallbacks) {
1548+
if (this.useSourceOfProjectReferenceRedirect() && this.projectReferenceCallbacks) {
15481549
const source = this.projectReferenceCallbacks.getSourceOfProjectReferenceRedirect(file);
15491550
if (source) return isString(source) ? super.fileExists(source) : true;
15501551
}
@@ -1553,7 +1554,7 @@ namespace ts.server {
15531554

15541555
directoryExists(path: string): boolean {
15551556
if (super.directoryExists(path)) return true;
1556-
if (!this.useSourceInsteadOfReferenceRedirect() || !this.projectReferenceCallbacks) return false;
1557+
if (!this.useSourceOfProjectReferenceRedirect() || !this.projectReferenceCallbacks) return false;
15571558

15581559
if (!this.mapOfDeclarationDirectories) {
15591560
this.mapOfDeclarationDirectories = createMap();

src/services/services.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1248,8 +1248,8 @@ namespace ts {
12481248
if (host.setResolvedProjectReferenceCallbacks) {
12491249
compilerHost.setResolvedProjectReferenceCallbacks = callbacks => host.setResolvedProjectReferenceCallbacks!(callbacks);
12501250
}
1251-
if (host.useSourceInsteadOfReferenceRedirect) {
1252-
compilerHost.useSourceInsteadOfReferenceRedirect = () => host.useSourceInsteadOfReferenceRedirect!();
1251+
if (host.useSourceOfProjectReferenceRedirect) {
1252+
compilerHost.useSourceOfProjectReferenceRedirect = () => host.useSourceOfProjectReferenceRedirect!();
12531253
}
12541254

12551255
const documentRegistryBucketKey = documentRegistry.getKeyForCompilationSettings(newSettings);

src/services/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -239,7 +239,7 @@ namespace ts {
239239
/* @internal */
240240
setResolvedProjectReferenceCallbacks?(callbacks: ResolvedProjectReferenceCallbacks): void;
241241
/* @internal */
242-
useSourceInsteadOfReferenceRedirect?(): boolean;
242+
useSourceOfProjectReferenceRedirect?(): boolean;
243243
}
244244

245245
/* @internal */

src/testRunner/unittests/tsserver/events/projectLoading.ts

Lines changed: 54 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -73,44 +73,64 @@ namespace ts.projectSystem {
7373
verifyEvent(project, `Change in config file detected`);
7474
});
7575

76-
it("when opening original location project", () => {
77-
const aDTs: File = {
78-
path: `${projectRoot}/a/a.d.ts`,
79-
content: `export declare class A {
76+
describe("when opening original location project", () => {
77+
it("with project references", () => {
78+
verify();
79+
});
80+
81+
it("when disableSourceOfProjectReferenceRedirect is true", () => {
82+
verify(/*disableSourceOfProjectReferenceRedirect*/ true);
83+
});
84+
85+
function verify(disableSourceOfProjectReferenceRedirect?: true) {
86+
const aDTs: File = {
87+
path: `${projectRoot}/a/a.d.ts`,
88+
content: `export declare class A {
8089
}
8190
//# sourceMappingURL=a.d.ts.map
8291
`
83-
};
84-
const aDTsMap: File = {
85-
path: `${projectRoot}/a/a.d.ts.map`,
86-
content: `{"version":3,"file":"a.d.ts","sourceRoot":"","sources":["./a.ts"],"names":[],"mappings":"AAAA,qBAAa,CAAC;CAAI"}`
87-
};
88-
const bTs: File = {
89-
path: bTsPath,
90-
content: `import {A} from "../a/a"; new A();`
91-
};
92-
const configB: File = {
93-
path: configBPath,
94-
content: JSON.stringify({
95-
references: [{ path: "../a" }]
96-
})
97-
};
98-
99-
const { service, session, verifyEventWithOpenTs, verifyEvent } = createSessionToVerifyEvent(files.concat(aDTs, aDTsMap, bTs, configB));
100-
verifyEventWithOpenTs(bTs, configB.path, 1);
101-
102-
session.executeCommandSeq<protocol.ReferencesRequest>({
103-
command: protocol.CommandTypes.References,
104-
arguments: {
105-
file: bTs.path,
106-
...protocolLocationFromSubstring(bTs.content, "A()")
107-
}
108-
});
92+
};
93+
const aDTsMap: File = {
94+
path: `${projectRoot}/a/a.d.ts.map`,
95+
content: `{"version":3,"file":"a.d.ts","sourceRoot":"","sources":["./a.ts"],"names":[],"mappings":"AAAA,qBAAa,CAAC;CAAI"}`
96+
};
97+
const bTs: File = {
98+
path: bTsPath,
99+
content: `import {A} from "../a/a"; new A();`
100+
};
101+
const configB: File = {
102+
path: configBPath,
103+
content: JSON.stringify({
104+
...(disableSourceOfProjectReferenceRedirect && {
105+
compilerOptions: {
106+
disableSourceOfProjectReferenceRedirect
107+
}
108+
}),
109+
references: [{ path: "../a" }]
110+
})
111+
};
112+
113+
const { service, session, verifyEventWithOpenTs, verifyEvent } = createSessionToVerifyEvent(files.concat(aDTs, aDTsMap, bTs, configB));
114+
verifyEventWithOpenTs(bTs, configB.path, 1);
115+
116+
session.executeCommandSeq<protocol.ReferencesRequest>({
117+
command: protocol.CommandTypes.References,
118+
arguments: {
119+
file: bTs.path,
120+
...protocolLocationFromSubstring(bTs.content, "A()")
121+
}
122+
});
109123

110-
checkNumberOfProjects(service, { configuredProjects: 2 });
111-
const project = service.configuredProjects.get(configA.path)!;
112-
assert.isDefined(project);
113-
verifyEvent(project, `Creating project for original file: ${aTs.path}`);
124+
checkNumberOfProjects(service, { configuredProjects: 2 });
125+
const project = service.configuredProjects.get(configA.path)!;
126+
assert.isDefined(project);
127+
verifyEvent(
128+
project,
129+
disableSourceOfProjectReferenceRedirect ?
130+
`Creating project for original file: ${aTs.path} for location: ${aDTs.path}` :
131+
`Creating project for original file: ${aTs.path}`
132+
);
133+
}
114134
});
115135

116136
describe("with external projects and config files ", () => {

src/testRunner/unittests/tsserver/projectReferences.ts

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -417,6 +417,7 @@ fn5();
417417

418418
interface VerifierAndWithRefs {
419419
withRefs: boolean;
420+
disableSourceOfProjectReferenceRedirect?: true;
420421
verifier: (withRefs: boolean) => readonly DocumentPositionMapperVerifier[];
421422
}
422423

@@ -426,19 +427,30 @@ fn5();
426427
interface OpenTsFile extends VerifierAndWithRefs {
427428
onHostCreate?: (host: TestServerHost) => void;
428429
}
429-
function openTsFile({ withRefs, verifier, onHostCreate }: OpenTsFile) {
430+
function openTsFile({ withRefs, disableSourceOfProjectReferenceRedirect, verifier, onHostCreate }: OpenTsFile) {
430431
const host = createHost(files, [mainConfig.path]);
431432
if (!withRefs) {
432433
// Erase project reference
433434
host.writeFile(mainConfig.path, JSON.stringify({
434435
compilerOptions: { composite: true, declarationMap: true }
435436
}));
436437
}
438+
else if (disableSourceOfProjectReferenceRedirect) {
439+
// Erase project reference
440+
host.writeFile(mainConfig.path, JSON.stringify({
441+
compilerOptions: {
442+
composite: true,
443+
declarationMap: true,
444+
disableSourceOfProjectReferenceRedirect: !!disableSourceOfProjectReferenceRedirect
445+
},
446+
references: [{ path: "../dependency" }]
447+
}));
448+
}
437449
if (onHostCreate) {
438450
onHostCreate(host);
439451
}
440452
const session = createSession(host);
441-
const verifiers = verifier(withRefs);
453+
const verifiers = verifier(withRefs && !disableSourceOfProjectReferenceRedirect);
442454
openFilesForSession([...openFiles(verifiers), randomFile], session);
443455
return { host, session, verifiers };
444456
}
@@ -786,9 +798,9 @@ fn5();
786798
});
787799
}
788800

789-
function verifyScenarioWorker({ mainScenario, verifier }: VerifyScenario, withRefs: boolean) {
801+
function verifyScenarioWorker({ mainScenario, verifier }: VerifyScenario, withRefs: boolean, disableSourceOfProjectReferenceRedirect?: true) {
790802
it(mainScenario, () => {
791-
const { host, session, verifiers } = openTsFile({ withRefs, verifier });
803+
const { host, session, verifiers } = openTsFile({ withRefs, disableSourceOfProjectReferenceRedirect, verifier });
792804
checkProject(session, verifiers);
793805
verifyScenarioAndScriptInfoCollection(session, host, verifiers, "main");
794806
});
@@ -798,6 +810,7 @@ fn5();
798810
scenarioName: "when usage file changes, document position mapper doesnt change",
799811
verifier,
800812
withRefs,
813+
disableSourceOfProjectReferenceRedirect,
801814
change: (_host, session, verifiers) => verifiers.forEach(
802815
verifier => session.executeCommandSeq<protocol.ChangeRequest>({
803816
command: protocol.CommandTypes.Change,
@@ -819,6 +832,7 @@ fn5();
819832
scenarioName: "when dependency .d.ts changes, document position mapper doesnt change",
820833
verifier,
821834
withRefs,
835+
disableSourceOfProjectReferenceRedirect,
822836
change: host => host.writeFile(
823837
dtsLocation,
824838
host.readFile(dtsLocation)!.replace(
@@ -835,6 +849,7 @@ fn5();
835849
scenarioName: "when dependency file's map changes",
836850
verifier,
837851
withRefs,
852+
disableSourceOfProjectReferenceRedirect,
838853
change: host => host.writeFile(
839854
dtsMapLocation,
840855
`{"version":3,"file":"FnS.d.ts","sourceRoot":"","sources":["../dependency/FnS.ts"],"names":[],"mappings":"AAAA,wBAAgB,GAAG,SAAM;AACzB,wBAAgB,GAAG,SAAM;AACzB,wBAAgB,GAAG,SAAM;AACzB,wBAAgB,GAAG,SAAM;AACzB,wBAAgB,GAAG,SAAM;AACzB,eAAO,MAAM,CAAC,KAAK,CAAC"}`
@@ -846,6 +861,7 @@ fn5();
846861
scenarioName: "with depedency files map file",
847862
verifier,
848863
withRefs,
864+
disableSourceOfProjectReferenceRedirect,
849865
fileLocation: dtsMapLocation,
850866
fileNotPresentKey: "noMap",
851867
fileCreatedKey: "mapFileCreated",
@@ -856,14 +872,15 @@ fn5();
856872
scenarioName: "with depedency .d.ts file",
857873
verifier,
858874
withRefs,
875+
disableSourceOfProjectReferenceRedirect,
859876
fileLocation: dtsLocation,
860877
fileNotPresentKey: "noDts",
861878
fileCreatedKey: "dtsFileCreated",
862879
fileDeletedKey: "dtsFileDeleted",
863880
noDts: true
864881
});
865882

866-
if (withRefs) {
883+
if (withRefs && !disableSourceOfProjectReferenceRedirect) {
867884
verifyScenarioWithChanges({
868885
scenarioName: "when defining project source changes",
869886
verifier,
@@ -907,6 +924,9 @@ ${dependencyTs.content}`);
907924
describe("when main tsconfig has project reference", () => {
908925
verifyScenarioWorker(scenario, /*withRefs*/ true);
909926
});
927+
describe("when main tsconfig has but has disableSourceOfProjectReferenceRedirect", () => {
928+
verifyScenarioWorker(scenario, /*withRefs*/ true);
929+
});
910930
}
911931

912932
describe("from project that uses dependency", () => {

0 commit comments

Comments
 (0)