Skip to content

Commit

Permalink
Implement --lib flag in the compiler and harness
Browse files Browse the repository at this point in the history
  • Loading branch information
Kanchalai Tanglertsampan committed Mar 28, 2016
1 parent 168118f commit 3fef5ba
Show file tree
Hide file tree
Showing 13 changed files with 206 additions and 97 deletions.
61 changes: 26 additions & 35 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -138,7 +138,7 @@ namespace ts {

const globals: SymbolTable = {};

let globalESSymbolConstructorSymbol: Symbol;
let getGlobalESSymbolConstructorSymbol: () => Symbol;

let getGlobalPromiseConstructorSymbol: () => Symbol;

Expand All @@ -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;
Expand Down Expand Up @@ -3973,7 +3974,7 @@ namespace ts {
type = globalBooleanType;
}
else if (type.flags & TypeFlags.ESSymbol) {
type = globalESSymbolType;
type = getGlobalESSymbolType();
}
return type;
}
Expand Down Expand Up @@ -4744,10 +4745,6 @@ namespace ts {
return typeSymbol && getDeclaredTypeOfSymbol(typeSymbol);
}

function getGlobalESSymbolConstructorSymbol() {
return globalESSymbolConstructorSymbol || (globalESSymbolConstructorSymbol = getGlobalValueSymbol("Symbol"));
}

/**
* Creates a TypeReference for a generic `TypedPropertyDescriptor<T>`.
*/
Expand All @@ -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 {
Expand Down Expand Up @@ -10415,7 +10412,7 @@ namespace ts {
return getEffectiveDecoratorArgumentType(<Decorator>node, argIndex);
}
else if (argIndex === 0 && node.kind === SyntaxKind.TaggedTemplateExpression) {
return globalTemplateStringsArrayType;
return getGlobalTemplateStringsArrayType();
}

// This is not a synthetic argument, so we return 'undefined'
Expand Down Expand Up @@ -14179,7 +14176,7 @@ namespace ts {
if (!typeAsIterable.iterableElementType) {
// As an optimization, if the type is instantiated directly using the globalIterableType (Iterable<number>),
// then just grab its type argument.
if ((type.flags & TypeFlags.Reference) && (<GenericType>type).target === globalIterableType) {
if ((type.flags & TypeFlags.Reference) && (<GenericType>type).target === getGlobalIterableType()) {
typeAsIterable.iterableElementType = (<GenericType>type).typeArguments[0];
}
else {
Expand Down Expand Up @@ -14225,7 +14222,7 @@ namespace ts {
if (!typeAsIterator.iteratorElementType) {
// As an optimization, if the type is instantiated directly using the globalIteratorType (Iterator<number>),
// then just grab its type argument.
if ((type.flags & TypeFlags.Reference) && (<GenericType>type).target === globalIteratorType) {
if ((type.flags & TypeFlags.Reference) && (<GenericType>type).target === getGlobalIteratorType()) {
typeAsIterator.iteratorElementType = (<GenericType>type).typeArguments[0];
}
else {
Expand Down Expand Up @@ -14269,7 +14266,7 @@ namespace ts {

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

Expand Down Expand Up @@ -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));
Expand All @@ -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 = <GenericType>getGlobalType("Iterable", /*arity*/ 1);
globalIteratorType = <GenericType>getGlobalType("Iterator", /*arity*/ 1);
globalIterableIteratorType = <GenericType>getGlobalType("IterableIterator", /*arity*/ 1);
getGlobalESSymbolType = memoize(() => getGlobalType("Symbol"));
getGlobalIterableType = memoize(() => <GenericType>getGlobalType("Iterable", /*arity*/ 1));
getGlobalIteratorType = memoize(() => <GenericType>getGlobalType("Iterator", /*arity*/ 1));
getGlobalIterableIteratorType = memoize(() => <GenericType>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);
Expand Down
92 changes: 66 additions & 26 deletions src/compiler/commandLineParser.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,6 @@ namespace ts {
},
{
name: "pretty",
paramType: Diagnostics.KIND,
description: Diagnostics.Stylize_errors_and_messages_using_color_and_context_experimental,
type: "boolean"
},
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -370,6 +406,7 @@ namespace ts {
}

let optionNameMapCache: OptionNameMap;

/* @internal */
export function getOptionNameMap(): OptionNameMap {
if (optionNameMapCache) {
Expand Down Expand Up @@ -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(<CommandLineOptionOfCustomType>opt.element, v, errors)), v => !!v);
}
}

/* @internal */
export function parseCommandLine(commandLine: string[], readFile?: (path: string) => string): ParsedCommandLine {
const options: CompilerOptions = {};
const fileNames: string[] = [];
Expand Down Expand Up @@ -453,12 +516,12 @@ namespace ts {
i++;
break;
case "list":
options[opt.name] = parseListTypeOption(<CommandLineOptionOfListType>opt, args[i]);
options[opt.name] = parseListTypeOption(<CommandLineOptionOfListType>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(<CommandLineOptionOfCustomType>opt, args[i]);
options[opt.name] = parseCustomTypeOption(<CommandLineOptionOfCustomType>opt, args[i], errors);
i++;
break;
}
Expand All @@ -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(<CommandLineOptionOfCustomType>opt.element, v)), v => !!v);
}
}
}
}

Expand Down
4 changes: 4 additions & 0 deletions src/compiler/diagnosticMessages.json
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
33 changes: 27 additions & 6 deletions src/compiler/program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand All @@ -25,7 +25,6 @@ namespace ts {
break;
}
searchPath = parentPath;
fileName = "../" + fileName;
}
return undefined;
}
Expand Down Expand Up @@ -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()),
Expand Down Expand Up @@ -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);
});
}
}
}

Expand Down Expand Up @@ -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
Expand All @@ -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);
});
}

Expand Down Expand Up @@ -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;

Expand Down
Loading

0 comments on commit 3fef5ba

Please sign in to comment.