diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9509c286236..1684938decd 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -138,7 +138,7 @@ namespace ts { const globals: SymbolTable = {}; - let globalESSymbolConstructorSymbol: Symbol; + let getGlobalESSymbolConstructorSymbol: () => Symbol; let getGlobalPromiseConstructorSymbol: () => Symbol; @@ -150,11 +150,12 @@ namespace ts { let globalNumberType: ObjectType; let globalBooleanType: ObjectType; let globalRegExpType: ObjectType; - let globalTemplateStringsArrayType: ObjectType; - let globalESSymbolType: ObjectType; - let globalIterableType: GenericType; - let globalIteratorType: GenericType; - let globalIterableIteratorType: GenericType; + let getGlobalTemplateStringsArrayType: () => ObjectType; + + let getGlobalESSymbolType: () => ObjectType; + let getGlobalIterableType: () => GenericType; + let getGlobalIteratorType: () => GenericType; + let getGlobalIterableIteratorType: () => GenericType; let anyArrayType: Type; let anyReadonlyArrayType: Type; @@ -3973,7 +3974,7 @@ namespace ts { type = globalBooleanType; } else if (type.flags & TypeFlags.ESSymbol) { - type = globalESSymbolType; + type = getGlobalESSymbolType(); } return type; } @@ -4744,10 +4745,6 @@ namespace ts { return typeSymbol && getDeclaredTypeOfSymbol(typeSymbol); } - function getGlobalESSymbolConstructorSymbol() { - return globalESSymbolConstructorSymbol || (globalESSymbolConstructorSymbol = getGlobalValueSymbol("Symbol")); - } - /** * Creates a TypeReference for a generic `TypedPropertyDescriptor`. */ @@ -4766,11 +4763,11 @@ namespace ts { } function createIterableType(elementType: Type): Type { - return createTypeFromGenericGlobalType(globalIterableType, [elementType]); + return createTypeFromGenericGlobalType(getGlobalIterableType(), [elementType]); } function createIterableIteratorType(elementType: Type): Type { - return createTypeFromGenericGlobalType(globalIterableIteratorType, [elementType]); + return createTypeFromGenericGlobalType(getGlobalIterableIteratorType(), [elementType]); } function createArrayType(elementType: Type): Type { @@ -10415,7 +10412,7 @@ namespace ts { return getEffectiveDecoratorArgumentType(node, argIndex); } else if (argIndex === 0 && node.kind === SyntaxKind.TaggedTemplateExpression) { - return globalTemplateStringsArrayType; + return getGlobalTemplateStringsArrayType(); } // This is not a synthetic argument, so we return 'undefined' @@ -14179,7 +14176,7 @@ namespace ts { if (!typeAsIterable.iterableElementType) { // As an optimization, if the type is instantiated directly using the globalIterableType (Iterable), // then just grab its type argument. - if ((type.flags & TypeFlags.Reference) && (type).target === globalIterableType) { + if ((type.flags & TypeFlags.Reference) && (type).target === getGlobalIterableType()) { typeAsIterable.iterableElementType = (type).typeArguments[0]; } else { @@ -14225,7 +14222,7 @@ namespace ts { if (!typeAsIterator.iteratorElementType) { // As an optimization, if the type is instantiated directly using the globalIteratorType (Iterator), // then just grab its type argument. - if ((type.flags & TypeFlags.Reference) && (type).target === globalIteratorType) { + if ((type.flags & TypeFlags.Reference) && (type).target === getGlobalIteratorType()) { typeAsIterator.iteratorElementType = (type).typeArguments[0]; } else { @@ -14269,7 +14266,7 @@ namespace ts { // As an optimization, if the type is instantiated directly using the globalIterableIteratorType (IterableIterator), // then just grab its type argument. - if ((type.flags & TypeFlags.Reference) && (type).target === globalIterableIteratorType) { + if ((type.flags & TypeFlags.Reference) && (type).target === getGlobalIterableIteratorType()) { return (type).typeArguments[0]; } @@ -16879,12 +16876,14 @@ namespace ts { globalNumberType = getGlobalType("Number"); globalBooleanType = getGlobalType("Boolean"); globalRegExpType = getGlobalType("RegExp"); + jsxElementType = getExportedTypeFromNamespace("JSX", JsxNames.Element); getGlobalClassDecoratorType = memoize(() => getGlobalType("ClassDecorator")); getGlobalPropertyDecoratorType = memoize(() => getGlobalType("PropertyDecorator")); getGlobalMethodDecoratorType = memoize(() => getGlobalType("MethodDecorator")); getGlobalParameterDecoratorType = memoize(() => getGlobalType("ParameterDecorator")); getGlobalTypedPropertyDescriptorType = memoize(() => getGlobalType("TypedPropertyDescriptor", /*arity*/ 1)); + getGlobalESSymbolConstructorSymbol = memoize(() => getGlobalValueSymbol("Symbol")); getGlobalPromiseType = memoize(() => getGlobalType("Promise", /*arity*/ 1)); tryGetGlobalPromiseType = memoize(() => getGlobalSymbol("Promise", SymbolFlags.Type, /*diagnostic*/ undefined) && getGlobalPromiseType()); getGlobalPromiseLikeType = memoize(() => getGlobalType("PromiseLike", /*arity*/ 1)); @@ -16893,27 +16892,19 @@ namespace ts { getGlobalPromiseConstructorLikeType = memoize(() => getGlobalType("PromiseConstructorLike")); getGlobalThenableType = memoize(createThenableType); - // If we're in ES6 mode, load the TemplateStringsArray. - // Otherwise, default to 'unknown' for the purposes of type checking in LS scenarios. + getGlobalTemplateStringsArrayType = memoize(() => getGlobalType("TemplateStringsArray")); + if (languageVersion >= ScriptTarget.ES6) { - globalTemplateStringsArrayType = getGlobalType("TemplateStringsArray"); - globalESSymbolType = getGlobalType("Symbol"); - globalESSymbolConstructorSymbol = getGlobalValueSymbol("Symbol"); - globalIterableType = getGlobalType("Iterable", /*arity*/ 1); - globalIteratorType = getGlobalType("Iterator", /*arity*/ 1); - globalIterableIteratorType = getGlobalType("IterableIterator", /*arity*/ 1); + getGlobalESSymbolType = memoize(() => getGlobalType("Symbol")); + getGlobalIterableType = memoize(() => getGlobalType("Iterable", /*arity*/ 1)); + getGlobalIteratorType = memoize(() => getGlobalType("Iterator", /*arity*/ 1)); + getGlobalIterableIteratorType = memoize(() => getGlobalType("IterableIterator", /*arity*/ 1)); } else { - globalTemplateStringsArrayType = unknownType; - - // Consider putting Symbol interface in lib.d.ts. On the plus side, putting it in lib.d.ts would make it - // extensible for Polyfilling Symbols. But putting it into lib.d.ts could also break users that have - // a global Symbol already, particularly if it is a class. - globalESSymbolType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); - globalESSymbolConstructorSymbol = undefined; - globalIterableType = emptyGenericType; - globalIteratorType = emptyGenericType; - globalIterableIteratorType = emptyGenericType; + getGlobalESSymbolType = memoize(() => emptyObjectType); + getGlobalIterableType = memoize(() => emptyGenericType); + getGlobalIteratorType = memoize(() => emptyGenericType); + getGlobalIterableIteratorType = memoize(() => emptyGenericType); } anyArrayType = createArrayType(anyType); diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index cc17383c064..930ad4b7575 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -162,7 +162,6 @@ namespace ts { }, { name: "pretty", - paramType: Diagnostics.KIND, description: Diagnostics.Stylize_errors_and_messages_using_color_and_context_experimental, type: "boolean" }, @@ -332,6 +331,43 @@ namespace ts { type: "boolean", description: Diagnostics.Do_not_emit_use_strict_directives_in_module_output }, + { + name: "lib", + type: "list", + element: { + name: "lib", + type: { + // JavaScript only + "es5": "lib.es5.d.ts", + "es6": "lib.es2015.d.ts", + "es2015": "lib.es2015.d.ts", + "es7": "lib.es2016.d.ts", + "es2016": "lib.es2016.d.ts", + // Host only + "dom": "lib.dom.d.ts", + "webworker": "lib.webworker.d.ts", + "scripthost": "lib.scripthost.d.ts", + // ES2015 Or ESNext By-feature options + "es2015.array": "lib.es2015.array.d.ts", + "es2015.collection": "lib.es2015.collection.d.ts", + "es2015.generator": "lib.es2015.generator.d.ts", + "es2015.function": "lib.es2015.function.d.ts", + "es2015.iterable": "lib.es2015.iterable.d.ts", + "es2015.math": "lib.es2015.math.d.ts", + "es2015.number": "lib.es2015.number.d.ts", + "es2015.object": "lib.es2015.object.d.ts", + "es2015.promise": "lib.es2015.promise.d.ts", + "es2015.proxy": "lib.es2015.proxy.d.ts", + "es2015.reflect": "lib.es2015.reflect.d.ts", + "es2015.regexp": "lib.es2015.regexp.d.ts", + "es2015.string": "lib.es2015.string.d.ts", + "es2015.symbol": "lib.es2015.symbol.d.ts", + "es2015.symbol.wellknown": "lib.es2015.symbol.wellknown.d.ts", + "es2016.array.include": "lib.es2016.array.include.d.ts" + }, + }, + description: Diagnostics.Specify_library_files_to_be_included_in_the_compilation_Colon + }, { name: "strictNullChecks", type: "boolean", @@ -370,6 +406,7 @@ namespace ts { } let optionNameMapCache: OptionNameMap; + /* @internal */ export function getOptionNameMap(): OptionNameMap { if (optionNameMapCache) { @@ -399,6 +436,32 @@ namespace ts { return createCompilerDiagnostic(Diagnostics.Argument_for_0_option_must_be_Colon_1, `--${opt.name}`, namesOfType); } + /* @internal */ + export function parseCustomTypeOption(opt: CommandLineOptionOfCustomType, value: string, errors: Diagnostic[]) { + const key = (value || "").trim().toLowerCase(); + const map = opt.type; + if (hasProperty(map, key)) { + return map[key]; + } + else { + errors.push(createCompilerDiagnosticForInvalidCustomType(opt)); + } + } + + /* @internal */ + export function parseListTypeOption(opt: CommandLineOptionOfListType, value: string, errors: Diagnostic[]): (string | number)[] { + const values = (value || "").trim().split(","); + switch (opt.element.type) { + case "number": + return ts.map(values, parseInt); + case "string": + return ts.map(values, v => v || ""); + default: + return filter(map(values, v => parseCustomTypeOption(opt.element, v, errors)), v => !!v); + } + } + + /* @internal */ export function parseCommandLine(commandLine: string[], readFile?: (path: string) => string): ParsedCommandLine { const options: CompilerOptions = {}; const fileNames: string[] = []; @@ -453,12 +516,12 @@ namespace ts { i++; break; case "list": - options[opt.name] = parseListTypeOption(opt, args[i]); + options[opt.name] = parseListTypeOption(opt, args[i], errors); i++; break; // If not a primitive, the possible types are specified in what is effectively a map of options. default: - options[opt.name] = parseCustomTypeOption(opt, args[i]); + options[opt.name] = parseCustomTypeOption(opt, args[i], errors); i++; break; } @@ -471,29 +534,6 @@ namespace ts { else { fileNames.push(s); } - - function parseCustomTypeOption(opt: CommandLineOptionOfCustomType, value: string) { - const key = (value || "").trim().toLowerCase(); - const map = opt.type; - if (hasProperty(map, key)) { - return map[key]; - } - else { - errors.push(createCompilerDiagnosticForInvalidCustomType(opt)); - } - } - - function parseListTypeOption(opt: CommandLineOptionOfListType, value: string): (string | number)[] { - const values = (value || "").trim().split(","); - switch (opt.element.type) { - case "number": - return ts.map(values, parseInt); - case "string": - return ts.map(values, v => v || ""); - default: - return filter(map(values, v => parseCustomTypeOption(opt.element, v)), v => !!v); - } - } } } diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index d7c2fac2710..0810595a89e 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -2488,6 +2488,10 @@ "category": "Message", "code": 6078 }, + "Specify library files to be included in the compilation: ": { + "category": "Message", + "code": 6079 + }, "Specify JSX code generation: 'preserve' or 'react'": { "category": "Message", "code": 6080 diff --git a/src/compiler/program.ts b/src/compiler/program.ts index b528143384e..be758e8dda6 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -15,8 +15,8 @@ namespace ts { export const version = "1.9.0"; export function findConfigFile(searchPath: string, fileExists: (fileName: string) => boolean): string { - let fileName = "tsconfig.json"; while (true) { + const fileName = combinePaths(searchPath, "tsconfig.json"); if (fileExists(fileName)) { return fileName; } @@ -25,7 +25,6 @@ namespace ts { break; } searchPath = parentPath; - fileName = "../" + fileName; } return undefined; } @@ -630,10 +629,18 @@ namespace ts { } } + function getUserDefinedLibFileName(options: CompilerOptions): string[] { + const directoryPath = getDirectoryPath(normalizePath(sys.getExecutingFilePath())); + return options.lib.map(fileName => { + return combinePaths(directoryPath, fileName); + }); + } + const newLine = getNewLineCharacter(options); return { getSourceFile, + getUserDefinedLibFileName, getDefaultLibFileName: options => combinePaths(getDirectoryPath(normalizePath(sys.getExecutingFilePath())), getDefaultLibFileName(options)), writeFile, getCurrentDirectory: memoize(() => sys.getCurrentDirectory()), @@ -754,7 +761,17 @@ namespace ts { // - A 'no-default-lib' reference comment is encountered in // processing the root files. if (!skipDefaultLib) { - processRootFile(host.getDefaultLibFileName(options), /*isDefaultLib*/ true); + // If '--lib' is not specified, include default library file according to '--target' + // otherwise, using options specified in '--lib' instead of '--target' default library file + if (!options.lib) { + processRootFile(host.getDefaultLibFileName(options), /*isDefaultLib*/ true); + } + else { + const libFileNames = host.getUserDefinedLibFileName(options); + libFileNames.forEach(libFileName => { + processRootFile(libFileName, /*isDefaultLib*/ true); + }); + } } } @@ -1483,7 +1500,7 @@ namespace ts { const basePath = getDirectoryPath(fileName); if (!options.noResolve) { - processReferencedFiles(file, basePath); + processReferencedFiles(file, basePath, /*isDefaultLib*/ isDefaultLib); } // always process imported modules to record module name resolutions @@ -1500,10 +1517,10 @@ namespace ts { return file; } - function processReferencedFiles(file: SourceFile, basePath: string) { + function processReferencedFiles(file: SourceFile, basePath: string, isDefaultLib: boolean) { forEach(file.referencedFiles, ref => { const referencedFileName = resolveTripleslashReference(ref.fileName, file.fileName); - processSourceFile(referencedFileName, /*isDefaultLib*/ false, /*isReference*/ true, file, ref.pos, ref.end); + processSourceFile(referencedFileName, isDefaultLib, /*isReference*/ true, file, ref.pos, ref.end); }); } @@ -1700,6 +1717,10 @@ namespace ts { } } + if (options.lib && options.noLib) { + programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_with_option_1, "lib", "noLib")); + } + const languageVersion = options.target || ScriptTarget.ES3; const outFile = options.outFile || options.out; diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index 24f95ab358f..36bc7717974 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -655,6 +655,8 @@ namespace ts { const usageColumn: string[] = []; // Things like "-d, --declaration" go in here. const descriptionColumn: string[] = []; + const optionsDescriptionMap: Map = {}; // Map between option.description and list of option.type if it is a kind + for (let i = 0; i < optsList.length; i++) { const option = optsList[i]; @@ -675,7 +677,22 @@ namespace ts { usageText += getParamType(option); usageColumn.push(usageText); - descriptionColumn.push(getDiagnosticText(option.description)); + let description: string; + + if (option.name === "lib") { + description = getDiagnosticText(option.description); + const options: string[] = []; + const element = (option).element; + forEachKey(>element.type, key => { + options.push(`'${key}'`); + }); + optionsDescriptionMap[description] = options; + } + else { + description = getDiagnosticText(option.description); + } + + descriptionColumn.push(description); // Set the new margin for the description column if necessary. marginLength = Math.max(usageText.length, marginLength); @@ -691,7 +708,15 @@ namespace ts { for (let i = 0; i < usageColumn.length; i++) { const usage = usageColumn[i]; const description = descriptionColumn[i]; + const kindsList = optionsDescriptionMap[description]; output += usage + makePadding(marginLength - usage.length + 2) + description + sys.newLine; + + if (kindsList) { + for (const kind of kindsList) { + output += makePadding(marginLength + 4) + kind + sys.newLine; + } + output += sys.newLine; + } } sys.write(output); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 546d1631945..d1a056edd7f 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2752,6 +2752,7 @@ namespace ts { getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile; getCancellationToken?(): CancellationToken; getDefaultLibFileName(options: CompilerOptions): string; + getUserDefinedLibFileName(options: CompilerOptions): string[]; writeFile: WriteFileCallback; getCurrentDirectory(): string; getCanonicalFileName(fileName: string): string; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 261ec57f225..ee029b7249f 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -2646,7 +2646,7 @@ namespace ts { namespace ts { export function getDefaultLibFileName(options: CompilerOptions): string { - return options.target === ScriptTarget.ES6 ? "lib.full.es6.d.ts" : "lib.d.ts"; + return options.target === ScriptTarget.ES6 ? "lib.full.es2015.d.ts" : "lib.d.ts"; } export function textSpanEnd(span: TextSpan) { diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 2fba2d13299..e02bb25e094 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -291,7 +291,8 @@ namespace FourSlash { // Check if no-default-lib flag is false and if so add default library if (!resolvedResult.isLibFile) { - this.languageServiceAdapterHost.addScript(Harness.Compiler.defaultLibFileName, Harness.Compiler.defaultLibSourceFile.text); + this.languageServiceAdapterHost.addScript(Harness.Compiler.defaultLibFileName, + Harness.Compiler.getDefaultLibrarySourceFile(Harness.Compiler.defaultLibFileName).text); } } else { @@ -301,7 +302,8 @@ namespace FourSlash { this.languageServiceAdapterHost.addScript(fileName, this.inputFiles[fileName]); } }); - this.languageServiceAdapterHost.addScript(Harness.Compiler.defaultLibFileName, Harness.Compiler.defaultLibSourceFile.text); + this.languageServiceAdapterHost.addScript(Harness.Compiler.defaultLibFileName, + Harness.Compiler.getDefaultLibrarySourceFile(Harness.Compiler.defaultLibFileName).text); } this.formatCodeOptions = { diff --git a/src/harness/harness.ts b/src/harness/harness.ts index bbc4d540e9c..2b555932e9e 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -809,9 +809,26 @@ namespace Harness { const lineFeed = "\n"; export const defaultLibFileName = "lib.d.ts"; - export const defaultLibSourceFile = createSourceFileAndAssertInvariants(defaultLibFileName, IO.readFile(libFolder + "lib.es5.d.ts"), /*languageVersion*/ ts.ScriptTarget.Latest); - // TODO (yuisu): we should not use the lib.full.es6.d.ts. We will fix this when all the work for library modularization is in - export const defaultES6LibSourceFile = createSourceFileAndAssertInvariants(defaultLibFileName, IO.readFile(libFolder + "lib.full.es6.d.ts"), /*languageVersion*/ ts.ScriptTarget.Latest); + export const es2015DefaultLibFileName = "lib.es2015.d.ts"; + + const libFileNameSourceFileMap: ts.Map = { + [defaultLibFileName]: createSourceFileAndAssertInvariants(defaultLibFileName, IO.readFile(libFolder + "lib.es5.d.ts"), /*languageVersion*/ ts.ScriptTarget.Latest) + }; + + export function getDefaultLibrarySourceFile(fileName: string): ts.SourceFile { + if (!isLibraryFile(fileName)) { + return undefined; + } + + if (!libFileNameSourceFileMap[fileName]) { + libFileNameSourceFileMap[fileName] = createSourceFileAndAssertInvariants(fileName, IO.readFile(libFolder + fileName), ts.ScriptTarget.Latest); + } + return libFileNameSourceFileMap[fileName]; + } + + export function getDefaultLibSourceFile(languageVersion: ts.ScriptTarget) { + return languageVersion === ts.ScriptTarget.ES6 ? getDefaultLibrarySourceFile("lib.es2015.d.ts") : getDefaultLibrarySourceFile(defaultLibFileName); + } // Cache these between executions so we don't have to re-parse them for every test export const fourslashFileName = "fourslash.ts"; @@ -843,23 +860,21 @@ namespace Harness { } } - function getSourceFile(fn: string, languageVersion: ts.ScriptTarget) { - fn = ts.normalizePath(fn); - const path = ts.toPath(fn, currentDirectory, getCanonicalFileName); + function getSourceFile(fileName: string, languageVersion: ts.ScriptTarget) { + fileName = ts.normalizePath(fileName); + const path = ts.toPath(fileName, currentDirectory, getCanonicalFileName); if (fileMap.contains(path)) { return fileMap.get(path); } - else if (fn === fourslashFileName) { + else if (fileName === fourslashFileName) { const tsFn = "tests/cases/fourslash/" + fourslashFileName; fourslashSourceFile = fourslashSourceFile || createSourceFileAndAssertInvariants(tsFn, Harness.IO.readFile(tsFn), scriptTarget); return fourslashSourceFile; } else { - if (fn === defaultLibFileName) { - return languageVersion === ts.ScriptTarget.ES6 ? defaultES6LibSourceFile : defaultLibSourceFile; - } // Don't throw here -- the compiler might be looking for a test that actually doesn't exist as part of the TC - return undefined; + // Return if it is other library file, otherwise return undefined + return getDefaultLibrarySourceFile(fileName); } } @@ -871,7 +886,8 @@ namespace Harness { return { getCurrentDirectory: () => currentDirectory, getSourceFile, - getDefaultLibFileName: options => defaultLibFileName, + getDefaultLibFileName: options => options.target === ts.ScriptTarget.ES6 ? es2015DefaultLibFileName : defaultLibFileName, + getUserDefinedLibFileName: options => options.lib, writeFile, getCanonicalFileName, useCaseSensitiveFileNames: () => useCaseSensitiveFileNames, @@ -922,6 +938,7 @@ namespace Harness { } const option = getCommandLineOption(name); if (option) { + const errors: ts.Diagnostic[] = []; switch (option.type) { case "boolean": options[option.name] = value.toLowerCase() === "true"; @@ -930,15 +947,16 @@ namespace Harness { options[option.name] = value; break; // If not a primitive, the possible types are specified in what is effectively a map of options. + case "list": + options[option.name] = ts.parseListTypeOption(option, value, errors); + break; default: - let map = >option.type; - let key = value.toLowerCase(); - if (ts.hasProperty(map, key)) { - options[option.name] = map[key]; - } - else { - throw new Error(`Unknown value '${value}' for compiler option '${name}'.`); - } + options[option.name] = ts.parseCustomTypeOption(option, value, errors); + break; + } + + if (errors.length > 0) { + throw new Error(`Unknown value '${value}' for compiler option '${name}'.`); } } else { @@ -965,7 +983,6 @@ namespace Harness { compilerOptions: ts.CompilerOptions, // Current directory is needed for rwcRunner to be able to use currentDirectory defined in json file currentDirectory: string): CompilationOutput { - const options: ts.CompilerOptions & HarnessOptions = compilerOptions ? ts.clone(compilerOptions) : { noResolve: false }; options.target = options.target || ts.ScriptTarget.ES3; options.newLine = options.newLine || ts.NewLineKind.CarriageReturnLineFeed; @@ -1144,7 +1161,7 @@ namespace Harness { totalErrorsReportedInNonLibraryFiles++; } } - + debugger; // Report global errors const globalErrors = diagnostics.filter(err => !err.file); globalErrors.forEach(outputErrorText); @@ -1606,8 +1623,10 @@ namespace Harness { } } + // Regex for check if the give filePath is a library file + const libRegex = /lib(\.\S+)*\.d\.ts/; export function isLibraryFile(filePath: string): boolean { - return (Path.getFileName(filePath) === "lib.d.ts") || (Path.getFileName(filePath) === "lib.es5.d.ts"); + return !!libRegex.exec(Path.getFileName(filePath)); } export function isBuiltFile(filePath: string): boolean { @@ -1615,7 +1634,7 @@ namespace Harness { } export function getDefaultLibraryFile(io: Harness.IO): Harness.Compiler.TestFile { - const libFile = Harness.userSpecifiedRoot + Harness.libFolder + "lib.d.ts"; + const libFile = Harness.userSpecifiedRoot + Harness.libFolder + Harness.Compiler.defaultLibFileName; return { unitName: libFile, content: io.readFile(libFile) }; } diff --git a/src/harness/projectsRunner.ts b/src/harness/projectsRunner.ts index f5df92bedbf..cd5ac3efd16 100644 --- a/src/harness/projectsRunner.ts +++ b/src/harness/projectsRunner.ts @@ -156,7 +156,7 @@ class ProjectRunner extends RunnerBase { function getSourceFile(fileName: string, languageVersion: ts.ScriptTarget): ts.SourceFile { let sourceFile: ts.SourceFile = undefined; if (fileName === Harness.Compiler.defaultLibFileName) { - sourceFile = languageVersion === ts.ScriptTarget.ES6 ? Harness.Compiler.defaultES6LibSourceFile : Harness.Compiler.defaultLibSourceFile; + sourceFile = Harness.Compiler.getDefaultLibSourceFile(languageVersion); } else { const text = getSourceFileText(fileName); @@ -172,6 +172,7 @@ class ProjectRunner extends RunnerBase { return { getSourceFile, getDefaultLibFileName: options => Harness.Compiler.defaultLibFileName, + getUserDefinedLibFileName: options => [], writeFile, getCurrentDirectory, getCanonicalFileName: Harness.Compiler.getCanonicalFileName, @@ -412,7 +413,7 @@ class ProjectRunner extends RunnerBase { function getErrorsBaseline(compilerResult: CompileProjectFilesResult) { const inputFiles = compilerResult.program ? ts.map(ts.filter(compilerResult.program.getSourceFiles(), - sourceFile => sourceFile.fileName !== "lib.d.ts"), + sourceFile => !Harness.isLibraryFile(sourceFile.fileName)), sourceFile => { return { unitName: ts.isRootedDiskPath(sourceFile.fileName) ? diff --git a/src/services/services.ts b/src/services/services.ts index a634b2baf1a..af9749d6416 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -1926,6 +1926,7 @@ namespace ts { } }, getDefaultLibFileName: () => "lib.d.ts", + getUserDefinedLibFileName: () => [], useCaseSensitiveFileNames: () => false, getCanonicalFileName: fileName => fileName, getCurrentDirectory: () => "", @@ -2825,6 +2826,7 @@ namespace ts { getCanonicalFileName, useCaseSensitiveFileNames: () => useCaseSensitivefileNames, getNewLine: () => getNewLineOrDefaultFromHost(host), + getUserDefinedLibFileName: (options) => [], getDefaultLibFileName: (options) => host.getDefaultLibFileName(options), writeFile: (fileName, data, writeByteOrderMark) => { }, getCurrentDirectory: () => currentDirectory, diff --git a/tests/cases/unittests/moduleResolution.ts b/tests/cases/unittests/moduleResolution.ts index 9a52d9896e4..be32e14c9ea 100644 --- a/tests/cases/unittests/moduleResolution.ts +++ b/tests/cases/unittests/moduleResolution.ts @@ -281,6 +281,7 @@ module ts { return hasProperty(files, path) ? createSourceFile(fileName, files[path], languageVersion) : undefined; }, getDefaultLibFileName: () => "lib.d.ts", + getUserDefinedLibFileName: options => [], writeFile: (fileName, content): void => { throw new Error("NotImplemented"); }, getCurrentDirectory: () => currentDirectory, getCanonicalFileName: fileName => fileName.toLowerCase(), @@ -364,6 +365,7 @@ export = C; return hasProperty(files, path) ? createSourceFile(fileName, files[path], languageVersion) : undefined; }, getDefaultLibFileName: () => "lib.d.ts", + getUserDefinedLibFileName: options => [], writeFile: (fileName, content): void => { throw new Error("NotImplemented"); }, getCurrentDirectory: () => currentDirectory, getCanonicalFileName, diff --git a/tests/cases/unittests/reuseProgramStructure.ts b/tests/cases/unittests/reuseProgramStructure.ts index 5f313eeae2b..563135ed5c2 100644 --- a/tests/cases/unittests/reuseProgramStructure.ts +++ b/tests/cases/unittests/reuseProgramStructure.ts @@ -111,6 +111,7 @@ module ts { getDefaultLibFileName(): string { return "lib.d.ts" }, + getUserDefinedLibFileName: options => [], writeFile(file, text) { throw new Error("NYI"); },