Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Handle more places where package direcroy is converted to canonical file path #50740

Merged
merged 2 commits into from Sep 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/compiler/checker.ts
Expand Up @@ -3629,7 +3629,7 @@ namespace ts {
if (ext === Extension.Ts || ext === Extension.Js || ext === Extension.Tsx || ext === Extension.Jsx) {
const scope = currentSourceFile.packageJsonScope;
const targetExt = ext === Extension.Ts ? Extension.Mts : ext === Extension.Js ? Extension.Mjs : undefined;
if (scope && !scope.packageJsonContent.type) {
if (scope && !scope.contents.packageJsonContent.type) {
if (targetExt) {
diagnosticDetails = chainDiagnosticMessages(
/*details*/ undefined,
Expand Down
82 changes: 43 additions & 39 deletions src/compiler/moduleNameResolver.ts

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion src/compiler/moduleSpecifiers.ts
Expand Up @@ -807,7 +807,7 @@ namespace ts.moduleSpecifiers {
let maybeBlockedByTypesVersions = false;
const cachedPackageJson = host.getPackageJsonInfoCache?.()?.getPackageJsonInfo(packageJsonPath);
if (typeof cachedPackageJson === "object" || cachedPackageJson === undefined && host.fileExists(packageJsonPath)) {
const packageJsonContent = cachedPackageJson?.packageJsonContent || JSON.parse(host.readFile!(packageJsonPath)!);
const packageJsonContent = cachedPackageJson?.contents.packageJsonContent || JSON.parse(host.readFile!(packageJsonPath)!);
const importMode = overrideMode || importingSourceFile.impliedNodeFormat;
if (getEmitModuleResolutionKind(options) === ModuleResolutionKind.Node16 || getEmitModuleResolutionKind(options) === ModuleResolutionKind.NodeNext) {
const conditions = ["node", importMode === ModuleKind.ESNext ? "import" : "require", "types"];
Expand Down
6 changes: 3 additions & 3 deletions src/compiler/program.ts
Expand Up @@ -849,7 +849,7 @@ namespace ts {

/*@internal*/
export function getImpliedNodeFormatForFileWorker(
fileName: Path,
fileName: string,
packageJsonInfoCache: PackageJsonInfoCache | undefined,
host: ModuleResolutionHost,
options: CompilerOptions,
Expand All @@ -870,7 +870,7 @@ namespace ts {
state.failedLookupLocations = packageJsonLocations;
state.affectingLocations = packageJsonLocations;
const packageJsonScope = getPackageScopeForPath(fileName, state);
const impliedNodeFormat = packageJsonScope?.packageJsonContent.type === "module" ? ModuleKind.ESNext : ModuleKind.CommonJS;
const impliedNodeFormat = packageJsonScope?.contents.packageJsonContent.type === "module" ? ModuleKind.ESNext : ModuleKind.CommonJS;
return { impliedNodeFormat, packageJsonLocations, packageJsonScope };
}
}
Expand Down Expand Up @@ -2834,7 +2834,7 @@ namespace ts {
// It's a _little odd_ that we can't set `impliedNodeFormat` until the program step - but it's the first and only time we have a resolution cache
// and a freshly made source file node on hand at the same time, and we need both to set the field. Persisting the resolution cache all the way
// to the check and emit steps would be bad - so we much prefer detecting and storing the format information on the source file node upfront.
const result = getImpliedNodeFormatForFileWorker(toPath(fileName), moduleResolutionCache?.getPackageJsonInfoCache(), host, options);
const result = getImpliedNodeFormatForFileWorker(getNormalizedAbsolutePath(fileName, currentDirectory), moduleResolutionCache?.getPackageJsonInfoCache(), host, options);
const languageVersion = getEmitScriptTarget(options);
const setExternalModuleIndicator = getSetExternalModuleIndicator(options);
return typeof result === "object" ?
Expand Down
2 changes: 1 addition & 1 deletion src/compiler/watch.ts
Expand Up @@ -262,7 +262,7 @@ namespace ts {
if (file.packageJsonScope) {
(result ??= []).push(chainDiagnosticMessages(
/*details*/ undefined,
file.packageJsonScope.packageJsonContent.type ?
file.packageJsonScope.contents.packageJsonContent.type ?
Diagnostics.File_is_CommonJS_module_because_0_has_field_type_whose_value_is_not_module :
Diagnostics.File_is_CommonJS_module_because_0_does_not_have_field_type,
toFileName(last(file.packageJsonLocations!), fileNameConvertor)
Expand Down
2 changes: 1 addition & 1 deletion src/server/session.ts
Expand Up @@ -1378,7 +1378,7 @@ namespace ts.server {
const packageDirectory = fileName.substring(0, nodeModulesPathParts.packageRootIndex);
const packageJsonCache = project.getModuleResolutionCache()?.getPackageJsonInfoCache();
const compilerOptions = project.getCompilationSettings();
const packageJson = getPackageScopeForPath(project.toPath(packageDirectory + "/package.json"), getTemporaryModuleResolutionState(packageJsonCache, project, compilerOptions));
const packageJson = getPackageScopeForPath(getNormalizedAbsolutePath(packageDirectory + "/package.json", project.getCurrentDirectory()), getTemporaryModuleResolutionState(packageJsonCache, project, compilerOptions));
if (!packageJson) return undefined;
// Use fake options instead of actual compiler options to avoid following export map if the project uses node16 or nodenext -
// Mapping from an export map entry across packages is out of scope for now. Returned entrypoints will only be what can be
Expand Down
Expand Up @@ -326,5 +326,36 @@ a;b;
}, { currentDirectory: "/Users/name/projects/web" }),
changes: emptyArray,
});


verifyTscWatch({
scenario: "forceConsistentCasingInFileNames",
subScenario: "package json is looked up for file",
commandLineArgs: ["-w", "--explainFiles"],
sys: () => createWatchedSystem({
"/Users/name/projects/lib-boilerplate/package.json": JSON.stringify({
name: "lib-boilerplate",
version: "0.0.2",
type: "module",
exports: "./src/index.ts",
}),
"/Users/name/projects/lib-boilerplate/src/index.ts": Utils.dedent`
export function thing(): void {}
`,
"/Users/name/projects/lib-boilerplate/test/basic.spec.ts": Utils.dedent`
import { thing } from 'lib-boilerplate'
`,
"/Users/name/projects/lib-boilerplate/tsconfig.json": JSON.stringify({
compilerOptions: {
module: "node16",
target: "es2021",
forceConsistentCasingInFileNames: true,
traceResolution: true,
}
}),
"/a/lib/lib.es2021.full.d.ts": libFile.content,
}, { currentDirectory: "/Users/name/projects/lib-boilerplate" }),
changes: emptyArray,
});
});
}
Expand Up @@ -25,15 +25,15 @@
"'package.json' does not have a 'typings' field.",
"'package.json' has 'types' field 'index.d.ts' that references 'tests/cases/compiler/node_modules/@types/react/index.d.ts'.",
"File 'tests/cases/compiler/node_modules/@types/react/index.d.ts' exist - use it as a name resolution result.",
"======== Module name './' was successfully resolved to 'tests/cases/compiler/node_modules/@types/react/index.d.ts' with Package ID '@types/react/index.d.ts@0.0.1'. ========",
"======== Module name './' was successfully resolved to 'tests/cases/compiler/node_modules/@types/react/index.d.ts' with Package ID '@types/react/ndex.d.ts@0.0.1'. ========",
"File 'tests/cases/compiler/node_modules/@types/react/package.json' exists according to earlier cached lookups.",
"======== Resolving module './' from 'tests/cases/compiler/node_modules/@types/react/jsx-runtime.d.ts'. ========",
"Resolution for module './' was found in cache from location 'tests/cases/compiler/node_modules/@types/react'.",
"======== Module name './' was successfully resolved to 'tests/cases/compiler/node_modules/@types/react/index.d.ts' with Package ID '@types/react/index.d.ts@0.0.1'. ========",
"======== Module name './' was successfully resolved to 'tests/cases/compiler/node_modules/@types/react/index.d.ts' with Package ID '@types/react/ndex.d.ts@0.0.1'. ========",
"File 'tests/cases/compiler/node_modules/@types/react/package.json' exists according to earlier cached lookups.",
"======== Resolving module './' from 'tests/cases/compiler/node_modules/@types/react/jsx-dev-runtime.d.ts'. ========",
"Resolution for module './' was found in cache from location 'tests/cases/compiler/node_modules/@types/react'.",
"======== Module name './' was successfully resolved to 'tests/cases/compiler/node_modules/@types/react/index.d.ts' with Package ID '@types/react/index.d.ts@0.0.1'. ========",
"======== Module name './' was successfully resolved to 'tests/cases/compiler/node_modules/@types/react/index.d.ts' with Package ID '@types/react/ndex.d.ts@0.0.1'. ========",
"File 'package.json' does not exist.",
"File '/package.json' does not exist according to earlier cached lookups.",
"File 'package.json' does not exist according to earlier cached lookups.",
Expand Down
Expand Up @@ -19,15 +19,15 @@
"'package.json' does not have a 'typings' field.",
"'package.json' has 'types' field 'index.d.ts' that references 'tests/cases/compiler/node_modules/@types/react/index.d.ts'.",
"File 'tests/cases/compiler/node_modules/@types/react/index.d.ts' exist - use it as a name resolution result.",
"======== Module name './' was successfully resolved to 'tests/cases/compiler/node_modules/@types/react/index.d.ts' with Package ID '@types/react/index.d.ts@0.0.1'. ========",
"======== Module name './' was successfully resolved to 'tests/cases/compiler/node_modules/@types/react/index.d.ts' with Package ID '@types/react/ndex.d.ts@0.0.1'. ========",
"File 'tests/cases/compiler/node_modules/@types/react/package.json' exists according to earlier cached lookups.",
"======== Resolving module './' from 'tests/cases/compiler/node_modules/@types/react/jsx-runtime.d.ts'. ========",
"Resolution for module './' was found in cache from location 'tests/cases/compiler/node_modules/@types/react'.",
"======== Module name './' was successfully resolved to 'tests/cases/compiler/node_modules/@types/react/index.d.ts' with Package ID '@types/react/index.d.ts@0.0.1'. ========",
"======== Module name './' was successfully resolved to 'tests/cases/compiler/node_modules/@types/react/index.d.ts' with Package ID '@types/react/ndex.d.ts@0.0.1'. ========",
"File 'tests/cases/compiler/node_modules/@types/react/package.json' exists according to earlier cached lookups.",
"======== Resolving module './' from 'tests/cases/compiler/node_modules/@types/react/jsx-dev-runtime.d.ts'. ========",
"Resolution for module './' was found in cache from location 'tests/cases/compiler/node_modules/@types/react'.",
"======== Module name './' was successfully resolved to 'tests/cases/compiler/node_modules/@types/react/index.d.ts' with Package ID '@types/react/index.d.ts@0.0.1'. ========",
"======== Module name './' was successfully resolved to 'tests/cases/compiler/node_modules/@types/react/index.d.ts' with Package ID '@types/react/ndex.d.ts@0.0.1'. ========",
"File 'package.json' does not exist.",
"File '/package.json' does not exist.",
"File 'package.json' does not exist according to earlier cached lookups.",
Expand Down
@@ -0,0 +1,116 @@
Input::
//// [/Users/name/projects/lib-boilerplate/package.json]
{"name":"lib-boilerplate","version":"0.0.2","type":"module","exports":"./src/index.ts"}

//// [/Users/name/projects/lib-boilerplate/src/index.ts]
export function thing(): void {}


//// [/Users/name/projects/lib-boilerplate/test/basic.spec.ts]
import { thing } from 'lib-boilerplate'


//// [/Users/name/projects/lib-boilerplate/tsconfig.json]
{"compilerOptions":{"module":"node16","target":"es2021","forceConsistentCasingInFileNames":true,"traceResolution":true}}

//// [/a/lib/lib.es2021.full.d.ts]
/// <reference no-default-lib="true"/>
interface Boolean {}
interface Function {}
interface CallableFunction {}
interface NewableFunction {}
interface IArguments {}
interface Number { toExponential: any; }
interface Object {}
interface RegExp {}
interface String { charAt: any; }
interface Array<T> { length: number; [n: number]: T; }


/a/lib/tsc.js -w --explainFiles
Output::
>> Screen clear
[12:00:29 AM] Starting compilation in watch mode...

File '/Users/name/projects/lib-boilerplate/src/package.json' does not exist.
Found 'package.json' at '/Users/name/projects/lib-boilerplate/package.json'.
'package.json' does not have a 'typesVersions' field.
File '/Users/name/projects/lib-boilerplate/test/package.json' does not exist.
File '/Users/name/projects/lib-boilerplate/package.json' exists according to earlier cached lookups.
======== Resolving module 'lib-boilerplate' from '/Users/name/projects/lib-boilerplate/test/basic.spec.ts'. ========
Module resolution kind is not specified, using 'Node16'.
File '/Users/name/projects/lib-boilerplate/test/package.json' does not exist according to earlier cached lookups.
File '/Users/name/projects/lib-boilerplate/package.json' exists according to earlier cached lookups.
File '/Users/name/projects/lib-boilerplate/src/index.ts' exist - use it as a name resolution result.
Resolving real path for '/Users/name/projects/lib-boilerplate/src/index.ts', result '/Users/name/projects/lib-boilerplate/src/index.ts'.
======== Module name 'lib-boilerplate' was successfully resolved to '/Users/name/projects/lib-boilerplate/src/index.ts' with Package ID 'lib-boilerplate/src/index.ts@0.0.2'. ========
File '/a/lib/package.json' does not exist.
File '/a/package.json' does not exist.
File '/package.json' does not exist.
../../../../a/lib/lib.es2021.full.d.ts
Default library for target 'es2021'
src/index.ts
Matched by default include pattern '**/*'
Imported via 'lib-boilerplate' from file 'test/basic.spec.ts' with packageId 'lib-boilerplate/src/index.ts@0.0.2'
File is ECMAScript module because 'package.json' has field "type" with value "module"
test/basic.spec.ts
Matched by default include pattern '**/*'
File is ECMAScript module because 'package.json' has field "type" with value "module"
[12:00:34 AM] Found 0 errors. Watching for file changes.



Program root files: ["/Users/name/projects/lib-boilerplate/src/index.ts","/Users/name/projects/lib-boilerplate/test/basic.spec.ts"]
Program options: {"module":100,"target":8,"forceConsistentCasingInFileNames":true,"traceResolution":true,"watch":true,"explainFiles":true,"configFilePath":"/Users/name/projects/lib-boilerplate/tsconfig.json"}
Program structureReused: Not
Program files::
/a/lib/lib.es2021.full.d.ts
/Users/name/projects/lib-boilerplate/src/index.ts
/Users/name/projects/lib-boilerplate/test/basic.spec.ts

Semantic diagnostics in builder refreshed for::
/a/lib/lib.es2021.full.d.ts
/Users/name/projects/lib-boilerplate/src/index.ts
/Users/name/projects/lib-boilerplate/test/basic.spec.ts

Shape signatures in builder refreshed for::
/a/lib/lib.es2021.full.d.ts (used version)
/users/name/projects/lib-boilerplate/src/index.ts (used version)
/users/name/projects/lib-boilerplate/test/basic.spec.ts (used version)

PolledWatches::
/users/name/projects/lib-boilerplate/src/package.json:
{"pollingInterval":2000}
/users/name/projects/lib-boilerplate/test/package.json:
{"pollingInterval":2000}
/users/name/projects/lib-boilerplate/node_modules/@types:
{"pollingInterval":500}

FsWatches::
/users/name/projects/lib-boilerplate/tsconfig.json:
{}
/users/name/projects/lib-boilerplate/src/index.ts:
{}
/users/name/projects/lib-boilerplate/test/basic.spec.ts:
{}
/a/lib/lib.es2021.full.d.ts:
{}
/users/name/projects/lib-boilerplate/package.json:
{}

FsWatchesRecursive::
/users/name/projects/lib-boilerplate/test:
{}
/users/name/projects/lib-boilerplate:
{}

exitCode:: ExitStatus.undefined

//// [/Users/name/projects/lib-boilerplate/src/index.js]
export function thing() { }


//// [/Users/name/projects/lib-boilerplate/test/basic.spec.js]
export {};


Expand Up @@ -30,11 +30,11 @@ Output::
>> Screen clear
[12:00:23 AM] Starting compilation in watch mode...

Found 'package.json' at '/users/name/projects/web/package.json'.
Found 'package.json' at '/Users/name/projects/web/package.json'.
'package.json' does not have a 'typesVersions' field.
======== Resolving module '@this/package' from '/Users/name/projects/web/index.ts'. ========
Module resolution kind is not specified, using 'NodeNext'.
File '/users/name/projects/web/package.json' exists according to earlier cached lookups.
File '/Users/name/projects/web/package.json' exists according to earlier cached lookups.
File '/Users/name/projects/web/index.ts' exist - use it as a name resolution result.
Resolving real path for '/Users/name/projects/web/index.ts', result '/Users/name/projects/web/index.ts'.
======== Module name '@this/package' was successfully resolved to '/Users/name/projects/web/index.ts'. ========
Expand Down