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:: +[12:00:39 AM] Projects in this build: + * packages/pkg2/tsconfig.json + * packages/pkg1/tsconfig.json + +[12:00:40 AM] Project 'packages/pkg2/tsconfig.json' is out of date because output file 'packages/pkg2/build/const.js' does not exist + +[12:00:41 AM] 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'. ======== +[12:00:55 AM] Project 'packages/pkg1/tsconfig.json' is out of date because output file 'packages/pkg1/build/index.js' does not exist + +[12:00:56 AM] 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:: +[12:00:39 AM] Projects in this build: + * packages/pkg2/tsconfig.json + * packages/pkg1/tsconfig.json + +[12:00:40 AM] Project 'packages/pkg2/tsconfig.json' is out of date because output file 'packages/pkg2/build/const.js' does not exist + +[12:00:41 AM] 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'. ======== +[12:00:55 AM] Project 'packages/pkg1/tsconfig.json' is out of date because output file 'packages/pkg1/build/index.js' does not exist + +[12:00:56 AM] 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; + +