diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 26b93b19335..f2f6ad93562 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2255,7 +2255,7 @@ namespace ts { ? Diagnostics.If_the_0_package_actually_exposes_this_module_consider_sending_a_pull_request_to_amend_https_Colon_Slash_Slashgithub_com_SlashDefinitelyTyped_SlashDefinitelyTyped_Slashtree_Slashmaster_Slashtypes_Slash_1 : Diagnostics.Try_npm_install_types_Slash_1_if_it_exists_or_add_a_new_declaration_d_ts_file_containing_declare_module_0, packageId.name, - getMangledNameForScopedPackage(packageId.name)) + mangleScopedPackageName(packageId.name)) : undefined; errorOrSuggestion(isError, errorNode, chainDiagnosticMessages( errorInfo, diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 6000c48de4d..ed528e5b87e 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -3273,7 +3273,7 @@ "category": "Message", "code": 6104 }, - "Expected type of '{0}' field in 'package.json' to be 'string', got '{1}'.": { + "Expected type of '{0}' field in 'package.json' to be '{1}', got '{2}'.": { "category": "Message", "code": 6105 }, diff --git a/src/compiler/moduleNameResolver.ts b/src/compiler/moduleNameResolver.ts index 7fb308912c3..d1054579e84 100644 --- a/src/compiler/moduleNameResolver.ts +++ b/src/compiler/moduleNameResolver.ts @@ -88,6 +88,7 @@ namespace ts { interface PackageJsonPathFields { typings?: string; types?: string; + typesVersions?: MapLike; main?: string; } @@ -111,7 +112,7 @@ namespace ts { const fileName = jsonContent[fieldName]; if (!isString(fileName)) { if (state.traceEnabled) { - trace(state.host, Diagnostics.Expected_type_of_0_field_in_package_json_to_be_string_got_1, fieldName, typeof fileName); + trace(state.host, Diagnostics.Expected_type_of_0_field_in_package_json_to_be_1_got_2, fieldName, "string", typeof fileName); } return; } @@ -124,21 +125,65 @@ namespace ts { } } - /* @internal */ - export function readJson(path: string, host: { readFile(fileName: string): string | undefined }): object { - try { - const jsonText = host.readFile(path); - if (!jsonText) return {}; - const result = parseConfigFileTextToJson(path, jsonText); - if (result.error) { - return {}; + function tryReadPackageJsonTypesVersion(jsonContent: PackageJson, baseDirectory: string, state: ModuleResolutionState): string | undefined { + if (!hasProperty(jsonContent, "typesVersions")) { + if (state.traceEnabled) { + trace(state.host, Diagnostics.package_json_does_not_have_a_0_field, "typesVersions"); } - return result.config; + return; } - catch (e) { - // gracefully handle if readFile fails or returns not JSON - return {}; + + const typesVersions = jsonContent.typesVersions; + if (typeof typesVersions !== "object") { + if (state.traceEnabled) { + trace(state.host, Diagnostics.Expected_type_of_0_field_in_package_json_to_be_1_got_2, "typesVersions", "object", typeof typesVersions); + } + return; } + + const typeScriptVersion = Version.parse(version); + let bestVersion: Version | undefined; + let bestVersionKey: string | undefined; + for (const key in typesVersions) { + if (!hasProperty(typesVersions, key)) continue; + + const keyVersion = Version.tryParse(key); + if (keyVersion === undefined) { + if (state.traceEnabled) { + // TODO(rbuckton): log + } + continue; + } + + // match the greatest version less than the current TypeScript version + if (keyVersion.compareTo(typeScriptVersion) <= 0 + && (bestVersion === undefined || keyVersion.compareTo(bestVersion) > 0)) { + bestVersion = keyVersion; + bestVersionKey = key; + } + } + + if (!bestVersionKey) { + if (state.traceEnabled) { + // TODO(rbuckton): log + } + return; + } + + const bestVersionPath = typesVersions[bestVersionKey]; + if (!isString(bestVersionPath)) { + if (state.traceEnabled) { + trace(state.host, Diagnostics.Expected_type_of_0_field_in_package_json_to_be_1_got_2, `typesVersion['${bestVersionKey}']`, "string", typeof bestVersionPath); + } + return; + } + + if (state.traceEnabled) { + const path = normalizePath(combinePaths(baseDirectory, bestVersionPath)); + trace(state.host, Diagnostics.package_json_has_0_field_1_that_references_2, `typesVersion['${bestVersionKey}']`, bestVersionPath, path); + } + + return bestVersionPath; } export function getEffectiveTypeRoots(options: CompilerOptions, host: GetEffectiveTypeRootsHost): string[] | undefined { @@ -720,7 +765,6 @@ namespace ts { } else { const candidate = normalizePath(combinePaths(state.compilerOptions.baseUrl, moduleName)); - if (state.traceEnabled) { trace(state.host, Diagnostics.Resolving_module_name_0_relative_to_base_url_1_2, moduleName, state.compilerOptions.baseUrl, candidate); } @@ -892,12 +936,6 @@ namespace ts { return path + "/index.d.ts"; } - /* @internal */ - export function directoryProbablyExists(directoryName: string, host: { directoryExists?: (directoryName: string) => boolean }): boolean { - // if host does not support 'directoryExists' assume that directory will exist - return !host.directoryExists || host.directoryExists(directoryName); - } - function loadModuleFromFileNoPackageId(extensions: Extensions, candidate: string, failedLookupLocations: Push, onlyRecordFailures: boolean, state: ModuleResolutionState): Resolved | undefined { return noPackageId(loadModuleFromFile(extensions, candidate, failedLookupLocations, onlyRecordFailures, state)); } @@ -977,9 +1015,12 @@ namespace ts { } function loadNodeModuleFromDirectory(extensions: Extensions, candidate: string, failedLookupLocations: Push, onlyRecordFailures: boolean, state: ModuleResolutionState, considerPackageJson = true) { - const { packageJsonContent, packageId } = considerPackageJson + const { packageJsonContent, packageId, versionPath } = considerPackageJson ? getPackageJsonInfo(candidate, "", failedLookupLocations, onlyRecordFailures, state) - : { packageJsonContent: undefined, packageId: undefined }; + : { packageJsonContent: undefined, packageId: undefined, versionPath: undefined }; + if (versionPath) { + candidate = normalizePath(combinePaths(candidate, versionPath)); + } return withPackageId(packageId, loadNodeModuleFromDirectoryWorker(extensions, candidate, failedLookupLocations, onlyRecordFailures, state, packageJsonContent)); } @@ -998,16 +1039,18 @@ namespace ts { failedLookupLocations: Push, onlyRecordFailures: boolean, state: ModuleResolutionState, - ): { found: boolean, packageJsonContent: PackageJsonPathFields | undefined, packageId: PackageId | undefined } { + ): { found: boolean, packageJsonContent: PackageJsonPathFields | undefined, packageId: PackageId | undefined, versionPath: string | undefined } { const { host, traceEnabled } = state; const directoryExists = !onlyRecordFailures && directoryProbablyExists(nodeModuleDirectory, host); const packageJsonPath = pathToPackageJson(nodeModuleDirectory); if (directoryExists && host.fileExists(packageJsonPath)) { const packageJsonContent = readJson(packageJsonPath, host) as PackageJson; + const versionPath = tryReadPackageJsonTypesVersion(packageJsonContent, nodeModuleDirectory, state); if (subModuleName === "") { // looking up the root - need to handle types/typings/main redirects for subModuleName - const path = tryReadPackageJsonFields(/*readTypes*/ true, packageJsonContent, nodeModuleDirectory, state); + const versionDirectory = versionPath ? normalizePath(combinePaths(nodeModuleDirectory, versionPath)) : nodeModuleDirectory; + const path = tryReadPackageJsonFields(/*readTypes*/ true, packageJsonContent, versionDirectory, state); if (typeof path === "string") { - subModuleName = addExtensionAndIndex(path.substring(nodeModuleDirectory.length + 1)); + subModuleName = addExtensionAndIndex(path.substring(versionDirectory.length + 1)); } else { const jsPath = tryReadPackageJsonFields(/*readTypes*/ false, packageJsonContent, nodeModuleDirectory, state); @@ -1021,6 +1064,11 @@ namespace ts { } } } + + // if (versionPath) { + // subModuleName = combinePaths(versionPath, subModuleName); + // } + if (!endsWith(subModuleName, Extension.Dts)) { subModuleName = addExtensionAndIndex(subModuleName); } @@ -1035,15 +1083,16 @@ namespace ts { trace(host, Diagnostics.Found_package_json_at_0, packageJsonPath); } } - return { found: true, packageJsonContent, packageId }; + return { found: true, packageJsonContent, packageId, versionPath }; } else { if (directoryExists && traceEnabled) { trace(host, Diagnostics.File_0_does_not_exist, packageJsonPath); } + // record package json as one of failed lookup locations - in the future if this file will appear it will invalidate resolution results failedLookupLocations.push(packageJsonPath); - return { found: false, packageJsonContent: undefined, packageId: undefined }; + return { found: false, packageJsonContent: undefined, packageId: undefined, versionPath: undefined }; } } @@ -1110,20 +1159,30 @@ namespace ts { } function loadModuleFromNodeModulesFolder(extensions: Extensions, moduleName: string, nodeModulesFolder: string, nodeModulesFolderExists: boolean, failedLookupLocations: Push, state: ModuleResolutionState): Resolved | undefined { - const candidate = normalizePath(combinePaths(nodeModulesFolder, moduleName)); + let candidate = normalizePath(combinePaths(nodeModulesFolder, moduleName)); // First look for a nested package.json, as in `node_modules/foo/bar/package.json`. let packageJsonContent: PackageJsonPathFields | undefined; + let versionPath: string | undefined; let packageId: PackageId | undefined; const packageInfo = getPackageJsonInfo(candidate, "", failedLookupLocations, /*onlyRecordFailures*/ !nodeModulesFolderExists, state); if (packageInfo.found) { - ({ packageJsonContent, packageId } = packageInfo); + ({ packageJsonContent, packageId, versionPath } = packageInfo); + + // If package.json supplied a typescript-version prefix path, apply it to the candidate. + if (versionPath) { + candidate = normalizePath(combinePaths(candidate, versionPath)); + } } else { - const { packageName, rest } = getPackageName(moduleName); + const { packageName, rest } = parsePackageName(moduleName); if (rest !== "") { // If "rest" is empty, we just did this search above. const packageRootPath = combinePaths(nodeModulesFolder, packageName); // Don't use a "types" or "main" from here because we're not loading the root, but a subdirectory -- just here for the packageId. - packageId = getPackageJsonInfo(packageRootPath, rest, failedLookupLocations, !nodeModulesFolderExists, state).packageId; + ({ packageId, versionPath } = getPackageJsonInfo(packageRootPath, rest, failedLookupLocations, !nodeModulesFolderExists, state)); + // If package.json supplied a typescript-version prefix path, apply it to the candidate. + if (versionPath) { + candidate = normalizePath(combinePaths(packageRootPath, versionPath, rest)); + } } } const pathAndExtension = loadModuleFromFile(extensions, candidate, failedLookupLocations, !nodeModulesFolderExists, state) || @@ -1132,7 +1191,7 @@ namespace ts { } /* @internal */ - export function getPackageName(moduleName: string): { packageName: string, rest: string } { + export function parsePackageName(moduleName: string): { packageName: string, rest: string } { let idx = moduleName.indexOf(directorySeparator); if (moduleName[0] === "@") { idx = moduleName.indexOf(directorySeparator, idx + 1); @@ -1141,14 +1200,14 @@ namespace ts { } function loadModuleFromNodeModules(extensions: Extensions, moduleName: string, directory: string, failedLookupLocations: Push, state: ModuleResolutionState, cache: NonRelativeModuleNameResolutionCache | undefined): SearchResult { - return loadModuleFromNodeModulesWorker(extensions, moduleName, directory, failedLookupLocations, state, /*typesOnly*/ false, cache); + return loadModuleFromNearestNodeModules(extensions, moduleName, directory, failedLookupLocations, state, /*typesOnly*/ false, cache); } function loadModuleFromNodeModulesAtTypes(moduleName: string, directory: string, failedLookupLocations: Push, state: ModuleResolutionState): SearchResult { // Extensions parameter here doesn't actually matter, because typesOnly ensures we're just doing @types lookup, which is always DtsOnly. - return loadModuleFromNodeModulesWorker(Extensions.DtsOnly, moduleName, directory, failedLookupLocations, state, /*typesOnly*/ true, /*cache*/ undefined); + return loadModuleFromNearestNodeModules(Extensions.DtsOnly, moduleName, directory, failedLookupLocations, state, /*typesOnly*/ true, /*cache*/ undefined); } - function loadModuleFromNodeModulesWorker(extensions: Extensions, moduleName: string, directory: string, failedLookupLocations: Push, state: ModuleResolutionState, typesOnly: boolean, cache: NonRelativeModuleNameResolutionCache | undefined): SearchResult { + function loadModuleFromNearestNodeModules(extensions: Extensions, moduleName: string, directory: string, failedLookupLocations: Push, state: ModuleResolutionState, typesOnly: boolean, cache: NonRelativeModuleNameResolutionCache | undefined): SearchResult { const perModuleNameCache = cache && cache.getOrCreateCacheForModuleName(moduleName); return forEachAncestorDirectory(normalizeSlashes(directory), ancestorDirectory => { if (getBaseFileName(ancestorDirectory) !== "node_modules") { @@ -1156,13 +1215,12 @@ namespace ts { if (resolutionFromCache) { return resolutionFromCache; } - return toSearchResult(loadModuleFromNodeModulesOneLevel(extensions, moduleName, ancestorDirectory, failedLookupLocations, state, typesOnly)); + return toSearchResult(loadModuleFromImmediateNodeModules(extensions, moduleName, ancestorDirectory, failedLookupLocations, state, typesOnly)); } }); } - /** Load a module from a single node_modules directory, but not from any ancestors' node_modules directories. */ - function loadModuleFromNodeModulesOneLevel(extensions: Extensions, moduleName: string, directory: string, failedLookupLocations: Push, state: ModuleResolutionState, typesOnly = false): Resolved | undefined { + function loadModuleFromImmediateNodeModules(extensions: Extensions, moduleName: string, directory: string, failedLookupLocations: Push, state: ModuleResolutionState, typesOnly: boolean): Resolved | undefined { const nodeModulesFolder = combinePaths(directory, "node_modules"); const nodeModulesFolderExists = directoryProbablyExists(nodeModulesFolder, state.host); if (!nodeModulesFolderExists && state.traceEnabled) { @@ -1182,7 +1240,7 @@ namespace ts { } nodeModulesAtTypesExists = false; } - return loadModuleFromNodeModulesFolder(Extensions.DtsOnly, mangleScopedPackage(moduleName, state), nodeModulesAtTypes, nodeModulesAtTypesExists, failedLookupLocations, state); + return loadModuleFromNodeModulesFolder(Extensions.DtsOnly, mangleScopedPackageNameWithTrace(moduleName, state), nodeModulesAtTypes, nodeModulesAtTypesExists, failedLookupLocations, state); } } @@ -1190,8 +1248,8 @@ namespace ts { const mangledScopedPackageSeparator = "__"; /** For a scoped package, we must look in `@types/foo__bar` instead of `@types/@foo/bar`. */ - function mangleScopedPackage(packageName: string, state: ModuleResolutionState): string { - const mangled = getMangledNameForScopedPackage(packageName); + function mangleScopedPackageNameWithTrace(packageName: string, state: ModuleResolutionState): string { + const mangled = mangleScopedPackageName(packageName); if (state.traceEnabled && mangled !== packageName) { trace(state.host, Diagnostics.Scoped_package_detected_looking_in_0, mangled); } @@ -1200,11 +1258,11 @@ namespace ts { /* @internal */ export function getTypesPackageName(packageName: string): string { - return `@types/${getMangledNameForScopedPackage(packageName)}`; + return `@types/${mangleScopedPackageName(packageName)}`; } /* @internal */ - export function getMangledNameForScopedPackage(packageName: string): string { + export function mangleScopedPackageName(packageName: string): string { if (startsWith(packageName, "@")) { const replaceSlash = packageName.replace(directorySeparator, mangledScopedPackageSeparator); if (replaceSlash !== packageName) { @@ -1215,16 +1273,16 @@ namespace ts { } /* @internal */ - export function getPackageNameFromAtTypesDirectory(mangledName: string): string { + export function getPackageNameFromTypesPackageName(mangledName: string): string { const withoutAtTypePrefix = removePrefix(mangledName, "@types/"); if (withoutAtTypePrefix !== mangledName) { - return getUnmangledNameForScopedPackage(withoutAtTypePrefix); + return unmangleScopedPackageName(withoutAtTypePrefix); } return mangledName; } /* @internal */ - export function getUnmangledNameForScopedPackage(typesPackageName: string): string { + export function unmangleScopedPackageName(typesPackageName: string): string { return stringContains(typesPackageName, mangledScopedPackageSeparator) ? "@" + typesPackageName.replace(mangledScopedPackageSeparator, directorySeparator) : typesPackageName; @@ -1295,7 +1353,7 @@ namespace ts { } const state: ModuleResolutionState = { compilerOptions, host, traceEnabled }; const failedLookupLocations: string[] = []; - const resolved = loadModuleFromNodeModulesOneLevel(Extensions.DtsOnly, moduleName, globalCache, failedLookupLocations, state); + const resolved = loadModuleFromImmediateNodeModules(Extensions.DtsOnly, moduleName, globalCache, failedLookupLocations, state, /*typesOnly*/ false); return createResolvedModuleWithFailedLookupLocations(resolved, /*isExternalLibraryImport*/ true, failedLookupLocations); } diff --git a/src/compiler/moduleSpecifiers.ts b/src/compiler/moduleSpecifiers.ts index 8c695e10be2..696736048b1 100644 --- a/src/compiler/moduleSpecifiers.ts +++ b/src/compiler/moduleSpecifiers.ts @@ -326,7 +326,7 @@ namespace ts.moduleSpecifiers { // if node_modules folder is in this folder or any of its parent folders, no need to keep it. if (!startsWith(sourceDirectory, getCanonicalFileName(moduleSpecifier.substring(0, parts.topLevelNodeModulesIndex)))) return undefined; // If the module was found in @types, get the actual Node package name - return getPackageNameFromAtTypesDirectory(moduleSpecifier.substring(parts.topLevelPackageNameIndex + 1)); + return getPackageNameFromTypesPackageName(moduleSpecifier.substring(parts.topLevelPackageNameIndex + 1)); function getDirectoryOrExtensionlessFileName(path: string): string { // If the file is the main module, it can be imported by the package name diff --git a/src/compiler/semver.ts b/src/compiler/semver.ts new file mode 100644 index 00000000000..a3c4e90d37a --- /dev/null +++ b/src/compiler/semver.ts @@ -0,0 +1,156 @@ +/* @internal */ +namespace ts { + // Per https://semver.org/#spec-item-2: + // + // > A normal version number MUST take the form X.Y.Z where X, Y, and Z are non-negative + // > integers, and MUST NOT contain leading zeroes. X is the major version, Y is the minor + // > version, and Z is the patch version. Each element MUST increase numerically. + // + // NOTE: We differ here in that we allow X and X.Y, with missing parts having the default + // value of `0`. + const versionRegExp = /^(0|[1-9]\d*)(?:\.(0|[1-9]\d*)(?:\.(0|[1-9]\d*)(?:-([a-z0-9-.]+))?(?:(\+[a-z0-9-.]+))?)?)?$/i; + + // Per https://semver.org/#spec-item-9: + // + // > A pre-release version MAY be denoted by appending a hyphen and a series of dot separated + // > identifiers immediately following the patch version. Identifiers MUST comprise only ASCII + // > alphanumerics and hyphen [0-9A-Za-z-]. Identifiers MUST NOT be empty. Numeric identifiers + // > MUST NOT include leading zeroes. + const prereleaseRegExp = /^(?:0|[1-9]\d*|[a-z-][a-z0-9-]*)(?:\.(?:0|[1-9]\d*|[a-z-][a-z0-9-]*))*$/i; + + // Per https://semver.org/#spec-item-10: + // + // > Build metadata MAY be denoted by appending a plus sign and a series of dot separated + // > identifiers immediately following the patch or pre-release version. Identifiers MUST + // > comprise only ASCII alphanumerics and hyphen [0-9A-Za-z-]. Identifiers MUST NOT be empty. + const buildRegExp = /^[a-z0-9-]+(?:\.[a-z0-9-]+)*$/i; + + // Per https://semver.org/#spec-item-9: + // + // > Numeric identifiers MUST NOT include leading zeroes. + const numericIdentifierRegExp = /^(0|[1-9]\d*)$/; + + /** + * Describes a precise semantic version number, per https://semver.org + */ + export class Version { + static readonly zero = new Version(0); + + readonly major: number; + readonly minor: number; + readonly patch: number; + readonly prerelease: ReadonlyArray; + readonly build: ReadonlyArray; + + constructor(major: number, minor = 0, patch = 0, prerelease = "", build = "") { + Debug.assert(major >= 0, "Invalid argument: major"); + Debug.assert(minor >= 0, "Invalid argument: minor"); + Debug.assert(patch >= 0, "Invalid argument: patch"); + Debug.assert(!prerelease || prereleaseRegExp.test(prerelease), "Invalid argument: prerelease"); + Debug.assert(!build || buildRegExp.test(build), "Invalid argument: build"); + this.major = major; + this.minor = minor; + this.patch = patch; + this.prerelease = prerelease === "" ? emptyArray : prerelease.split("."); + this.build = build === "" ? emptyArray : build.split("."); + } + + static parse(text: string) { + return Debug.assertDefined(this.tryParse(text)); + } + + static tryParse(text: string) { + const match = versionRegExp.exec(text); + if (!match) return undefined; + + const [, major, minor = 0, patch = 0, prerelease, build] = match; + if (prerelease && !prereleaseRegExp.test(prerelease)) return undefined; + if (build && !buildRegExp.test(build)) return undefined; + return new Version(+major, +minor, +patch, prerelease, build); + } + + static compare(left: Version | undefined, right: Version | undefined, compareBuildMetadata?: boolean) { + // Per https://semver.org/#spec-item-11: + // + // > Precedence is determined by the first difference when comparing each of these + // > identifiers from left to right as follows: Major, minor, and patch versions are + // > always compared numerically. + // + // > When major, minor, and patch are equal, a pre-release version has lower + // > precedence than a normal version. + // + // Per https://semver.org/#spec-item-10: + // + // > Build metadata SHOULD be ignored when determining version precedence. + if (left === right) return Comparison.EqualTo; + if (left === undefined) return Comparison.LessThan; + if (right === undefined) return Comparison.GreaterThan; + return compareValues(left.major, right.major) + || compareValues(left.minor, right.minor) + || compareValues(left.patch, right.patch) + || compareVersionFragments(left.prerelease, right.prerelease, /*compareNumericIdentifiers*/ true) + || (compareBuildMetadata ? compareVersionFragments(left.build, right.build, /*compareNumericIdentifiers*/ false) : Comparison.EqualTo); + } + + compareTo(other: Version, compareBuildMetadata?: boolean) { + return Version.compare(this, other, compareBuildMetadata); + } + + toString() { + let result = `${this.major}.${this.minor}.${this.patch}`; + if (this.prerelease) result += `-${this.prerelease.join(".")}`; + if (this.build) result += `+${this.build.join(".")}`; + return result; + } + } + + function compareVersionFragments(left: ReadonlyArray, right: ReadonlyArray, compareNumericIdentifiers: boolean) { + // Per https://semver.org/#spec-item-11: + // + // > When major, minor, and patch are equal, a pre-release version has lower precedence + // > than a normal version. + if (left === right) return Comparison.EqualTo; + if (left.length === 0) return right.length === 0 ? Comparison.EqualTo : Comparison.GreaterThan; + if (right.length === 0) return Comparison.LessThan; + + // Per https://semver.org/#spec-item-11: + // + // > Precedence for two pre-release versions with the same major, minor, and patch version + // > MUST be determined by comparing each dot separated identifier from left to right until + // > a difference is found + const length = Math.min(left.length, right.length); + for (let i = 0; i < length; i++) { + const leftIdentifier = left[i]; + const rightIdentifier = right[i]; + if (leftIdentifier === rightIdentifier) continue; + + const leftIsNumeric = compareNumericIdentifiers && numericIdentifierRegExp.test(leftIdentifier); + const rightIsNumeric = compareNumericIdentifiers && numericIdentifierRegExp.test(rightIdentifier); + if (leftIsNumeric || rightIsNumeric) { + // Per https://semver.org/#spec-item-11: + // + // > Numeric identifiers always have lower precedence than non-numeric identifiers. + if (leftIsNumeric !== rightIsNumeric) return leftIsNumeric ? Comparison.LessThan : Comparison.GreaterThan; + + // Per https://semver.org/#spec-item-11: + // + // > identifiers consisting of only digits are compared numerically + const result = compareValues(+leftIdentifier, +rightIdentifier); + if (result) return result; + } + else { + // Per https://semver.org/#spec-item-11: + // + // > identifiers with letters or hyphens are compared lexically in ASCII sort order. + const result = compareStringsCaseSensitive(leftIdentifier, rightIdentifier); + if (result) return result; + } + } + + // Per https://semver.org/#spec-item-11: + // + // > A larger set of pre-release fields has a higher precedence than a smaller set, if all + // > of the preceding identifiers are equal. + return compareValues(left.length, right.length); + } +} \ No newline at end of file diff --git a/src/compiler/tsconfig.json b/src/compiler/tsconfig.json index 20b97c1b778..2d3cbcf54fe 100644 --- a/src/compiler/tsconfig.json +++ b/src/compiler/tsconfig.json @@ -9,6 +9,7 @@ "files": [ "core.ts", "performance.ts", + "semver.ts", "types.ts", "sys.ts", diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 33dfd2617c9..e7eb352da84 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -3940,6 +3940,27 @@ namespace ts { return getStringFromExpandedCharCodes(expandedCharCodes); } + export function readJson(path: string, host: { readFile(fileName: string): string | undefined }): object { + try { + const jsonText = host.readFile(path); + if (!jsonText) return {}; + const result = parseConfigFileTextToJson(path, jsonText); + if (result.error) { + return {}; + } + return result.config; + } + catch (e) { + // gracefully handle if readFile fails or returns not JSON + return {}; + } + } + + export function directoryProbablyExists(directoryName: string, host: { directoryExists?: (directoryName: string) => boolean }): boolean { + // if host does not support 'directoryExists' assume that directory will exist + return !host.directoryExists || host.directoryExists(directoryName); + } + const carriageReturnLineFeed = "\r\n"; const lineFeed = "\n"; export function getNewLineCharacter(options: CompilerOptions | PrinterOptions, getNewLine?: () => string): string { diff --git a/src/services/codefixes/fixCannotFindModule.ts b/src/services/codefixes/fixCannotFindModule.ts index 68fa3a5c030..6822cae7911 100644 --- a/src/services/codefixes/fixCannotFindModule.ts +++ b/src/services/codefixes/fixCannotFindModule.ts @@ -29,7 +29,7 @@ namespace ts.codefix { function getTypesPackageNameToInstall(host: LanguageServiceHost, sourceFile: SourceFile, pos: number, diagCode: number): string | undefined { const moduleName = cast(getTokenAtPosition(sourceFile, pos), isStringLiteral).text; - const { packageName } = getPackageName(moduleName); + const { packageName } = parsePackageName(moduleName); return diagCode === errorCodeCannotFindModule ? (JsTyping.nodeCoreModules.has(packageName) ? "@types/node" : undefined) : (host.isKnownTypesPackageName!(packageName) ? getTypesPackageName(packageName) : undefined); // TODO: GH#18217 diff --git a/src/services/pathCompletions.ts b/src/services/pathCompletions.ts index 8ab7cc315ad..3a546573db7 100644 --- a/src/services/pathCompletions.ts +++ b/src/services/pathCompletions.ts @@ -329,7 +329,7 @@ namespace ts.Completions.PathCompletions { const seen = createMap(); if (options.types) { for (const typesName of options.types) { - const moduleName = getUnmangledNameForScopedPackage(typesName); + const moduleName = unmangleScopedPackageName(typesName); pushResult(moduleName); } } @@ -363,7 +363,7 @@ namespace ts.Completions.PathCompletions { for (let typeDirectory of directories) { typeDirectory = normalizePath(typeDirectory); const directoryName = getBaseFileName(typeDirectory); - const moduleName = getUnmangledNameForScopedPackage(directoryName); + const moduleName = unmangleScopedPackageName(directoryName); pushResult(moduleName); } } diff --git a/tests/baselines/reference/duplicatePackage_relativeImportWithinPackage.trace.json b/tests/baselines/reference/duplicatePackage_relativeImportWithinPackage.trace.json index d75683d210f..dbf67e3802c 100644 --- a/tests/baselines/reference/duplicatePackage_relativeImportWithinPackage.trace.json +++ b/tests/baselines/reference/duplicatePackage_relativeImportWithinPackage.trace.json @@ -2,6 +2,7 @@ "======== Resolving module 'foo/use' from '/index.ts'. ========", "Module resolution kind is not specified, using 'NodeJs'.", "Loading module 'foo/use' from 'node_modules' folder, target file type 'TypeScript'.", + "'package.json' does not have a 'typesVersions' field.", "Found 'package.json' at '/node_modules/foo/package.json'. Package ID is 'foo/use/index.d.ts@1.2.3'.", "File '/node_modules/foo/use.ts' does not exist.", "File '/node_modules/foo/use.tsx' does not exist.", @@ -26,11 +27,13 @@ "File '/node_modules/foo/index.ts' does not exist.", "File '/node_modules/foo/index.tsx' does not exist.", "File '/node_modules/foo/index.d.ts' exist - use it as a name resolution result.", + "'package.json' does not have a 'typesVersions' field.", "Found 'package.json' at '/node_modules/foo/package.json'. Package ID is 'foo/index.d.ts@1.2.3'.", "======== Module name './index' was successfully resolved to '/node_modules/foo/index.d.ts'. ========", "======== Resolving module 'foo' from '/node_modules/a/index.d.ts'. ========", "Module resolution kind is not specified, using 'NodeJs'.", "Loading module 'foo' from 'node_modules' folder, target file type 'TypeScript'.", + "'package.json' does not have a 'typesVersions' field.", "'package.json' does not have a 'typings' field.", "'package.json' does not have a 'types' field.", "'package.json' does not have a 'main' field.", diff --git a/tests/baselines/reference/duplicatePackage_relativeImportWithinPackage_scoped.trace.json b/tests/baselines/reference/duplicatePackage_relativeImportWithinPackage_scoped.trace.json index 7b07ecd66e4..d3d3dfac064 100644 --- a/tests/baselines/reference/duplicatePackage_relativeImportWithinPackage_scoped.trace.json +++ b/tests/baselines/reference/duplicatePackage_relativeImportWithinPackage_scoped.trace.json @@ -2,6 +2,7 @@ "======== Resolving module '@foo/bar/use' from '/index.ts'. ========", "Module resolution kind is not specified, using 'NodeJs'.", "Loading module '@foo/bar/use' from 'node_modules' folder, target file type 'TypeScript'.", + "'package.json' does not have a 'typesVersions' field.", "Found 'package.json' at '/node_modules/@foo/bar/package.json'. Package ID is '@foo/bar/use/index.d.ts@1.2.3'.", "File '/node_modules/@foo/bar/use.ts' does not exist.", "File '/node_modules/@foo/bar/use.tsx' does not exist.", @@ -26,11 +27,13 @@ "File '/node_modules/@foo/bar/index.ts' does not exist.", "File '/node_modules/@foo/bar/index.tsx' does not exist.", "File '/node_modules/@foo/bar/index.d.ts' exist - use it as a name resolution result.", + "'package.json' does not have a 'typesVersions' field.", "Found 'package.json' at '/node_modules/@foo/bar/package.json'. Package ID is '@foo/bar/index.d.ts@1.2.3'.", "======== Module name './index' was successfully resolved to '/node_modules/@foo/bar/index.d.ts'. ========", "======== Resolving module '@foo/bar' from '/node_modules/a/index.d.ts'. ========", "Module resolution kind is not specified, using 'NodeJs'.", "Loading module '@foo/bar' from 'node_modules' folder, target file type 'TypeScript'.", + "'package.json' does not have a 'typesVersions' field.", "'package.json' does not have a 'typings' field.", "'package.json' does not have a 'types' field.", "'package.json' does not have a 'main' field.", diff --git a/tests/baselines/reference/library-reference-10.trace.json b/tests/baselines/reference/library-reference-10.trace.json index ad34c0b1dc3..d24bc21f283 100644 --- a/tests/baselines/reference/library-reference-10.trace.json +++ b/tests/baselines/reference/library-reference-10.trace.json @@ -1,6 +1,7 @@ [ "======== Resolving type reference directive 'jquery', containing file '/foo/consumer.ts', root directory './types'. ========", "Resolving with primary search path './types'.", + "'package.json' does not have a 'typesVersions' field.", "'package.json' has 'typings' field 'jquery.d.ts' that references 'types/jquery/jquery.d.ts'.", "Found 'package.json' at './types/jquery/package.json'.", "'package.json' has 'typings' field 'jquery.d.ts' that references 'types/jquery/jquery.d.ts'.", @@ -9,6 +10,7 @@ "======== Type reference directive 'jquery' was successfully resolved to '/foo/types/jquery/jquery.d.ts', primary: true. ========", "======== Resolving type reference directive 'jquery', containing file '/foo/__inferred type names__.ts', root directory './types'. ========", "Resolving with primary search path './types'.", + "'package.json' does not have a 'typesVersions' field.", "'package.json' has 'typings' field 'jquery.d.ts' that references 'types/jquery/jquery.d.ts'.", "Found 'package.json' at './types/jquery/package.json'.", "'package.json' has 'typings' field 'jquery.d.ts' that references 'types/jquery/jquery.d.ts'.", diff --git a/tests/baselines/reference/library-reference-11.trace.json b/tests/baselines/reference/library-reference-11.trace.json index be260b6bc6e..5b2d6695356 100644 --- a/tests/baselines/reference/library-reference-11.trace.json +++ b/tests/baselines/reference/library-reference-11.trace.json @@ -3,6 +3,7 @@ "Root directory cannot be determined, skipping primary search paths.", "Looking up in 'node_modules' folder, initial location '/a/b'.", "Directory '/a/b/node_modules' does not exist, skipping all lookups in it.", + "'package.json' does not have a 'typesVersions' field.", "'package.json' has 'typings' field 'jquery.d.ts' that references '/a/node_modules/jquery/jquery.d.ts'.", "Found 'package.json' at '/a/node_modules/jquery/package.json'.", "File '/a/node_modules/jquery.d.ts' does not exist.", diff --git a/tests/baselines/reference/library-reference-12.trace.json b/tests/baselines/reference/library-reference-12.trace.json index 26361703708..f6c1aef4811 100644 --- a/tests/baselines/reference/library-reference-12.trace.json +++ b/tests/baselines/reference/library-reference-12.trace.json @@ -3,6 +3,7 @@ "Root directory cannot be determined, skipping primary search paths.", "Looking up in 'node_modules' folder, initial location '/a/b'.", "Directory '/a/b/node_modules' does not exist, skipping all lookups in it.", + "'package.json' does not have a 'typesVersions' field.", "'package.json' does not have a 'typings' field.", "'package.json' has 'types' field 'dist/jquery.d.ts' that references '/a/node_modules/jquery/dist/jquery.d.ts'.", "Found 'package.json' at '/a/node_modules/jquery/package.json'.", diff --git a/tests/baselines/reference/library-reference-2.trace.json b/tests/baselines/reference/library-reference-2.trace.json index 649189fbbdd..baef46d8995 100644 --- a/tests/baselines/reference/library-reference-2.trace.json +++ b/tests/baselines/reference/library-reference-2.trace.json @@ -1,6 +1,7 @@ [ "======== Resolving type reference directive 'jquery', containing file '/consumer.ts', root directory '/types'. ========", "Resolving with primary search path '/types'.", + "'package.json' does not have a 'typesVersions' field.", "'package.json' does not have a 'typings' field.", "'package.json' has 'types' field 'jquery.d.ts' that references '/types/jquery/jquery.d.ts'.", "Found 'package.json' at '/types/jquery/package.json'.", @@ -11,6 +12,7 @@ "======== Type reference directive 'jquery' was successfully resolved to '/types/jquery/jquery.d.ts', primary: true. ========", "======== Resolving type reference directive 'jquery', containing file '/test/__inferred type names__.ts', root directory '/types'. ========", "Resolving with primary search path '/types'.", + "'package.json' does not have a 'typesVersions' field.", "'package.json' does not have a 'typings' field.", "'package.json' has 'types' field 'jquery.d.ts' that references '/types/jquery/jquery.d.ts'.", "Found 'package.json' at '/types/jquery/package.json'.", diff --git a/tests/baselines/reference/moduleResolutionWithExtensions_unexpected.trace.json b/tests/baselines/reference/moduleResolutionWithExtensions_unexpected.trace.json index 60cdab44a29..2f743d9e200 100644 --- a/tests/baselines/reference/moduleResolutionWithExtensions_unexpected.trace.json +++ b/tests/baselines/reference/moduleResolutionWithExtensions_unexpected.trace.json @@ -2,6 +2,7 @@ "======== Resolving module 'normalize.css' from '/a.ts'. ========", "Module resolution kind is not specified, using 'NodeJs'.", "Loading module 'normalize.css' from 'node_modules' folder, target file type 'TypeScript'.", + "'package.json' does not have a 'typesVersions' field.", "'package.json' does not have a 'typings' field.", "'package.json' does not have a 'types' field.", "'package.json' has 'main' field 'normalize.css' that references '/node_modules/normalize.css/normalize.css'.", @@ -24,6 +25,7 @@ "File '/node_modules/normalize.css/index.d.ts' does not exist.", "Directory '/node_modules/@types' does not exist, skipping all lookups in it.", "Loading module 'normalize.css' from 'node_modules' folder, target file type 'JavaScript'.", + "'package.json' does not have a 'typesVersions' field.", "'package.json' does not have a 'typings' field.", "'package.json' does not have a 'types' field.", "'package.json' has 'main' field 'normalize.css' that references '/node_modules/normalize.css/normalize.css'.", diff --git a/tests/baselines/reference/moduleResolutionWithExtensions_unexpected2.trace.json b/tests/baselines/reference/moduleResolutionWithExtensions_unexpected2.trace.json index bab6be18d39..06610253558 100644 --- a/tests/baselines/reference/moduleResolutionWithExtensions_unexpected2.trace.json +++ b/tests/baselines/reference/moduleResolutionWithExtensions_unexpected2.trace.json @@ -2,6 +2,7 @@ "======== Resolving module 'foo' from '/a.ts'. ========", "Module resolution kind is not specified, using 'NodeJs'.", "Loading module 'foo' from 'node_modules' folder, target file type 'TypeScript'.", + "'package.json' does not have a 'typesVersions' field.", "'package.json' does not have a 'typings' field.", "'package.json' has 'types' field 'foo.js' that references '/node_modules/foo/foo.js'.", "Found 'package.json' at '/node_modules/foo/package.json'.", @@ -26,6 +27,7 @@ "File '/node_modules/foo/index.d.ts' does not exist.", "Directory '/node_modules/@types' does not exist, skipping all lookups in it.", "Loading module 'foo' from 'node_modules' folder, target file type 'JavaScript'.", + "'package.json' does not have a 'typesVersions' field.", "'package.json' does not have a 'typings' field.", "'package.json' has 'types' field 'foo.js' that references '/node_modules/foo/foo.js'.", "Found 'package.json' at '/node_modules/foo/package.json'.", diff --git a/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot.trace.json b/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot.trace.json index 3473f33c1f2..2a4a1e71a4a 100644 --- a/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot.trace.json +++ b/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot.trace.json @@ -2,6 +2,7 @@ "======== Resolving module 'foo/bar' from '/a.ts'. ========", "Module resolution kind is not specified, using 'NodeJs'.", "Loading module 'foo/bar' from 'node_modules' folder, target file type 'TypeScript'.", + "'package.json' does not have a 'typesVersions' field.", "'package.json' does not have a 'typings' field.", "'package.json' has 'types' field 'types.d.ts' that references '/node_modules/foo/bar/types.d.ts'.", "Found 'package.json' at '/node_modules/foo/bar/package.json'.", diff --git a/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot_fakeScopedPackage.trace.json b/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot_fakeScopedPackage.trace.json index 07dc908b745..b54519397ab 100644 --- a/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot_fakeScopedPackage.trace.json +++ b/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot_fakeScopedPackage.trace.json @@ -2,6 +2,7 @@ "======== Resolving module 'foo/@bar' from '/a.ts'. ========", "Module resolution kind is not specified, using 'NodeJs'.", "Loading module 'foo/@bar' from 'node_modules' folder, target file type 'TypeScript'.", + "'package.json' does not have a 'typesVersions' field.", "'package.json' does not have a 'typings' field.", "'package.json' has 'types' field 'types.d.ts' that references '/node_modules/foo/@bar/types.d.ts'.", "Found 'package.json' at '/node_modules/foo/@bar/package.json'.", diff --git a/tests/baselines/reference/moduleResolution_packageJson_scopedPackage.trace.json b/tests/baselines/reference/moduleResolution_packageJson_scopedPackage.trace.json index 77ea6a244c1..389bd892d2f 100644 --- a/tests/baselines/reference/moduleResolution_packageJson_scopedPackage.trace.json +++ b/tests/baselines/reference/moduleResolution_packageJson_scopedPackage.trace.json @@ -2,6 +2,7 @@ "======== Resolving module '@foo/bar' from '/a.ts'. ========", "Module resolution kind is not specified, using 'NodeJs'.", "Loading module '@foo/bar' from 'node_modules' folder, target file type 'TypeScript'.", + "'package.json' does not have a 'typesVersions' field.", "'package.json' does not have a 'typings' field.", "'package.json' has 'types' field 'types.d.ts' that references '/node_modules/@foo/bar/types.d.ts'.", "Found 'package.json' at '/node_modules/@foo/bar/package.json'.", diff --git a/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot.trace.json b/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot.trace.json index 453f5c088a3..873805b8b57 100644 --- a/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot.trace.json +++ b/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot.trace.json @@ -3,6 +3,7 @@ "Module resolution kind is not specified, using 'NodeJs'.", "Loading module 'foo/bar' from 'node_modules' folder, target file type 'TypeScript'.", "File '/node_modules/foo/bar/package.json' does not exist.", + "'package.json' does not have a 'typesVersions' field.", "Found 'package.json' at '/node_modules/foo/package.json'. Package ID is 'foo/bar/index.d.ts@1.2.3'.", "File '/node_modules/foo/bar.ts' does not exist.", "File '/node_modules/foo/bar.tsx' does not exist.", @@ -13,6 +14,7 @@ "Directory '/node_modules/@types' does not exist, skipping all lookups in it.", "Loading module 'foo/bar' from 'node_modules' folder, target file type 'JavaScript'.", "File '/node_modules/foo/bar/package.json' does not exist.", + "'package.json' does not have a 'typesVersions' field.", "Found 'package.json' at '/node_modules/foo/package.json'. Package ID is 'foo/bar/index.d.ts@1.2.3'.", "File '/node_modules/foo/bar.js' does not exist.", "File '/node_modules/foo/bar.jsx' does not exist.", diff --git a/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot_fakeScopedPackage.trace.json b/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot_fakeScopedPackage.trace.json index b84bac8993a..95beae1393e 100644 --- a/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot_fakeScopedPackage.trace.json +++ b/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot_fakeScopedPackage.trace.json @@ -3,6 +3,7 @@ "Module resolution kind is not specified, using 'NodeJs'.", "Loading module 'foo/@bar' from 'node_modules' folder, target file type 'TypeScript'.", "File '/node_modules/foo/@bar/package.json' does not exist.", + "'package.json' does not have a 'typesVersions' field.", "Found 'package.json' at '/node_modules/foo/package.json'. Package ID is 'foo/@bar/index.d.ts@1.2.3'.", "File '/node_modules/foo/@bar.ts' does not exist.", "File '/node_modules/foo/@bar.tsx' does not exist.", @@ -13,6 +14,7 @@ "Directory '/node_modules/@types' does not exist, skipping all lookups in it.", "Loading module 'foo/@bar' from 'node_modules' folder, target file type 'JavaScript'.", "File '/node_modules/foo/@bar/package.json' does not exist.", + "'package.json' does not have a 'typesVersions' field.", "Found 'package.json' at '/node_modules/foo/package.json'. Package ID is 'foo/@bar/index.d.ts@1.2.3'.", "File '/node_modules/foo/@bar.js' does not exist.", "File '/node_modules/foo/@bar.jsx' does not exist.", diff --git a/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot_mainFieldInSubDirectory.trace.json b/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot_mainFieldInSubDirectory.trace.json index 849b65ee59f..84b7a4873c0 100644 --- a/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot_mainFieldInSubDirectory.trace.json +++ b/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot_mainFieldInSubDirectory.trace.json @@ -2,6 +2,7 @@ "======== Resolving module 'foo' from '/index.ts'. ========", "Module resolution kind is not specified, using 'NodeJs'.", "Loading module 'foo' from 'node_modules' folder, target file type 'TypeScript'.", + "'package.json' does not have a 'typesVersions' field.", "'package.json' does not have a 'typings' field.", "'package.json' does not have a 'types' field.", "'package.json' has 'main' field 'src/index.js' that references '/node_modules/foo/src/index.js'.", diff --git a/tests/baselines/reference/packageJsonMain.trace.json b/tests/baselines/reference/packageJsonMain.trace.json index 06c8cff6643..583fc96774e 100644 --- a/tests/baselines/reference/packageJsonMain.trace.json +++ b/tests/baselines/reference/packageJsonMain.trace.json @@ -2,6 +2,7 @@ "======== Resolving module 'foo' from '/a.ts'. ========", "Module resolution kind is not specified, using 'NodeJs'.", "Loading module 'foo' from 'node_modules' folder, target file type 'TypeScript'.", + "'package.json' does not have a 'typesVersions' field.", "'package.json' does not have a 'typings' field.", "'package.json' does not have a 'types' field.", "'package.json' has 'main' field 'oof' that references '/node_modules/foo/oof'.", @@ -23,6 +24,7 @@ "File '/node_modules/foo/index.d.ts' does not exist.", "Directory '/node_modules/@types' does not exist, skipping all lookups in it.", "Loading module 'foo' from 'node_modules' folder, target file type 'JavaScript'.", + "'package.json' does not have a 'typesVersions' field.", "'package.json' does not have a 'typings' field.", "'package.json' does not have a 'types' field.", "'package.json' has 'main' field 'oof' that references '/node_modules/foo/oof'.", @@ -38,6 +40,7 @@ "======== Resolving module 'bar' from '/a.ts'. ========", "Module resolution kind is not specified, using 'NodeJs'.", "Loading module 'bar' from 'node_modules' folder, target file type 'TypeScript'.", + "'package.json' does not have a 'typesVersions' field.", "'package.json' does not have a 'typings' field.", "'package.json' does not have a 'types' field.", "'package.json' has 'main' field 'rab.js' that references '/node_modules/bar/rab.js'.", @@ -64,6 +67,7 @@ "File '/node_modules/bar/index.d.ts' does not exist.", "Directory '/node_modules/@types' does not exist, skipping all lookups in it.", "Loading module 'bar' from 'node_modules' folder, target file type 'JavaScript'.", + "'package.json' does not have a 'typesVersions' field.", "'package.json' does not have a 'typings' field.", "'package.json' does not have a 'types' field.", "'package.json' has 'main' field 'rab.js' that references '/node_modules/bar/rab.js'.", @@ -77,6 +81,7 @@ "======== Resolving module 'baz' from '/a.ts'. ========", "Module resolution kind is not specified, using 'NodeJs'.", "Loading module 'baz' from 'node_modules' folder, target file type 'TypeScript'.", + "'package.json' does not have a 'typesVersions' field.", "'package.json' does not have a 'typings' field.", "'package.json' does not have a 'types' field.", "'package.json' has 'main' field 'zab' that references '/node_modules/baz/zab'.", @@ -100,6 +105,7 @@ "File '/node_modules/baz/index.d.ts' does not exist.", "Directory '/node_modules/@types' does not exist, skipping all lookups in it.", "Loading module 'baz' from 'node_modules' folder, target file type 'JavaScript'.", + "'package.json' does not have a 'typesVersions' field.", "'package.json' does not have a 'typings' field.", "'package.json' does not have a 'types' field.", "'package.json' has 'main' field 'zab' that references '/node_modules/baz/zab'.", diff --git a/tests/baselines/reference/packageJsonMain_isNonRecursive.trace.json b/tests/baselines/reference/packageJsonMain_isNonRecursive.trace.json index a2878a2a4fe..b7d26d0f852 100644 --- a/tests/baselines/reference/packageJsonMain_isNonRecursive.trace.json +++ b/tests/baselines/reference/packageJsonMain_isNonRecursive.trace.json @@ -2,6 +2,7 @@ "======== Resolving module 'foo' from '/a.ts'. ========", "Module resolution kind is not specified, using 'NodeJs'.", "Loading module 'foo' from 'node_modules' folder, target file type 'TypeScript'.", + "'package.json' does not have a 'typesVersions' field.", "'package.json' does not have a 'typings' field.", "'package.json' does not have a 'types' field.", "'package.json' has 'main' field 'oof' that references '/node_modules/foo/oof'.", @@ -25,6 +26,7 @@ "File '/node_modules/foo/index.d.ts' does not exist.", "Directory '/node_modules/@types' does not exist, skipping all lookups in it.", "Loading module 'foo' from 'node_modules' folder, target file type 'JavaScript'.", + "'package.json' does not have a 'typesVersions' field.", "'package.json' does not have a 'typings' field.", "'package.json' does not have a 'types' field.", "'package.json' has 'main' field 'oof' that references '/node_modules/foo/oof'.", diff --git a/tests/baselines/reference/typesVersions.ambientModules.js b/tests/baselines/reference/typesVersions.ambientModules.js new file mode 100644 index 00000000000..c7f198b8467 --- /dev/null +++ b/tests/baselines/reference/typesVersions.ambientModules.js @@ -0,0 +1,43 @@ +//// [tests/cases/conformance/moduleResolution/typesVersions.ambientModules.ts] //// + +//// [package.json] +{ + "name": "ext", + "version": "1.0.0", + "types": "index", + "typesVersions": { + "3.0": "ts3.0" + } +} + +//// [index.d.ts] +declare module "ext" { + export const a = "default a"; +} +declare module "ext/other" { + export const b = "default b"; +} + +//// [index.d.ts] +declare module "ext" { + export const a = "ts3.0 a"; +} +declare module "ext/other" { + export const b = "ts3.0 b"; +} + +//// [main.ts] +import { a } from "ext"; +import { b } from "ext/other"; + +const aa: "ts3.0 a" = a; +const bb: "ts3.0 b" = b; + + +//// [main.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const ext_1 = require("ext"); +const other_1 = require("ext/other"); +const aa = ext_1.a; +const bb = other_1.b; diff --git a/tests/baselines/reference/typesVersions.ambientModules.symbols b/tests/baselines/reference/typesVersions.ambientModules.symbols new file mode 100644 index 00000000000..d8a0ab0f2ca --- /dev/null +++ b/tests/baselines/reference/typesVersions.ambientModules.symbols @@ -0,0 +1,29 @@ +=== tests/cases/conformance/moduleResolution/main.ts === +import { a } from "ext"; +>a : Symbol(a, Decl(main.ts, 0, 8)) + +import { b } from "ext/other"; +>b : Symbol(b, Decl(main.ts, 1, 8)) + +const aa: "ts3.0 a" = a; +>aa : Symbol(aa, Decl(main.ts, 3, 5)) +>a : Symbol(a, Decl(main.ts, 0, 8)) + +const bb: "ts3.0 b" = b; +>bb : Symbol(bb, Decl(main.ts, 4, 5)) +>b : Symbol(b, Decl(main.ts, 1, 8)) + +=== tests/cases/conformance/moduleResolution/node_modules/ext/ts3.0/index.d.ts === +declare module "ext" { +>"ext" : Symbol("ext", Decl(index.d.ts, 0, 0)) + + export const a = "ts3.0 a"; +>a : Symbol(a, Decl(index.d.ts, 1, 16)) +} +declare module "ext/other" { +>"ext/other" : Symbol("ext/other", Decl(index.d.ts, 2, 1)) + + export const b = "ts3.0 b"; +>b : Symbol(b, Decl(index.d.ts, 4, 16)) +} + diff --git a/tests/baselines/reference/typesVersions.ambientModules.trace.json b/tests/baselines/reference/typesVersions.ambientModules.trace.json new file mode 100644 index 00000000000..990834accc2 --- /dev/null +++ b/tests/baselines/reference/typesVersions.ambientModules.trace.json @@ -0,0 +1,46 @@ +[ + "======== Resolving module 'ext' from 'tests/cases/conformance/moduleResolution/main.ts'. ========", + "Module resolution kind is not specified, using 'NodeJs'.", + "Loading module 'ext' from 'node_modules' folder, target file type 'TypeScript'.", + "'package.json' has 'typesVersion['3.0']' field 'ts3.0' that references 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.0'.", + "'package.json' does not have a 'typings' field.", + "'package.json' has 'types' field 'index' that references 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.0/index'.", + "Found 'package.json' at 'tests/cases/conformance/moduleResolution/node_modules/ext/package.json'. Package ID is 'ext/ts3.0/index.d.ts@1.0.0'.", + "File 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.0.ts' does not exist.", + "File 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.0.tsx' does not exist.", + "File 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.0.d.ts' does not exist.", + "'package.json' does not have a 'typings' field.", + "'package.json' has 'types' field 'index' that references 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.0/index'.", + "File 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.0/index' does not exist.", + "Loading module as file / folder, candidate module location 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.0/index', target file type 'TypeScript'.", + "File 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.0/index.ts' does not exist.", + "File 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.0/index.tsx' does not exist.", + "File 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.0/index.d.ts' exist - use it as a name resolution result.", + "Resolving real path for 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.0/index.d.ts', result 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.0/index.d.ts'.", + "======== Module name 'ext' was successfully resolved to 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.0/index.d.ts'. ========", + "======== Resolving module 'ext/other' from 'tests/cases/conformance/moduleResolution/main.ts'. ========", + "Module resolution kind is not specified, using 'NodeJs'.", + "Loading module 'ext/other' from 'node_modules' folder, target file type 'TypeScript'.", + "'package.json' has 'typesVersion['3.0']' field 'ts3.0' that references 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.0'.", + "Found 'package.json' at 'tests/cases/conformance/moduleResolution/node_modules/ext/package.json'. Package ID is 'ext/ts3.0/other/index.d.ts@1.0.0'.", + "File 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.0/other.ts' does not exist.", + "File 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.0/other.tsx' does not exist.", + "File 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.0/other.d.ts' does not exist.", + "Directory 'tests/cases/conformance/moduleResolution/node_modules/@types' does not exist, skipping all lookups in it.", + "Directory 'tests/cases/conformance/node_modules' does not exist, skipping all lookups in it.", + "Directory 'tests/cases/node_modules' does not exist, skipping all lookups in it.", + "Directory 'tests/node_modules' does not exist, skipping all lookups in it.", + "Directory 'node_modules' does not exist, skipping all lookups in it.", + "Directory '/node_modules' does not exist, skipping all lookups in it.", + "Loading module 'ext/other' from 'node_modules' folder, target file type 'JavaScript'.", + "'package.json' has 'typesVersion['3.0']' field 'ts3.0' that references 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.0'.", + "Found 'package.json' at 'tests/cases/conformance/moduleResolution/node_modules/ext/package.json'. Package ID is 'ext/ts3.0/other/index.d.ts@1.0.0'.", + "File 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.0/other.js' does not exist.", + "File 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.0/other.jsx' does not exist.", + "Directory 'tests/cases/conformance/node_modules' does not exist, skipping all lookups in it.", + "Directory 'tests/cases/node_modules' does not exist, skipping all lookups in it.", + "Directory 'tests/node_modules' does not exist, skipping all lookups in it.", + "Directory 'node_modules' does not exist, skipping all lookups in it.", + "Directory '/node_modules' does not exist, skipping all lookups in it.", + "======== Module name 'ext/other' was not resolved. ========" +] \ No newline at end of file diff --git a/tests/baselines/reference/typesVersions.ambientModules.types b/tests/baselines/reference/typesVersions.ambientModules.types new file mode 100644 index 00000000000..20cd4112ebe --- /dev/null +++ b/tests/baselines/reference/typesVersions.ambientModules.types @@ -0,0 +1,31 @@ +=== tests/cases/conformance/moduleResolution/main.ts === +import { a } from "ext"; +>a : "ts3.0 a" + +import { b } from "ext/other"; +>b : "ts3.0 b" + +const aa: "ts3.0 a" = a; +>aa : "ts3.0 a" +>a : "ts3.0 a" + +const bb: "ts3.0 b" = b; +>bb : "ts3.0 b" +>b : "ts3.0 b" + +=== tests/cases/conformance/moduleResolution/node_modules/ext/ts3.0/index.d.ts === +declare module "ext" { +>"ext" : typeof import("ext") + + export const a = "ts3.0 a"; +>a : "ts3.0 a" +>"ts3.0 a" : "ts3.0 a" +} +declare module "ext/other" { +>"ext/other" : typeof import("ext/other") + + export const b = "ts3.0 b"; +>b : "ts3.0 b" +>"ts3.0 b" : "ts3.0 b" +} + diff --git a/tests/baselines/reference/typesVersions.multiFile.js b/tests/baselines/reference/typesVersions.multiFile.js new file mode 100644 index 00000000000..98a1331500b --- /dev/null +++ b/tests/baselines/reference/typesVersions.multiFile.js @@ -0,0 +1,39 @@ +//// [tests/cases/conformance/moduleResolution/typesVersions.multiFile.ts] //// + +//// [package.json] +{ + "name": "ext", + "version": "1.0.0", + "types": "index", + "typesVersions": { + "3.0": "ts3.0" + } +} + +//// [index.d.ts] +export const a = "default a"; + +//// [other.d.ts] +export const b = "default b"; + +//// [index.d.ts] +export const a = "ts3.0 a"; + +//// [other.d.ts] +export const b = "ts3.0 b"; + +//// [main.ts] +import { a } from "ext"; +import { b } from "ext/other"; + +const aa: "ts3.0 a" = a; +const bb: "ts3.0 b" = b; + + +//// [main.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const ext_1 = require("ext"); +const other_1 = require("ext/other"); +const aa = ext_1.a; +const bb = other_1.b; diff --git a/tests/baselines/reference/typesVersions.multiFile.symbols b/tests/baselines/reference/typesVersions.multiFile.symbols new file mode 100644 index 00000000000..c79bb054609 --- /dev/null +++ b/tests/baselines/reference/typesVersions.multiFile.symbols @@ -0,0 +1,31 @@ +=== tests/cases/conformance/moduleResolution/node_modules/ext/index.d.ts === +export const a = "default a"; +>a : Symbol(a, Decl(index.d.ts, 0, 12)) + +=== tests/cases/conformance/moduleResolution/node_modules/ext/other.d.ts === +export const b = "default b"; +>b : Symbol(b, Decl(other.d.ts, 0, 12)) + +=== tests/cases/conformance/moduleResolution/node_modules/ext/ts3.0/index.d.ts === +export const a = "ts3.0 a"; +>a : Symbol(a, Decl(index.d.ts, 0, 12)) + +=== tests/cases/conformance/moduleResolution/node_modules/ext/ts3.0/other.d.ts === +export const b = "ts3.0 b"; +>b : Symbol(b, Decl(other.d.ts, 0, 12)) + +=== tests/cases/conformance/moduleResolution/main.ts === +import { a } from "ext"; +>a : Symbol(a, Decl(main.ts, 0, 8)) + +import { b } from "ext/other"; +>b : Symbol(b, Decl(main.ts, 1, 8)) + +const aa: "ts3.0 a" = a; +>aa : Symbol(aa, Decl(main.ts, 3, 5)) +>a : Symbol(a, Decl(main.ts, 0, 8)) + +const bb: "ts3.0 b" = b; +>bb : Symbol(bb, Decl(main.ts, 4, 5)) +>b : Symbol(b, Decl(main.ts, 1, 8)) + diff --git a/tests/baselines/reference/typesVersions.multiFile.trace.json b/tests/baselines/reference/typesVersions.multiFile.trace.json new file mode 100644 index 00000000000..0ef02bb8a02 --- /dev/null +++ b/tests/baselines/reference/typesVersions.multiFile.trace.json @@ -0,0 +1,31 @@ +[ + "======== Resolving module 'ext' from 'tests/cases/conformance/moduleResolution/main.ts'. ========", + "Module resolution kind is not specified, using 'NodeJs'.", + "Loading module 'ext' from 'node_modules' folder, target file type 'TypeScript'.", + "'package.json' has 'typesVersion['3.0']' field 'ts3.0' that references 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.0'.", + "'package.json' does not have a 'typings' field.", + "'package.json' has 'types' field 'index' that references 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.0/index'.", + "Found 'package.json' at 'tests/cases/conformance/moduleResolution/node_modules/ext/package.json'. Package ID is 'ext/ts3.0/index.d.ts@1.0.0'.", + "File 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.0.ts' does not exist.", + "File 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.0.tsx' does not exist.", + "File 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.0.d.ts' does not exist.", + "'package.json' does not have a 'typings' field.", + "'package.json' has 'types' field 'index' that references 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.0/index'.", + "File 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.0/index' does not exist.", + "Loading module as file / folder, candidate module location 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.0/index', target file type 'TypeScript'.", + "File 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.0/index.ts' does not exist.", + "File 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.0/index.tsx' does not exist.", + "File 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.0/index.d.ts' exist - use it as a name resolution result.", + "Resolving real path for 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.0/index.d.ts', result 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.0/index.d.ts'.", + "======== Module name 'ext' was successfully resolved to 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.0/index.d.ts'. ========", + "======== Resolving module 'ext/other' from 'tests/cases/conformance/moduleResolution/main.ts'. ========", + "Module resolution kind is not specified, using 'NodeJs'.", + "Loading module 'ext/other' from 'node_modules' folder, target file type 'TypeScript'.", + "'package.json' has 'typesVersion['3.0']' field 'ts3.0' that references 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.0'.", + "Found 'package.json' at 'tests/cases/conformance/moduleResolution/node_modules/ext/package.json'. Package ID is 'ext/ts3.0/other/index.d.ts@1.0.0'.", + "File 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.0/other.ts' does not exist.", + "File 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.0/other.tsx' does not exist.", + "File 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.0/other.d.ts' exist - use it as a name resolution result.", + "Resolving real path for 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.0/other.d.ts', result 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.0/other.d.ts'.", + "======== Module name 'ext/other' was successfully resolved to 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.0/other.d.ts'. ========" +] \ No newline at end of file diff --git a/tests/baselines/reference/typesVersions.multiFile.types b/tests/baselines/reference/typesVersions.multiFile.types new file mode 100644 index 00000000000..c0634803d29 --- /dev/null +++ b/tests/baselines/reference/typesVersions.multiFile.types @@ -0,0 +1,35 @@ +=== tests/cases/conformance/moduleResolution/node_modules/ext/index.d.ts === +export const a = "default a"; +>a : "default a" +>"default a" : "default a" + +=== tests/cases/conformance/moduleResolution/node_modules/ext/other.d.ts === +export const b = "default b"; +>b : "default b" +>"default b" : "default b" + +=== tests/cases/conformance/moduleResolution/node_modules/ext/ts3.0/index.d.ts === +export const a = "ts3.0 a"; +>a : "ts3.0 a" +>"ts3.0 a" : "ts3.0 a" + +=== tests/cases/conformance/moduleResolution/node_modules/ext/ts3.0/other.d.ts === +export const b = "ts3.0 b"; +>b : "ts3.0 b" +>"ts3.0 b" : "ts3.0 b" + +=== tests/cases/conformance/moduleResolution/main.ts === +import { a } from "ext"; +>a : "ts3.0 a" + +import { b } from "ext/other"; +>b : "ts3.0 b" + +const aa: "ts3.0 a" = a; +>aa : "ts3.0 a" +>a : "ts3.0 a" + +const bb: "ts3.0 b" = b; +>bb : "ts3.0 b" +>b : "ts3.0 b" + diff --git a/tests/baselines/reference/typingsLookup4.trace.json b/tests/baselines/reference/typingsLookup4.trace.json index 6cd025d099a..30d0122b8fd 100644 --- a/tests/baselines/reference/typingsLookup4.trace.json +++ b/tests/baselines/reference/typingsLookup4.trace.json @@ -5,6 +5,7 @@ "File '/node_modules/jquery.ts' does not exist.", "File '/node_modules/jquery.tsx' does not exist.", "File '/node_modules/jquery.d.ts' does not exist.", + "'package.json' does not have a 'typesVersions' field.", "'package.json' has 'typings' field 'jquery.d.ts' that references '/node_modules/@types/jquery/jquery.d.ts'.", "Found 'package.json' at '/node_modules/@types/jquery/package.json'.", "File '/node_modules/@types/jquery.d.ts' does not exist.", @@ -18,6 +19,7 @@ "File '/node_modules/kquery.ts' does not exist.", "File '/node_modules/kquery.tsx' does not exist.", "File '/node_modules/kquery.d.ts' does not exist.", + "'package.json' does not have a 'typesVersions' field.", "'package.json' has 'typings' field 'kquery' that references '/node_modules/@types/kquery/kquery'.", "Found 'package.json' at '/node_modules/@types/kquery/package.json'.", "File '/node_modules/@types/kquery.d.ts' does not exist.", @@ -35,6 +37,7 @@ "File '/node_modules/lquery.ts' does not exist.", "File '/node_modules/lquery.tsx' does not exist.", "File '/node_modules/lquery.d.ts' does not exist.", + "'package.json' does not have a 'typesVersions' field.", "'package.json' has 'typings' field 'lquery' that references '/node_modules/@types/lquery/lquery'.", "Found 'package.json' at '/node_modules/@types/lquery/package.json'.", "File '/node_modules/@types/lquery.d.ts' does not exist.", @@ -50,6 +53,7 @@ "File '/node_modules/mquery.ts' does not exist.", "File '/node_modules/mquery.tsx' does not exist.", "File '/node_modules/mquery.d.ts' does not exist.", + "'package.json' does not have a 'typesVersions' field.", "'package.json' has 'typings' field 'mquery' that references '/node_modules/@types/mquery/mquery'.", "Found 'package.json' at '/node_modules/@types/mquery/package.json'.", "File '/node_modules/@types/mquery.d.ts' does not exist.", @@ -65,6 +69,7 @@ "======== Module name 'mquery' was successfully resolved to '/node_modules/@types/mquery/mquery/index.tsx'. ========", "======== Resolving type reference directive 'jquery', containing file '/__inferred type names__.ts', root directory '/node_modules/@types'. ========", "Resolving with primary search path '/node_modules/@types'.", + "'package.json' does not have a 'typesVersions' field.", "'package.json' has 'typings' field 'jquery.d.ts' that references '/node_modules/@types/jquery/jquery.d.ts'.", "Found 'package.json' at '/node_modules/@types/jquery/package.json'.", "'package.json' has 'typings' field 'jquery.d.ts' that references '/node_modules/@types/jquery/jquery.d.ts'.", @@ -73,6 +78,7 @@ "======== Type reference directive 'jquery' was successfully resolved to '/node_modules/@types/jquery/jquery.d.ts', primary: true. ========", "======== Resolving type reference directive 'kquery', containing file '/__inferred type names__.ts', root directory '/node_modules/@types'. ========", "Resolving with primary search path '/node_modules/@types'.", + "'package.json' does not have a 'typesVersions' field.", "'package.json' has 'typings' field 'kquery' that references '/node_modules/@types/kquery/kquery'.", "Found 'package.json' at '/node_modules/@types/kquery/package.json'.", "'package.json' has 'typings' field 'kquery' that references '/node_modules/@types/kquery/kquery'.", @@ -85,6 +91,7 @@ "======== Type reference directive 'kquery' was successfully resolved to '/node_modules/@types/kquery/kquery.d.ts', primary: true. ========", "======== Resolving type reference directive 'lquery', containing file '/__inferred type names__.ts', root directory '/node_modules/@types'. ========", "Resolving with primary search path '/node_modules/@types'.", + "'package.json' does not have a 'typesVersions' field.", "'package.json' has 'typings' field 'lquery' that references '/node_modules/@types/lquery/lquery'.", "Found 'package.json' at '/node_modules/@types/lquery/package.json'.", "'package.json' has 'typings' field 'lquery' that references '/node_modules/@types/lquery/lquery'.", @@ -95,6 +102,7 @@ "======== Type reference directive 'lquery' was successfully resolved to '/node_modules/@types/lquery/lquery.ts', primary: true. ========", "======== Resolving type reference directive 'mquery', containing file '/__inferred type names__.ts', root directory '/node_modules/@types'. ========", "Resolving with primary search path '/node_modules/@types'.", + "'package.json' does not have a 'typesVersions' field.", "'package.json' has 'typings' field 'mquery' that references '/node_modules/@types/mquery/mquery'.", "Found 'package.json' at '/node_modules/@types/mquery/package.json'.", "'package.json' has 'typings' field 'mquery' that references '/node_modules/@types/mquery/mquery'.", diff --git a/tests/cases/conformance/moduleResolution/typesVersions.ambientModules.ts b/tests/cases/conformance/moduleResolution/typesVersions.ambientModules.ts new file mode 100644 index 00000000000..781740d96d2 --- /dev/null +++ b/tests/cases/conformance/moduleResolution/typesVersions.ambientModules.ts @@ -0,0 +1,39 @@ +// @traceResolution: true +// @target: esnext +// @module: commonjs +// @noImplicitReferences: true +// @filename: node_modules/ext/package.json +{ + "name": "ext", + "version": "1.0.0", + "types": "index", + "typesVersions": { + "3.0": "ts3.0" + } +} + +// @filename: node_modules/ext/index.d.ts +declare module "ext" { + export const a = "default a"; +} +declare module "ext/other" { + export const b = "default b"; +} + +// @filename: node_modules/ext/ts3.0/index.d.ts +declare module "ext" { + export const a = "ts3.0 a"; +} +declare module "ext/other" { + export const b = "ts3.0 b"; +} + +// @filename: main.ts +import { a } from "ext"; +import { b } from "ext/other"; + +const aa: "ts3.0 a" = a; +const bb: "ts3.0 b" = b; + +// @filename: tsconfig.json +{} \ No newline at end of file diff --git a/tests/cases/conformance/moduleResolution/typesVersions.multiFile.ts b/tests/cases/conformance/moduleResolution/typesVersions.multiFile.ts new file mode 100644 index 00000000000..44cf98e45c6 --- /dev/null +++ b/tests/cases/conformance/moduleResolution/typesVersions.multiFile.ts @@ -0,0 +1,34 @@ +// @traceResolution: true +// @target: esnext +// @module: commonjs +// @filename: node_modules/ext/package.json +{ + "name": "ext", + "version": "1.0.0", + "types": "index", + "typesVersions": { + "3.0": "ts3.0" + } +} + +// @filename: node_modules/ext/index.d.ts +export const a = "default a"; + +// @filename: node_modules/ext/other.d.ts +export const b = "default b"; + +// @filename: node_modules/ext/ts3.0/index.d.ts +export const a = "ts3.0 a"; + +// @filename: node_modules/ext/ts3.0/other.d.ts +export const b = "ts3.0 b"; + +// @filename: main.ts +import { a } from "ext"; +import { b } from "ext/other"; + +const aa: "ts3.0 a" = a; +const bb: "ts3.0 b" = b; + +// @filename: tsconfig.json +{} \ No newline at end of file