From 015babb6f7d8d6904bd31ff4da887d8f3ecd3855 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Fri, 17 Aug 2018 18:27:45 -0700 Subject: [PATCH 01/10] Initial support for 'typesVersions' --- src/compiler/checker.ts | 2 +- src/compiler/diagnosticMessages.json | 2 +- src/compiler/moduleNameResolver.ts | 152 +++++++++++------ src/compiler/moduleSpecifiers.ts | 2 +- src/compiler/semver.ts | 156 ++++++++++++++++++ src/compiler/tsconfig.json | 1 + src/compiler/utilities.ts | 21 +++ src/services/codefixes/fixCannotFindModule.ts | 2 +- src/services/pathCompletions.ts | 4 +- ...age_relativeImportWithinPackage.trace.json | 3 + ...ativeImportWithinPackage_scoped.trace.json | 3 + .../reference/library-reference-10.trace.json | 2 + .../reference/library-reference-11.trace.json | 1 + .../reference/library-reference-12.trace.json | 1 + .../reference/library-reference-2.trace.json | 2 + ...lutionWithExtensions_unexpected.trace.json | 2 + ...utionWithExtensions_unexpected2.trace.json | 2 + ...on_packageJson_notAtPackageRoot.trace.json | 1 + ...AtPackageRoot_fakeScopedPackage.trace.json | 1 + ...ution_packageJson_scopedPackage.trace.json | 1 + ...on_packageJson_yesAtPackageRoot.trace.json | 2 + ...AtPackageRoot_fakeScopedPackage.trace.json | 2 + ...ageRoot_mainFieldInSubDirectory.trace.json | 1 + .../reference/packageJsonMain.trace.json | 6 + .../packageJsonMain_isNonRecursive.trace.json | 2 + .../reference/typesVersions.ambientModules.js | 43 +++++ .../typesVersions.ambientModules.symbols | 29 ++++ .../typesVersions.ambientModules.trace.json | 46 ++++++ .../typesVersions.ambientModules.types | 31 ++++ .../reference/typesVersions.multiFile.js | 39 +++++ .../reference/typesVersions.multiFile.symbols | 31 ++++ .../typesVersions.multiFile.trace.json | 31 ++++ .../reference/typesVersions.multiFile.types | 35 ++++ .../reference/typingsLookup4.trace.json | 8 + .../typesVersions.ambientModules.ts | 39 +++++ .../typesVersions.multiFile.ts | 34 ++++ 36 files changed, 687 insertions(+), 53 deletions(-) create mode 100644 src/compiler/semver.ts create mode 100644 tests/baselines/reference/typesVersions.ambientModules.js create mode 100644 tests/baselines/reference/typesVersions.ambientModules.symbols create mode 100644 tests/baselines/reference/typesVersions.ambientModules.trace.json create mode 100644 tests/baselines/reference/typesVersions.ambientModules.types create mode 100644 tests/baselines/reference/typesVersions.multiFile.js create mode 100644 tests/baselines/reference/typesVersions.multiFile.symbols create mode 100644 tests/baselines/reference/typesVersions.multiFile.trace.json create mode 100644 tests/baselines/reference/typesVersions.multiFile.types create mode 100644 tests/cases/conformance/moduleResolution/typesVersions.ambientModules.ts create mode 100644 tests/cases/conformance/moduleResolution/typesVersions.multiFile.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 26b93b19335b4..f2f6ad93562ab 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 6000c48de4dc3..ed528e5b87e94 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 7fb308912c3fb..d1054579e8496 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; + } + + 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 result.config; + return; } - catch (e) { - // gracefully handle if readFile fails or returns not JSON - 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 8c695e10be258..696736048b1d4 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 0000000000000..a3c4e90d37a16 --- /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 20b97c1b7784a..2d3cbcf54fe67 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 33dfd2617c979..e7eb352da84d4 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 68fa3a5c0305b..6822cae79115b 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 8ab7cc315ad9e..3a546573db725 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 d75683d210f83..dbf67e3802c2a 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 7b07ecd66e49d..d3d3dfac06411 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 ad34c0b1dc3fe..d24bc21f28323 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 be260b6bc6e2c..5b2d6695356b6 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 26361703708dc..f6c1aef48114c 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 649189fbbdda3..baef46d89952c 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 60cdab44a29fc..2f743d9e200e8 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 bab6be18d397f..0661025355823 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 3473f33c1f258..2a4a1e71a4a9e 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 07dc908b74517..b54519397ab32 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 77ea6a244c1a5..389bd892d2fdc 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 453f5c088a308..873805b8b5765 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 b84bac8993a0e..95beae1393e75 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 849b65ee59ff6..84b7a4873c0ca 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 06c8cff66431b..583fc96774e56 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 a2878a2a4fed5..b7d26d0f85258 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 0000000000000..c7f198b8467b3 --- /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 0000000000000..d8a0ab0f2ca6e --- /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 0000000000000..990834accc2ee --- /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 0000000000000..20cd4112ebef2 --- /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 0000000000000..98a1331500b4f --- /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 0000000000000..c79bb054609a7 --- /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 0000000000000..0ef02bb8a026c --- /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 0000000000000..c0634803d2937 --- /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 6cd025d099afd..30d0122b8fde2 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 0000000000000..781740d96d212 --- /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 0000000000000..44cf98e45c61a --- /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 From 6f7a37c99aa43267f2aae4ade4db840fc344035d Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Mon, 20 Aug 2018 17:44:34 -0700 Subject: [PATCH 02/10] Added fourslash test --- src/compiler/moduleNameResolver.ts | 46 ++++++++++--------- src/services/pathCompletions.ts | 28 ++++++++++- ...tionForStringLiteralNonrelativeImport13.ts | 36 +++++++++++++++ 3 files changed, 88 insertions(+), 22 deletions(-) create mode 100644 tests/cases/fourslash/completionForStringLiteralNonrelativeImport13.ts diff --git a/src/compiler/moduleNameResolver.ts b/src/compiler/moduleNameResolver.ts index d1054579e8496..c474226217e10 100644 --- a/src/compiler/moduleNameResolver.ts +++ b/src/compiler/moduleNameResolver.ts @@ -125,22 +125,8 @@ namespace ts { } } - 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; - } - - 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; - } - + /* @internal */ + export function getPackageJsonTypesVersionsOverride(typesVersions: MapLike) { const typeScriptVersion = Version.parse(version); let bestVersion: Version | undefined; let bestVersionKey: string | undefined; @@ -149,9 +135,6 @@ namespace ts { const keyVersion = Version.tryParse(key); if (keyVersion === undefined) { - if (state.traceEnabled) { - // TODO(rbuckton): log - } continue; } @@ -164,13 +147,34 @@ namespace ts { } if (!bestVersionKey) { + return; + } + + return { version: bestVersionKey, directory: typesVersions[bestVersionKey] }; + } + + function tryReadPackageJsonTypesVersion(jsonContent: PackageJson, baseDirectory: string, state: ModuleResolutionState): string | undefined { + if (!hasProperty(jsonContent, "typesVersions")) { if (state.traceEnabled) { - // TODO(rbuckton): log + trace(state.host, Diagnostics.package_json_does_not_have_a_0_field, "typesVersions"); } return; } - const bestVersionPath = typesVersions[bestVersionKey]; + 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 result = getPackageJsonTypesVersionsOverride(typesVersions); + if (!result) { + return undefined; + } + + const { version: bestVersionKey, directory: bestVersionPath } = result; 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); diff --git a/src/services/pathCompletions.ts b/src/services/pathCompletions.ts index 3a546573db725..f958163bb1497 100644 --- a/src/services/pathCompletions.ts +++ b/src/services/pathCompletions.ts @@ -107,10 +107,24 @@ namespace ts.Completions.PathCompletions { // const absolutePath = normalizeAndPreserveTrailingSlash(isRootedDiskPath(fragment) ? fragment : combinePaths(scriptPath, fragment)); // TODO(rbuckton): should use resolvePaths const absolutePath = resolvePath(scriptPath, fragment); - const baseDirectory = hasTrailingDirectorySeparator(absolutePath) ? absolutePath : getDirectoryPath(absolutePath); + let baseDirectory = hasTrailingDirectorySeparator(absolutePath) ? absolutePath : getDirectoryPath(absolutePath); const ignoreCase = !(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames()); if (tryDirectoryExists(host, baseDirectory)) { + // check for a version redirect + const packageJsonPath = findPackageJson(baseDirectory, host); + if (packageJsonPath) { + const packageJson = readJson(packageJsonPath, host as { readFile: (filename: string) => string | undefined }); + const typesVersions = (packageJson as any).typesVersions; + if (typeof typesVersions === "object") { + const result = getPackageJsonTypesVersionsOverride(typesVersions); + const versionPath = result && result.directory; + if (versionPath) { + baseDirectory = resolvePath(baseDirectory, versionPath); + } + } + } + // Enumerate the available files if possible const files = tryReadDirectory(host, baseDirectory, extensions, /*exclude*/ undefined, /*include*/ ["./*"]); @@ -390,6 +404,18 @@ namespace ts.Completions.PathCompletions { return paths; } + function findPackageJson(directory: string, host: LanguageServiceHost): string | undefined { + let packageJson: string | undefined; + forEachAncestorDirectory(directory, ancestor => { + if (ancestor === "node_modules") return true; + packageJson = findConfigFile(ancestor, (f) => tryFileExists(host, f), "package.json"); + if (packageJson) { + return true; // break out + } + }); + return packageJson; + } + function enumerateNodeModulesVisibleToScript(host: LanguageServiceHost, scriptPath: string): ReadonlyArray { if (!host.readFile || !host.fileExists) return emptyArray; diff --git a/tests/cases/fourslash/completionForStringLiteralNonrelativeImport13.ts b/tests/cases/fourslash/completionForStringLiteralNonrelativeImport13.ts new file mode 100644 index 0000000000000..db88a272ad5eb --- /dev/null +++ b/tests/cases/fourslash/completionForStringLiteralNonrelativeImport13.ts @@ -0,0 +1,36 @@ +/// + +// Should give completions based on typesVersions + +// @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 {}; + +// @Filename: node_modules/ext/aaa.d.ts +//// export {}; + +// @Filename: node_modules/ext/ts3.0/index.d.ts +//// export {}; + +// @Filename: node_modules/ext/ts3.0/zzz.d.ts +//// export {}; + +// @Filename: main.ts +//// import * as ext1 from "ext//*import_as0*/ +//// import ext2 = require("ext//*import_equals0*/ +//// var ext2 = require("ext//*require0*/ + +verify.completions({ + marker: test.markerNames(), + exact: ["index", "zzz"], + isNewIdentifierLocation: true, +}); From 8398a87da77e3cd7aaf5e4dfbac5167cf69d51fc Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Mon, 20 Aug 2018 17:50:28 -0700 Subject: [PATCH 03/10] Base version test on 'versionMajorMinor' --- src/compiler/moduleNameResolver.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/moduleNameResolver.ts b/src/compiler/moduleNameResolver.ts index c474226217e10..bd532e6dd0187 100644 --- a/src/compiler/moduleNameResolver.ts +++ b/src/compiler/moduleNameResolver.ts @@ -127,7 +127,7 @@ namespace ts { /* @internal */ export function getPackageJsonTypesVersionsOverride(typesVersions: MapLike) { - const typeScriptVersion = Version.parse(version); + const typeScriptVersion = Version.parse(versionMajorMinor); let bestVersion: Version | undefined; let bestVersionKey: string | undefined; for (const key in typesVersions) { From aa04ef5ce7580c7d16167ca7cc9023ae370ef4e9 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Mon, 20 Aug 2018 20:49:52 -0700 Subject: [PATCH 04/10] Adjust subModuleName --- src/compiler/moduleNameResolver.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/compiler/moduleNameResolver.ts b/src/compiler/moduleNameResolver.ts index bd532e6dd0187..21ff919872b84 100644 --- a/src/compiler/moduleNameResolver.ts +++ b/src/compiler/moduleNameResolver.ts @@ -934,7 +934,7 @@ namespace ts { if (endsWith(path, ".d.ts")) { return path; } - if (endsWith(path, "/index")) { + if (path === "index" || endsWith(path, "/index")) { return path + ".d.ts"; } return path + "/index.d.ts"; @@ -1069,9 +1069,9 @@ namespace ts { } } - // if (versionPath) { - // subModuleName = combinePaths(versionPath, subModuleName); - // } + if (versionPath) { + subModuleName = combinePaths(versionPath, subModuleName); + } if (!endsWith(subModuleName, Extension.Dts)) { subModuleName = addExtensionAndIndex(subModuleName); From b9afdadf71d76512183c7470159f34c49e545702 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Wed, 22 Aug 2018 11:22:09 -0700 Subject: [PATCH 05/10] Remove jsTypings/semver.ts, add unit tests and logging --- src/compiler/diagnosticMessages.json | 8 ++ src/compiler/moduleNameResolver.ts | 27 +++- src/compiler/semver.ts | 125 +++++++++--------- src/jsTyping/jsTyping.ts | 6 +- src/jsTyping/semver.ts | 61 --------- src/jsTyping/tsconfig.json | 3 +- src/testRunner/tsconfig.json | 1 + src/testRunner/unittests/semver.ts | 94 +++++++++++++ src/testRunner/unittests/typingsInstaller.ts | 14 +- src/typingsInstallerCore/typingsInstaller.ts | 9 +- .../typesVersions.ambientModules.trace.json | 6 +- .../typesVersions.multiFile.trace.json | 4 +- 12 files changed, 207 insertions(+), 151 deletions(-) delete mode 100644 src/jsTyping/semver.ts create mode 100644 src/testRunner/unittests/semver.ts diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index ed528e5b87e94..ebe5c3efbcd5e 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -3671,6 +3671,14 @@ "category": "Error", "code": 6205 }, + "'package.json' has invalid version '{0}' in 'typesVersions' field.": { + "category": "Message", + "code": 6206 + }, + "'package.json' does not have a 'typesVersions' entry that matches version '{0}'.": { + "category": "Message", + "code": 6207 + }, "Projects to reference": { "category": "Message", diff --git a/src/compiler/moduleNameResolver.ts b/src/compiler/moduleNameResolver.ts index 21ff919872b84..3b61c2cd83b0e 100644 --- a/src/compiler/moduleNameResolver.ts +++ b/src/compiler/moduleNameResolver.ts @@ -127,7 +127,14 @@ namespace ts { /* @internal */ export function getPackageJsonTypesVersionsOverride(typesVersions: MapLike) { - const typeScriptVersion = Version.parse(versionMajorMinor); + return getPackageJsonTypesVersionsOverrideWithTrace(typesVersions, /*state*/ undefined); + } + + let typeScriptVersion: Version | undefined; + + function getPackageJsonTypesVersionsOverrideWithTrace(typesVersions: MapLike, state: ModuleResolutionState | undefined) { + if (!typeScriptVersion) typeScriptVersion = new Version(versionMajorMinor); + let bestVersion: Version | undefined; let bestVersionKey: string | undefined; for (const key in typesVersions) { @@ -135,12 +142,15 @@ namespace ts { const keyVersion = Version.tryParse(key); if (keyVersion === undefined) { + if (state && state.traceEnabled) { + trace(state.host, Diagnostics.package_json_has_invalid_version_0_in_typesVersions_field, key); + } continue; } // match the greatest version less than the current TypeScript version - if (keyVersion.compareTo(typeScriptVersion) <= 0 - && (bestVersion === undefined || keyVersion.compareTo(bestVersion) > 0)) { + if (keyVersion.compareTo(bestVersion) > 0 && + keyVersion.compareTo(typeScriptVersion) <= 0) { bestVersion = keyVersion; bestVersionKey = key; } @@ -169,22 +179,25 @@ namespace ts { return; } - const result = getPackageJsonTypesVersionsOverride(typesVersions); + const result = getPackageJsonTypesVersionsOverrideWithTrace(typesVersions, state); if (!result) { - return undefined; + if (state.traceEnabled) { + trace(state.host, Diagnostics.package_json_does_not_have_a_typesVersions_entry_that_matches_version_0, versionMajorMinor); + } + return; } const { version: bestVersionKey, directory: bestVersionPath } = result; 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); + trace(state.host, Diagnostics.Expected_type_of_0_field_in_package_json_to_be_1_got_2, `typesVersions['${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); + trace(state.host, Diagnostics.package_json_has_0_field_1_that_references_2, `typesVersions['${bestVersionKey}']`, bestVersionPath, path); } return bestVersionPath; diff --git a/src/compiler/semver.ts b/src/compiler/semver.ts index a3c4e90d37a16..203739f7c957d 100644 --- a/src/compiler/semver.ts +++ b/src/compiler/semver.ts @@ -1,48 +1,49 @@ /* @internal */ namespace ts { - // Per https://semver.org/#spec-item-2: - // + // 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; + 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: - // + // 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: - // + // 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: - // + // 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 + * Describes a precise semantic version number, 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 = "") { + constructor(text: string); + constructor(major: number, minor?: number, patch?: number, prerelease?: string, build?: string); + constructor(major: number | string, minor = 0, patch = 0, prerelease = "", build = "") { + if (typeof major === "string") { + const result = Debug.assertDefined(tryParseComponents(major), "Invalid version"); + ({ major, minor, patch, prerelease, build } = result); + } + Debug.assert(major >= 0, "Invalid argument: major"); Debug.assert(minor >= 0, "Invalid argument: minor"); Debug.assert(patch >= 0, "Invalid argument: patch"); @@ -51,104 +52,102 @@ namespace ts { 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)); + this.prerelease = prerelease ? prerelease.split(".") : emptyArray; + this.build = build ? build.split(".") : emptyArray; } static tryParse(text: string) { - const match = versionRegExp.exec(text); - if (!match) return undefined; + const result = tryParseComponents(text); + if (!result) 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); + const { major, minor, patch, prerelease, build } = result; + 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: - // + compareTo(other: Version | undefined) { + // 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. + // 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 [...] // - // 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); + // https://semver.org/#spec-item-11 + // > Build metadata does not figure into precedence + if (this === other) return Comparison.EqualTo; + if (other === undefined) return Comparison.GreaterThan; + return compareValues(this.major, other.major) + || compareValues(this.minor, other.minor) + || compareValues(this.patch, other.patch) + || comparePrerelaseIdentifiers(this.prerelease, other.prerelease); } toString() { let result = `${this.major}.${this.minor}.${this.patch}`; - if (this.prerelease) result += `-${this.prerelease.join(".")}`; - if (this.build) result += `+${this.build.join(".")}`; + if (some(this.prerelease)) result += `-${this.prerelease.join(".")}`; + if (some(this.build)) result += `+${this.build.join(".")}`; return result; } } - function compareVersionFragments(left: ReadonlyArray, right: ReadonlyArray, compareNumericIdentifiers: boolean) { - // Per https://semver.org/#spec-item-11: - // + function tryParseComponents(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 { + major: parseInt(major, 10), + minor: parseInt(minor, 10), + patch: parseInt(patch, 10), + prerelease, + build + }; + } + + function comparePrerelaseIdentifiers(left: ReadonlyArray, right: ReadonlyArray) { + // 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: - // + // 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 + // > 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); + const leftIsNumeric = numericIdentifierRegExp.test(leftIdentifier); + const rightIsNumeric = numericIdentifierRegExp.test(rightIdentifier); if (leftIsNumeric || rightIsNumeric) { - // Per https://semver.org/#spec-item-11: - // + // 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: - // + // 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: - // + // 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: - // + // 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); diff --git a/src/jsTyping/jsTyping.ts b/src/jsTyping/jsTyping.ts index e9c96ba2bf614..db55ce4993b5c 100644 --- a/src/jsTyping/jsTyping.ts +++ b/src/jsTyping/jsTyping.ts @@ -21,13 +21,13 @@ namespace ts.JsTyping { export interface CachedTyping { typingLocation: string; - version: Semver; + version: Version; } /* @internal */ export function isTypingUpToDate(cachedTyping: CachedTyping, availableTypingVersions: MapLike) { - const availableVersion = Semver.parse(getProperty(availableTypingVersions, `ts${versionMajorMinor}`) || getProperty(availableTypingVersions, "latest")!); - return !availableVersion.greaterThan(cachedTyping.version); + const availableVersion = new Version(getProperty(availableTypingVersions, `ts${versionMajorMinor}`) || getProperty(availableTypingVersions, "latest")!); + return availableVersion.compareTo(cachedTyping.version) <= 0; } /* @internal */ diff --git a/src/jsTyping/semver.ts b/src/jsTyping/semver.ts deleted file mode 100644 index 1c58da8c8f7a7..0000000000000 --- a/src/jsTyping/semver.ts +++ /dev/null @@ -1,61 +0,0 @@ -/* @internal */ -namespace ts { - function stringToInt(str: string): number { - const n = parseInt(str, 10); - if (isNaN(n)) { - throw new Error(`Error in parseInt(${JSON.stringify(str)})`); - } - return n; - } - - const isPrereleaseRegex = /^(.*)-next.\d+/; - const prereleaseSemverRegex = /^(\d+)\.(\d+)\.0-next.(\d+)$/; - const semverRegex = /^(\d+)\.(\d+)\.(\d+)$/; - - export class Semver { - static parse(semver: string): Semver { - const isPrerelease = isPrereleaseRegex.test(semver); - const result = Semver.tryParse(semver, isPrerelease); - if (!result) { - throw new Error(`Unexpected semver: ${semver} (isPrerelease: ${isPrerelease})`); - } - return result; - } - - static fromRaw({ major, minor, patch, isPrerelease }: Semver): Semver { - return new Semver(major, minor, patch, isPrerelease); - } - - // This must parse the output of `versionString`. - private static tryParse(semver: string, isPrerelease: boolean): Semver | undefined { - // Per the semver spec : - // "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." - const rgx = isPrerelease ? prereleaseSemverRegex : semverRegex; - const match = rgx.exec(semver); - return match ? new Semver(stringToInt(match[1]), stringToInt(match[2]), stringToInt(match[3]), isPrerelease) : undefined; - } - - private constructor( - readonly major: number, readonly minor: number, readonly patch: number, - /** - * If true, this is `major.minor.0-next.patch`. - * If false, this is `major.minor.patch`. - */ - readonly isPrerelease: boolean) { } - - get versionString(): string { - return this.isPrerelease ? `${this.major}.${this.minor}.0-next.${this.patch}` : `${this.major}.${this.minor}.${this.patch}`; - } - - equals(sem: Semver): boolean { - return this.major === sem.major && this.minor === sem.minor && this.patch === sem.patch && this.isPrerelease === sem.isPrerelease; - } - - greaterThan(sem: Semver): boolean { - return this.major > sem.major || this.major === sem.major - && (this.minor > sem.minor || this.minor === sem.minor - && (!this.isPrerelease && sem.isPrerelease || this.isPrerelease === sem.isPrerelease - && this.patch > sem.patch)); - } - } -} \ No newline at end of file diff --git a/src/jsTyping/tsconfig.json b/src/jsTyping/tsconfig.json index 4886463e16382..ac5b8b19c2920 100644 --- a/src/jsTyping/tsconfig.json +++ b/src/jsTyping/tsconfig.json @@ -16,7 +16,6 @@ "files": [ "shared.ts", "types.ts", - "jsTyping.ts", - "semver.ts" + "jsTyping.ts" ] } diff --git a/src/testRunner/tsconfig.json b/src/testRunner/tsconfig.json index 12c671f9cf09b..744a62811e5cb 100644 --- a/src/testRunner/tsconfig.json +++ b/src/testRunner/tsconfig.json @@ -73,6 +73,7 @@ "unittests/publicApi.ts", "unittests/reuseProgramStructure.ts", "unittests/session.ts", + "unittests/semver.ts", "unittests/symbolWalker.ts", "unittests/telemetry.ts", "unittests/textChanges.ts", diff --git a/src/testRunner/unittests/semver.ts b/src/testRunner/unittests/semver.ts new file mode 100644 index 0000000000000..edc888e1075ad --- /dev/null +++ b/src/testRunner/unittests/semver.ts @@ -0,0 +1,94 @@ +namespace ts { + describe("semver", () => { + describe("Version", () => { + function assertVersion(version: Version, [major, minor, patch, prerelease, build]: [number, number, number, string[]?, string[]?]) { + assert.strictEqual(version.major, major); + assert.strictEqual(version.minor, minor); + assert.strictEqual(version.patch, patch); + assert.deepEqual(version.prerelease, prerelease || emptyArray); + assert.deepEqual(version.build, build || emptyArray); + } + describe("new", () => { + it("text", () => { + assertVersion(new Version("1.2.3-pre.4+build.5"), [1, 2, 3, ["pre", "4"], ["build", "5"]]); + }); + it("parts", () => { + assertVersion(new Version(1, 2, 3, "pre.4", "build.5"), [1, 2, 3, ["pre", "4"], ["build", "5"]]); + assertVersion(new Version(1, 2, 3), [1, 2, 3]); + assertVersion(new Version(1, 2), [1, 2, 0]); + assertVersion(new Version(1), [1, 0, 0]); + }); + }); + it("toString", () => { + assert.strictEqual(new Version(1, 2, 3, "pre.4", "build.5").toString(), "1.2.3-pre.4+build.5"); + assert.strictEqual(new Version(1, 2, 3, "pre.4").toString(), "1.2.3-pre.4"); + assert.strictEqual(new Version(1, 2, 3, /*prerelease*/ undefined, "build.5").toString(), "1.2.3+build.5"); + assert.strictEqual(new Version(1, 2, 3).toString(), "1.2.3"); + assert.strictEqual(new Version(1, 2).toString(), "1.2.0"); + assert.strictEqual(new Version(1).toString(), "1.0.0"); + }); + it("compareTo", () => { + // 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. + assert.strictEqual(new Version("1.0.0").compareTo(new Version("2.0.0")), Comparison.LessThan); + assert.strictEqual(new Version("1.0.0").compareTo(new Version("1.1.0")), Comparison.LessThan); + assert.strictEqual(new Version("1.0.0").compareTo(new Version("1.0.1")), Comparison.LessThan); + assert.strictEqual(new Version("2.0.0").compareTo(new Version("1.0.0")), Comparison.GreaterThan); + assert.strictEqual(new Version("1.1.0").compareTo(new Version("1.0.0")), Comparison.GreaterThan); + assert.strictEqual(new Version("1.0.1").compareTo(new Version("1.0.0")), Comparison.GreaterThan); + assert.strictEqual(new Version("1.0.0").compareTo(new Version("1.0.0")), Comparison.EqualTo); + + // https://semver.org/#spec-item-11 + // > When major, minor, and patch are equal, a pre-release version has lower + // > precedence than a normal version. + assert.strictEqual(new Version("1.0.0").compareTo(new Version("1.0.0-pre")), Comparison.GreaterThan); + assert.strictEqual(new Version("1.0.1-pre").compareTo(new Version("1.0.0")), Comparison.GreaterThan); + assert.strictEqual(new Version("1.0.0-pre").compareTo(new Version("1.0.0")), Comparison.LessThan); + + // https://semver.org/#spec-item-11 + // > identifiers consisting of only digits are compared numerically + assert.strictEqual(new Version("1.0.0-0").compareTo(new Version("1.0.0-1")), Comparison.LessThan); + assert.strictEqual(new Version("1.0.0-1").compareTo(new Version("1.0.0-0")), Comparison.GreaterThan); + assert.strictEqual(new Version("1.0.0-2").compareTo(new Version("1.0.0-10")), Comparison.LessThan); + assert.strictEqual(new Version("1.0.0-10").compareTo(new Version("1.0.0-2")), Comparison.GreaterThan); + assert.strictEqual(new Version("1.0.0-0").compareTo(new Version("1.0.0-0")), Comparison.EqualTo); + + // https://semver.org/#spec-item-11 + // > identifiers with letters or hyphens are compared lexically in ASCII sort order. + assert.strictEqual(new Version("1.0.0-a").compareTo(new Version("1.0.0-b")), Comparison.LessThan); + assert.strictEqual(new Version("1.0.0-a-2").compareTo(new Version("1.0.0-a-10")), Comparison.GreaterThan); + assert.strictEqual(new Version("1.0.0-b").compareTo(new Version("1.0.0-a")), Comparison.GreaterThan); + assert.strictEqual(new Version("1.0.0-a").compareTo(new Version("1.0.0-a")), Comparison.EqualTo); + assert.strictEqual(new Version("1.0.0-A").compareTo(new Version("1.0.0-a")), Comparison.LessThan); + + // https://semver.org/#spec-item-11 + // > Numeric identifiers always have lower precedence than non-numeric identifiers. + assert.strictEqual(new Version("1.0.0-0").compareTo(new Version("1.0.0-alpha")), Comparison.LessThan); + assert.strictEqual(new Version("1.0.0-alpha").compareTo(new Version("1.0.0-0")), Comparison.GreaterThan); + assert.strictEqual(new Version("1.0.0-0").compareTo(new Version("1.0.0-0")), Comparison.EqualTo); + assert.strictEqual(new Version("1.0.0-alpha").compareTo(new Version("1.0.0-alpha")), Comparison.EqualTo); + + // 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. + assert.strictEqual(new Version("1.0.0-alpha").compareTo(new Version("1.0.0-alpha.0")), Comparison.LessThan); + assert.strictEqual(new Version("1.0.0-alpha.0").compareTo(new Version("1.0.0-alpha")), Comparison.GreaterThan); + + // 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 [...] + assert.strictEqual(new Version("1.0.0-a.0.b.1").compareTo(new Version("1.0.0-a.0.b.2")), Comparison.LessThan); + assert.strictEqual(new Version("1.0.0-a.0.b.1").compareTo(new Version("1.0.0-b.0.a.1")), Comparison.LessThan); + assert.strictEqual(new Version("1.0.0-a.0.b.2").compareTo(new Version("1.0.0-a.0.b.1")), Comparison.GreaterThan); + assert.strictEqual(new Version("1.0.0-b.0.a.1").compareTo(new Version("1.0.0-a.0.b.1")), Comparison.GreaterThan); + + // https://semver.org/#spec-item-11 + // > Build metadata does not figure into precedence + assert.strictEqual(new Version("1.0.0+build").compareTo(new Version("1.0.0")), Comparison.EqualTo); + }); + }); + }); +} \ No newline at end of file diff --git a/src/testRunner/unittests/typingsInstaller.ts b/src/testRunner/unittests/typingsInstaller.ts index 6a7e76e15dea0..a718a12f5484f 100644 --- a/src/testRunner/unittests/typingsInstaller.ts +++ b/src/testRunner/unittests/typingsInstaller.ts @@ -1322,7 +1322,7 @@ namespace ts.projectSystem { content: "" }; const host = createServerHost([f, node]); - const cache = createMapFromTemplate({ node: { typingLocation: node.path, version: Semver.parse("1.3.0") } }); + const cache = createMapFromTemplate({ node: { typingLocation: node.path, version: new Version("1.3.0") } }); const registry = createTypesRegistry("node"); const logger = trackingLogger(); const result = JsTyping.discoverTypings(host, logger.log, [f.path], getDirectoryPath(f.path), emptySafeList, cache, { enable: true }, ["fs", "bar"], registry); @@ -1344,7 +1344,7 @@ namespace ts.projectSystem { content: "" }; const host = createServerHost([f, node]); - const cache = createMapFromTemplate({ node: { typingLocation: node.path, version: Semver.parse("1.3.0") } }); + const cache = createMapFromTemplate({ node: { typingLocation: node.path, version: new Version("1.3.0") } }); const logger = trackingLogger(); const result = JsTyping.discoverTypings(host, logger.log, [f.path], getDirectoryPath(f.path), emptySafeList, cache, { enable: true }, ["fs", "bar"], emptyMap); assert.deepEqual(logger.finish(), [ @@ -1401,8 +1401,8 @@ namespace ts.projectSystem { }; const host = createServerHost([app]); const cache = createMapFromTemplate({ - node: { typingLocation: node.path, version: Semver.parse("1.3.0") }, - commander: { typingLocation: commander.path, version: Semver.parse("1.0.0") } + node: { typingLocation: node.path, version: new Version("1.3.0") }, + commander: { typingLocation: commander.path, version: new Version("1.0.0") } }); const registry = createTypesRegistry("node", "commander"); const logger = trackingLogger(); @@ -1427,7 +1427,7 @@ namespace ts.projectSystem { }; const host = createServerHost([app]); const cache = createMapFromTemplate({ - node: { typingLocation: node.path, version: Semver.parse("1.0.0") } + node: { typingLocation: node.path, version: new Version("1.0.0") } }); const registry = createTypesRegistry("node"); registry.delete(`ts${versionMajorMinor}`); @@ -1458,8 +1458,8 @@ namespace ts.projectSystem { }; const host = createServerHost([app]); const cache = createMapFromTemplate({ - node: { typingLocation: node.path, version: Semver.parse("1.3.0-next.0") }, - commander: { typingLocation: commander.path, version: Semver.parse("1.3.0-next.0") } + node: { typingLocation: node.path, version: new Version("1.3.0-next.0") }, + commander: { typingLocation: commander.path, version: new Version("1.3.0-next.0") } }); const registry = createTypesRegistry("node", "commander"); registry.get("node")![`ts${versionMajorMinor}`] = "1.3.0-next.1"; diff --git a/src/typingsInstallerCore/typingsInstaller.ts b/src/typingsInstallerCore/typingsInstaller.ts index 44a51a01779f9..df83f1a677c39 100644 --- a/src/typingsInstallerCore/typingsInstaller.ts +++ b/src/typingsInstallerCore/typingsInstaller.ts @@ -252,8 +252,11 @@ namespace ts.server.typingsInstaller { } const info = getProperty(npmLock.dependencies, key); const version = info && info.version; - const semver = Semver.parse(version!); // TODO: GH#18217 - const newTyping: JsTyping.CachedTyping = { typingLocation: typingFile, version: semver }; + if (!version) { + continue; + } + + const newTyping: JsTyping.CachedTyping = { typingLocation: typingFile, version: new Version(version) }; this.packageNameToTypingLocation.set(packageName, newTyping); } } @@ -356,7 +359,7 @@ namespace ts.server.typingsInstaller { // packageName is guaranteed to exist in typesRegistry by filterTypings const distTags = this.typesRegistry.get(packageName)!; - const newVersion = Semver.parse(distTags[`ts${versionMajorMinor}`] || distTags[this.latestDistTag]); + const newVersion = new Version(distTags[`ts${versionMajorMinor}`] || distTags[this.latestDistTag]); const newTyping: JsTyping.CachedTyping = { typingLocation: typingFile, version: newVersion }; this.packageNameToTypingLocation.set(packageName, newTyping); installedTypingFiles.push(typingFile); diff --git a/tests/baselines/reference/typesVersions.ambientModules.trace.json b/tests/baselines/reference/typesVersions.ambientModules.trace.json index 990834accc2ee..0bf8bc16c5d27 100644 --- a/tests/baselines/reference/typesVersions.ambientModules.trace.json +++ b/tests/baselines/reference/typesVersions.ambientModules.trace.json @@ -2,7 +2,7 @@ "======== 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' has 'typesVersions['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'.", @@ -21,7 +21,7 @@ "======== 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'.", + "'package.json' has 'typesVersions['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.", @@ -33,7 +33,7 @@ "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'.", + "'package.json' has 'typesVersions['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.", diff --git a/tests/baselines/reference/typesVersions.multiFile.trace.json b/tests/baselines/reference/typesVersions.multiFile.trace.json index 0ef02bb8a026c..2508681421b5c 100644 --- a/tests/baselines/reference/typesVersions.multiFile.trace.json +++ b/tests/baselines/reference/typesVersions.multiFile.trace.json @@ -2,7 +2,7 @@ "======== 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' has 'typesVersions['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'.", @@ -21,7 +21,7 @@ "======== 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'.", + "'package.json' has 'typesVersions['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.", From dc5cd9676bfe36cf2e68cb7ce63f3662acc5dc06 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Mon, 27 Aug 2018 12:06:45 -0700 Subject: [PATCH 06/10] Switch to paths-like pattern matching --- src/compiler/diagnosticMessages.json | 6 +- src/compiler/moduleNameResolver.ts | 543 ++++++++++-------- src/compiler/moduleSpecifiers.ts | 40 +- src/compiler/transformers/declarations.ts | 7 + src/services/pathCompletions.ts | 63 +- ...age_relativeImportWithinPackage.trace.json | 2 +- ...ativeImportWithinPackage_scoped.trace.json | 2 +- .../reference/library-reference-10.trace.json | 6 +- .../reference/library-reference-11.trace.json | 2 +- .../reference/library-reference-12.trace.json | 2 +- .../reference/library-reference-2.trace.json | 6 +- ...lutionWithExtensions_unexpected.trace.json | 4 +- ...utionWithExtensions_unexpected2.trace.json | 4 +- ...on_packageJson_notAtPackageRoot.trace.json | 2 +- ...AtPackageRoot_fakeScopedPackage.trace.json | 2 +- ...ution_packageJson_scopedPackage.trace.json | 2 +- ...ageRoot_mainFieldInSubDirectory.trace.json | 2 +- .../reference/packageJsonMain.trace.json | 12 +- .../packageJsonMain_isNonRecursive.trace.json | 4 +- ...eactTransitiveImportHasValidDeclaration.js | 1 - .../reference/typesVersions.ambientModules.js | 2 +- .../typesVersions.ambientModules.trace.json | 31 +- .../reference/typesVersions.multiFile.js | 2 +- .../typesVersions.multiFile.trace.json | 24 +- .../typesVersionsDeclarationEmit.ambient.js | 51 ++ ...pesVersionsDeclarationEmit.ambient.symbols | 37 ++ ...VersionsDeclarationEmit.ambient.trace.json | 55 ++ ...typesVersionsDeclarationEmit.ambient.types | 33 ++ .../typesVersionsDeclarationEmit.multiFile.js | 48 ++ ...sVersionsDeclarationEmit.multiFile.symbols | 47 ++ ...rsionsDeclarationEmit.multiFile.trace.json | 37 ++ ...pesVersionsDeclarationEmit.multiFile.types | 37 ++ .../reference/typingsLookup4.trace.json | 20 +- .../typesVersionsDeclarationEmit.ambient.ts | 43 ++ .../typesVersionsDeclarationEmit.multiFile.ts | 39 ++ .../typesVersions.ambientModules.ts | 2 +- .../typesVersions.multiFile.ts | 2 +- ...tionForStringLiteralNonrelativeImport13.ts | 4 +- 38 files changed, 872 insertions(+), 354 deletions(-) create mode 100644 tests/baselines/reference/typesVersionsDeclarationEmit.ambient.js create mode 100644 tests/baselines/reference/typesVersionsDeclarationEmit.ambient.symbols create mode 100644 tests/baselines/reference/typesVersionsDeclarationEmit.ambient.trace.json create mode 100644 tests/baselines/reference/typesVersionsDeclarationEmit.ambient.types create mode 100644 tests/baselines/reference/typesVersionsDeclarationEmit.multiFile.js create mode 100644 tests/baselines/reference/typesVersionsDeclarationEmit.multiFile.symbols create mode 100644 tests/baselines/reference/typesVersionsDeclarationEmit.multiFile.trace.json create mode 100644 tests/baselines/reference/typesVersionsDeclarationEmit.multiFile.types create mode 100644 tests/cases/conformance/declarationEmit/typesVersionsDeclarationEmit.ambient.ts create mode 100644 tests/cases/conformance/declarationEmit/typesVersionsDeclarationEmit.multiFile.ts diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index ebe5c3efbcd5e..69cc7c018f41b 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -3671,7 +3671,7 @@ "category": "Error", "code": 6205 }, - "'package.json' has invalid version '{0}' in 'typesVersions' field.": { + "'package.json' has a 'typesVersions' field with version-specific path mappings.": { "category": "Message", "code": 6206 }, @@ -3679,6 +3679,10 @@ "category": "Message", "code": 6207 }, + "'package.json' has a 'typesVersions' entry '{0}' that matches compiler version '{1}', looking for a pattern to match module name '{2}'.": { + "category": "Message", + "code": 6208 + }, "Projects to reference": { "category": "Message", diff --git a/src/compiler/moduleNameResolver.ts b/src/compiler/moduleNameResolver.ts index 3b61c2cd83b0e..6545ce353e645 100644 --- a/src/compiler/moduleNameResolver.ts +++ b/src/compiler/moduleNameResolver.ts @@ -24,6 +24,13 @@ namespace ts { return withPackageId(/*packageId*/ undefined, r); } + function removeIgnoredPackageId(r: Resolved | undefined): PathAndExtension | undefined { + if (r) { + Debug.assert(r.packageId === undefined); + return { path: r.path, ext: r.extension }; + } + } + /** Result of trying to resolve a module. */ interface Resolved { path: string; @@ -82,13 +89,14 @@ namespace ts { host: ModuleResolutionHost; compilerOptions: CompilerOptions; traceEnabled: boolean; + failedLookupLocations: Push; } /** Just the fields that we use for module resolution. */ interface PackageJsonPathFields { typings?: string; types?: string; - typesVersions?: MapLike; + typesVersions?: MapLike>; main?: string; } @@ -97,42 +105,89 @@ namespace ts { version?: string; } - /** Reads from "main" or "types"/"typings" depending on `extensions`. */ - function tryReadPackageJsonFields(readTypes: boolean, jsonContent: PackageJsonPathFields, baseDirectory: string, state: ModuleResolutionState): string | undefined { - return readTypes ? tryReadFromField("typings") || tryReadFromField("types") : tryReadFromField("main"); + type MatchingKeys = K extends (TRecord[K] extends TMatch ? K : never) ? K : never; - function tryReadFromField(fieldName: "typings" | "types" | "main"): string | undefined { - if (!hasProperty(jsonContent, fieldName)) { - if (state.traceEnabled) { - trace(state.host, Diagnostics.package_json_does_not_have_a_0_field, fieldName); - } - return; + function readPackageJsonField>(jsonContent: PackageJson, fieldName: K, typeOfTag: "string", state: ModuleResolutionState): PackageJson[K] | undefined; + function readPackageJsonField>(jsonContent: PackageJson, fieldName: K, typeOfTag: "object", state: ModuleResolutionState): PackageJson[K] | undefined; + function readPackageJsonField(jsonContent: PackageJson, fieldName: K, typeOfTag: "string" | "object", state: ModuleResolutionState): PackageJson[K] | undefined { + if (!hasProperty(jsonContent, fieldName)) { + if (state.traceEnabled) { + trace(state.host, Diagnostics.package_json_does_not_have_a_0_field, fieldName); } + return; + } + const value = jsonContent[fieldName]; + if (typeof value !== typeOfTag || value === null) { + if (state.traceEnabled) { + trace(state.host, Diagnostics.Expected_type_of_0_field_in_package_json_to_be_1_got_2, fieldName, typeOfTag, value === null ? "null" : typeof value); + } + return; + } + return value; + } - const fileName = jsonContent[fieldName]; - if (!isString(fileName)) { - if (state.traceEnabled) { - trace(state.host, Diagnostics.Expected_type_of_0_field_in_package_json_to_be_1_got_2, fieldName, "string", typeof fileName); - } - return; + function readPackageJsonPathField(jsonContent: PackageJson, fieldName: K, baseDirectory: string, state: ModuleResolutionState): PackageJson[K] | undefined { + const fileName = readPackageJsonField(jsonContent, fieldName, "string", state); + if (fileName === undefined) return; + const path = normalizePath(combinePaths(baseDirectory, fileName)); + if (state.traceEnabled) { + trace(state.host, Diagnostics.package_json_has_0_field_1_that_references_2, fieldName, fileName, path); + } + return path; + } + + function readPackageJsonTypesFields(jsonContent: PackageJson, baseDirectory: string, state: ModuleResolutionState) { + return readPackageJsonPathField(jsonContent, "typings", baseDirectory, state) + || readPackageJsonPathField(jsonContent, "types", baseDirectory, state); + } + + function readPackageJsonMainField(jsonContent: PackageJson, baseDirectory: string, state: ModuleResolutionState) { + return readPackageJsonPathField(jsonContent, "main", baseDirectory, state); + } + + function readPackageJsonTypesVersionsField(jsonContent: PackageJson, state: ModuleResolutionState) { + const typesVersions = readPackageJsonField(jsonContent, "typesVersions", "object", state); + if (typesVersions === undefined) return; + + if (state.traceEnabled) { + trace(state.host, Diagnostics.package_json_has_a_typesVersions_field_with_version_specific_path_mappings); + } + + return typesVersions; + } + + interface VersionPaths { + version: string; + paths: MapLike; + } + + function readPackageJsonTypesVersionPaths(jsonContent: PackageJson, state: ModuleResolutionState): VersionPaths | undefined { + const typesVersions = readPackageJsonTypesVersionsField(jsonContent, state); + if (typesVersions === undefined) return; + + const result = getPackageJsonTypesVersionsPaths(typesVersions); + if (!result) { + if (state.traceEnabled) { + trace(state.host, Diagnostics.package_json_does_not_have_a_typesVersions_entry_that_matches_version_0, versionMajorMinor); } + return; + } - const path = normalizePath(combinePaths(baseDirectory, fileName)); + const { version: bestVersionKey, paths: bestVersionPaths } = result; + if (typeof bestVersionPaths !== "object") { if (state.traceEnabled) { - trace(state.host, Diagnostics.package_json_has_0_field_1_that_references_2, fieldName, fileName, path); + trace(state.host, Diagnostics.Expected_type_of_0_field_in_package_json_to_be_1_got_2, `typesVersions['${bestVersionKey}']`, "object", typeof bestVersionPaths); } - return path; + return; } - } - /* @internal */ - export function getPackageJsonTypesVersionsOverride(typesVersions: MapLike) { - return getPackageJsonTypesVersionsOverrideWithTrace(typesVersions, /*state*/ undefined); + return result; } let typeScriptVersion: Version | undefined; - function getPackageJsonTypesVersionsOverrideWithTrace(typesVersions: MapLike, state: ModuleResolutionState | undefined) { + /* @internal */ + export function getPackageJsonTypesVersionsPaths(typesVersions: MapLike>) { if (!typeScriptVersion) typeScriptVersion = new Version(versionMajorMinor); let bestVersion: Version | undefined; @@ -142,9 +197,6 @@ namespace ts { const keyVersion = Version.tryParse(key); if (keyVersion === undefined) { - if (state && state.traceEnabled) { - trace(state.host, Diagnostics.package_json_has_invalid_version_0_in_typesVersions_field, key); - } continue; } @@ -160,47 +212,7 @@ namespace ts { return; } - return { version: bestVersionKey, directory: typesVersions[bestVersionKey] }; - } - - 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; - } - - 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 result = getPackageJsonTypesVersionsOverrideWithTrace(typesVersions, state); - if (!result) { - if (state.traceEnabled) { - trace(state.host, Diagnostics.package_json_does_not_have_a_typesVersions_entry_that_matches_version_0, versionMajorMinor); - } - return; - } - - const { version: bestVersionKey, directory: bestVersionPath } = result; - if (!isString(bestVersionPath)) { - if (state.traceEnabled) { - trace(state.host, Diagnostics.Expected_type_of_0_field_in_package_json_to_be_1_got_2, `typesVersions['${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, `typesVersions['${bestVersionKey}']`, bestVersionPath, path); - } - - return bestVersionPath; + return { version: bestVersionKey, paths: typesVersions[bestVersionKey] }; } export function getEffectiveTypeRoots(options: CompilerOptions, host: GetEffectiveTypeRootsHost): string[] | undefined { @@ -250,7 +262,8 @@ namespace ts { */ export function resolveTypeReferenceDirective(typeReferenceDirectiveName: string, containingFile: string | undefined, options: CompilerOptions, host: ModuleResolutionHost): ResolvedTypeReferenceDirectiveWithFailedLookupLocations { const traceEnabled = isTraceEnabled(options, host); - const moduleResolutionState: ModuleResolutionState = { compilerOptions: options, host, traceEnabled }; + const failedLookupLocations: string[] = []; + const moduleResolutionState: ModuleResolutionState = { compilerOptions: options, host, traceEnabled, failedLookupLocations }; const typeRoots = getEffectiveTypeRoots(options, host); if (traceEnabled) { @@ -272,8 +285,6 @@ namespace ts { } } - const failedLookupLocations: string[] = []; - let resolved = primaryLookup(); let primary = true; if (!resolved) { @@ -309,7 +320,7 @@ namespace ts { trace(host, Diagnostics.Directory_0_does_not_exist_skipping_all_lookups_in_it, candidateDirectory); } return resolvedTypeScriptOnly( - loadNodeModuleFromDirectory(Extensions.DtsOnly, candidate, failedLookupLocations, + loadNodeModuleFromDirectory(Extensions.DtsOnly, candidate, !directoryExists, moduleResolutionState)); }); } @@ -328,7 +339,7 @@ namespace ts { if (traceEnabled) { trace(host, Diagnostics.Looking_up_in_node_modules_folder_initial_location_0, initialLocationForSecondaryLookup); } - const result = loadModuleFromNodeModules(Extensions.DtsOnly, typeReferenceDirectiveName, initialLocationForSecondaryLookup, failedLookupLocations, moduleResolutionState, /*cache*/ undefined); + const result = loadModuleFromNearestNodeModulesDirectory(Extensions.DtsOnly, typeReferenceDirectiveName, initialLocationForSecondaryLookup, moduleResolutionState, /*cache*/ undefined); const resolvedFile = resolvedTypeScriptOnly(result && result.value); if (!resolvedFile && traceEnabled) { trace(host, Diagnostics.Type_reference_directive_0_was_not_resolved, typeReferenceDirectiveName); @@ -366,7 +377,7 @@ namespace ts { if (host.directoryExists(root)) { for (const typeDirectivePath of host.getDirectories(root)) { const normalized = normalizePath(typeDirectivePath); - const packageJsonPath = pathToPackageJson(combinePaths(root, normalized)); + const packageJsonPath = combinePaths(root, normalized, "package.json"); // `types-publisher` sometimes creates packages with `"typings": null` for packages that don't provide their own types. // See `createNotNeededPackageJSON` in the types-publisher` repo. // tslint:disable-next-line:no-null-keyword @@ -589,7 +600,7 @@ namespace ts { * 'typings' entry or file 'index' with some supported extension * - Classic loader will only try to interpret '/a/b/c' as file. */ - type ResolutionKindSpecificLoader = (extensions: Extensions, candidate: string, failedLookupLocations: Push, onlyRecordFailures: boolean, state: ModuleResolutionState) => Resolved | undefined; + type ResolutionKindSpecificLoader = (extensions: Extensions, candidate: string, onlyRecordFailures: boolean, state: ModuleResolutionState) => Resolved | undefined; /** * Any module resolution kind can be augmented with optional settings: 'baseUrl', 'paths' and 'rootDirs' - they are used to @@ -652,18 +663,18 @@ namespace ts { * entries in 'rootDirs', use them to build absolute path out of (*) and try to resolve module from this location. */ function tryLoadModuleUsingOptionalResolutionSettings(extensions: Extensions, moduleName: string, containingDirectory: string, loader: ResolutionKindSpecificLoader, - failedLookupLocations: Push, state: ModuleResolutionState): Resolved | undefined { + state: ModuleResolutionState): Resolved | undefined { if (!isExternalModuleNameRelative(moduleName)) { - return tryLoadModuleUsingBaseUrl(extensions, moduleName, loader, failedLookupLocations, state); + return tryLoadModuleUsingBaseUrl(extensions, moduleName, loader, state); } else { - return tryLoadModuleUsingRootDirs(extensions, moduleName, containingDirectory, loader, failedLookupLocations, state); + return tryLoadModuleUsingRootDirs(extensions, moduleName, containingDirectory, loader, state); } } function tryLoadModuleUsingRootDirs(extensions: Extensions, moduleName: string, containingDirectory: string, loader: ResolutionKindSpecificLoader, - failedLookupLocations: Push, state: ModuleResolutionState): Resolved | undefined { + state: ModuleResolutionState): Resolved | undefined { if (!state.compilerOptions.rootDirs) { return undefined; @@ -708,7 +719,7 @@ namespace ts { if (state.traceEnabled) { trace(state.host, Diagnostics.Loading_0_from_the_root_dir_1_candidate_location_2, suffix, matchedNormalizedPrefix, candidate); } - const resolvedFileName = loader(extensions, candidate, failedLookupLocations, !directoryProbablyExists(containingDirectory, state.host), state); + const resolvedFileName = loader(extensions, candidate, !directoryProbablyExists(containingDirectory, state.host), state); if (resolvedFileName) { return resolvedFileName; } @@ -727,7 +738,7 @@ namespace ts { trace(state.host, Diagnostics.Loading_0_from_the_root_dir_1_candidate_location_2, suffix, rootDir, candidate); } const baseDirectory = getDirectoryPath(candidate); - const resolvedFileName = loader(extensions, candidate, failedLookupLocations, !directoryProbablyExists(baseDirectory, state.host), state); + const resolvedFileName = loader(extensions, candidate, !directoryProbablyExists(baseDirectory, state.host), state); if (resolvedFileName) { return resolvedFileName; } @@ -739,59 +750,28 @@ namespace ts { return undefined; } - function tryLoadModuleUsingBaseUrl(extensions: Extensions, moduleName: string, loader: ResolutionKindSpecificLoader, failedLookupLocations: Push, state: ModuleResolutionState): Resolved | undefined { - if (!state.compilerOptions.baseUrl) { + function tryLoadModuleUsingBaseUrl(extensions: Extensions, moduleName: string, loader: ResolutionKindSpecificLoader, state: ModuleResolutionState): Resolved | undefined { + const { baseUrl, paths } = state.compilerOptions; + if (!baseUrl) { return undefined; } if (state.traceEnabled) { - trace(state.host, Diagnostics.baseUrl_option_is_set_to_0_using_this_value_to_resolve_non_relative_module_name_1, state.compilerOptions.baseUrl, moduleName); + trace(state.host, Diagnostics.baseUrl_option_is_set_to_0_using_this_value_to_resolve_non_relative_module_name_1, baseUrl, moduleName); } - - // string is for exact match - let matchedPattern: Pattern | string | undefined; - if (state.compilerOptions.paths) { + if (paths) { if (state.traceEnabled) { trace(state.host, Diagnostics.paths_option_is_specified_looking_for_a_pattern_to_match_module_name_0, moduleName); } - matchedPattern = matchPatternOrExact(getOwnKeys(state.compilerOptions.paths), moduleName); - } - - if (matchedPattern) { - const matchedStar = isString(matchedPattern) ? undefined : matchedText(matchedPattern, moduleName); - const matchedPatternText = isString(matchedPattern) ? matchedPattern : patternText(matchedPattern); - if (state.traceEnabled) { - trace(state.host, Diagnostics.Module_name_0_matched_pattern_1, moduleName, matchedPatternText); + const resolved = tryLoadModuleUsingPaths(extensions, moduleName, baseUrl, paths, loader, /*onlyRecordFailures*/ false, state); + if (resolved) { + return resolved.value; } - return forEach(state.compilerOptions.paths![matchedPatternText], subst => { - const path = matchedStar ? subst.replace("*", matchedStar) : subst; - const candidate = normalizePath(combinePaths(state.compilerOptions.baseUrl!, path)); - if (state.traceEnabled) { - trace(state.host, Diagnostics.Trying_substitution_0_candidate_module_location_Colon_1, subst, path); - } - // A path mapping may have an extension, in contrast to an import, which should omit it. - const extension = tryGetExtensionFromPath(candidate); - if (extension !== undefined) { - const path = tryFile(candidate, failedLookupLocations, /*onlyRecordFailures*/ false, state); - if (path !== undefined) { - return noPackageId({ path, ext: extension }); - } - } - - return loader(extensions, candidate, failedLookupLocations, !directoryProbablyExists(getDirectoryPath(candidate), state.host), state); - }); } - 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); - } - - return loader(extensions, candidate, failedLookupLocations, !directoryProbablyExists(getDirectoryPath(candidate), state.host), state); + const candidate = normalizePath(combinePaths(baseUrl, moduleName)); + if (state.traceEnabled) { + trace(state.host, Diagnostics.Resolving_module_name_0_relative_to_base_url_1_2, moduleName, baseUrl, candidate); } - } - - export function nodeModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache): ResolvedModuleWithFailedLookupLocations { - return nodeModuleNameResolverWorker(moduleName, getDirectoryPath(containingFile), compilerOptions, host, cache, /*jsOnly*/ false); + return loader(extensions, candidate, !directoryProbablyExists(getDirectoryPath(candidate), state.host), state); } /** @@ -809,11 +789,15 @@ namespace ts { return resolvedModule.resolvedFileName; } + export function nodeModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: ModuleResolutionCache): ResolvedModuleWithFailedLookupLocations { + return nodeModuleNameResolverWorker(moduleName, getDirectoryPath(containingFile), compilerOptions, host, cache, /*jsOnly*/ false); + } + function nodeModuleNameResolverWorker(moduleName: string, containingDirectory: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache: ModuleResolutionCache | undefined, jsOnly: boolean): ResolvedModuleWithFailedLookupLocations { const traceEnabled = isTraceEnabled(compilerOptions, host); const failedLookupLocations: string[] = []; - const state: ModuleResolutionState = { compilerOptions, host, traceEnabled }; + const state: ModuleResolutionState = { compilerOptions, host, traceEnabled, failedLookupLocations }; const result = jsOnly ? tryResolve(Extensions.JavaScript) : @@ -827,8 +811,8 @@ namespace ts { return { resolvedModule: undefined, failedLookupLocations }; function tryResolve(extensions: Extensions): SearchResult<{ resolved: Resolved, isExternalLibraryImport: boolean }> { - const loader: ResolutionKindSpecificLoader = (extensions, candidate, failedLookupLocations, onlyRecordFailures, state) => nodeLoadModuleByRelativeName(extensions, candidate, failedLookupLocations, onlyRecordFailures, state, /*considerPackageJson*/ true); - const resolved = tryLoadModuleUsingOptionalResolutionSettings(extensions, moduleName, containingDirectory, loader, failedLookupLocations, state); + const loader: ResolutionKindSpecificLoader = (extensions, candidate, onlyRecordFailures, state) => nodeLoadModuleByRelativeName(extensions, candidate, onlyRecordFailures, state, /*considerPackageJson*/ true); + const resolved = tryLoadModuleUsingOptionalResolutionSettings(extensions, moduleName, containingDirectory, loader, state); if (resolved) { return toSearchResult({ resolved, isExternalLibraryImport: stringContains(resolved.path, nodeModulesPathPart) }); } @@ -837,7 +821,7 @@ namespace ts { if (traceEnabled) { trace(host, Diagnostics.Loading_module_0_from_node_modules_folder_target_file_type_1, moduleName, Extensions[extensions]); } - const resolved = loadModuleFromNodeModules(extensions, moduleName, containingDirectory, failedLookupLocations, state, cache); + const resolved = loadModuleFromNearestNodeModulesDirectory(extensions, moduleName, containingDirectory, state, cache); if (!resolved) return undefined; let resolvedValue = resolved.value; @@ -851,7 +835,7 @@ namespace ts { } else { const { path: candidate, parts } = normalizePathAndParts(combinePaths(containingDirectory, moduleName)); - const resolved = nodeLoadModuleByRelativeName(extensions, candidate, failedLookupLocations, /*onlyRecordFailures*/ false, state, /*considerPackageJson*/ true); + const resolved = nodeLoadModuleByRelativeName(extensions, candidate, /*onlyRecordFailures*/ false, state, /*considerPackageJson*/ true); // Treat explicit "node_modules" import as an external library import. return resolved && toSearchResult({ resolved, isExternalLibraryImport: contains(parts, "node_modules") }); } @@ -871,7 +855,7 @@ namespace ts { return real; } - function nodeLoadModuleByRelativeName(extensions: Extensions, candidate: string, failedLookupLocations: Push, onlyRecordFailures: boolean, state: ModuleResolutionState, considerPackageJson: boolean): Resolved | undefined { + function nodeLoadModuleByRelativeName(extensions: Extensions, candidate: string, onlyRecordFailures: boolean, state: ModuleResolutionState, considerPackageJson: boolean): Resolved | undefined { if (state.traceEnabled) { trace(state.host, Diagnostics.Loading_module_as_file_Slash_folder_candidate_module_location_0_target_file_type_1, candidate, Extensions[extensions]); } @@ -885,10 +869,11 @@ namespace ts { onlyRecordFailures = true; } } - const resolvedFromFile = loadModuleFromFile(extensions, candidate, failedLookupLocations, onlyRecordFailures, state); + const resolvedFromFile = loadModuleFromFile(extensions, candidate, onlyRecordFailures, state); if (resolvedFromFile) { const nm = considerPackageJson ? parseNodeModuleFromPath(resolvedFromFile) : undefined; - const packageId = nm && getPackageJsonInfo(nm.packageDirectory, nm.subModuleName, failedLookupLocations, /*onlyRecordFailures*/ false, state).packageId; + const packageInfo = nm && getPackageJsonInfo(nm.packageDirectory, nm.subModuleName, /*onlyRecordFailures*/ false, state); + const packageId = packageInfo && packageInfo.packageId; return withPackageId(packageId, resolvedFromFile); } } @@ -901,7 +886,7 @@ namespace ts { onlyRecordFailures = true; } } - return loadNodeModuleFromDirectory(extensions, candidate, failedLookupLocations, onlyRecordFailures, state, considerPackageJson); + return loadNodeModuleFromDirectory(extensions, candidate, onlyRecordFailures, state, considerPackageJson); } /*@internal*/ @@ -953,22 +938,22 @@ namespace ts { return path + "/index.d.ts"; } - function loadModuleFromFileNoPackageId(extensions: Extensions, candidate: string, failedLookupLocations: Push, onlyRecordFailures: boolean, state: ModuleResolutionState): Resolved | undefined { - return noPackageId(loadModuleFromFile(extensions, candidate, failedLookupLocations, onlyRecordFailures, state)); + function loadModuleFromFileNoPackageId(extensions: Extensions, candidate: string, onlyRecordFailures: boolean, state: ModuleResolutionState): Resolved | undefined { + return noPackageId(loadModuleFromFile(extensions, candidate, onlyRecordFailures, state)); } /** * @param {boolean} onlyRecordFailures - if true then function won't try to actually load files but instead record all attempts as failures. This flag is necessary * in cases when we know upfront that all load attempts will fail (because containing folder does not exists) however we still need to record all failed lookup locations. */ - function loadModuleFromFile(extensions: Extensions, candidate: string, failedLookupLocations: Push, onlyRecordFailures: boolean, state: ModuleResolutionState): PathAndExtension | undefined { + function loadModuleFromFile(extensions: Extensions, candidate: string, onlyRecordFailures: boolean, state: ModuleResolutionState): PathAndExtension | undefined { if (extensions === Extensions.Json) { const extensionLess = tryRemoveExtension(candidate, Extension.Json); - return extensionLess === undefined ? undefined : tryAddingExtensions(extensionLess, extensions, failedLookupLocations, onlyRecordFailures, state); + return extensionLess === undefined ? undefined : tryAddingExtensions(extensionLess, extensions, onlyRecordFailures, state); } // First, try adding an extension. An import of "foo" could be matched by a file "foo.ts", or "foo.js" by "foo.js.ts" - const resolvedByAddingExtension = tryAddingExtensions(candidate, extensions, failedLookupLocations, onlyRecordFailures, state); + const resolvedByAddingExtension = tryAddingExtensions(candidate, extensions, onlyRecordFailures, state); if (resolvedByAddingExtension) { return resolvedByAddingExtension; } @@ -981,12 +966,12 @@ namespace ts { const extension = candidate.substring(extensionless.length); trace(state.host, Diagnostics.File_name_0_has_a_1_extension_stripping_it, candidate, extension); } - return tryAddingExtensions(extensionless, extensions, failedLookupLocations, onlyRecordFailures, state); + return tryAddingExtensions(extensionless, extensions, onlyRecordFailures, state); } } /** Try to return an existing file that adds one of the `extensions` to `candidate`. */ - function tryAddingExtensions(candidate: string, extensions: Extensions, failedLookupLocations: Push, onlyRecordFailures: boolean, state: ModuleResolutionState): PathAndExtension | undefined { + function tryAddingExtensions(candidate: string, extensions: Extensions, onlyRecordFailures: boolean, state: ModuleResolutionState): PathAndExtension | undefined { if (!onlyRecordFailures) { // check if containing folder exists - if it doesn't then just record failures for all supported extensions without disk probing const directory = getDirectoryPath(candidate); @@ -1007,13 +992,13 @@ namespace ts { } function tryExtension(ext: Extension): PathAndExtension | undefined { - const path = tryFile(candidate + ext, failedLookupLocations, onlyRecordFailures, state); + const path = tryFile(candidate + ext, onlyRecordFailures, state); return path === undefined ? undefined : { path, ext }; } } /** Return the file if it exists. */ - function tryFile(fileName: string, failedLookupLocations: Push, onlyRecordFailures: boolean, state: ModuleResolutionState): string | undefined { + function tryFile(fileName: string, onlyRecordFailures: boolean, state: ModuleResolutionState): string | undefined { if (!onlyRecordFailures) { if (state.host.fileExists(fileName)) { if (state.traceEnabled) { @@ -1027,52 +1012,48 @@ namespace ts { } } } - failedLookupLocations.push(fileName); + state.failedLookupLocations.push(fileName); return undefined; } - function loadNodeModuleFromDirectory(extensions: Extensions, candidate: string, failedLookupLocations: Push, onlyRecordFailures: boolean, state: ModuleResolutionState, considerPackageJson = true) { - const { packageJsonContent, packageId, versionPath } = considerPackageJson - ? getPackageJsonInfo(candidate, "", failedLookupLocations, onlyRecordFailures, state) - : { packageJsonContent: undefined, packageId: undefined, versionPath: undefined }; - if (versionPath) { - candidate = normalizePath(combinePaths(candidate, versionPath)); - } - return withPackageId(packageId, loadNodeModuleFromDirectoryWorker(extensions, candidate, failedLookupLocations, onlyRecordFailures, state, packageJsonContent)); + function loadNodeModuleFromDirectory(extensions: Extensions, candidate: string, onlyRecordFailures: boolean, state: ModuleResolutionState, considerPackageJson = true) { + const packageInfo = considerPackageJson ? getPackageJsonInfo(candidate, "", onlyRecordFailures, state) : undefined; + const packageId = packageInfo && packageInfo.packageId; + const packageJsonContent = packageInfo && packageInfo.packageJsonContent; + const versionPaths = packageJsonContent && readPackageJsonTypesVersionPaths(packageJsonContent, state); + return withPackageId(packageId, loadNodeModuleFromDirectoryWorker(extensions, candidate, onlyRecordFailures, state, packageJsonContent, versionPaths)); } - function loadNodeModuleFromDirectoryWorker(extensions: Extensions, candidate: string, failedLookupLocations: Push, onlyRecordFailures: boolean, state: ModuleResolutionState, packageJsonContent: PackageJsonPathFields | undefined): PathAndExtension | undefined { - const fromPackageJson = packageJsonContent && loadModuleFromPackageJson(packageJsonContent, extensions, candidate, failedLookupLocations, state); + function loadNodeModuleFromDirectoryWorker(extensions: Extensions, candidate: string, onlyRecordFailures: boolean, state: ModuleResolutionState, packageJsonContent: PackageJsonPathFields | undefined, versionPaths: VersionPaths | undefined): PathAndExtension | undefined { + const fromPackageJson = packageJsonContent && loadModuleFromPackageJson(packageJsonContent, versionPaths, extensions, candidate, state); if (fromPackageJson) { return fromPackageJson; } const directoryExists = !onlyRecordFailures && directoryProbablyExists(candidate, state.host); - return loadModuleFromFile(extensions, combinePaths(candidate, "index"), failedLookupLocations, !directoryExists, state); + return loadModuleFromFile(extensions, combinePaths(candidate, "index"), !directoryExists, state); + } + + interface PackageJsonInfo { + packageJsonContent: PackageJsonPathFields | undefined; + packageId: PackageId | undefined; + versionPaths: VersionPaths | undefined; } - function getPackageJsonInfo( - nodeModuleDirectory: string, - subModuleName: string, - failedLookupLocations: Push, - onlyRecordFailures: boolean, - state: ModuleResolutionState, - ): { found: boolean, packageJsonContent: PackageJsonPathFields | undefined, packageId: PackageId | undefined, versionPath: string | undefined } { + function getPackageJsonInfo(packageDirectory: string, subModuleName: string, onlyRecordFailures: boolean, state: ModuleResolutionState): PackageJsonInfo | undefined { const { host, traceEnabled } = state; - const directoryExists = !onlyRecordFailures && directoryProbablyExists(nodeModuleDirectory, host); - const packageJsonPath = pathToPackageJson(nodeModuleDirectory); + const directoryExists = !onlyRecordFailures && directoryProbablyExists(packageDirectory, host); + const packageJsonPath = combinePaths(packageDirectory, "package.json"); 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 versionDirectory = versionPath ? normalizePath(combinePaths(nodeModuleDirectory, versionPath)) : nodeModuleDirectory; - const path = tryReadPackageJsonFields(/*readTypes*/ true, packageJsonContent, versionDirectory, state); + const path = readPackageJsonTypesFields(packageJsonContent, packageDirectory, state); if (typeof path === "string") { - subModuleName = addExtensionAndIndex(path.substring(versionDirectory.length + 1)); + subModuleName = addExtensionAndIndex(path.substring(packageDirectory.length + 1)); } else { - const jsPath = tryReadPackageJsonFields(/*readTypes*/ false, packageJsonContent, nodeModuleDirectory, state); - if (typeof jsPath === "string" && jsPath.length > nodeModuleDirectory.length) { - const potentialSubModule = jsPath.substring(nodeModuleDirectory.length + 1); + const jsPath = readPackageJsonMainField(packageJsonContent, packageDirectory, state); + if (typeof jsPath === "string" && jsPath.length > packageDirectory.length) { + const potentialSubModule = jsPath.substring(packageDirectory.length + 1); subModuleName = (forEach(supportedJavascriptExtensions, extension => tryRemoveExtension(potentialSubModule, extension)) || potentialSubModule) + Extension.Dts; } @@ -1082,13 +1063,11 @@ namespace ts { } } - if (versionPath) { - subModuleName = combinePaths(versionPath, subModuleName); - } - if (!endsWith(subModuleName, Extension.Dts)) { subModuleName = addExtensionAndIndex(subModuleName); } + + const versionPaths = readPackageJsonTypesVersionPaths(packageJsonContent, state); const packageId: PackageId | undefined = typeof packageJsonContent.name === "string" && typeof packageJsonContent.version === "string" ? { name: packageJsonContent.name, subModuleName, version: packageJsonContent.version } : undefined; @@ -1100,7 +1079,8 @@ namespace ts { trace(host, Diagnostics.Found_package_json_at_0, packageJsonPath); } } - return { found: true, packageJsonContent, packageId, versionPath }; + + return { packageJsonContent, packageId, versionPaths }; } else { if (directoryExists && traceEnabled) { @@ -1108,17 +1088,18 @@ namespace ts { } // 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, versionPath: undefined }; + state.failedLookupLocations.push(packageJsonPath); } } - function loadModuleFromPackageJson(jsonContent: PackageJsonPathFields, extensions: Extensions, candidate: string, failedLookupLocations: Push, state: ModuleResolutionState): PathAndExtension | undefined { - let file = tryReadPackageJsonFields(extensions !== Extensions.JavaScript && extensions !== Extensions.Json, jsonContent, candidate, state); + function loadModuleFromPackageJson(jsonContent: PackageJsonPathFields, versionPaths: VersionPaths | undefined, extensions: Extensions, candidate: string, state: ModuleResolutionState): PathAndExtension | undefined { + let file = extensions !== Extensions.JavaScript && extensions !== Extensions.Json + ? readPackageJsonTypesFields(jsonContent, candidate, state) + : readPackageJsonMainField(jsonContent, candidate, state); if (!file) { if (extensions === Extensions.TypeScript) { // When resolving typescript modules, try resolving using main field as well - file = tryReadPackageJsonFields(/*readTypes*/ false, jsonContent, candidate, state); + file = readPackageJsonMainField(jsonContent, candidate, state); if (!file) { return undefined; } @@ -1128,27 +1109,39 @@ namespace ts { } } - const onlyRecordFailures = !directoryProbablyExists(getDirectoryPath(file), state.host); - const fromFile = tryFile(file, failedLookupLocations, onlyRecordFailures, state); - if (fromFile) { - const resolved = resolvedIfExtensionMatches(extensions, fromFile); - if (resolved) { - return resolved; + const loader: ResolutionKindSpecificLoader = (extensions, candidate, onlyRecordFailures, state) => { + const fromFile = tryFile(candidate, onlyRecordFailures, state); + if (fromFile) { + const resolved = resolvedIfExtensionMatches(extensions, fromFile); + if (resolved) { + return noPackageId(resolved); + } + if (state.traceEnabled) { + trace(state.host, Diagnostics.File_0_has_an_unsupported_extension_so_skipping_it, fromFile); + } } + + // Even if extensions is DtsOnly, we can still look up a .ts file as a result of package.json "types" + const nextExtensions = extensions === Extensions.DtsOnly ? Extensions.TypeScript : extensions; + // Don't do package.json lookup recursively, because Node.js' package lookup doesn't. + return nodeLoadModuleByRelativeName(nextExtensions, candidate, onlyRecordFailures, state, /*considerPackageJson*/ false); + }; + + const onlyRecordFailures = !directoryProbablyExists(getDirectoryPath(file), state.host); + + if (versionPaths && containsPath(candidate, file)) { + const moduleName = getRelativePathFromDirectory(candidate, file, /*ignoreCase*/ false); if (state.traceEnabled) { - trace(state.host, Diagnostics.File_0_has_an_unsupported_extension_so_skipping_it, fromFile); + trace(state.host, Diagnostics.package_json_has_a_typesVersions_entry_0_that_matches_compiler_version_1_looking_for_a_pattern_to_match_module_name_2, versionPaths.version, versionMajorMinor, moduleName); + } + const result = tryLoadModuleUsingPaths(extensions, moduleName, candidate, versionPaths.paths, loader, onlyRecordFailures, state); + if (result) { + return removeIgnoredPackageId(result.value); } } - // Even if extensions is DtsOnly, we can still look up a .ts file as a result of package.json "types" - const nextExtensions = extensions === Extensions.DtsOnly ? Extensions.TypeScript : extensions; - // Don't do package.json lookup recursively, because Node.js' package lookup doesn't. - const result = nodeLoadModuleByRelativeName(nextExtensions, file, failedLookupLocations, onlyRecordFailures, state, /*considerPackageJson*/ false); - if (result) { - // It won't have a `packageId` set, because we disabled `considerPackageJson`. - Debug.assert(result.packageId === undefined); - return { path: result.path, ext: result.extension }; - } + // It won't have a `packageId` set, because we disabled `considerPackageJson`. + return removeIgnoredPackageId(loader(extensions, file, onlyRecordFailures, state)); } /** Resolve from an arbitrarily specified file. Return `undefined` if it has an unsupported extension. */ @@ -1171,42 +1164,6 @@ namespace ts { } } - function pathToPackageJson(directory: string): string { - return combinePaths(directory, "package.json"); - } - - function loadModuleFromNodeModulesFolder(extensions: Extensions, moduleName: string, nodeModulesFolder: string, nodeModulesFolderExists: boolean, failedLookupLocations: Push, state: ModuleResolutionState): Resolved | undefined { - 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, 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 } = 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, 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) || - loadNodeModuleFromDirectoryWorker(extensions, candidate, failedLookupLocations, !nodeModulesFolderExists, state, packageJsonContent); - return withPackageId(packageId, pathAndExtension); - } - /* @internal */ export function parsePackageName(moduleName: string): { packageName: string, rest: string } { let idx = moduleName.indexOf(directorySeparator); @@ -1216,35 +1173,36 @@ namespace ts { return idx === -1 ? { packageName: moduleName, rest: "" } : { packageName: moduleName.slice(0, idx), rest: moduleName.slice(idx + 1) }; } - function loadModuleFromNodeModules(extensions: Extensions, moduleName: string, directory: string, failedLookupLocations: Push, state: ModuleResolutionState, cache: NonRelativeModuleNameResolutionCache | undefined): SearchResult { - return loadModuleFromNearestNodeModules(extensions, moduleName, directory, failedLookupLocations, state, /*typesOnly*/ false, cache); + function loadModuleFromNearestNodeModulesDirectory(extensions: Extensions, moduleName: string, directory: string, state: ModuleResolutionState, cache: NonRelativeModuleNameResolutionCache | undefined): SearchResult { + return loadModuleFromNearestNodeModulesDirectoryWorker(extensions, moduleName, directory, state, /*typesScopeOnly*/ false, cache); } - function loadModuleFromNodeModulesAtTypes(moduleName: string, directory: string, failedLookupLocations: Push, state: ModuleResolutionState): SearchResult { + + function loadModuleFromNearestNodeModulesDirectoryTypesScope(moduleName: string, directory: string, state: ModuleResolutionState): SearchResult { // Extensions parameter here doesn't actually matter, because typesOnly ensures we're just doing @types lookup, which is always DtsOnly. - return loadModuleFromNearestNodeModules(Extensions.DtsOnly, moduleName, directory, failedLookupLocations, state, /*typesOnly*/ true, /*cache*/ undefined); + return loadModuleFromNearestNodeModulesDirectoryWorker(Extensions.DtsOnly, moduleName, directory, state, /*typesScopeOnly*/ true, /*cache*/ undefined); } - function loadModuleFromNearestNodeModules(extensions: Extensions, moduleName: string, directory: string, failedLookupLocations: Push, state: ModuleResolutionState, typesOnly: boolean, cache: NonRelativeModuleNameResolutionCache | undefined): SearchResult { + function loadModuleFromNearestNodeModulesDirectoryWorker(extensions: Extensions, moduleName: string, directory: string, state: ModuleResolutionState, typesScopeOnly: boolean, cache: NonRelativeModuleNameResolutionCache | undefined): SearchResult { const perModuleNameCache = cache && cache.getOrCreateCacheForModuleName(moduleName); return forEachAncestorDirectory(normalizeSlashes(directory), ancestorDirectory => { if (getBaseFileName(ancestorDirectory) !== "node_modules") { - const resolutionFromCache = tryFindNonRelativeModuleNameInCache(perModuleNameCache, moduleName, ancestorDirectory, state.traceEnabled, state.host, failedLookupLocations); + const resolutionFromCache = tryFindNonRelativeModuleNameInCache(perModuleNameCache, moduleName, ancestorDirectory, state); if (resolutionFromCache) { return resolutionFromCache; } - return toSearchResult(loadModuleFromImmediateNodeModules(extensions, moduleName, ancestorDirectory, failedLookupLocations, state, typesOnly)); + return toSearchResult(loadModuleFromImmediateNodeModulesDirectory(extensions, moduleName, ancestorDirectory, state, typesScopeOnly)); } }); } - function loadModuleFromImmediateNodeModules(extensions: Extensions, moduleName: string, directory: string, failedLookupLocations: Push, state: ModuleResolutionState, typesOnly: boolean): Resolved | undefined { + function loadModuleFromImmediateNodeModulesDirectory(extensions: Extensions, moduleName: string, directory: string, state: ModuleResolutionState, typesScopeOnly: boolean): Resolved | undefined { const nodeModulesFolder = combinePaths(directory, "node_modules"); const nodeModulesFolderExists = directoryProbablyExists(nodeModulesFolder, state.host); if (!nodeModulesFolderExists && state.traceEnabled) { trace(state.host, Diagnostics.Directory_0_does_not_exist_skipping_all_lookups_in_it, nodeModulesFolder); } - const packageResult = typesOnly ? undefined : loadModuleFromNodeModulesFolder(extensions, moduleName, nodeModulesFolder, nodeModulesFolderExists, failedLookupLocations, state); + const packageResult = typesScopeOnly ? undefined : loadModuleFromSpecificNodeModulesDirectory(extensions, moduleName, nodeModulesFolder, nodeModulesFolderExists, state); if (packageResult) { return packageResult; } @@ -1257,7 +1215,84 @@ namespace ts { } nodeModulesAtTypesExists = false; } - return loadModuleFromNodeModulesFolder(Extensions.DtsOnly, mangleScopedPackageNameWithTrace(moduleName, state), nodeModulesAtTypes, nodeModulesAtTypesExists, failedLookupLocations, state); + return loadModuleFromSpecificNodeModulesDirectory(Extensions.DtsOnly, mangleScopedPackageNameWithTrace(moduleName, state), nodeModulesAtTypes, nodeModulesAtTypesExists, state); + } + } + + function loadModuleFromSpecificNodeModulesDirectory(extensions: Extensions, moduleName: string, nodeModulesDirectory: string, nodeModulesDirectoryExists: boolean, state: ModuleResolutionState): Resolved | undefined { + const candidate = normalizePath(combinePaths(nodeModulesDirectory, moduleName)); + + // First look for a nested package.json, as in `node_modules/foo/bar/package.json`. + let packageJsonContent: PackageJsonPathFields | undefined; + let packageId: PackageId | undefined; + let versionPaths: VersionPaths | undefined; + + const packageInfo = getPackageJsonInfo(candidate, "", !nodeModulesDirectoryExists, state); + if (packageInfo) { + ({ packageJsonContent, packageId, versionPaths } = packageInfo); + const fromFile = loadModuleFromFile(extensions, candidate, !nodeModulesDirectoryExists, state); + if (fromFile) { + return noPackageId(fromFile); + } + + const fromDirectory = loadNodeModuleFromDirectoryWorker(extensions, candidate, !nodeModulesDirectoryExists, state, packageJsonContent, versionPaths); + return withPackageId(packageId, fromDirectory); + } + + const loader: ResolutionKindSpecificLoader = (extensions, candidate, onlyRecordFailures, state) => { + const pathAndExtension = + loadModuleFromFile(extensions, candidate, onlyRecordFailures, state) || + loadNodeModuleFromDirectoryWorker(extensions, candidate, onlyRecordFailures, state, packageJsonContent, versionPaths); + return withPackageId(packageId, pathAndExtension); + }; + + const { packageName, rest } = parsePackageName(moduleName); + if (rest !== "") { // If "rest" is empty, we just did this search above. + const packageDirectory = combinePaths(nodeModulesDirectory, 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 and path mappings. + const packageInfo = getPackageJsonInfo(packageDirectory, rest, !nodeModulesDirectoryExists, state); + if (packageInfo) ({ packageId, versionPaths } = packageInfo); + if (versionPaths) { + if (state.traceEnabled) { + trace(state.host, Diagnostics.package_json_has_a_typesVersions_entry_0_that_matches_compiler_version_1_looking_for_a_pattern_to_match_module_name_2, versionPaths.version, versionMajorMinor, rest); + } + const packageDirectoryExists = nodeModulesDirectoryExists && directoryProbablyExists(packageDirectory, state.host); + const fromPaths = tryLoadModuleUsingPaths(extensions, rest, packageDirectory, versionPaths.paths, loader, !packageDirectoryExists, state); + if (fromPaths) { + return fromPaths.value; + } + } + } + + return loader(extensions, candidate, !nodeModulesDirectoryExists, state); + } + + function tryLoadModuleUsingPaths(extensions: Extensions, moduleName: string, baseDirectory: string, paths: MapLike, loader: ResolutionKindSpecificLoader, onlyRecordFailures: boolean, state: ModuleResolutionState): SearchResult { + const matchedPattern = matchPatternOrExact(getOwnKeys(paths), moduleName); + if (matchedPattern) { + const matchedStar = isString(matchedPattern) ? undefined : matchedText(matchedPattern, moduleName); + const matchedPatternText = isString(matchedPattern) ? matchedPattern : patternText(matchedPattern); + if (state.traceEnabled) { + trace(state.host, Diagnostics.Module_name_0_matched_pattern_1, moduleName, matchedPatternText); + } + const resolved = forEach(paths[matchedPatternText], subst => { + const path = matchedStar ? subst.replace("*", matchedStar) : subst; + const candidate = normalizePath(combinePaths(baseDirectory, path)); + if (state.traceEnabled) { + trace(state.host, Diagnostics.Trying_substitution_0_candidate_module_location_Colon_1, subst, path); + } + // A path mapping may have an extension, in contrast to an import, which should omit it. + const extension = tryGetExtensionFromPath(candidate); + if (extension !== undefined) { + const path = tryFile(candidate, onlyRecordFailures, state); + if (path !== undefined) { + return noPackageId({ path, ext: extension }); + } + } + return loader(extensions, candidate, onlyRecordFailures || !directoryProbablyExists(getDirectoryPath(candidate), state.host), state); + }); + return { value: resolved }; } } @@ -1305,21 +1340,21 @@ namespace ts { typesPackageName; } - function tryFindNonRelativeModuleNameInCache(cache: PerModuleNameCache | undefined, moduleName: string, containingDirectory: string, traceEnabled: boolean, host: ModuleResolutionHost, failedLookupLocations: Push): SearchResult { + function tryFindNonRelativeModuleNameInCache(cache: PerModuleNameCache | undefined, moduleName: string, containingDirectory: string, state: ModuleResolutionState): SearchResult { const result = cache && cache.get(containingDirectory); if (result) { - if (traceEnabled) { - trace(host, Diagnostics.Resolution_for_module_0_was_found_in_cache_from_location_1, moduleName, containingDirectory); + if (state.traceEnabled) { + trace(state.host, Diagnostics.Resolution_for_module_0_was_found_in_cache_from_location_1, moduleName, containingDirectory); } - failedLookupLocations.push(...result.failedLookupLocations); + state.failedLookupLocations.push(...result.failedLookupLocations); return { value: result.resolvedModule && { path: result.resolvedModule.resolvedFileName, originalPath: result.resolvedModule.originalPath || true, extension: result.resolvedModule.extension, packageId: result.resolvedModule.packageId } }; } } export function classicNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost, cache?: NonRelativeModuleNameResolutionCache): ResolvedModuleWithFailedLookupLocations { const traceEnabled = isTraceEnabled(compilerOptions, host); - const state: ModuleResolutionState = { compilerOptions, host, traceEnabled }; const failedLookupLocations: string[] = []; + const state: ModuleResolutionState = { compilerOptions, host, traceEnabled, failedLookupLocations }; const containingDirectory = getDirectoryPath(containingFile); const resolved = tryResolve(Extensions.TypeScript) || tryResolve(Extensions.JavaScript); @@ -1327,7 +1362,7 @@ namespace ts { return createResolvedModuleWithFailedLookupLocations(resolved && resolved.value, /*isExternalLibraryImport*/ false, failedLookupLocations); function tryResolve(extensions: Extensions): SearchResult { - const resolvedUsingSettings = tryLoadModuleUsingOptionalResolutionSettings(extensions, moduleName, containingDirectory, loadModuleFromFileNoPackageId, failedLookupLocations, state); + const resolvedUsingSettings = tryLoadModuleUsingOptionalResolutionSettings(extensions, moduleName, containingDirectory, loadModuleFromFileNoPackageId, state); if (resolvedUsingSettings) { return { value: resolvedUsingSettings }; } @@ -1336,24 +1371,24 @@ namespace ts { const perModuleNameCache = cache && cache.getOrCreateCacheForModuleName(moduleName); // Climb up parent directories looking for a module. const resolved = forEachAncestorDirectory(containingDirectory, directory => { - const resolutionFromCache = tryFindNonRelativeModuleNameInCache(perModuleNameCache, moduleName, directory, traceEnabled, host, failedLookupLocations); + const resolutionFromCache = tryFindNonRelativeModuleNameInCache(perModuleNameCache, moduleName, directory, state); if (resolutionFromCache) { return resolutionFromCache; } const searchName = normalizePath(combinePaths(directory, moduleName)); - return toSearchResult(loadModuleFromFileNoPackageId(extensions, searchName, failedLookupLocations, /*onlyRecordFailures*/ false, state)); + return toSearchResult(loadModuleFromFileNoPackageId(extensions, searchName, /*onlyRecordFailures*/ false, state)); }); if (resolved) { return resolved; } if (extensions === Extensions.TypeScript) { // If we didn't find the file normally, look it up in @types. - return loadModuleFromNodeModulesAtTypes(moduleName, containingDirectory, failedLookupLocations, state); + return loadModuleFromNearestNodeModulesDirectoryTypesScope(moduleName, containingDirectory, state); } } else { const candidate = normalizePath(combinePaths(containingDirectory, moduleName)); - return toSearchResult(loadModuleFromFileNoPackageId(extensions, candidate, failedLookupLocations, /*onlyRecordFailures*/ false, state)); + return toSearchResult(loadModuleFromFileNoPackageId(extensions, candidate, /*onlyRecordFailures*/ false, state)); } } } @@ -1368,9 +1403,9 @@ namespace ts { if (traceEnabled) { trace(host, Diagnostics.Auto_discovery_for_typings_is_enabled_in_project_0_Running_extra_resolution_pass_for_module_1_using_cache_location_2, projectName, moduleName, globalCache); } - const state: ModuleResolutionState = { compilerOptions, host, traceEnabled }; const failedLookupLocations: string[] = []; - const resolved = loadModuleFromImmediateNodeModules(Extensions.DtsOnly, moduleName, globalCache, failedLookupLocations, state, /*typesOnly*/ false); + const state: ModuleResolutionState = { compilerOptions, host, traceEnabled, failedLookupLocations }; + const resolved = loadModuleFromImmediateNodeModulesDirectory(Extensions.DtsOnly, moduleName, globalCache, state, /*typesScopeOnly*/ false); return createResolvedModuleWithFailedLookupLocations(resolved, /*isExternalLibraryImport*/ true, failedLookupLocations); } diff --git a/src/compiler/moduleSpecifiers.ts b/src/compiler/moduleSpecifiers.ts index 696736048b1d4..5035fd52ec9c0 100644 --- a/src/compiler/moduleSpecifiers.ts +++ b/src/compiler/moduleSpecifiers.ts @@ -260,7 +260,8 @@ namespace ts.moduleSpecifiers { const suffix = pattern.substr(indexOfStar + 1); if (relativeToBaseUrl.length >= prefix.length + suffix.length && startsWith(relativeToBaseUrl, prefix) && - endsWith(relativeToBaseUrl, suffix)) { + endsWith(relativeToBaseUrl, suffix) || + !suffix && relativeToBaseUrl === removeTrailingDirectorySeparator(prefix)) { const matchedStar = relativeToBaseUrl.substr(prefix.length, relativeToBaseUrl.length - suffix.length); return key.replace("*", matchedStar); } @@ -318,6 +319,26 @@ namespace ts.moduleSpecifiers { return undefined; } + const packageRootPath = moduleFileName.substring(0, parts.packageRootIndex); + const packageJsonPath = combinePaths(packageRootPath, "package.json"); + const packageJsonContent = host.fileExists!(packageJsonPath) + ? JSON.parse(host.readFile!(packageJsonPath)!) + : undefined; + const versionPaths = packageJsonContent && packageJsonContent.typesVersions + ? getPackageJsonTypesVersionsPaths(packageJsonContent.typesVersions) + : undefined; + if (versionPaths) { + const subModuleName = moduleFileName.slice(parts.packageRootIndex + 1); + const fromPaths = tryGetModuleNameFromPaths( + removeFileExtension(subModuleName), + removeExtensionAndIndexPostFix(subModuleName, ModuleResolutionKind.NodeJs, /*addJsExtension*/ false), + versionPaths.paths + ); + if (fromPaths !== undefined) { + moduleFileName = combinePaths(moduleFileName.slice(0, parts.packageRootIndex), fromPaths); + } + } + // Simplify the full file path to something that can be resolved by Node. // If the module could be imported by a directory name, use that directory's name @@ -330,17 +351,12 @@ namespace ts.moduleSpecifiers { function getDirectoryOrExtensionlessFileName(path: string): string { // If the file is the main module, it can be imported by the package name - const packageRootPath = path.substring(0, parts.packageRootIndex); - const packageJsonPath = combinePaths(packageRootPath, "package.json"); - if (host.fileExists!(packageJsonPath)) { // TODO: GH#18217 - const packageJsonContent = JSON.parse(host.readFile!(packageJsonPath)!); - if (packageJsonContent) { - const mainFileRelative = packageJsonContent.typings || packageJsonContent.types || packageJsonContent.main; - if (mainFileRelative) { - const mainExportFile = toPath(mainFileRelative, packageRootPath, getCanonicalFileName); - if (removeFileExtension(mainExportFile) === removeFileExtension(getCanonicalFileName(path))) { - return packageRootPath; - } + if (packageJsonContent) { + const mainFileRelative = packageJsonContent.typings || packageJsonContent.types || packageJsonContent.main; + if (mainFileRelative) { + const mainExportFile = toPath(mainFileRelative, packageRootPath, getCanonicalFileName); + if (removeFileExtension(mainExportFile) === removeFileExtension(getCanonicalFileName(path))) { + return packageRootPath; } } } diff --git a/src/compiler/transformers/declarations.ts b/src/compiler/transformers/declarations.ts index 063b5f1cd1dfd..e33d9eec292a0 100644 --- a/src/compiler/transformers/declarations.ts +++ b/src/compiler/transformers/declarations.ts @@ -289,6 +289,13 @@ namespace ts { if (startsWith(fileName, "./") && hasExtension(fileName)) { fileName = fileName.substring(2); } + + // omit references to files from node_modules (npm may disambiguate module + // references when installing this package, making the path is unreliable). + if (startsWith(fileName, "node_modules/") || fileName.indexOf("/node_modules/") !== -1) { + return; + } + references.push({ pos: -1, end: -1, fileName }); } }; diff --git a/src/services/pathCompletions.ts b/src/services/pathCompletions.ts index f958163bb1497..22cc56903c0fc 100644 --- a/src/services/pathCompletions.ts +++ b/src/services/pathCompletions.ts @@ -107,24 +107,10 @@ namespace ts.Completions.PathCompletions { // const absolutePath = normalizeAndPreserveTrailingSlash(isRootedDiskPath(fragment) ? fragment : combinePaths(scriptPath, fragment)); // TODO(rbuckton): should use resolvePaths const absolutePath = resolvePath(scriptPath, fragment); - let baseDirectory = hasTrailingDirectorySeparator(absolutePath) ? absolutePath : getDirectoryPath(absolutePath); + const baseDirectory = hasTrailingDirectorySeparator(absolutePath) ? absolutePath : getDirectoryPath(absolutePath); const ignoreCase = !(host.useCaseSensitiveFileNames && host.useCaseSensitiveFileNames()); if (tryDirectoryExists(host, baseDirectory)) { - // check for a version redirect - const packageJsonPath = findPackageJson(baseDirectory, host); - if (packageJsonPath) { - const packageJson = readJson(packageJsonPath, host as { readFile: (filename: string) => string | undefined }); - const typesVersions = (packageJson as any).typesVersions; - if (typeof typesVersions === "object") { - const result = getPackageJsonTypesVersionsOverride(typesVersions); - const versionPath = result && result.directory; - if (versionPath) { - baseDirectory = resolvePath(baseDirectory, versionPath); - } - } - } - // Enumerate the available files if possible const files = tryReadDirectory(host, baseDirectory, extensions, /*exclude*/ undefined, /*include*/ ["./*"]); @@ -165,11 +151,41 @@ namespace ts.Completions.PathCompletions { } } } + + // check for a version redirect + const packageJsonPath = findPackageJson(baseDirectory, host); + if (packageJsonPath) { + const packageJson = readJson(packageJsonPath, host as { readFile: (filename: string) => string | undefined }); + const typesVersions = (packageJson as any).typesVersions; + if (typeof typesVersions === "object") { + const versionResult = getPackageJsonTypesVersionsPaths(typesVersions); + const versionPaths = versionResult && versionResult.paths; + const rest = absolutePath.slice(ensureTrailingDirectorySeparator(baseDirectory).length); + if (versionPaths) { + addCompletionEntriesFromPaths(result, rest, baseDirectory, extensions, versionPaths, host); + } + } + } } return result; } + function addCompletionEntriesFromPaths(result: NameAndKind[], fragment: string, baseDirectory: string, fileExtensions: ReadonlyArray, paths: MapLike, host: LanguageServiceHost) { + for (const path in paths) { + if (!hasProperty(paths, path)) continue; + const patterns = paths[path]; + if (patterns) { + for (const { name, kind } of getCompletionsForPathMapping(path, patterns, fragment, baseDirectory, fileExtensions, host)) { + // Path mappings may provide a duplicate way to get to something we've already added, so don't add again. + if (!result.some(entry => entry.name === name)) { + result.push(nameAndKind(name, kind)); + } + } + } + } + } + /** * Check all of the declared modules and those in node modules. Possible sources of modules: * Modules that are found by the type checker @@ -185,19 +201,10 @@ namespace ts.Completions.PathCompletions { const fileExtensions = getSupportedExtensionsForModuleResolution(compilerOptions); if (baseUrl) { const projectDir = compilerOptions.project || host.getCurrentDirectory(); - const absolute = isRootedDiskPath(baseUrl) ? baseUrl : combinePaths(projectDir, baseUrl); - getCompletionEntriesForDirectoryFragment(fragment, normalizePath(absolute), fileExtensions, /*includeExtensions*/ false, host, /*exclude*/ undefined, result); - - for (const path in paths!) { - const patterns = paths![path]; - if (paths!.hasOwnProperty(path) && patterns) { - for (const { name, kind } of getCompletionsForPathMapping(path, patterns, fragment, baseUrl, fileExtensions, host)) { - // Path mappings may provide a duplicate way to get to something we've already added, so don't add again. - if (!result.some(entry => entry.name === name)) { - result.push(nameAndKind(name, kind)); - } - } - } + const absolute = normalizePath(combinePaths(projectDir, baseUrl)); + getCompletionEntriesForDirectoryFragment(fragment, absolute, fileExtensions, /*includeExtensions*/ false, host, /*exclude*/ undefined, result); + if (paths) { + addCompletionEntriesFromPaths(result, fragment, absolute, fileExtensions, paths, host); } } diff --git a/tests/baselines/reference/duplicatePackage_relativeImportWithinPackage.trace.json b/tests/baselines/reference/duplicatePackage_relativeImportWithinPackage.trace.json index dbf67e3802c2a..c4421e45579a5 100644 --- a/tests/baselines/reference/duplicatePackage_relativeImportWithinPackage.trace.json +++ b/tests/baselines/reference/duplicatePackage_relativeImportWithinPackage.trace.json @@ -33,10 +33,10 @@ "======== 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.", + "'package.json' does not have a 'typesVersions' field.", "Found 'package.json' at '/node_modules/a/node_modules/foo/package.json'. Package ID is 'foo/index.d.ts@1.2.3'.", "File '/node_modules/a/node_modules/foo.ts' does not exist.", "File '/node_modules/a/node_modules/foo.tsx' does not exist.", diff --git a/tests/baselines/reference/duplicatePackage_relativeImportWithinPackage_scoped.trace.json b/tests/baselines/reference/duplicatePackage_relativeImportWithinPackage_scoped.trace.json index d3d3dfac06411..97340de57ca66 100644 --- a/tests/baselines/reference/duplicatePackage_relativeImportWithinPackage_scoped.trace.json +++ b/tests/baselines/reference/duplicatePackage_relativeImportWithinPackage_scoped.trace.json @@ -33,10 +33,10 @@ "======== 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.", + "'package.json' does not have a 'typesVersions' field.", "Found 'package.json' at '/node_modules/a/node_modules/@foo/bar/package.json'. Package ID is '@foo/bar/index.d.ts@1.2.3'.", "File '/node_modules/a/node_modules/@foo/bar.ts' does not exist.", "File '/node_modules/a/node_modules/@foo/bar.tsx' does not exist.", diff --git a/tests/baselines/reference/library-reference-10.trace.json b/tests/baselines/reference/library-reference-10.trace.json index d24bc21f28323..3e6cf4432eaed 100644 --- a/tests/baselines/reference/library-reference-10.trace.json +++ b/tests/baselines/reference/library-reference-10.trace.json @@ -1,18 +1,20 @@ [ "======== 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'.", + "'package.json' does not have a 'typesVersions' field.", "Found 'package.json' at './types/jquery/package.json'.", + "'package.json' does not have a 'typesVersions' field.", "'package.json' has 'typings' field 'jquery.d.ts' that references 'types/jquery/jquery.d.ts'.", "File 'types/jquery/jquery.d.ts' exist - use it as a name resolution result.", "Resolving real path for 'types/jquery/jquery.d.ts', result '/foo/types/jquery/jquery.d.ts'.", "======== 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'.", + "'package.json' does not have a 'typesVersions' field.", "Found 'package.json' at './types/jquery/package.json'.", + "'package.json' does not have a 'typesVersions' field.", "'package.json' has 'typings' field 'jquery.d.ts' that references 'types/jquery/jquery.d.ts'.", "File 'types/jquery/jquery.d.ts' exist - use it as a name resolution result.", "Resolving real path for 'types/jquery/jquery.d.ts', result '/foo/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 5b2d6695356b6..b5e324d8c369a 100644 --- a/tests/baselines/reference/library-reference-11.trace.json +++ b/tests/baselines/reference/library-reference-11.trace.json @@ -3,8 +3,8 @@ "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'.", + "'package.json' does not have a 'typesVersions' field.", "Found 'package.json' at '/a/node_modules/jquery/package.json'.", "File '/a/node_modules/jquery.d.ts' does not exist.", "'package.json' has 'typings' field 'jquery.d.ts' that references '/a/node_modules/jquery/jquery.d.ts'.", diff --git a/tests/baselines/reference/library-reference-12.trace.json b/tests/baselines/reference/library-reference-12.trace.json index f6c1aef48114c..1421f1501d932 100644 --- a/tests/baselines/reference/library-reference-12.trace.json +++ b/tests/baselines/reference/library-reference-12.trace.json @@ -3,9 +3,9 @@ "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'.", + "'package.json' does not have a 'typesVersions' field.", "Found 'package.json' at '/a/node_modules/jquery/package.json'.", "File '/a/node_modules/jquery.d.ts' does not exist.", "'package.json' does not have a 'typings' field.", diff --git a/tests/baselines/reference/library-reference-2.trace.json b/tests/baselines/reference/library-reference-2.trace.json index baef46d89952c..8a13d1e6f5455 100644 --- a/tests/baselines/reference/library-reference-2.trace.json +++ b/tests/baselines/reference/library-reference-2.trace.json @@ -1,10 +1,11 @@ [ "======== 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'.", + "'package.json' does not have a 'typesVersions' field.", "Found 'package.json' at '/types/jquery/package.json'.", + "'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'.", "File '/types/jquery/jquery.d.ts' exist - use it as a name resolution result.", @@ -12,10 +13,11 @@ "======== 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'.", + "'package.json' does not have a 'typesVersions' field.", "Found 'package.json' at '/types/jquery/package.json'.", + "'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'.", "File '/types/jquery/jquery.d.ts' exist - use it as a name resolution result.", diff --git a/tests/baselines/reference/moduleResolutionWithExtensions_unexpected.trace.json b/tests/baselines/reference/moduleResolutionWithExtensions_unexpected.trace.json index 2f743d9e200e8..d386774db15ac 100644 --- a/tests/baselines/reference/moduleResolutionWithExtensions_unexpected.trace.json +++ b/tests/baselines/reference/moduleResolutionWithExtensions_unexpected.trace.json @@ -2,10 +2,10 @@ "======== 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'.", + "'package.json' does not have a 'typesVersions' field.", "Found 'package.json' at '/node_modules/normalize.css/package.json'.", "File '/node_modules/normalize.css.ts' does not exist.", "File '/node_modules/normalize.css.tsx' does not exist.", @@ -25,10 +25,10 @@ "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'.", + "'package.json' does not have a 'typesVersions' field.", "Found 'package.json' at '/node_modules/normalize.css/package.json'.", "File '/node_modules/normalize.css.js' does not exist.", "File '/node_modules/normalize.css.jsx' does not exist.", diff --git a/tests/baselines/reference/moduleResolutionWithExtensions_unexpected2.trace.json b/tests/baselines/reference/moduleResolutionWithExtensions_unexpected2.trace.json index 0661025355823..09a7bf81c98ab 100644 --- a/tests/baselines/reference/moduleResolutionWithExtensions_unexpected2.trace.json +++ b/tests/baselines/reference/moduleResolutionWithExtensions_unexpected2.trace.json @@ -2,9 +2,9 @@ "======== 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'.", + "'package.json' does not have a 'typesVersions' field.", "Found 'package.json' at '/node_modules/foo/package.json'.", "File '/node_modules/foo.ts' does not exist.", "File '/node_modules/foo.tsx' does not exist.", @@ -27,9 +27,9 @@ "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'.", + "'package.json' does not have a 'typesVersions' field.", "Found 'package.json' at '/node_modules/foo/package.json'.", "File '/node_modules/foo.js' does not exist.", "File '/node_modules/foo.jsx' does not exist.", diff --git a/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot.trace.json b/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot.trace.json index 2a4a1e71a4a9e..dbd645d9d65d8 100644 --- a/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot.trace.json +++ b/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot.trace.json @@ -2,9 +2,9 @@ "======== 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'.", + "'package.json' does not have a 'typesVersions' field.", "Found 'package.json' at '/node_modules/foo/bar/package.json'.", "File '/node_modules/foo/bar.ts' does not exist.", "File '/node_modules/foo/bar.tsx' does not exist.", diff --git a/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot_fakeScopedPackage.trace.json b/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot_fakeScopedPackage.trace.json index b54519397ab32..e47dcc86b1234 100644 --- a/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot_fakeScopedPackage.trace.json +++ b/tests/baselines/reference/moduleResolution_packageJson_notAtPackageRoot_fakeScopedPackage.trace.json @@ -2,9 +2,9 @@ "======== 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'.", + "'package.json' does not have a 'typesVersions' field.", "Found 'package.json' at '/node_modules/foo/@bar/package.json'.", "File '/node_modules/foo/@bar.ts' does not exist.", "File '/node_modules/foo/@bar.tsx' does not exist.", diff --git a/tests/baselines/reference/moduleResolution_packageJson_scopedPackage.trace.json b/tests/baselines/reference/moduleResolution_packageJson_scopedPackage.trace.json index 389bd892d2fdc..a8e509ff6e8af 100644 --- a/tests/baselines/reference/moduleResolution_packageJson_scopedPackage.trace.json +++ b/tests/baselines/reference/moduleResolution_packageJson_scopedPackage.trace.json @@ -2,9 +2,9 @@ "======== 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'.", + "'package.json' does not have a 'typesVersions' field.", "Found 'package.json' at '/node_modules/@foo/bar/package.json'.", "File '/node_modules/@foo/bar.ts' does not exist.", "File '/node_modules/@foo/bar.tsx' 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 84b7a4873c0ca..4d7ae4878139c 100644 --- a/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot_mainFieldInSubDirectory.trace.json +++ b/tests/baselines/reference/moduleResolution_packageJson_yesAtPackageRoot_mainFieldInSubDirectory.trace.json @@ -2,10 +2,10 @@ "======== 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'.", + "'package.json' does not have a 'typesVersions' field.", "Found 'package.json' at '/node_modules/foo/package.json'. Package ID is 'foo/src/index.d.ts@1.2.3'.", "File '/node_modules/foo.ts' does not exist.", "File '/node_modules/foo.tsx' does not exist.", diff --git a/tests/baselines/reference/packageJsonMain.trace.json b/tests/baselines/reference/packageJsonMain.trace.json index 583fc96774e56..1f722312e1d77 100644 --- a/tests/baselines/reference/packageJsonMain.trace.json +++ b/tests/baselines/reference/packageJsonMain.trace.json @@ -2,10 +2,10 @@ "======== 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'.", + "'package.json' does not have a 'typesVersions' field.", "Found 'package.json' at '/node_modules/foo/package.json'.", "File '/node_modules/foo.ts' does not exist.", "File '/node_modules/foo.tsx' does not exist.", @@ -24,10 +24,10 @@ "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'.", + "'package.json' does not have a 'typesVersions' field.", "Found 'package.json' at '/node_modules/foo/package.json'.", "File '/node_modules/foo.js' does not exist.", "File '/node_modules/foo.jsx' does not exist.", @@ -40,10 +40,10 @@ "======== 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'.", + "'package.json' does not have a 'typesVersions' field.", "Found 'package.json' at '/node_modules/bar/package.json'.", "File '/node_modules/bar.ts' does not exist.", "File '/node_modules/bar.tsx' does not exist.", @@ -67,10 +67,10 @@ "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'.", + "'package.json' does not have a 'typesVersions' field.", "Found 'package.json' at '/node_modules/bar/package.json'.", "File '/node_modules/bar.js' does not exist.", "File '/node_modules/bar.jsx' does not exist.", @@ -81,10 +81,10 @@ "======== 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'.", + "'package.json' does not have a 'typesVersions' field.", "Found 'package.json' at '/node_modules/baz/package.json'.", "File '/node_modules/baz.ts' does not exist.", "File '/node_modules/baz.tsx' does not exist.", @@ -105,10 +105,10 @@ "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'.", + "'package.json' does not have a 'typesVersions' field.", "Found 'package.json' at '/node_modules/baz/package.json'.", "File '/node_modules/baz.js' does not exist.", "File '/node_modules/baz.jsx' does not exist.", diff --git a/tests/baselines/reference/packageJsonMain_isNonRecursive.trace.json b/tests/baselines/reference/packageJsonMain_isNonRecursive.trace.json index b7d26d0f85258..f2f16ec6aebf8 100644 --- a/tests/baselines/reference/packageJsonMain_isNonRecursive.trace.json +++ b/tests/baselines/reference/packageJsonMain_isNonRecursive.trace.json @@ -2,10 +2,10 @@ "======== 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'.", + "'package.json' does not have a 'typesVersions' field.", "Found 'package.json' at '/node_modules/foo/package.json'.", "File '/node_modules/foo.ts' does not exist.", "File '/node_modules/foo.tsx' does not exist.", @@ -26,10 +26,10 @@ "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'.", + "'package.json' does not have a 'typesVersions' field.", "Found 'package.json' at '/node_modules/foo/package.json'.", "File '/node_modules/foo.js' does not exist.", "File '/node_modules/foo.jsx' does not exist.", diff --git a/tests/baselines/reference/reactTransitiveImportHasValidDeclaration.js b/tests/baselines/reference/reactTransitiveImportHasValidDeclaration.js index 75086611695c2..4cd606eae0ed0 100644 --- a/tests/baselines/reference/reactTransitiveImportHasValidDeclaration.js +++ b/tests/baselines/reference/reactTransitiveImportHasValidDeclaration.js @@ -43,7 +43,6 @@ exports["default"] = Form; //// [index.d.ts] -/// /// declare const Form: import("create-emotion-styled/types/react").StyledOtherComponent<{}, import("react").DetailedHTMLProps, HTMLDivElement>, any>; export default Form; diff --git a/tests/baselines/reference/typesVersions.ambientModules.js b/tests/baselines/reference/typesVersions.ambientModules.js index c7f198b8467b3..5dc00d8b376fc 100644 --- a/tests/baselines/reference/typesVersions.ambientModules.js +++ b/tests/baselines/reference/typesVersions.ambientModules.js @@ -6,7 +6,7 @@ "version": "1.0.0", "types": "index", "typesVersions": { - "3.0": "ts3.0" + "3.0": { "*" : ["ts3.0/*"] } } } diff --git a/tests/baselines/reference/typesVersions.ambientModules.trace.json b/tests/baselines/reference/typesVersions.ambientModules.trace.json index 0bf8bc16c5d27..f40d37bd7c3a6 100644 --- a/tests/baselines/reference/typesVersions.ambientModules.trace.json +++ b/tests/baselines/reference/typesVersions.ambientModules.trace.json @@ -2,15 +2,18 @@ "======== 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 'typesVersions['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' has 'types' field 'index' that references 'tests/cases/conformance/moduleResolution/node_modules/ext/index'.", + "'package.json' has a 'typesVersions' field with version-specific path mappings.", + "Found 'package.json' at 'tests/cases/conformance/moduleResolution/node_modules/ext/package.json'. Package ID is 'ext/index.d.ts@1.0.0'.", + "File 'tests/cases/conformance/moduleResolution/node_modules/ext.ts' does not exist.", + "File 'tests/cases/conformance/moduleResolution/node_modules/ext.tsx' does not exist.", + "File 'tests/cases/conformance/moduleResolution/node_modules/ext.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'.", + "'package.json' has 'types' field 'index' that references 'tests/cases/conformance/moduleResolution/node_modules/ext/index'.", + "'package.json' has a 'typesVersions' entry '3.0' that matches compiler version '3.1', looking for a pattern to match module name 'index'.", + "Module name 'index', matched pattern '*'.", + "Trying substitution 'ts3.0/*', candidate module location: '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.", @@ -21,8 +24,11 @@ "======== 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 'typesVersions['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'.", + "'package.json' has a 'typesVersions' field with version-specific path mappings.", + "Found 'package.json' at 'tests/cases/conformance/moduleResolution/node_modules/ext/package.json'. Package ID is 'ext/other/index.d.ts@1.0.0'.", + "'package.json' has a 'typesVersions' entry '3.0' that matches compiler version '3.1', looking for a pattern to match module name 'other'.", + "Module name 'other', matched pattern '*'.", + "Trying substitution 'ts3.0/*', candidate module location: 'ts3.0/other'.", "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.", @@ -33,8 +39,11 @@ "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 'typesVersions['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'.", + "'package.json' has a 'typesVersions' field with version-specific path mappings.", + "Found 'package.json' at 'tests/cases/conformance/moduleResolution/node_modules/ext/package.json'. Package ID is 'ext/other/index.d.ts@1.0.0'.", + "'package.json' has a 'typesVersions' entry '3.0' that matches compiler version '3.1', looking for a pattern to match module name 'other'.", + "Module name 'other', matched pattern '*'.", + "Trying substitution 'ts3.0/*', candidate module location: 'ts3.0/other'.", "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.", diff --git a/tests/baselines/reference/typesVersions.multiFile.js b/tests/baselines/reference/typesVersions.multiFile.js index 98a1331500b4f..0d3b91f7b13ed 100644 --- a/tests/baselines/reference/typesVersions.multiFile.js +++ b/tests/baselines/reference/typesVersions.multiFile.js @@ -6,7 +6,7 @@ "version": "1.0.0", "types": "index", "typesVersions": { - "3.0": "ts3.0" + "3.0": { "*" : ["ts3.0/*"] } } } diff --git a/tests/baselines/reference/typesVersions.multiFile.trace.json b/tests/baselines/reference/typesVersions.multiFile.trace.json index 2508681421b5c..6884322c301f3 100644 --- a/tests/baselines/reference/typesVersions.multiFile.trace.json +++ b/tests/baselines/reference/typesVersions.multiFile.trace.json @@ -2,15 +2,18 @@ "======== 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 'typesVersions['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' has 'types' field 'index' that references 'tests/cases/conformance/moduleResolution/node_modules/ext/index'.", + "'package.json' has a 'typesVersions' field with version-specific path mappings.", + "Found 'package.json' at 'tests/cases/conformance/moduleResolution/node_modules/ext/package.json'. Package ID is 'ext/index.d.ts@1.0.0'.", + "File 'tests/cases/conformance/moduleResolution/node_modules/ext.ts' does not exist.", + "File 'tests/cases/conformance/moduleResolution/node_modules/ext.tsx' does not exist.", + "File 'tests/cases/conformance/moduleResolution/node_modules/ext.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'.", + "'package.json' has 'types' field 'index' that references 'tests/cases/conformance/moduleResolution/node_modules/ext/index'.", + "'package.json' has a 'typesVersions' entry '3.0' that matches compiler version '3.1', looking for a pattern to match module name 'index'.", + "Module name 'index', matched pattern '*'.", + "Trying substitution 'ts3.0/*', candidate module location: '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.", @@ -21,8 +24,11 @@ "======== 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 'typesVersions['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'.", + "'package.json' has a 'typesVersions' field with version-specific path mappings.", + "Found 'package.json' at 'tests/cases/conformance/moduleResolution/node_modules/ext/package.json'. Package ID is 'ext/other/index.d.ts@1.0.0'.", + "'package.json' has a 'typesVersions' entry '3.0' that matches compiler version '3.1', looking for a pattern to match module name 'other'.", + "Module name 'other', matched pattern '*'.", + "Trying substitution 'ts3.0/*', candidate module location: 'ts3.0/other'.", "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.", diff --git a/tests/baselines/reference/typesVersionsDeclarationEmit.ambient.js b/tests/baselines/reference/typesVersionsDeclarationEmit.ambient.js new file mode 100644 index 0000000000000..a226df8e87361 --- /dev/null +++ b/tests/baselines/reference/typesVersionsDeclarationEmit.ambient.js @@ -0,0 +1,51 @@ +//// [tests/cases/conformance/declarationEmit/typesVersionsDeclarationEmit.ambient.ts] //// + +//// [package.json] +{ + "name": "ext", + "version": "1.0.0", + "types": "index", + "typesVersions": { + "3.0": { "*" : ["ts3.0/*"] } + } +} + +//// [index.d.ts] +declare module "ext" { + export interface A {} + export function fa(): A; +} +declare module "ext/other" { + export interface B {} + export function fb(): B; +} +//// [index.d.ts] +declare module "ext" { + export interface A {} + export function fa(): A; +} +declare module "ext/other" { + export interface B {} + export function fb(): B; +} + +//// [main.ts] +import { fa } from "ext"; +import { fb } from "ext/other"; + +export const va = fa(); +export const vb = fb(); + + +//// [main.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const ext_1 = require("ext"); +const other_1 = require("ext/other"); +exports.va = ext_1.fa(); +exports.vb = other_1.fb(); + + +//// [main.d.ts] +export declare const va: import("ext").A; +export declare const vb: import("ext/other").B; diff --git a/tests/baselines/reference/typesVersionsDeclarationEmit.ambient.symbols b/tests/baselines/reference/typesVersionsDeclarationEmit.ambient.symbols new file mode 100644 index 0000000000000..15d1718cce77f --- /dev/null +++ b/tests/baselines/reference/typesVersionsDeclarationEmit.ambient.symbols @@ -0,0 +1,37 @@ +=== tests/cases/conformance/declarationEmit/main.ts === +import { fa } from "ext"; +>fa : Symbol(fa, Decl(main.ts, 0, 8)) + +import { fb } from "ext/other"; +>fb : Symbol(fb, Decl(main.ts, 1, 8)) + +export const va = fa(); +>va : Symbol(va, Decl(main.ts, 3, 12)) +>fa : Symbol(fa, Decl(main.ts, 0, 8)) + +export const vb = fb(); +>vb : Symbol(vb, Decl(main.ts, 4, 12)) +>fb : Symbol(fb, Decl(main.ts, 1, 8)) + +=== tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/index.d.ts === +declare module "ext" { +>"ext" : Symbol("ext", Decl(index.d.ts, 0, 0)) + + export interface A {} +>A : Symbol(A, Decl(index.d.ts, 0, 22)) + + export function fa(): A; +>fa : Symbol(fa, Decl(index.d.ts, 1, 25)) +>A : Symbol(A, Decl(index.d.ts, 0, 22)) +} +declare module "ext/other" { +>"ext/other" : Symbol("ext/other", Decl(index.d.ts, 3, 1)) + + export interface B {} +>B : Symbol(B, Decl(index.d.ts, 4, 28)) + + export function fb(): B; +>fb : Symbol(fb, Decl(index.d.ts, 5, 25)) +>B : Symbol(B, Decl(index.d.ts, 4, 28)) +} + diff --git a/tests/baselines/reference/typesVersionsDeclarationEmit.ambient.trace.json b/tests/baselines/reference/typesVersionsDeclarationEmit.ambient.trace.json new file mode 100644 index 0000000000000..f973d37cd5878 --- /dev/null +++ b/tests/baselines/reference/typesVersionsDeclarationEmit.ambient.trace.json @@ -0,0 +1,55 @@ +[ + "======== Resolving module 'ext' from 'tests/cases/conformance/declarationEmit/main.ts'. ========", + "Module resolution kind is not specified, using 'NodeJs'.", + "Loading module 'ext' from 'node_modules' folder, target file type 'TypeScript'.", + "'package.json' does not have a 'typings' field.", + "'package.json' has 'types' field 'index' that references 'tests/cases/conformance/declarationEmit/node_modules/ext/index'.", + "'package.json' has a 'typesVersions' field with version-specific path mappings.", + "Found 'package.json' at 'tests/cases/conformance/declarationEmit/node_modules/ext/package.json'. Package ID is 'ext/index.d.ts@1.0.0'.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext.ts' does not exist.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext.tsx' does not exist.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext.d.ts' does not exist.", + "'package.json' does not have a 'typings' field.", + "'package.json' has 'types' field 'index' that references 'tests/cases/conformance/declarationEmit/node_modules/ext/index'.", + "'package.json' has a 'typesVersions' entry '3.0' that matches compiler version '3.1', looking for a pattern to match module name 'index'.", + "Module name 'index', matched pattern '*'.", + "Trying substitution 'ts3.0/*', candidate module location: 'ts3.0/index'.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/index' does not exist.", + "Loading module as file / folder, candidate module location 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/index', target file type 'TypeScript'.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/index.ts' does not exist.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/index.tsx' does not exist.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/index.d.ts' exist - use it as a name resolution result.", + "Resolving real path for 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/index.d.ts', result 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/index.d.ts'.", + "======== Module name 'ext' was successfully resolved to 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/index.d.ts'. ========", + "======== Resolving module 'ext/other' from 'tests/cases/conformance/declarationEmit/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 a 'typesVersions' field with version-specific path mappings.", + "Found 'package.json' at 'tests/cases/conformance/declarationEmit/node_modules/ext/package.json'. Package ID is 'ext/other/index.d.ts@1.0.0'.", + "'package.json' has a 'typesVersions' entry '3.0' that matches compiler version '3.1', looking for a pattern to match module name 'other'.", + "Module name 'other', matched pattern '*'.", + "Trying substitution 'ts3.0/*', candidate module location: 'ts3.0/other'.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/other.ts' does not exist.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/other.tsx' does not exist.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/other.d.ts' does not exist.", + "Directory 'tests/cases/conformance/declarationEmit/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 a 'typesVersions' field with version-specific path mappings.", + "Found 'package.json' at 'tests/cases/conformance/declarationEmit/node_modules/ext/package.json'. Package ID is 'ext/other/index.d.ts@1.0.0'.", + "'package.json' has a 'typesVersions' entry '3.0' that matches compiler version '3.1', looking for a pattern to match module name 'other'.", + "Module name 'other', matched pattern '*'.", + "Trying substitution 'ts3.0/*', candidate module location: 'ts3.0/other'.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/other.js' does not exist.", + "File 'tests/cases/conformance/declarationEmit/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/typesVersionsDeclarationEmit.ambient.types b/tests/baselines/reference/typesVersionsDeclarationEmit.ambient.types new file mode 100644 index 0000000000000..9f47ca9750c23 --- /dev/null +++ b/tests/baselines/reference/typesVersionsDeclarationEmit.ambient.types @@ -0,0 +1,33 @@ +=== tests/cases/conformance/declarationEmit/main.ts === +import { fa } from "ext"; +>fa : () => import("ext").A + +import { fb } from "ext/other"; +>fb : () => import("ext/other").B + +export const va = fa(); +>va : import("ext").A +>fa() : import("ext").A +>fa : () => import("ext").A + +export const vb = fb(); +>vb : import("ext/other").B +>fb() : import("ext/other").B +>fb : () => import("ext/other").B + +=== tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/index.d.ts === +declare module "ext" { +>"ext" : typeof import("ext") + + export interface A {} + export function fa(): A; +>fa : () => A +} +declare module "ext/other" { +>"ext/other" : typeof import("ext/other") + + export interface B {} + export function fb(): B; +>fb : () => B +} + diff --git a/tests/baselines/reference/typesVersionsDeclarationEmit.multiFile.js b/tests/baselines/reference/typesVersionsDeclarationEmit.multiFile.js new file mode 100644 index 0000000000000..4a1edf5c97e2b --- /dev/null +++ b/tests/baselines/reference/typesVersionsDeclarationEmit.multiFile.js @@ -0,0 +1,48 @@ +//// [tests/cases/conformance/declarationEmit/typesVersionsDeclarationEmit.multiFile.ts] //// + +//// [package.json] +{ + "name": "ext", + "version": "1.0.0", + "types": "index", + "typesVersions": { + "3.0": { "*" : ["ts3.0/*"] } + } +} + +//// [index.d.ts] +export interface A {} +export function fa(): A; + +//// [other.d.ts] +export interface B {} +export function fb(): B; + +//// [index.d.ts] +export interface A {} +export function fa(): A; + +//// [other.d.ts] +export interface B {} +export function fb(): B; + +//// [main.ts] +import { fa } from "ext"; +import { fb } from "ext/other"; + +export const va = fa(); +export const vb = fb(); + + +//// [main.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const ext_1 = require("ext"); +const other_1 = require("ext/other"); +exports.va = ext_1.fa(); +exports.vb = other_1.fb(); + + +//// [main.d.ts] +export declare const va: import("ext").A; +export declare const vb: import("ext/other").B; diff --git a/tests/baselines/reference/typesVersionsDeclarationEmit.multiFile.symbols b/tests/baselines/reference/typesVersionsDeclarationEmit.multiFile.symbols new file mode 100644 index 0000000000000..e5db04915416c --- /dev/null +++ b/tests/baselines/reference/typesVersionsDeclarationEmit.multiFile.symbols @@ -0,0 +1,47 @@ +=== tests/cases/conformance/declarationEmit/node_modules/ext/index.d.ts === +export interface A {} +>A : Symbol(A, Decl(index.d.ts, 0, 0)) + +export function fa(): A; +>fa : Symbol(fa, Decl(index.d.ts, 0, 21)) +>A : Symbol(A, Decl(index.d.ts, 0, 0)) + +=== tests/cases/conformance/declarationEmit/node_modules/ext/other.d.ts === +export interface B {} +>B : Symbol(B, Decl(other.d.ts, 0, 0)) + +export function fb(): B; +>fb : Symbol(fb, Decl(other.d.ts, 0, 21)) +>B : Symbol(B, Decl(other.d.ts, 0, 0)) + +=== tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/index.d.ts === +export interface A {} +>A : Symbol(A, Decl(index.d.ts, 0, 0)) + +export function fa(): A; +>fa : Symbol(fa, Decl(index.d.ts, 0, 21)) +>A : Symbol(A, Decl(index.d.ts, 0, 0)) + +=== tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/other.d.ts === +export interface B {} +>B : Symbol(B, Decl(other.d.ts, 0, 0)) + +export function fb(): B; +>fb : Symbol(fb, Decl(other.d.ts, 0, 21)) +>B : Symbol(B, Decl(other.d.ts, 0, 0)) + +=== tests/cases/conformance/declarationEmit/main.ts === +import { fa } from "ext"; +>fa : Symbol(fa, Decl(main.ts, 0, 8)) + +import { fb } from "ext/other"; +>fb : Symbol(fb, Decl(main.ts, 1, 8)) + +export const va = fa(); +>va : Symbol(va, Decl(main.ts, 3, 12)) +>fa : Symbol(fa, Decl(main.ts, 0, 8)) + +export const vb = fb(); +>vb : Symbol(vb, Decl(main.ts, 4, 12)) +>fb : Symbol(fb, Decl(main.ts, 1, 8)) + diff --git a/tests/baselines/reference/typesVersionsDeclarationEmit.multiFile.trace.json b/tests/baselines/reference/typesVersionsDeclarationEmit.multiFile.trace.json new file mode 100644 index 0000000000000..0296a58b8962b --- /dev/null +++ b/tests/baselines/reference/typesVersionsDeclarationEmit.multiFile.trace.json @@ -0,0 +1,37 @@ +[ + "======== Resolving module 'ext' from 'tests/cases/conformance/declarationEmit/main.ts'. ========", + "Module resolution kind is not specified, using 'NodeJs'.", + "Loading module 'ext' from 'node_modules' folder, target file type 'TypeScript'.", + "'package.json' does not have a 'typings' field.", + "'package.json' has 'types' field 'index' that references 'tests/cases/conformance/declarationEmit/node_modules/ext/index'.", + "'package.json' has a 'typesVersions' field with version-specific path mappings.", + "Found 'package.json' at 'tests/cases/conformance/declarationEmit/node_modules/ext/package.json'. Package ID is 'ext/index.d.ts@1.0.0'.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext.ts' does not exist.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext.tsx' does not exist.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext.d.ts' does not exist.", + "'package.json' does not have a 'typings' field.", + "'package.json' has 'types' field 'index' that references 'tests/cases/conformance/declarationEmit/node_modules/ext/index'.", + "'package.json' has a 'typesVersions' entry '3.0' that matches compiler version '3.1', looking for a pattern to match module name 'index'.", + "Module name 'index', matched pattern '*'.", + "Trying substitution 'ts3.0/*', candidate module location: 'ts3.0/index'.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/index' does not exist.", + "Loading module as file / folder, candidate module location 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/index', target file type 'TypeScript'.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/index.ts' does not exist.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/index.tsx' does not exist.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/index.d.ts' exist - use it as a name resolution result.", + "Resolving real path for 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/index.d.ts', result 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/index.d.ts'.", + "======== Module name 'ext' was successfully resolved to 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/index.d.ts'. ========", + "======== Resolving module 'ext/other' from 'tests/cases/conformance/declarationEmit/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 a 'typesVersions' field with version-specific path mappings.", + "Found 'package.json' at 'tests/cases/conformance/declarationEmit/node_modules/ext/package.json'. Package ID is 'ext/other/index.d.ts@1.0.0'.", + "'package.json' has a 'typesVersions' entry '3.0' that matches compiler version '3.1', looking for a pattern to match module name 'other'.", + "Module name 'other', matched pattern '*'.", + "Trying substitution 'ts3.0/*', candidate module location: 'ts3.0/other'.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/other.ts' does not exist.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/other.tsx' does not exist.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/other.d.ts' exist - use it as a name resolution result.", + "Resolving real path for 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/other.d.ts', result 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/other.d.ts'.", + "======== Module name 'ext/other' was successfully resolved to 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/other.d.ts'. ========" +] \ No newline at end of file diff --git a/tests/baselines/reference/typesVersionsDeclarationEmit.multiFile.types b/tests/baselines/reference/typesVersionsDeclarationEmit.multiFile.types new file mode 100644 index 0000000000000..73721bafec1a6 --- /dev/null +++ b/tests/baselines/reference/typesVersionsDeclarationEmit.multiFile.types @@ -0,0 +1,37 @@ +=== tests/cases/conformance/declarationEmit/node_modules/ext/index.d.ts === +export interface A {} +export function fa(): A; +>fa : () => A + +=== tests/cases/conformance/declarationEmit/node_modules/ext/other.d.ts === +export interface B {} +export function fb(): B; +>fb : () => B + +=== tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/index.d.ts === +export interface A {} +export function fa(): A; +>fa : () => A + +=== tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/other.d.ts === +export interface B {} +export function fb(): B; +>fb : () => B + +=== tests/cases/conformance/declarationEmit/main.ts === +import { fa } from "ext"; +>fa : () => import("tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/index").A + +import { fb } from "ext/other"; +>fb : () => import("tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/other").B + +export const va = fa(); +>va : import("tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/index").A +>fa() : import("tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/index").A +>fa : () => import("tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/index").A + +export const vb = fb(); +>vb : import("tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/other").B +>fb() : import("tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/other").B +>fb : () => import("tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/other").B + diff --git a/tests/baselines/reference/typingsLookup4.trace.json b/tests/baselines/reference/typingsLookup4.trace.json index 30d0122b8fde2..86b386670d6a5 100644 --- a/tests/baselines/reference/typingsLookup4.trace.json +++ b/tests/baselines/reference/typingsLookup4.trace.json @@ -5,8 +5,8 @@ "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'.", + "'package.json' does not have a 'typesVersions' field.", "Found 'package.json' at '/node_modules/@types/jquery/package.json'.", "File '/node_modules/@types/jquery.d.ts' does not exist.", "'package.json' has 'typings' field 'jquery.d.ts' that references '/node_modules/@types/jquery/jquery.d.ts'.", @@ -19,8 +19,8 @@ "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'.", + "'package.json' does not have a 'typesVersions' field.", "Found 'package.json' at '/node_modules/@types/kquery/package.json'.", "File '/node_modules/@types/kquery.d.ts' does not exist.", "'package.json' has 'typings' field 'kquery' that references '/node_modules/@types/kquery/kquery'.", @@ -37,8 +37,8 @@ "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'.", + "'package.json' does not have a 'typesVersions' field.", "Found 'package.json' at '/node_modules/@types/lquery/package.json'.", "File '/node_modules/@types/lquery.d.ts' does not exist.", "'package.json' has 'typings' field 'lquery' that references '/node_modules/@types/lquery/lquery'.", @@ -53,8 +53,8 @@ "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'.", + "'package.json' does not have a 'typesVersions' field.", "Found 'package.json' at '/node_modules/@types/mquery/package.json'.", "File '/node_modules/@types/mquery.d.ts' does not exist.", "'package.json' has 'typings' field 'mquery' that references '/node_modules/@types/mquery/mquery'.", @@ -69,18 +69,20 @@ "======== 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'.", + "'package.json' does not have a 'typesVersions' field.", "Found 'package.json' at '/node_modules/@types/jquery/package.json'.", + "'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'.", "File '/node_modules/@types/jquery/jquery.d.ts' exist - use it as a name resolution result.", "Resolving real path for '/node_modules/@types/jquery/jquery.d.ts', result '/node_modules/@types/jquery/jquery.d.ts'.", "======== 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'.", + "'package.json' does not have a 'typesVersions' field.", "Found 'package.json' at '/node_modules/@types/kquery/package.json'.", + "'package.json' does not have a 'typesVersions' field.", "'package.json' has 'typings' field 'kquery' that references '/node_modules/@types/kquery/kquery'.", "File '/node_modules/@types/kquery/kquery' does not exist.", "Loading module as file / folder, candidate module location '/node_modules/@types/kquery/kquery', target file type 'TypeScript'.", @@ -91,9 +93,10 @@ "======== 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'.", + "'package.json' does not have a 'typesVersions' field.", "Found 'package.json' at '/node_modules/@types/lquery/package.json'.", + "'package.json' does not have a 'typesVersions' field.", "'package.json' has 'typings' field 'lquery' that references '/node_modules/@types/lquery/lquery'.", "File '/node_modules/@types/lquery/lquery' does not exist.", "Loading module as file / folder, candidate module location '/node_modules/@types/lquery/lquery', target file type 'TypeScript'.", @@ -102,9 +105,10 @@ "======== 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'.", + "'package.json' does not have a 'typesVersions' field.", "Found 'package.json' at '/node_modules/@types/mquery/package.json'.", + "'package.json' does not have a 'typesVersions' field.", "'package.json' has 'typings' field 'mquery' that references '/node_modules/@types/mquery/mquery'.", "File '/node_modules/@types/mquery/mquery' does not exist.", "Loading module as file / folder, candidate module location '/node_modules/@types/mquery/mquery', target file type 'TypeScript'.", diff --git a/tests/cases/conformance/declarationEmit/typesVersionsDeclarationEmit.ambient.ts b/tests/cases/conformance/declarationEmit/typesVersionsDeclarationEmit.ambient.ts new file mode 100644 index 0000000000000..27bba8e830e7f --- /dev/null +++ b/tests/cases/conformance/declarationEmit/typesVersionsDeclarationEmit.ambient.ts @@ -0,0 +1,43 @@ +// @traceResolution: true +// @target: esnext +// @module: commonjs +// @declaration: true +// @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 interface A {} + export function fa(): A; +} +declare module "ext/other" { + export interface B {} + export function fb(): B; +} +// @filename: node_modules/ext/ts3.0/index.d.ts +declare module "ext" { + export interface A {} + export function fa(): A; +} +declare module "ext/other" { + export interface B {} + export function fb(): B; +} + +// @filename: main.ts +import { fa } from "ext"; +import { fb } from "ext/other"; + +export const va = fa(); +export const vb = fb(); + +// @filename: tsconfig.json +{} \ No newline at end of file diff --git a/tests/cases/conformance/declarationEmit/typesVersionsDeclarationEmit.multiFile.ts b/tests/cases/conformance/declarationEmit/typesVersionsDeclarationEmit.multiFile.ts new file mode 100644 index 0000000000000..dd71b9b13e236 --- /dev/null +++ b/tests/cases/conformance/declarationEmit/typesVersionsDeclarationEmit.multiFile.ts @@ -0,0 +1,39 @@ +// @traceResolution: true +// @target: esnext +// @module: commonjs +// @declaration: 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 +export interface A {} +export function fa(): A; + +// @filename: node_modules/ext/other.d.ts +export interface B {} +export function fb(): B; + +// @filename: node_modules/ext/ts3.0/index.d.ts +export interface A {} +export function fa(): A; + +// @filename: node_modules/ext/ts3.0/other.d.ts +export interface B {} +export function fb(): B; + +// @filename: main.ts +import { fa } from "ext"; +import { fb } from "ext/other"; + +export const va = fa(); +export const vb = fb(); + +// @filename: tsconfig.json +{} \ No newline at end of file diff --git a/tests/cases/conformance/moduleResolution/typesVersions.ambientModules.ts b/tests/cases/conformance/moduleResolution/typesVersions.ambientModules.ts index 781740d96d212..ac314e0c31320 100644 --- a/tests/cases/conformance/moduleResolution/typesVersions.ambientModules.ts +++ b/tests/cases/conformance/moduleResolution/typesVersions.ambientModules.ts @@ -8,7 +8,7 @@ "version": "1.0.0", "types": "index", "typesVersions": { - "3.0": "ts3.0" + "3.0": { "*" : ["ts3.0/*"] } } } diff --git a/tests/cases/conformance/moduleResolution/typesVersions.multiFile.ts b/tests/cases/conformance/moduleResolution/typesVersions.multiFile.ts index 44cf98e45c61a..c9001ca221936 100644 --- a/tests/cases/conformance/moduleResolution/typesVersions.multiFile.ts +++ b/tests/cases/conformance/moduleResolution/typesVersions.multiFile.ts @@ -7,7 +7,7 @@ "version": "1.0.0", "types": "index", "typesVersions": { - "3.0": "ts3.0" + "3.0": { "*" : ["ts3.0/*"] } } } diff --git a/tests/cases/fourslash/completionForStringLiteralNonrelativeImport13.ts b/tests/cases/fourslash/completionForStringLiteralNonrelativeImport13.ts index db88a272ad5eb..d1e67ae9a90b0 100644 --- a/tests/cases/fourslash/completionForStringLiteralNonrelativeImport13.ts +++ b/tests/cases/fourslash/completionForStringLiteralNonrelativeImport13.ts @@ -8,7 +8,7 @@ //// "version": "1.0.0", //// "types": "index", //// "typesVersions": { -//// "3.0": "ts3.0" +//// "3.0": { "*" : ["ts3.0/*"] } //// } //// } @@ -31,6 +31,6 @@ verify.completions({ marker: test.markerNames(), - exact: ["index", "zzz"], + exact: ["aaa", "index", "ts3.0", "zzz"], isNewIdentifierLocation: true, }); From 37ec065d93b7a193f68952bbd7f182565ffb9278 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Tue, 28 Aug 2018 11:44:40 -0700 Subject: [PATCH 07/10] Add path back-reference tests --- src/compiler/checker.ts | 2 +- .../reference/typesVersions.ambientModules.js | 10 +-- .../typesVersions.ambientModules.symbols | 10 +-- .../typesVersions.ambientModules.trace.json | 36 +++++----- .../typesVersions.ambientModules.types | 30 ++++----- .../reference/typesVersions.multiFile.js | 10 +-- .../reference/typesVersions.multiFile.symbols | 12 ++-- .../typesVersions.multiFile.trace.json | 32 ++++----- .../reference/typesVersions.multiFile.types | 32 ++++----- .../typesVersionsDeclarationEmit.ambient.js | 2 +- ...pesVersionsDeclarationEmit.ambient.symbols | 2 +- ...VersionsDeclarationEmit.ambient.trace.json | 36 +++++----- ...typesVersionsDeclarationEmit.ambient.types | 2 +- .../typesVersionsDeclarationEmit.multiFile.js | 2 +- ...sVersionsDeclarationEmit.multiFile.symbols | 4 +- ...rsionsDeclarationEmit.multiFile.trace.json | 32 ++++----- ...pesVersionsDeclarationEmit.multiFile.types | 20 +++--- ...it.multiFileBackReferenceToSelf.errors.txt | 38 +++++++++++ ...rationEmit.multiFileBackReferenceToSelf.js | 46 +++++++++++++ ...nEmit.multiFileBackReferenceToSelf.symbols | 37 +++++++++++ ...it.multiFileBackReferenceToSelf.trace.json | 65 +++++++++++++++++++ ...ionEmit.multiFileBackReferenceToSelf.types | 33 ++++++++++ ...onEmit.multiFileBackReferenceToUnmapped.js | 45 +++++++++++++ ...t.multiFileBackReferenceToUnmapped.symbols | 35 ++++++++++ ...ultiFileBackReferenceToUnmapped.trace.json | 44 +++++++++++++ ...mit.multiFileBackReferenceToUnmapped.types | 31 +++++++++ .../typesVersionsDeclarationEmit.ambient.ts | 4 +- .../typesVersionsDeclarationEmit.multiFile.ts | 6 +- ...rationEmit.multiFileBackReferenceToSelf.ts | 37 +++++++++++ ...onEmit.multiFileBackReferenceToUnmapped.ts | 36 ++++++++++ .../typesVersions.ambientModules.ts | 12 ++-- .../typesVersions.multiFile.ts | 14 ++-- 32 files changed, 602 insertions(+), 155 deletions(-) create mode 100644 tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToSelf.errors.txt create mode 100644 tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToSelf.js create mode 100644 tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToSelf.symbols create mode 100644 tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToSelf.trace.json create mode 100644 tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToSelf.types create mode 100644 tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToUnmapped.js create mode 100644 tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToUnmapped.symbols create mode 100644 tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToUnmapped.trace.json create mode 100644 tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToUnmapped.types create mode 100644 tests/cases/conformance/declarationEmit/typesVersionsDeclarationEmit.multiFileBackReferenceToSelf.ts create mode 100644 tests/cases/conformance/declarationEmit/typesVersionsDeclarationEmit.multiFileBackReferenceToUnmapped.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index d3974da993029..1e495bf538e22 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -22233,7 +22233,7 @@ namespace ts { for (const decl of indexSymbol.declarations) { const declaration = decl; if (declaration.parameters.length === 1 && declaration.parameters[0].type) { - switch (declaration.parameters[0].type.kind) { + switch (declaration.parameters[0].type!.kind) { case SyntaxKind.StringKeyword: if (!seenStringIndexer) { seenStringIndexer = true; diff --git a/tests/baselines/reference/typesVersions.ambientModules.js b/tests/baselines/reference/typesVersions.ambientModules.js index 5dc00d8b376fc..1d7e3f04ec30a 100644 --- a/tests/baselines/reference/typesVersions.ambientModules.js +++ b/tests/baselines/reference/typesVersions.ambientModules.js @@ -6,7 +6,7 @@ "version": "1.0.0", "types": "index", "typesVersions": { - "3.0": { "*" : ["ts3.0/*"] } + "3.1": { "*" : ["ts3.1/*"] } } } @@ -20,18 +20,18 @@ declare module "ext/other" { //// [index.d.ts] declare module "ext" { - export const a = "ts3.0 a"; + export const a = "ts3.1 a"; } declare module "ext/other" { - export const b = "ts3.0 b"; + export const b = "ts3.1 b"; } //// [main.ts] import { a } from "ext"; import { b } from "ext/other"; -const aa: "ts3.0 a" = a; -const bb: "ts3.0 b" = b; +const aa: "ts3.1 a" = a; +const bb: "ts3.1 b" = b; //// [main.js] diff --git a/tests/baselines/reference/typesVersions.ambientModules.symbols b/tests/baselines/reference/typesVersions.ambientModules.symbols index d8a0ab0f2ca6e..91d1adacd9c74 100644 --- a/tests/baselines/reference/typesVersions.ambientModules.symbols +++ b/tests/baselines/reference/typesVersions.ambientModules.symbols @@ -5,25 +5,25 @@ import { a } from "ext"; import { b } from "ext/other"; >b : Symbol(b, Decl(main.ts, 1, 8)) -const aa: "ts3.0 a" = a; +const aa: "ts3.1 a" = a; >aa : Symbol(aa, Decl(main.ts, 3, 5)) >a : Symbol(a, Decl(main.ts, 0, 8)) -const bb: "ts3.0 b" = b; +const bb: "ts3.1 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 === +=== tests/cases/conformance/moduleResolution/node_modules/ext/ts3.1/index.d.ts === declare module "ext" { >"ext" : Symbol("ext", Decl(index.d.ts, 0, 0)) - export const a = "ts3.0 a"; + export const a = "ts3.1 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"; + export const b = "ts3.1 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 index f40d37bd7c3a6..7a442ce50486f 100644 --- a/tests/baselines/reference/typesVersions.ambientModules.trace.json +++ b/tests/baselines/reference/typesVersions.ambientModules.trace.json @@ -11,27 +11,27 @@ "File 'tests/cases/conformance/moduleResolution/node_modules/ext.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/index'.", - "'package.json' has a 'typesVersions' entry '3.0' that matches compiler version '3.1', looking for a pattern to match module name 'index'.", + "'package.json' has a 'typesVersions' entry '3.1' that matches compiler version '3.1', looking for a pattern to match module name 'index'.", "Module name 'index', matched pattern '*'.", - "Trying substitution 'ts3.0/*', candidate module location: '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'. ========", + "Trying substitution 'ts3.1/*', candidate module location: 'ts3.1/index'.", + "File 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.1/index' does not exist.", + "Loading module as file / folder, candidate module location 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.1/index', target file type 'TypeScript'.", + "File 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.1/index.ts' does not exist.", + "File 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.1/index.tsx' does not exist.", + "File 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.1/index.d.ts' exist - use it as a name resolution result.", + "Resolving real path for 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.1/index.d.ts', result 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.1/index.d.ts'.", + "======== Module name 'ext' was successfully resolved to 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.1/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 a 'typesVersions' field with version-specific path mappings.", "Found 'package.json' at 'tests/cases/conformance/moduleResolution/node_modules/ext/package.json'. Package ID is 'ext/other/index.d.ts@1.0.0'.", - "'package.json' has a 'typesVersions' entry '3.0' that matches compiler version '3.1', looking for a pattern to match module name 'other'.", + "'package.json' has a 'typesVersions' entry '3.1' that matches compiler version '3.1', looking for a pattern to match module name 'other'.", "Module name 'other', matched pattern '*'.", - "Trying substitution 'ts3.0/*', candidate module location: 'ts3.0/other'.", - "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.", + "Trying substitution 'ts3.1/*', candidate module location: 'ts3.1/other'.", + "File 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.1/other.ts' does not exist.", + "File 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.1/other.tsx' does not exist.", + "File 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.1/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.", @@ -41,11 +41,11 @@ "Loading module 'ext/other' from 'node_modules' folder, target file type 'JavaScript'.", "'package.json' has a 'typesVersions' field with version-specific path mappings.", "Found 'package.json' at 'tests/cases/conformance/moduleResolution/node_modules/ext/package.json'. Package ID is 'ext/other/index.d.ts@1.0.0'.", - "'package.json' has a 'typesVersions' entry '3.0' that matches compiler version '3.1', looking for a pattern to match module name 'other'.", + "'package.json' has a 'typesVersions' entry '3.1' that matches compiler version '3.1', looking for a pattern to match module name 'other'.", "Module name 'other', matched pattern '*'.", - "Trying substitution 'ts3.0/*', candidate module location: 'ts3.0/other'.", - "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.", + "Trying substitution 'ts3.1/*', candidate module location: 'ts3.1/other'.", + "File 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.1/other.js' does not exist.", + "File 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.1/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.", diff --git a/tests/baselines/reference/typesVersions.ambientModules.types b/tests/baselines/reference/typesVersions.ambientModules.types index 20cd4112ebef2..0e81bad67a0e7 100644 --- a/tests/baselines/reference/typesVersions.ambientModules.types +++ b/tests/baselines/reference/typesVersions.ambientModules.types @@ -1,31 +1,31 @@ === tests/cases/conformance/moduleResolution/main.ts === import { a } from "ext"; ->a : "ts3.0 a" +>a : "ts3.1 a" import { b } from "ext/other"; ->b : "ts3.0 b" +>b : "ts3.1 b" -const aa: "ts3.0 a" = a; ->aa : "ts3.0 a" ->a : "ts3.0 a" +const aa: "ts3.1 a" = a; +>aa : "ts3.1 a" +>a : "ts3.1 a" -const bb: "ts3.0 b" = b; ->bb : "ts3.0 b" ->b : "ts3.0 b" +const bb: "ts3.1 b" = b; +>bb : "ts3.1 b" +>b : "ts3.1 b" -=== tests/cases/conformance/moduleResolution/node_modules/ext/ts3.0/index.d.ts === +=== tests/cases/conformance/moduleResolution/node_modules/ext/ts3.1/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" + export const a = "ts3.1 a"; +>a : "ts3.1 a" +>"ts3.1 a" : "ts3.1 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" + export const b = "ts3.1 b"; +>b : "ts3.1 b" +>"ts3.1 b" : "ts3.1 b" } diff --git a/tests/baselines/reference/typesVersions.multiFile.js b/tests/baselines/reference/typesVersions.multiFile.js index 0d3b91f7b13ed..14f7fd8aaf4c6 100644 --- a/tests/baselines/reference/typesVersions.multiFile.js +++ b/tests/baselines/reference/typesVersions.multiFile.js @@ -6,7 +6,7 @@ "version": "1.0.0", "types": "index", "typesVersions": { - "3.0": { "*" : ["ts3.0/*"] } + "3.1": { "*" : ["ts3.1/*"] } } } @@ -17,17 +17,17 @@ export const a = "default a"; export const b = "default b"; //// [index.d.ts] -export const a = "ts3.0 a"; +export const a = "ts3.1 a"; //// [other.d.ts] -export const b = "ts3.0 b"; +export const b = "ts3.1 b"; //// [main.ts] import { a } from "ext"; import { b } from "ext/other"; -const aa: "ts3.0 a" = a; -const bb: "ts3.0 b" = b; +const aa: "ts3.1 a" = a; +const bb: "ts3.1 b" = b; //// [main.js] diff --git a/tests/baselines/reference/typesVersions.multiFile.symbols b/tests/baselines/reference/typesVersions.multiFile.symbols index c79bb054609a7..11ea8b7857abb 100644 --- a/tests/baselines/reference/typesVersions.multiFile.symbols +++ b/tests/baselines/reference/typesVersions.multiFile.symbols @@ -6,12 +6,12 @@ export const a = "default a"; 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"; +=== tests/cases/conformance/moduleResolution/node_modules/ext/ts3.1/index.d.ts === +export const a = "ts3.1 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"; +=== tests/cases/conformance/moduleResolution/node_modules/ext/ts3.1/other.d.ts === +export const b = "ts3.1 b"; >b : Symbol(b, Decl(other.d.ts, 0, 12)) === tests/cases/conformance/moduleResolution/main.ts === @@ -21,11 +21,11 @@ import { a } from "ext"; import { b } from "ext/other"; >b : Symbol(b, Decl(main.ts, 1, 8)) -const aa: "ts3.0 a" = a; +const aa: "ts3.1 a" = a; >aa : Symbol(aa, Decl(main.ts, 3, 5)) >a : Symbol(a, Decl(main.ts, 0, 8)) -const bb: "ts3.0 b" = b; +const bb: "ts3.1 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 index 6884322c301f3..e7245fa5765bb 100644 --- a/tests/baselines/reference/typesVersions.multiFile.trace.json +++ b/tests/baselines/reference/typesVersions.multiFile.trace.json @@ -11,27 +11,27 @@ "File 'tests/cases/conformance/moduleResolution/node_modules/ext.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/index'.", - "'package.json' has a 'typesVersions' entry '3.0' that matches compiler version '3.1', looking for a pattern to match module name 'index'.", + "'package.json' has a 'typesVersions' entry '3.1' that matches compiler version '3.1', looking for a pattern to match module name 'index'.", "Module name 'index', matched pattern '*'.", - "Trying substitution 'ts3.0/*', candidate module location: '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'. ========", + "Trying substitution 'ts3.1/*', candidate module location: 'ts3.1/index'.", + "File 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.1/index' does not exist.", + "Loading module as file / folder, candidate module location 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.1/index', target file type 'TypeScript'.", + "File 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.1/index.ts' does not exist.", + "File 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.1/index.tsx' does not exist.", + "File 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.1/index.d.ts' exist - use it as a name resolution result.", + "Resolving real path for 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.1/index.d.ts', result 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.1/index.d.ts'.", + "======== Module name 'ext' was successfully resolved to 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.1/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 a 'typesVersions' field with version-specific path mappings.", "Found 'package.json' at 'tests/cases/conformance/moduleResolution/node_modules/ext/package.json'. Package ID is 'ext/other/index.d.ts@1.0.0'.", - "'package.json' has a 'typesVersions' entry '3.0' that matches compiler version '3.1', looking for a pattern to match module name 'other'.", + "'package.json' has a 'typesVersions' entry '3.1' that matches compiler version '3.1', looking for a pattern to match module name 'other'.", "Module name 'other', matched pattern '*'.", - "Trying substitution 'ts3.0/*', candidate module location: 'ts3.0/other'.", - "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'. ========" + "Trying substitution 'ts3.1/*', candidate module location: 'ts3.1/other'.", + "File 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.1/other.ts' does not exist.", + "File 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.1/other.tsx' does not exist.", + "File 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.1/other.d.ts' exist - use it as a name resolution result.", + "Resolving real path for 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.1/other.d.ts', result 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.1/other.d.ts'.", + "======== Module name 'ext/other' was successfully resolved to 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.1/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 index c0634803d2937..734a90067cb19 100644 --- a/tests/baselines/reference/typesVersions.multiFile.types +++ b/tests/baselines/reference/typesVersions.multiFile.types @@ -8,28 +8,28 @@ 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.1/index.d.ts === +export const a = "ts3.1 a"; +>a : "ts3.1 a" +>"ts3.1 a" : "ts3.1 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/node_modules/ext/ts3.1/other.d.ts === +export const b = "ts3.1 b"; +>b : "ts3.1 b" +>"ts3.1 b" : "ts3.1 b" === tests/cases/conformance/moduleResolution/main.ts === import { a } from "ext"; ->a : "ts3.0 a" +>a : "ts3.1 a" import { b } from "ext/other"; ->b : "ts3.0 b" +>b : "ts3.1 b" -const aa: "ts3.0 a" = a; ->aa : "ts3.0 a" ->a : "ts3.0 a" +const aa: "ts3.1 a" = a; +>aa : "ts3.1 a" +>a : "ts3.1 a" -const bb: "ts3.0 b" = b; ->bb : "ts3.0 b" ->b : "ts3.0 b" +const bb: "ts3.1 b" = b; +>bb : "ts3.1 b" +>b : "ts3.1 b" diff --git a/tests/baselines/reference/typesVersionsDeclarationEmit.ambient.js b/tests/baselines/reference/typesVersionsDeclarationEmit.ambient.js index a226df8e87361..b1af852940b9f 100644 --- a/tests/baselines/reference/typesVersionsDeclarationEmit.ambient.js +++ b/tests/baselines/reference/typesVersionsDeclarationEmit.ambient.js @@ -6,7 +6,7 @@ "version": "1.0.0", "types": "index", "typesVersions": { - "3.0": { "*" : ["ts3.0/*"] } + "3.1": { "*" : ["ts3.1/*"] } } } diff --git a/tests/baselines/reference/typesVersionsDeclarationEmit.ambient.symbols b/tests/baselines/reference/typesVersionsDeclarationEmit.ambient.symbols index 15d1718cce77f..2e4794ba56ad6 100644 --- a/tests/baselines/reference/typesVersionsDeclarationEmit.ambient.symbols +++ b/tests/baselines/reference/typesVersionsDeclarationEmit.ambient.symbols @@ -13,7 +13,7 @@ export const vb = fb(); >vb : Symbol(vb, Decl(main.ts, 4, 12)) >fb : Symbol(fb, Decl(main.ts, 1, 8)) -=== tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/index.d.ts === +=== tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/index.d.ts === declare module "ext" { >"ext" : Symbol("ext", Decl(index.d.ts, 0, 0)) diff --git a/tests/baselines/reference/typesVersionsDeclarationEmit.ambient.trace.json b/tests/baselines/reference/typesVersionsDeclarationEmit.ambient.trace.json index f973d37cd5878..c3b0e2327481a 100644 --- a/tests/baselines/reference/typesVersionsDeclarationEmit.ambient.trace.json +++ b/tests/baselines/reference/typesVersionsDeclarationEmit.ambient.trace.json @@ -11,27 +11,27 @@ "File 'tests/cases/conformance/declarationEmit/node_modules/ext.d.ts' does not exist.", "'package.json' does not have a 'typings' field.", "'package.json' has 'types' field 'index' that references 'tests/cases/conformance/declarationEmit/node_modules/ext/index'.", - "'package.json' has a 'typesVersions' entry '3.0' that matches compiler version '3.1', looking for a pattern to match module name 'index'.", + "'package.json' has a 'typesVersions' entry '3.1' that matches compiler version '3.1', looking for a pattern to match module name 'index'.", "Module name 'index', matched pattern '*'.", - "Trying substitution 'ts3.0/*', candidate module location: 'ts3.0/index'.", - "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/index' does not exist.", - "Loading module as file / folder, candidate module location 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/index', target file type 'TypeScript'.", - "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/index.ts' does not exist.", - "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/index.tsx' does not exist.", - "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/index.d.ts' exist - use it as a name resolution result.", - "Resolving real path for 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/index.d.ts', result 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/index.d.ts'.", - "======== Module name 'ext' was successfully resolved to 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/index.d.ts'. ========", + "Trying substitution 'ts3.1/*', candidate module location: 'ts3.1/index'.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/index' does not exist.", + "Loading module as file / folder, candidate module location 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/index', target file type 'TypeScript'.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/index.ts' does not exist.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/index.tsx' does not exist.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/index.d.ts' exist - use it as a name resolution result.", + "Resolving real path for 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/index.d.ts', result 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/index.d.ts'.", + "======== Module name 'ext' was successfully resolved to 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/index.d.ts'. ========", "======== Resolving module 'ext/other' from 'tests/cases/conformance/declarationEmit/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 a 'typesVersions' field with version-specific path mappings.", "Found 'package.json' at 'tests/cases/conformance/declarationEmit/node_modules/ext/package.json'. Package ID is 'ext/other/index.d.ts@1.0.0'.", - "'package.json' has a 'typesVersions' entry '3.0' that matches compiler version '3.1', looking for a pattern to match module name 'other'.", + "'package.json' has a 'typesVersions' entry '3.1' that matches compiler version '3.1', looking for a pattern to match module name 'other'.", "Module name 'other', matched pattern '*'.", - "Trying substitution 'ts3.0/*', candidate module location: 'ts3.0/other'.", - "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/other.ts' does not exist.", - "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/other.tsx' does not exist.", - "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/other.d.ts' does not exist.", + "Trying substitution 'ts3.1/*', candidate module location: 'ts3.1/other'.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/other.ts' does not exist.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/other.tsx' does not exist.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/other.d.ts' does not exist.", "Directory 'tests/cases/conformance/declarationEmit/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.", @@ -41,11 +41,11 @@ "Loading module 'ext/other' from 'node_modules' folder, target file type 'JavaScript'.", "'package.json' has a 'typesVersions' field with version-specific path mappings.", "Found 'package.json' at 'tests/cases/conformance/declarationEmit/node_modules/ext/package.json'. Package ID is 'ext/other/index.d.ts@1.0.0'.", - "'package.json' has a 'typesVersions' entry '3.0' that matches compiler version '3.1', looking for a pattern to match module name 'other'.", + "'package.json' has a 'typesVersions' entry '3.1' that matches compiler version '3.1', looking for a pattern to match module name 'other'.", "Module name 'other', matched pattern '*'.", - "Trying substitution 'ts3.0/*', candidate module location: 'ts3.0/other'.", - "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/other.js' does not exist.", - "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/other.jsx' does not exist.", + "Trying substitution 'ts3.1/*', candidate module location: 'ts3.1/other'.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/other.js' does not exist.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/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.", diff --git a/tests/baselines/reference/typesVersionsDeclarationEmit.ambient.types b/tests/baselines/reference/typesVersionsDeclarationEmit.ambient.types index 9f47ca9750c23..3599ee312a391 100644 --- a/tests/baselines/reference/typesVersionsDeclarationEmit.ambient.types +++ b/tests/baselines/reference/typesVersionsDeclarationEmit.ambient.types @@ -15,7 +15,7 @@ export const vb = fb(); >fb() : import("ext/other").B >fb : () => import("ext/other").B -=== tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/index.d.ts === +=== tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/index.d.ts === declare module "ext" { >"ext" : typeof import("ext") diff --git a/tests/baselines/reference/typesVersionsDeclarationEmit.multiFile.js b/tests/baselines/reference/typesVersionsDeclarationEmit.multiFile.js index 4a1edf5c97e2b..22cdb0087ef22 100644 --- a/tests/baselines/reference/typesVersionsDeclarationEmit.multiFile.js +++ b/tests/baselines/reference/typesVersionsDeclarationEmit.multiFile.js @@ -6,7 +6,7 @@ "version": "1.0.0", "types": "index", "typesVersions": { - "3.0": { "*" : ["ts3.0/*"] } + "3.1": { "*" : ["ts3.1/*"] } } } diff --git a/tests/baselines/reference/typesVersionsDeclarationEmit.multiFile.symbols b/tests/baselines/reference/typesVersionsDeclarationEmit.multiFile.symbols index e5db04915416c..4449de33ded9c 100644 --- a/tests/baselines/reference/typesVersionsDeclarationEmit.multiFile.symbols +++ b/tests/baselines/reference/typesVersionsDeclarationEmit.multiFile.symbols @@ -14,7 +14,7 @@ export function fb(): B; >fb : Symbol(fb, Decl(other.d.ts, 0, 21)) >B : Symbol(B, Decl(other.d.ts, 0, 0)) -=== tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/index.d.ts === +=== tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/index.d.ts === export interface A {} >A : Symbol(A, Decl(index.d.ts, 0, 0)) @@ -22,7 +22,7 @@ export function fa(): A; >fa : Symbol(fa, Decl(index.d.ts, 0, 21)) >A : Symbol(A, Decl(index.d.ts, 0, 0)) -=== tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/other.d.ts === +=== tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/other.d.ts === export interface B {} >B : Symbol(B, Decl(other.d.ts, 0, 0)) diff --git a/tests/baselines/reference/typesVersionsDeclarationEmit.multiFile.trace.json b/tests/baselines/reference/typesVersionsDeclarationEmit.multiFile.trace.json index 0296a58b8962b..532e80feac79b 100644 --- a/tests/baselines/reference/typesVersionsDeclarationEmit.multiFile.trace.json +++ b/tests/baselines/reference/typesVersionsDeclarationEmit.multiFile.trace.json @@ -11,27 +11,27 @@ "File 'tests/cases/conformance/declarationEmit/node_modules/ext.d.ts' does not exist.", "'package.json' does not have a 'typings' field.", "'package.json' has 'types' field 'index' that references 'tests/cases/conformance/declarationEmit/node_modules/ext/index'.", - "'package.json' has a 'typesVersions' entry '3.0' that matches compiler version '3.1', looking for a pattern to match module name 'index'.", + "'package.json' has a 'typesVersions' entry '3.1' that matches compiler version '3.1', looking for a pattern to match module name 'index'.", "Module name 'index', matched pattern '*'.", - "Trying substitution 'ts3.0/*', candidate module location: 'ts3.0/index'.", - "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/index' does not exist.", - "Loading module as file / folder, candidate module location 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/index', target file type 'TypeScript'.", - "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/index.ts' does not exist.", - "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/index.tsx' does not exist.", - "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/index.d.ts' exist - use it as a name resolution result.", - "Resolving real path for 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/index.d.ts', result 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/index.d.ts'.", - "======== Module name 'ext' was successfully resolved to 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/index.d.ts'. ========", + "Trying substitution 'ts3.1/*', candidate module location: 'ts3.1/index'.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/index' does not exist.", + "Loading module as file / folder, candidate module location 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/index', target file type 'TypeScript'.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/index.ts' does not exist.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/index.tsx' does not exist.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/index.d.ts' exist - use it as a name resolution result.", + "Resolving real path for 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/index.d.ts', result 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/index.d.ts'.", + "======== Module name 'ext' was successfully resolved to 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/index.d.ts'. ========", "======== Resolving module 'ext/other' from 'tests/cases/conformance/declarationEmit/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 a 'typesVersions' field with version-specific path mappings.", "Found 'package.json' at 'tests/cases/conformance/declarationEmit/node_modules/ext/package.json'. Package ID is 'ext/other/index.d.ts@1.0.0'.", - "'package.json' has a 'typesVersions' entry '3.0' that matches compiler version '3.1', looking for a pattern to match module name 'other'.", + "'package.json' has a 'typesVersions' entry '3.1' that matches compiler version '3.1', looking for a pattern to match module name 'other'.", "Module name 'other', matched pattern '*'.", - "Trying substitution 'ts3.0/*', candidate module location: 'ts3.0/other'.", - "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/other.ts' does not exist.", - "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/other.tsx' does not exist.", - "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/other.d.ts' exist - use it as a name resolution result.", - "Resolving real path for 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/other.d.ts', result 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/other.d.ts'.", - "======== Module name 'ext/other' was successfully resolved to 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/other.d.ts'. ========" + "Trying substitution 'ts3.1/*', candidate module location: 'ts3.1/other'.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/other.ts' does not exist.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/other.tsx' does not exist.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/other.d.ts' exist - use it as a name resolution result.", + "Resolving real path for 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/other.d.ts', result 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/other.d.ts'.", + "======== Module name 'ext/other' was successfully resolved to 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/other.d.ts'. ========" ] \ No newline at end of file diff --git a/tests/baselines/reference/typesVersionsDeclarationEmit.multiFile.types b/tests/baselines/reference/typesVersionsDeclarationEmit.multiFile.types index 73721bafec1a6..9f9dd01594270 100644 --- a/tests/baselines/reference/typesVersionsDeclarationEmit.multiFile.types +++ b/tests/baselines/reference/typesVersionsDeclarationEmit.multiFile.types @@ -8,30 +8,30 @@ export interface B {} export function fb(): B; >fb : () => B -=== tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/index.d.ts === +=== tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/index.d.ts === export interface A {} export function fa(): A; >fa : () => A -=== tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/other.d.ts === +=== tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/other.d.ts === export interface B {} export function fb(): B; >fb : () => B === tests/cases/conformance/declarationEmit/main.ts === import { fa } from "ext"; ->fa : () => import("tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/index").A +>fa : () => import("tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/index").A import { fb } from "ext/other"; ->fb : () => import("tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/other").B +>fb : () => import("tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/other").B export const va = fa(); ->va : import("tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/index").A ->fa() : import("tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/index").A ->fa : () => import("tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/index").A +>va : import("tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/index").A +>fa() : import("tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/index").A +>fa : () => import("tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/index").A export const vb = fb(); ->vb : import("tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/other").B ->fb() : import("tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/other").B ->fb : () => import("tests/cases/conformance/declarationEmit/node_modules/ext/ts3.0/other").B +>vb : import("tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/other").B +>fb() : import("tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/other").B +>fb : () => import("tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/other").B diff --git a/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToSelf.errors.txt b/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToSelf.errors.txt new file mode 100644 index 0000000000000..66624634d9f62 --- /dev/null +++ b/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToSelf.errors.txt @@ -0,0 +1,38 @@ +tests/cases/conformance/declarationEmit/main.ts(1,10): error TS2305: Module '"tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/index"' has no exported member 'fa'. + + +==== tests/cases/conformance/declarationEmit/tsconfig.json (0 errors) ==== + {} +==== tests/cases/conformance/declarationEmit/node_modules/ext/package.json (0 errors) ==== + { + "name": "ext", + "version": "1.0.0", + "types": "index", + "typesVersions": { + "3.1": { "*" : ["ts3.1/*"] } + } + } + +==== tests/cases/conformance/declarationEmit/node_modules/ext/index.d.ts (0 errors) ==== + export interface A {} + export function fa(): A; + +==== tests/cases/conformance/declarationEmit/node_modules/ext/other.d.ts (0 errors) ==== + export interface B {} + export function fb(): B; + +==== tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/index.d.ts (0 errors) ==== + export * from "../"; + +==== tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/other.d.ts (0 errors) ==== + export * from "../other"; + +==== tests/cases/conformance/declarationEmit/main.ts (1 errors) ==== + import { fa } from "ext"; + ~~ +!!! error TS2305: Module '"tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/index"' has no exported member 'fa'. + import { fb } from "ext/other"; + + export const va = fa(); + export const vb = fb(); + \ No newline at end of file diff --git a/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToSelf.js b/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToSelf.js new file mode 100644 index 0000000000000..c7b885d5e9e55 --- /dev/null +++ b/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToSelf.js @@ -0,0 +1,46 @@ +//// [tests/cases/conformance/declarationEmit/typesVersionsDeclarationEmit.multiFileBackReferenceToSelf.ts] //// + +//// [package.json] +{ + "name": "ext", + "version": "1.0.0", + "types": "index", + "typesVersions": { + "3.1": { "*" : ["ts3.1/*"] } + } +} + +//// [index.d.ts] +export interface A {} +export function fa(): A; + +//// [other.d.ts] +export interface B {} +export function fb(): B; + +//// [index.d.ts] +export * from "../"; + +//// [other.d.ts] +export * from "../other"; + +//// [main.ts] +import { fa } from "ext"; +import { fb } from "ext/other"; + +export const va = fa(); +export const vb = fb(); + + +//// [main.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const ext_1 = require("ext"); +const other_1 = require("ext/other"); +exports.va = ext_1.fa(); +exports.vb = other_1.fb(); + + +//// [main.d.ts] +export declare const va: any; +export declare const vb: import("ext/other").B; diff --git a/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToSelf.symbols b/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToSelf.symbols new file mode 100644 index 0000000000000..a3367579265c6 --- /dev/null +++ b/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToSelf.symbols @@ -0,0 +1,37 @@ +=== tests/cases/conformance/declarationEmit/node_modules/ext/index.d.ts === +export interface A {} +>A : Symbol(A, Decl(index.d.ts, 0, 0)) + +export function fa(): A; +>fa : Symbol(fa, Decl(index.d.ts, 0, 21)) +>A : Symbol(A, Decl(index.d.ts, 0, 0)) + +=== tests/cases/conformance/declarationEmit/node_modules/ext/other.d.ts === +export interface B {} +>B : Symbol(B, Decl(other.d.ts, 0, 0)) + +export function fb(): B; +>fb : Symbol(fb, Decl(other.d.ts, 0, 21)) +>B : Symbol(B, Decl(other.d.ts, 0, 0)) + +=== tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/index.d.ts === +export * from "../"; +No type information for this code. +No type information for this code.=== tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/other.d.ts === +export * from "../other"; +No type information for this code. +No type information for this code.=== tests/cases/conformance/declarationEmit/main.ts === +import { fa } from "ext"; +>fa : Symbol(fa, Decl(main.ts, 0, 8)) + +import { fb } from "ext/other"; +>fb : Symbol(fb, Decl(main.ts, 1, 8)) + +export const va = fa(); +>va : Symbol(va, Decl(main.ts, 3, 12)) +>fa : Symbol(fa, Decl(main.ts, 0, 8)) + +export const vb = fb(); +>vb : Symbol(vb, Decl(main.ts, 4, 12)) +>fb : Symbol(fb, Decl(main.ts, 1, 8)) + diff --git a/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToSelf.trace.json b/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToSelf.trace.json new file mode 100644 index 0000000000000..33d5a0e317752 --- /dev/null +++ b/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToSelf.trace.json @@ -0,0 +1,65 @@ +[ + "======== Resolving module '../' from 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/index.d.ts'. ========", + "Module resolution kind is not specified, using 'NodeJs'.", + "Loading module as file / folder, candidate module location 'tests/cases/conformance/declarationEmit/node_modules/ext/', target file type 'TypeScript'.", + "'package.json' does not have a 'typings' field.", + "'package.json' has 'types' field 'index' that references 'tests/cases/conformance/declarationEmit/node_modules/ext/index'.", + "'package.json' has a 'typesVersions' field with version-specific path mappings.", + "Found 'package.json' at 'tests/cases/conformance/declarationEmit/node_modules/ext/package.json'. Package ID is 'ext/ndex/index.d.ts@1.0.0'.", + "'package.json' has a 'typesVersions' field with version-specific path mappings.", + "'package.json' does not have a 'typings' field.", + "'package.json' has 'types' field 'index' that references 'tests/cases/conformance/declarationEmit/node_modules/ext/index'.", + "'package.json' has a 'typesVersions' entry '3.1' that matches compiler version '3.1', looking for a pattern to match module name 'index'.", + "Module name 'index', matched pattern '*'.", + "Trying substitution 'ts3.1/*', candidate module location: 'ts3.1/index'.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/index' does not exist.", + "Loading module as file / folder, candidate module location 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/index', target file type 'TypeScript'.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/index.ts' does not exist.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/index.tsx' does not exist.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/index.d.ts' exist - use it as a name resolution result.", + "======== Module name '../' was successfully resolved to 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/index.d.ts'. ========", + "======== Resolving module '../other' from 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/other.d.ts'. ========", + "Module resolution kind is not specified, using 'NodeJs'.", + "Loading module as file / folder, candidate module location 'tests/cases/conformance/declarationEmit/node_modules/ext/other', target file type 'TypeScript'.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext/other.ts' does not exist.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext/other.tsx' does not exist.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext/other.d.ts' exist - use it as a name resolution result.", + "'package.json' has a 'typesVersions' field with version-specific path mappings.", + "Found 'package.json' at 'tests/cases/conformance/declarationEmit/node_modules/ext/package.json'. Package ID is 'ext/other.d.ts@1.0.0'.", + "======== Module name '../other' was successfully resolved to 'tests/cases/conformance/declarationEmit/node_modules/ext/other.d.ts'. ========", + "======== Resolving module 'ext' from 'tests/cases/conformance/declarationEmit/main.ts'. ========", + "Module resolution kind is not specified, using 'NodeJs'.", + "Loading module 'ext' from 'node_modules' folder, target file type 'TypeScript'.", + "'package.json' does not have a 'typings' field.", + "'package.json' has 'types' field 'index' that references 'tests/cases/conformance/declarationEmit/node_modules/ext/index'.", + "'package.json' has a 'typesVersions' field with version-specific path mappings.", + "Found 'package.json' at 'tests/cases/conformance/declarationEmit/node_modules/ext/package.json'. Package ID is 'ext/index.d.ts@1.0.0'.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext.ts' does not exist.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext.tsx' does not exist.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext.d.ts' does not exist.", + "'package.json' does not have a 'typings' field.", + "'package.json' has 'types' field 'index' that references 'tests/cases/conformance/declarationEmit/node_modules/ext/index'.", + "'package.json' has a 'typesVersions' entry '3.1' that matches compiler version '3.1', looking for a pattern to match module name 'index'.", + "Module name 'index', matched pattern '*'.", + "Trying substitution 'ts3.1/*', candidate module location: 'ts3.1/index'.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/index' does not exist.", + "Loading module as file / folder, candidate module location 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/index', target file type 'TypeScript'.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/index.ts' does not exist.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/index.tsx' does not exist.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/index.d.ts' exist - use it as a name resolution result.", + "Resolving real path for 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/index.d.ts', result 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/index.d.ts'.", + "======== Module name 'ext' was successfully resolved to 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/index.d.ts'. ========", + "======== Resolving module 'ext/other' from 'tests/cases/conformance/declarationEmit/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 a 'typesVersions' field with version-specific path mappings.", + "Found 'package.json' at 'tests/cases/conformance/declarationEmit/node_modules/ext/package.json'. Package ID is 'ext/other/index.d.ts@1.0.0'.", + "'package.json' has a 'typesVersions' entry '3.1' that matches compiler version '3.1', looking for a pattern to match module name 'other'.", + "Module name 'other', matched pattern '*'.", + "Trying substitution 'ts3.1/*', candidate module location: 'ts3.1/other'.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/other.ts' does not exist.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/other.tsx' does not exist.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/other.d.ts' exist - use it as a name resolution result.", + "Resolving real path for 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/other.d.ts', result 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/other.d.ts'.", + "======== Module name 'ext/other' was successfully resolved to 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/other.d.ts'. ========" +] \ No newline at end of file diff --git a/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToSelf.types b/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToSelf.types new file mode 100644 index 0000000000000..05800e1d35d58 --- /dev/null +++ b/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToSelf.types @@ -0,0 +1,33 @@ +=== tests/cases/conformance/declarationEmit/node_modules/ext/index.d.ts === +export interface A {} +export function fa(): A; +>fa : () => A + +=== tests/cases/conformance/declarationEmit/node_modules/ext/other.d.ts === +export interface B {} +export function fb(): B; +>fb : () => B + +=== tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/index.d.ts === +export * from "../"; +No type information for this code. +No type information for this code.=== tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/other.d.ts === +export * from "../other"; +No type information for this code. +No type information for this code.=== tests/cases/conformance/declarationEmit/main.ts === +import { fa } from "ext"; +>fa : any + +import { fb } from "ext/other"; +>fb : () => import("tests/cases/conformance/declarationEmit/node_modules/ext/other").B + +export const va = fa(); +>va : any +>fa() : any +>fa : any + +export const vb = fb(); +>vb : import("tests/cases/conformance/declarationEmit/node_modules/ext/other").B +>fb() : import("tests/cases/conformance/declarationEmit/node_modules/ext/other").B +>fb : () => import("tests/cases/conformance/declarationEmit/node_modules/ext/other").B + diff --git a/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToUnmapped.js b/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToUnmapped.js new file mode 100644 index 0000000000000..86a621161f648 --- /dev/null +++ b/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToUnmapped.js @@ -0,0 +1,45 @@ +//// [tests/cases/conformance/declarationEmit/typesVersionsDeclarationEmit.multiFileBackReferenceToUnmapped.ts] //// + +//// [package.json] +{ + "name": "ext", + "version": "1.0.0", + "types": "index", + "typesVersions": { + "3.1": { + "index" : ["ts3.1/index"] + } + } +} + +//// [index.d.ts] +export interface A {} +export function fa(): A; + +//// [other.d.ts] +export interface A2 {} +export function fa(): A2; + +//// [index.d.ts] +export * from "../other"; + +//// [main.ts] +import { fa } from "ext"; +import { fa as fa2 } from "ext/other"; + +export const va = fa(); +export const va2 = fa2(); + + +//// [main.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +const ext_1 = require("ext"); +const other_1 = require("ext/other"); +exports.va = ext_1.fa(); +exports.va2 = other_1.fa(); + + +//// [main.d.ts] +export declare const va: import("ext/other").A2; +export declare const va2: import("ext/other").A2; diff --git a/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToUnmapped.symbols b/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToUnmapped.symbols new file mode 100644 index 0000000000000..892e521994bef --- /dev/null +++ b/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToUnmapped.symbols @@ -0,0 +1,35 @@ +=== tests/cases/conformance/declarationEmit/node_modules/ext/index.d.ts === +export interface A {} +>A : Symbol(A, Decl(index.d.ts, 0, 0)) + +export function fa(): A; +>fa : Symbol(fa, Decl(index.d.ts, 0, 21)) +>A : Symbol(A, Decl(index.d.ts, 0, 0)) + +=== tests/cases/conformance/declarationEmit/node_modules/ext/other.d.ts === +export interface A2 {} +>A2 : Symbol(A2, Decl(other.d.ts, 0, 0)) + +export function fa(): A2; +>fa : Symbol(fa, Decl(other.d.ts, 0, 22)) +>A2 : Symbol(A2, Decl(other.d.ts, 0, 0)) + +=== tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/index.d.ts === +export * from "../other"; +No type information for this code. +No type information for this code.=== tests/cases/conformance/declarationEmit/main.ts === +import { fa } from "ext"; +>fa : Symbol(fa, Decl(main.ts, 0, 8)) + +import { fa as fa2 } from "ext/other"; +>fa : Symbol(fa2, Decl(main.ts, 1, 8)) +>fa2 : Symbol(fa2, Decl(main.ts, 1, 8)) + +export const va = fa(); +>va : Symbol(va, Decl(main.ts, 3, 12)) +>fa : Symbol(fa, Decl(main.ts, 0, 8)) + +export const va2 = fa2(); +>va2 : Symbol(va2, Decl(main.ts, 4, 12)) +>fa2 : Symbol(fa2, Decl(main.ts, 1, 8)) + diff --git a/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToUnmapped.trace.json b/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToUnmapped.trace.json new file mode 100644 index 0000000000000..d31c0730fd995 --- /dev/null +++ b/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToUnmapped.trace.json @@ -0,0 +1,44 @@ +[ + "======== Resolving module '../other' from 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/index.d.ts'. ========", + "Module resolution kind is not specified, using 'NodeJs'.", + "Loading module as file / folder, candidate module location 'tests/cases/conformance/declarationEmit/node_modules/ext/other', target file type 'TypeScript'.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext/other.ts' does not exist.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext/other.tsx' does not exist.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext/other.d.ts' exist - use it as a name resolution result.", + "'package.json' has a 'typesVersions' field with version-specific path mappings.", + "Found 'package.json' at 'tests/cases/conformance/declarationEmit/node_modules/ext/package.json'. Package ID is 'ext/other.d.ts@1.0.0'.", + "======== Module name '../other' was successfully resolved to 'tests/cases/conformance/declarationEmit/node_modules/ext/other.d.ts'. ========", + "======== Resolving module 'ext' from 'tests/cases/conformance/declarationEmit/main.ts'. ========", + "Module resolution kind is not specified, using 'NodeJs'.", + "Loading module 'ext' from 'node_modules' folder, target file type 'TypeScript'.", + "'package.json' does not have a 'typings' field.", + "'package.json' has 'types' field 'index' that references 'tests/cases/conformance/declarationEmit/node_modules/ext/index'.", + "'package.json' has a 'typesVersions' field with version-specific path mappings.", + "Found 'package.json' at 'tests/cases/conformance/declarationEmit/node_modules/ext/package.json'. Package ID is 'ext/index.d.ts@1.0.0'.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext.ts' does not exist.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext.tsx' does not exist.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext.d.ts' does not exist.", + "'package.json' does not have a 'typings' field.", + "'package.json' has 'types' field 'index' that references 'tests/cases/conformance/declarationEmit/node_modules/ext/index'.", + "'package.json' has a 'typesVersions' entry '3.1' that matches compiler version '3.1', looking for a pattern to match module name 'index'.", + "Module name 'index', matched pattern 'index'.", + "Trying substitution 'ts3.1/index', candidate module location: 'ts3.1/index'.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/index' does not exist.", + "Loading module as file / folder, candidate module location 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/index', target file type 'TypeScript'.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/index.ts' does not exist.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/index.tsx' does not exist.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/index.d.ts' exist - use it as a name resolution result.", + "Resolving real path for 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/index.d.ts', result 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/index.d.ts'.", + "======== Module name 'ext' was successfully resolved to 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/index.d.ts'. ========", + "======== Resolving module 'ext/other' from 'tests/cases/conformance/declarationEmit/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 a 'typesVersions' field with version-specific path mappings.", + "Found 'package.json' at 'tests/cases/conformance/declarationEmit/node_modules/ext/package.json'. Package ID is 'ext/other/index.d.ts@1.0.0'.", + "'package.json' has a 'typesVersions' entry '3.1' that matches compiler version '3.1', looking for a pattern to match module name 'other'.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext/other.ts' does not exist.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext/other.tsx' does not exist.", + "File 'tests/cases/conformance/declarationEmit/node_modules/ext/other.d.ts' exist - use it as a name resolution result.", + "Resolving real path for 'tests/cases/conformance/declarationEmit/node_modules/ext/other.d.ts', result 'tests/cases/conformance/declarationEmit/node_modules/ext/other.d.ts'.", + "======== Module name 'ext/other' was successfully resolved to 'tests/cases/conformance/declarationEmit/node_modules/ext/other.d.ts'. ========" +] \ No newline at end of file diff --git a/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToUnmapped.types b/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToUnmapped.types new file mode 100644 index 0000000000000..d29183141335c --- /dev/null +++ b/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToUnmapped.types @@ -0,0 +1,31 @@ +=== tests/cases/conformance/declarationEmit/node_modules/ext/index.d.ts === +export interface A {} +export function fa(): A; +>fa : () => A + +=== tests/cases/conformance/declarationEmit/node_modules/ext/other.d.ts === +export interface A2 {} +export function fa(): A2; +>fa : () => A2 + +=== tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/index.d.ts === +export * from "../other"; +No type information for this code. +No type information for this code.=== tests/cases/conformance/declarationEmit/main.ts === +import { fa } from "ext"; +>fa : () => import("tests/cases/conformance/declarationEmit/node_modules/ext/other").A2 + +import { fa as fa2 } from "ext/other"; +>fa : () => import("tests/cases/conformance/declarationEmit/node_modules/ext/other").A2 +>fa2 : () => import("tests/cases/conformance/declarationEmit/node_modules/ext/other").A2 + +export const va = fa(); +>va : import("tests/cases/conformance/declarationEmit/node_modules/ext/other").A2 +>fa() : import("tests/cases/conformance/declarationEmit/node_modules/ext/other").A2 +>fa : () => import("tests/cases/conformance/declarationEmit/node_modules/ext/other").A2 + +export const va2 = fa2(); +>va2 : import("tests/cases/conformance/declarationEmit/node_modules/ext/other").A2 +>fa2() : import("tests/cases/conformance/declarationEmit/node_modules/ext/other").A2 +>fa2 : () => import("tests/cases/conformance/declarationEmit/node_modules/ext/other").A2 + diff --git a/tests/cases/conformance/declarationEmit/typesVersionsDeclarationEmit.ambient.ts b/tests/cases/conformance/declarationEmit/typesVersionsDeclarationEmit.ambient.ts index 27bba8e830e7f..447f3aaa82a11 100644 --- a/tests/cases/conformance/declarationEmit/typesVersionsDeclarationEmit.ambient.ts +++ b/tests/cases/conformance/declarationEmit/typesVersionsDeclarationEmit.ambient.ts @@ -9,7 +9,7 @@ "version": "1.0.0", "types": "index", "typesVersions": { - "3.0": { "*" : ["ts3.0/*"] } + "3.1": { "*" : ["ts3.1/*"] } } } @@ -22,7 +22,7 @@ declare module "ext/other" { export interface B {} export function fb(): B; } -// @filename: node_modules/ext/ts3.0/index.d.ts +// @filename: node_modules/ext/ts3.1/index.d.ts declare module "ext" { export interface A {} export function fa(): A; diff --git a/tests/cases/conformance/declarationEmit/typesVersionsDeclarationEmit.multiFile.ts b/tests/cases/conformance/declarationEmit/typesVersionsDeclarationEmit.multiFile.ts index dd71b9b13e236..57ae6c1d631fc 100644 --- a/tests/cases/conformance/declarationEmit/typesVersionsDeclarationEmit.multiFile.ts +++ b/tests/cases/conformance/declarationEmit/typesVersionsDeclarationEmit.multiFile.ts @@ -8,7 +8,7 @@ "version": "1.0.0", "types": "index", "typesVersions": { - "3.0": { "*" : ["ts3.0/*"] } + "3.1": { "*" : ["ts3.1/*"] } } } @@ -20,11 +20,11 @@ export function fa(): A; export interface B {} export function fb(): B; -// @filename: node_modules/ext/ts3.0/index.d.ts +// @filename: node_modules/ext/ts3.1/index.d.ts export interface A {} export function fa(): A; -// @filename: node_modules/ext/ts3.0/other.d.ts +// @filename: node_modules/ext/ts3.1/other.d.ts export interface B {} export function fb(): B; diff --git a/tests/cases/conformance/declarationEmit/typesVersionsDeclarationEmit.multiFileBackReferenceToSelf.ts b/tests/cases/conformance/declarationEmit/typesVersionsDeclarationEmit.multiFileBackReferenceToSelf.ts new file mode 100644 index 0000000000000..3391361225d80 --- /dev/null +++ b/tests/cases/conformance/declarationEmit/typesVersionsDeclarationEmit.multiFileBackReferenceToSelf.ts @@ -0,0 +1,37 @@ +// @traceResolution: true +// @target: esnext +// @module: commonjs +// @declaration: true +// @filename: node_modules/ext/package.json +{ + "name": "ext", + "version": "1.0.0", + "types": "index", + "typesVersions": { + "3.1": { "*" : ["ts3.1/*"] } + } +} + +// @filename: node_modules/ext/index.d.ts +export interface A {} +export function fa(): A; + +// @filename: node_modules/ext/other.d.ts +export interface B {} +export function fb(): B; + +// @filename: node_modules/ext/ts3.1/index.d.ts +export * from "../"; + +// @filename: node_modules/ext/ts3.1/other.d.ts +export * from "../other"; + +// @filename: main.ts +import { fa } from "ext"; +import { fb } from "ext/other"; + +export const va = fa(); +export const vb = fb(); + +// @filename: tsconfig.json +{} \ No newline at end of file diff --git a/tests/cases/conformance/declarationEmit/typesVersionsDeclarationEmit.multiFileBackReferenceToUnmapped.ts b/tests/cases/conformance/declarationEmit/typesVersionsDeclarationEmit.multiFileBackReferenceToUnmapped.ts new file mode 100644 index 0000000000000..15072d2a7ed15 --- /dev/null +++ b/tests/cases/conformance/declarationEmit/typesVersionsDeclarationEmit.multiFileBackReferenceToUnmapped.ts @@ -0,0 +1,36 @@ +// @traceResolution: true +// @target: esnext +// @module: commonjs +// @declaration: true +// @filename: node_modules/ext/package.json +{ + "name": "ext", + "version": "1.0.0", + "types": "index", + "typesVersions": { + "3.1": { + "index" : ["ts3.1/index"] + } + } +} + +// @filename: node_modules/ext/index.d.ts +export interface A {} +export function fa(): A; + +// @filename: node_modules/ext/other.d.ts +export interface A2 {} +export function fa(): A2; + +// @filename: node_modules/ext/ts3.1/index.d.ts +export * from "../other"; + +// @filename: main.ts +import { fa } from "ext"; +import { fa as fa2 } from "ext/other"; + +export const va = fa(); +export const va2 = fa2(); + +// @filename: tsconfig.json +{} \ No newline at end of file diff --git a/tests/cases/conformance/moduleResolution/typesVersions.ambientModules.ts b/tests/cases/conformance/moduleResolution/typesVersions.ambientModules.ts index ac314e0c31320..2de5f47047369 100644 --- a/tests/cases/conformance/moduleResolution/typesVersions.ambientModules.ts +++ b/tests/cases/conformance/moduleResolution/typesVersions.ambientModules.ts @@ -8,7 +8,7 @@ "version": "1.0.0", "types": "index", "typesVersions": { - "3.0": { "*" : ["ts3.0/*"] } + "3.1": { "*" : ["ts3.1/*"] } } } @@ -20,20 +20,20 @@ declare module "ext/other" { export const b = "default b"; } -// @filename: node_modules/ext/ts3.0/index.d.ts +// @filename: node_modules/ext/ts3.1/index.d.ts declare module "ext" { - export const a = "ts3.0 a"; + export const a = "ts3.1 a"; } declare module "ext/other" { - export const b = "ts3.0 b"; + export const b = "ts3.1 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; +const aa: "ts3.1 a" = a; +const bb: "ts3.1 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 index c9001ca221936..8d57630af218d 100644 --- a/tests/cases/conformance/moduleResolution/typesVersions.multiFile.ts +++ b/tests/cases/conformance/moduleResolution/typesVersions.multiFile.ts @@ -7,7 +7,7 @@ "version": "1.0.0", "types": "index", "typesVersions": { - "3.0": { "*" : ["ts3.0/*"] } + "3.1": { "*" : ["ts3.1/*"] } } } @@ -17,18 +17,18 @@ 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.1/index.d.ts +export const a = "ts3.1 a"; -// @filename: node_modules/ext/ts3.0/other.d.ts -export const b = "ts3.0 b"; +// @filename: node_modules/ext/ts3.1/other.d.ts +export const b = "ts3.1 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; +const aa: "ts3.1 a" = a; +const bb: "ts3.1 b" = b; // @filename: tsconfig.json {} \ No newline at end of file From 04a524511ebe5abc61445bf2dd6eb685099cb968 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Tue, 28 Aug 2018 14:11:01 -0700 Subject: [PATCH 08/10] Add semver range parsing support --- Gulpfile.js | 4 +- scripts/build/countdown.js | 62 ++++++++ scripts/build/exec.js | 2 + scripts/build/project.js | 48 ++++-- src/compiler/checker.ts | 2 +- src/compiler/core.ts | 1 + src/compiler/semver.ts | 236 +++++++++++++++++++++++++++++ src/compiler/utilities.ts | 1 - src/harness/utils.ts | 12 ++ src/testRunner/unittests/semver.ts | 134 ++++++++++++++++ 10 files changed, 483 insertions(+), 19 deletions(-) create mode 100644 scripts/build/countdown.js diff --git a/Gulpfile.js b/Gulpfile.js index b31462755adb1..b2fb584d4a28d 100644 --- a/Gulpfile.js +++ b/Gulpfile.js @@ -570,12 +570,12 @@ gulp.task( }); }, /*timeout*/ 100, { max: 500 }); - gulp.watch(watchPatterns, () => project.wait().then(fn)); + gulp.watch(watchPatterns, () => project.wait(runTestsSource && runTestsSource.token).then(fn)); // NOTE: gulp.watch is far too slow when watching tests/cases/**/* as it first enumerates *every* file const testFilePattern = /(\.ts|[\\/]tsconfig\.json)$/; fs.watch("tests/cases", { recursive: true }, (_, file) => { - if (testFilePattern.test(file)) project.wait().then(fn); + if (testFilePattern.test(file)) project.wait(runTestsSource && runTestsSource.token).then(fn); }); function runTests() { diff --git a/scripts/build/countdown.js b/scripts/build/countdown.js new file mode 100644 index 0000000000000..dda05352d28c3 --- /dev/null +++ b/scripts/build/countdown.js @@ -0,0 +1,62 @@ +// @ts-check +const { CancelToken } = require("./cancellation"); + +class Countdown { + constructor(initialCount = 0) { + if (initialCount < 0) throw new Error(); + this._remainingCount = initialCount; + this._promise = undefined; + this._resolve = undefined; + } + + get remainingCount() { + return this._remainingCount; + } + + add(count = 1) { + if (count < 1 || !isFinite(count) || Math.trunc(count) !== count) throw new Error(); + if (this._remainingCount === 0) { + this._promise = undefined; + this._resolve = undefined; + } + + this._remainingCount += count; + } + + signal(count = 1) { + if (count < 1 || !isFinite(count) || Math.trunc(count) !== count) throw new Error(); + if (this._remainingCount - count < 0) throw new Error(); + this._remainingCount -= count; + if (this._remainingCount == 0) { + if (this._resolve) { + this._resolve(); + } + return true; + } + return false; + } + + /** @param {CancelToken} [token] */ + wait(token) { + if (!this._promise) { + this._promise = new Promise(resolve => { this._resolve = resolve; }); + } + if (this._remainingCount === 0) { + this._resolve(); + } + if (!token) return this._promise; + return new Promise((resolve, reject) => { + const subscription = token.subscribe(reject); + this._promise.then( + value => { + subscription.unsubscribe(); + resolve(value); + }, + error => { + subscription.unsubscribe(); + reject(error); + }); + }); + } +} +exports.Countdown = Countdown; \ No newline at end of file diff --git a/scripts/build/exec.js b/scripts/build/exec.js index 04336321dd468..068bf33b9e906 100644 --- a/scripts/build/exec.js +++ b/scripts/build/exec.js @@ -25,8 +25,10 @@ function exec(cmd, args, options = {}) { const command = isWin ? [possiblyQuote(cmd), ...args] : [`${cmd} ${args.join(" ")}`]; const ex = cp.spawn(isWin ? "cmd" : "/bin/sh", [subshellFlag, ...command], { stdio: "inherit", windowsVerbatimArguments: true }); const subscription = options.cancelToken && options.cancelToken.subscribe(() => { + log(`${chalk.red("killing")} '${chalk.green(cmd)} ${args.join(" ")}'...`); ex.kill("SIGINT"); ex.kill("SIGTERM"); + ex.kill(); reject(new CancelError()); }); ex.on("exit", exitCode => { diff --git a/scripts/build/project.js b/scripts/build/project.js index 933f7c44c65fc..8519e4c71ec23 100644 --- a/scripts/build/project.js +++ b/scripts/build/project.js @@ -13,8 +13,27 @@ const del = require("del"); const needsUpdate = require("./needsUpdate"); const mkdirp = require("./mkdirp"); const { reportDiagnostics } = require("./diagnostics"); +const { Countdown } = require("./countdown"); +const { CancelToken } = require("./cancellation"); + +const countdown = new Countdown(); class CompilationGulp extends gulp.Gulp { + constructor() { + super(); + this.on("start", () => { + const onDone = () => { + this.removeListener("stop", onDone); + this.removeListener("err", onDone); + countdown.signal(); + }; + + this.on("stop", onDone); + this.on("err", onDone); + countdown.add(); + }); + } + /** * @param {boolean} [verbose] */ @@ -38,6 +57,17 @@ class ForkedGulp extends gulp.Gulp { constructor(tasks) { super(); this.tasks = tasks; + this.on("start", () => { + const onDone = () => { + this.removeListener("stop", onDone); + this.removeListener("err", onDone); + countdown.signal(); + }; + + this.on("stop", onDone); + this.on("err", onDone); + countdown.add(); + }); } // Do not reset tasks @@ -211,22 +241,10 @@ exports.flatten = flatten; /** * Returns a Promise that resolves when all pending build tasks have completed + * @param {CancelToken} [token] */ -function wait() { - return new Promise(resolve => { - if (compilationGulp.allDone()) { - resolve(); - } - else { - const onDone = () => { - compilationGulp.removeListener("onDone", onDone); - compilationGulp.removeListener("err", onDone); - resolve(); - }; - compilationGulp.on("stop", onDone); - compilationGulp.on("err", onDone); - } - }); +function wait(token) { + return countdown.wait(token); } exports.wait = wait; diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 1e495bf538e22..d3974da993029 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -22233,7 +22233,7 @@ namespace ts { for (const decl of indexSymbol.declarations) { const declaration = decl; if (declaration.parameters.length === 1 && declaration.parameters[0].type) { - switch (declaration.parameters[0].type!.kind) { + switch (declaration.parameters[0].type.kind) { case SyntaxKind.StringKeyword: if (!seenStringIndexer) { seenStringIndexer = true; diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 1eaab5b1b59e0..5e4d42a890ec1 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -65,6 +65,7 @@ namespace ts { /* @internal */ namespace ts { + export const emptyArray: never[] = [] as never[]; /** Create a MapLike with good performance. */ function createDictionaryObject(): MapLike { diff --git a/src/compiler/semver.ts b/src/compiler/semver.ts index 203739f7c957d..33623f45542bf 100644 --- a/src/compiler/semver.ts +++ b/src/compiler/semver.ts @@ -30,6 +30,8 @@ namespace ts { * Describes a precise semantic version number, https://semver.org */ export class Version { + static readonly zero = new Version(0, 0, 0); + readonly major: number; readonly minor: number; readonly patch: number; @@ -85,6 +87,15 @@ namespace ts { || comparePrerelaseIdentifiers(this.prerelease, other.prerelease); } + increment(field: "major" | "minor" | "patch") { + switch (field) { + case "major": return new Version(this.major + 1, 0, 0); + case "minor": return new Version(this.major, this.minor + 1, 0); + case "patch": return new Version(this.major, this.minor, this.patch + 1); + default: return Debug.assertNever(field); + } + } + toString() { let result = `${this.major}.${this.minor}.${this.patch}`; if (some(this.prerelease)) result += `-${this.prerelease.join(".")}`; @@ -152,4 +163,229 @@ namespace ts { // > of the preceding identifiers are equal. return compareValues(left.length, right.length); } + + /** + * Describes a semantic version range, per https://github.com/npm/node-semver#ranges + */ + export class VersionRange { + private _alternatives: ReadonlyArray>; + + constructor(spec: string) { + this._alternatives = spec ? Debug.assertDefined(parseRange(spec), "Invalid range spec.") : emptyArray; + } + + static tryParse(text: string) { + const sets = parseRange(text); + if (sets) { + const range = new VersionRange(""); + range._alternatives = sets; + return range; + } + return undefined; + } + + test(version: Version | string) { + if (typeof version === "string") version = new Version(version); + return testDisjunction(version, this._alternatives); + } + + toString() { + return formatDisjunction(this._alternatives); + } + } + + interface Comparator { + readonly operator: "<" | "<=" | ">" | ">=" | "="; + readonly operand: Version; + } + + // https://github.com/npm/node-semver#range-grammar + // + // range-set ::= range ( logical-or range ) * + // range ::= hyphen | simple ( ' ' simple ) * | '' + // logical-or ::= ( ' ' ) * '||' ( ' ' ) * + const logicalOrRegExp = /\s*\|\|\s*/g; + const whitespaceRegExp = /\s+/g; + + // https://github.com/npm/node-semver#range-grammar + // + // partial ::= xr ( '.' xr ( '.' xr qualifier ? )? )? + // xr ::= 'x' | 'X' | '*' | nr + // nr ::= '0' | ['1'-'9'] ( ['0'-'9'] ) * + // qualifier ::= ( '-' pre )? ( '+' build )? + // pre ::= parts + // build ::= parts + // parts ::= part ( '.' part ) * + // part ::= nr | [-0-9A-Za-z]+ + const partialRegExp = /^([xX*0]|[1-9]\d*)(?:\.([xX*0]|[1-9]\d*)(?:\.([xX*0]|[1-9]\d*)(?:-([a-z0-9-.]+))?(?:\+([a-z0-9-.]+))?)?)?$/i; + + // https://github.com/npm/node-semver#range-grammar + // + // hyphen ::= partial ' - ' partial + const hyphenRegExp = /^\s*([a-z0-9-+.*]+)\s+-\s+([a-z0-9-+.*]+)\s*$/i; + + // https://github.com/npm/node-semver#range-grammar + // + // simple ::= primitive | partial | tilde | caret + // primitive ::= ( '<' | '>' | '>=' | '<=' | '=' ) partial + // tilde ::= '~' partial + // caret ::= '^' partial + const rangeRegExp = /^\s*(~|\^|<|<=|>|>=|=)?\s*([a-z0-9-+.*]+)$/i; + + function parseRange(text: string) { + const alternatives: Comparator[][] = []; + for (const range of text.trim().split(logicalOrRegExp)) { + if (!range) continue; + const comparators: Comparator[] = []; + const match = hyphenRegExp.exec(range); + if (match) { + if (!parseHyphen(match[1], match[2], comparators)) return undefined; + } + else { + for (const simple of range.split(whitespaceRegExp)) { + const match = rangeRegExp.exec(simple); + if (!match || !parseComparator(match[1], match[2], comparators)) return undefined; + } + } + alternatives.push(comparators); + } + return alternatives; + } + + function parsePartial(text: string) { + const match = partialRegExp.exec(text); + if (!match) return undefined; + + const [, major, minor = "*", patch = "*", prerelease, build] = match; + const version = new Version( + isWildcard(major) ? 0 : parseInt(major, 10), + isWildcard(major) || isWildcard(minor) ? 0 : parseInt(minor, 10), + isWildcard(major) || isWildcard(minor) || isWildcard(patch) ? 0 : parseInt(patch, 10), + prerelease, + build); + + return { version, major, minor, patch }; + } + + function parseHyphen(left: string, right: string, comparators: Comparator[]) { + const leftResult = parsePartial(left); + if (!leftResult) return false; + + const rightResult = parsePartial(right); + if (!rightResult) return false; + + if (!isWildcard(leftResult.major)) { + comparators.push(createComparator(">=", leftResult.version)); + } + + if (!isWildcard(rightResult.major)) { + comparators.push( + isWildcard(rightResult.minor) ? createComparator("<", rightResult.version.increment("major")) : + isWildcard(rightResult.patch) ? createComparator("<", rightResult.version.increment("minor")) : + createComparator("<=", rightResult.version)); + } + + return true; + } + + function parseComparator(operator: string, text: string, comparators: Comparator[]) { + const result = parsePartial(text); + if (!result) return false; + + const { version, major, minor, patch } = result; + if (!isWildcard(major)) { + switch (operator) { + case "~": + comparators.push(createComparator(">=", version)); + comparators.push(createComparator("<", version.increment( + isWildcard(minor) ? "major" : + "minor"))); + break; + case "^": + comparators.push(createComparator(">=", version)); + comparators.push(createComparator("<", version.increment( + version.major > 0 || isWildcard(minor) ? "major" : + version.minor > 0 || isWildcard(patch) ? "minor" : + "patch"))); + break; + case "<": + case ">=": + comparators.push(createComparator(operator, version)); + break; + case "<=": + case ">": + comparators.push( + isWildcard(minor) ? createComparator(operator === "<=" ? "<" : ">=", version.increment("major")) : + isWildcard(patch) ? createComparator(operator === "<=" ? "<" : ">=", version.increment("minor")) : + createComparator(operator, version)); + break; + case "=": + case undefined: + if (isWildcard(minor) || isWildcard(patch)) { + comparators.push(createComparator(">=", version)); + comparators.push(createComparator("<", version.increment(isWildcard(minor) ? "major" : "minor"))); + } + else { + comparators.push(createComparator("=", version)); + } + break; + default: + // unrecognized + return false; + } + } + else if (operator === "<" || operator === ">") { + comparators.push(createComparator("<", Version.zero)); + } + + return true; + } + + function isWildcard(part: string) { + return part === "*" || part === "x" || part === "X"; + } + + function createComparator(operator: Comparator["operator"], operand: Version) { + return { operator, operand }; + } + + function testDisjunction(version: Version, alternatives: ReadonlyArray>) { + // an empty disjunction is treated as "*" (all versions) + if (alternatives.length === 0) return true; + for (const alternative of alternatives) { + if (testAlternative(version, alternative)) return true; + } + return false; + } + + function testAlternative(version: Version, comparators: ReadonlyArray) { + for (const comparator of comparators) { + if (!testComparator(version, comparator.operator, comparator.operand)) return false; + } + return true; + } + + function testComparator(version: Version, operator: Comparator["operator"], operand: Version) { + const cmp = version.compareTo(operand); + switch (operator) { + case "<": return cmp < 0; + case "<=": return cmp <= 0; + case ">": return cmp > 0; + case ">=": return cmp >= 0; + case "=": return cmp === 0; + default: return Debug.assertNever(operator); + } + } + + function formatDisjunction(alternatives: ReadonlyArray>) { + return map(alternatives, formatAlternative).join(" || ") || "*"; + } + + function formatAlternative(comparators: ReadonlyArray) { + return map(comparators, formatComparator).join(" "); + } + + function formatComparator(comparator: Comparator) { + return `${comparator.operator}${comparator.operand}`; + } } \ No newline at end of file diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index e7eb352da84d4..0192aa3827017 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -14,7 +14,6 @@ namespace ts { /* @internal */ namespace ts { - export const emptyArray: never[] = [] as never[]; export const resolvingEmptyArray: never[] = [] as never[]; export const emptyMap: ReadonlyMap = createMap(); export const emptyUnderscoreEscapedMap: ReadonlyUnderscoreEscapedMap = emptyMap as ReadonlyUnderscoreEscapedMap; diff --git a/src/harness/utils.ts b/src/harness/utils.ts index 4650badadafa3..14820f10529bd 100644 --- a/src/harness/utils.ts +++ b/src/harness/utils.ts @@ -82,4 +82,16 @@ namespace utils { export function addUTF8ByteOrderMark(text: string) { return getByteOrderMarkLength(text) === 0 ? "\u00EF\u00BB\u00BF" + text : text; } + + export function theory(name: string, cb: (...args: T) => void, data: T[]) { + for (const entry of data) { + it(`${name}(${entry.map(formatTheoryDatum).join(", ")})`, () => cb(...entry)); + } + } + + function formatTheoryDatum(value: any) { + return typeof value === "function" ? value.name || "" : + value === undefined ? "undefined" : + JSON.stringify(value); + } } \ No newline at end of file diff --git a/src/testRunner/unittests/semver.ts b/src/testRunner/unittests/semver.ts index edc888e1075ad..357a24307caff 100644 --- a/src/testRunner/unittests/semver.ts +++ b/src/testRunner/unittests/semver.ts @@ -1,4 +1,5 @@ namespace ts { + import theory = utils.theory; describe("semver", () => { describe("Version", () => { function assertVersion(version: Version, [major, minor, patch, prerelease, build]: [number, number, number, string[]?, string[]?]) { @@ -89,6 +90,139 @@ namespace ts { // > Build metadata does not figure into precedence assert.strictEqual(new Version("1.0.0+build").compareTo(new Version("1.0.0")), Comparison.EqualTo); }); + it("increment", () => { + assertVersion(new Version(1, 2, 3, "pre.4", "build.5").increment("major"), [2, 0, 0]); + assertVersion(new Version(1, 2, 3, "pre.4", "build.5").increment("minor"), [1, 3, 0]); + assertVersion(new Version(1, 2, 3, "pre.4", "build.5").increment("patch"), [1, 2, 4]); + }); + }); + describe("VersionRange", () => { + function assertRange(rangeText: string, versionText: string, inRange = true) { + const range = new VersionRange(rangeText); + const version = new Version(versionText); + assert.strictEqual(range.test(version), inRange, `Expected version '${version}' ${inRange ? `to be` : `to not be`} in range '${rangeText}' (${range})`); + } + theory("comparators", assertRange, [ + ["", "1.0.0"], + ["*", "1.0.0"], + ["1", "1.0.0"], + ["1", "2.0.0", false], + ["1.0", "1.0.0"], + ["1.0", "1.1.0", false], + ["1.0.0", "1.0.0"], + ["1.0.0", "1.0.1", false], + ["1.*", "1.0.0"], + ["1.*", "2.0.0", false], + ["1.x", "1.0.0"], + ["1.x", "2.0.0", false], + ["=1", "1.0.0"], + ["=1", "1.1.0"], + ["=1", "1.0.1"], + ["=1.0", "1.0.0"], + ["=1.0", "1.0.1"], + ["=1.0.0", "1.0.0"], + ["=*", "0.0.0"], + ["=*", "1.0.0"], + [">1", "2"], + [">1.0", "1.1"], + [">1.0.0", "1.0.1"], + [">1.0.0", "1.0.1-pre"], + [">*", "0.0.0", false], + [">*", "1.0.0", false], + [">=1", "1.0.0"], + [">=1.0", "1.0.0"], + [">=1.0.0", "1.0.0"], + [">=1.0.0", "1.0.1-pre"], + [">=*", "0.0.0"], + [">=*", "1.0.0"], + ["<2", "1.0.0"], + ["<2.1", "2.0.0"], + ["<2.0.1", "2.0.0"], + ["<2.0.0", "2.0.0-pre"], + ["<*", "0.0.0", false], + ["<*", "1.0.0", false], + ["<=2", "2.0.0"], + ["<=2.1", "2.1.0"], + ["<=2.0.1", "2.0.1"], + ["<=*", "0.0.0"], + ["<=*", "1.0.0"], + ]); + theory("conjunctions", assertRange, [ + [">1.0.0 <2.0.0", "1.0.1"], + [">1.0.0 <2.0.0", "2.0.0", false], + [">1.0.0 <2.0.0", "1.0.0", false], + [">1 >2", "3.0.0"], + ]); + theory("disjunctions", assertRange, [ + [">=1.0.0 <2.0.0 || >=3.0.0 <4.0.0", "1.0.0"], + [">=1.0.0 <2.0.0 || >=3.0.0 <4.0.0", "2.0.0", false], + [">=1.0.0 <2.0.0 || >=3.0.0 <4.0.0", "3.0.0"], + ]); + theory("hyphen", assertRange, [ + ["1.0.0 - 2.0.0", "1.0.0"], + ["1.0.0 - 2.0.0", "2.0.0"], + ["1.0.0 - 2.0.0", "3.0.0", false], + ]); + theory("tilde", assertRange, [ + ["~0", "0.0.0"], + ["~0", "0.1.0"], + ["~0", "0.1.2"], + ["~0", "0.1.9"], + ["~0", "1.0.0", false], + ["~0.1", "0.1.0"], + ["~0.1", "0.1.2"], + ["~0.1", "0.1.9"], + ["~0.1", "0.2.0", false], + ["~0.1.2", "0.1.2"], + ["~0.1.2", "0.1.9"], + ["~0.1.2", "0.2.0", false], + ["~1", "1.0.0"], + ["~1", "1.2.0"], + ["~1", "1.2.3"], + ["~1", "1.2.0"], + ["~1", "1.2.3"], + ["~1", "0.0.0", false], + ["~1", "2.0.0", false], + ["~1.2", "1.2.0"], + ["~1.2", "1.2.3"], + ["~1.2", "1.1.0", false], + ["~1.2", "1.3.0", false], + ["~1.2.3", "1.2.3"], + ["~1.2.3", "1.2.9"], + ["~1.2.3", "1.1.0", false], + ["~1.2.3", "1.3.0", false], + ]); + theory("caret", assertRange, [ + ["^0", "0.0.0"], + ["^0", "0.1.0"], + ["^0", "0.9.0"], + ["^0", "0.1.2"], + ["^0", "0.1.9"], + ["^0", "1.0.0", false], + ["^0.1", "0.1.0"], + ["^0.1", "0.1.2"], + ["^0.1", "0.1.9"], + ["^0.1.2", "0.1.2"], + ["^0.1.2", "0.1.9"], + ["^0.1.2", "0.0.0", false], + ["^0.1.2", "0.2.0", false], + ["^0.1.2", "1.0.0", false], + ["^1", "1.0.0"], + ["^1", "1.2.0"], + ["^1", "1.2.3"], + ["^1", "1.9.0"], + ["^1", "0.0.0", false], + ["^1", "2.0.0", false], + ["^1.2", "1.2.0"], + ["^1.2", "1.2.3"], + ["^1.2", "1.9.0"], + ["^1.2", "1.1.0", false], + ["^1.2", "2.0.0", false], + ["^1.2.3", "1.2.3"], + ["^1.2.3", "1.9.0"], + ["^1.2.3", "1.2.2", false], + ["^1.2.3", "2.0.0", false], + ]); }); }); } \ No newline at end of file From 37c33f43696526db33470825c3614c783db1bebb Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Tue, 28 Aug 2018 17:24:02 -0700 Subject: [PATCH 09/10] Use semver ranges --- Gulpfile.js | 67 +++++++++----- package.json | 1 + scripts/build/cancellation.js | 71 -------------- scripts/build/countdown.js | 62 ------------- scripts/build/exec.js | 14 ++- scripts/build/project.js | 92 +++++++++++-------- scripts/build/tests.js | 3 +- src/compiler/moduleNameResolver.ts | 26 ++---- .../reference/typesVersions.ambientModules.js | 2 +- .../typesVersions.ambientModules.trace.json | 6 +- .../reference/typesVersions.multiFile.js | 2 +- .../typesVersions.multiFile.trace.json | 4 +- .../typesVersionsDeclarationEmit.ambient.js | 2 +- ...VersionsDeclarationEmit.ambient.trace.json | 6 +- .../typesVersionsDeclarationEmit.multiFile.js | 2 +- ...rsionsDeclarationEmit.multiFile.trace.json | 4 +- ...it.multiFileBackReferenceToSelf.errors.txt | 2 +- ...rationEmit.multiFileBackReferenceToSelf.js | 2 +- ...it.multiFileBackReferenceToSelf.trace.json | 6 +- ...onEmit.multiFileBackReferenceToUnmapped.js | 2 +- ...ultiFileBackReferenceToUnmapped.trace.json | 4 +- .../typesVersionsDeclarationEmit.ambient.ts | 2 +- .../typesVersionsDeclarationEmit.multiFile.ts | 2 +- ...rationEmit.multiFileBackReferenceToSelf.ts | 2 +- ...onEmit.multiFileBackReferenceToUnmapped.ts | 2 +- .../typesVersions.ambientModules.ts | 2 +- .../typesVersions.multiFile.ts | 2 +- 27 files changed, 147 insertions(+), 245 deletions(-) delete mode 100644 scripts/build/cancellation.js delete mode 100644 scripts/build/countdown.js diff --git a/Gulpfile.js b/Gulpfile.js index b2fb584d4a28d..6dc78d1e5ee98 100644 --- a/Gulpfile.js +++ b/Gulpfile.js @@ -24,10 +24,9 @@ const baselineAccept = require("./scripts/build/baselineAccept"); const cmdLineOptions = require("./scripts/build/options"); const exec = require("./scripts/build/exec"); const browserify = require("./scripts/build/browserify"); -const debounce = require("./scripts/build/debounce"); const prepend = require("./scripts/build/prepend"); const { removeSourceMaps } = require("./scripts/build/sourcemaps"); -const { CancelSource, CancelError } = require("./scripts/build/cancellation"); +const { CancellationTokenSource, CancelError, delay, Semaphore } = require("prex"); const { libraryTargets, generateLibs } = require("./scripts/build/lib"); const { runConsoleTests, cleanTestDirs, writeTestConfigFile, refBaseline, localBaseline, refRwcBaseline, localRwcBaseline } = require("./scripts/build/tests"); @@ -556,35 +555,61 @@ gulp.task( "Watches for changes to the build inputs for built/local/run.js, then executes runtests-parallel.", ["build-rules", "watch-runner", "watch-services", "watch-lssl"], () => { - /** @type {CancelSource | undefined} */ - let runTestsSource; - - const fn = debounce(() => { - runTests().catch(error => { - if (error instanceof CancelError) { + const runTestsSemaphore = new Semaphore(1); + const fn = async () => { + try { + // Ensure only one instance of the test runner is running at any given time. + if (runTestsSemaphore.count > 0) { + await runTestsSemaphore.wait(); + try { + // Wait for any concurrent recompilations to complete... + try { + await delay(100); + while (project.hasRemainingWork()) { + await project.waitForWorkToComplete(); + await delay(500); + } + } + catch (e) { + if (e instanceof CancelError) return; + throw e; + } + + // cancel any pending or active test run if a new recompilation is triggered + const runTestsSource = new CancellationTokenSource(); + project.waitForWorkToStart().then(() => { + runTestsSource.cancel(); + }); + + if (cmdLineOptions.tests || cmdLineOptions.failed) { + await runConsoleTests(runJs, "mocha-fivemat-progress-reporter", /*runInParallel*/ false, /*watchMode*/ true, runTestsSource.token); + } + else { + await runConsoleTests(runJs, "min", /*runInParallel*/ true, /*watchMode*/ true, runTestsSource.token); + } + } + finally { + runTestsSemaphore.release(); + } + } + } + catch (e) { + if (e instanceof CancelError) { log.warn("Operation was canceled"); } else { - log.error(error); + log.error(e); } - }); - }, /*timeout*/ 100, { max: 500 }); + } + }; - gulp.watch(watchPatterns, () => project.wait(runTestsSource && runTestsSource.token).then(fn)); + gulp.watch(watchPatterns, (e) => fn()); // NOTE: gulp.watch is far too slow when watching tests/cases/**/* as it first enumerates *every* file const testFilePattern = /(\.ts|[\\/]tsconfig\.json)$/; fs.watch("tests/cases", { recursive: true }, (_, file) => { - if (testFilePattern.test(file)) project.wait(runTestsSource && runTestsSource.token).then(fn); + if (testFilePattern.test(file)) fn(); }); - - function runTests() { - if (runTestsSource) runTestsSource.cancel(); - runTestsSource = new CancelSource(); - return cmdLineOptions.tests || cmdLineOptions.failed - ? runConsoleTests(runJs, "mocha-fivemat-progress-reporter", /*runInParallel*/ false, /*watchMode*/ true, runTestsSource.token) - : runConsoleTests(runJs, "min", /*runInParallel*/ true, /*watchMode*/ true, runTestsSource.token); - } }); gulp.task("clean-built", /*help*/ false, [`clean:${diagnosticInformationMapTs}`], () => del(["built"])); diff --git a/package.json b/package.json index 510d3aab53b1b..55acc40268deb 100644 --- a/package.json +++ b/package.json @@ -81,6 +81,7 @@ "mocha": "latest", "mocha-fivemat-progress-reporter": "latest", "plugin-error": "latest", + "prex": "^0.4.3", "q": "latest", "remove-internal": "^2.9.2", "run-sequence": "latest", diff --git a/scripts/build/cancellation.js b/scripts/build/cancellation.js deleted file mode 100644 index 793aaf19d868c..0000000000000 --- a/scripts/build/cancellation.js +++ /dev/null @@ -1,71 +0,0 @@ -// @ts-check -const symSource = Symbol("CancelToken.source"); -const symToken = Symbol("CancelSource.token"); -const symCancellationRequested = Symbol("CancelSource.cancellationRequested"); -const symCancellationCallbacks = Symbol("CancelSource.cancellationCallbacks"); - -class CancelSource { - constructor() { - this[symCancellationRequested] = false; - this[symCancellationCallbacks] = []; - } - - /** @type {CancelToken} */ - get token() { - return this[symToken] || (this[symToken] = new CancelToken(this)); - } - - cancel() { - if (!this[symCancellationRequested]) { - this[symCancellationRequested] = true; - for (const callback of this[symCancellationCallbacks]) { - callback(); - } - } - } -} -exports.CancelSource = CancelSource; - -class CancelToken { - /** - * @param {CancelSource} source - */ - constructor(source) { - if (source[symToken]) return source[symToken]; - this[symSource] = source; - } - - /** @type {boolean} */ - get cancellationRequested() { - return this[symSource][symCancellationRequested]; - } - - /** - * @param {() => void} callback - */ - subscribe(callback) { - const source = this[symSource]; - if (source[symCancellationRequested]) { - callback(); - return; - } - - source[symCancellationCallbacks].push(callback); - - return { - unsubscribe() { - const index = source[symCancellationCallbacks].indexOf(callback); - if (index !== -1) source[symCancellationCallbacks].splice(index, 1); - } - }; - } -} -exports.CancelToken = CancelToken; - -class CancelError extends Error { - constructor(message = "Operation was canceled") { - super(message); - this.name = "CancelError"; - } -} -exports.CancelError = CancelError; \ No newline at end of file diff --git a/scripts/build/countdown.js b/scripts/build/countdown.js deleted file mode 100644 index dda05352d28c3..0000000000000 --- a/scripts/build/countdown.js +++ /dev/null @@ -1,62 +0,0 @@ -// @ts-check -const { CancelToken } = require("./cancellation"); - -class Countdown { - constructor(initialCount = 0) { - if (initialCount < 0) throw new Error(); - this._remainingCount = initialCount; - this._promise = undefined; - this._resolve = undefined; - } - - get remainingCount() { - return this._remainingCount; - } - - add(count = 1) { - if (count < 1 || !isFinite(count) || Math.trunc(count) !== count) throw new Error(); - if (this._remainingCount === 0) { - this._promise = undefined; - this._resolve = undefined; - } - - this._remainingCount += count; - } - - signal(count = 1) { - if (count < 1 || !isFinite(count) || Math.trunc(count) !== count) throw new Error(); - if (this._remainingCount - count < 0) throw new Error(); - this._remainingCount -= count; - if (this._remainingCount == 0) { - if (this._resolve) { - this._resolve(); - } - return true; - } - return false; - } - - /** @param {CancelToken} [token] */ - wait(token) { - if (!this._promise) { - this._promise = new Promise(resolve => { this._resolve = resolve; }); - } - if (this._remainingCount === 0) { - this._resolve(); - } - if (!token) return this._promise; - return new Promise((resolve, reject) => { - const subscription = token.subscribe(reject); - this._promise.then( - value => { - subscription.unsubscribe(); - resolve(value); - }, - error => { - subscription.unsubscribe(); - reject(error); - }); - }); - } -} -exports.Countdown = Countdown; \ No newline at end of file diff --git a/scripts/build/exec.js b/scripts/build/exec.js index 068bf33b9e906..024cb6d3b5b33 100644 --- a/scripts/build/exec.js +++ b/scripts/build/exec.js @@ -3,7 +3,7 @@ const cp = require("child_process"); const log = require("fancy-log"); // was `require("gulp-util").log (see https://github.com/gulpjs/gulp-util) const isWin = /^win/.test(process.platform); const chalk = require("./chalk"); -const { CancelToken, CancelError } = require("./cancellation"); +const { CancelError } = require("prex"); module.exports = exec; @@ -15,16 +15,20 @@ module.exports = exec; * * @typedef ExecOptions * @property {boolean} [ignoreExitCode] - * @property {CancelToken} [cancelToken] + * @property {import("prex").CancellationToken} [cancelToken] */ function exec(cmd, args, options = {}) { return /**@type {Promise<{exitCode: number}>}*/(new Promise((resolve, reject) => { + if (options.cancelToken) { + options.cancelToken.throwIfCancellationRequested(); + } + log(`> ${chalk.green(cmd)} ${args.join(" ")}`); // TODO (weswig): Update child_process types to add windowsVerbatimArguments to the type definition const subshellFlag = isWin ? "/c" : "-c"; const command = isWin ? [possiblyQuote(cmd), ...args] : [`${cmd} ${args.join(" ")}`]; const ex = cp.spawn(isWin ? "cmd" : "/bin/sh", [subshellFlag, ...command], { stdio: "inherit", windowsVerbatimArguments: true }); - const subscription = options.cancelToken && options.cancelToken.subscribe(() => { + const subscription = options.cancelToken && options.cancelToken.register(() => { log(`${chalk.red("killing")} '${chalk.green(cmd)} ${args.join(" ")}'...`); ex.kill("SIGINT"); ex.kill("SIGTERM"); @@ -32,7 +36,7 @@ function exec(cmd, args, options = {}) { reject(new CancelError()); }); ex.on("exit", exitCode => { - subscription && subscription.unsubscribe(); + if (subscription) subscription.unregister(); if (exitCode === 0 || options.ignoreExitCode) { resolve({ exitCode }); } @@ -41,7 +45,7 @@ function exec(cmd, args, options = {}) { } }); ex.on("error", error => { - subscription && subscription.unsubscribe(); + if (subscription) subscription.unregister(); reject(error); }); })); diff --git a/scripts/build/project.js b/scripts/build/project.js index 8519e4c71ec23..bd41926a2045d 100644 --- a/scripts/build/project.js +++ b/scripts/build/project.js @@ -3,6 +3,8 @@ const path = require("path"); const fs = require("fs"); const gulp = require("./gulp"); const gulpif = require("gulp-if"); +const log = require("fancy-log"); // was `require("gulp-util").log (see https://github.com/gulpjs/gulp-util) +const chalk = require("./chalk"); const sourcemaps = require("gulp-sourcemaps"); const merge2 = require("merge2"); const tsc = require("gulp-typescript"); @@ -12,42 +14,51 @@ const ts = require("../../lib/typescript"); const del = require("del"); const needsUpdate = require("./needsUpdate"); const mkdirp = require("./mkdirp"); +const prettyTime = require("pretty-hrtime"); const { reportDiagnostics } = require("./diagnostics"); -const { Countdown } = require("./countdown"); -const { CancelToken } = require("./cancellation"); +const { CountdownEvent, Pulsar } = require("prex"); -const countdown = new Countdown(); +const workStartedEvent = new Pulsar(); +const countdown = new CountdownEvent(0); class CompilationGulp extends gulp.Gulp { - constructor() { - super(); - this.on("start", () => { - const onDone = () => { - this.removeListener("stop", onDone); - this.removeListener("err", onDone); - countdown.signal(); - }; - - this.on("stop", onDone); - this.on("err", onDone); - countdown.add(); - }); - } - /** * @param {boolean} [verbose] */ fork(verbose) { const child = new ForkedGulp(this.tasks); - if (verbose) { - child.on("task_start", e => gulp.emit("task_start", e)); - child.on("task_stop", e => gulp.emit("task_stop", e)); - child.on("task_err", e => gulp.emit("task_err", e)); - child.on("task_not_found", e => gulp.emit("task_not_found", e)); - child.on("task_recursion", e => gulp.emit("task_recursion", e)); - } + child.on("task_start", e => { + if (countdown.remainingCount === 0) { + countdown.reset(1); + workStartedEvent.pulseAll(); + } + else { + countdown.add(); + } + if (verbose) { + log('Starting', `'${chalk.cyan(e.task)}' ${chalk.gray(`(${countdown.remainingCount} remaining)`)}...`); + } + }); + child.on("task_stop", e => { + countdown.signal(); + if (verbose) { + log('Finished', `'${chalk.cyan(e.task)}' after ${chalk.magenta(prettyTime(/** @type {*}*/(e).hrDuration))} ${chalk.gray(`(${countdown.remainingCount} remaining)`)}`); + } + }); + child.on("task_err", e => { + countdown.signal(); + if (verbose) { + log(`'${chalk.cyan(e.task)}' ${chalk.red("errored after")} ${chalk.magenta(prettyTime(/** @type {*}*/(e).hrDuration))} ${chalk.gray(`(${countdown.remainingCount} remaining)`)}`); + log(e.err ? e.err.stack : e.message); + } + }); return child; } + + // @ts-ignore + start() { + throw new Error("Not supported, use fork."); + } } class ForkedGulp extends gulp.Gulp { @@ -57,17 +68,6 @@ class ForkedGulp extends gulp.Gulp { constructor(tasks) { super(); this.tasks = tasks; - this.on("start", () => { - const onDone = () => { - this.removeListener("stop", onDone); - this.removeListener("err", onDone); - countdown.signal(); - }; - - this.on("stop", onDone); - this.on("err", onDone); - countdown.add(); - }); } // Do not reset tasks @@ -241,12 +241,26 @@ exports.flatten = flatten; /** * Returns a Promise that resolves when all pending build tasks have completed - * @param {CancelToken} [token] + * @param {import("prex").CancellationToken} [token] */ -function wait(token) { +function waitForWorkToComplete(token) { return countdown.wait(token); } -exports.wait = wait; +exports.waitForWorkToComplete = waitForWorkToComplete; + +/** + * Returns a Promise that resolves when all pending build tasks have completed + * @param {import("prex").CancellationToken} [token] + */ +function waitForWorkToStart(token) { + return workStartedEvent.wait(token); +} +exports.waitForWorkToStart = waitForWorkToStart; + +function getRemainingWork() { + return countdown.remainingCount > 0; +} +exports.hasRemainingWork = getRemainingWork; /** * Resolve a TypeScript specifier into a fully-qualified module specifier and any requisite dependencies. diff --git a/scripts/build/tests.js b/scripts/build/tests.js index d631f1e35acc5..3fd65b2c8598d 100644 --- a/scripts/build/tests.js +++ b/scripts/build/tests.js @@ -21,7 +21,7 @@ exports.localTest262Baseline = "internal/baselines/test262/local"; * @param {string} defaultReporter * @param {boolean} runInParallel * @param {boolean} watchMode - * @param {InstanceType} [cancelToken] + * @param {import("prex").CancellationToken} [cancelToken] */ async function runConsoleTests(runJs, defaultReporter, runInParallel, watchMode, cancelToken) { let testTimeout = cmdLineOptions.timeout; @@ -37,6 +37,7 @@ async function runConsoleTests(runJs, defaultReporter, runInParallel, watchMode, const keepFailed = cmdLineOptions.keepFailed; if (!cmdLineOptions.dirty) { await cleanTestDirs(); + if (cancelToken) cancelToken.throwIfCancellationRequested(); } if (fs.existsSync(testConfigFile)) { diff --git a/src/compiler/moduleNameResolver.ts b/src/compiler/moduleNameResolver.ts index 6545ce353e645..0c2d35f19a830 100644 --- a/src/compiler/moduleNameResolver.ts +++ b/src/compiler/moduleNameResolver.ts @@ -188,31 +188,21 @@ namespace ts { /* @internal */ export function getPackageJsonTypesVersionsPaths(typesVersions: MapLike>) { - if (!typeScriptVersion) typeScriptVersion = new Version(versionMajorMinor); + if (!typeScriptVersion) typeScriptVersion = new Version(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) { + const keyRange = VersionRange.tryParse(key); + if (keyRange === undefined) { continue; } - // match the greatest version less than the current TypeScript version - if (keyVersion.compareTo(bestVersion) > 0 && - keyVersion.compareTo(typeScriptVersion) <= 0) { - bestVersion = keyVersion; - bestVersionKey = key; + // return the first entry whose range matches the current compiler version. + if (keyRange.test(typeScriptVersion)) { + return { version: key, paths: typesVersions[key] }; } } - - if (!bestVersionKey) { - return; - } - - return { version: bestVersionKey, paths: typesVersions[bestVersionKey] }; } export function getEffectiveTypeRoots(options: CompilerOptions, host: GetEffectiveTypeRootsHost): string[] | undefined { @@ -1132,7 +1122,7 @@ namespace ts { if (versionPaths && containsPath(candidate, file)) { const moduleName = getRelativePathFromDirectory(candidate, file, /*ignoreCase*/ false); if (state.traceEnabled) { - trace(state.host, Diagnostics.package_json_has_a_typesVersions_entry_0_that_matches_compiler_version_1_looking_for_a_pattern_to_match_module_name_2, versionPaths.version, versionMajorMinor, moduleName); + trace(state.host, Diagnostics.package_json_has_a_typesVersions_entry_0_that_matches_compiler_version_1_looking_for_a_pattern_to_match_module_name_2, versionPaths.version, version, moduleName); } const result = tryLoadModuleUsingPaths(extensions, moduleName, candidate, versionPaths.paths, loader, onlyRecordFailures, state); if (result) { @@ -1255,7 +1245,7 @@ namespace ts { if (packageInfo) ({ packageId, versionPaths } = packageInfo); if (versionPaths) { if (state.traceEnabled) { - trace(state.host, Diagnostics.package_json_has_a_typesVersions_entry_0_that_matches_compiler_version_1_looking_for_a_pattern_to_match_module_name_2, versionPaths.version, versionMajorMinor, rest); + trace(state.host, Diagnostics.package_json_has_a_typesVersions_entry_0_that_matches_compiler_version_1_looking_for_a_pattern_to_match_module_name_2, versionPaths.version, version, rest); } const packageDirectoryExists = nodeModulesDirectoryExists && directoryProbablyExists(packageDirectory, state.host); const fromPaths = tryLoadModuleUsingPaths(extensions, rest, packageDirectory, versionPaths.paths, loader, !packageDirectoryExists, state); diff --git a/tests/baselines/reference/typesVersions.ambientModules.js b/tests/baselines/reference/typesVersions.ambientModules.js index 1d7e3f04ec30a..7dee6e9e3fded 100644 --- a/tests/baselines/reference/typesVersions.ambientModules.js +++ b/tests/baselines/reference/typesVersions.ambientModules.js @@ -6,7 +6,7 @@ "version": "1.0.0", "types": "index", "typesVersions": { - "3.1": { "*" : ["ts3.1/*"] } + ">=3.1.0-0": { "*" : ["ts3.1/*"] } } } diff --git a/tests/baselines/reference/typesVersions.ambientModules.trace.json b/tests/baselines/reference/typesVersions.ambientModules.trace.json index 7a442ce50486f..8e4d2ecba2d14 100644 --- a/tests/baselines/reference/typesVersions.ambientModules.trace.json +++ b/tests/baselines/reference/typesVersions.ambientModules.trace.json @@ -11,7 +11,7 @@ "File 'tests/cases/conformance/moduleResolution/node_modules/ext.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/index'.", - "'package.json' has a 'typesVersions' entry '3.1' that matches compiler version '3.1', looking for a pattern to match module name 'index'.", + "'package.json' has a 'typesVersions' entry '>=3.1.0-0' that matches compiler version '3.1.0-dev', looking for a pattern to match module name 'index'.", "Module name 'index', matched pattern '*'.", "Trying substitution 'ts3.1/*', candidate module location: 'ts3.1/index'.", "File 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.1/index' does not exist.", @@ -26,7 +26,7 @@ "Loading module 'ext/other' from 'node_modules' folder, target file type 'TypeScript'.", "'package.json' has a 'typesVersions' field with version-specific path mappings.", "Found 'package.json' at 'tests/cases/conformance/moduleResolution/node_modules/ext/package.json'. Package ID is 'ext/other/index.d.ts@1.0.0'.", - "'package.json' has a 'typesVersions' entry '3.1' that matches compiler version '3.1', looking for a pattern to match module name 'other'.", + "'package.json' has a 'typesVersions' entry '>=3.1.0-0' that matches compiler version '3.1.0-dev', looking for a pattern to match module name 'other'.", "Module name 'other', matched pattern '*'.", "Trying substitution 'ts3.1/*', candidate module location: 'ts3.1/other'.", "File 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.1/other.ts' does not exist.", @@ -41,7 +41,7 @@ "Loading module 'ext/other' from 'node_modules' folder, target file type 'JavaScript'.", "'package.json' has a 'typesVersions' field with version-specific path mappings.", "Found 'package.json' at 'tests/cases/conformance/moduleResolution/node_modules/ext/package.json'. Package ID is 'ext/other/index.d.ts@1.0.0'.", - "'package.json' has a 'typesVersions' entry '3.1' that matches compiler version '3.1', looking for a pattern to match module name 'other'.", + "'package.json' has a 'typesVersions' entry '>=3.1.0-0' that matches compiler version '3.1.0-dev', looking for a pattern to match module name 'other'.", "Module name 'other', matched pattern '*'.", "Trying substitution 'ts3.1/*', candidate module location: 'ts3.1/other'.", "File 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.1/other.js' does not exist.", diff --git a/tests/baselines/reference/typesVersions.multiFile.js b/tests/baselines/reference/typesVersions.multiFile.js index 14f7fd8aaf4c6..cca708988c688 100644 --- a/tests/baselines/reference/typesVersions.multiFile.js +++ b/tests/baselines/reference/typesVersions.multiFile.js @@ -6,7 +6,7 @@ "version": "1.0.0", "types": "index", "typesVersions": { - "3.1": { "*" : ["ts3.1/*"] } + ">=3.1.0-0": { "*" : ["ts3.1/*"] } } } diff --git a/tests/baselines/reference/typesVersions.multiFile.trace.json b/tests/baselines/reference/typesVersions.multiFile.trace.json index e7245fa5765bb..d52db48acfef2 100644 --- a/tests/baselines/reference/typesVersions.multiFile.trace.json +++ b/tests/baselines/reference/typesVersions.multiFile.trace.json @@ -11,7 +11,7 @@ "File 'tests/cases/conformance/moduleResolution/node_modules/ext.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/index'.", - "'package.json' has a 'typesVersions' entry '3.1' that matches compiler version '3.1', looking for a pattern to match module name 'index'.", + "'package.json' has a 'typesVersions' entry '>=3.1.0-0' that matches compiler version '3.1.0-dev', looking for a pattern to match module name 'index'.", "Module name 'index', matched pattern '*'.", "Trying substitution 'ts3.1/*', candidate module location: 'ts3.1/index'.", "File 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.1/index' does not exist.", @@ -26,7 +26,7 @@ "Loading module 'ext/other' from 'node_modules' folder, target file type 'TypeScript'.", "'package.json' has a 'typesVersions' field with version-specific path mappings.", "Found 'package.json' at 'tests/cases/conformance/moduleResolution/node_modules/ext/package.json'. Package ID is 'ext/other/index.d.ts@1.0.0'.", - "'package.json' has a 'typesVersions' entry '3.1' that matches compiler version '3.1', looking for a pattern to match module name 'other'.", + "'package.json' has a 'typesVersions' entry '>=3.1.0-0' that matches compiler version '3.1.0-dev', looking for a pattern to match module name 'other'.", "Module name 'other', matched pattern '*'.", "Trying substitution 'ts3.1/*', candidate module location: 'ts3.1/other'.", "File 'tests/cases/conformance/moduleResolution/node_modules/ext/ts3.1/other.ts' does not exist.", diff --git a/tests/baselines/reference/typesVersionsDeclarationEmit.ambient.js b/tests/baselines/reference/typesVersionsDeclarationEmit.ambient.js index b1af852940b9f..ddd2f8b0ef58a 100644 --- a/tests/baselines/reference/typesVersionsDeclarationEmit.ambient.js +++ b/tests/baselines/reference/typesVersionsDeclarationEmit.ambient.js @@ -6,7 +6,7 @@ "version": "1.0.0", "types": "index", "typesVersions": { - "3.1": { "*" : ["ts3.1/*"] } + ">=3.1.0-0": { "*" : ["ts3.1/*"] } } } diff --git a/tests/baselines/reference/typesVersionsDeclarationEmit.ambient.trace.json b/tests/baselines/reference/typesVersionsDeclarationEmit.ambient.trace.json index c3b0e2327481a..f1db86cc283fe 100644 --- a/tests/baselines/reference/typesVersionsDeclarationEmit.ambient.trace.json +++ b/tests/baselines/reference/typesVersionsDeclarationEmit.ambient.trace.json @@ -11,7 +11,7 @@ "File 'tests/cases/conformance/declarationEmit/node_modules/ext.d.ts' does not exist.", "'package.json' does not have a 'typings' field.", "'package.json' has 'types' field 'index' that references 'tests/cases/conformance/declarationEmit/node_modules/ext/index'.", - "'package.json' has a 'typesVersions' entry '3.1' that matches compiler version '3.1', looking for a pattern to match module name 'index'.", + "'package.json' has a 'typesVersions' entry '>=3.1.0-0' that matches compiler version '3.1.0-dev', looking for a pattern to match module name 'index'.", "Module name 'index', matched pattern '*'.", "Trying substitution 'ts3.1/*', candidate module location: 'ts3.1/index'.", "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/index' does not exist.", @@ -26,7 +26,7 @@ "Loading module 'ext/other' from 'node_modules' folder, target file type 'TypeScript'.", "'package.json' has a 'typesVersions' field with version-specific path mappings.", "Found 'package.json' at 'tests/cases/conformance/declarationEmit/node_modules/ext/package.json'. Package ID is 'ext/other/index.d.ts@1.0.0'.", - "'package.json' has a 'typesVersions' entry '3.1' that matches compiler version '3.1', looking for a pattern to match module name 'other'.", + "'package.json' has a 'typesVersions' entry '>=3.1.0-0' that matches compiler version '3.1.0-dev', looking for a pattern to match module name 'other'.", "Module name 'other', matched pattern '*'.", "Trying substitution 'ts3.1/*', candidate module location: 'ts3.1/other'.", "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/other.ts' does not exist.", @@ -41,7 +41,7 @@ "Loading module 'ext/other' from 'node_modules' folder, target file type 'JavaScript'.", "'package.json' has a 'typesVersions' field with version-specific path mappings.", "Found 'package.json' at 'tests/cases/conformance/declarationEmit/node_modules/ext/package.json'. Package ID is 'ext/other/index.d.ts@1.0.0'.", - "'package.json' has a 'typesVersions' entry '3.1' that matches compiler version '3.1', looking for a pattern to match module name 'other'.", + "'package.json' has a 'typesVersions' entry '>=3.1.0-0' that matches compiler version '3.1.0-dev', looking for a pattern to match module name 'other'.", "Module name 'other', matched pattern '*'.", "Trying substitution 'ts3.1/*', candidate module location: 'ts3.1/other'.", "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/other.js' does not exist.", diff --git a/tests/baselines/reference/typesVersionsDeclarationEmit.multiFile.js b/tests/baselines/reference/typesVersionsDeclarationEmit.multiFile.js index 22cdb0087ef22..5fd7da959ea2f 100644 --- a/tests/baselines/reference/typesVersionsDeclarationEmit.multiFile.js +++ b/tests/baselines/reference/typesVersionsDeclarationEmit.multiFile.js @@ -6,7 +6,7 @@ "version": "1.0.0", "types": "index", "typesVersions": { - "3.1": { "*" : ["ts3.1/*"] } + ">=3.1.0-0": { "*" : ["ts3.1/*"] } } } diff --git a/tests/baselines/reference/typesVersionsDeclarationEmit.multiFile.trace.json b/tests/baselines/reference/typesVersionsDeclarationEmit.multiFile.trace.json index 532e80feac79b..eee9622037b79 100644 --- a/tests/baselines/reference/typesVersionsDeclarationEmit.multiFile.trace.json +++ b/tests/baselines/reference/typesVersionsDeclarationEmit.multiFile.trace.json @@ -11,7 +11,7 @@ "File 'tests/cases/conformance/declarationEmit/node_modules/ext.d.ts' does not exist.", "'package.json' does not have a 'typings' field.", "'package.json' has 'types' field 'index' that references 'tests/cases/conformance/declarationEmit/node_modules/ext/index'.", - "'package.json' has a 'typesVersions' entry '3.1' that matches compiler version '3.1', looking for a pattern to match module name 'index'.", + "'package.json' has a 'typesVersions' entry '>=3.1.0-0' that matches compiler version '3.1.0-dev', looking for a pattern to match module name 'index'.", "Module name 'index', matched pattern '*'.", "Trying substitution 'ts3.1/*', candidate module location: 'ts3.1/index'.", "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/index' does not exist.", @@ -26,7 +26,7 @@ "Loading module 'ext/other' from 'node_modules' folder, target file type 'TypeScript'.", "'package.json' has a 'typesVersions' field with version-specific path mappings.", "Found 'package.json' at 'tests/cases/conformance/declarationEmit/node_modules/ext/package.json'. Package ID is 'ext/other/index.d.ts@1.0.0'.", - "'package.json' has a 'typesVersions' entry '3.1' that matches compiler version '3.1', looking for a pattern to match module name 'other'.", + "'package.json' has a 'typesVersions' entry '>=3.1.0-0' that matches compiler version '3.1.0-dev', looking for a pattern to match module name 'other'.", "Module name 'other', matched pattern '*'.", "Trying substitution 'ts3.1/*', candidate module location: 'ts3.1/other'.", "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/other.ts' does not exist.", diff --git a/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToSelf.errors.txt b/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToSelf.errors.txt index 66624634d9f62..540dd917fa0a1 100644 --- a/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToSelf.errors.txt +++ b/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToSelf.errors.txt @@ -9,7 +9,7 @@ tests/cases/conformance/declarationEmit/main.ts(1,10): error TS2305: Module '"te "version": "1.0.0", "types": "index", "typesVersions": { - "3.1": { "*" : ["ts3.1/*"] } + ">=3.1.0-0": { "*" : ["ts3.1/*"] } } } diff --git a/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToSelf.js b/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToSelf.js index c7b885d5e9e55..ab415ca2b61d4 100644 --- a/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToSelf.js +++ b/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToSelf.js @@ -6,7 +6,7 @@ "version": "1.0.0", "types": "index", "typesVersions": { - "3.1": { "*" : ["ts3.1/*"] } + ">=3.1.0-0": { "*" : ["ts3.1/*"] } } } diff --git a/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToSelf.trace.json b/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToSelf.trace.json index 33d5a0e317752..cf08a29478f1d 100644 --- a/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToSelf.trace.json +++ b/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToSelf.trace.json @@ -9,7 +9,7 @@ "'package.json' has a 'typesVersions' field with version-specific path mappings.", "'package.json' does not have a 'typings' field.", "'package.json' has 'types' field 'index' that references 'tests/cases/conformance/declarationEmit/node_modules/ext/index'.", - "'package.json' has a 'typesVersions' entry '3.1' that matches compiler version '3.1', looking for a pattern to match module name 'index'.", + "'package.json' has a 'typesVersions' entry '>=3.1.0-0' that matches compiler version '3.1.0-dev', looking for a pattern to match module name 'index'.", "Module name 'index', matched pattern '*'.", "Trying substitution 'ts3.1/*', candidate module location: 'ts3.1/index'.", "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/index' does not exist.", @@ -39,7 +39,7 @@ "File 'tests/cases/conformance/declarationEmit/node_modules/ext.d.ts' does not exist.", "'package.json' does not have a 'typings' field.", "'package.json' has 'types' field 'index' that references 'tests/cases/conformance/declarationEmit/node_modules/ext/index'.", - "'package.json' has a 'typesVersions' entry '3.1' that matches compiler version '3.1', looking for a pattern to match module name 'index'.", + "'package.json' has a 'typesVersions' entry '>=3.1.0-0' that matches compiler version '3.1.0-dev', looking for a pattern to match module name 'index'.", "Module name 'index', matched pattern '*'.", "Trying substitution 'ts3.1/*', candidate module location: 'ts3.1/index'.", "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/index' does not exist.", @@ -54,7 +54,7 @@ "Loading module 'ext/other' from 'node_modules' folder, target file type 'TypeScript'.", "'package.json' has a 'typesVersions' field with version-specific path mappings.", "Found 'package.json' at 'tests/cases/conformance/declarationEmit/node_modules/ext/package.json'. Package ID is 'ext/other/index.d.ts@1.0.0'.", - "'package.json' has a 'typesVersions' entry '3.1' that matches compiler version '3.1', looking for a pattern to match module name 'other'.", + "'package.json' has a 'typesVersions' entry '>=3.1.0-0' that matches compiler version '3.1.0-dev', looking for a pattern to match module name 'other'.", "Module name 'other', matched pattern '*'.", "Trying substitution 'ts3.1/*', candidate module location: 'ts3.1/other'.", "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/other.ts' does not exist.", diff --git a/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToUnmapped.js b/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToUnmapped.js index 86a621161f648..fb7dfd74b2d45 100644 --- a/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToUnmapped.js +++ b/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToUnmapped.js @@ -6,7 +6,7 @@ "version": "1.0.0", "types": "index", "typesVersions": { - "3.1": { + ">=3.1.0-0": { "index" : ["ts3.1/index"] } } diff --git a/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToUnmapped.trace.json b/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToUnmapped.trace.json index d31c0730fd995..fe65b605283e5 100644 --- a/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToUnmapped.trace.json +++ b/tests/baselines/reference/typesVersionsDeclarationEmit.multiFileBackReferenceToUnmapped.trace.json @@ -20,7 +20,7 @@ "File 'tests/cases/conformance/declarationEmit/node_modules/ext.d.ts' does not exist.", "'package.json' does not have a 'typings' field.", "'package.json' has 'types' field 'index' that references 'tests/cases/conformance/declarationEmit/node_modules/ext/index'.", - "'package.json' has a 'typesVersions' entry '3.1' that matches compiler version '3.1', looking for a pattern to match module name 'index'.", + "'package.json' has a 'typesVersions' entry '>=3.1.0-0' that matches compiler version '3.1.0-dev', looking for a pattern to match module name 'index'.", "Module name 'index', matched pattern 'index'.", "Trying substitution 'ts3.1/index', candidate module location: 'ts3.1/index'.", "File 'tests/cases/conformance/declarationEmit/node_modules/ext/ts3.1/index' does not exist.", @@ -35,7 +35,7 @@ "Loading module 'ext/other' from 'node_modules' folder, target file type 'TypeScript'.", "'package.json' has a 'typesVersions' field with version-specific path mappings.", "Found 'package.json' at 'tests/cases/conformance/declarationEmit/node_modules/ext/package.json'. Package ID is 'ext/other/index.d.ts@1.0.0'.", - "'package.json' has a 'typesVersions' entry '3.1' that matches compiler version '3.1', looking for a pattern to match module name 'other'.", + "'package.json' has a 'typesVersions' entry '>=3.1.0-0' that matches compiler version '3.1.0-dev', looking for a pattern to match module name 'other'.", "File 'tests/cases/conformance/declarationEmit/node_modules/ext/other.ts' does not exist.", "File 'tests/cases/conformance/declarationEmit/node_modules/ext/other.tsx' does not exist.", "File 'tests/cases/conformance/declarationEmit/node_modules/ext/other.d.ts' exist - use it as a name resolution result.", diff --git a/tests/cases/conformance/declarationEmit/typesVersionsDeclarationEmit.ambient.ts b/tests/cases/conformance/declarationEmit/typesVersionsDeclarationEmit.ambient.ts index 447f3aaa82a11..b03c1eea07837 100644 --- a/tests/cases/conformance/declarationEmit/typesVersionsDeclarationEmit.ambient.ts +++ b/tests/cases/conformance/declarationEmit/typesVersionsDeclarationEmit.ambient.ts @@ -9,7 +9,7 @@ "version": "1.0.0", "types": "index", "typesVersions": { - "3.1": { "*" : ["ts3.1/*"] } + ">=3.1.0-0": { "*" : ["ts3.1/*"] } } } diff --git a/tests/cases/conformance/declarationEmit/typesVersionsDeclarationEmit.multiFile.ts b/tests/cases/conformance/declarationEmit/typesVersionsDeclarationEmit.multiFile.ts index 57ae6c1d631fc..01adfac0480b9 100644 --- a/tests/cases/conformance/declarationEmit/typesVersionsDeclarationEmit.multiFile.ts +++ b/tests/cases/conformance/declarationEmit/typesVersionsDeclarationEmit.multiFile.ts @@ -8,7 +8,7 @@ "version": "1.0.0", "types": "index", "typesVersions": { - "3.1": { "*" : ["ts3.1/*"] } + ">=3.1.0-0": { "*" : ["ts3.1/*"] } } } diff --git a/tests/cases/conformance/declarationEmit/typesVersionsDeclarationEmit.multiFileBackReferenceToSelf.ts b/tests/cases/conformance/declarationEmit/typesVersionsDeclarationEmit.multiFileBackReferenceToSelf.ts index 3391361225d80..ee37f43630208 100644 --- a/tests/cases/conformance/declarationEmit/typesVersionsDeclarationEmit.multiFileBackReferenceToSelf.ts +++ b/tests/cases/conformance/declarationEmit/typesVersionsDeclarationEmit.multiFileBackReferenceToSelf.ts @@ -8,7 +8,7 @@ "version": "1.0.0", "types": "index", "typesVersions": { - "3.1": { "*" : ["ts3.1/*"] } + ">=3.1.0-0": { "*" : ["ts3.1/*"] } } } diff --git a/tests/cases/conformance/declarationEmit/typesVersionsDeclarationEmit.multiFileBackReferenceToUnmapped.ts b/tests/cases/conformance/declarationEmit/typesVersionsDeclarationEmit.multiFileBackReferenceToUnmapped.ts index 15072d2a7ed15..7ef6adcce52af 100644 --- a/tests/cases/conformance/declarationEmit/typesVersionsDeclarationEmit.multiFileBackReferenceToUnmapped.ts +++ b/tests/cases/conformance/declarationEmit/typesVersionsDeclarationEmit.multiFileBackReferenceToUnmapped.ts @@ -8,7 +8,7 @@ "version": "1.0.0", "types": "index", "typesVersions": { - "3.1": { + ">=3.1.0-0": { "index" : ["ts3.1/index"] } } diff --git a/tests/cases/conformance/moduleResolution/typesVersions.ambientModules.ts b/tests/cases/conformance/moduleResolution/typesVersions.ambientModules.ts index 2de5f47047369..870a1a1308dc7 100644 --- a/tests/cases/conformance/moduleResolution/typesVersions.ambientModules.ts +++ b/tests/cases/conformance/moduleResolution/typesVersions.ambientModules.ts @@ -8,7 +8,7 @@ "version": "1.0.0", "types": "index", "typesVersions": { - "3.1": { "*" : ["ts3.1/*"] } + ">=3.1.0-0": { "*" : ["ts3.1/*"] } } } diff --git a/tests/cases/conformance/moduleResolution/typesVersions.multiFile.ts b/tests/cases/conformance/moduleResolution/typesVersions.multiFile.ts index 8d57630af218d..14a05118b6531 100644 --- a/tests/cases/conformance/moduleResolution/typesVersions.multiFile.ts +++ b/tests/cases/conformance/moduleResolution/typesVersions.multiFile.ts @@ -7,7 +7,7 @@ "version": "1.0.0", "types": "index", "typesVersions": { - "3.1": { "*" : ["ts3.1/*"] } + ">=3.1.0-0": { "*" : ["ts3.1/*"] } } } From e726e4cfecbe808cdca9122ea9e62835498706b0 Mon Sep 17 00:00:00 2001 From: Ron Buckton Date: Wed, 5 Sep 2018 11:23:39 -0700 Subject: [PATCH 10/10] PR Feedback --- src/compiler/diagnosticMessages.json | 4 ++++ src/compiler/moduleNameResolver.ts | 8 ++++++++ 2 files changed, 12 insertions(+) diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 8eb5f73b1a9a6..a1e33f00d8faf 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -3684,6 +3684,10 @@ "category": "Message", "code": 6208 }, + "'package.json' has a 'typesVersions' entry '{0}' that is not a valid semver range.": { + "category": "Message", + "code": 6209 + }, "Projects to reference": { "category": "Message", diff --git a/src/compiler/moduleNameResolver.ts b/src/compiler/moduleNameResolver.ts index 0c2d35f19a830..bae4dbfa430cd 100644 --- a/src/compiler/moduleNameResolver.ts +++ b/src/compiler/moduleNameResolver.ts @@ -165,6 +165,14 @@ namespace ts { const typesVersions = readPackageJsonTypesVersionsField(jsonContent, state); if (typesVersions === undefined) return; + if (state.traceEnabled) { + for (const key in typesVersions) { + if (hasProperty(typesVersions, key) && !VersionRange.tryParse(key)) { + trace(state.host, Diagnostics.package_json_has_a_typesVersions_entry_0_that_is_not_a_valid_semver_range, key); + } + } + } + const result = getPackageJsonTypesVersionsPaths(typesVersions); if (!result) { if (state.traceEnabled) {