Skip to content

Commit 3b22339

Browse files
authored
Triple slash references must resolve against the resolved file name (.d.ts and not original source file) since they are rewritten in the .d.ts emit (#39645)
* Add tests corresponding to repro from #37928 * Triple slash references must resolve against the resolved file name (.d.ts and not original source file) since they are rewritten in the .d.ts emit * Remove the scenario not fixed in this PR
1 parent 92f41c8 commit 3b22339

File tree

6 files changed

+545
-2
lines changed

6 files changed

+545
-2
lines changed

src/compiler/checker.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37470,7 +37470,7 @@ namespace ts {
3747037470
if (fileToDirective.has(file.path)) return;
3747137471
fileToDirective.set(file.path, key);
3747237472
for (const { fileName } of file.referencedFiles) {
37473-
const resolvedFile = resolveTripleslashReference(fileName, file.originalFileName);
37473+
const resolvedFile = resolveTripleslashReference(fileName, file.fileName);
3747437474
const referencedFile = host.getSourceFile(resolvedFile);
3747537475
if (referencedFile) {
3747637476
addReferencedFilesToTypeDirective(referencedFile, key);

src/compiler/program.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2667,7 +2667,7 @@ namespace ts {
26672667
return;
26682668
}
26692669
forEach(file.referencedFiles, (ref, index) => {
2670-
const referencedFileName = resolveTripleslashReference(ref.fileName, file.originalFileName);
2670+
const referencedFileName = resolveTripleslashReference(ref.fileName, file.fileName);
26712671
processSourceFile(
26722672
referencedFileName,
26732673
isDefaultLib,

src/testRunner/tsconfig.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@
110110
"unittests/tsbuild/amdModulesWithOut.ts",
111111
"unittests/tsbuild/configFileErrors.ts",
112112
"unittests/tsbuild/containerOnlyReferenced.ts",
113+
"unittests/tsbuild/declarationEmit.ts",
113114
"unittests/tsbuild/demo.ts",
114115
"unittests/tsbuild/emitDeclarationOnly.ts",
115116
"unittests/tsbuild/emptyFiles.ts",
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
namespace ts {
2+
describe("unittests:: tsbuild:: declarationEmit", () => {
3+
function getFiles(): vfs.FileSet {
4+
return {
5+
"/src/solution/tsconfig.base.json": JSON.stringify({
6+
compilerOptions: {
7+
rootDir: "./",
8+
outDir: "lib"
9+
}
10+
}),
11+
"/src/solution/tsconfig.json": JSON.stringify({
12+
compilerOptions: { composite: true },
13+
references: [{ path: "./src" }],
14+
include: []
15+
}),
16+
"/src/solution/src/tsconfig.json": JSON.stringify({
17+
compilerOptions: { composite: true },
18+
references: [{ path: "./subProject" }, { path: "./subProject2" }],
19+
include: []
20+
}),
21+
"/src/solution/src/subProject/tsconfig.json": JSON.stringify({
22+
extends: "../../tsconfig.base.json",
23+
compilerOptions: { composite: true },
24+
references: [{ path: "../common" }],
25+
include: ["./index.ts"]
26+
}),
27+
"/src/solution/src/subProject/index.ts": Utils.dedent`
28+
import { Nominal } from '../common/nominal';
29+
export type MyNominal = Nominal<string, 'MyNominal'>;`,
30+
"/src/solution/src/subProject2/tsconfig.json": JSON.stringify({
31+
extends: "../../tsconfig.base.json",
32+
compilerOptions: { composite: true },
33+
references: [{ path: "../subProject" }],
34+
include: ["./index.ts"]
35+
}),
36+
"/src/solution/src/subProject2/index.ts": Utils.dedent`
37+
import { MyNominal } from '../subProject/index';
38+
const variable = {
39+
key: 'value' as MyNominal,
40+
};
41+
export function getVar(): keyof typeof variable {
42+
return 'key';
43+
}`,
44+
"/src/solution/src/common/tsconfig.json": JSON.stringify({
45+
extends: "../../tsconfig.base.json",
46+
compilerOptions: { composite: true },
47+
include: ["./nominal.ts"]
48+
}),
49+
"/src/solution/src/common/nominal.ts": Utils.dedent`
50+
/// <reference path="./types.d.ts" />
51+
export declare type Nominal<T, Name extends string> = MyNominal<T, Name>;`,
52+
"/src/solution/src/common/types.d.ts": Utils.dedent`
53+
declare type MyNominal<T, Name extends string> = T & {
54+
specialKey: Name;
55+
};`,
56+
};
57+
}
58+
verifyTsc({
59+
scenario: "declarationEmit",
60+
subScenario: "when declaration file is referenced through triple slash",
61+
fs: () => loadProjectFromFiles(getFiles()),
62+
commandLineArgs: ["--b", "/src/solution/tsconfig.json", "--verbose"]
63+
});
64+
65+
verifyTsc({
66+
scenario: "declarationEmit",
67+
subScenario: "when declaration file is referenced through triple slash but uses no references",
68+
fs: () => loadProjectFromFiles({
69+
...getFiles(),
70+
"/src/solution/tsconfig.json": JSON.stringify({
71+
extends: "./tsconfig.base.json",
72+
compilerOptions: { composite: true },
73+
include: ["./src/**/*.ts"]
74+
}),
75+
}),
76+
commandLineArgs: ["--b", "/src/solution/tsconfig.json", "--verbose"]
77+
});
78+
});
79+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
Input::
2+
//// [/lib/lib.d.ts]
3+
/// <reference no-default-lib="true"/>
4+
interface Boolean {}
5+
interface Function {}
6+
interface CallableFunction {}
7+
interface NewableFunction {}
8+
interface IArguments {}
9+
interface Number { toExponential: any; }
10+
interface Object {}
11+
interface RegExp {}
12+
interface String { charAt: any; }
13+
interface Array<T> { length: number; [n: number]: T; }
14+
interface ReadonlyArray<T> {}
15+
declare const console: { log(msg: any): void; };
16+
17+
//// [/src/solution/src/common/nominal.ts]
18+
/// <reference path="./types.d.ts" />
19+
export declare type Nominal<T, Name extends string> = MyNominal<T, Name>;
20+
21+
//// [/src/solution/src/common/tsconfig.json]
22+
23+
24+
//// [/src/solution/src/common/types.d.ts]
25+
declare type MyNominal<T, Name extends string> = T & {
26+
specialKey: Name;
27+
};
28+
29+
//// [/src/solution/src/subProject/index.ts]
30+
import { Nominal } from '../common/nominal';
31+
export type MyNominal = Nominal<string, 'MyNominal'>;
32+
33+
//// [/src/solution/src/subProject/tsconfig.json]
34+
35+
36+
//// [/src/solution/src/subProject2/index.ts]
37+
import { MyNominal } from '../subProject/index';
38+
const variable = {
39+
key: 'value' as MyNominal,
40+
};
41+
export function getVar(): keyof typeof variable {
42+
return 'key';
43+
}
44+
45+
//// [/src/solution/src/subProject2/tsconfig.json]
46+
47+
48+
//// [/src/solution/src/tsconfig.json]
49+
50+
51+
//// [/src/solution/tsconfig.base.json]
52+
{"compilerOptions":{"rootDir":"./","outDir":"lib"}}
53+
54+
//// [/src/solution/tsconfig.json]
55+
{"extends":"./tsconfig.base.json","compilerOptions":{"composite":true},"include":["./src/**/*.ts"]}
56+
57+
58+
59+
Output::
60+
/lib/tsc --b /src/solution/tsconfig.json --verbose
61+
[12:00:00 AM] Projects in this build:
62+
* src/solution/tsconfig.json
63+
64+
[12:00:00 AM] Project 'src/solution/tsconfig.json' is out of date because output file 'src/solution/lib/src/common/nominal.js' does not exist
65+
66+
[12:00:00 AM] Building project '/src/solution/tsconfig.json'...
67+
68+
exitCode:: ExitStatus.Success
69+
70+
71+
//// [/src/solution/lib/src/common/nominal.d.ts]
72+
/// <reference path="../../../src/common/types.d.ts" />
73+
export declare type Nominal<T, Name extends string> = MyNominal<T, Name>;
74+
75+
76+
//// [/src/solution/lib/src/common/nominal.js]
77+
"use strict";
78+
exports.__esModule = true;
79+
/// <reference path="./types.d.ts" />
80+
81+
82+
//// [/src/solution/lib/src/subProject/index.d.ts]
83+
import { Nominal } from '../common/nominal';
84+
export declare type MyNominal = Nominal<string, 'MyNominal'>;
85+
86+
87+
//// [/src/solution/lib/src/subProject/index.js]
88+
"use strict";
89+
exports.__esModule = true;
90+
91+
92+
//// [/src/solution/lib/src/subProject2/index.d.ts]
93+
declare const variable: {
94+
key: globalThis.MyNominal<string, "MyNominal">;
95+
};
96+
export declare function getVar(): keyof typeof variable;
97+
export {};
98+
99+
100+
//// [/src/solution/lib/src/subProject2/index.js]
101+
"use strict";
102+
exports.__esModule = true;
103+
exports.getVar = void 0;
104+
var variable = {
105+
key: 'value'
106+
};
107+
function getVar() {
108+
return 'key';
109+
}
110+
exports.getVar = getVar;
111+
112+
113+
//// [/src/solution/lib/tsconfig.tsbuildinfo]
114+
{
115+
"program": {
116+
"fileInfos": {
117+
"../../../lib/lib.d.ts": {
118+
"version": "3858781397-/// <reference no-default-lib=\"true\"/>\ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array<T> { length: number; [n: number]: T; }\ninterface ReadonlyArray<T> {}\ndeclare const console: { log(msg: any): void; };",
119+
"signature": "3858781397-/// <reference no-default-lib=\"true\"/>\ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array<T> { length: number; [n: number]: T; }\ninterface ReadonlyArray<T> {}\ndeclare const console: { log(msg: any): void; };",
120+
"affectsGlobalScope": true
121+
},
122+
"../src/common/types.d.ts": {
123+
"version": "23815050294-declare type MyNominal<T, Name extends string> = T & {\n specialKey: Name;\n};",
124+
"signature": "23815050294-declare type MyNominal<T, Name extends string> = T & {\n specialKey: Name;\n};",
125+
"affectsGlobalScope": true
126+
},
127+
"../src/common/nominal.ts": {
128+
"version": "4107369137-/// <reference path=\"./types.d.ts\" />\nexport declare type Nominal<T, Name extends string> = MyNominal<T, Name>;",
129+
"signature": "-18894149496-/// <reference path=\"../../../src/common/types.d.ts\" />\r\nexport declare type Nominal<T, Name extends string> = MyNominal<T, Name>;\r\n",
130+
"affectsGlobalScope": false
131+
},
132+
"../src/subproject/index.ts": {
133+
"version": "-25117049605-import { Nominal } from '../common/nominal';\nexport type MyNominal = Nominal<string, 'MyNominal'>;",
134+
"signature": "-21416888433-import { Nominal } from '../common/nominal';\r\nexport declare type MyNominal = Nominal<string, 'MyNominal'>;\r\n",
135+
"affectsGlobalScope": false
136+
},
137+
"../src/subproject2/index.ts": {
138+
"version": "2747033208-import { MyNominal } from '../subProject/index';\nconst variable = {\n key: 'value' as MyNominal,\n};\nexport function getVar(): keyof typeof variable {\n return 'key';\n}",
139+
"signature": "-448645961-declare const variable: {\r\n key: globalThis.MyNominal<string, \"MyNominal\">;\r\n};\r\nexport declare function getVar(): keyof typeof variable;\r\nexport {};\r\n",
140+
"affectsGlobalScope": false
141+
}
142+
},
143+
"options": {
144+
"rootDir": "..",
145+
"outDir": "./",
146+
"composite": true,
147+
"configFilePath": "../tsconfig.json"
148+
},
149+
"referencedMap": {
150+
"../src/common/nominal.ts": [
151+
"../src/common/types.d.ts"
152+
],
153+
"../src/subproject/index.ts": [
154+
"../src/common/nominal.ts"
155+
],
156+
"../src/subproject2/index.ts": [
157+
"../src/subproject/index.ts"
158+
]
159+
},
160+
"exportedModulesMap": {
161+
"../src/subproject/index.ts": [
162+
"../src/common/nominal.ts"
163+
]
164+
},
165+
"semanticDiagnosticsPerFile": [
166+
"../../../lib/lib.d.ts",
167+
"../src/common/nominal.ts",
168+
"../src/common/types.d.ts",
169+
"../src/subproject/index.ts",
170+
"../src/subproject2/index.ts"
171+
]
172+
},
173+
"version": "FakeTSVersion"
174+
}
175+

0 commit comments

Comments
 (0)