Skip to content

Commit 3fef5ba

Browse files
author
Kanchalai Tanglertsampan
committed
Implement --lib flag in the compiler and harness
1 parent 168118f commit 3fef5ba

13 files changed

+206
-97
lines changed

src/compiler/checker.ts

Lines changed: 26 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,7 @@ namespace ts {
138138

139139
const globals: SymbolTable = {};
140140

141-
let globalESSymbolConstructorSymbol: Symbol;
141+
let getGlobalESSymbolConstructorSymbol: () => Symbol;
142142

143143
let getGlobalPromiseConstructorSymbol: () => Symbol;
144144

@@ -150,11 +150,12 @@ namespace ts {
150150
let globalNumberType: ObjectType;
151151
let globalBooleanType: ObjectType;
152152
let globalRegExpType: ObjectType;
153-
let globalTemplateStringsArrayType: ObjectType;
154-
let globalESSymbolType: ObjectType;
155-
let globalIterableType: GenericType;
156-
let globalIteratorType: GenericType;
157-
let globalIterableIteratorType: GenericType;
153+
let getGlobalTemplateStringsArrayType: () => ObjectType;
154+
155+
let getGlobalESSymbolType: () => ObjectType;
156+
let getGlobalIterableType: () => GenericType;
157+
let getGlobalIteratorType: () => GenericType;
158+
let getGlobalIterableIteratorType: () => GenericType;
158159

159160
let anyArrayType: Type;
160161
let anyReadonlyArrayType: Type;
@@ -3973,7 +3974,7 @@ namespace ts {
39733974
type = globalBooleanType;
39743975
}
39753976
else if (type.flags & TypeFlags.ESSymbol) {
3976-
type = globalESSymbolType;
3977+
type = getGlobalESSymbolType();
39773978
}
39783979
return type;
39793980
}
@@ -4744,10 +4745,6 @@ namespace ts {
47444745
return typeSymbol && getDeclaredTypeOfSymbol(typeSymbol);
47454746
}
47464747

4747-
function getGlobalESSymbolConstructorSymbol() {
4748-
return globalESSymbolConstructorSymbol || (globalESSymbolConstructorSymbol = getGlobalValueSymbol("Symbol"));
4749-
}
4750-
47514748
/**
47524749
* Creates a TypeReference for a generic `TypedPropertyDescriptor<T>`.
47534750
*/
@@ -4766,11 +4763,11 @@ namespace ts {
47664763
}
47674764

47684765
function createIterableType(elementType: Type): Type {
4769-
return createTypeFromGenericGlobalType(globalIterableType, [elementType]);
4766+
return createTypeFromGenericGlobalType(getGlobalIterableType(), [elementType]);
47704767
}
47714768

47724769
function createIterableIteratorType(elementType: Type): Type {
4773-
return createTypeFromGenericGlobalType(globalIterableIteratorType, [elementType]);
4770+
return createTypeFromGenericGlobalType(getGlobalIterableIteratorType(), [elementType]);
47744771
}
47754772

47764773
function createArrayType(elementType: Type): Type {
@@ -10415,7 +10412,7 @@ namespace ts {
1041510412
return getEffectiveDecoratorArgumentType(<Decorator>node, argIndex);
1041610413
}
1041710414
else if (argIndex === 0 && node.kind === SyntaxKind.TaggedTemplateExpression) {
10418-
return globalTemplateStringsArrayType;
10415+
return getGlobalTemplateStringsArrayType();
1041910416
}
1042010417

1042110418
// This is not a synthetic argument, so we return 'undefined'
@@ -14179,7 +14176,7 @@ namespace ts {
1417914176
if (!typeAsIterable.iterableElementType) {
1418014177
// As an optimization, if the type is instantiated directly using the globalIterableType (Iterable<number>),
1418114178
// then just grab its type argument.
14182-
if ((type.flags & TypeFlags.Reference) && (<GenericType>type).target === globalIterableType) {
14179+
if ((type.flags & TypeFlags.Reference) && (<GenericType>type).target === getGlobalIterableType()) {
1418314180
typeAsIterable.iterableElementType = (<GenericType>type).typeArguments[0];
1418414181
}
1418514182
else {
@@ -14225,7 +14222,7 @@ namespace ts {
1422514222
if (!typeAsIterator.iteratorElementType) {
1422614223
// As an optimization, if the type is instantiated directly using the globalIteratorType (Iterator<number>),
1422714224
// then just grab its type argument.
14228-
if ((type.flags & TypeFlags.Reference) && (<GenericType>type).target === globalIteratorType) {
14225+
if ((type.flags & TypeFlags.Reference) && (<GenericType>type).target === getGlobalIteratorType()) {
1422914226
typeAsIterator.iteratorElementType = (<GenericType>type).typeArguments[0];
1423014227
}
1423114228
else {
@@ -14269,7 +14266,7 @@ namespace ts {
1426914266

1427014267
// As an optimization, if the type is instantiated directly using the globalIterableIteratorType (IterableIterator<number>),
1427114268
// then just grab its type argument.
14272-
if ((type.flags & TypeFlags.Reference) && (<GenericType>type).target === globalIterableIteratorType) {
14269+
if ((type.flags & TypeFlags.Reference) && (<GenericType>type).target === getGlobalIterableIteratorType()) {
1427314270
return (<GenericType>type).typeArguments[0];
1427414271
}
1427514272

@@ -16879,12 +16876,14 @@ namespace ts {
1687916876
globalNumberType = getGlobalType("Number");
1688016877
globalBooleanType = getGlobalType("Boolean");
1688116878
globalRegExpType = getGlobalType("RegExp");
16879+
1688216880
jsxElementType = getExportedTypeFromNamespace("JSX", JsxNames.Element);
1688316881
getGlobalClassDecoratorType = memoize(() => getGlobalType("ClassDecorator"));
1688416882
getGlobalPropertyDecoratorType = memoize(() => getGlobalType("PropertyDecorator"));
1688516883
getGlobalMethodDecoratorType = memoize(() => getGlobalType("MethodDecorator"));
1688616884
getGlobalParameterDecoratorType = memoize(() => getGlobalType("ParameterDecorator"));
1688716885
getGlobalTypedPropertyDescriptorType = memoize(() => getGlobalType("TypedPropertyDescriptor", /*arity*/ 1));
16886+
getGlobalESSymbolConstructorSymbol = memoize(() => getGlobalValueSymbol("Symbol"));
1688816887
getGlobalPromiseType = memoize(() => getGlobalType("Promise", /*arity*/ 1));
1688916888
tryGetGlobalPromiseType = memoize(() => getGlobalSymbol("Promise", SymbolFlags.Type, /*diagnostic*/ undefined) && getGlobalPromiseType());
1689016889
getGlobalPromiseLikeType = memoize(() => getGlobalType("PromiseLike", /*arity*/ 1));
@@ -16893,27 +16892,19 @@ namespace ts {
1689316892
getGlobalPromiseConstructorLikeType = memoize(() => getGlobalType("PromiseConstructorLike"));
1689416893
getGlobalThenableType = memoize(createThenableType);
1689516894

16896-
// If we're in ES6 mode, load the TemplateStringsArray.
16897-
// Otherwise, default to 'unknown' for the purposes of type checking in LS scenarios.
16895+
getGlobalTemplateStringsArrayType = memoize(() => getGlobalType("TemplateStringsArray"));
16896+
1689816897
if (languageVersion >= ScriptTarget.ES6) {
16899-
globalTemplateStringsArrayType = getGlobalType("TemplateStringsArray");
16900-
globalESSymbolType = getGlobalType("Symbol");
16901-
globalESSymbolConstructorSymbol = getGlobalValueSymbol("Symbol");
16902-
globalIterableType = <GenericType>getGlobalType("Iterable", /*arity*/ 1);
16903-
globalIteratorType = <GenericType>getGlobalType("Iterator", /*arity*/ 1);
16904-
globalIterableIteratorType = <GenericType>getGlobalType("IterableIterator", /*arity*/ 1);
16898+
getGlobalESSymbolType = memoize(() => getGlobalType("Symbol"));
16899+
getGlobalIterableType = memoize(() => <GenericType>getGlobalType("Iterable", /*arity*/ 1));
16900+
getGlobalIteratorType = memoize(() => <GenericType>getGlobalType("Iterator", /*arity*/ 1));
16901+
getGlobalIterableIteratorType = memoize(() => <GenericType>getGlobalType("IterableIterator", /*arity*/ 1));
1690516902
}
1690616903
else {
16907-
globalTemplateStringsArrayType = unknownType;
16908-
16909-
// Consider putting Symbol interface in lib.d.ts. On the plus side, putting it in lib.d.ts would make it
16910-
// extensible for Polyfilling Symbols. But putting it into lib.d.ts could also break users that have
16911-
// a global Symbol already, particularly if it is a class.
16912-
globalESSymbolType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
16913-
globalESSymbolConstructorSymbol = undefined;
16914-
globalIterableType = emptyGenericType;
16915-
globalIteratorType = emptyGenericType;
16916-
globalIterableIteratorType = emptyGenericType;
16904+
getGlobalESSymbolType = memoize(() => emptyObjectType);
16905+
getGlobalIterableType = memoize(() => emptyGenericType);
16906+
getGlobalIteratorType = memoize(() => emptyGenericType);
16907+
getGlobalIterableIteratorType = memoize(() => emptyGenericType);
1691716908
}
1691816909

1691916910
anyArrayType = createArrayType(anyType);

src/compiler/commandLineParser.ts

Lines changed: 66 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -162,7 +162,6 @@ namespace ts {
162162
},
163163
{
164164
name: "pretty",
165-
paramType: Diagnostics.KIND,
166165
description: Diagnostics.Stylize_errors_and_messages_using_color_and_context_experimental,
167166
type: "boolean"
168167
},
@@ -332,6 +331,43 @@ namespace ts {
332331
type: "boolean",
333332
description: Diagnostics.Do_not_emit_use_strict_directives_in_module_output
334333
},
334+
{
335+
name: "lib",
336+
type: "list",
337+
element: {
338+
name: "lib",
339+
type: {
340+
// JavaScript only
341+
"es5": "lib.es5.d.ts",
342+
"es6": "lib.es2015.d.ts",
343+
"es2015": "lib.es2015.d.ts",
344+
"es7": "lib.es2016.d.ts",
345+
"es2016": "lib.es2016.d.ts",
346+
// Host only
347+
"dom": "lib.dom.d.ts",
348+
"webworker": "lib.webworker.d.ts",
349+
"scripthost": "lib.scripthost.d.ts",
350+
// ES2015 Or ESNext By-feature options
351+
"es2015.array": "lib.es2015.array.d.ts",
352+
"es2015.collection": "lib.es2015.collection.d.ts",
353+
"es2015.generator": "lib.es2015.generator.d.ts",
354+
"es2015.function": "lib.es2015.function.d.ts",
355+
"es2015.iterable": "lib.es2015.iterable.d.ts",
356+
"es2015.math": "lib.es2015.math.d.ts",
357+
"es2015.number": "lib.es2015.number.d.ts",
358+
"es2015.object": "lib.es2015.object.d.ts",
359+
"es2015.promise": "lib.es2015.promise.d.ts",
360+
"es2015.proxy": "lib.es2015.proxy.d.ts",
361+
"es2015.reflect": "lib.es2015.reflect.d.ts",
362+
"es2015.regexp": "lib.es2015.regexp.d.ts",
363+
"es2015.string": "lib.es2015.string.d.ts",
364+
"es2015.symbol": "lib.es2015.symbol.d.ts",
365+
"es2015.symbol.wellknown": "lib.es2015.symbol.wellknown.d.ts",
366+
"es2016.array.include": "lib.es2016.array.include.d.ts"
367+
},
368+
},
369+
description: Diagnostics.Specify_library_files_to_be_included_in_the_compilation_Colon
370+
},
335371
{
336372
name: "strictNullChecks",
337373
type: "boolean",
@@ -370,6 +406,7 @@ namespace ts {
370406
}
371407

372408
let optionNameMapCache: OptionNameMap;
409+
373410
/* @internal */
374411
export function getOptionNameMap(): OptionNameMap {
375412
if (optionNameMapCache) {
@@ -399,6 +436,32 @@ namespace ts {
399436
return createCompilerDiagnostic(Diagnostics.Argument_for_0_option_must_be_Colon_1, `--${opt.name}`, namesOfType);
400437
}
401438

439+
/* @internal */
440+
export function parseCustomTypeOption(opt: CommandLineOptionOfCustomType, value: string, errors: Diagnostic[]) {
441+
const key = (value || "").trim().toLowerCase();
442+
const map = opt.type;
443+
if (hasProperty(map, key)) {
444+
return map[key];
445+
}
446+
else {
447+
errors.push(createCompilerDiagnosticForInvalidCustomType(opt));
448+
}
449+
}
450+
451+
/* @internal */
452+
export function parseListTypeOption(opt: CommandLineOptionOfListType, value: string, errors: Diagnostic[]): (string | number)[] {
453+
const values = (value || "").trim().split(",");
454+
switch (opt.element.type) {
455+
case "number":
456+
return ts.map(values, parseInt);
457+
case "string":
458+
return ts.map(values, v => v || "");
459+
default:
460+
return filter(map(values, v => parseCustomTypeOption(<CommandLineOptionOfCustomType>opt.element, v, errors)), v => !!v);
461+
}
462+
}
463+
464+
/* @internal */
402465
export function parseCommandLine(commandLine: string[], readFile?: (path: string) => string): ParsedCommandLine {
403466
const options: CompilerOptions = {};
404467
const fileNames: string[] = [];
@@ -453,12 +516,12 @@ namespace ts {
453516
i++;
454517
break;
455518
case "list":
456-
options[opt.name] = parseListTypeOption(<CommandLineOptionOfListType>opt, args[i]);
519+
options[opt.name] = parseListTypeOption(<CommandLineOptionOfListType>opt, args[i], errors);
457520
i++;
458521
break;
459522
// If not a primitive, the possible types are specified in what is effectively a map of options.
460523
default:
461-
options[opt.name] = parseCustomTypeOption(<CommandLineOptionOfCustomType>opt, args[i]);
524+
options[opt.name] = parseCustomTypeOption(<CommandLineOptionOfCustomType>opt, args[i], errors);
462525
i++;
463526
break;
464527
}
@@ -471,29 +534,6 @@ namespace ts {
471534
else {
472535
fileNames.push(s);
473536
}
474-
475-
function parseCustomTypeOption(opt: CommandLineOptionOfCustomType, value: string) {
476-
const key = (value || "").trim().toLowerCase();
477-
const map = opt.type;
478-
if (hasProperty(map, key)) {
479-
return map[key];
480-
}
481-
else {
482-
errors.push(createCompilerDiagnosticForInvalidCustomType(opt));
483-
}
484-
}
485-
486-
function parseListTypeOption(opt: CommandLineOptionOfListType, value: string): (string | number)[] {
487-
const values = (value || "").trim().split(",");
488-
switch (opt.element.type) {
489-
case "number":
490-
return ts.map(values, parseInt);
491-
case "string":
492-
return ts.map(values, v => v || "");
493-
default:
494-
return filter(map(values, v => parseCustomTypeOption(<CommandLineOptionOfCustomType>opt.element, v)), v => !!v);
495-
}
496-
}
497537
}
498538
}
499539

src/compiler/diagnosticMessages.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2488,6 +2488,10 @@
24882488
"category": "Message",
24892489
"code": 6078
24902490
},
2491+
"Specify library files to be included in the compilation: ": {
2492+
"category": "Message",
2493+
"code": 6079
2494+
},
24912495
"Specify JSX code generation: 'preserve' or 'react'": {
24922496
"category": "Message",
24932497
"code": 6080

src/compiler/program.ts

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ namespace ts {
1515
export const version = "1.9.0";
1616

1717
export function findConfigFile(searchPath: string, fileExists: (fileName: string) => boolean): string {
18-
let fileName = "tsconfig.json";
1918
while (true) {
19+
const fileName = combinePaths(searchPath, "tsconfig.json");
2020
if (fileExists(fileName)) {
2121
return fileName;
2222
}
@@ -25,7 +25,6 @@ namespace ts {
2525
break;
2626
}
2727
searchPath = parentPath;
28-
fileName = "../" + fileName;
2928
}
3029
return undefined;
3130
}
@@ -630,10 +629,18 @@ namespace ts {
630629
}
631630
}
632631

632+
function getUserDefinedLibFileName(options: CompilerOptions): string[] {
633+
const directoryPath = getDirectoryPath(normalizePath(sys.getExecutingFilePath()));
634+
return options.lib.map(fileName => {
635+
return combinePaths(directoryPath, fileName);
636+
});
637+
}
638+
633639
const newLine = getNewLineCharacter(options);
634640

635641
return {
636642
getSourceFile,
643+
getUserDefinedLibFileName,
637644
getDefaultLibFileName: options => combinePaths(getDirectoryPath(normalizePath(sys.getExecutingFilePath())), getDefaultLibFileName(options)),
638645
writeFile,
639646
getCurrentDirectory: memoize(() => sys.getCurrentDirectory()),
@@ -754,7 +761,17 @@ namespace ts {
754761
// - A 'no-default-lib' reference comment is encountered in
755762
// processing the root files.
756763
if (!skipDefaultLib) {
757-
processRootFile(host.getDefaultLibFileName(options), /*isDefaultLib*/ true);
764+
// If '--lib' is not specified, include default library file according to '--target'
765+
// otherwise, using options specified in '--lib' instead of '--target' default library file
766+
if (!options.lib) {
767+
processRootFile(host.getDefaultLibFileName(options), /*isDefaultLib*/ true);
768+
}
769+
else {
770+
const libFileNames = host.getUserDefinedLibFileName(options);
771+
libFileNames.forEach(libFileName => {
772+
processRootFile(libFileName, /*isDefaultLib*/ true);
773+
});
774+
}
758775
}
759776
}
760777

@@ -1483,7 +1500,7 @@ namespace ts {
14831500

14841501
const basePath = getDirectoryPath(fileName);
14851502
if (!options.noResolve) {
1486-
processReferencedFiles(file, basePath);
1503+
processReferencedFiles(file, basePath, /*isDefaultLib*/ isDefaultLib);
14871504
}
14881505

14891506
// always process imported modules to record module name resolutions
@@ -1500,10 +1517,10 @@ namespace ts {
15001517
return file;
15011518
}
15021519

1503-
function processReferencedFiles(file: SourceFile, basePath: string) {
1520+
function processReferencedFiles(file: SourceFile, basePath: string, isDefaultLib: boolean) {
15041521
forEach(file.referencedFiles, ref => {
15051522
const referencedFileName = resolveTripleslashReference(ref.fileName, file.fileName);
1506-
processSourceFile(referencedFileName, /*isDefaultLib*/ false, /*isReference*/ true, file, ref.pos, ref.end);
1523+
processSourceFile(referencedFileName, isDefaultLib, /*isReference*/ true, file, ref.pos, ref.end);
15071524
});
15081525
}
15091526

@@ -1700,6 +1717,10 @@ namespace ts {
17001717
}
17011718
}
17021719

1720+
if (options.lib && options.noLib) {
1721+
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_with_option_1, "lib", "noLib"));
1722+
}
1723+
17031724
const languageVersion = options.target || ScriptTarget.ES3;
17041725
const outFile = options.outFile || options.out;
17051726

0 commit comments

Comments
 (0)