diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 733e3158593df..d5bf95a64058a 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -255,7 +255,7 @@ namespace ts { name: "moduleResolution", type: { "node": ModuleResolutionKind.NodeJs, - "classic": ModuleResolutionKind.Classic + "classic": ModuleResolutionKind.Classic, }, description: Diagnostics.Specifies_module_resolution_strategy_Colon_node_Node_js_or_classic_TypeScript_pre_1_6, error: Diagnostics.Argument_for_moduleResolution_option_must_be_node_or_classic, @@ -286,14 +286,40 @@ namespace ts { description: Diagnostics.Disallow_inconsistently_cased_references_to_the_same_file }, { - name: "allowSyntheticDefaultImports", + name: "baseUrl", + type: "string", + isFilePath: true, + description: Diagnostics.Base_directory_to_resolve_non_absolute_module_names + }, + { + // this option can only be specified in tsconfig.json + // use type = object to copy the value as-is + name: "paths", + type: "object", + isTSConfigOnly: true + }, + { + // this option can only be specified in tsconfig.json + // use type = object to copy the value as-is + name: "rootDirs", + type: "object", + isTSConfigOnly: true, + isFilePath: true + }, + { + name: "traceModuleResolution", type: "boolean", - description: Diagnostics.Allow_default_imports_from_modules_with_no_default_export_This_does_not_affect_code_emit_just_typechecking + description: Diagnostics.Enable_tracing_of_the_module_resolution_process }, { name: "allowJs", type: "boolean", description: Diagnostics.Allow_javascript_files_to_be_compiled + }, + { + name: "allowSyntheticDefaultImports", + type: "boolean", + description: Diagnostics.Allow_default_imports_from_modules_with_no_default_export_This_does_not_affect_code_emit_just_typechecking } ]; @@ -355,34 +381,39 @@ namespace ts { if (hasProperty(optionNameMap, s)) { const opt = optionNameMap[s]; - // Check to see if no argument was provided (e.g. "--locale" is the last command-line argument). - if (!args[i] && opt.type !== "boolean") { - errors.push(createCompilerDiagnostic(Diagnostics.Compiler_option_0_expects_an_argument, opt.name)); + if (opt.isTSConfigOnly) { + errors.push(createCompilerDiagnostic(Diagnostics.Option_0_can_only_be_specified_in_tsconfig_json_file, opt.name)); } + else { + // Check to see if no argument was provided (e.g. "--locale" is the last command-line argument). + if (!args[i] && opt.type !== "boolean") { + errors.push(createCompilerDiagnostic(Diagnostics.Compiler_option_0_expects_an_argument, opt.name)); + } - switch (opt.type) { - case "number": - options[opt.name] = parseInt(args[i]); - i++; - break; - case "boolean": - options[opt.name] = true; - break; - case "string": - options[opt.name] = args[i] || ""; - i++; - break; - // If not a primitive, the possible types are specified in what is effectively a map of options. - default: - let map = >opt.type; - let key = (args[i] || "").toLowerCase(); - i++; - if (hasProperty(map, key)) { - options[opt.name] = map[key]; - } - else { - errors.push(createCompilerDiagnostic((opt).error)); - } + switch (opt.type) { + case "number": + options[opt.name] = parseInt(args[i]); + i++; + break; + case "boolean": + options[opt.name] = true; + break; + case "string": + options[opt.name] = args[i] || ""; + i++; + break; + // If not a primitive, the possible types are specified in what is effectively a map of options. + default: + let map = >opt.type; + let key = (args[i] || "").toLowerCase(); + i++; + if (hasProperty(map, key)) { + options[opt.name] = map[key]; + } + else { + errors.push(createCompilerDiagnostic((opt).error)); + } + } } } else { @@ -485,7 +516,6 @@ namespace ts { return output; } - /** * Parse the contents of a config file (tsconfig.json). * @param json The contents of the config file to parse @@ -497,6 +527,7 @@ namespace ts { const { options: optionsFromJsonConfigFile, errors } = convertCompilerOptionsFromJson(json["compilerOptions"], basePath, configFileName); const options = extend(existingOptions, optionsFromJsonConfigFile); + return { options, fileNames: getFileNames(), @@ -580,7 +611,36 @@ namespace ts { } } if (opt.isFilePath) { - value = normalizePath(combinePaths(basePath, value)); + switch (typeof value) { + case "string": + value = normalizePath(combinePaths(basePath, value)); + break; + case "object": + // "object" options with 'isFilePath' = true expected to be string arrays + let paths: string[] = []; + let invalidOptionType = false; + if (!isArray(value)) { + invalidOptionType = true; + } + else { + for (const element of value) { + if (typeof element === "string") { + paths.push(normalizePath(combinePaths(basePath, element))); + } + else { + invalidOptionType = true; + break; + } + } + } + if (invalidOptionType) { + errors.push(createCompilerDiagnostic(Diagnostics.Option_0_should_have_array_of_strings_as_a_value, opt.name)); + } + else { + value = paths; + } + break; + } if (value === "") { value = "."; } diff --git a/src/compiler/core.ts b/src/compiler/core.ts index cfdcb2b930c63..21536da36ff26 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -74,8 +74,6 @@ namespace ts { GreaterThan = 1 } - export interface StringSet extends Map { } - /** * Iterates through 'array' by index and performs the callback on each element of array until the callback * returns a truthy value, then returns that value. @@ -441,6 +439,17 @@ namespace ts { }; } + /* internal */ + export function formatMessage(dummy: any, message: DiagnosticMessage): string { + let text = getLocaleSpecificMessage(message); + + if (arguments.length > 2) { + text = formatStringFromArgs(text, arguments, 2); + } + + return text; + } + export function createCompilerDiagnostic(message: DiagnosticMessage, ...args: any[]): Diagnostic; export function createCompilerDiagnostic(message: DiagnosticMessage): Diagnostic { let text = getLocaleSpecificMessage(message); diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 8fd40f7b42169..2d677c90e7c06 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -2159,7 +2159,18 @@ "category": "Error", "code": 5059 }, - + "Option 'paths' cannot be used without specifying '--baseUrl' option.": { + "category": "Error", + "code": 5060 + }, + "Pattern '{0}' can have at most one '*' character": { + "category": "Error", + "code": 5061 + }, + "Substitution '{0}' in pattern '{1}' in can have at most one '*' character": { + "category": "Error", + "code": 5062 + }, "Concatenate and emit output to single file.": { "category": "Message", "code": 6001 @@ -2296,10 +2307,10 @@ "category": "Error", "code": 6046 }, - "Argument for '--target' option must be 'ES3', 'ES5', or 'ES2015'.": { - "category": "Error", - "code": 6047 - }, + "Argument for '--target' option must be 'ES3', 'ES5', or 'ES2015'.": { + "category": "Error", + "code": 6047 + }, "Locale must be of the form or -. For example '{0}' or '{1}'.": { "category": "Error", "code": 6048 @@ -2360,7 +2371,10 @@ "category": "Error", "code": 6063 }, - + "Option '{0}' can only be specified in 'tsconfig.json' file.": { + "category": "Error", + "code": 6064 + }, "Enables experimental support for ES7 decorators.": { "category": "Message", "code": 6065 @@ -2425,7 +2439,7 @@ "category": "Error", "code": 6082 }, - "Allow javascript files to be compiled.": { + "Base directory to resolve non-absolute module names.": { "category": "Message", "code": 6083 }, @@ -2433,7 +2447,114 @@ "category": "Message", "code": 6084 }, - + "Enable tracing of the module resolution process.": { + "category": "Message", + "code": 6085 + }, + "======== Resolving module '{0}' from '{1}'. ========": { + "category": "Message", + "code": 6086 + }, + "Explicitly specified module resolution kind: '{0}'.": { + "category": "Message", + "code": 6087 + }, + "Module resolution kind is not specified, using '{0}'.": { + "category": "Message", + "code": 6088 + }, + "======== Module name '{0}' was successfully resolved to '{1}'. ========": { + "category": "Message", + "code": 6089 + }, + "======== Module name '{0}' was not resolved. ========": { + "category": "Message", + "code": 6090 + }, + "'paths' option is specified, looking for a pattern to match module name '{0}'.": { + "category": "Message", + "code": 6091 + }, + "Module name '{0}', matched pattern '{1}'.": { + "category": "Message", + "code": 6092 + }, + "Trying substitution '{0}', candidate module location: '{1}'.": { + "category": "Message", + "code": 6093 + }, + "Resolving module name '{0}' relative to base url '{1}' - '{2}'.": { + "category": "Message", + "code": 6094 + }, + "Loading module as file / folder, candidate module location '{0}'.": { + "category": "Message", + "code": 6095 + }, + "File '{0}' does not exist.": { + "category": "Message", + "code": 6096 + }, + "File '{0}' exist - use it as a module resolution result.": { + "category": "Message", + "code": 6097 + }, + "Loading module '{0}' from 'node_modules' folder.": { + "category": "Message", + "code": 6098 + }, + "Found 'package.json' at '{0}'.": { + "category": "Message", + "code": 6099 + }, + "'package.json' does not have 'typings' field.": { + "category": "Message", + "code": 6100 + }, + "'package.json' has 'typings' field '{0}' that references '{1}'.": { + "category": "Message", + "code": 6101 + }, + "Allow javascript files to be compiled.": { + "category": "Message", + "code": 6102 + }, + "Option '{0}' should have array of strings as a value.": { + "category": "Error", + "code": 6103 + }, + "Checking if '{0}' is the longest matching prefix for '{1}' - '{2}'.": { + "category": "Message", + "code": 6104 + }, + "Expected type of 'typings' field in 'package.json' to be 'string', got '{0}'.": { + "category": "Message", + "code": 6105 + }, + "'baseUrl' option is set to '{0}', using this value to resolve non-relative module name '{1}'": { + "category": "Message", + "code": 6106 + }, + "'rootDirs' option is set, using it to resolve relative module name '{0}'": { + "category": "Message", + "code": 6107 + }, + "Longest matching prefix for '{0}' is '{1}'": { + "category": "Message", + "code": 6108 + }, + "Loading '{0}' from the root dir '{1}', candidate location '{2}'": { + "category": "Message", + "code": 6109 + }, + "Trying other entries in 'rootDirs'": { + "category": "Message", + "code": 6110 + }, + "Module resolution using 'rootDirs' has failed": { + "category": "Message", + "code": 6111 + }, "Variable '{0}' implicitly has an '{1}' type.": { "category": "Error", "code": 7005 diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 398ce27ef48a3..90517ab3189ff 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -36,37 +36,372 @@ namespace ts { return normalizePath(referencedFileName); } + function trace(host: ModuleResolutionHost, message: DiagnosticMessage, ...args: any[]): void; + function trace(host: ModuleResolutionHost, message: DiagnosticMessage): void { + host.trace(formatMessage.apply(undefined, arguments)); + } + + function isTraceEnabled(compilerOptions: CompilerOptions, host: ModuleResolutionHost): boolean { + return compilerOptions.traceModuleResolution && host.trace !== undefined; + } + + function startsWith(str: string, prefix: string): boolean { + return str.lastIndexOf(prefix, 0) === 0; + } + + function endsWith(str: string, suffix: string): boolean { + const expectedPos = str.length - suffix.length; + return str.indexOf(suffix, expectedPos) === expectedPos; + } + + function hasZeroOrOneAsteriskCharacter(str: string): boolean { + let seenAsterisk = false; + for (let i = 0; i < str.length; i++) { + if (str.charCodeAt(i) === CharacterCodes.asterisk) { + if (!seenAsterisk) { + seenAsterisk = true; + } + else { + // have already seen asterisk + return false; + } + } + } + return true; + } + + function createResolvedModule(resolvedFileName: string, isExternalLibraryImport: boolean, failedLookupLocations: string[]): ResolvedModuleWithFailedLookupLocations { + return { resolvedModule: resolvedFileName ? { resolvedFileName, isExternalLibraryImport } : undefined, failedLookupLocations }; + } + + function moduleHasNonRelativeName(moduleName: string): boolean { + if (isRootedDiskPath(moduleName)) { + return false; + } + + const i = moduleName.lastIndexOf("./", 1); + const startsWithDotSlashOrDotDotSlash = i === 0 || (i === 1 && moduleName.charCodeAt(0) === CharacterCodes.dot); + return !startsWithDotSlashOrDotDotSlash; + } + + interface ModuleResolutionState { + host: ModuleResolutionHost; + compilerOptions: CompilerOptions; + traceEnabled: boolean; + } + export function resolveModuleName(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost): ResolvedModuleWithFailedLookupLocations { - const moduleResolution = compilerOptions.moduleResolution !== undefined - ? compilerOptions.moduleResolution - : compilerOptions.module === ModuleKind.CommonJS ? ModuleResolutionKind.NodeJs : ModuleResolutionKind.Classic; + const traceEnabled = isTraceEnabled(compilerOptions, host); + if (traceEnabled) { + trace(host, Diagnostics.Resolving_module_0_from_1, moduleName, containingFile); + } + + let moduleResolution = compilerOptions.moduleResolution; + if (moduleResolution === undefined) { + moduleResolution = compilerOptions.module === ModuleKind.CommonJS ? ModuleResolutionKind.NodeJs : ModuleResolutionKind.Classic; + if (traceEnabled) { + trace(host, Diagnostics.Module_resolution_kind_is_not_specified_using_0, ModuleResolutionKind[moduleResolution]); + } + } + else { + if (traceEnabled) { + trace(host, Diagnostics.Explicitly_specified_module_resolution_kind_Colon_0, ModuleResolutionKind[moduleResolution]); + } + } + let result: ResolvedModuleWithFailedLookupLocations; switch (moduleResolution) { - case ModuleResolutionKind.NodeJs: return nodeModuleNameResolver(moduleName, containingFile, compilerOptions, host); - case ModuleResolutionKind.Classic: return classicNameResolver(moduleName, containingFile, compilerOptions, host); + case ModuleResolutionKind.NodeJs: + result = nodeModuleNameResolver(moduleName, containingFile, compilerOptions, host); + break; + case ModuleResolutionKind.Classic: + result = classicNameResolver(moduleName, containingFile, compilerOptions, host); + break; + } + + if (traceEnabled) { + if (result.resolvedModule) { + trace(host, Diagnostics.Module_name_0_was_successfully_resolved_to_1, moduleName, result.resolvedModule.resolvedFileName); + } + else { + trace(host, Diagnostics.Module_name_0_was_not_resolved, moduleName); + } + } + + return result; + } + + /* + * Every module resolution kind can has its specific understanding how to load module from a specific path on disk + * I.e. for path '/a/b/c': + * - Node loader will first to try to check if '/a/b/c' points to a file with some supported extension and if this fails + * it will try to load module from directory: directory '/a/b/c' should exist and it should have either 'package.json' with + * 'typings' entry or file 'index' with some supported extension + * - Classic loader will only try to interpret '/a/b/c' as file. + */ + type ResolutionKindSpecificLoader = (candidate: string, extensions: string[], failedLookupLocations: string[], onlyRecordFalures: boolean, state: ModuleResolutionState) => string; + + /** + * Any module resolution kind can be augmented with optional settings: 'baseUrl', 'paths' and 'rootDirs' - they are used to + * mitigate differences between design time structure of the project and its runtime counterpart so the same import name + * can be resolved successfully by TypeScript compiler and runtime module loader. + * If these settings are set then loading procedure will try to use them to resolve module name and it can of failure it will + * fallback to standard resolution routine. + * + * - baseUrl - this setting controls how non-relative module names are resolved. If this setting is specified then non-relative + * names will be resolved relative to baseUrl: i.e. if baseUrl is '/a/b' then canditate location to resolve module name 'c/d' will + * be '/a/b/c/d' + * - paths - this setting can only be used when baseUrl is specified. allows to tune how non-relative module names + * will be resolved based on the content of the module name. + * Structure of 'paths' compiler options + * 'paths': { + * pattern-1: [...substitutions], + * pattern-2: [...substitutions], + * ... + * pattern-n: [...substitutions] + * } + * Pattern here is a string that can contain zero or one '*' character. During module resolution module name will be matched against + * all patterns in the list. Matching for patterns that don't contain '*' means that module name must be equal to pattern respecting the case. + * If pattern contains '*' then to match pattern "*" module name must start with the and end with . + * denotes part of the module name between and . + * If module name can be matches with multiple patterns then pattern with the longest prefix will be picked. + * After selecting pattern we'll use list of substitutions to get candidate locations of the module and the try to load module + * from the candidate location. + * Substitiution is a string that can contain zero or one '*'. To get candidate location from substitution we'll pick every + * substitution in the list and replace '*' with string. If candidate location is not rooted it + * will be converted to absolute using baseUrl. + * For example: + * baseUrl: /a/b/c + * "paths": { + * // match all module names + * "*": [ + * "*", // use matched name as is, + * // will be looked as /a/b/c/ + * + * "folder1/*" // substitution will convert matched name to 'folder1/', + * // since it is not rooted then final candidate location will be /a/b/c/folder1/ + * ], + * // match module names that start with 'components/' + * "components/*": [ "/root/components/*" ] // substitution will convert /components/folder1/ to '/root/components/folder1/', + * // it is rooted so it will be final candidate location + * } + * + * 'rootDirs' allows the project to be spreaded across multiple locations and resolve modules with relative names as if + * they were in the same location. For example lets say there are two files + * '/local/src/content/file1.ts' + * '/shared/components/contracts/src/content/protocols/file2.ts' + * After bundling content of '/shared/components/contracts/src' will be merged with '/local/src' so + * if file1 has the following import 'import {x} from "./protocols/file2"' it will be resolved successfully in runtime. + * 'rootDirs' provides the way to tell compiler that in order to get the whole project it should behave as if content of all + * root dirs were merged together. + * I.e. for the example above 'rootDirs' will have two entries: [ '/local/src', '/shared/components/contracts/src' ]. + * Compiler wil first convert './protocols/file2' into absolute path relative to the location of containing file: + * '/local/src/content/protocols/file2' and try to load it - failure. + * Then it will search 'rootDirs' looking for a longest matching prefix of this absolute path and if such prefix is found - absolute path will + * be converted to a path relative to found rootDir entry './content/protocols/file2' (*). As a last step compiler will check all remainining + * entries in 'rootDirs', use them to build absolute path out of (*) and try to resolve module from this location. + */ + function tryLoadModuleUsingOptionalResolutionSettings(moduleName: string, containingDirectory: string, loader: ResolutionKindSpecificLoader, + failedLookupLocations: string[], supportedExtensions: string[], state: ModuleResolutionState): string { + + if (moduleHasNonRelativeName(moduleName)) { + return tryLoadModuleUsingBaseUrl(moduleName, loader, failedLookupLocations, supportedExtensions, state); + } + else { + return tryLoadModuleUsingRootDirs(moduleName, containingDirectory, loader, failedLookupLocations, supportedExtensions, state); + } + } + + function tryLoadModuleUsingRootDirs(moduleName: string, containingDirectory: string, loader: ResolutionKindSpecificLoader, + failedLookupLocations: string[], supportedExtensions: string[], state: ModuleResolutionState): string { + + if (!state.compilerOptions.rootDirs) { + return undefined; + } + + if (state.traceEnabled) { + trace(state.host, Diagnostics.rootDirs_option_is_set_using_it_to_resolve_relative_module_name_0, moduleName); + } + + const candidate = normalizePath(combinePaths(containingDirectory, moduleName)); + + let matchedRootDir: string; + let matchedNormalizedPrefix: string; + for (const rootDir of state.compilerOptions.rootDirs) { + // rootDirs are expected to be absolute + // in case of tsconfig.json this will happen automatically - compiler will expand relative names + // using locaton of tsconfig.json as base location + let normalizedRoot = normalizePath(rootDir); + if (!endsWith(normalizedRoot, directorySeparator)) { + normalizedRoot += directorySeparator; + } + const isLongestMatchingPrefix = + startsWith(candidate, normalizedRoot) && + (matchedNormalizedPrefix === undefined || matchedNormalizedPrefix.length < normalizedRoot.length); + + if (state.traceEnabled) { + trace(state.host, Diagnostics.Checking_if_0_is_the_longest_matching_prefix_for_1_2, normalizedRoot, candidate, isLongestMatchingPrefix); + } + + if (isLongestMatchingPrefix) { + matchedNormalizedPrefix = normalizedRoot; + matchedRootDir = rootDir; + } + } + if (matchedNormalizedPrefix) { + if (state.traceEnabled) { + trace(state.host, Diagnostics.Longest_matching_prefix_for_0_is_1, candidate, matchedNormalizedPrefix); + } + const suffix = candidate.substr(matchedNormalizedPrefix.length); + + // first - try to load from a initial location + if (state.traceEnabled) { + trace(state.host, Diagnostics.Loading_0_from_the_root_dir_1_candidate_location_2, suffix, matchedNormalizedPrefix, candidate); + } + const resolvedFileName = loader(candidate, supportedExtensions, failedLookupLocations, !directoryProbablyExists(containingDirectory, state.host), state); + if (resolvedFileName) { + return resolvedFileName; + } + + if (state.traceEnabled) { + trace(state.host, Diagnostics.Trying_other_entries_in_rootDirs); + } + // then try to resolve using remaining entries in rootDirs + for (const rootDir of state.compilerOptions.rootDirs) { + if (rootDir === matchedRootDir) { + // skip the initially matched entry + continue; + } + const candidate = combinePaths(normalizePath(rootDir), suffix); + if (state.traceEnabled) { + trace(state.host, Diagnostics.Loading_0_from_the_root_dir_1_candidate_location_2, suffix, rootDir, candidate); + } + const baseDirectory = getDirectoryPath(candidate); + const resolvedFileName = loader(candidate, supportedExtensions, failedLookupLocations, !directoryProbablyExists(baseDirectory, state.host), state); + if (resolvedFileName) { + return resolvedFileName; + } + } + if (state.traceEnabled) { + trace(state.host, Diagnostics.Module_resolution_using_rootDirs_has_failed); + } + } + return undefined; + } + + function tryLoadModuleUsingBaseUrl(moduleName: string, loader: ResolutionKindSpecificLoader, failedLookupLocations: string[], + supportedExtensions: string[], state: ModuleResolutionState): string { + + if (!state.compilerOptions.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); + } + + let longestMatchPrefixLength = -1; + let matchedPattern: string; + let matchedStar: string; + + if (state.compilerOptions.paths) { + if (state.traceEnabled) { + trace(state.host, Diagnostics.paths_option_is_specified_looking_for_a_pattern_to_match_module_name_0, moduleName); + } + + for (const key in state.compilerOptions.paths) { + const pattern: string = key; + const indexOfStar = pattern.indexOf("*"); + if (indexOfStar !== -1) { + const prefix = pattern.substr(0, indexOfStar); + const suffix = pattern.substr(indexOfStar + 1); + if (moduleName.length >= prefix.length + suffix.length && + startsWith(moduleName, prefix) && + endsWith(moduleName, suffix)) { + + // use length of prefix as betterness criteria + if (prefix.length > longestMatchPrefixLength) { + longestMatchPrefixLength = prefix.length; + matchedPattern = pattern; + matchedStar = moduleName.substr(prefix.length, moduleName.length - suffix.length); + } + } + } + else if (pattern === moduleName) { + // pattern was matched as is - no need to seatch further + matchedPattern = pattern; + matchedStar = undefined; + break; + } + } + } + + if (matchedPattern) { + if (state.traceEnabled) { + trace(state.host, Diagnostics.Module_name_0_matched_pattern_1, moduleName, matchedPattern); + } + for (const subst of state.compilerOptions.paths[matchedPattern]) { + 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); + } + const resolvedFileName = loader(candidate, supportedExtensions, failedLookupLocations, !directoryProbablyExists(getDirectoryPath(candidate), state.host), state); + if (resolvedFileName) { + return resolvedFileName; + } + } + return undefined; + } + 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(candidate, supportedExtensions, failedLookupLocations, !directoryProbablyExists(getDirectoryPath(candidate), state.host), state); } } export function nodeModuleNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost): ResolvedModuleWithFailedLookupLocations { const containingDirectory = getDirectoryPath(containingFile); const supportedExtensions = getSupportedExtensions(compilerOptions); - if (getRootLength(moduleName) !== 0 || nameStartsWithDotSlashOrDotDotSlash(moduleName)) { - const failedLookupLocations: string[] = []; - const candidate = normalizePath(combinePaths(containingDirectory, moduleName)); - let resolvedFileName = loadNodeModuleFromFile(supportedExtensions, candidate, failedLookupLocations, /*onlyRecordFailures*/ false, host); + const traceEnabled = isTraceEnabled(compilerOptions, host); - if (resolvedFileName) { - return { resolvedModule: { resolvedFileName }, failedLookupLocations }; - } + const failedLookupLocations: string[] = []; + const state = {compilerOptions, host, traceEnabled}; + let resolvedFileName = tryLoadModuleUsingOptionalResolutionSettings(moduleName, containingDirectory, nodeLoadModuleByRelativeName, + failedLookupLocations, supportedExtensions, state); + + if (resolvedFileName) { + return createResolvedModule(resolvedFileName, /*isExternalLibraryImport*/false, failedLookupLocations); + } - resolvedFileName = loadNodeModuleFromDirectory(supportedExtensions, candidate, failedLookupLocations, /*onlyRecordFailures*/ false, host); - return resolvedFileName - ? { resolvedModule: { resolvedFileName }, failedLookupLocations } - : { resolvedModule: undefined, failedLookupLocations }; + let isExternalLibraryImport = false; + if (moduleHasNonRelativeName(moduleName)) { + if (traceEnabled) { + trace(host, Diagnostics.Loading_module_0_from_node_modules_folder, moduleName); + } + resolvedFileName = loadModuleFromNodeModules(moduleName, containingDirectory, failedLookupLocations, state); + isExternalLibraryImport = resolvedFileName !== undefined; } else { - return loadModuleFromNodeModules(moduleName, containingDirectory, host); + const candidate = normalizePath(combinePaths(containingDirectory, moduleName)); + resolvedFileName = nodeLoadModuleByRelativeName(candidate, supportedExtensions, failedLookupLocations, /*onlyRecordFailures*/ false, state); + } + return createResolvedModule(resolvedFileName, isExternalLibraryImport, failedLookupLocations); + } + + function nodeLoadModuleByRelativeName(candidate: string, supportedExtensions: string[], failedLookupLocations: string[], + onlyRecordFailures: boolean, state: ModuleResolutionState): string { + + if (state.traceEnabled) { + trace(state.host, Diagnostics.Loading_module_as_file_Slash_folder_candidate_module_location_0, candidate); } + + const resolvedFileName = loadModuleFromFile(candidate, supportedExtensions, failedLookupLocations, onlyRecordFailures, state); + + return resolvedFileName || loadNodeModuleFromDirectory(supportedExtensions, candidate, failedLookupLocations, onlyRecordFailures, state); } /* @internal */ @@ -79,30 +414,39 @@ namespace ts { * @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 loadNodeModuleFromFile(extensions: string[], candidate: string, failedLookupLocation: string[], onlyRecordFailures: boolean, host: ModuleResolutionHost): string { + function loadModuleFromFile(candidate: string, extensions: string[], failedLookupLocation: string[], onlyRecordFailures: boolean, state: ModuleResolutionState): string { return forEach(extensions, tryLoad); function tryLoad(ext: string): string { const fileName = fileExtensionIs(candidate, ext) ? candidate : candidate + ext; - if (!onlyRecordFailures && host.fileExists(fileName)) { + if (!onlyRecordFailures && state.host.fileExists(fileName)) { + if (state.traceEnabled) { + trace(state.host, Diagnostics.File_0_exist_use_it_as_a_module_resolution_result, fileName); + } return fileName; } else { + if (state.traceEnabled) { + trace(state.host, Diagnostics.File_0_does_not_exist, fileName); + } failedLookupLocation.push(fileName); return undefined; } } } - function loadNodeModuleFromDirectory(extensions: string[], candidate: string, failedLookupLocation: string[], onlyRecordFailures: boolean, host: ModuleResolutionHost): string { + function loadNodeModuleFromDirectory(extensions: string[], candidate: string, failedLookupLocation: string[], onlyRecordFailures: boolean, state: ModuleResolutionState): string { const packageJsonPath = combinePaths(candidate, "package.json"); - const directoryExists = !onlyRecordFailures && directoryProbablyExists(candidate, host); - if (directoryExists && host.fileExists(packageJsonPath)) { + const directoryExists = !onlyRecordFailures && directoryProbablyExists(candidate, state.host); + if (directoryExists && state.host.fileExists(packageJsonPath)) { + if (state.traceEnabled) { + trace(state.host, Diagnostics.Found_package_json_at_0, packageJsonPath); + } let jsonContent: { typings?: string }; try { - const jsonText = host.readFile(packageJsonPath); + const jsonText = state.host.readFile(packageJsonPath); jsonContent = jsonText ? <{ typings?: string }>JSON.parse(jsonText) : { typings: undefined }; } catch (e) { @@ -110,40 +454,54 @@ namespace ts { jsonContent = { typings: undefined }; } - if (typeof jsonContent.typings === "string") { - const path = normalizePath(combinePaths(candidate, jsonContent.typings)); - const result = loadNodeModuleFromFile(extensions, path, failedLookupLocation, !directoryProbablyExists(getDirectoryPath(path), host), host); - if (result) { - return result; + if (jsonContent.typings) { + if (typeof jsonContent.typings === "string") { + const typingsFile = normalizePath(combinePaths(candidate, jsonContent.typings)); + if (state.traceEnabled) { + trace(state.host, Diagnostics.package_json_has_typings_field_0_that_references_1, jsonContent.typings, typingsFile); + } + const result = loadModuleFromFile(typingsFile, extensions, failedLookupLocation, !directoryProbablyExists(getDirectoryPath(typingsFile), state.host), state); + if (result) { + return result; + } + } + else if (state.traceEnabled) { + trace(state.host, Diagnostics.Expected_type_of_typings_field_in_package_json_to_be_string_got_0, typeof jsonContent.typings); + } + } + else { + if (state.traceEnabled) { + trace(state.host, Diagnostics.package_json_does_not_have_typings_field); } } } else { + if (state.traceEnabled) { + trace(state.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 failedLookupLocation.push(packageJsonPath); } - return loadNodeModuleFromFile(extensions, combinePaths(candidate, "index"), failedLookupLocation, !directoryExists, host); + return loadModuleFromFile(combinePaths(candidate, "index"), extensions, failedLookupLocation, !directoryExists, state); } - function loadModuleFromNodeModules(moduleName: string, directory: string, host: ModuleResolutionHost): ResolvedModuleWithFailedLookupLocations { - const failedLookupLocations: string[] = []; + function loadModuleFromNodeModules(moduleName: string, directory: string, failedLookupLocations: string[], state: ModuleResolutionState): string { directory = normalizeSlashes(directory); while (true) { const baseName = getBaseFileName(directory); if (baseName !== "node_modules") { const nodeModulesFolder = combinePaths(directory, "node_modules"); - const nodeModulesFolderExists = directoryProbablyExists(nodeModulesFolder, host); + const nodeModulesFolderExists = directoryProbablyExists(nodeModulesFolder, state.host); const candidate = normalizePath(combinePaths(nodeModulesFolder, moduleName)); // Load only typescript files irrespective of allowJs option if loading from node modules - let result = loadNodeModuleFromFile(supportedTypeScriptExtensions, candidate, failedLookupLocations, !nodeModulesFolderExists, host); + let result = loadModuleFromFile(candidate, supportedTypeScriptExtensions, failedLookupLocations, !nodeModulesFolderExists, state); if (result) { - return { resolvedModule: { resolvedFileName: result, isExternalLibraryImport: true }, failedLookupLocations }; + return result; } - - result = loadNodeModuleFromDirectory(supportedTypeScriptExtensions, candidate, failedLookupLocations, !nodeModulesFolderExists, host); + result = loadNodeModuleFromDirectory(supportedTypeScriptExtensions, candidate, failedLookupLocations, !nodeModulesFolderExists, state); if (result) { - return { resolvedModule: { resolvedFileName: result, isExternalLibraryImport: true }, failedLookupLocations }; + return result; } } @@ -154,56 +512,34 @@ namespace ts { directory = parentPath; } - - return { resolvedModule: undefined, failedLookupLocations }; - } - - function nameStartsWithDotSlashOrDotDotSlash(name: string) { - const i = name.lastIndexOf("./", 1); - return i === 0 || (i === 1 && name.charCodeAt(0) === CharacterCodes.dot); + return undefined; } export function classicNameResolver(moduleName: string, containingFile: string, compilerOptions: CompilerOptions, host: ModuleResolutionHost): ResolvedModuleWithFailedLookupLocations { + const traceEnabled = isTraceEnabled(compilerOptions, host); + const state = { compilerOptions, host, traceEnabled }; + const failedLookupLocations: string[] = []; + const supportedExtensions = getSupportedExtensions(compilerOptions); + let containingDirectory = getDirectoryPath(containingFile); - // module names that contain '!' are used to reference resources and are not resolved to actual files on disk - if (moduleName.indexOf("!") != -1) { - return { resolvedModule: undefined, failedLookupLocations: [] }; + const resolvedFileName = tryLoadModuleUsingOptionalResolutionSettings(moduleName, containingDirectory, loadModuleFromFile, failedLookupLocations, supportedExtensions, state); + if (resolvedFileName) { + return createResolvedModule(resolvedFileName, /*isExternalLibraryImport*/false, failedLookupLocations); } - let searchPath = getDirectoryPath(containingFile); - let searchName: string; - - const failedLookupLocations: string[] = []; - let referencedSourceFile: string; - const supportedExtensions = getSupportedExtensions(compilerOptions); while (true) { - searchName = normalizePath(combinePaths(searchPath, moduleName)); - referencedSourceFile = forEach(supportedExtensions, extension => { - if (extension === ".tsx" && !compilerOptions.jsx) { - // resolve .tsx files only if jsx support is enabled - // 'logical not' handles both undefined and None cases - return undefined; - } - - const candidate = searchName + extension; - if (host.fileExists(candidate)) { - return candidate; - } - else { - failedLookupLocations.push(candidate); - } - }); - + const searchName = normalizePath(combinePaths(containingDirectory, moduleName)); + const directoryName = getDirectoryPath(searchName); + referencedSourceFile = loadModuleFromFile(searchName, supportedExtensions, failedLookupLocations, !directoryProbablyExists(directoryName, host), state); if (referencedSourceFile) { break; } - - const parentPath = getDirectoryPath(searchPath); - if (parentPath === searchPath) { + const parentPath = getDirectoryPath(containingDirectory); + if (parentPath === containingDirectory) { break; } - searchPath = parentPath; + containingDirectory = parentPath; } return referencedSourceFile @@ -295,6 +631,7 @@ namespace ts { getNewLine: () => newLine, fileExists: fileName => sys.fileExists(fileName), readFile: fileName => sys.readFile(fileName), + trace: (s: string) => sys.write(s + newLine), directoryExists: directoryName => sys.directoryExists(directoryName) }; } @@ -1259,6 +1596,26 @@ namespace ts { } } + if (options.paths && options.baseUrl === undefined) { + programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_paths_cannot_be_used_without_specifying_baseUrl_option)); + } + + if (options.paths) { + for (const key in options.paths) { + if (!hasProperty(options.paths, key)) { + continue; + } + if (!hasZeroOrOneAsteriskCharacter(key)) { + programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Pattern_0_can_have_at_most_one_Asterisk_character, key)); + } + for (const subst of options.paths[key]) { + if (!hasZeroOrOneAsteriskCharacter(subst)) { + programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Substitution_0_in_pattern_1_in_can_have_at_most_one_Asterisk_character, subst, key)); + } + } + } + } + if (options.inlineSources) { if (!options.sourceMap && !options.inlineSourceMap) { programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_inlineSources_can_only_be_used_when_either_option_inlineSourceMap_or_option_sourceMap_is_provided)); diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index 9b2457d091692..889810bebec54 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -376,7 +376,7 @@ namespace ts { sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped); return; } - const configParseResult = parseJsonConfigFileContent(configObject, sys, getDirectoryPath(configFileName), commandLine.options); + const configParseResult = parseJsonConfigFileContent(configObject, sys, getNormalizedAbsolutePath(getDirectoryPath(configFileName), sys.getCurrentDirectory()), commandLine.options); if (configParseResult.errors.length > 0) { reportDiagnostics(configParseResult.errors, /* compilerHost */ undefined); sys.exit(ExitStatus.DiagnosticsPresent_OutputsSkipped); @@ -740,7 +740,9 @@ namespace ts { for (const name in options) { if (hasProperty(options, name)) { - const value = options[name]; + // tsconfig only options cannot be specified via command line, + // so we can assume that only types that can appear here string | number | boolean + const value = options[name]; switch (name) { case "init": case "watch": diff --git a/src/compiler/types.ts b/src/compiler/types.ts index ca94060d86900..cc94cbd9ce216 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2374,11 +2374,15 @@ namespace ts { Message, } - export const enum ModuleResolutionKind { + export enum ModuleResolutionKind { Classic = 1, - NodeJs = 2 + NodeJs = 2 } + export type RootPaths = string[]; + export type PathSubstitutions = Map; + export type TsConfigOnlyOptions = RootPaths | PathSubstitutions; + export interface CompilerOptions { allowNonTsExtensions?: boolean; charset?: string; @@ -2427,6 +2431,10 @@ namespace ts { noImplicitReturns?: boolean; noFallthroughCasesInSwitch?: boolean; forceConsistentCasingInFileNames?: boolean; + baseUrl?: string; + paths?: PathSubstitutions; + rootDirs?: RootPaths; + traceModuleResolution?: boolean; allowSyntheticDefaultImports?: boolean; allowJs?: boolean; /* @internal */ stripInternal?: boolean; @@ -2434,10 +2442,10 @@ namespace ts { // Skip checking lib.d.ts to help speed up tests. /* @internal */ skipDefaultLibCheck?: boolean; - [option: string]: string | number | boolean; + [option: string]: string | number | boolean | TsConfigOnlyOptions; } - export const enum ModuleKind { + export enum ModuleKind { None = 0, CommonJS = 1, AMD = 2, @@ -2494,12 +2502,13 @@ namespace ts { /* @internal */ export interface CommandLineOptionBase { name: string; - type: "string" | "number" | "boolean" | Map; // a value of a primitive type, or an object literal mapping named values to actual values + type: "string" | "number" | "boolean" | "object" | Map; // a value of a primitive type, or an object literal mapping named values to actual values isFilePath?: boolean; // True if option value is a path or fileName shortName?: string; // A short mnemonic for convenience - for instance, 'h' can be used in place of 'help' description?: DiagnosticMessage; // The message describing what the command line switch does paramType?: DiagnosticMessage; // The name to be used for a non-boolean option's parameter experimental?: boolean; + isTSConfigOnly?: boolean; // True if option can only be specified via tsconfig.json file } /* @internal */ @@ -2514,7 +2523,12 @@ namespace ts { } /* @internal */ - export type CommandLineOption = CommandLineOptionOfCustomType | CommandLineOptionOfPrimitiveType; + export interface TsConfigOnlyOption extends CommandLineOptionBase { + type: "object"; + } + + /* @internal */ + export type CommandLineOption = CommandLineOptionOfCustomType | CommandLineOptionOfPrimitiveType | TsConfigOnlyOption; /* @internal */ export const enum CharacterCodes { @@ -2658,7 +2672,7 @@ namespace ts { // readFile function is used to read arbitrary text files on disk, i.e. when resolution procedure needs the content of 'package.json' // to determine location of bundled typings for node module readFile(fileName: string): string; - + trace?(s: string): void; directoryExists?(directoryName: string): boolean; } diff --git a/src/harness/compilerRunner.ts b/src/harness/compilerRunner.ts index d1566c05d4e3c..8b19955941225 100644 --- a/src/harness/compilerRunner.ts +++ b/src/harness/compilerRunner.ts @@ -49,7 +49,6 @@ class CompilerBaselineRunner extends RunnerBase { // Mocha holds onto the closure environment of the describe callback even after the test is done. // Everything declared here should be cleared out in the "after" callback. let justName: string; - let lastUnit: Harness.TestCaseParser.TestUnitData; let harnessSettings: Harness.TestCaseParser.CompilerSettings; let hasNonDtsFiles: boolean; @@ -64,17 +63,31 @@ class CompilerBaselineRunner extends RunnerBase { before(() => { justName = fileName.replace(/^.*[\\\/]/, ""); // strips the fileName from the path. const content = Harness.IO.readFile(fileName); - const testCaseContent = Harness.TestCaseParser.makeUnitsFromTest(content, fileName); + const rootDir = fileName.indexOf("conformance") === -1 ? "tests/cases/compiler/" : ts.getDirectoryPath(fileName) + "/"; + const testCaseContent = Harness.TestCaseParser.makeUnitsFromTest(content, fileName, rootDir); const units = testCaseContent.testUnitData; harnessSettings = testCaseContent.settings; + let tsConfigOptions: ts.CompilerOptions; + if (testCaseContent.tsConfig) { + assert.equal(testCaseContent.tsConfig.fileNames.length, 0, `list of files in tsconfig is not currently supported`); + + tsConfigOptions = ts.clone(testCaseContent.tsConfig.options); + } + else { + const baseUrl = harnessSettings["baseUrl"]; + if (baseUrl !== undefined && !ts.isRootedDiskPath(baseUrl)) { + harnessSettings["baseUrl"] = ts.getNormalizedAbsolutePath(baseUrl, rootDir); + } + } + lastUnit = units[units.length - 1]; hasNonDtsFiles = ts.forEach(units, unit => !ts.fileExtensionIs(unit.name, ".d.ts")); - const rootDir = lastUnit.originalFilePath.indexOf("conformance") === -1 ? "tests/cases/compiler/" : lastUnit.originalFilePath.substring(0, lastUnit.originalFilePath.lastIndexOf("/")) + "/"; // We need to assemble the list of input files for the compiler and other related files on the 'filesystem' (ie in a multi-file test) // If the last file in a test uses require or a triple slash reference we'll assume all other files will be brought in via references, // otherwise, assume all files are just meant to be in the same compilation session without explicit references to one another. toBeCompiled = []; otherFiles = []; + if (/require\(/.test(lastUnit.content) || /reference\spath/.test(lastUnit.content)) { toBeCompiled.push({ unitName: this.makeUnitName(lastUnit.name, rootDir), content: lastUnit.content }); units.forEach(unit => { @@ -90,7 +103,7 @@ class CompilerBaselineRunner extends RunnerBase { } const output = Harness.Compiler.compileFiles( - toBeCompiled, otherFiles, harnessSettings, /* options */ undefined, /* currentDirectory */ undefined); + toBeCompiled, otherFiles, harnessSettings, /*options*/ tsConfigOptions, /*currentDirectory*/ undefined); options = output.options; result = output.result; @@ -126,6 +139,14 @@ class CompilerBaselineRunner extends RunnerBase { } }); + it (`Correct module resolution tracing for ${fileName}`, () => { + if (options.traceModuleResolution) { + Harness.Baseline.runBaseline("Correct sourcemap content for " + fileName, justName.replace(/\.tsx?$/, ".trace.json"), () => { + return JSON.stringify(result.traceResults || [], undefined, 4); + }); + } + }); + // Source maps? it("Correct sourcemap content for " + fileName, () => { if (options.sourceMap || options.inlineSourceMap) { diff --git a/src/harness/harness.ts b/src/harness/harness.ts index 7fd819731721a..2b0c95c0a61b0 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -985,6 +985,9 @@ namespace Harness { if (harnessSettings) { setCompilerOptionsFromHarnessSetting(harnessSettings, options); } + if (options.rootDirs) { + options.rootDirs = ts.map(options.rootDirs, d => ts.getNormalizedAbsolutePath(d, currentDirectory)); + } const useCaseSensitiveFileNames = options.useCaseSensitiveFileNames !== undefined ? options.useCaseSensitiveFileNames : Harness.IO.useCaseSensitiveFileNames(); const programFiles: TestFile[] = inputFiles.slice(); @@ -1019,13 +1022,19 @@ namespace Harness { useCaseSensitiveFileNames, currentDirectory, options.newLine); + + let traceResults: string[]; + if (options.traceModuleResolution) { + traceResults = []; + compilerHost.trace = text => traceResults.push(text); + } const program = ts.createProgram(programFileNames, options, compilerHost); const emitResult = program.emit(); const errors = ts.getPreEmitDiagnostics(program); - const result = new CompilerResult(fileOutputs, errors, program, Harness.IO.getCurrentDirectory(), emitResult.sourceMaps); + const result = new CompilerResult(fileOutputs, errors, program, Harness.IO.getCurrentDirectory(), emitResult.sourceMaps, traceResults); return { result, options }; } @@ -1306,7 +1315,7 @@ namespace Harness { /** @param fileResults an array of strings for the fileName and an ITextWriter with its code */ constructor(fileResults: GeneratedFile[], errors: ts.Diagnostic[], public program: ts.Program, - public currentDirectoryForProgram: string, private sourceMapData: ts.SourceMapData[]) { + public currentDirectoryForProgram: string, private sourceMapData: ts.SourceMapData[], public traceResults: string[]) { for (const emittedFile of fileResults) { if (isDTS(emittedFile.fileName)) { @@ -1366,7 +1375,7 @@ namespace Harness { } /** Given a test file containing // @FileName directives, return an array of named units of code to be added to an existing compiler instance */ - export function makeUnitsFromTest(code: string, fileName: string): { settings: CompilerSettings; testUnitData: TestUnitData[]; } { + export function makeUnitsFromTest(code: string, fileName: string, rootDir?: string): { settings: CompilerSettings; testUnitData: TestUnitData[]; tsConfig: ts.ParsedCommandLine } { const settings = extractCompilerSettings(code); // List of all the subfiles we've parsed out @@ -1444,7 +1453,31 @@ namespace Harness { }; testUnitData.push(newTestFile2); - return { settings, testUnitData }; + // unit tests always list files explicitly + const parseConfigHost: ts.ParseConfigHost = { + readDirectory: (name) => [] + }; + + // check if project has tsconfig.json in the list of files + let tsConfig: ts.ParsedCommandLine; + for (let i = 0; i < testUnitData.length; i++) { + const data = testUnitData[i]; + if (ts.getBaseFileName(data.name).toLowerCase() === "tsconfig.json") { + const configJson = ts.parseConfigFileTextToJson(data.name, data.content); + assert.isTrue(configJson.config !== undefined); + let baseDir = ts.normalizePath(ts.getDirectoryPath(data.name)); + if (rootDir) { + baseDir = ts.getNormalizedAbsolutePath(baseDir, rootDir); + } + tsConfig = ts.parseJsonConfigFileContent(configJson.config, parseConfigHost, baseDir); + + // delete entry from the list + testUnitData.splice(i, 1); + + break; + } + } + return { settings, testUnitData, tsConfig }; } } diff --git a/src/harness/harnessLanguageService.ts b/src/harness/harnessLanguageService.ts index a0cac43972952..6ab9cd896c122 100644 --- a/src/harness/harnessLanguageService.ts +++ b/src/harness/harnessLanguageService.ts @@ -547,7 +547,8 @@ namespace Harness.LanguageService { } directoryExists(path: string): boolean { - return false; + // for tests assume that directory exists + return true; } getExecutingFilePath(): string { diff --git a/src/services/services.ts b/src/services/services.ts index 28f7f8488355e..cb57d415c66a4 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -2777,6 +2777,9 @@ namespace ts { return directoryProbablyExists(directoryName, host); } }; + if (host.trace) { + compilerHost.trace = message => host.trace(message); + } if (host.resolveModuleNames) { compilerHost.resolveModuleNames = (moduleNames, containingFile) => host.resolveModuleNames(moduleNames, containingFile); diff --git a/src/services/shims.ts b/src/services/shims.ts index 9ca3f19244d89..a9b6f4c3cb2c6 100644 --- a/src/services/shims.ts +++ b/src/services/shims.ts @@ -78,6 +78,8 @@ namespace ts { * when enumerating the directory. */ readDirectory(rootDir: string, extension: string, exclude?: string): string; + + trace(s: string): void; } /// diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution1_classic.errors.txt b/tests/baselines/reference/pathMappingBasedModuleResolution1_classic.errors.txt new file mode 100644 index 0000000000000..85e25ec99fb93 --- /dev/null +++ b/tests/baselines/reference/pathMappingBasedModuleResolution1_classic.errors.txt @@ -0,0 +1,7 @@ +error TS5060: Option 'paths' cannot be used without specifying '--baseUrl' option. + + +!!! error TS5060: Option 'paths' cannot be used without specifying '--baseUrl' option. +==== c:/root/f1.ts (0 errors) ==== + export var x = 1; + \ No newline at end of file diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution1_classic.js b/tests/baselines/reference/pathMappingBasedModuleResolution1_classic.js new file mode 100644 index 0000000000000..1a1bd387dce94 --- /dev/null +++ b/tests/baselines/reference/pathMappingBasedModuleResolution1_classic.js @@ -0,0 +1,9 @@ +//// [f1.ts] +export var x = 1; + + +//// [f1.js] +define(["require", "exports"], function (require, exports) { + "use strict"; + exports.x = 1; +}); diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution1_classic.trace.json b/tests/baselines/reference/pathMappingBasedModuleResolution1_classic.trace.json new file mode 100644 index 0000000000000..0637a088a01e8 --- /dev/null +++ b/tests/baselines/reference/pathMappingBasedModuleResolution1_classic.trace.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution1_node.errors.txt b/tests/baselines/reference/pathMappingBasedModuleResolution1_node.errors.txt new file mode 100644 index 0000000000000..85e25ec99fb93 --- /dev/null +++ b/tests/baselines/reference/pathMappingBasedModuleResolution1_node.errors.txt @@ -0,0 +1,7 @@ +error TS5060: Option 'paths' cannot be used without specifying '--baseUrl' option. + + +!!! error TS5060: Option 'paths' cannot be used without specifying '--baseUrl' option. +==== c:/root/f1.ts (0 errors) ==== + export var x = 1; + \ No newline at end of file diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution1_node.js b/tests/baselines/reference/pathMappingBasedModuleResolution1_node.js new file mode 100644 index 0000000000000..5fcaa23b976df --- /dev/null +++ b/tests/baselines/reference/pathMappingBasedModuleResolution1_node.js @@ -0,0 +1,7 @@ +//// [f1.ts] +export var x = 1; + + +//// [f1.js] +"use strict"; +exports.x = 1; diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution1_node.trace.json b/tests/baselines/reference/pathMappingBasedModuleResolution1_node.trace.json new file mode 100644 index 0000000000000..0637a088a01e8 --- /dev/null +++ b/tests/baselines/reference/pathMappingBasedModuleResolution1_node.trace.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution2_classic.errors.txt b/tests/baselines/reference/pathMappingBasedModuleResolution2_classic.errors.txt new file mode 100644 index 0000000000000..ad954bd142b54 --- /dev/null +++ b/tests/baselines/reference/pathMappingBasedModuleResolution2_classic.errors.txt @@ -0,0 +1,8 @@ +error TS5061: Pattern '*1*' can have at most one '*' character +error TS5062: Substitution '*2*' in pattern '*1*' in can have at most one '*' character + + +!!! error TS5061: Pattern '*1*' can have at most one '*' character +!!! error TS5062: Substitution '*2*' in pattern '*1*' in can have at most one '*' character +==== tests/cases/compiler/root/src/folder1/file1.ts (0 errors) ==== + export var x = 1; \ No newline at end of file diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution2_classic.js b/tests/baselines/reference/pathMappingBasedModuleResolution2_classic.js new file mode 100644 index 0000000000000..52dab845bb296 --- /dev/null +++ b/tests/baselines/reference/pathMappingBasedModuleResolution2_classic.js @@ -0,0 +1,8 @@ +//// [file1.ts] +export var x = 1; + +//// [file1.js] +define(["require", "exports"], function (require, exports) { + "use strict"; + exports.x = 1; +}); diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution2_classic.trace.json b/tests/baselines/reference/pathMappingBasedModuleResolution2_classic.trace.json new file mode 100644 index 0000000000000..0637a088a01e8 --- /dev/null +++ b/tests/baselines/reference/pathMappingBasedModuleResolution2_classic.trace.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution2_node.errors.txt b/tests/baselines/reference/pathMappingBasedModuleResolution2_node.errors.txt new file mode 100644 index 0000000000000..ad954bd142b54 --- /dev/null +++ b/tests/baselines/reference/pathMappingBasedModuleResolution2_node.errors.txt @@ -0,0 +1,8 @@ +error TS5061: Pattern '*1*' can have at most one '*' character +error TS5062: Substitution '*2*' in pattern '*1*' in can have at most one '*' character + + +!!! error TS5061: Pattern '*1*' can have at most one '*' character +!!! error TS5062: Substitution '*2*' in pattern '*1*' in can have at most one '*' character +==== tests/cases/compiler/root/src/folder1/file1.ts (0 errors) ==== + export var x = 1; \ No newline at end of file diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution2_node.js b/tests/baselines/reference/pathMappingBasedModuleResolution2_node.js new file mode 100644 index 0000000000000..8c8b5c9a926fe --- /dev/null +++ b/tests/baselines/reference/pathMappingBasedModuleResolution2_node.js @@ -0,0 +1,6 @@ +//// [file1.ts] +export var x = 1; + +//// [file1.js] +"use strict"; +exports.x = 1; diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution2_node.trace.json b/tests/baselines/reference/pathMappingBasedModuleResolution2_node.trace.json new file mode 100644 index 0000000000000..0637a088a01e8 --- /dev/null +++ b/tests/baselines/reference/pathMappingBasedModuleResolution2_node.trace.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution3_classic.js b/tests/baselines/reference/pathMappingBasedModuleResolution3_classic.js new file mode 100644 index 0000000000000..15867b085eae9 --- /dev/null +++ b/tests/baselines/reference/pathMappingBasedModuleResolution3_classic.js @@ -0,0 +1,42 @@ +//// [tests/cases/compiler/pathMappingBasedModuleResolution3_classic.ts] //// + +//// [file1.ts] + +// baseUrl set via command line + +import {x} from "folder2/file2" +declare function use(a: any): void; +use(x.toExponential()); + +//// [file2.ts] +import {x as a} from "./file3" // found with baseurl +import {y as b} from "file4" // found with fallback +export var x = a + b; + +//// [file3.ts] +export var x = 1; + +//// [file4.ts] +export var y = 100; + +//// [file3.js] +define(["require", "exports"], function (require, exports) { + "use strict"; + exports.x = 1; +}); +//// [file4.js] +define(["require", "exports"], function (require, exports) { + "use strict"; + exports.y = 100; +}); +//// [file2.js] +define(["require", "exports", "./file3", "file4"], function (require, exports, file3_1, file4_1) { + "use strict"; + exports.x = file3_1.x + file4_1.y; +}); +//// [file1.js] +// baseUrl set via command line +define(["require", "exports", "folder2/file2"], function (require, exports, file2_1) { + "use strict"; + use(file2_1.x.toExponential()); +}); diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution3_classic.symbols b/tests/baselines/reference/pathMappingBasedModuleResolution3_classic.symbols new file mode 100644 index 0000000000000..97ec40d4cb4d4 --- /dev/null +++ b/tests/baselines/reference/pathMappingBasedModuleResolution3_classic.symbols @@ -0,0 +1,39 @@ +=== c:/root/folder1/file1.ts === + +// baseUrl set via command line + +import {x} from "folder2/file2" +>x : Symbol(x, Decl(file1.ts, 3, 8)) + +declare function use(a: any): void; +>use : Symbol(use, Decl(file1.ts, 3, 31)) +>a : Symbol(a, Decl(file1.ts, 4, 21)) + +use(x.toExponential()); +>use : Symbol(use, Decl(file1.ts, 3, 31)) +>x.toExponential : Symbol(Number.toExponential, Decl(lib.d.ts, --, --)) +>x : Symbol(x, Decl(file1.ts, 3, 8)) +>toExponential : Symbol(Number.toExponential, Decl(lib.d.ts, --, --)) + +=== c:/root/folder2/file2.ts === +import {x as a} from "./file3" // found with baseurl +>x : Symbol(a, Decl(file2.ts, 0, 8)) +>a : Symbol(a, Decl(file2.ts, 0, 8)) + +import {y as b} from "file4" // found with fallback +>y : Symbol(b, Decl(file2.ts, 1, 8)) +>b : Symbol(b, Decl(file2.ts, 1, 8)) + +export var x = a + b; +>x : Symbol(x, Decl(file2.ts, 2, 10)) +>a : Symbol(a, Decl(file2.ts, 0, 8)) +>b : Symbol(b, Decl(file2.ts, 1, 8)) + +=== c:/root/folder2/file3.ts === +export var x = 1; +>x : Symbol(x, Decl(file3.ts, 0, 10)) + +=== c:/file4.ts === +export var y = 100; +>y : Symbol(y, Decl(file4.ts, 0, 10)) + diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution3_classic.trace.json b/tests/baselines/reference/pathMappingBasedModuleResolution3_classic.trace.json new file mode 100644 index 0000000000000..ac82f87bceeb0 --- /dev/null +++ b/tests/baselines/reference/pathMappingBasedModuleResolution3_classic.trace.json @@ -0,0 +1,27 @@ +[ + "======== Resolving module 'folder2/file2' from 'c:/root/folder1/file1.ts'. ========", + "Explicitly specified module resolution kind: 'Classic'.", + "'baseUrl' option is set to 'c:/root', using this value to resolve non-relative module name 'folder2/file2'", + "Resolving module name 'folder2/file2' relative to base url 'c:/root' - 'c:/root/folder2/file2'.", + "File 'c:/root/folder2/file2.ts' exist - use it as a module resolution result.", + "======== Module name 'folder2/file2' was successfully resolved to 'c:/root/folder2/file2.ts'. ========", + "======== Resolving module './file3' from 'c:/root/folder2/file2.ts'. ========", + "Explicitly specified module resolution kind: 'Classic'.", + "File 'c:/root/folder2/file3.ts' exist - use it as a module resolution result.", + "======== Module name './file3' was successfully resolved to 'c:/root/folder2/file3.ts'. ========", + "======== Resolving module 'file4' from 'c:/root/folder2/file2.ts'. ========", + "Explicitly specified module resolution kind: 'Classic'.", + "'baseUrl' option is set to 'c:/root', using this value to resolve non-relative module name 'file4'", + "Resolving module name 'file4' relative to base url 'c:/root' - 'c:/root/file4'.", + "File 'c:/root/file4.ts' does not exist.", + "File 'c:/root/file4.tsx' does not exist.", + "File 'c:/root/file4.d.ts' does not exist.", + "File 'c:/root/folder2/file4.ts' does not exist.", + "File 'c:/root/folder2/file4.tsx' does not exist.", + "File 'c:/root/folder2/file4.d.ts' does not exist.", + "File 'c:/root/file4.ts' does not exist.", + "File 'c:/root/file4.tsx' does not exist.", + "File 'c:/root/file4.d.ts' does not exist.", + "File 'c:/file4.ts' exist - use it as a module resolution result.", + "======== Module name 'file4' was successfully resolved to 'c:/file4.ts'. ========" +] \ No newline at end of file diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution3_classic.types b/tests/baselines/reference/pathMappingBasedModuleResolution3_classic.types new file mode 100644 index 0000000000000..359811ff3b20d --- /dev/null +++ b/tests/baselines/reference/pathMappingBasedModuleResolution3_classic.types @@ -0,0 +1,44 @@ +=== c:/root/folder1/file1.ts === + +// baseUrl set via command line + +import {x} from "folder2/file2" +>x : number + +declare function use(a: any): void; +>use : (a: any) => void +>a : any + +use(x.toExponential()); +>use(x.toExponential()) : void +>use : (a: any) => void +>x.toExponential() : string +>x.toExponential : (fractionDigits?: number) => string +>x : number +>toExponential : (fractionDigits?: number) => string + +=== c:/root/folder2/file2.ts === +import {x as a} from "./file3" // found with baseurl +>x : number +>a : number + +import {y as b} from "file4" // found with fallback +>y : number +>b : number + +export var x = a + b; +>x : number +>a + b : number +>a : number +>b : number + +=== c:/root/folder2/file3.ts === +export var x = 1; +>x : number +>1 : number + +=== c:/file4.ts === +export var y = 100; +>y : number +>100 : number + diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution3_node.js b/tests/baselines/reference/pathMappingBasedModuleResolution3_node.js new file mode 100644 index 0000000000000..cbff608753010 --- /dev/null +++ b/tests/baselines/reference/pathMappingBasedModuleResolution3_node.js @@ -0,0 +1,34 @@ +//// [tests/cases/compiler/pathMappingBasedModuleResolution3_node.ts] //// + +//// [file1.ts] + +// baseUrl set via command line + +import {x} from "folder2/file2" +declare function use(a: any): void; +use(x.toExponential()); + +//// [file2.ts] +import {x as a} from "./file3" // found with baseurl +import {y as b} from "file4" // found with fallback +export var x = a + b; + +//// [file3.ts] +export var x = 1; + +//// [index.d.ts] +export var y: number; + +//// [file3.js] +"use strict"; +exports.x = 1; +//// [file2.js] +"use strict"; +var file3_1 = require("./file3"); // found with baseurl +var file4_1 = require("file4"); // found with fallback +exports.x = file3_1.x + file4_1.y; +//// [file1.js] +// baseUrl set via command line +"use strict"; +var file2_1 = require("folder2/file2"); +use(file2_1.x.toExponential()); diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution3_node.symbols b/tests/baselines/reference/pathMappingBasedModuleResolution3_node.symbols new file mode 100644 index 0000000000000..487dea2fb8983 --- /dev/null +++ b/tests/baselines/reference/pathMappingBasedModuleResolution3_node.symbols @@ -0,0 +1,39 @@ +=== c:/root/folder1/file1.ts === + +// baseUrl set via command line + +import {x} from "folder2/file2" +>x : Symbol(x, Decl(file1.ts, 3, 8)) + +declare function use(a: any): void; +>use : Symbol(use, Decl(file1.ts, 3, 31)) +>a : Symbol(a, Decl(file1.ts, 4, 21)) + +use(x.toExponential()); +>use : Symbol(use, Decl(file1.ts, 3, 31)) +>x.toExponential : Symbol(Number.toExponential, Decl(lib.d.ts, --, --)) +>x : Symbol(x, Decl(file1.ts, 3, 8)) +>toExponential : Symbol(Number.toExponential, Decl(lib.d.ts, --, --)) + +=== c:/root/folder2/file2.ts === +import {x as a} from "./file3" // found with baseurl +>x : Symbol(a, Decl(file2.ts, 0, 8)) +>a : Symbol(a, Decl(file2.ts, 0, 8)) + +import {y as b} from "file4" // found with fallback +>y : Symbol(b, Decl(file2.ts, 1, 8)) +>b : Symbol(b, Decl(file2.ts, 1, 8)) + +export var x = a + b; +>x : Symbol(x, Decl(file2.ts, 2, 10)) +>a : Symbol(a, Decl(file2.ts, 0, 8)) +>b : Symbol(b, Decl(file2.ts, 1, 8)) + +=== c:/root/folder2/file3.ts === +export var x = 1; +>x : Symbol(x, Decl(file3.ts, 0, 10)) + +=== c:/node_modules/file4/index.d.ts === +export var y: number; +>y : Symbol(y, Decl(index.d.ts, 0, 10)) + diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution3_node.trace.json b/tests/baselines/reference/pathMappingBasedModuleResolution3_node.trace.json new file mode 100644 index 0000000000000..6d0de807bc03c --- /dev/null +++ b/tests/baselines/reference/pathMappingBasedModuleResolution3_node.trace.json @@ -0,0 +1,49 @@ +[ + "======== Resolving module 'folder2/file2' from 'c:/root/folder1/file1.ts'. ========", + "Explicitly specified module resolution kind: 'NodeJs'.", + "'baseUrl' option is set to 'c:/root', using this value to resolve non-relative module name 'folder2/file2'", + "Resolving module name 'folder2/file2' relative to base url 'c:/root' - 'c:/root/folder2/file2'.", + "Loading module as file / folder, candidate module location 'c:/root/folder2/file2'.", + "File 'c:/root/folder2/file2.ts' exist - use it as a module resolution result.", + "======== Module name 'folder2/file2' was successfully resolved to 'c:/root/folder2/file2.ts'. ========", + "======== Resolving module './file3' from 'c:/root/folder2/file2.ts'. ========", + "Explicitly specified module resolution kind: 'NodeJs'.", + "Loading module as file / folder, candidate module location 'c:/root/folder2/file3'.", + "File 'c:/root/folder2/file3.ts' exist - use it as a module resolution result.", + "======== Module name './file3' was successfully resolved to 'c:/root/folder2/file3.ts'. ========", + "======== Resolving module 'file4' from 'c:/root/folder2/file2.ts'. ========", + "Explicitly specified module resolution kind: 'NodeJs'.", + "'baseUrl' option is set to 'c:/root', using this value to resolve non-relative module name 'file4'", + "Resolving module name 'file4' relative to base url 'c:/root' - 'c:/root/file4'.", + "Loading module as file / folder, candidate module location 'c:/root/file4'.", + "File 'c:/root/file4.ts' does not exist.", + "File 'c:/root/file4.tsx' does not exist.", + "File 'c:/root/file4.d.ts' does not exist.", + "File 'c:/root/file4/package.json' does not exist.", + "File 'c:/root/file4/index.ts' does not exist.", + "File 'c:/root/file4/index.tsx' does not exist.", + "File 'c:/root/file4/index.d.ts' does not exist.", + "Loading module 'file4' from 'node_modules' folder.", + "File 'c:/root/folder2/node_modules/file4.ts' does not exist.", + "File 'c:/root/folder2/node_modules/file4.tsx' does not exist.", + "File 'c:/root/folder2/node_modules/file4.d.ts' does not exist.", + "File 'c:/root/folder2/node_modules/file4/package.json' does not exist.", + "File 'c:/root/folder2/node_modules/file4/index.ts' does not exist.", + "File 'c:/root/folder2/node_modules/file4/index.tsx' does not exist.", + "File 'c:/root/folder2/node_modules/file4/index.d.ts' does not exist.", + "File 'c:/root/node_modules/file4.ts' does not exist.", + "File 'c:/root/node_modules/file4.tsx' does not exist.", + "File 'c:/root/node_modules/file4.d.ts' does not exist.", + "File 'c:/root/node_modules/file4/package.json' does not exist.", + "File 'c:/root/node_modules/file4/index.ts' does not exist.", + "File 'c:/root/node_modules/file4/index.tsx' does not exist.", + "File 'c:/root/node_modules/file4/index.d.ts' does not exist.", + "File 'c:/node_modules/file4.ts' does not exist.", + "File 'c:/node_modules/file4.tsx' does not exist.", + "File 'c:/node_modules/file4.d.ts' does not exist.", + "File 'c:/node_modules/file4/package.json' does not exist.", + "File 'c:/node_modules/file4/index.ts' does not exist.", + "File 'c:/node_modules/file4/index.tsx' does not exist.", + "File 'c:/node_modules/file4/index.d.ts' exist - use it as a module resolution result.", + "======== Module name 'file4' was successfully resolved to 'c:/node_modules/file4/index.d.ts'. ========" +] \ No newline at end of file diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution3_node.types b/tests/baselines/reference/pathMappingBasedModuleResolution3_node.types new file mode 100644 index 0000000000000..78597cf50eff6 --- /dev/null +++ b/tests/baselines/reference/pathMappingBasedModuleResolution3_node.types @@ -0,0 +1,43 @@ +=== c:/root/folder1/file1.ts === + +// baseUrl set via command line + +import {x} from "folder2/file2" +>x : number + +declare function use(a: any): void; +>use : (a: any) => void +>a : any + +use(x.toExponential()); +>use(x.toExponential()) : void +>use : (a: any) => void +>x.toExponential() : string +>x.toExponential : (fractionDigits?: number) => string +>x : number +>toExponential : (fractionDigits?: number) => string + +=== c:/root/folder2/file2.ts === +import {x as a} from "./file3" // found with baseurl +>x : number +>a : number + +import {y as b} from "file4" // found with fallback +>y : number +>b : number + +export var x = a + b; +>x : number +>a + b : number +>a : number +>b : number + +=== c:/root/folder2/file3.ts === +export var x = 1; +>x : number +>1 : number + +=== c:/node_modules/file4/index.d.ts === +export var y: number; +>y : number + diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution4_classic.js b/tests/baselines/reference/pathMappingBasedModuleResolution4_classic.js new file mode 100644 index 0000000000000..c1de8cea6c91a --- /dev/null +++ b/tests/baselines/reference/pathMappingBasedModuleResolution4_classic.js @@ -0,0 +1,38 @@ +//// [tests/cases/compiler/pathMappingBasedModuleResolution4_classic.ts] //// + +//// [file1.ts] +import {x} from "folder2/file2" +declare function use(a: any): void; +use(x.toExponential()); + +//// [file2.ts] +import {x as a} from "./file3" // found with baseurl +import {y as b} from "file4" // found with fallback +export var x = a + b; + +//// [file3.ts] +export var x = 1; + +//// [file4.ts] +export var y = 100; + +//// [file3.js] +define(["require", "exports"], function (require, exports) { + "use strict"; + exports.x = 1; +}); +//// [file4.js] +define(["require", "exports"], function (require, exports) { + "use strict"; + exports.y = 100; +}); +//// [file2.js] +define(["require", "exports", "./file3", "file4"], function (require, exports, file3_1, file4_1) { + "use strict"; + exports.x = file3_1.x + file4_1.y; +}); +//// [file1.js] +define(["require", "exports", "folder2/file2"], function (require, exports, file2_1) { + "use strict"; + use(file2_1.x.toExponential()); +}); diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution4_classic.symbols b/tests/baselines/reference/pathMappingBasedModuleResolution4_classic.symbols new file mode 100644 index 0000000000000..7c1943dae462b --- /dev/null +++ b/tests/baselines/reference/pathMappingBasedModuleResolution4_classic.symbols @@ -0,0 +1,36 @@ +=== c:/root/folder1/file1.ts === +import {x} from "folder2/file2" +>x : Symbol(x, Decl(file1.ts, 0, 8)) + +declare function use(a: any): void; +>use : Symbol(use, Decl(file1.ts, 0, 31)) +>a : Symbol(a, Decl(file1.ts, 1, 21)) + +use(x.toExponential()); +>use : Symbol(use, Decl(file1.ts, 0, 31)) +>x.toExponential : Symbol(Number.toExponential, Decl(lib.d.ts, --, --)) +>x : Symbol(x, Decl(file1.ts, 0, 8)) +>toExponential : Symbol(Number.toExponential, Decl(lib.d.ts, --, --)) + +=== c:/root/folder2/file2.ts === +import {x as a} from "./file3" // found with baseurl +>x : Symbol(a, Decl(file2.ts, 0, 8)) +>a : Symbol(a, Decl(file2.ts, 0, 8)) + +import {y as b} from "file4" // found with fallback +>y : Symbol(b, Decl(file2.ts, 1, 8)) +>b : Symbol(b, Decl(file2.ts, 1, 8)) + +export var x = a + b; +>x : Symbol(x, Decl(file2.ts, 2, 10)) +>a : Symbol(a, Decl(file2.ts, 0, 8)) +>b : Symbol(b, Decl(file2.ts, 1, 8)) + +=== c:/root/folder2/file3.ts === +export var x = 1; +>x : Symbol(x, Decl(file3.ts, 0, 10)) + +=== c:/file4.ts === +export var y = 100; +>y : Symbol(y, Decl(file4.ts, 0, 10)) + diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution4_classic.trace.json b/tests/baselines/reference/pathMappingBasedModuleResolution4_classic.trace.json new file mode 100644 index 0000000000000..ac82f87bceeb0 --- /dev/null +++ b/tests/baselines/reference/pathMappingBasedModuleResolution4_classic.trace.json @@ -0,0 +1,27 @@ +[ + "======== Resolving module 'folder2/file2' from 'c:/root/folder1/file1.ts'. ========", + "Explicitly specified module resolution kind: 'Classic'.", + "'baseUrl' option is set to 'c:/root', using this value to resolve non-relative module name 'folder2/file2'", + "Resolving module name 'folder2/file2' relative to base url 'c:/root' - 'c:/root/folder2/file2'.", + "File 'c:/root/folder2/file2.ts' exist - use it as a module resolution result.", + "======== Module name 'folder2/file2' was successfully resolved to 'c:/root/folder2/file2.ts'. ========", + "======== Resolving module './file3' from 'c:/root/folder2/file2.ts'. ========", + "Explicitly specified module resolution kind: 'Classic'.", + "File 'c:/root/folder2/file3.ts' exist - use it as a module resolution result.", + "======== Module name './file3' was successfully resolved to 'c:/root/folder2/file3.ts'. ========", + "======== Resolving module 'file4' from 'c:/root/folder2/file2.ts'. ========", + "Explicitly specified module resolution kind: 'Classic'.", + "'baseUrl' option is set to 'c:/root', using this value to resolve non-relative module name 'file4'", + "Resolving module name 'file4' relative to base url 'c:/root' - 'c:/root/file4'.", + "File 'c:/root/file4.ts' does not exist.", + "File 'c:/root/file4.tsx' does not exist.", + "File 'c:/root/file4.d.ts' does not exist.", + "File 'c:/root/folder2/file4.ts' does not exist.", + "File 'c:/root/folder2/file4.tsx' does not exist.", + "File 'c:/root/folder2/file4.d.ts' does not exist.", + "File 'c:/root/file4.ts' does not exist.", + "File 'c:/root/file4.tsx' does not exist.", + "File 'c:/root/file4.d.ts' does not exist.", + "File 'c:/file4.ts' exist - use it as a module resolution result.", + "======== Module name 'file4' was successfully resolved to 'c:/file4.ts'. ========" +] \ No newline at end of file diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution4_classic.types b/tests/baselines/reference/pathMappingBasedModuleResolution4_classic.types new file mode 100644 index 0000000000000..d225246e2f949 --- /dev/null +++ b/tests/baselines/reference/pathMappingBasedModuleResolution4_classic.types @@ -0,0 +1,41 @@ +=== c:/root/folder1/file1.ts === +import {x} from "folder2/file2" +>x : number + +declare function use(a: any): void; +>use : (a: any) => void +>a : any + +use(x.toExponential()); +>use(x.toExponential()) : void +>use : (a: any) => void +>x.toExponential() : string +>x.toExponential : (fractionDigits?: number) => string +>x : number +>toExponential : (fractionDigits?: number) => string + +=== c:/root/folder2/file2.ts === +import {x as a} from "./file3" // found with baseurl +>x : number +>a : number + +import {y as b} from "file4" // found with fallback +>y : number +>b : number + +export var x = a + b; +>x : number +>a + b : number +>a : number +>b : number + +=== c:/root/folder2/file3.ts === +export var x = 1; +>x : number +>1 : number + +=== c:/file4.ts === +export var y = 100; +>y : number +>100 : number + diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution4_node.js b/tests/baselines/reference/pathMappingBasedModuleResolution4_node.js new file mode 100644 index 0000000000000..c5a08d55d8bbe --- /dev/null +++ b/tests/baselines/reference/pathMappingBasedModuleResolution4_node.js @@ -0,0 +1,30 @@ +//// [tests/cases/compiler/pathMappingBasedModuleResolution4_node.ts] //// + +//// [file1.ts] +import {x} from "folder2/file2" +declare function use(a: any): void; +use(x.toExponential()); + +//// [file2.ts] +import {x as a} from "./file3" // found with baseurl +import {y as b} from "file4" // found with fallback +export var x = a + b; + +//// [file3.ts] +export var x = 1; + +//// [index.d.ts] +export var y: number; + +//// [file3.js] +"use strict"; +exports.x = 1; +//// [file2.js] +"use strict"; +var file3_1 = require("./file3"); // found with baseurl +var file4_1 = require("file4"); // found with fallback +exports.x = file3_1.x + file4_1.y; +//// [file1.js] +"use strict"; +var file2_1 = require("folder2/file2"); +use(file2_1.x.toExponential()); diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution4_node.symbols b/tests/baselines/reference/pathMappingBasedModuleResolution4_node.symbols new file mode 100644 index 0000000000000..fb1c5be9de6bc --- /dev/null +++ b/tests/baselines/reference/pathMappingBasedModuleResolution4_node.symbols @@ -0,0 +1,36 @@ +=== c:/root/folder1/file1.ts === +import {x} from "folder2/file2" +>x : Symbol(x, Decl(file1.ts, 0, 8)) + +declare function use(a: any): void; +>use : Symbol(use, Decl(file1.ts, 0, 31)) +>a : Symbol(a, Decl(file1.ts, 1, 21)) + +use(x.toExponential()); +>use : Symbol(use, Decl(file1.ts, 0, 31)) +>x.toExponential : Symbol(Number.toExponential, Decl(lib.d.ts, --, --)) +>x : Symbol(x, Decl(file1.ts, 0, 8)) +>toExponential : Symbol(Number.toExponential, Decl(lib.d.ts, --, --)) + +=== c:/root/folder2/file2.ts === +import {x as a} from "./file3" // found with baseurl +>x : Symbol(a, Decl(file2.ts, 0, 8)) +>a : Symbol(a, Decl(file2.ts, 0, 8)) + +import {y as b} from "file4" // found with fallback +>y : Symbol(b, Decl(file2.ts, 1, 8)) +>b : Symbol(b, Decl(file2.ts, 1, 8)) + +export var x = a + b; +>x : Symbol(x, Decl(file2.ts, 2, 10)) +>a : Symbol(a, Decl(file2.ts, 0, 8)) +>b : Symbol(b, Decl(file2.ts, 1, 8)) + +=== c:/root/folder2/file3.ts === +export var x = 1; +>x : Symbol(x, Decl(file3.ts, 0, 10)) + +=== c:/node_modules/file4/index.d.ts === +export var y: number; +>y : Symbol(y, Decl(index.d.ts, 0, 10)) + diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution4_node.trace.json b/tests/baselines/reference/pathMappingBasedModuleResolution4_node.trace.json new file mode 100644 index 0000000000000..6d0de807bc03c --- /dev/null +++ b/tests/baselines/reference/pathMappingBasedModuleResolution4_node.trace.json @@ -0,0 +1,49 @@ +[ + "======== Resolving module 'folder2/file2' from 'c:/root/folder1/file1.ts'. ========", + "Explicitly specified module resolution kind: 'NodeJs'.", + "'baseUrl' option is set to 'c:/root', using this value to resolve non-relative module name 'folder2/file2'", + "Resolving module name 'folder2/file2' relative to base url 'c:/root' - 'c:/root/folder2/file2'.", + "Loading module as file / folder, candidate module location 'c:/root/folder2/file2'.", + "File 'c:/root/folder2/file2.ts' exist - use it as a module resolution result.", + "======== Module name 'folder2/file2' was successfully resolved to 'c:/root/folder2/file2.ts'. ========", + "======== Resolving module './file3' from 'c:/root/folder2/file2.ts'. ========", + "Explicitly specified module resolution kind: 'NodeJs'.", + "Loading module as file / folder, candidate module location 'c:/root/folder2/file3'.", + "File 'c:/root/folder2/file3.ts' exist - use it as a module resolution result.", + "======== Module name './file3' was successfully resolved to 'c:/root/folder2/file3.ts'. ========", + "======== Resolving module 'file4' from 'c:/root/folder2/file2.ts'. ========", + "Explicitly specified module resolution kind: 'NodeJs'.", + "'baseUrl' option is set to 'c:/root', using this value to resolve non-relative module name 'file4'", + "Resolving module name 'file4' relative to base url 'c:/root' - 'c:/root/file4'.", + "Loading module as file / folder, candidate module location 'c:/root/file4'.", + "File 'c:/root/file4.ts' does not exist.", + "File 'c:/root/file4.tsx' does not exist.", + "File 'c:/root/file4.d.ts' does not exist.", + "File 'c:/root/file4/package.json' does not exist.", + "File 'c:/root/file4/index.ts' does not exist.", + "File 'c:/root/file4/index.tsx' does not exist.", + "File 'c:/root/file4/index.d.ts' does not exist.", + "Loading module 'file4' from 'node_modules' folder.", + "File 'c:/root/folder2/node_modules/file4.ts' does not exist.", + "File 'c:/root/folder2/node_modules/file4.tsx' does not exist.", + "File 'c:/root/folder2/node_modules/file4.d.ts' does not exist.", + "File 'c:/root/folder2/node_modules/file4/package.json' does not exist.", + "File 'c:/root/folder2/node_modules/file4/index.ts' does not exist.", + "File 'c:/root/folder2/node_modules/file4/index.tsx' does not exist.", + "File 'c:/root/folder2/node_modules/file4/index.d.ts' does not exist.", + "File 'c:/root/node_modules/file4.ts' does not exist.", + "File 'c:/root/node_modules/file4.tsx' does not exist.", + "File 'c:/root/node_modules/file4.d.ts' does not exist.", + "File 'c:/root/node_modules/file4/package.json' does not exist.", + "File 'c:/root/node_modules/file4/index.ts' does not exist.", + "File 'c:/root/node_modules/file4/index.tsx' does not exist.", + "File 'c:/root/node_modules/file4/index.d.ts' does not exist.", + "File 'c:/node_modules/file4.ts' does not exist.", + "File 'c:/node_modules/file4.tsx' does not exist.", + "File 'c:/node_modules/file4.d.ts' does not exist.", + "File 'c:/node_modules/file4/package.json' does not exist.", + "File 'c:/node_modules/file4/index.ts' does not exist.", + "File 'c:/node_modules/file4/index.tsx' does not exist.", + "File 'c:/node_modules/file4/index.d.ts' exist - use it as a module resolution result.", + "======== Module name 'file4' was successfully resolved to 'c:/node_modules/file4/index.d.ts'. ========" +] \ No newline at end of file diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution4_node.types b/tests/baselines/reference/pathMappingBasedModuleResolution4_node.types new file mode 100644 index 0000000000000..5478a601f0226 --- /dev/null +++ b/tests/baselines/reference/pathMappingBasedModuleResolution4_node.types @@ -0,0 +1,40 @@ +=== c:/root/folder1/file1.ts === +import {x} from "folder2/file2" +>x : number + +declare function use(a: any): void; +>use : (a: any) => void +>a : any + +use(x.toExponential()); +>use(x.toExponential()) : void +>use : (a: any) => void +>x.toExponential() : string +>x.toExponential : (fractionDigits?: number) => string +>x : number +>toExponential : (fractionDigits?: number) => string + +=== c:/root/folder2/file2.ts === +import {x as a} from "./file3" // found with baseurl +>x : number +>a : number + +import {y as b} from "file4" // found with fallback +>y : number +>b : number + +export var x = a + b; +>x : number +>a + b : number +>a : number +>b : number + +=== c:/root/folder2/file3.ts === +export var x = 1; +>x : number +>1 : number + +=== c:/node_modules/file4/index.d.ts === +export var y: number; +>y : number + diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution5_classic.js b/tests/baselines/reference/pathMappingBasedModuleResolution5_classic.js new file mode 100644 index 0000000000000..24297f85e35bc --- /dev/null +++ b/tests/baselines/reference/pathMappingBasedModuleResolution5_classic.js @@ -0,0 +1,55 @@ +//// [tests/cases/compiler/pathMappingBasedModuleResolution5_classic.ts] //// + +//// [file1.ts] +import {x} from "folder2/file1" +import {y} from "folder3/file2" +import {z} from "components/file3" +import {z1} from "file4" + +declare function use(a: any): void; + +use(x.toExponential()); +use(y.toExponential()); +use(z.toExponential()); +use(z1.toExponential()); + +//// [file1.ts] +export var x = 1; + +//// [file2.ts] +export var y = 1; + +//// [file3.ts] +export var z = 1; + +//// [file4.ts] +export var z1 = 1; + +//// [file1.js] +define(["require", "exports"], function (require, exports) { + "use strict"; + exports.x = 1; +}); +//// [file2.js] +define(["require", "exports"], function (require, exports) { + "use strict"; + exports.y = 1; +}); +//// [file3.js] +define(["require", "exports"], function (require, exports) { + "use strict"; + exports.z = 1; +}); +//// [file4.js] +define(["require", "exports"], function (require, exports) { + "use strict"; + exports.z1 = 1; +}); +//// [file1.js] +define(["require", "exports", "folder2/file1", "folder3/file2", "components/file3", "file4"], function (require, exports, file1_1, file2_1, file3_1, file4_1) { + "use strict"; + use(file1_1.x.toExponential()); + use(file2_1.y.toExponential()); + use(file3_1.z.toExponential()); + use(file4_1.z1.toExponential()); +}); diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution5_classic.symbols b/tests/baselines/reference/pathMappingBasedModuleResolution5_classic.symbols new file mode 100644 index 0000000000000..057b5a622a1b9 --- /dev/null +++ b/tests/baselines/reference/pathMappingBasedModuleResolution5_classic.symbols @@ -0,0 +1,57 @@ +=== c:/root/folder1/file1.ts === +import {x} from "folder2/file1" +>x : Symbol(x, Decl(file1.ts, 0, 8)) + +import {y} from "folder3/file2" +>y : Symbol(y, Decl(file1.ts, 1, 8)) + +import {z} from "components/file3" +>z : Symbol(z, Decl(file1.ts, 2, 8)) + +import {z1} from "file4" +>z1 : Symbol(z1, Decl(file1.ts, 3, 8)) + +declare function use(a: any): void; +>use : Symbol(use, Decl(file1.ts, 3, 24)) +>a : Symbol(a, Decl(file1.ts, 5, 21)) + +use(x.toExponential()); +>use : Symbol(use, Decl(file1.ts, 3, 24)) +>x.toExponential : Symbol(Number.toExponential, Decl(lib.d.ts, --, --)) +>x : Symbol(x, Decl(file1.ts, 0, 8)) +>toExponential : Symbol(Number.toExponential, Decl(lib.d.ts, --, --)) + +use(y.toExponential()); +>use : Symbol(use, Decl(file1.ts, 3, 24)) +>y.toExponential : Symbol(Number.toExponential, Decl(lib.d.ts, --, --)) +>y : Symbol(y, Decl(file1.ts, 1, 8)) +>toExponential : Symbol(Number.toExponential, Decl(lib.d.ts, --, --)) + +use(z.toExponential()); +>use : Symbol(use, Decl(file1.ts, 3, 24)) +>z.toExponential : Symbol(Number.toExponential, Decl(lib.d.ts, --, --)) +>z : Symbol(z, Decl(file1.ts, 2, 8)) +>toExponential : Symbol(Number.toExponential, Decl(lib.d.ts, --, --)) + +use(z1.toExponential()); +>use : Symbol(use, Decl(file1.ts, 3, 24)) +>z1.toExponential : Symbol(Number.toExponential, Decl(lib.d.ts, --, --)) +>z1 : Symbol(z1, Decl(file1.ts, 3, 8)) +>toExponential : Symbol(Number.toExponential, Decl(lib.d.ts, --, --)) + +=== c:/root/folder2/file1.ts === +export var x = 1; +>x : Symbol(x, Decl(file1.ts, 0, 10)) + +=== c:/root/generated/folder3/file2.ts === +export var y = 1; +>y : Symbol(y, Decl(file2.ts, 0, 10)) + +=== c:/root/shared/components/file3.ts === +export var z = 1; +>z : Symbol(z, Decl(file3.ts, 0, 10)) + +=== c:/file4.ts === +export var z1 = 1; +>z1 : Symbol(z1, Decl(file4.ts, 0, 10)) + diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution5_classic.trace.json b/tests/baselines/reference/pathMappingBasedModuleResolution5_classic.trace.json new file mode 100644 index 0000000000000..293291e4acfe3 --- /dev/null +++ b/tests/baselines/reference/pathMappingBasedModuleResolution5_classic.trace.json @@ -0,0 +1,51 @@ +[ + "======== Resolving module 'folder2/file1' from 'c:/root/folder1/file1.ts'. ========", + "Module resolution kind is not specified, using 'Classic'.", + "'baseUrl' option is set to 'c:/root', using this value to resolve non-relative module name 'folder2/file1'", + "'paths' option is specified, looking for a pattern to match module name 'folder2/file1'.", + "Module name 'folder2/file1', matched pattern '*'.", + "Trying substitution '*', candidate module location: 'folder2/file1'.", + "File 'c:/root/folder2/file1.ts' exist - use it as a module resolution result.", + "======== Module name 'folder2/file1' was successfully resolved to 'c:/root/folder2/file1.ts'. ========", + "======== Resolving module 'folder3/file2' from 'c:/root/folder1/file1.ts'. ========", + "Module resolution kind is not specified, using 'Classic'.", + "'baseUrl' option is set to 'c:/root', using this value to resolve non-relative module name 'folder3/file2'", + "'paths' option is specified, looking for a pattern to match module name 'folder3/file2'.", + "Module name 'folder3/file2', matched pattern '*'.", + "Trying substitution '*', candidate module location: 'folder3/file2'.", + "File 'c:/root/folder3/file2.ts' does not exist.", + "File 'c:/root/folder3/file2.tsx' does not exist.", + "File 'c:/root/folder3/file2.d.ts' does not exist.", + "Trying substitution 'generated/*', candidate module location: 'generated/folder3/file2'.", + "File 'c:/root/generated/folder3/file2.ts' exist - use it as a module resolution result.", + "======== Module name 'folder3/file2' was successfully resolved to 'c:/root/generated/folder3/file2.ts'. ========", + "======== Resolving module 'components/file3' from 'c:/root/folder1/file1.ts'. ========", + "Module resolution kind is not specified, using 'Classic'.", + "'baseUrl' option is set to 'c:/root', using this value to resolve non-relative module name 'components/file3'", + "'paths' option is specified, looking for a pattern to match module name 'components/file3'.", + "Module name 'components/file3', matched pattern 'components/*'.", + "Trying substitution 'shared/components/*', candidate module location: 'shared/components/file3'.", + "File 'c:/root/shared/components/file3.ts' exist - use it as a module resolution result.", + "======== Module name 'components/file3' was successfully resolved to 'c:/root/shared/components/file3.ts'. ========", + "======== Resolving module 'file4' from 'c:/root/folder1/file1.ts'. ========", + "Module resolution kind is not specified, using 'Classic'.", + "'baseUrl' option is set to 'c:/root', using this value to resolve non-relative module name 'file4'", + "'paths' option is specified, looking for a pattern to match module name 'file4'.", + "Module name 'file4', matched pattern '*'.", + "Trying substitution '*', candidate module location: 'file4'.", + "File 'c:/root/file4.ts' does not exist.", + "File 'c:/root/file4.tsx' does not exist.", + "File 'c:/root/file4.d.ts' does not exist.", + "Trying substitution 'generated/*', candidate module location: 'generated/file4'.", + "File 'c:/root/generated/file4.ts' does not exist.", + "File 'c:/root/generated/file4.tsx' does not exist.", + "File 'c:/root/generated/file4.d.ts' does not exist.", + "File 'c:/root/folder1/file4.ts' does not exist.", + "File 'c:/root/folder1/file4.tsx' does not exist.", + "File 'c:/root/folder1/file4.d.ts' does not exist.", + "File 'c:/root/file4.ts' does not exist.", + "File 'c:/root/file4.tsx' does not exist.", + "File 'c:/root/file4.d.ts' does not exist.", + "File 'c:/file4.ts' exist - use it as a module resolution result.", + "======== Module name 'file4' was successfully resolved to 'c:/file4.ts'. ========" +] \ No newline at end of file diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution5_classic.types b/tests/baselines/reference/pathMappingBasedModuleResolution5_classic.types new file mode 100644 index 0000000000000..32a1f42bc0fb4 --- /dev/null +++ b/tests/baselines/reference/pathMappingBasedModuleResolution5_classic.types @@ -0,0 +1,69 @@ +=== c:/root/folder1/file1.ts === +import {x} from "folder2/file1" +>x : number + +import {y} from "folder3/file2" +>y : number + +import {z} from "components/file3" +>z : number + +import {z1} from "file4" +>z1 : number + +declare function use(a: any): void; +>use : (a: any) => void +>a : any + +use(x.toExponential()); +>use(x.toExponential()) : void +>use : (a: any) => void +>x.toExponential() : string +>x.toExponential : (fractionDigits?: number) => string +>x : number +>toExponential : (fractionDigits?: number) => string + +use(y.toExponential()); +>use(y.toExponential()) : void +>use : (a: any) => void +>y.toExponential() : string +>y.toExponential : (fractionDigits?: number) => string +>y : number +>toExponential : (fractionDigits?: number) => string + +use(z.toExponential()); +>use(z.toExponential()) : void +>use : (a: any) => void +>z.toExponential() : string +>z.toExponential : (fractionDigits?: number) => string +>z : number +>toExponential : (fractionDigits?: number) => string + +use(z1.toExponential()); +>use(z1.toExponential()) : void +>use : (a: any) => void +>z1.toExponential() : string +>z1.toExponential : (fractionDigits?: number) => string +>z1 : number +>toExponential : (fractionDigits?: number) => string + +=== c:/root/folder2/file1.ts === +export var x = 1; +>x : number +>1 : number + +=== c:/root/generated/folder3/file2.ts === +export var y = 1; +>y : number +>1 : number + +=== c:/root/shared/components/file3.ts === +export var z = 1; +>z : number +>1 : number + +=== c:/file4.ts === +export var z1 = 1; +>z1 : number +>1 : number + diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution5_node.js b/tests/baselines/reference/pathMappingBasedModuleResolution5_node.js new file mode 100644 index 0000000000000..1958800f91893 --- /dev/null +++ b/tests/baselines/reference/pathMappingBasedModuleResolution5_node.js @@ -0,0 +1,46 @@ +//// [tests/cases/compiler/pathMappingBasedModuleResolution5_node.ts] //// + +//// [file1.ts] +import {x} from "folder2/file1" +import {y} from "folder3/file2" +import {z} from "components/file3" +import {z1} from "file4" + +declare function use(a: any): void; + +use(x.toExponential()); +use(y.toExponential()); +use(z.toExponential()); +use(z1.toExponential()); + +//// [file1.ts] +export var x = 1; + +//// [file2.ts] +export var y = 1; + +//// [index.d.ts] +export var z: number; + +//// [file4.ts] +export var z1 = 1; + +//// [file1.js] +"use strict"; +exports.x = 1; +//// [file2.js] +"use strict"; +exports.y = 1; +//// [file4.js] +"use strict"; +exports.z1 = 1; +//// [file1.js] +"use strict"; +var file1_1 = require("folder2/file1"); +var file2_1 = require("folder3/file2"); +var file3_1 = require("components/file3"); +var file4_1 = require("file4"); +use(file1_1.x.toExponential()); +use(file2_1.y.toExponential()); +use(file3_1.z.toExponential()); +use(file4_1.z1.toExponential()); diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution5_node.symbols b/tests/baselines/reference/pathMappingBasedModuleResolution5_node.symbols new file mode 100644 index 0000000000000..67bf14607dd10 --- /dev/null +++ b/tests/baselines/reference/pathMappingBasedModuleResolution5_node.symbols @@ -0,0 +1,57 @@ +=== c:/root/folder1/file1.ts === +import {x} from "folder2/file1" +>x : Symbol(x, Decl(file1.ts, 0, 8)) + +import {y} from "folder3/file2" +>y : Symbol(y, Decl(file1.ts, 1, 8)) + +import {z} from "components/file3" +>z : Symbol(z, Decl(file1.ts, 2, 8)) + +import {z1} from "file4" +>z1 : Symbol(z1, Decl(file1.ts, 3, 8)) + +declare function use(a: any): void; +>use : Symbol(use, Decl(file1.ts, 3, 24)) +>a : Symbol(a, Decl(file1.ts, 5, 21)) + +use(x.toExponential()); +>use : Symbol(use, Decl(file1.ts, 3, 24)) +>x.toExponential : Symbol(Number.toExponential, Decl(lib.d.ts, --, --)) +>x : Symbol(x, Decl(file1.ts, 0, 8)) +>toExponential : Symbol(Number.toExponential, Decl(lib.d.ts, --, --)) + +use(y.toExponential()); +>use : Symbol(use, Decl(file1.ts, 3, 24)) +>y.toExponential : Symbol(Number.toExponential, Decl(lib.d.ts, --, --)) +>y : Symbol(y, Decl(file1.ts, 1, 8)) +>toExponential : Symbol(Number.toExponential, Decl(lib.d.ts, --, --)) + +use(z.toExponential()); +>use : Symbol(use, Decl(file1.ts, 3, 24)) +>z.toExponential : Symbol(Number.toExponential, Decl(lib.d.ts, --, --)) +>z : Symbol(z, Decl(file1.ts, 2, 8)) +>toExponential : Symbol(Number.toExponential, Decl(lib.d.ts, --, --)) + +use(z1.toExponential()); +>use : Symbol(use, Decl(file1.ts, 3, 24)) +>z1.toExponential : Symbol(Number.toExponential, Decl(lib.d.ts, --, --)) +>z1 : Symbol(z1, Decl(file1.ts, 3, 8)) +>toExponential : Symbol(Number.toExponential, Decl(lib.d.ts, --, --)) + +=== c:/root/folder2/file1.ts === +export var x = 1; +>x : Symbol(x, Decl(file1.ts, 0, 10)) + +=== c:/root/generated/folder3/file2.ts === +export var y = 1; +>y : Symbol(y, Decl(file2.ts, 0, 10)) + +=== c:/root/shared/components/file3/index.d.ts === +export var z: number; +>z : Symbol(z, Decl(index.d.ts, 0, 10)) + +=== c:/node_modules/file4.ts === +export var z1 = 1; +>z1 : Symbol(z1, Decl(file4.ts, 0, 10)) + diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution5_node.trace.json b/tests/baselines/reference/pathMappingBasedModuleResolution5_node.trace.json new file mode 100644 index 0000000000000..398d15839de92 --- /dev/null +++ b/tests/baselines/reference/pathMappingBasedModuleResolution5_node.trace.json @@ -0,0 +1,84 @@ +[ + "======== Resolving module 'folder2/file1' from 'c:/root/folder1/file1.ts'. ========", + "Module resolution kind is not specified, using 'NodeJs'.", + "'baseUrl' option is set to 'c:/root', using this value to resolve non-relative module name 'folder2/file1'", + "'paths' option is specified, looking for a pattern to match module name 'folder2/file1'.", + "Module name 'folder2/file1', matched pattern '*'.", + "Trying substitution '*', candidate module location: 'folder2/file1'.", + "Loading module as file / folder, candidate module location 'c:/root/folder2/file1'.", + "File 'c:/root/folder2/file1.ts' exist - use it as a module resolution result.", + "======== Module name 'folder2/file1' was successfully resolved to 'c:/root/folder2/file1.ts'. ========", + "======== Resolving module 'folder3/file2' from 'c:/root/folder1/file1.ts'. ========", + "Module resolution kind is not specified, using 'NodeJs'.", + "'baseUrl' option is set to 'c:/root', using this value to resolve non-relative module name 'folder3/file2'", + "'paths' option is specified, looking for a pattern to match module name 'folder3/file2'.", + "Module name 'folder3/file2', matched pattern '*'.", + "Trying substitution '*', candidate module location: 'folder3/file2'.", + "Loading module as file / folder, candidate module location 'c:/root/folder3/file2'.", + "File 'c:/root/folder3/file2.ts' does not exist.", + "File 'c:/root/folder3/file2.tsx' does not exist.", + "File 'c:/root/folder3/file2.d.ts' does not exist.", + "File 'c:/root/folder3/file2/package.json' does not exist.", + "File 'c:/root/folder3/file2/index.ts' does not exist.", + "File 'c:/root/folder3/file2/index.tsx' does not exist.", + "File 'c:/root/folder3/file2/index.d.ts' does not exist.", + "Trying substitution 'generated/*', candidate module location: 'generated/folder3/file2'.", + "Loading module as file / folder, candidate module location 'c:/root/generated/folder3/file2'.", + "File 'c:/root/generated/folder3/file2.ts' exist - use it as a module resolution result.", + "======== Module name 'folder3/file2' was successfully resolved to 'c:/root/generated/folder3/file2.ts'. ========", + "======== Resolving module 'components/file3' from 'c:/root/folder1/file1.ts'. ========", + "Module resolution kind is not specified, using 'NodeJs'.", + "'baseUrl' option is set to 'c:/root', using this value to resolve non-relative module name 'components/file3'", + "'paths' option is specified, looking for a pattern to match module name 'components/file3'.", + "Module name 'components/file3', matched pattern 'components/*'.", + "Trying substitution 'shared/components/*', candidate module location: 'shared/components/file3'.", + "Loading module as file / folder, candidate module location 'c:/root/shared/components/file3'.", + "File 'c:/root/shared/components/file3.ts' does not exist.", + "File 'c:/root/shared/components/file3.tsx' does not exist.", + "File 'c:/root/shared/components/file3.d.ts' does not exist.", + "File 'c:/root/shared/components/file3/package.json' does not exist.", + "File 'c:/root/shared/components/file3/index.ts' does not exist.", + "File 'c:/root/shared/components/file3/index.tsx' does not exist.", + "File 'c:/root/shared/components/file3/index.d.ts' exist - use it as a module resolution result.", + "======== Module name 'components/file3' was successfully resolved to 'c:/root/shared/components/file3/index.d.ts'. ========", + "======== Resolving module 'file4' from 'c:/root/folder1/file1.ts'. ========", + "Module resolution kind is not specified, using 'NodeJs'.", + "'baseUrl' option is set to 'c:/root', using this value to resolve non-relative module name 'file4'", + "'paths' option is specified, looking for a pattern to match module name 'file4'.", + "Module name 'file4', matched pattern '*'.", + "Trying substitution '*', candidate module location: 'file4'.", + "Loading module as file / folder, candidate module location 'c:/root/file4'.", + "File 'c:/root/file4.ts' does not exist.", + "File 'c:/root/file4.tsx' does not exist.", + "File 'c:/root/file4.d.ts' does not exist.", + "File 'c:/root/file4/package.json' does not exist.", + "File 'c:/root/file4/index.ts' does not exist.", + "File 'c:/root/file4/index.tsx' does not exist.", + "File 'c:/root/file4/index.d.ts' does not exist.", + "Trying substitution 'generated/*', candidate module location: 'generated/file4'.", + "Loading module as file / folder, candidate module location 'c:/root/generated/file4'.", + "File 'c:/root/generated/file4.ts' does not exist.", + "File 'c:/root/generated/file4.tsx' does not exist.", + "File 'c:/root/generated/file4.d.ts' does not exist.", + "File 'c:/root/generated/file4/package.json' does not exist.", + "File 'c:/root/generated/file4/index.ts' does not exist.", + "File 'c:/root/generated/file4/index.tsx' does not exist.", + "File 'c:/root/generated/file4/index.d.ts' does not exist.", + "Loading module 'file4' from 'node_modules' folder.", + "File 'c:/root/folder1/node_modules/file4.ts' does not exist.", + "File 'c:/root/folder1/node_modules/file4.tsx' does not exist.", + "File 'c:/root/folder1/node_modules/file4.d.ts' does not exist.", + "File 'c:/root/folder1/node_modules/file4/package.json' does not exist.", + "File 'c:/root/folder1/node_modules/file4/index.ts' does not exist.", + "File 'c:/root/folder1/node_modules/file4/index.tsx' does not exist.", + "File 'c:/root/folder1/node_modules/file4/index.d.ts' does not exist.", + "File 'c:/root/node_modules/file4.ts' does not exist.", + "File 'c:/root/node_modules/file4.tsx' does not exist.", + "File 'c:/root/node_modules/file4.d.ts' does not exist.", + "File 'c:/root/node_modules/file4/package.json' does not exist.", + "File 'c:/root/node_modules/file4/index.ts' does not exist.", + "File 'c:/root/node_modules/file4/index.tsx' does not exist.", + "File 'c:/root/node_modules/file4/index.d.ts' does not exist.", + "File 'c:/node_modules/file4.ts' exist - use it as a module resolution result.", + "======== Module name 'file4' was successfully resolved to 'c:/node_modules/file4.ts'. ========" +] \ No newline at end of file diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution5_node.types b/tests/baselines/reference/pathMappingBasedModuleResolution5_node.types new file mode 100644 index 0000000000000..1b96e3f4f22a9 --- /dev/null +++ b/tests/baselines/reference/pathMappingBasedModuleResolution5_node.types @@ -0,0 +1,68 @@ +=== c:/root/folder1/file1.ts === +import {x} from "folder2/file1" +>x : number + +import {y} from "folder3/file2" +>y : number + +import {z} from "components/file3" +>z : number + +import {z1} from "file4" +>z1 : number + +declare function use(a: any): void; +>use : (a: any) => void +>a : any + +use(x.toExponential()); +>use(x.toExponential()) : void +>use : (a: any) => void +>x.toExponential() : string +>x.toExponential : (fractionDigits?: number) => string +>x : number +>toExponential : (fractionDigits?: number) => string + +use(y.toExponential()); +>use(y.toExponential()) : void +>use : (a: any) => void +>y.toExponential() : string +>y.toExponential : (fractionDigits?: number) => string +>y : number +>toExponential : (fractionDigits?: number) => string + +use(z.toExponential()); +>use(z.toExponential()) : void +>use : (a: any) => void +>z.toExponential() : string +>z.toExponential : (fractionDigits?: number) => string +>z : number +>toExponential : (fractionDigits?: number) => string + +use(z1.toExponential()); +>use(z1.toExponential()) : void +>use : (a: any) => void +>z1.toExponential() : string +>z1.toExponential : (fractionDigits?: number) => string +>z1 : number +>toExponential : (fractionDigits?: number) => string + +=== c:/root/folder2/file1.ts === +export var x = 1; +>x : number +>1 : number + +=== c:/root/generated/folder3/file2.ts === +export var y = 1; +>y : number +>1 : number + +=== c:/root/shared/components/file3/index.d.ts === +export var z: number; +>z : number + +=== c:/node_modules/file4.ts === +export var z1 = 1; +>z1 : number +>1 : number + diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution6_classic.js b/tests/baselines/reference/pathMappingBasedModuleResolution6_classic.js new file mode 100644 index 0000000000000..1e8f8807e2cf0 --- /dev/null +++ b/tests/baselines/reference/pathMappingBasedModuleResolution6_classic.js @@ -0,0 +1,23 @@ +//// [tests/cases/compiler/pathMappingBasedModuleResolution6_classic.ts] //// + +//// [file1.ts] +import {x} from "./project/file3"; +declare function use(x: string); +use(x.toExponential()); + +//// [file2.d.ts] +export let x: number; + +//// [file3.ts] +export {x} from "../file2"; + +//// [file3.js] +define(["require", "exports", "../file2"], function (require, exports, file2_1) { + "use strict"; + exports.x = file2_1.x; +}); +//// [file1.js] +define(["require", "exports", "./project/file3"], function (require, exports, file3_1) { + "use strict"; + use(file3_1.x.toExponential()); +}); diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution6_classic.symbols b/tests/baselines/reference/pathMappingBasedModuleResolution6_classic.symbols new file mode 100644 index 0000000000000..a451ffb2584e9 --- /dev/null +++ b/tests/baselines/reference/pathMappingBasedModuleResolution6_classic.symbols @@ -0,0 +1,22 @@ +=== c:/root/src/file1.ts === +import {x} from "./project/file3"; +>x : Symbol(x, Decl(file1.ts, 0, 8)) + +declare function use(x: string); +>use : Symbol(use, Decl(file1.ts, 0, 34)) +>x : Symbol(x, Decl(file1.ts, 1, 21)) + +use(x.toExponential()); +>use : Symbol(use, Decl(file1.ts, 0, 34)) +>x.toExponential : Symbol(Number.toExponential, Decl(lib.d.ts, --, --)) +>x : Symbol(x, Decl(file1.ts, 0, 8)) +>toExponential : Symbol(Number.toExponential, Decl(lib.d.ts, --, --)) + +=== c:/root/src/file2.d.ts === +export let x: number; +>x : Symbol(x, Decl(file2.d.ts, 0, 10)) + +=== c:/root/generated/src/project/file3.ts === +export {x} from "../file2"; +>x : Symbol(x, Decl(file3.ts, 0, 8)) + diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution6_classic.trace.json b/tests/baselines/reference/pathMappingBasedModuleResolution6_classic.trace.json new file mode 100644 index 0000000000000..229ef51a9247f --- /dev/null +++ b/tests/baselines/reference/pathMappingBasedModuleResolution6_classic.trace.json @@ -0,0 +1,32 @@ +[ + "======== Resolving module './project/file3' from 'c:/root/src/file1.ts'. ========", + "Module resolution kind is not specified, using 'Classic'.", + "'rootDirs' option is set, using it to resolve relative module name './project/file3'", + "Checking if 'c:/root/src/' is the longest matching prefix for 'c:/root/src/project/file3' - 'true'.", + "Checking if 'c:/root/generated/src/' is the longest matching prefix for 'c:/root/src/project/file3' - 'false'.", + "Longest matching prefix for 'c:/root/src/project/file3' is 'c:/root/src/'", + "Loading 'project/file3' from the root dir 'c:/root/src/', candidate location 'c:/root/src/project/file3'", + "File 'c:/root/src/project/file3.ts' does not exist.", + "File 'c:/root/src/project/file3.tsx' does not exist.", + "File 'c:/root/src/project/file3.d.ts' does not exist.", + "Trying other entries in 'rootDirs'", + "Loading 'project/file3' from the root dir 'c:/root/generated/src', candidate location 'c:/root/generated/src/project/file3'", + "File 'c:/root/generated/src/project/file3.ts' exist - use it as a module resolution result.", + "======== Module name './project/file3' was successfully resolved to 'c:/root/generated/src/project/file3.ts'. ========", + "======== Resolving module '../file2' from 'c:/root/generated/src/project/file3.ts'. ========", + "Module resolution kind is not specified, using 'Classic'.", + "'rootDirs' option is set, using it to resolve relative module name '../file2'", + "Checking if 'c:/root/src/' is the longest matching prefix for 'c:/root/generated/src/file2' - 'false'.", + "Checking if 'c:/root/generated/src/' is the longest matching prefix for 'c:/root/generated/src/file2' - 'true'.", + "Longest matching prefix for 'c:/root/generated/src/file2' is 'c:/root/generated/src/'", + "Loading 'file2' from the root dir 'c:/root/generated/src/', candidate location 'c:/root/generated/src/file2'", + "File 'c:/root/generated/src/file2.ts' does not exist.", + "File 'c:/root/generated/src/file2.tsx' does not exist.", + "File 'c:/root/generated/src/file2.d.ts' does not exist.", + "Trying other entries in 'rootDirs'", + "Loading 'file2' from the root dir 'c:/root/src', candidate location 'c:/root/src/file2'", + "File 'c:/root/src/file2.ts' does not exist.", + "File 'c:/root/src/file2.tsx' does not exist.", + "File 'c:/root/src/file2.d.ts' exist - use it as a module resolution result.", + "======== Module name '../file2' was successfully resolved to 'c:/root/src/file2.d.ts'. ========" +] \ No newline at end of file diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution6_classic.types b/tests/baselines/reference/pathMappingBasedModuleResolution6_classic.types new file mode 100644 index 0000000000000..06d2cbdce34d4 --- /dev/null +++ b/tests/baselines/reference/pathMappingBasedModuleResolution6_classic.types @@ -0,0 +1,24 @@ +=== c:/root/src/file1.ts === +import {x} from "./project/file3"; +>x : number + +declare function use(x: string); +>use : (x: string) => any +>x : string + +use(x.toExponential()); +>use(x.toExponential()) : any +>use : (x: string) => any +>x.toExponential() : string +>x.toExponential : (fractionDigits?: number) => string +>x : number +>toExponential : (fractionDigits?: number) => string + +=== c:/root/src/file2.d.ts === +export let x: number; +>x : number + +=== c:/root/generated/src/project/file3.ts === +export {x} from "../file2"; +>x : number + diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution6_node.js b/tests/baselines/reference/pathMappingBasedModuleResolution6_node.js new file mode 100644 index 0000000000000..6db3fecf83fad --- /dev/null +++ b/tests/baselines/reference/pathMappingBasedModuleResolution6_node.js @@ -0,0 +1,21 @@ +//// [tests/cases/compiler/pathMappingBasedModuleResolution6_node.ts] //// + +//// [file1.ts] +import {x} from "./project/file3"; +declare function use(x: string); +use(x.toFixed()); + +//// [index.d.ts] +export let x: number; + +//// [file3.ts] +export {x} from "../file2"; + +//// [file3.js] +"use strict"; +var file2_1 = require("../file2"); +exports.x = file2_1.x; +//// [file1.js] +"use strict"; +var file3_1 = require("./project/file3"); +use(file3_1.x.toFixed()); diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution6_node.symbols b/tests/baselines/reference/pathMappingBasedModuleResolution6_node.symbols new file mode 100644 index 0000000000000..06554bae03989 --- /dev/null +++ b/tests/baselines/reference/pathMappingBasedModuleResolution6_node.symbols @@ -0,0 +1,22 @@ +=== c:/root/src/file1.ts === +import {x} from "./project/file3"; +>x : Symbol(x, Decl(file1.ts, 0, 8)) + +declare function use(x: string); +>use : Symbol(use, Decl(file1.ts, 0, 34)) +>x : Symbol(x, Decl(file1.ts, 1, 21)) + +use(x.toFixed()); +>use : Symbol(use, Decl(file1.ts, 0, 34)) +>x.toFixed : Symbol(Number.toFixed, Decl(lib.d.ts, --, --)) +>x : Symbol(x, Decl(file1.ts, 0, 8)) +>toFixed : Symbol(Number.toFixed, Decl(lib.d.ts, --, --)) + +=== c:/root/src/file2/index.d.ts === +export let x: number; +>x : Symbol(x, Decl(index.d.ts, 0, 10)) + +=== c:/root/generated/src/project/file3.ts === +export {x} from "../file2"; +>x : Symbol(x, Decl(file3.ts, 0, 8)) + diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution6_node.trace.json b/tests/baselines/reference/pathMappingBasedModuleResolution6_node.trace.json new file mode 100644 index 0000000000000..4ea2f12a63c35 --- /dev/null +++ b/tests/baselines/reference/pathMappingBasedModuleResolution6_node.trace.json @@ -0,0 +1,48 @@ +[ + "======== Resolving module './project/file3' from 'c:/root/src/file1.ts'. ========", + "Module resolution kind is not specified, using 'NodeJs'.", + "'rootDirs' option is set, using it to resolve relative module name './project/file3'", + "Checking if 'c:/root/src/' is the longest matching prefix for 'c:/root/src/project/file3' - 'true'.", + "Checking if 'c:/root/generated/src/' is the longest matching prefix for 'c:/root/src/project/file3' - 'false'.", + "Longest matching prefix for 'c:/root/src/project/file3' is 'c:/root/src/'", + "Loading 'project/file3' from the root dir 'c:/root/src/', candidate location 'c:/root/src/project/file3'", + "Loading module as file / folder, candidate module location 'c:/root/src/project/file3'.", + "File 'c:/root/src/project/file3.ts' does not exist.", + "File 'c:/root/src/project/file3.tsx' does not exist.", + "File 'c:/root/src/project/file3.d.ts' does not exist.", + "File 'c:/root/src/project/file3/package.json' does not exist.", + "File 'c:/root/src/project/file3/index.ts' does not exist.", + "File 'c:/root/src/project/file3/index.tsx' does not exist.", + "File 'c:/root/src/project/file3/index.d.ts' does not exist.", + "Trying other entries in 'rootDirs'", + "Loading 'project/file3' from the root dir 'c:/root/generated/src', candidate location 'c:/root/generated/src/project/file3'", + "Loading module as file / folder, candidate module location 'c:/root/generated/src/project/file3'.", + "File 'c:/root/generated/src/project/file3.ts' exist - use it as a module resolution result.", + "======== Module name './project/file3' was successfully resolved to 'c:/root/generated/src/project/file3.ts'. ========", + "======== Resolving module '../file2' from 'c:/root/generated/src/project/file3.ts'. ========", + "Module resolution kind is not specified, using 'NodeJs'.", + "'rootDirs' option is set, using it to resolve relative module name '../file2'", + "Checking if 'c:/root/src/' is the longest matching prefix for 'c:/root/generated/src/file2' - 'false'.", + "Checking if 'c:/root/generated/src/' is the longest matching prefix for 'c:/root/generated/src/file2' - 'true'.", + "Longest matching prefix for 'c:/root/generated/src/file2' is 'c:/root/generated/src/'", + "Loading 'file2' from the root dir 'c:/root/generated/src/', candidate location 'c:/root/generated/src/file2'", + "Loading module as file / folder, candidate module location 'c:/root/generated/src/file2'.", + "File 'c:/root/generated/src/file2.ts' does not exist.", + "File 'c:/root/generated/src/file2.tsx' does not exist.", + "File 'c:/root/generated/src/file2.d.ts' does not exist.", + "File 'c:/root/generated/src/file2/package.json' does not exist.", + "File 'c:/root/generated/src/file2/index.ts' does not exist.", + "File 'c:/root/generated/src/file2/index.tsx' does not exist.", + "File 'c:/root/generated/src/file2/index.d.ts' does not exist.", + "Trying other entries in 'rootDirs'", + "Loading 'file2' from the root dir 'c:/root/src', candidate location 'c:/root/src/file2'", + "Loading module as file / folder, candidate module location 'c:/root/src/file2'.", + "File 'c:/root/src/file2.ts' does not exist.", + "File 'c:/root/src/file2.tsx' does not exist.", + "File 'c:/root/src/file2.d.ts' does not exist.", + "File 'c:/root/src/file2/package.json' does not exist.", + "File 'c:/root/src/file2/index.ts' does not exist.", + "File 'c:/root/src/file2/index.tsx' does not exist.", + "File 'c:/root/src/file2/index.d.ts' exist - use it as a module resolution result.", + "======== Module name '../file2' was successfully resolved to 'c:/root/src/file2/index.d.ts'. ========" +] \ No newline at end of file diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution6_node.types b/tests/baselines/reference/pathMappingBasedModuleResolution6_node.types new file mode 100644 index 0000000000000..2fd10e8e1330d --- /dev/null +++ b/tests/baselines/reference/pathMappingBasedModuleResolution6_node.types @@ -0,0 +1,24 @@ +=== c:/root/src/file1.ts === +import {x} from "./project/file3"; +>x : number + +declare function use(x: string); +>use : (x: string) => any +>x : string + +use(x.toFixed()); +>use(x.toFixed()) : any +>use : (x: string) => any +>x.toFixed() : string +>x.toFixed : (fractionDigits?: number) => string +>x : number +>toFixed : (fractionDigits?: number) => string + +=== c:/root/src/file2/index.d.ts === +export let x: number; +>x : number + +=== c:/root/generated/src/project/file3.ts === +export {x} from "../file2"; +>x : number + diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution7_classic.js b/tests/baselines/reference/pathMappingBasedModuleResolution7_classic.js new file mode 100644 index 0000000000000..5670f41be0f11 --- /dev/null +++ b/tests/baselines/reference/pathMappingBasedModuleResolution7_classic.js @@ -0,0 +1,45 @@ +//// [tests/cases/compiler/pathMappingBasedModuleResolution7_classic.ts] //// + +//// [file1.ts] +import {x} from "./project/file2"; +import {y} from "module3"; + +declare function use(x: string); +use(x.toFixed()); +use(y.toFixed()); + +//// [file2.ts] +import {a} from "module1"; +import {b} from "templates/module2"; +import {x as c} from "../file3"; +export let x = a + b + c; + +//// [module1.d.ts] +export let a: number + +//// [module2.ts] +export let b: number; + +//// [file3.d.ts] +export let x: number; + +//// [module3.d.ts] +export let y: number; + + + +//// [module2.js] +define(["require", "exports"], function (require, exports) { + "use strict"; +}); +//// [file2.js] +define(["require", "exports", "module1", "templates/module2", "../file3"], function (require, exports, module1_1, module2_1, file3_1) { + "use strict"; + exports.x = module1_1.a + module2_1.b + file3_1.x; +}); +//// [file1.js] +define(["require", "exports", "./project/file2", "module3"], function (require, exports, file2_1, module3_1) { + "use strict"; + use(file2_1.x.toFixed()); + use(module3_1.y.toFixed()); +}); diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution7_classic.symbols b/tests/baselines/reference/pathMappingBasedModuleResolution7_classic.symbols new file mode 100644 index 0000000000000..b1e4751c495d2 --- /dev/null +++ b/tests/baselines/reference/pathMappingBasedModuleResolution7_classic.symbols @@ -0,0 +1,57 @@ +=== c:/root/src/file1.ts === +import {x} from "./project/file2"; +>x : Symbol(x, Decl(file1.ts, 0, 8)) + +import {y} from "module3"; +>y : Symbol(y, Decl(file1.ts, 1, 8)) + +declare function use(x: string); +>use : Symbol(use, Decl(file1.ts, 1, 26)) +>x : Symbol(x, Decl(file1.ts, 3, 21)) + +use(x.toFixed()); +>use : Symbol(use, Decl(file1.ts, 1, 26)) +>x.toFixed : Symbol(Number.toFixed, Decl(lib.d.ts, --, --)) +>x : Symbol(x, Decl(file1.ts, 0, 8)) +>toFixed : Symbol(Number.toFixed, Decl(lib.d.ts, --, --)) + +use(y.toFixed()); +>use : Symbol(use, Decl(file1.ts, 1, 26)) +>y.toFixed : Symbol(Number.toFixed, Decl(lib.d.ts, --, --)) +>y : Symbol(y, Decl(file1.ts, 1, 8)) +>toFixed : Symbol(Number.toFixed, Decl(lib.d.ts, --, --)) + +=== c:/root/generated/src/project/file2.ts === +import {a} from "module1"; +>a : Symbol(a, Decl(file2.ts, 0, 8)) + +import {b} from "templates/module2"; +>b : Symbol(b, Decl(file2.ts, 1, 8)) + +import {x as c} from "../file3"; +>x : Symbol(c, Decl(file2.ts, 2, 8)) +>c : Symbol(c, Decl(file2.ts, 2, 8)) + +export let x = a + b + c; +>x : Symbol(x, Decl(file2.ts, 3, 10)) +>a : Symbol(a, Decl(file2.ts, 0, 8)) +>b : Symbol(b, Decl(file2.ts, 1, 8)) +>c : Symbol(c, Decl(file2.ts, 2, 8)) + +=== c:/shared/module1.d.ts === +export let a: number +>a : Symbol(a, Decl(module1.d.ts, 0, 10)) + +=== c:/root/generated/src/templates/module2.ts === +export let b: number; +>b : Symbol(b, Decl(module2.ts, 0, 10)) + +=== c:/root/src/file3.d.ts === +export let x: number; +>x : Symbol(x, Decl(file3.d.ts, 0, 10)) + +=== c:/module3.d.ts === +export let y: number; +>y : Symbol(y, Decl(module3.d.ts, 0, 10)) + + diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution7_classic.trace.json b/tests/baselines/reference/pathMappingBasedModuleResolution7_classic.trace.json new file mode 100644 index 0000000000000..8242f8fb442bc --- /dev/null +++ b/tests/baselines/reference/pathMappingBasedModuleResolution7_classic.trace.json @@ -0,0 +1,77 @@ +[ + "======== Resolving module './project/file2' from 'c:/root/src/file1.ts'. ========", + "Module resolution kind is not specified, using 'Classic'.", + "'rootDirs' option is set, using it to resolve relative module name './project/file2'", + "Checking if 'c:/root/src/' is the longest matching prefix for 'c:/root/src/project/file2' - 'true'.", + "Checking if 'c:/root/generated/src/' is the longest matching prefix for 'c:/root/src/project/file2' - 'false'.", + "Longest matching prefix for 'c:/root/src/project/file2' is 'c:/root/src/'", + "Loading 'project/file2' from the root dir 'c:/root/src/', candidate location 'c:/root/src/project/file2'", + "File 'c:/root/src/project/file2.ts' does not exist.", + "File 'c:/root/src/project/file2.tsx' does not exist.", + "File 'c:/root/src/project/file2.d.ts' does not exist.", + "Trying other entries in 'rootDirs'", + "Loading 'project/file2' from the root dir 'c:/root/generated/src', candidate location 'c:/root/generated/src/project/file2'", + "File 'c:/root/generated/src/project/file2.ts' exist - use it as a module resolution result.", + "======== Module name './project/file2' was successfully resolved to 'c:/root/generated/src/project/file2.ts'. ========", + "======== Resolving module 'module3' from 'c:/root/src/file1.ts'. ========", + "Module resolution kind is not specified, using 'Classic'.", + "'baseUrl' option is set to 'c:/root', using this value to resolve non-relative module name 'module3'", + "'paths' option is specified, looking for a pattern to match module name 'module3'.", + "Module name 'module3', matched pattern '*'.", + "Trying substitution '*', candidate module location: 'module3'.", + "File 'c:/root/module3.ts' does not exist.", + "File 'c:/root/module3.tsx' does not exist.", + "File 'c:/root/module3.d.ts' does not exist.", + "Trying substitution 'c:/shared/*', candidate module location: 'c:/shared/module3'.", + "File 'c:/shared/module3.ts' does not exist.", + "File 'c:/shared/module3.tsx' does not exist.", + "File 'c:/shared/module3.d.ts' does not exist.", + "File 'c:/root/src/module3.ts' does not exist.", + "File 'c:/root/src/module3.tsx' does not exist.", + "File 'c:/root/src/module3.d.ts' does not exist.", + "File 'c:/root/module3.ts' does not exist.", + "File 'c:/root/module3.tsx' does not exist.", + "File 'c:/root/module3.d.ts' does not exist.", + "File 'c:/module3.ts' does not exist.", + "File 'c:/module3.tsx' does not exist.", + "File 'c:/module3.d.ts' exist - use it as a module resolution result.", + "======== Module name 'module3' was successfully resolved to 'c:/module3.d.ts'. ========", + "======== Resolving module 'module1' from 'c:/root/generated/src/project/file2.ts'. ========", + "Module resolution kind is not specified, using 'Classic'.", + "'baseUrl' option is set to 'c:/root', using this value to resolve non-relative module name 'module1'", + "'paths' option is specified, looking for a pattern to match module name 'module1'.", + "Module name 'module1', matched pattern '*'.", + "Trying substitution '*', candidate module location: 'module1'.", + "File 'c:/root/module1.ts' does not exist.", + "File 'c:/root/module1.tsx' does not exist.", + "File 'c:/root/module1.d.ts' does not exist.", + "Trying substitution 'c:/shared/*', candidate module location: 'c:/shared/module1'.", + "File 'c:/shared/module1.ts' does not exist.", + "File 'c:/shared/module1.tsx' does not exist.", + "File 'c:/shared/module1.d.ts' exist - use it as a module resolution result.", + "======== Module name 'module1' was successfully resolved to 'c:/shared/module1.d.ts'. ========", + "======== Resolving module 'templates/module2' from 'c:/root/generated/src/project/file2.ts'. ========", + "Module resolution kind is not specified, using 'Classic'.", + "'baseUrl' option is set to 'c:/root', using this value to resolve non-relative module name 'templates/module2'", + "'paths' option is specified, looking for a pattern to match module name 'templates/module2'.", + "Module name 'templates/module2', matched pattern 'templates/*'.", + "Trying substitution 'generated/src/templates/*', candidate module location: 'generated/src/templates/module2'.", + "File 'c:/root/generated/src/templates/module2.ts' exist - use it as a module resolution result.", + "======== Module name 'templates/module2' was successfully resolved to 'c:/root/generated/src/templates/module2.ts'. ========", + "======== Resolving module '../file3' from 'c:/root/generated/src/project/file2.ts'. ========", + "Module resolution kind is not specified, using 'Classic'.", + "'rootDirs' option is set, using it to resolve relative module name '../file3'", + "Checking if 'c:/root/src/' is the longest matching prefix for 'c:/root/generated/src/file3' - 'false'.", + "Checking if 'c:/root/generated/src/' is the longest matching prefix for 'c:/root/generated/src/file3' - 'true'.", + "Longest matching prefix for 'c:/root/generated/src/file3' is 'c:/root/generated/src/'", + "Loading 'file3' from the root dir 'c:/root/generated/src/', candidate location 'c:/root/generated/src/file3'", + "File 'c:/root/generated/src/file3.ts' does not exist.", + "File 'c:/root/generated/src/file3.tsx' does not exist.", + "File 'c:/root/generated/src/file3.d.ts' does not exist.", + "Trying other entries in 'rootDirs'", + "Loading 'file3' from the root dir 'c:/root/src', candidate location 'c:/root/src/file3'", + "File 'c:/root/src/file3.ts' does not exist.", + "File 'c:/root/src/file3.tsx' does not exist.", + "File 'c:/root/src/file3.d.ts' exist - use it as a module resolution result.", + "======== Module name '../file3' was successfully resolved to 'c:/root/src/file3.d.ts'. ========" +] \ No newline at end of file diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution7_classic.types b/tests/baselines/reference/pathMappingBasedModuleResolution7_classic.types new file mode 100644 index 0000000000000..26c4b425c8806 --- /dev/null +++ b/tests/baselines/reference/pathMappingBasedModuleResolution7_classic.types @@ -0,0 +1,63 @@ +=== c:/root/src/file1.ts === +import {x} from "./project/file2"; +>x : number + +import {y} from "module3"; +>y : number + +declare function use(x: string); +>use : (x: string) => any +>x : string + +use(x.toFixed()); +>use(x.toFixed()) : any +>use : (x: string) => any +>x.toFixed() : string +>x.toFixed : (fractionDigits?: number) => string +>x : number +>toFixed : (fractionDigits?: number) => string + +use(y.toFixed()); +>use(y.toFixed()) : any +>use : (x: string) => any +>y.toFixed() : string +>y.toFixed : (fractionDigits?: number) => string +>y : number +>toFixed : (fractionDigits?: number) => string + +=== c:/root/generated/src/project/file2.ts === +import {a} from "module1"; +>a : number + +import {b} from "templates/module2"; +>b : number + +import {x as c} from "../file3"; +>x : number +>c : number + +export let x = a + b + c; +>x : number +>a + b + c : number +>a + b : number +>a : number +>b : number +>c : number + +=== c:/shared/module1.d.ts === +export let a: number +>a : number + +=== c:/root/generated/src/templates/module2.ts === +export let b: number; +>b : number + +=== c:/root/src/file3.d.ts === +export let x: number; +>x : number + +=== c:/module3.d.ts === +export let y: number; +>y : number + + diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution7_node.js b/tests/baselines/reference/pathMappingBasedModuleResolution7_node.js new file mode 100644 index 0000000000000..3be48cfc85c76 --- /dev/null +++ b/tests/baselines/reference/pathMappingBasedModuleResolution7_node.js @@ -0,0 +1,44 @@ +//// [tests/cases/compiler/pathMappingBasedModuleResolution7_node.ts] //// + +//// [file1.ts] +import {x} from "./project/file2"; +import {y} from "module3"; + +declare function use(x: string); +use(x.toFixed()); +use(y.toFixed()); + +//// [file2.ts] +import {a} from "module1"; +import {b} from "templates/module2"; +import {x as c} from "../file3"; +export let x = a + b + c; + +//// [index.d.ts] +export let a: number + +//// [module2.ts] +export let b: number; + +//// [index.d.ts] +export let x: number; + +//// [module3.d.ts] +export let y: number; + + + +//// [module2.js] +"use strict"; +//// [file2.js] +"use strict"; +var module1_1 = require("module1"); +var module2_1 = require("templates/module2"); +var file3_1 = require("../file3"); +exports.x = module1_1.a + module2_1.b + file3_1.x; +//// [file1.js] +"use strict"; +var file2_1 = require("./project/file2"); +var module3_1 = require("module3"); +use(file2_1.x.toFixed()); +use(module3_1.y.toFixed()); diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution7_node.symbols b/tests/baselines/reference/pathMappingBasedModuleResolution7_node.symbols new file mode 100644 index 0000000000000..9cda76790ea01 --- /dev/null +++ b/tests/baselines/reference/pathMappingBasedModuleResolution7_node.symbols @@ -0,0 +1,57 @@ +=== c:/root/src/file1.ts === +import {x} from "./project/file2"; +>x : Symbol(x, Decl(file1.ts, 0, 8)) + +import {y} from "module3"; +>y : Symbol(y, Decl(file1.ts, 1, 8)) + +declare function use(x: string); +>use : Symbol(use, Decl(file1.ts, 1, 26)) +>x : Symbol(x, Decl(file1.ts, 3, 21)) + +use(x.toFixed()); +>use : Symbol(use, Decl(file1.ts, 1, 26)) +>x.toFixed : Symbol(Number.toFixed, Decl(lib.d.ts, --, --)) +>x : Symbol(x, Decl(file1.ts, 0, 8)) +>toFixed : Symbol(Number.toFixed, Decl(lib.d.ts, --, --)) + +use(y.toFixed()); +>use : Symbol(use, Decl(file1.ts, 1, 26)) +>y.toFixed : Symbol(Number.toFixed, Decl(lib.d.ts, --, --)) +>y : Symbol(y, Decl(file1.ts, 1, 8)) +>toFixed : Symbol(Number.toFixed, Decl(lib.d.ts, --, --)) + +=== c:/root/generated/src/project/file2.ts === +import {a} from "module1"; +>a : Symbol(a, Decl(file2.ts, 0, 8)) + +import {b} from "templates/module2"; +>b : Symbol(b, Decl(file2.ts, 1, 8)) + +import {x as c} from "../file3"; +>x : Symbol(c, Decl(file2.ts, 2, 8)) +>c : Symbol(c, Decl(file2.ts, 2, 8)) + +export let x = a + b + c; +>x : Symbol(x, Decl(file2.ts, 3, 10)) +>a : Symbol(a, Decl(file2.ts, 0, 8)) +>b : Symbol(b, Decl(file2.ts, 1, 8)) +>c : Symbol(c, Decl(file2.ts, 2, 8)) + +=== c:/shared/module1/index.d.ts === +export let a: number +>a : Symbol(a, Decl(index.d.ts, 0, 10)) + +=== c:/root/generated/src/templates/module2.ts === +export let b: number; +>b : Symbol(b, Decl(module2.ts, 0, 10)) + +=== c:/root/src/file3/index.d.ts === +export let x: number; +>x : Symbol(x, Decl(index.d.ts, 0, 10)) + +=== c:/node_modules/module3.d.ts === +export let y: number; +>y : Symbol(y, Decl(module3.d.ts, 0, 10)) + + diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution7_node.trace.json b/tests/baselines/reference/pathMappingBasedModuleResolution7_node.trace.json new file mode 100644 index 0000000000000..39d5c25c92a12 --- /dev/null +++ b/tests/baselines/reference/pathMappingBasedModuleResolution7_node.trace.json @@ -0,0 +1,123 @@ +[ + "======== Resolving module './project/file2' from 'c:/root/src/file1.ts'. ========", + "Module resolution kind is not specified, using 'NodeJs'.", + "'rootDirs' option is set, using it to resolve relative module name './project/file2'", + "Checking if 'c:/root/src/' is the longest matching prefix for 'c:/root/src/project/file2' - 'true'.", + "Checking if 'c:/root/generated/src/' is the longest matching prefix for 'c:/root/src/project/file2' - 'false'.", + "Longest matching prefix for 'c:/root/src/project/file2' is 'c:/root/src/'", + "Loading 'project/file2' from the root dir 'c:/root/src/', candidate location 'c:/root/src/project/file2'", + "Loading module as file / folder, candidate module location 'c:/root/src/project/file2'.", + "File 'c:/root/src/project/file2.ts' does not exist.", + "File 'c:/root/src/project/file2.tsx' does not exist.", + "File 'c:/root/src/project/file2.d.ts' does not exist.", + "File 'c:/root/src/project/file2/package.json' does not exist.", + "File 'c:/root/src/project/file2/index.ts' does not exist.", + "File 'c:/root/src/project/file2/index.tsx' does not exist.", + "File 'c:/root/src/project/file2/index.d.ts' does not exist.", + "Trying other entries in 'rootDirs'", + "Loading 'project/file2' from the root dir 'c:/root/generated/src', candidate location 'c:/root/generated/src/project/file2'", + "Loading module as file / folder, candidate module location 'c:/root/generated/src/project/file2'.", + "File 'c:/root/generated/src/project/file2.ts' exist - use it as a module resolution result.", + "======== Module name './project/file2' was successfully resolved to 'c:/root/generated/src/project/file2.ts'. ========", + "======== Resolving module 'module3' from 'c:/root/src/file1.ts'. ========", + "Module resolution kind is not specified, using 'NodeJs'.", + "'baseUrl' option is set to 'c:/root', using this value to resolve non-relative module name 'module3'", + "'paths' option is specified, looking for a pattern to match module name 'module3'.", + "Module name 'module3', matched pattern '*'.", + "Trying substitution '*', candidate module location: 'module3'.", + "Loading module as file / folder, candidate module location 'c:/root/module3'.", + "File 'c:/root/module3.ts' does not exist.", + "File 'c:/root/module3.tsx' does not exist.", + "File 'c:/root/module3.d.ts' does not exist.", + "File 'c:/root/module3/package.json' does not exist.", + "File 'c:/root/module3/index.ts' does not exist.", + "File 'c:/root/module3/index.tsx' does not exist.", + "File 'c:/root/module3/index.d.ts' does not exist.", + "Trying substitution 'c:/shared/*', candidate module location: 'c:/shared/module3'.", + "Loading module as file / folder, candidate module location 'c:/shared/module3'.", + "File 'c:/shared/module3.ts' does not exist.", + "File 'c:/shared/module3.tsx' does not exist.", + "File 'c:/shared/module3.d.ts' does not exist.", + "File 'c:/shared/module3/package.json' does not exist.", + "File 'c:/shared/module3/index.ts' does not exist.", + "File 'c:/shared/module3/index.tsx' does not exist.", + "File 'c:/shared/module3/index.d.ts' does not exist.", + "Loading module 'module3' from 'node_modules' folder.", + "File 'c:/root/src/node_modules/module3.ts' does not exist.", + "File 'c:/root/src/node_modules/module3.tsx' does not exist.", + "File 'c:/root/src/node_modules/module3.d.ts' does not exist.", + "File 'c:/root/src/node_modules/module3/package.json' does not exist.", + "File 'c:/root/src/node_modules/module3/index.ts' does not exist.", + "File 'c:/root/src/node_modules/module3/index.tsx' does not exist.", + "File 'c:/root/src/node_modules/module3/index.d.ts' does not exist.", + "File 'c:/root/node_modules/module3.ts' does not exist.", + "File 'c:/root/node_modules/module3.tsx' does not exist.", + "File 'c:/root/node_modules/module3.d.ts' does not exist.", + "File 'c:/root/node_modules/module3/package.json' does not exist.", + "File 'c:/root/node_modules/module3/index.ts' does not exist.", + "File 'c:/root/node_modules/module3/index.tsx' does not exist.", + "File 'c:/root/node_modules/module3/index.d.ts' does not exist.", + "File 'c:/node_modules/module3.ts' does not exist.", + "File 'c:/node_modules/module3.tsx' does not exist.", + "File 'c:/node_modules/module3.d.ts' exist - use it as a module resolution result.", + "======== Module name 'module3' was successfully resolved to 'c:/node_modules/module3.d.ts'. ========", + "======== Resolving module 'module1' from 'c:/root/generated/src/project/file2.ts'. ========", + "Module resolution kind is not specified, using 'NodeJs'.", + "'baseUrl' option is set to 'c:/root', using this value to resolve non-relative module name 'module1'", + "'paths' option is specified, looking for a pattern to match module name 'module1'.", + "Module name 'module1', matched pattern '*'.", + "Trying substitution '*', candidate module location: 'module1'.", + "Loading module as file / folder, candidate module location 'c:/root/module1'.", + "File 'c:/root/module1.ts' does not exist.", + "File 'c:/root/module1.tsx' does not exist.", + "File 'c:/root/module1.d.ts' does not exist.", + "File 'c:/root/module1/package.json' does not exist.", + "File 'c:/root/module1/index.ts' does not exist.", + "File 'c:/root/module1/index.tsx' does not exist.", + "File 'c:/root/module1/index.d.ts' does not exist.", + "Trying substitution 'c:/shared/*', candidate module location: 'c:/shared/module1'.", + "Loading module as file / folder, candidate module location 'c:/shared/module1'.", + "File 'c:/shared/module1.ts' does not exist.", + "File 'c:/shared/module1.tsx' does not exist.", + "File 'c:/shared/module1.d.ts' does not exist.", + "File 'c:/shared/module1/package.json' does not exist.", + "File 'c:/shared/module1/index.ts' does not exist.", + "File 'c:/shared/module1/index.tsx' does not exist.", + "File 'c:/shared/module1/index.d.ts' exist - use it as a module resolution result.", + "======== Module name 'module1' was successfully resolved to 'c:/shared/module1/index.d.ts'. ========", + "======== Resolving module 'templates/module2' from 'c:/root/generated/src/project/file2.ts'. ========", + "Module resolution kind is not specified, using 'NodeJs'.", + "'baseUrl' option is set to 'c:/root', using this value to resolve non-relative module name 'templates/module2'", + "'paths' option is specified, looking for a pattern to match module name 'templates/module2'.", + "Module name 'templates/module2', matched pattern 'templates/*'.", + "Trying substitution 'generated/src/templates/*', candidate module location: 'generated/src/templates/module2'.", + "Loading module as file / folder, candidate module location 'c:/root/generated/src/templates/module2'.", + "File 'c:/root/generated/src/templates/module2.ts' exist - use it as a module resolution result.", + "======== Module name 'templates/module2' was successfully resolved to 'c:/root/generated/src/templates/module2.ts'. ========", + "======== Resolving module '../file3' from 'c:/root/generated/src/project/file2.ts'. ========", + "Module resolution kind is not specified, using 'NodeJs'.", + "'rootDirs' option is set, using it to resolve relative module name '../file3'", + "Checking if 'c:/root/src/' is the longest matching prefix for 'c:/root/generated/src/file3' - 'false'.", + "Checking if 'c:/root/generated/src/' is the longest matching prefix for 'c:/root/generated/src/file3' - 'true'.", + "Longest matching prefix for 'c:/root/generated/src/file3' is 'c:/root/generated/src/'", + "Loading 'file3' from the root dir 'c:/root/generated/src/', candidate location 'c:/root/generated/src/file3'", + "Loading module as file / folder, candidate module location 'c:/root/generated/src/file3'.", + "File 'c:/root/generated/src/file3.ts' does not exist.", + "File 'c:/root/generated/src/file3.tsx' does not exist.", + "File 'c:/root/generated/src/file3.d.ts' does not exist.", + "File 'c:/root/generated/src/file3/package.json' does not exist.", + "File 'c:/root/generated/src/file3/index.ts' does not exist.", + "File 'c:/root/generated/src/file3/index.tsx' does not exist.", + "File 'c:/root/generated/src/file3/index.d.ts' does not exist.", + "Trying other entries in 'rootDirs'", + "Loading 'file3' from the root dir 'c:/root/src', candidate location 'c:/root/src/file3'", + "Loading module as file / folder, candidate module location 'c:/root/src/file3'.", + "File 'c:/root/src/file3.ts' does not exist.", + "File 'c:/root/src/file3.tsx' does not exist.", + "File 'c:/root/src/file3.d.ts' does not exist.", + "File 'c:/root/src/file3/package.json' does not exist.", + "File 'c:/root/src/file3/index.ts' does not exist.", + "File 'c:/root/src/file3/index.tsx' does not exist.", + "File 'c:/root/src/file3/index.d.ts' exist - use it as a module resolution result.", + "======== Module name '../file3' was successfully resolved to 'c:/root/src/file3/index.d.ts'. ========" +] \ No newline at end of file diff --git a/tests/baselines/reference/pathMappingBasedModuleResolution7_node.types b/tests/baselines/reference/pathMappingBasedModuleResolution7_node.types new file mode 100644 index 0000000000000..974f710b4c280 --- /dev/null +++ b/tests/baselines/reference/pathMappingBasedModuleResolution7_node.types @@ -0,0 +1,63 @@ +=== c:/root/src/file1.ts === +import {x} from "./project/file2"; +>x : number + +import {y} from "module3"; +>y : number + +declare function use(x: string); +>use : (x: string) => any +>x : string + +use(x.toFixed()); +>use(x.toFixed()) : any +>use : (x: string) => any +>x.toFixed() : string +>x.toFixed : (fractionDigits?: number) => string +>x : number +>toFixed : (fractionDigits?: number) => string + +use(y.toFixed()); +>use(y.toFixed()) : any +>use : (x: string) => any +>y.toFixed() : string +>y.toFixed : (fractionDigits?: number) => string +>y : number +>toFixed : (fractionDigits?: number) => string + +=== c:/root/generated/src/project/file2.ts === +import {a} from "module1"; +>a : number + +import {b} from "templates/module2"; +>b : number + +import {x as c} from "../file3"; +>x : number +>c : number + +export let x = a + b + c; +>x : number +>a + b + c : number +>a + b : number +>a : number +>b : number +>c : number + +=== c:/shared/module1/index.d.ts === +export let a: number +>a : number + +=== c:/root/generated/src/templates/module2.ts === +export let b: number; +>b : number + +=== c:/root/src/file3/index.d.ts === +export let x: number; +>x : number + +=== c:/node_modules/module3.d.ts === +export let y: number; +>y : number + + diff --git a/tests/baselines/reference/staticInstanceResolution5.errors.txt b/tests/baselines/reference/staticInstanceResolution5.errors.txt index 3c1cee93fd548..da6f0fde1433a 100644 --- a/tests/baselines/reference/staticInstanceResolution5.errors.txt +++ b/tests/baselines/reference/staticInstanceResolution5.errors.txt @@ -1,15 +1,21 @@ -tests/cases/compiler/staticInstanceResolution5_1.ts(1,24): error TS2307: Cannot find module 'staticInstanceResolution5_0.ts'. +tests/cases/compiler/staticInstanceResolution5_1.ts(4,14): error TS2304: Cannot find name 'WinJS'. +tests/cases/compiler/staticInstanceResolution5_1.ts(5,23): error TS2304: Cannot find name 'WinJS'. +tests/cases/compiler/staticInstanceResolution5_1.ts(6,16): error TS2304: Cannot find name 'WinJS'. -==== tests/cases/compiler/staticInstanceResolution5_1.ts (1 errors) ==== +==== tests/cases/compiler/staticInstanceResolution5_1.ts (3 errors) ==== import WinJS = require('staticInstanceResolution5_0.ts'); - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2307: Cannot find module 'staticInstanceResolution5_0.ts'. // these 3 should be errors var x = (w1: WinJS) => { }; + ~~~~~ +!!! error TS2304: Cannot find name 'WinJS'. var y = function (w2: WinJS) { } + ~~~~~ +!!! error TS2304: Cannot find name 'WinJS'. function z(w3: WinJS) { } + ~~~~~ +!!! error TS2304: Cannot find name 'WinJS'. ==== tests/cases/compiler/staticInstanceResolution5_0.ts (0 errors) ==== export class Promise { diff --git a/tests/baselines/reference/staticInstanceResolution5.js b/tests/baselines/reference/staticInstanceResolution5.js index 58def522978b3..0809d1af5f059 100644 --- a/tests/baselines/reference/staticInstanceResolution5.js +++ b/tests/baselines/reference/staticInstanceResolution5.js @@ -16,6 +16,19 @@ var y = function (w2: WinJS) { } function z(w3: WinJS) { } +//// [staticInstanceResolution5_0.js] +define(["require", "exports"], function (require, exports) { + "use strict"; + var Promise = (function () { + function Promise() { + } + Promise.timeout = function (delay) { + return null; + }; + return Promise; + }()); + exports.Promise = Promise; +}); //// [staticInstanceResolution5_1.js] define(["require", "exports"], function (require, exports) { "use strict"; diff --git a/tests/cases/compiler/pathMappingBasedModuleResolution1_classic.ts b/tests/cases/compiler/pathMappingBasedModuleResolution1_classic.ts new file mode 100644 index 0000000000000..20845a49372ab --- /dev/null +++ b/tests/cases/compiler/pathMappingBasedModuleResolution1_classic.ts @@ -0,0 +1,19 @@ +// @module: amd +// @traceModuleResolution: true + +// paths should error in the absence of baseurl + +// @filename: c:/root/tsconfig.json +{ + "compilerOptions": { + "paths": { + "*": [ + "*", + "generated/*" + ] + } + } +} + +// @filename: c:/root/f1.ts +export var x = 1; diff --git a/tests/cases/compiler/pathMappingBasedModuleResolution1_node.ts b/tests/cases/compiler/pathMappingBasedModuleResolution1_node.ts new file mode 100644 index 0000000000000..392e85bd7c39c --- /dev/null +++ b/tests/cases/compiler/pathMappingBasedModuleResolution1_node.ts @@ -0,0 +1,18 @@ +// @module: commonjs +// @traceModuleResolution: true + +// paths should error in the absence of baseurl +// @filename: c:/root/tsconfig.json +{ + "compilerOptions": { + "paths": { + "*": [ + "*", + "generated/*" + ] + } + } +} + +// @filename: c:/root/f1.ts +export var x = 1; diff --git a/tests/cases/compiler/pathMappingBasedModuleResolution2_classic.ts b/tests/cases/compiler/pathMappingBasedModuleResolution2_classic.ts new file mode 100644 index 0000000000000..6c84a197eeb13 --- /dev/null +++ b/tests/cases/compiler/pathMappingBasedModuleResolution2_classic.ts @@ -0,0 +1,18 @@ +// @module: amd +// @traceModuleResolution: true + +// baseurl is defined in tsconfig.json +// paths has errors + +// @filename: root/tsconfig.json +{ + "compilerOptions": { + "baseUrl": "./src", + "paths": { + "*1*": [ "*2*" ] + } + } +} + +// @filename: root/src/folder1/file1.ts +export var x = 1; \ No newline at end of file diff --git a/tests/cases/compiler/pathMappingBasedModuleResolution2_node.ts b/tests/cases/compiler/pathMappingBasedModuleResolution2_node.ts new file mode 100644 index 0000000000000..78ef7215e737e --- /dev/null +++ b/tests/cases/compiler/pathMappingBasedModuleResolution2_node.ts @@ -0,0 +1,18 @@ +// @module: commonjs +// @traceModuleResolution: true + +// baseurl is defined in tsconfig.json +// paths has errors + +// @filename: root/tsconfig.json +{ + "compilerOptions": { + "baseUrl": "./src", + "paths": { + "*1*": [ "*2*" ] + } + } +} + +// @filename: root/src/folder1/file1.ts +export var x = 1; \ No newline at end of file diff --git a/tests/cases/compiler/pathMappingBasedModuleResolution3_classic.ts b/tests/cases/compiler/pathMappingBasedModuleResolution3_classic.ts new file mode 100644 index 0000000000000..d46308d089fb0 --- /dev/null +++ b/tests/cases/compiler/pathMappingBasedModuleResolution3_classic.ts @@ -0,0 +1,22 @@ +// @moduleResolution: classic +// @module: amd +// @baseUrl: c:/root +// @traceModuleResolution: true + +// baseUrl set via command line + +// @filename: c:/root/folder1/file1.ts +import {x} from "folder2/file2" +declare function use(a: any): void; +use(x.toExponential()); + +// @filename: c:/root/folder2/file2.ts +import {x as a} from "./file3" // found with baseurl +import {y as b} from "file4" // found with fallback +export var x = a + b; + +// @filename: c:/root/folder2/file3.ts +export var x = 1; + +// @filename: c:/file4.ts +export var y = 100; \ No newline at end of file diff --git a/tests/cases/compiler/pathMappingBasedModuleResolution3_node.ts b/tests/cases/compiler/pathMappingBasedModuleResolution3_node.ts new file mode 100644 index 0000000000000..30e95c9303ee6 --- /dev/null +++ b/tests/cases/compiler/pathMappingBasedModuleResolution3_node.ts @@ -0,0 +1,22 @@ +// @moduleResolution: node +// @module: commonjs +// @baseUrl: c:/root +// @traceModuleResolution: true + +// baseUrl set via command line + +// @filename: c:/root/folder1/file1.ts +import {x} from "folder2/file2" +declare function use(a: any): void; +use(x.toExponential()); + +// @filename: c:/root/folder2/file2.ts +import {x as a} from "./file3" // found with baseurl +import {y as b} from "file4" // found with fallback +export var x = a + b; + +// @filename: c:/root/folder2/file3.ts +export var x = 1; + +// @filename: c:/node_modules/file4/index.d.ts +export var y: number; \ No newline at end of file diff --git a/tests/cases/compiler/pathMappingBasedModuleResolution4_classic.ts b/tests/cases/compiler/pathMappingBasedModuleResolution4_classic.ts new file mode 100644 index 0000000000000..723de05b70c14 --- /dev/null +++ b/tests/cases/compiler/pathMappingBasedModuleResolution4_classic.ts @@ -0,0 +1,28 @@ +// @moduleResolution: classic +// @module: amd +// @traceModuleResolution: true + +// baseUrl set via command line + +// @filename: c:/root/tsconfig.json +{ + "compilerOptions": { + "baseUrl": "." + } +} + +// @filename: c:/root/folder1/file1.ts +import {x} from "folder2/file2" +declare function use(a: any): void; +use(x.toExponential()); + +// @filename: c:/root/folder2/file2.ts +import {x as a} from "./file3" // found with baseurl +import {y as b} from "file4" // found with fallback +export var x = a + b; + +// @filename: c:/root/folder2/file3.ts +export var x = 1; + +// @filename: c:/file4.ts +export var y = 100; \ No newline at end of file diff --git a/tests/cases/compiler/pathMappingBasedModuleResolution4_node.ts b/tests/cases/compiler/pathMappingBasedModuleResolution4_node.ts new file mode 100644 index 0000000000000..e68635e205e57 --- /dev/null +++ b/tests/cases/compiler/pathMappingBasedModuleResolution4_node.ts @@ -0,0 +1,28 @@ +// @moduleResolution: node +// @module: commonjs +// @traceModuleResolution: true + +// baseUrl set via command line + +// @filename: c:/root/tsconfig.json +{ + "compilerOptions": { + "baseUrl": "." + } +} + +// @filename: c:/root/folder1/file1.ts +import {x} from "folder2/file2" +declare function use(a: any): void; +use(x.toExponential()); + +// @filename: c:/root/folder2/file2.ts +import {x as a} from "./file3" // found with baseurl +import {y as b} from "file4" // found with fallback +export var x = a + b; + +// @filename: c:/root/folder2/file3.ts +export var x = 1; + +// @filename: c:/node_modules/file4/index.d.ts +export var y: number; \ No newline at end of file diff --git a/tests/cases/compiler/pathMappingBasedModuleResolution5_classic.ts b/tests/cases/compiler/pathMappingBasedModuleResolution5_classic.ts new file mode 100644 index 0000000000000..a7662688e373a --- /dev/null +++ b/tests/cases/compiler/pathMappingBasedModuleResolution5_classic.ts @@ -0,0 +1,43 @@ +// @module: amd +// @traceModuleResolution: true + +// paths is defined in tsconfig.json +// @filename: c:/root/tsconfig.json +{ + "compilerOptions": { + "baseUrl": ".", + "paths": { + "*": [ + "*", + "generated/*" + ], + "components/*": [ + "shared/components/*" + ] + } + } +} +// @filename: c:/root/folder1/file1.ts +import {x} from "folder2/file1" +import {y} from "folder3/file2" +import {z} from "components/file3" +import {z1} from "file4" + +declare function use(a: any): void; + +use(x.toExponential()); +use(y.toExponential()); +use(z.toExponential()); +use(z1.toExponential()); + +// @filename: c:/root/folder2/file1.ts +export var x = 1; + +// @filename: c:/root/generated/folder3/file2.ts +export var y = 1; + +// @filename: c:/root/shared/components/file3.ts +export var z = 1; + +// @filename: c:/file4.ts +export var z1 = 1; \ No newline at end of file diff --git a/tests/cases/compiler/pathMappingBasedModuleResolution5_node.ts b/tests/cases/compiler/pathMappingBasedModuleResolution5_node.ts new file mode 100644 index 0000000000000..ef5ef0afd6a52 --- /dev/null +++ b/tests/cases/compiler/pathMappingBasedModuleResolution5_node.ts @@ -0,0 +1,43 @@ +// @module: commonjs +// @traceModuleResolution: true + +// paths is defined in tsconfig.json +// @filename: c:/root/tsconfig.json +{ + "compilerOptions": { + "baseUrl": ".", + "paths": { + "*": [ + "*", + "generated/*" + ], + "components/*": [ + "shared/components/*" + ] + } + } +} +// @filename: c:/root/folder1/file1.ts +import {x} from "folder2/file1" +import {y} from "folder3/file2" +import {z} from "components/file3" +import {z1} from "file4" + +declare function use(a: any): void; + +use(x.toExponential()); +use(y.toExponential()); +use(z.toExponential()); +use(z1.toExponential()); + +// @filename: c:/root/folder2/file1.ts +export var x = 1; + +// @filename: c:/root/generated/folder3/file2.ts +export var y = 1; + +// @filename: c:/root/shared/components/file3/index.d.ts +export var z: number; + +// @filename: c:/node_modules/file4.ts +export var z1 = 1; \ No newline at end of file diff --git a/tests/cases/compiler/pathMappingBasedModuleResolution6_classic.ts b/tests/cases/compiler/pathMappingBasedModuleResolution6_classic.ts new file mode 100644 index 0000000000000..adaba8478c997 --- /dev/null +++ b/tests/cases/compiler/pathMappingBasedModuleResolution6_classic.ts @@ -0,0 +1,23 @@ +// @module: amd +// @traceModuleResolution: true + +// @filename: c:/root/src/tsconfig.json +{ + "compilerOptions": { + "rootDirs": [ + ".", + "../generated/src" + ] + } +} + +// @filename: c:/root/src/file1.ts +import {x} from "./project/file3"; +declare function use(x: string); +use(x.toExponential()); + +// @filename: c:/root/src/file2.d.ts +export let x: number; + +// @filename: c:/root/generated/src/project/file3.ts +export {x} from "../file2"; \ No newline at end of file diff --git a/tests/cases/compiler/pathMappingBasedModuleResolution6_node.ts b/tests/cases/compiler/pathMappingBasedModuleResolution6_node.ts new file mode 100644 index 0000000000000..a3d0feadf7c9e --- /dev/null +++ b/tests/cases/compiler/pathMappingBasedModuleResolution6_node.ts @@ -0,0 +1,23 @@ +// @module: commonjs +// @traceModuleResolution: true + +// @filename: c:/root/src/tsconfig.json +{ + "compilerOptions": { + "rootDirs": [ + ".", + "../generated/src" + ] + } +} + +// @filename: c:/root/src/file1.ts +import {x} from "./project/file3"; +declare function use(x: string); +use(x.toFixed()); + +// @filename: c:/root/src/file2/index.d.ts +export let x: number; + +// @filename: c:/root/generated/src/project/file3.ts +export {x} from "../file2"; \ No newline at end of file diff --git a/tests/cases/compiler/pathMappingBasedModuleResolution7_classic.ts b/tests/cases/compiler/pathMappingBasedModuleResolution7_classic.ts new file mode 100644 index 0000000000000..af092df5ce95f --- /dev/null +++ b/tests/cases/compiler/pathMappingBasedModuleResolution7_classic.ts @@ -0,0 +1,49 @@ +// @module: amd +// @traceModuleResolution: true + +// @filename: c:/root/src/tsconfig.json +{ + "compilerOptions": { + "baseUrl": "../", + "paths": { + "*": [ + "*", + "c:/shared/*" + ], + "templates/*": [ + "generated/src/templates/*" + ] + }, + "rootDirs": [ + ".", + "../generated/src" + ] + } +} + +// @filename: c:/root/src/file1.ts +import {x} from "./project/file2"; +import {y} from "module3"; + +declare function use(x: string); +use(x.toFixed()); +use(y.toFixed()); + +// @filename: c:/root/generated/src/project/file2.ts +import {a} from "module1"; +import {b} from "templates/module2"; +import {x as c} from "../file3"; +export let x = a + b + c; + +// @filename: c:/shared/module1.d.ts +export let a: number + +// @filename: c:/root/generated/src/templates/module2.ts +export let b: number; + +// @filename: c:/root/src/file3.d.ts +export let x: number; + +// @filename: c:/module3.d.ts +export let y: number; + diff --git a/tests/cases/compiler/pathMappingBasedModuleResolution7_node.ts b/tests/cases/compiler/pathMappingBasedModuleResolution7_node.ts new file mode 100644 index 0000000000000..faecbe4adb91e --- /dev/null +++ b/tests/cases/compiler/pathMappingBasedModuleResolution7_node.ts @@ -0,0 +1,49 @@ +// @module: commonjs +// @traceModuleResolution: true + +// @filename: c:/root/src/tsconfig.json +{ + "compilerOptions": { + "baseUrl": "../", + "paths": { + "*": [ + "*", + "c:/shared/*" + ], + "templates/*": [ + "generated/src/templates/*" + ] + }, + "rootDirs": [ + ".", + "../generated/src" + ] + } +} + +// @filename: c:/root/src/file1.ts +import {x} from "./project/file2"; +import {y} from "module3"; + +declare function use(x: string); +use(x.toFixed()); +use(y.toFixed()); + +// @filename: c:/root/generated/src/project/file2.ts +import {a} from "module1"; +import {b} from "templates/module2"; +import {x as c} from "../file3"; +export let x = a + b + c; + +// @filename: c:/shared/module1/index.d.ts +export let a: number + +// @filename: c:/root/generated/src/templates/module2.ts +export let b: number; + +// @filename: c:/root/src/file3/index.d.ts +export let x: number; + +// @filename: c:/node_modules/module3.d.ts +export let y: number; + diff --git a/tests/cases/unittests/cachingInServerLSHost.ts b/tests/cases/unittests/cachingInServerLSHost.ts index 88b44a693b940..59f97f434e6cc 100644 --- a/tests/cases/unittests/cachingInServerLSHost.ts +++ b/tests/cases/unittests/cachingInServerLSHost.ts @@ -7,6 +7,10 @@ module ts { } function createDefaultServerHost(fileMap: Map): server.ServerHost { + const directories: Map = {}; + for (const f in fileMap) { + directories[getDirectoryPath(f)] = f; + } return { args: [], newLine: "\r\n", @@ -26,7 +30,7 @@ module ts { return hasProperty(fileMap, path); }, directoryExists: (path: string): boolean => { - throw new Error("NYI"); + return hasProperty(directories, path); }, createDirectory: (path: string) => { }, diff --git a/tests/cases/unittests/moduleResolution.ts b/tests/cases/unittests/moduleResolution.ts index 81d7c5f8b2e2f..6bbbdcc90b49a 100644 --- a/tests/cases/unittests/moduleResolution.ts +++ b/tests/cases/unittests/moduleResolution.ts @@ -459,6 +459,446 @@ import b = require("./moduleB.ts"); }) }); + describe("baseUrl augmented module resolution", () => { + + it("module resolution without path mappings/rootDirs", () => { + test(/*hasDirectoryExists*/ false); + test(/*hasDirectoryExists*/ true); + + function test(hasDirectoryExists: boolean) { + const file1: File = { name: "/root/folder1/file1.ts" }; + const file2: File = { name: "/root/folder2/file2.ts" }; + const file3: File = { name: "/root/folder2/file3.ts" }; + const host = createModuleResolutionHost(hasDirectoryExists, file1, file2, file3); + for (const moduleResolution of [ ModuleResolutionKind.NodeJs, ModuleResolutionKind.Classic ]) { + const options: CompilerOptions = { moduleResolution, baseUrl: "/root" }; + { + const result = resolveModuleName("folder2/file2", file1.name, options, host); + assert.isTrue(result.resolvedModule !== undefined, "module should be resolved"); + assert.equal(result.resolvedModule.resolvedFileName, file2.name); + assert.deepEqual(result.failedLookupLocations, []); + } + { + const result = resolveModuleName("./file3", file2.name, options, host); + assert.isTrue(result.resolvedModule !== undefined, "module should be resolved"); + assert.equal(result.resolvedModule.resolvedFileName, file3.name); + assert.deepEqual(result.failedLookupLocations, []); + } + { + const result = resolveModuleName("/root/folder1/file1", file2.name, options, host); + assert.isTrue(result.resolvedModule !== undefined, "module should be resolved"); + assert.equal(result.resolvedModule.resolvedFileName, file1.name); + assert.deepEqual(result.failedLookupLocations, []); + } + } + } + // add failure tests + }); + + it("node + baseUrl", () => { + test(/*hasDirectoryExists*/ false); + test(/*hasDirectoryExists*/ true); + + function test(hasDirectoryExists: boolean) { + const main: File = { name: "/root/a/b/main.ts" }; + const m1: File = { name: "/root/m1.ts" }; // load file as module + const m2: File = { name: "/root/m2/index.d.ts" }; // load folder as module + const m3: File = { name: "/root/m3/package.json", content: JSON.stringify({ typings: "dist/typings.d.ts" }) }; + const m3Typings: File = { name: "/root/m3/dist/typings.d.ts" }; + const m4: File = { name: "/root/node_modules/m4.ts" }; // fallback to node + + const options: CompilerOptions = { moduleResolution: ModuleResolutionKind.NodeJs, baseUrl: "/root" }; + const host = createModuleResolutionHost(hasDirectoryExists, main, m1, m2, m3, m3Typings, m4); + + check("m1", main, m1); + check("m2", main, m2); + check("m3", main, m3Typings); + check("m4", main, m4); + + function check(name: string, caller: File, expected: File) { + const result = resolveModuleName(name, caller.name, options, host); + assert.isTrue(result.resolvedModule !== undefined); + assert.equal(result.resolvedModule.resolvedFileName, expected.name); + } + } + }); + + it("classic + baseUrl", () => { + test(/*hasDirectoryExists*/ false); + test(/*hasDirectoryExists*/ true); + + function test(hasDirectoryExists: boolean) { + const main: File = { name: "/root/a/b/main.ts" }; + const m1: File = { name: "/root/x/m1.ts" }; // load from base url + const m2: File = { name: "/m2.ts" }; // fallback to classic + + const options: CompilerOptions = { moduleResolution: ModuleResolutionKind.Classic, baseUrl: "/root/x" }; + const host = createModuleResolutionHost(hasDirectoryExists, main, m1, m2); + + check("m1", main, m1); + check("m2", main, m2); + + function check(name: string, caller: File, expected: File) { + const result = resolveModuleName(name, caller.name, options, host); + assert.isTrue(result.resolvedModule !== undefined); + assert.equal(result.resolvedModule.resolvedFileName, expected.name); + } + } + }) + + it("node + baseUrl + path mappings", () => { + test(/*hasDirectoryExists*/ false); + test(/*hasDirectoryExists*/ true); + + function test(hasDirectoryExists: boolean) { + const main: File = { name: "/root/folder1/main.ts" }; + + const file1: File = { name: "/root/folder1/file1.ts" }; + const file2: File = { name: "/root/generated/folder1/file2.ts" } // load remapped file as module + const file3: File = { name: "/root/generated/folder2/file3/index.d.ts" } // load folder a module + const file4Typings: File = { name: "/root/generated/folder2/file4/package.json", content: JSON.stringify({ typings: "dist/types.d.ts" })}; + const file4: File = { name: "/root/generated/folder2/file4/dist/types.d.ts" }; // load file pointed by typings + const file5: File = { name: "/root/someanotherfolder/file5/index.d.ts" } // load remapped module from folder + const file6: File = { name: "/root/node_modules/file6.ts" }; // fallback to node + const host = createModuleResolutionHost(hasDirectoryExists, file1, file2, file3, file4, file4Typings, file5, file6); + + const options: CompilerOptions = { + moduleResolution: ModuleResolutionKind.NodeJs, + baseUrl: "/root", + paths: { + "*": [ + "*", + "generated/*" + ], + "somefolder/*": [ + "someanotherfolder/*" + ] + } + }; + check("folder1/file1", file1, []); + check("folder1/file2", file2, [ + // first try the '*' + "/root/folder1/file2.ts", + "/root/folder1/file2.tsx", + "/root/folder1/file2.d.ts", + "/root/folder1/file2/package.json", + "/root/folder1/file2/index.ts", + "/root/folder1/file2/index.tsx", + "/root/folder1/file2/index.d.ts" + // then first attempt on 'generated/*' was successful + ]); + check("folder2/file3", file3, [ + // first try '*' + "/root/folder2/file3.ts", + "/root/folder2/file3.tsx", + "/root/folder2/file3.d.ts", + "/root/folder2/file3/package.json", + "/root/folder2/file3/index.ts", + "/root/folder2/file3/index.tsx", + "/root/folder2/file3/index.d.ts", + // then use remapped location + "/root/generated/folder2/file3.ts", + "/root/generated/folder2/file3.tsx", + "/root/generated/folder2/file3.d.ts", + "/root/generated/folder2/file3/package.json", + "/root/generated/folder2/file3/index.ts", + "/root/generated/folder2/file3/index.tsx", + // success on index.d.ts + ]); + check("folder2/file4", file4, [ + // first try '*' + "/root/folder2/file4.ts", + "/root/folder2/file4.tsx", + "/root/folder2/file4.d.ts", + "/root/folder2/file4/package.json", + "/root/folder2/file4/index.ts", + "/root/folder2/file4/index.tsx", + "/root/folder2/file4/index.d.ts", + // try to load from file from remapped location + "/root/generated/folder2/file4.ts", + "/root/generated/folder2/file4.tsx", + "/root/generated/folder2/file4.d.ts" + // success on loading as from folder + ]); + check("somefolder/file5", file5, [ + // load from remapped location + // first load from fle + "/root/someanotherfolder/file5.ts", + "/root/someanotherfolder/file5.tsx", + "/root/someanotherfolder/file5.d.ts", + // load from folder + "/root/someanotherfolder/file5/package.json", + "/root/someanotherfolder/file5/index.ts", + "/root/someanotherfolder/file5/index.tsx", + // success on index.d.ts + ]); + check("file6", file6, [ + // first try * + // load from file + "/root/file6.ts", + "/root/file6.tsx", + "/root/file6.d.ts", + // load from folder + "/root/file6/package.json", + "/root/file6/index.ts", + "/root/file6/index.tsx", + "/root/file6/index.d.ts", + // then try 'generated/*' + // load from file + "/root/generated/file6.ts", + "/root/generated/file6.tsx", + "/root/generated/file6.d.ts", + // load from folder + "/root/generated/file6/package.json", + "/root/generated/file6/index.ts", + "/root/generated/file6/index.tsx", + "/root/generated/file6/index.d.ts", + // fallback to standard node behavior + // load from file + "/root/folder1/node_modules/file6.ts", + "/root/folder1/node_modules/file6.tsx", + "/root/folder1/node_modules/file6.d.ts", + // load from folder + "/root/folder1/node_modules/file6/package.json", + "/root/folder1/node_modules/file6/index.ts", + "/root/folder1/node_modules/file6/index.tsx", + "/root/folder1/node_modules/file6/index.d.ts", + // success on /root/node_modules/file6.ts + ]); + + function check(name: string, expected: File, expectedFailedLookups: string[]) { + const result = resolveModuleName(name, main.name, options, host); + assert.isTrue(result.resolvedModule !== undefined, "module should be resolved"); + assert.equal(result.resolvedModule.resolvedFileName, expected.name); + assert.deepEqual(result.failedLookupLocations, expectedFailedLookups); + } + } + }); + + it ("classic + baseUrl + path mappings", () => { + test(/*hasDirectoryExists*/ false); + test(/*hasDirectoryExists*/ true); + + function test(hasDirectoryExists: boolean) { + const main: File = { name: "/root/folder1/main.ts" }; + + const file1: File = { name: "/root/folder1/file1.ts" }; + const file2: File = { name: "/root/generated/folder1/file2.ts" }; + const file3: File = { name: "/folder1/file3.ts" }; // fallback to classic + const host = createModuleResolutionHost(hasDirectoryExists, file1, file2, file3); + + const options: CompilerOptions = { + moduleResolution: ModuleResolutionKind.Classic, + baseUrl: "/root", + paths: { + "*": [ + "*", + "generated/*" + ], + "somefolder/*": [ + "someanotherfolder/*" + ] + } + }; + check("folder1/file1", file1, []); + check("folder1/file2", file2, [ + // first try '*' + "/root/folder1/file2.ts", + "/root/folder1/file2.tsx", + "/root/folder1/file2.d.ts", + // success when using 'generated/*' + ]); + check("folder1/file3", file3, [ + // first try '*' + "/root/folder1/file3.ts", + "/root/folder1/file3.tsx", + "/root/folder1/file3.d.ts", + // then try 'generated/*' + "/root/generated/folder1/file3.ts", + "/root/generated/folder1/file3.tsx", + "/root/generated/folder1/file3.d.ts", + // fallback to classic + "/root/folder1/folder1/file3.ts", + "/root/folder1/folder1/file3.tsx", + "/root/folder1/folder1/file3.d.ts", + "/root/folder1/file3.ts", + "/root/folder1/file3.tsx", + "/root/folder1/file3.d.ts", + ]); + + function check(name: string, expected: File, expectedFailedLookups: string[]) { + const result = resolveModuleName(name, main.name, options, host); + assert.isTrue(result.resolvedModule !== undefined, "module should be resolved"); + assert.equal(result.resolvedModule.resolvedFileName, expected.name); + assert.deepEqual(result.failedLookupLocations, expectedFailedLookups); + } + } + }) + + it ("node + rootDirs", () => { + test(/*hasDirectoryExists*/ false); + test(/*hasDirectoryExists*/ true); + + function test(hasDirectoryExists: boolean) { + let file1: File = { name: "/root/folder1/file1.ts" }; + let file1_1: File = { name: "/root/folder1/file1_1/index.d.ts" }; + let file2: File = { name: "/root/generated/folder1/file2.ts" }; + let file3: File = { name: "/root/generated/folder2/file3.ts" }; + const host = createModuleResolutionHost(hasDirectoryExists, file1, file1_1, file2, file3); + const options: CompilerOptions = { + moduleResolution: ModuleResolutionKind.NodeJs, + rootDirs: [ + "/root", + "/root/generated/" + ] + }; + check("./file2", file1, file2, [ + // first try current location + // load from file + "/root/folder1/file2.ts", + "/root/folder1/file2.tsx", + "/root/folder1/file2.d.ts", + // load from folder + "/root/folder1/file2/package.json", + "/root/folder1/file2/index.ts", + "/root/folder1/file2/index.tsx", + "/root/folder1/file2/index.d.ts", + // success after using alternative rootDir entry + ]); + check("../folder1/file1", file3, file1, [ + // first try current location + // load from file + "/root/generated/folder1/file1.ts", + "/root/generated/folder1/file1.tsx", + "/root/generated/folder1/file1.d.ts", + // load from module + "/root/generated/folder1/file1/package.json", + "/root/generated/folder1/file1/index.ts", + "/root/generated/folder1/file1/index.tsx", + "/root/generated/folder1/file1/index.d.ts", + // success after using alternative rootDir entry + ]); + check("../folder1/file1_1", file3, file1_1, [ + // first try current location + // load from file + "/root/generated/folder1/file1_1.ts", + "/root/generated/folder1/file1_1.tsx", + "/root/generated/folder1/file1_1.d.ts", + // load from folder + "/root/generated/folder1/file1_1/package.json", + "/root/generated/folder1/file1_1/index.ts", + "/root/generated/folder1/file1_1/index.tsx", + "/root/generated/folder1/file1_1/index.d.ts", + // try alternative rootDir entry + // load from file + "/root/folder1/file1_1.ts", + "/root/folder1/file1_1.tsx", + "/root/folder1/file1_1.d.ts", + // load from directory + "/root/folder1/file1_1/package.json", + "/root/folder1/file1_1/index.ts", + "/root/folder1/file1_1/index.tsx", + // success on loading '/root/folder1/file1_1/index.d.ts' + ]); + + function check(name: string, container: File, expected: File, expectedFailedLookups: string[]) { + const result = resolveModuleName(name, container.name, options, host); + assert.isTrue(result.resolvedModule !== undefined, "module should be resolved"); + assert.equal(result.resolvedModule.resolvedFileName, expected.name); + assert.deepEqual(result.failedLookupLocations,expectedFailedLookups); + } + } + }); + + it ("classic + rootDirs", () => { + test(/*hasDirectoryExists*/ false); + test(/*hasDirectoryExists*/ true); + + function test(hasDirectoryExists: boolean) { + let file1: File = { name: "/root/folder1/file1.ts" }; + let file2: File = { name: "/root/generated/folder1/file2.ts" }; + let file3: File = { name: "/root/generated/folder2/file3.ts" }; + let file4: File = { name: "/folder1/file1_1.ts" }; + const host = createModuleResolutionHost(hasDirectoryExists, file1, file2, file3, file4); + const options: CompilerOptions = { + moduleResolution: ModuleResolutionKind.Classic, + rootDirs: [ + "/root", + "/root/generated/" + ] + }; + check("./file2", file1, file2, [ + // first load from current location + "/root/folder1/file2.ts", + "/root/folder1/file2.tsx", + "/root/folder1/file2.d.ts", + // then try alternative rootDir entry + ]); + check("../folder1/file1", file3, file1, [ + // first load from current location + "/root/generated/folder1/file1.ts", + "/root/generated/folder1/file1.tsx", + "/root/generated/folder1/file1.d.ts", + // then try alternative rootDir entry + ]); + check("../folder1/file1_1", file3, file4, [ + // load from initial location + "/root/generated/folder1/file1_1.ts", + "/root/generated/folder1/file1_1.tsx", + "/root/generated/folder1/file1_1.d.ts", + // load from alternative rootDir entry + "/root/folder1/file1_1.ts", + "/root/folder1/file1_1.tsx", + "/root/folder1/file1_1.d.ts", + // fallback to classic + // step1: initial location + "/root/generated/folder1/file1_1.ts", + "/root/generated/folder1/file1_1.tsx", + "/root/generated/folder1/file1_1.d.ts", + // step2: walk 1 level up + "/root/folder1/file1_1.ts", + "/root/folder1/file1_1.tsx", + "/root/folder1/file1_1.d.ts", + ]); + + function check(name: string, container: File, expected: File, expectedFailedLookups: string[]) { + const result = resolveModuleName(name, container.name, options, host); + assert.isTrue(result.resolvedModule !== undefined, "module should be resolved"); + assert.equal(result.resolvedModule.resolvedFileName, expected.name); + assert.deepEqual(result.failedLookupLocations,expectedFailedLookups); + } + } + }); + + it ("nested node module", () => { + test(/*hasDirectoryExists*/ false); + test(/*hasDirectoryExists*/ true); + + function test(hasDirectoryExists: boolean) { + const app: File = { name: "/root/src/app.ts" } + const libsPackage: File = { name: "/root/src/libs/guid/package.json", content: JSON.stringify({ typings: "dist/guid.d.ts" }) }; + const libsTypings: File = { name: "/root/src/libs/guid/dist/guid.d.ts" }; + const host = createModuleResolutionHost(hasDirectoryExists, app, libsPackage, libsTypings); + const options: CompilerOptions = { + moduleResolution: ModuleResolutionKind.NodeJs, + baseUrl: "/root", + paths: { + "libs/guid": [ "src/libs/guid" ] + } + }; + const result = resolveModuleName("libs/guid", app.name, options, host); + assert.isTrue(result.resolvedModule !== undefined, "module should be resolved"); + assert.equal(result.resolvedModule.resolvedFileName, libsTypings.name); + assert.deepEqual(result.failedLookupLocations, [ + // first try to load module as file + "/root/src/libs/guid.ts", + "/root/src/libs/guid.tsx", + "/root/src/libs/guid.d.ts", + ]); + } + }) + }); + function notImplemented(name: string): () => any { return () => assert(`${name} is not implemented and should not be called`); }