diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 91653c140c83e..af0fe5430c652 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -58,6 +58,7 @@ namespace ts { let symbolInstantiationDepth = 0; const emptySymbols = createSymbolTable(); + const identityMapper: (type: Type) => Type = identity; const compilerOptions = host.getCompilerOptions(); const languageVersion = getEmitScriptTarget(compilerOptions); @@ -8113,10 +8114,6 @@ namespace ts { mapper; } - function identityMapper(type: Type): Type { - return type; - } - function combineTypeMappers(mapper1: TypeMapper, mapper2: TypeMapper): TypeMapper { return t => instantiateType(mapper1(t), mapper2); } diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index dc9c2ad35ede6..54e5ee1d01dbc 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -1385,6 +1385,12 @@ namespace ts { return x === undefined || x === null; } + function directoryOfCombinedPath(fileName: string, basePath: string) { + // Use the `identity` function to avoid canonicalizing the path, as it must remain noncanonical + // until consistient casing errors are reported + return getDirectoryPath(toPath(fileName, basePath, identity)); + } + /** * Parse the contents of a config file from json or json source file (tsconfig.json). * @param json The contents of the config file to parse @@ -1467,7 +1473,7 @@ namespace ts { includeSpecs = ["**/*"]; } - const result = matchFileNames(fileNames, includeSpecs, excludeSpecs, configFileName ? getDirectoryPath(toPath(configFileName, basePath, createGetCanonicalFileName(host.useCaseSensitiveFileNames))) : basePath, options, host, errors, extraFileExtensions, sourceFile); + const result = matchFileNames(fileNames, includeSpecs, excludeSpecs, configFileName ? directoryOfCombinedPath(configFileName, basePath) : basePath, options, host, errors, extraFileExtensions, sourceFile); if (result.fileNames.length === 0 && !hasProperty(raw, "files") && resolutionStack.length === 0) { errors.push( @@ -1577,7 +1583,7 @@ namespace ts { errors.push(createCompilerDiagnostic(Diagnostics.Compiler_option_0_requires_a_value_of_type_1, "extends", "string")); } else { - const newBase = configFileName ? getDirectoryPath(toPath(configFileName, basePath, getCanonicalFileName)) : basePath; + const newBase = configFileName ? directoryOfCombinedPath(configFileName, basePath) : basePath; extendedConfigPath = getExtendsConfigPath(json.extends, host, newBase, getCanonicalFileName, errors, createCompilerDiagnostic); } } @@ -1610,7 +1616,7 @@ namespace ts { onSetValidOptionKeyValueInRoot(key: string, _keyNode: PropertyName, value: CompilerOptionsValue, valueNode: Expression) { switch (key) { case "extends": - const newBase = configFileName ? getDirectoryPath(toPath(configFileName, basePath, getCanonicalFileName)) : basePath; + const newBase = configFileName ? directoryOfCombinedPath(configFileName, basePath) : basePath; extendedConfigPath = getExtendsConfigPath( value, host, diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 2c0416c071157..06456366355ce 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -1228,6 +1228,9 @@ namespace ts { /** Does nothing. */ export function noop(): void {} + /** Returns its argument. */ + export function identity(x: T) { return x; } + /** Throws an error because a function is not implemented. */ export function notImplemented(): never { throw new Error("Not implemented");