diff --git a/src/compiler/program.ts b/src/compiler/program.ts
index 70ea81c35d5..da9fe1b2ba9 100644
--- a/src/compiler/program.ts
+++ b/src/compiler/program.ts
@@ -989,22 +989,60 @@ namespace ts {
return program;
- function resolveModuleNamesWorker(moduleNames: string[], containingFile: string, reusedNames?: string[], redirectedReference?: ResolvedProjectReference) {
+ function resolveModuleNamesWorker(moduleNames: string[], containingFile: SourceFile, reusedNames: string[] | undefined): readonly ResolvedModuleFull[] {
+ if (!moduleNames.length) return emptyArray;
+ const containingFileName = getNormalizedAbsolutePath(containingFile.originalFileName, currentDirectory);
+ const redirectedReference = getRedirectReferenceForResolution(containingFile);
performance.mark("beforeResolveModule");
- const result = actualResolveModuleNamesWorker(moduleNames, containingFile, reusedNames, redirectedReference);
+ const result = actualResolveModuleNamesWorker(moduleNames, containingFileName, reusedNames, redirectedReference);
performance.mark("afterResolveModule");
performance.measure("ResolveModule", "beforeResolveModule", "afterResolveModule");
return result;
}
- function resolveTypeReferenceDirectiveNamesWorker(typeDirectiveNames: string[], containingFile: string, redirectedReference?: ResolvedProjectReference) {
+ function resolveTypeReferenceDirectiveNamesWorker(typeDirectiveNames: string[], containingFile: string | SourceFile): readonly (ResolvedTypeReferenceDirective | undefined)[] {
+ if (!typeDirectiveNames.length) return [];
performance.mark("beforeResolveTypeReference");
- const result = actualResolveTypeReferenceDirectiveNamesWorker(typeDirectiveNames, containingFile, redirectedReference);
+ const containingFileName = !isString(containingFile) ? getNormalizedAbsolutePath(containingFile.originalFileName, currentDirectory) : containingFile;
+ const redirectedReference = !isString(containingFile) ? getRedirectReferenceForResolution(containingFile) : undefined;
+ const result = actualResolveTypeReferenceDirectiveNamesWorker(typeDirectiveNames, containingFileName, redirectedReference);
performance.mark("afterResolveTypeReference");
performance.measure("ResolveTypeReference", "beforeResolveTypeReference", "afterResolveTypeReference");
return result;
}
+ function getRedirectReferenceForResolution(file: SourceFile) {
+ const redirect = getResolvedProjectReferenceToRedirect(file.originalFileName);
+ if (redirect || !fileExtensionIs(file.originalFileName, Extension.Dts)) return redirect;
+
+ // The originalFileName could not be actual source file name if file found was d.ts from referecned project
+ // So in this case try to look up if this is output from referenced project, if it is use the redirected project in that case
+ const resultFromDts = getRedirectReferenceForResolutionFromSourceOfProject(file.originalFileName, file.path);
+ if (resultFromDts) return resultFromDts;
+
+ // If preserveSymlinks is true, module resolution wont jump the symlink
+ // but the resolved real path may be the .d.ts from project reference
+ // Note:: Currently we try the real path only if the
+ // file is from node_modules to avoid having to run real path on all file paths
+ if (!host.realpath || !options.preserveSymlinks || !stringContains(file.originalFileName, nodeModulesPathPart)) return undefined;
+ const realDeclarationFileName = host.realpath(file.originalFileName);
+ const realDeclarationPath = toPath(realDeclarationFileName);
+ return realDeclarationPath === file.path ? undefined : getRedirectReferenceForResolutionFromSourceOfProject(realDeclarationFileName, realDeclarationPath);
+ }
+
+ function getRedirectReferenceForResolutionFromSourceOfProject(fileName: string, filePath: Path) {
+ const source = getSourceOfProjectReferenceRedirect(fileName);
+ if (isString(source)) return getResolvedProjectReferenceToRedirect(source);
+ if (!source) return undefined;
+ // Output of .d.ts file so return resolved ref that matches the out file name
+ return forEachResolvedProjectReference(resolvedRef => {
+ if (!resolvedRef) return undefined;
+ const out = outFile(resolvedRef.commandLine.options);
+ if (!out) return undefined;
+ return toPath(out) === filePath ? resolvedRef : undefined;
+ });
+ }
+
function compareDefaultLibFiles(a: SourceFile, b: SourceFile) {
return compareValues(getDefaultLibFilePriority(a), getDefaultLibFilePriority(b));
}
@@ -1068,14 +1106,14 @@ namespace ts {
return classifiableNames;
}
- function resolveModuleNamesReusingOldState(moduleNames: string[], containingFile: string, file: SourceFile) {
+ function resolveModuleNamesReusingOldState(moduleNames: string[], file: SourceFile): readonly ResolvedModuleFull[] {
if (structuralIsReused === StructureIsReused.Not && !file.ambientModuleNames.length) {
// If the old program state does not permit reusing resolutions and `file` does not contain locally defined ambient modules,
// the best we can do is fallback to the default logic.
- return resolveModuleNamesWorker(moduleNames, containingFile, /*reusedNames*/ undefined, getResolvedProjectReferenceToRedirect(file.originalFileName));
+ return resolveModuleNamesWorker(moduleNames, file, /*reusedNames*/ undefined);
}
- const oldSourceFile = oldProgram && oldProgram.getSourceFile(containingFile);
+ const oldSourceFile = oldProgram && oldProgram.getSourceFile(file.fileName);
if (oldSourceFile !== file && file.resolvedModules) {
// `file` was created for the new program.
//
@@ -1120,7 +1158,7 @@ namespace ts {
const oldResolvedModule = getResolvedModule(oldSourceFile, moduleName);
if (oldResolvedModule) {
if (isTraceEnabled(options, host)) {
- trace(host, Diagnostics.Reusing_resolution_of_module_0_to_file_1_from_old_program, moduleName, containingFile);
+ trace(host, Diagnostics.Reusing_resolution_of_module_0_to_file_1_from_old_program, moduleName, getNormalizedAbsolutePath(file.originalFileName, currentDirectory));
}
(result || (result = new Array(moduleNames.length)))[i] = oldResolvedModule;
(reusedNames || (reusedNames = [])).push(moduleName);
@@ -1135,7 +1173,7 @@ namespace ts {
if (contains(file.ambientModuleNames, moduleName)) {
resolvesToAmbientModuleInNonModifiedFile = true;
if (isTraceEnabled(options, host)) {
- trace(host, Diagnostics.Module_0_was_resolved_as_locally_declared_ambient_module_in_file_1, moduleName, containingFile);
+ trace(host, Diagnostics.Module_0_was_resolved_as_locally_declared_ambient_module_in_file_1, moduleName, getNormalizedAbsolutePath(file.originalFileName, currentDirectory));
}
}
else {
@@ -1152,7 +1190,7 @@ namespace ts {
}
const resolutions = unknownModuleNames && unknownModuleNames.length
- ? resolveModuleNamesWorker(unknownModuleNames, containingFile, reusedNames, getResolvedProjectReferenceToRedirect(file.originalFileName))
+ ? resolveModuleNamesWorker(unknownModuleNames, file, reusedNames)
: emptyArray;
// Combine results of resolutions and predicted results
@@ -1397,9 +1435,8 @@ namespace ts {
}
// try to verify results of module resolution
for (const { oldFile: oldSourceFile, newFile: newSourceFile } of modifiedSourceFiles) {
- const newSourceFilePath = getNormalizedAbsolutePath(newSourceFile.originalFileName, currentDirectory);
const moduleNames = getModuleNames(newSourceFile);
- const resolutions = resolveModuleNamesReusingOldState(moduleNames, newSourceFilePath, newSourceFile);
+ const resolutions = resolveModuleNamesReusingOldState(moduleNames, newSourceFile);
// ensure that module resolution results are still correct
const resolutionsChanged = hasChangesInResolutions(moduleNames, resolutions, oldSourceFile.resolvedModules, moduleResolutionIsEqualTo);
if (resolutionsChanged) {
@@ -1409,19 +1446,17 @@ namespace ts {
else {
newSourceFile.resolvedModules = oldSourceFile.resolvedModules;
}
- if (resolveTypeReferenceDirectiveNamesWorker) {
- // We lower-case all type references because npm automatically lowercases all packages. See GH#9824.
- const typesReferenceDirectives = map(newSourceFile.typeReferenceDirectives, ref => toFileNameLowerCase(ref.fileName));
- const resolutions = resolveTypeReferenceDirectiveNamesWorker(typesReferenceDirectives, newSourceFilePath, getResolvedProjectReferenceToRedirect(newSourceFile.originalFileName));
- // ensure that types resolutions are still correct
- const resolutionsChanged = hasChangesInResolutions(typesReferenceDirectives, resolutions, oldSourceFile.resolvedTypeReferenceDirectiveNames, typeDirectiveIsEqualTo);
- if (resolutionsChanged) {
- oldProgram.structureIsReused = StructureIsReused.SafeModules;
- newSourceFile.resolvedTypeReferenceDirectiveNames = zipToMap(typesReferenceDirectives, resolutions);
- }
- else {
- newSourceFile.resolvedTypeReferenceDirectiveNames = oldSourceFile.resolvedTypeReferenceDirectiveNames;
- }
+ // We lower-case all type references because npm automatically lowercases all packages. See GH#9824.
+ const typesReferenceDirectives = map(newSourceFile.typeReferenceDirectives, ref => toFileNameLowerCase(ref.fileName));
+ const typeReferenceResolutions = resolveTypeReferenceDirectiveNamesWorker(typesReferenceDirectives, newSourceFile);
+ // ensure that types resolutions are still correct
+ const typeReferenceEesolutionsChanged = hasChangesInResolutions(typesReferenceDirectives, typeReferenceResolutions, oldSourceFile.resolvedTypeReferenceDirectiveNames, typeDirectiveIsEqualTo);
+ if (typeReferenceEesolutionsChanged) {
+ oldProgram.structureIsReused = StructureIsReused.SafeModules;
+ newSourceFile.resolvedTypeReferenceDirectiveNames = zipToMap(typesReferenceDirectives, typeReferenceResolutions);
+ }
+ else {
+ newSourceFile.resolvedTypeReferenceDirectiveNames = oldSourceFile.resolvedTypeReferenceDirectiveNames;
}
}
@@ -2685,7 +2720,7 @@ namespace ts {
return;
}
- const resolutions = resolveTypeReferenceDirectiveNamesWorker(typeDirectives, file.originalFileName, getResolvedProjectReferenceToRedirect(file.originalFileName));
+ const resolutions = resolveTypeReferenceDirectiveNamesWorker(typeDirectives, file);
for (let i = 0; i < typeDirectives.length; i++) {
const ref = file.typeReferenceDirectives[i];
@@ -2823,7 +2858,7 @@ namespace ts {
if (file.imports.length || file.moduleAugmentations.length) {
// Because global augmentation doesn't have string literal name, we can check for global augmentation as such.
const moduleNames = getModuleNames(file);
- const resolutions = resolveModuleNamesReusingOldState(moduleNames, getNormalizedAbsolutePath(file.originalFileName, currentDirectory), file);
+ const resolutions = resolveModuleNamesReusingOldState(moduleNames, file);
Debug.assert(resolutions.length === moduleNames.length);
for (let i = 0; i < moduleNames.length; i++) {
const resolution = resolutions[i];
diff --git a/src/testRunner/tsconfig.json b/src/testRunner/tsconfig.json
index 7ed0718f67f..fc9b2272ca3 100644
--- a/src/testRunner/tsconfig.json
+++ b/src/testRunner/tsconfig.json
@@ -120,6 +120,7 @@
"unittests/tsbuild/inferredTypeFromTransitiveModule.ts",
"unittests/tsbuild/javascriptProjectEmit.ts",
"unittests/tsbuild/lateBoundSymbol.ts",
+ "unittests/tsbuild/moduleResolution.ts",
"unittests/tsbuild/moduleSpecifiers.ts",
"unittests/tsbuild/noEmitOnError.ts",
"unittests/tsbuild/outFile.ts",
diff --git a/src/testRunner/unittests/tsbuild/moduleResolution.ts b/src/testRunner/unittests/tsbuild/moduleResolution.ts
new file mode 100644
index 00000000000..11403bdc18f
--- /dev/null
+++ b/src/testRunner/unittests/tsbuild/moduleResolution.ts
@@ -0,0 +1,69 @@
+namespace ts.tscWatch {
+ describe("unittests:: tsbuild:: moduleResolution:: handles the modules and options from referenced project correctly", () => {
+ function sys(optionsToExtend?: CompilerOptions) {
+ return createWatchedSystem([
+ {
+ path: `${projectRoot}/packages/pkg1/index.ts`,
+ content: Utils.dedent`
+ import type { TheNum } from 'pkg2'
+ export const theNum: TheNum = 42;`
+ },
+ {
+ path: `${projectRoot}/packages/pkg1/tsconfig.json`,
+ content: JSON.stringify({
+ compilerOptions: { outDir: "build", ...optionsToExtend },
+ references: [{ path: "../pkg2" }]
+ })
+ },
+ {
+ path: `${projectRoot}/packages/pkg2/const.ts`,
+ content: `export type TheNum = 42;`
+ },
+ {
+ path: `${projectRoot}/packages/pkg2/index.ts`,
+ content: `export type { TheNum } from 'const';`
+ },
+ {
+ path: `${projectRoot}/packages/pkg2/tsconfig.json`,
+ content: JSON.stringify({
+ compilerOptions: {
+ composite: true,
+ outDir: "build",
+ baseUrl: ".",
+ ...optionsToExtend
+ }
+ })
+ },
+ {
+ path: `${projectRoot}/packages/pkg2/package.json`,
+ content: JSON.stringify({
+ name: "pkg2",
+ version: "1.0.0",
+ main: "build/index.js",
+ })
+ },
+ {
+ path: `${projectRoot}/node_modules/pkg2`,
+ symLink: `${projectRoot}/packages/pkg2`,
+ },
+ libFile
+ ], { currentDirectory: projectRoot });
+ }
+
+ verifyTscWatch({
+ scenario: "moduleResolution",
+ subScenario: `resolves specifier in output declaration file from referenced project correctly`,
+ sys,
+ commandLineArgs: ["-b", "packages/pkg1", "--verbose", "--traceResolution"],
+ changes: emptyArray
+ });
+
+ verifyTscWatch({
+ scenario: "moduleResolution",
+ subScenario: `resolves specifier in output declaration file from referenced project correctly with preserveSymlinks`,
+ sys: () => sys({ preserveSymlinks: true }),
+ commandLineArgs: ["-b", "packages/pkg1", "--verbose", "--traceResolution"],
+ changes: emptyArray
+ });
+ });
+}
diff --git a/tests/baselines/reference/tsbuild/moduleResolution/resolves-specifier-in-output-declaration-file-from-referenced-project-correctly-with-preserveSymlinks.js b/tests/baselines/reference/tsbuild/moduleResolution/resolves-specifier-in-output-declaration-file-from-referenced-project-correctly-with-preserveSymlinks.js
new file mode 100644
index 00000000000..6e97736af16
--- /dev/null
+++ b/tests/baselines/reference/tsbuild/moduleResolution/resolves-specifier-in-output-declaration-file-from-referenced-project-correctly-with-preserveSymlinks.js
@@ -0,0 +1,196 @@
+Input::
+//// [/user/username/projects/myproject/packages/pkg1/index.ts]
+import type { TheNum } from 'pkg2'
+export const theNum: TheNum = 42;
+
+//// [/user/username/projects/myproject/packages/pkg1/tsconfig.json]
+{"compilerOptions":{"outDir":"build","preserveSymlinks":true},"references":[{"path":"../pkg2"}]}
+
+//// [/user/username/projects/myproject/packages/pkg2/const.ts]
+export type TheNum = 42;
+
+//// [/user/username/projects/myproject/packages/pkg2/index.ts]
+export type { TheNum } from 'const';
+
+//// [/user/username/projects/myproject/packages/pkg2/tsconfig.json]
+{"compilerOptions":{"composite":true,"outDir":"build","baseUrl":".","preserveSymlinks":true}}
+
+//// [/user/username/projects/myproject/packages/pkg2/package.json]
+{"name":"pkg2","version":"1.0.0","main":"build/index.js"}
+
+//// [/user/username/projects/myproject/node_modules/pkg2] symlink(/user/username/projects/myproject/packages/pkg2)
+//// [/a/lib/lib.d.ts]
+///
+interface Boolean {}
+interface Function {}
+interface CallableFunction {}
+interface NewableFunction {}
+interface IArguments {}
+interface Number { toExponential: any; }
+interface Object {}
+interface RegExp {}
+interface String { charAt: any; }
+interface Array { length: number; [n: number]: T; }
+
+
+/a/lib/tsc.js -b packages/pkg1 --verbose --traceResolution
+Output::
+[[90m12:00:39 AM[0m] Projects in this build:
+ * packages/pkg2/tsconfig.json
+ * packages/pkg1/tsconfig.json
+
+[[90m12:00:40 AM[0m] Project 'packages/pkg2/tsconfig.json' is out of date because output file 'packages/pkg2/build/const.js' does not exist
+
+[[90m12:00:41 AM[0m] Building project '/user/username/projects/myproject/packages/pkg2/tsconfig.json'...
+
+======== Resolving module 'const' from '/user/username/projects/myproject/packages/pkg2/index.ts'. ========
+Module resolution kind is not specified, using 'NodeJs'.
+'baseUrl' option is set to '/user/username/projects/myproject/packages/pkg2', using this value to resolve non-relative module name 'const'.
+Resolving module name 'const' relative to base url '/user/username/projects/myproject/packages/pkg2' - '/user/username/projects/myproject/packages/pkg2/const'.
+Loading module as file / folder, candidate module location '/user/username/projects/myproject/packages/pkg2/const', target file type 'TypeScript'.
+File '/user/username/projects/myproject/packages/pkg2/const.ts' exist - use it as a name resolution result.
+======== Module name 'const' was successfully resolved to '/user/username/projects/myproject/packages/pkg2/const.ts'. ========
+[[90m12:00:55 AM[0m] Project 'packages/pkg1/tsconfig.json' is out of date because output file 'packages/pkg1/build/index.js' does not exist
+
+[[90m12:00:56 AM[0m] Building project '/user/username/projects/myproject/packages/pkg1/tsconfig.json'...
+
+======== Resolving module 'pkg2' from '/user/username/projects/myproject/packages/pkg1/index.ts'. ========
+Module resolution kind is not specified, using 'NodeJs'.
+Loading module 'pkg2' from 'node_modules' folder, target file type 'TypeScript'.
+Directory '/user/username/projects/myproject/packages/pkg1/node_modules' does not exist, skipping all lookups in it.
+Directory '/user/username/projects/myproject/packages/node_modules' does not exist, skipping all lookups in it.
+Found 'package.json' at '/user/username/projects/myproject/node_modules/pkg2/package.json'.
+'package.json' does not have a 'typesVersions' field.
+File '/user/username/projects/myproject/node_modules/pkg2.ts' does not exist.
+File '/user/username/projects/myproject/node_modules/pkg2.tsx' does not exist.
+File '/user/username/projects/myproject/node_modules/pkg2.d.ts' does not exist.
+'package.json' does not have a 'typings' field.
+'package.json' does not have a 'types' field.
+'package.json' has 'main' field 'build/index.js' that references '/user/username/projects/myproject/node_modules/pkg2/build/index.js'.
+File '/user/username/projects/myproject/node_modules/pkg2/build/index.js' exist - use it as a name resolution result.
+File '/user/username/projects/myproject/node_modules/pkg2/build/index.js' has an unsupported extension, so skipping it.
+Loading module as file / folder, candidate module location '/user/username/projects/myproject/node_modules/pkg2/build/index.js', target file type 'TypeScript'.
+File '/user/username/projects/myproject/node_modules/pkg2/build/index.js.ts' does not exist.
+File '/user/username/projects/myproject/node_modules/pkg2/build/index.js.tsx' does not exist.
+File '/user/username/projects/myproject/node_modules/pkg2/build/index.js.d.ts' does not exist.
+File name '/user/username/projects/myproject/node_modules/pkg2/build/index.js' has a '.js' extension - stripping it.
+File '/user/username/projects/myproject/node_modules/pkg2/build/index.ts' does not exist.
+File '/user/username/projects/myproject/node_modules/pkg2/build/index.tsx' does not exist.
+File '/user/username/projects/myproject/node_modules/pkg2/build/index.d.ts' exist - use it as a name resolution result.
+======== Module name 'pkg2' was successfully resolved to '/user/username/projects/myproject/node_modules/pkg2/build/index.d.ts' with Package ID 'pkg2/build/index.d.ts@1.0.0'. ========
+======== Resolving module 'const' from '/user/username/projects/myproject/node_modules/pkg2/build/index.d.ts'. ========
+Using compiler options of project reference redirect '/user/username/projects/myproject/packages/pkg2/tsconfig.json'.
+Module resolution kind is not specified, using 'NodeJs'.
+'baseUrl' option is set to '/user/username/projects/myproject/packages/pkg2', using this value to resolve non-relative module name 'const'.
+Resolving module name 'const' relative to base url '/user/username/projects/myproject/packages/pkg2' - '/user/username/projects/myproject/packages/pkg2/const'.
+Loading module as file / folder, candidate module location '/user/username/projects/myproject/packages/pkg2/const', target file type 'TypeScript'.
+File '/user/username/projects/myproject/packages/pkg2/const.ts' exist - use it as a name resolution result.
+======== Module name 'const' was successfully resolved to '/user/username/projects/myproject/packages/pkg2/const.ts'. ========
+
+
+Program root files: ["/user/username/projects/myproject/packages/pkg2/const.ts","/user/username/projects/myproject/packages/pkg2/index.ts"]
+Program options: {"composite":true,"outDir":"/user/username/projects/myproject/packages/pkg2/build","baseUrl":"/user/username/projects/myproject/packages/pkg2","preserveSymlinks":true,"traceResolution":true,"configFilePath":"/user/username/projects/myproject/packages/pkg2/tsconfig.json"}
+Program files::
+/a/lib/lib.d.ts
+/user/username/projects/myproject/packages/pkg2/const.ts
+/user/username/projects/myproject/packages/pkg2/index.ts
+
+Semantic diagnostics in builder refreshed for::
+/a/lib/lib.d.ts
+/user/username/projects/myproject/packages/pkg2/const.ts
+/user/username/projects/myproject/packages/pkg2/index.ts
+
+Program root files: ["/user/username/projects/myproject/packages/pkg1/index.ts"]
+Program options: {"outDir":"/user/username/projects/myproject/packages/pkg1/build","preserveSymlinks":true,"traceResolution":true,"configFilePath":"/user/username/projects/myproject/packages/pkg1/tsconfig.json"}
+Program files::
+/a/lib/lib.d.ts
+/user/username/projects/myproject/packages/pkg2/build/const.d.ts
+/user/username/projects/myproject/node_modules/pkg2/build/index.d.ts
+/user/username/projects/myproject/packages/pkg1/index.ts
+
+Semantic diagnostics in builder refreshed for::
+/a/lib/lib.d.ts
+/user/username/projects/myproject/packages/pkg2/build/const.d.ts
+/user/username/projects/myproject/node_modules/pkg2/build/index.d.ts
+/user/username/projects/myproject/packages/pkg1/index.ts
+
+WatchedFiles::
+
+FsWatches::
+
+FsWatchesRecursive::
+
+exitCode:: ExitStatus.Success
+
+//// [/user/username/projects/myproject/packages/pkg2/build/const.js]
+"use strict";
+exports.__esModule = true;
+
+
+//// [/user/username/projects/myproject/packages/pkg2/build/const.d.ts]
+export declare type TheNum = 42;
+
+
+//// [/user/username/projects/myproject/packages/pkg2/build/index.js]
+"use strict";
+exports.__esModule = true;
+
+
+//// [/user/username/projects/myproject/packages/pkg2/build/index.d.ts]
+export type { TheNum } from 'const';
+
+
+//// [/user/username/projects/myproject/packages/pkg2/build/tsconfig.tsbuildinfo]
+{
+ "program": {
+ "fileInfos": {
+ "../../../../../../../a/lib/lib.d.ts": {
+ "version": "-7698705165-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }",
+ "signature": "-7698705165-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }",
+ "affectsGlobalScope": true
+ },
+ "../const.ts": {
+ "version": "-11202312776-export type TheNum = 42;",
+ "signature": "-9649133742-export declare type TheNum = 42;\n",
+ "affectsGlobalScope": false
+ },
+ "../index.ts": {
+ "version": "-10837689162-export type { TheNum } from 'const';",
+ "signature": "-9751391360-export type { TheNum } from 'const';\n",
+ "affectsGlobalScope": false
+ }
+ },
+ "options": {
+ "composite": true,
+ "outDir": "./",
+ "baseUrl": "..",
+ "preserveSymlinks": true,
+ "traceResolution": true,
+ "configFilePath": "../tsconfig.json"
+ },
+ "referencedMap": {
+ "../index.ts": [
+ "../const.ts"
+ ]
+ },
+ "exportedModulesMap": {
+ "../index.ts": [
+ "../const.ts"
+ ]
+ },
+ "semanticDiagnosticsPerFile": [
+ "../../../../../../../a/lib/lib.d.ts",
+ "../const.ts",
+ "../index.ts"
+ ]
+ },
+ "version": "FakeTSVersion"
+}
+
+//// [/user/username/projects/myproject/packages/pkg1/build/index.js]
+"use strict";
+exports.__esModule = true;
+exports.theNum = void 0;
+exports.theNum = 42;
+
+
diff --git a/tests/baselines/reference/tsbuild/moduleResolution/resolves-specifier-in-output-declaration-file-from-referenced-project-correctly.js b/tests/baselines/reference/tsbuild/moduleResolution/resolves-specifier-in-output-declaration-file-from-referenced-project-correctly.js
new file mode 100644
index 00000000000..faf05f5ae32
--- /dev/null
+++ b/tests/baselines/reference/tsbuild/moduleResolution/resolves-specifier-in-output-declaration-file-from-referenced-project-correctly.js
@@ -0,0 +1,196 @@
+Input::
+//// [/user/username/projects/myproject/packages/pkg1/index.ts]
+import type { TheNum } from 'pkg2'
+export const theNum: TheNum = 42;
+
+//// [/user/username/projects/myproject/packages/pkg1/tsconfig.json]
+{"compilerOptions":{"outDir":"build"},"references":[{"path":"../pkg2"}]}
+
+//// [/user/username/projects/myproject/packages/pkg2/const.ts]
+export type TheNum = 42;
+
+//// [/user/username/projects/myproject/packages/pkg2/index.ts]
+export type { TheNum } from 'const';
+
+//// [/user/username/projects/myproject/packages/pkg2/tsconfig.json]
+{"compilerOptions":{"composite":true,"outDir":"build","baseUrl":"."}}
+
+//// [/user/username/projects/myproject/packages/pkg2/package.json]
+{"name":"pkg2","version":"1.0.0","main":"build/index.js"}
+
+//// [/user/username/projects/myproject/node_modules/pkg2] symlink(/user/username/projects/myproject/packages/pkg2)
+//// [/a/lib/lib.d.ts]
+///
+interface Boolean {}
+interface Function {}
+interface CallableFunction {}
+interface NewableFunction {}
+interface IArguments {}
+interface Number { toExponential: any; }
+interface Object {}
+interface RegExp {}
+interface String { charAt: any; }
+interface Array { length: number; [n: number]: T; }
+
+
+/a/lib/tsc.js -b packages/pkg1 --verbose --traceResolution
+Output::
+[[90m12:00:39 AM[0m] Projects in this build:
+ * packages/pkg2/tsconfig.json
+ * packages/pkg1/tsconfig.json
+
+[[90m12:00:40 AM[0m] Project 'packages/pkg2/tsconfig.json' is out of date because output file 'packages/pkg2/build/const.js' does not exist
+
+[[90m12:00:41 AM[0m] Building project '/user/username/projects/myproject/packages/pkg2/tsconfig.json'...
+
+======== Resolving module 'const' from '/user/username/projects/myproject/packages/pkg2/index.ts'. ========
+Module resolution kind is not specified, using 'NodeJs'.
+'baseUrl' option is set to '/user/username/projects/myproject/packages/pkg2', using this value to resolve non-relative module name 'const'.
+Resolving module name 'const' relative to base url '/user/username/projects/myproject/packages/pkg2' - '/user/username/projects/myproject/packages/pkg2/const'.
+Loading module as file / folder, candidate module location '/user/username/projects/myproject/packages/pkg2/const', target file type 'TypeScript'.
+File '/user/username/projects/myproject/packages/pkg2/const.ts' exist - use it as a name resolution result.
+======== Module name 'const' was successfully resolved to '/user/username/projects/myproject/packages/pkg2/const.ts'. ========
+[[90m12:00:55 AM[0m] Project 'packages/pkg1/tsconfig.json' is out of date because output file 'packages/pkg1/build/index.js' does not exist
+
+[[90m12:00:56 AM[0m] Building project '/user/username/projects/myproject/packages/pkg1/tsconfig.json'...
+
+======== Resolving module 'pkg2' from '/user/username/projects/myproject/packages/pkg1/index.ts'. ========
+Module resolution kind is not specified, using 'NodeJs'.
+Loading module 'pkg2' from 'node_modules' folder, target file type 'TypeScript'.
+Directory '/user/username/projects/myproject/packages/pkg1/node_modules' does not exist, skipping all lookups in it.
+Directory '/user/username/projects/myproject/packages/node_modules' does not exist, skipping all lookups in it.
+Found 'package.json' at '/user/username/projects/myproject/node_modules/pkg2/package.json'.
+'package.json' does not have a 'typesVersions' field.
+File '/user/username/projects/myproject/node_modules/pkg2.ts' does not exist.
+File '/user/username/projects/myproject/node_modules/pkg2.tsx' does not exist.
+File '/user/username/projects/myproject/node_modules/pkg2.d.ts' does not exist.
+'package.json' does not have a 'typings' field.
+'package.json' does not have a 'types' field.
+'package.json' has 'main' field 'build/index.js' that references '/user/username/projects/myproject/node_modules/pkg2/build/index.js'.
+File '/user/username/projects/myproject/node_modules/pkg2/build/index.js' exist - use it as a name resolution result.
+File '/user/username/projects/myproject/node_modules/pkg2/build/index.js' has an unsupported extension, so skipping it.
+Loading module as file / folder, candidate module location '/user/username/projects/myproject/node_modules/pkg2/build/index.js', target file type 'TypeScript'.
+File '/user/username/projects/myproject/node_modules/pkg2/build/index.js.ts' does not exist.
+File '/user/username/projects/myproject/node_modules/pkg2/build/index.js.tsx' does not exist.
+File '/user/username/projects/myproject/node_modules/pkg2/build/index.js.d.ts' does not exist.
+File name '/user/username/projects/myproject/node_modules/pkg2/build/index.js' has a '.js' extension - stripping it.
+File '/user/username/projects/myproject/node_modules/pkg2/build/index.ts' does not exist.
+File '/user/username/projects/myproject/node_modules/pkg2/build/index.tsx' does not exist.
+File '/user/username/projects/myproject/node_modules/pkg2/build/index.d.ts' exist - use it as a name resolution result.
+Resolving real path for '/user/username/projects/myproject/node_modules/pkg2/build/index.d.ts', result '/user/username/projects/myproject/packages/pkg2/build/index.d.ts'.
+======== Module name 'pkg2' was successfully resolved to '/user/username/projects/myproject/packages/pkg2/build/index.d.ts' with Package ID 'pkg2/build/index.d.ts@1.0.0'. ========
+======== Resolving module 'const' from '/user/username/projects/myproject/packages/pkg2/build/index.d.ts'. ========
+Using compiler options of project reference redirect '/user/username/projects/myproject/packages/pkg2/tsconfig.json'.
+Module resolution kind is not specified, using 'NodeJs'.
+'baseUrl' option is set to '/user/username/projects/myproject/packages/pkg2', using this value to resolve non-relative module name 'const'.
+Resolving module name 'const' relative to base url '/user/username/projects/myproject/packages/pkg2' - '/user/username/projects/myproject/packages/pkg2/const'.
+Loading module as file / folder, candidate module location '/user/username/projects/myproject/packages/pkg2/const', target file type 'TypeScript'.
+File '/user/username/projects/myproject/packages/pkg2/const.ts' exist - use it as a name resolution result.
+======== Module name 'const' was successfully resolved to '/user/username/projects/myproject/packages/pkg2/const.ts'. ========
+
+
+Program root files: ["/user/username/projects/myproject/packages/pkg2/const.ts","/user/username/projects/myproject/packages/pkg2/index.ts"]
+Program options: {"composite":true,"outDir":"/user/username/projects/myproject/packages/pkg2/build","baseUrl":"/user/username/projects/myproject/packages/pkg2","traceResolution":true,"configFilePath":"/user/username/projects/myproject/packages/pkg2/tsconfig.json"}
+Program files::
+/a/lib/lib.d.ts
+/user/username/projects/myproject/packages/pkg2/const.ts
+/user/username/projects/myproject/packages/pkg2/index.ts
+
+Semantic diagnostics in builder refreshed for::
+/a/lib/lib.d.ts
+/user/username/projects/myproject/packages/pkg2/const.ts
+/user/username/projects/myproject/packages/pkg2/index.ts
+
+Program root files: ["/user/username/projects/myproject/packages/pkg1/index.ts"]
+Program options: {"outDir":"/user/username/projects/myproject/packages/pkg1/build","traceResolution":true,"configFilePath":"/user/username/projects/myproject/packages/pkg1/tsconfig.json"}
+Program files::
+/a/lib/lib.d.ts
+/user/username/projects/myproject/packages/pkg2/build/const.d.ts
+/user/username/projects/myproject/packages/pkg2/build/index.d.ts
+/user/username/projects/myproject/packages/pkg1/index.ts
+
+Semantic diagnostics in builder refreshed for::
+/a/lib/lib.d.ts
+/user/username/projects/myproject/packages/pkg2/build/const.d.ts
+/user/username/projects/myproject/packages/pkg2/build/index.d.ts
+/user/username/projects/myproject/packages/pkg1/index.ts
+
+WatchedFiles::
+
+FsWatches::
+
+FsWatchesRecursive::
+
+exitCode:: ExitStatus.Success
+
+//// [/user/username/projects/myproject/packages/pkg2/build/const.js]
+"use strict";
+exports.__esModule = true;
+
+
+//// [/user/username/projects/myproject/packages/pkg2/build/const.d.ts]
+export declare type TheNum = 42;
+
+
+//// [/user/username/projects/myproject/packages/pkg2/build/index.js]
+"use strict";
+exports.__esModule = true;
+
+
+//// [/user/username/projects/myproject/packages/pkg2/build/index.d.ts]
+export type { TheNum } from 'const';
+
+
+//// [/user/username/projects/myproject/packages/pkg2/build/tsconfig.tsbuildinfo]
+{
+ "program": {
+ "fileInfos": {
+ "../../../../../../../a/lib/lib.d.ts": {
+ "version": "-7698705165-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }",
+ "signature": "-7698705165-/// \ninterface Boolean {}\ninterface Function {}\ninterface CallableFunction {}\ninterface NewableFunction {}\ninterface IArguments {}\ninterface Number { toExponential: any; }\ninterface Object {}\ninterface RegExp {}\ninterface String { charAt: any; }\ninterface Array { length: number; [n: number]: T; }",
+ "affectsGlobalScope": true
+ },
+ "../const.ts": {
+ "version": "-11202312776-export type TheNum = 42;",
+ "signature": "-9649133742-export declare type TheNum = 42;\n",
+ "affectsGlobalScope": false
+ },
+ "../index.ts": {
+ "version": "-10837689162-export type { TheNum } from 'const';",
+ "signature": "-9751391360-export type { TheNum } from 'const';\n",
+ "affectsGlobalScope": false
+ }
+ },
+ "options": {
+ "composite": true,
+ "outDir": "./",
+ "baseUrl": "..",
+ "traceResolution": true,
+ "configFilePath": "../tsconfig.json"
+ },
+ "referencedMap": {
+ "../index.ts": [
+ "../const.ts"
+ ]
+ },
+ "exportedModulesMap": {
+ "../index.ts": [
+ "../const.ts"
+ ]
+ },
+ "semanticDiagnosticsPerFile": [
+ "../../../../../../../a/lib/lib.d.ts",
+ "../const.ts",
+ "../index.ts"
+ ]
+ },
+ "version": "FakeTSVersion"
+}
+
+//// [/user/username/projects/myproject/packages/pkg1/build/index.js]
+"use strict";
+exports.__esModule = true;
+exports.theNum = void 0;
+exports.theNum = 42;
+
+