Skip to content

Commit 15a67ee

Browse files
sheetalkamattypescript-bot
authored andcommitted
Cherry-pick PR microsoft#50557 into release-4.8
Component commits: 0cb4514 Add test to show how scope messes with casing a3ea961 Do not canonicalize the file names when getting absolute paths Fixes microsoft#50544 dfb1e40 Unnecessary exports fc35e0a Add test for self referencing package 9076f4d Fix self reference package with casing
1 parent 45c6828 commit 15a67ee

File tree

4 files changed

+356
-3
lines changed

4 files changed

+356
-3
lines changed

src/compiler/moduleNameResolver.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -2227,7 +2227,7 @@ namespace ts {
22272227
function toAbsolutePath(path: string | undefined): string | undefined;
22282228
function toAbsolutePath(path: string | undefined): string | undefined {
22292229
if (path === undefined) return path;
2230-
return hostGetCanonicalFileName({ useCaseSensitiveFileNames })(getNormalizedAbsolutePath(path, state.host.getCurrentDirectory?.()));
2230+
return getNormalizedAbsolutePath(path, state.host.getCurrentDirectory?.());
22312231
}
22322232

22332233
function combineDirectoryPath(root: string, dir: string) {
@@ -2249,7 +2249,7 @@ namespace ts {
22492249
if ((extensions === Extensions.TypeScript || extensions === Extensions.JavaScript || extensions === Extensions.Json)
22502250
&& (state.compilerOptions.declarationDir || state.compilerOptions.outDir)
22512251
&& finalPath.indexOf("/node_modules/") === -1
2252-
&& (state.compilerOptions.configFile ? startsWith(toAbsolutePath(state.compilerOptions.configFile.fileName), scope.packageDirectory) : true)
2252+
&& (state.compilerOptions.configFile ? containsPath(scope.packageDirectory, toAbsolutePath(state.compilerOptions.configFile.fileName), !useCaseSensitiveFileNames()) : true)
22532253
) {
22542254
// So that all means we'll only try these guesses for files outside `node_modules` in a directory where the `package.json` and `tsconfig.json` are siblings.
22552255
// Even with all that, we still don't know if the root of the output file structure will be (relative to the package file)
@@ -2310,7 +2310,7 @@ namespace ts {
23102310
for (const commonSourceDirGuess of commonSourceDirGuesses) {
23112311
const candidateDirectories = getOutputDirectoriesForBaseDirectory(commonSourceDirGuess);
23122312
for (const candidateDir of candidateDirectories) {
2313-
if (startsWith(finalPath, candidateDir)) {
2313+
if (containsPath(candidateDir, finalPath, !useCaseSensitiveFileNames())) {
23142314
// The matched export is looking up something in either the out declaration or js dir, now map the written path back into the source dir and source extension
23152315
const pathFragment = finalPath.slice(candidateDir.length + 1); // +1 to also remove directory seperator
23162316
const possibleInputBase = combinePaths(commonSourceDirGuess, pathFragment);

src/testRunner/unittests/tscWatch/forceConsistentCasingInFileNames.ts

+64
Original file line numberDiff line numberDiff line change
@@ -262,5 +262,69 @@ a;b;
262262
verifyDirSymlink("when import matches disk but directory symlink target does not", `${projectRoot}/XY`, `${projectRoot}/XY`, `./Xy`);
263263
verifyDirSymlink("when import and directory symlink target agree but do not match disk", `${projectRoot}/XY`, `${projectRoot}/Xy`, `./Xy`);
264264
verifyDirSymlink("when import, directory symlink target, and disk are all different", `${projectRoot}/XY`, `${projectRoot}/Xy`, `./yX`);
265+
266+
verifyTscWatch({
267+
scenario: "forceConsistentCasingInFileNames",
268+
subScenario: "with nodeNext resolution",
269+
commandLineArgs: ["--w", "--explainFiles"],
270+
sys: () => createWatchedSystem({
271+
"/Users/name/projects/web/src/bin.ts": `import { foo } from "yargs";`,
272+
"/Users/name/projects/web/node_modules/@types/yargs/index.d.ts": "export function foo(): void;",
273+
"/Users/name/projects/web/node_modules/@types/yargs/index.d.mts": "export function foo(): void;",
274+
"/Users/name/projects/web/node_modules/@types/yargs/package.json": JSON.stringify({
275+
name: "yargs",
276+
version: "17.0.12",
277+
exports: {
278+
".": {
279+
types: {
280+
import: "./index.d.mts",
281+
default: "./index.d.ts"
282+
}
283+
},
284+
}
285+
}),
286+
"/Users/name/projects/web/tsconfig.json": JSON.stringify({
287+
compilerOptions: {
288+
moduleResolution: "nodenext",
289+
forceConsistentCasingInFileNames: true,
290+
traceResolution: true,
291+
}
292+
}),
293+
[libFile.path]: libFile.content,
294+
}, { currentDirectory: "/Users/name/projects/web" }),
295+
changes: emptyArray,
296+
});
297+
298+
verifyTscWatch({
299+
scenario: "forceConsistentCasingInFileNames",
300+
subScenario: "self name package reference",
301+
commandLineArgs: ["-w", "--explainFiles"],
302+
sys: () => createWatchedSystem({
303+
"/Users/name/projects/web/package.json": JSON.stringify({
304+
name: "@this/package",
305+
type: "module",
306+
exports: {
307+
".": "./dist/index.js"
308+
}
309+
}),
310+
"/Users/name/projects/web/index.ts": Utils.dedent`
311+
import * as me from "@this/package";
312+
me.thing();
313+
export function thing(): void {}
314+
`,
315+
"/Users/name/projects/web/tsconfig.json": JSON.stringify({
316+
compilerOptions: {
317+
module: "nodenext",
318+
outDir: "./dist",
319+
declarationDir: "./types",
320+
composite: true,
321+
forceConsistentCasingInFileNames: true,
322+
traceResolution: true,
323+
}
324+
}),
325+
"/a/lib/lib.esnext.full.d.ts": libFile.content,
326+
}, { currentDirectory: "/Users/name/projects/web" }),
327+
changes: emptyArray,
328+
});
265329
});
266330
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
Input::
2+
//// [/Users/name/projects/web/package.json]
3+
{"name":"@this/package","type":"module","exports":{".":"./dist/index.js"}}
4+
5+
//// [/Users/name/projects/web/index.ts]
6+
import * as me from "@this/package";
7+
me.thing();
8+
export function thing(): void {}
9+
10+
11+
//// [/Users/name/projects/web/tsconfig.json]
12+
{"compilerOptions":{"module":"nodenext","outDir":"./dist","declarationDir":"./types","composite":true,"forceConsistentCasingInFileNames":true,"traceResolution":true}}
13+
14+
//// [/a/lib/lib.esnext.full.d.ts]
15+
/// <reference no-default-lib="true"/>
16+
interface Boolean {}
17+
interface Function {}
18+
interface CallableFunction {}
19+
interface NewableFunction {}
20+
interface IArguments {}
21+
interface Number { toExponential: any; }
22+
interface Object {}
23+
interface RegExp {}
24+
interface String { charAt: any; }
25+
interface Array<T> { length: number; [n: number]: T; }
26+
27+
28+
/a/lib/tsc.js -w --explainFiles
29+
Output::
30+
>> Screen clear
31+
[12:00:23 AM] Starting compilation in watch mode...
32+
33+
Found 'package.json' at '/users/name/projects/web/package.json'.
34+
'package.json' does not have a 'typesVersions' field.
35+
======== Resolving module '@this/package' from '/Users/name/projects/web/index.ts'. ========
36+
Module resolution kind is not specified, using 'NodeNext'.
37+
File '/users/name/projects/web/package.json' exists according to earlier cached lookups.
38+
File '/Users/name/projects/web/index.ts' exist - use it as a name resolution result.
39+
Resolving real path for '/Users/name/projects/web/index.ts', result '/Users/name/projects/web/index.ts'.
40+
======== Module name '@this/package' was successfully resolved to '/Users/name/projects/web/index.ts'. ========
41+
File '/a/lib/package.json' does not exist.
42+
File '/a/package.json' does not exist.
43+
File '/package.json' does not exist.
44+
../../../../a/lib/lib.esnext.full.d.ts
45+
Default library for target 'esnext'
46+
index.ts
47+
Matched by default include pattern '**/*'
48+
Imported via "@this/package" from file 'index.ts'
49+
File is ECMAScript module because 'package.json' has field "type" with value "module"
50+
[12:00:36 AM] Found 0 errors. Watching for file changes.
51+
52+
53+
54+
Program root files: ["/Users/name/projects/web/index.ts"]
55+
Program options: {"module":199,"outDir":"/Users/name/projects/web/dist","declarationDir":"/Users/name/projects/web/types","composite":true,"forceConsistentCasingInFileNames":true,"traceResolution":true,"watch":true,"explainFiles":true,"configFilePath":"/Users/name/projects/web/tsconfig.json"}
56+
Program structureReused: Not
57+
Program files::
58+
/a/lib/lib.esnext.full.d.ts
59+
/Users/name/projects/web/index.ts
60+
61+
Semantic diagnostics in builder refreshed for::
62+
/a/lib/lib.esnext.full.d.ts
63+
/Users/name/projects/web/index.ts
64+
65+
Shape signatures in builder refreshed for::
66+
/a/lib/lib.esnext.full.d.ts (used version)
67+
/users/name/projects/web/index.ts (computed .d.ts during emit)
68+
69+
WatchedFiles::
70+
/users/name/projects/web/tsconfig.json:
71+
{"fileName":"/Users/name/projects/web/tsconfig.json","pollingInterval":250}
72+
/users/name/projects/web/index.ts:
73+
{"fileName":"/Users/name/projects/web/index.ts","pollingInterval":250}
74+
/a/lib/lib.esnext.full.d.ts:
75+
{"fileName":"/a/lib/lib.esnext.full.d.ts","pollingInterval":250}
76+
/users/name/projects/web/package.json:
77+
{"fileName":"/Users/name/projects/web/package.json","pollingInterval":250}
78+
/users/name/projects/web/node_modules/@types:
79+
{"fileName":"/Users/name/projects/web/node_modules/@types","pollingInterval":500}
80+
81+
FsWatches::
82+
83+
FsWatchesRecursive::
84+
/users/name/projects/web:
85+
{"directoryName":"/users/name/projects/web"}
86+
87+
exitCode:: ExitStatus.undefined
88+
89+
//// [/Users/name/projects/web/dist/index.js]
90+
import * as me from "@this/package";
91+
me.thing();
92+
export function thing() { }
93+
94+
95+
//// [/Users/name/projects/web/types/index.d.ts]
96+
export declare function thing(): void;
97+
98+
99+
//// [/Users/name/projects/web/dist/tsconfig.tsbuildinfo]
100+
{"program":{"fileNames":["../../../../../a/lib/lib.esnext.full.d.ts","../index.ts"],"fileInfos":[{"version":"-7698705165-/// <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; }","affectsGlobalScope":true,"impliedFormat":1},{"version":"14361483761-import * as me from \"@this/package\";\nme.thing();\nexport function thing(): void {}\n","signature":"-2724770439-export declare function thing(): void;\n","impliedFormat":99}],"options":{"composite":true,"declarationDir":"../types","module":199,"outDir":"./"},"fileIdsList":[[2]],"referencedMap":[[2,1]],"exportedModulesMap":[],"semanticDiagnosticsPerFile":[1,2],"latestChangedDtsFile":"../types/index.d.ts"},"version":"FakeTSVersion"}
101+
102+
//// [/Users/name/projects/web/dist/tsconfig.tsbuildinfo.readable.baseline.txt]
103+
{
104+
"program": {
105+
"fileNames": [
106+
"../../../../../a/lib/lib.esnext.full.d.ts",
107+
"../index.ts"
108+
],
109+
"fileNamesList": [
110+
[
111+
"../index.ts"
112+
]
113+
],
114+
"fileInfos": {
115+
"../../../../../a/lib/lib.esnext.full.d.ts": {
116+
"version": "-7698705165-/// <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; }",
117+
"signature": "-7698705165-/// <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; }",
118+
"affectsGlobalScope": true,
119+
"impliedFormat": "commonjs"
120+
},
121+
"../index.ts": {
122+
"version": "14361483761-import * as me from \"@this/package\";\nme.thing();\nexport function thing(): void {}\n",
123+
"signature": "-2724770439-export declare function thing(): void;\n",
124+
"impliedFormat": "esnext"
125+
}
126+
},
127+
"options": {
128+
"composite": true,
129+
"declarationDir": "../types",
130+
"module": 199,
131+
"outDir": "./"
132+
},
133+
"referencedMap": {
134+
"../index.ts": [
135+
"../index.ts"
136+
]
137+
},
138+
"exportedModulesMap": {},
139+
"semanticDiagnosticsPerFile": [
140+
"../../../../../a/lib/lib.esnext.full.d.ts",
141+
"../index.ts"
142+
],
143+
"latestChangedDtsFile": "../types/index.d.ts"
144+
},
145+
"version": "FakeTSVersion",
146+
"size": 974
147+
}
148+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
Input::
2+
//// [/Users/name/projects/web/src/bin.ts]
3+
import { foo } from "yargs";
4+
5+
//// [/Users/name/projects/web/node_modules/@types/yargs/index.d.ts]
6+
export function foo(): void;
7+
8+
//// [/Users/name/projects/web/node_modules/@types/yargs/index.d.mts]
9+
export function foo(): void;
10+
11+
//// [/Users/name/projects/web/node_modules/@types/yargs/package.json]
12+
{"name":"yargs","version":"17.0.12","exports":{".":{"types":{"import":"./index.d.mts","default":"./index.d.ts"}}}}
13+
14+
//// [/Users/name/projects/web/tsconfig.json]
15+
{"compilerOptions":{"moduleResolution":"nodenext","forceConsistentCasingInFileNames":true,"traceResolution":true}}
16+
17+
//// [/a/lib/lib.d.ts]
18+
/// <reference no-default-lib="true"/>
19+
interface Boolean {}
20+
interface Function {}
21+
interface CallableFunction {}
22+
interface NewableFunction {}
23+
interface IArguments {}
24+
interface Number { toExponential: any; }
25+
interface Object {}
26+
interface RegExp {}
27+
interface String { charAt: any; }
28+
interface Array<T> { length: number; [n: number]: T; }
29+
30+
31+
/a/lib/tsc.js --w --explainFiles
32+
Output::
33+
>> Screen clear
34+
[12:00:35 AM] Starting compilation in watch mode...
35+
36+
File '/users/name/projects/web/src/package.json' does not exist.
37+
File '/users/name/projects/web/package.json' does not exist.
38+
File '/users/name/projects/package.json' does not exist.
39+
File '/users/name/package.json' does not exist.
40+
File '/users/package.json' does not exist.
41+
File '/package.json' does not exist.
42+
======== Resolving module 'yargs' from '/Users/name/projects/web/src/bin.ts'. ========
43+
Explicitly specified module resolution kind: 'NodeNext'.
44+
File '/users/name/projects/web/src/package.json' does not exist according to earlier cached lookups.
45+
File '/users/name/projects/web/package.json' does not exist according to earlier cached lookups.
46+
File '/users/name/projects/package.json' does not exist according to earlier cached lookups.
47+
File '/users/name/package.json' does not exist according to earlier cached lookups.
48+
File '/users/package.json' does not exist according to earlier cached lookups.
49+
File '/package.json' does not exist according to earlier cached lookups.
50+
Loading module 'yargs' from 'node_modules' folder, target file type 'TypeScript'.
51+
Directory '/Users/name/projects/web/src/node_modules' does not exist, skipping all lookups in it.
52+
File '/Users/name/projects/web/node_modules/yargs.ts' does not exist.
53+
File '/Users/name/projects/web/node_modules/yargs.tsx' does not exist.
54+
File '/Users/name/projects/web/node_modules/yargs.d.ts' does not exist.
55+
Found 'package.json' at '/Users/name/projects/web/node_modules/@types/yargs/package.json'.
56+
'package.json' does not have a 'typesVersions' field.
57+
File '/Users/name/projects/web/node_modules/@types/yargs/index.d.ts' exist - use it as a name resolution result.
58+
Resolving real path for '/Users/name/projects/web/node_modules/@types/yargs/index.d.ts', result '/Users/name/projects/web/node_modules/@types/yargs/index.d.ts'.
59+
======== Module name 'yargs' was successfully resolved to '/Users/name/projects/web/node_modules/@types/yargs/index.d.ts' with Package ID 'yargs/[email protected]'. ========
60+
File '/users/name/projects/web/node_modules/@types/yargs/package.json' exists according to earlier cached lookups.
61+
======== Resolving type reference directive 'yargs', containing file '/Users/name/projects/web/__inferred type names__.ts', root directory '/Users/name/projects/web/node_modules/@types'. ========
62+
Resolving with primary search path '/Users/name/projects/web/node_modules/@types'.
63+
File '/Users/name/projects/web/node_modules/@types/yargs/package.json' exists according to earlier cached lookups.
64+
'package.json' does not have a 'typings' field.
65+
'package.json' does not have a 'types' field.
66+
File '/Users/name/projects/web/node_modules/@types/yargs/index.d.ts' exist - use it as a name resolution result.
67+
Resolving real path for '/Users/name/projects/web/node_modules/@types/yargs/index.d.ts', result '/Users/name/projects/web/node_modules/@types/yargs/index.d.ts'.
68+
======== Type reference directive 'yargs' was successfully resolved to '/Users/name/projects/web/node_modules/@types/yargs/index.d.ts' with Package ID 'yargs/[email protected]', primary: true. ========
69+
File '/a/lib/package.json' does not exist.
70+
File '/a/package.json' does not exist.
71+
File '/package.json' does not exist according to earlier cached lookups.
72+
../../../../a/lib/lib.d.ts
73+
Default library for target 'es3'
74+
node_modules/@types/yargs/index.d.ts
75+
Imported via "yargs" from file 'src/bin.ts' with packageId 'yargs/[email protected]'
76+
Entry point for implicit type library 'yargs' with packageId 'yargs/[email protected]'
77+
File is CommonJS module because 'node_modules/@types/yargs/package.json' does not have field "type"
78+
src/bin.ts
79+
Matched by default include pattern '**/*'
80+
File is CommonJS module because 'package.json' was not found
81+
[12:00:38 AM] Found 0 errors. Watching for file changes.
82+
83+
84+
85+
Program root files: ["/Users/name/projects/web/src/bin.ts"]
86+
Program options: {"moduleResolution":99,"forceConsistentCasingInFileNames":true,"traceResolution":true,"watch":true,"explainFiles":true,"configFilePath":"/Users/name/projects/web/tsconfig.json"}
87+
Program structureReused: Not
88+
Program files::
89+
/a/lib/lib.d.ts
90+
/Users/name/projects/web/node_modules/@types/yargs/index.d.ts
91+
/Users/name/projects/web/src/bin.ts
92+
93+
Semantic diagnostics in builder refreshed for::
94+
/a/lib/lib.d.ts
95+
/Users/name/projects/web/node_modules/@types/yargs/index.d.ts
96+
/Users/name/projects/web/src/bin.ts
97+
98+
Shape signatures in builder refreshed for::
99+
/a/lib/lib.d.ts (used version)
100+
/users/name/projects/web/node_modules/@types/yargs/index.d.ts (used version)
101+
/users/name/projects/web/src/bin.ts (used version)
102+
103+
WatchedFiles::
104+
/users/name/projects/web/tsconfig.json:
105+
{"fileName":"/Users/name/projects/web/tsconfig.json","pollingInterval":250}
106+
/users/name/projects/web/src/bin.ts:
107+
{"fileName":"/Users/name/projects/web/src/bin.ts","pollingInterval":250}
108+
/users/name/projects/web/node_modules/@types/yargs/index.d.ts:
109+
{"fileName":"/Users/name/projects/web/node_modules/@types/yargs/index.d.ts","pollingInterval":250}
110+
/a/lib/lib.d.ts:
111+
{"fileName":"/a/lib/lib.d.ts","pollingInterval":250}
112+
/users/name/projects/web/node_modules/@types/yargs/package.json:
113+
{"fileName":"/Users/name/projects/web/node_modules/@types/yargs/package.json","pollingInterval":250}
114+
/users/name/projects/web/src/package.json:
115+
{"fileName":"/Users/name/projects/web/src/package.json","pollingInterval":250}
116+
/users/name/projects/web/package.json:
117+
{"fileName":"/Users/name/projects/web/package.json","pollingInterval":250}
118+
/users/name/projects/package.json:
119+
{"fileName":"/Users/name/projects/package.json","pollingInterval":250}
120+
121+
FsWatches::
122+
/users/name/projects/web:
123+
{"directoryName":"/Users/name/projects/web"}
124+
125+
FsWatchesRecursive::
126+
/users/name/projects/web/src:
127+
{"directoryName":"/users/name/projects/web/src"}
128+
/users/name/projects/web/node_modules:
129+
{"directoryName":"/Users/name/projects/web/node_modules"}
130+
/users/name/projects/web/node_modules/@types:
131+
{"directoryName":"/Users/name/projects/web/node_modules/@types"}
132+
/users/name/projects/web:
133+
{"directoryName":"/users/name/projects/web"}
134+
135+
exitCode:: ExitStatus.undefined
136+
137+
//// [/Users/name/projects/web/src/bin.js]
138+
"use strict";
139+
exports.__esModule = true;
140+
141+

0 commit comments

Comments
 (0)