Merge branch 'master' into cast_of_await

This commit is contained in:
Andy Hanson
2016-08-19 06:16:57 -07:00
850 changed files with 26597 additions and 35015 deletions
+74 -73
View File
@@ -89,9 +89,10 @@ namespace ts {
const binder = createBinder();
export function bindSourceFile(file: SourceFile, options: CompilerOptions) {
const start = performance.mark();
performance.mark("beforeBind");
binder(file, options);
performance.measure("Bind", start);
performance.mark("afterBind");
performance.measure("Bind", "beforeBind", "afterBind");
}
function createBinder(): (file: SourceFile, options: CompilerOptions) => void {
@@ -135,7 +136,7 @@ namespace ts {
options = opts;
languageVersion = getEmitScriptTarget(options);
inStrictMode = !!file.externalModuleIndicator;
classifiableNames = {};
classifiableNames = createMap<string>();
symbolCount = 0;
Symbol = objectAllocator.getSymbolConstructor();
@@ -183,11 +184,11 @@ namespace ts {
symbol.declarations.push(node);
if (symbolFlags & SymbolFlags.HasExports && !symbol.exports) {
symbol.exports = {};
symbol.exports = createMap<Symbol>();
}
if (symbolFlags & SymbolFlags.HasMembers && !symbol.members) {
symbol.members = {};
symbol.members = createMap<Symbol>();
}
if (symbolFlags & SymbolFlags.Value) {
@@ -298,8 +299,10 @@ namespace ts {
const name = isDefaultExport && parent ? "default" : getDeclarationName(node);
let symbol: Symbol;
if (name !== undefined) {
if (name === undefined) {
symbol = createSymbol(SymbolFlags.None, "__missing");
}
else {
// Check and see if the symbol table already has a symbol with this name. If not,
// create a new symbol with this name and add it to the table. Note that we don't
// give the new symbol any flags *yet*. This ensures that it will not conflict
@@ -311,6 +314,11 @@ namespace ts {
// declaration we have for this symbol, and then create a new symbol for this
// declaration.
//
// Note that when properties declared in Javascript constructors
// (marked by isReplaceableByMethod) conflict with another symbol, the property loses.
// Always. This allows the common Javascript pattern of overwriting a prototype method
// with an bound instance method of the same type: `this.method = this.method.bind(this)`
//
// If we created a new symbol, either because we didn't have a symbol with this name
// in the symbol table, or we conflicted with an existing symbol, then just add this
// node as the sole declaration of the new symbol.
@@ -318,42 +326,44 @@ namespace ts {
// Otherwise, we'll be merging into a compatible existing symbol (for example when
// you have multiple 'vars' with the same name in the same container). In this case
// just add this node into the declarations list of the symbol.
symbol = hasProperty(symbolTable, name)
? symbolTable[name]
: (symbolTable[name] = createSymbol(SymbolFlags.None, name));
symbol = symbolTable[name] || (symbolTable[name] = createSymbol(SymbolFlags.None, name));
if (name && (includes & SymbolFlags.Classifiable)) {
classifiableNames[name] = name;
}
if (symbol.flags & excludes) {
if (node.name) {
node.name.parent = node;
if (symbol.isReplaceableByMethod) {
// Javascript constructor-declared symbols can be discarded in favor of
// prototype symbols like methods.
symbol = symbolTable[name] = createSymbol(SymbolFlags.None, name);
}
// Report errors every position with duplicate declaration
// Report errors on previous encountered declarations
let message = symbol.flags & SymbolFlags.BlockScopedVariable
? Diagnostics.Cannot_redeclare_block_scoped_variable_0
: Diagnostics.Duplicate_identifier_0;
forEach(symbol.declarations, declaration => {
if (declaration.flags & NodeFlags.Default) {
message = Diagnostics.A_module_cannot_have_multiple_default_exports;
else {
if (node.name) {
node.name.parent = node;
}
});
forEach(symbol.declarations, declaration => {
file.bindDiagnostics.push(createDiagnosticForNode(declaration.name || declaration, message, getDisplayName(declaration)));
});
file.bindDiagnostics.push(createDiagnosticForNode(node.name || node, message, getDisplayName(node)));
// Report errors every position with duplicate declaration
// Report errors on previous encountered declarations
let message = symbol.flags & SymbolFlags.BlockScopedVariable
? Diagnostics.Cannot_redeclare_block_scoped_variable_0
: Diagnostics.Duplicate_identifier_0;
symbol = createSymbol(SymbolFlags.None, name);
forEach(symbol.declarations, declaration => {
if (declaration.flags & NodeFlags.Default) {
message = Diagnostics.A_module_cannot_have_multiple_default_exports;
}
});
forEach(symbol.declarations, declaration => {
file.bindDiagnostics.push(createDiagnosticForNode(declaration.name || declaration, message, getDisplayName(declaration)));
});
file.bindDiagnostics.push(createDiagnosticForNode(node.name || node, message, getDisplayName(node)));
symbol = createSymbol(SymbolFlags.None, name);
}
}
}
else {
symbol = createSymbol(SymbolFlags.None, "__missing");
}
addDeclarationToSymbol(symbol, node, includes);
symbol.parent = parent;
@@ -434,7 +444,7 @@ namespace ts {
if (containerFlags & ContainerFlags.IsContainer) {
container = blockScopeContainer = node;
if (containerFlags & ContainerFlags.HasLocals) {
container.locals = {};
container.locals = createMap<Symbol>();
}
addToContainerChain(container);
}
@@ -618,18 +628,10 @@ namespace ts {
return false;
}
function isNarrowingNullCheckOperands(expr1: Expression, expr2: Expression) {
return (expr1.kind === SyntaxKind.NullKeyword || expr1.kind === SyntaxKind.Identifier && (<Identifier>expr1).text === "undefined") && isNarrowableOperand(expr2);
}
function isNarrowingTypeofOperands(expr1: Expression, expr2: Expression) {
return expr1.kind === SyntaxKind.TypeOfExpression && isNarrowableOperand((<TypeOfExpression>expr1).expression) && expr2.kind === SyntaxKind.StringLiteral;
}
function isNarrowingDiscriminant(expr: Expression) {
return expr.kind === SyntaxKind.PropertyAccessExpression && isNarrowableReference((<PropertyAccessExpression>expr).expression);
}
function isNarrowingBinaryExpression(expr: BinaryExpression) {
switch (expr.operatorToken.kind) {
case SyntaxKind.EqualsToken:
@@ -638,9 +640,8 @@ namespace ts {
case SyntaxKind.ExclamationEqualsToken:
case SyntaxKind.EqualsEqualsEqualsToken:
case SyntaxKind.ExclamationEqualsEqualsToken:
return isNarrowingNullCheckOperands(expr.right, expr.left) || isNarrowingNullCheckOperands(expr.left, expr.right) ||
isNarrowingTypeofOperands(expr.right, expr.left) || isNarrowingTypeofOperands(expr.left, expr.right) ||
isNarrowingDiscriminant(expr.left) || isNarrowingDiscriminant(expr.right);
return isNarrowableOperand(expr.left) || isNarrowableOperand(expr.right) ||
isNarrowingTypeofOperands(expr.right, expr.left) || isNarrowingTypeofOperands(expr.left, expr.right);
case SyntaxKind.InstanceOfKeyword:
return isNarrowableOperand(expr.left);
case SyntaxKind.CommaToken:
@@ -664,11 +665,6 @@ namespace ts {
return isNarrowableReference(expr);
}
function isNarrowingSwitchStatement(switchStatement: SwitchStatement) {
const expr = switchStatement.expression;
return expr.kind === SyntaxKind.PropertyAccessExpression && isNarrowableReference((<PropertyAccessExpression>expr).expression);
}
function createBranchLabel(): FlowLabel {
return {
flags: FlowFlags.BranchLabel,
@@ -718,7 +714,7 @@ namespace ts {
}
function createFlowSwitchClause(antecedent: FlowNode, switchStatement: SwitchStatement, clauseStart: number, clauseEnd: number): FlowNode {
if (!isNarrowingSwitchStatement(switchStatement)) {
if (!isNarrowingExpression(switchStatement.expression)) {
return antecedent;
}
setFlowNodeReferenced(antecedent);
@@ -1413,7 +1409,8 @@ namespace ts {
const typeLiteralSymbol = createSymbol(SymbolFlags.TypeLiteral, "__type");
addDeclarationToSymbol(typeLiteralSymbol, node, SymbolFlags.TypeLiteral);
typeLiteralSymbol.members = { [symbol.name]: symbol };
typeLiteralSymbol.members = createMap<Symbol>();
typeLiteralSymbol.members[symbol.name] = symbol;
}
function bindObjectLiteralExpression(node: ObjectLiteralExpression) {
@@ -1423,7 +1420,7 @@ namespace ts {
}
if (inStrictMode) {
const seen: Map<ElementKind> = {};
const seen = createMap<ElementKind>();
for (const prop of node.properties) {
if (prop.name.kind !== SyntaxKind.Identifier) {
@@ -1479,7 +1476,7 @@ namespace ts {
// fall through.
default:
if (!blockScopeContainer.locals) {
blockScopeContainer.locals = {};
blockScopeContainer.locals = createMap<Symbol>();
addToContainerChain(blockScopeContainer);
}
declareSymbol(blockScopeContainer.locals, undefined, node, symbolFlags, symbolExcludes);
@@ -1901,18 +1898,17 @@ namespace ts {
}
function bindExportAssignment(node: ExportAssignment | BinaryExpression) {
const boundExpression = node.kind === SyntaxKind.ExportAssignment ? (<ExportAssignment>node).expression : (<BinaryExpression>node).right;
if (!container.symbol || !container.symbol.exports) {
// Export assignment in some sort of block construct
bindAnonymousDeclaration(node, SymbolFlags.Alias, getDeclarationName(node));
}
else if (boundExpression.kind === SyntaxKind.Identifier && node.kind === SyntaxKind.ExportAssignment) {
// An export default clause with an identifier exports all meanings of that identifier
declareSymbol(container.symbol.exports, container.symbol, node, SymbolFlags.Alias, SymbolFlags.PropertyExcludes | SymbolFlags.AliasExcludes);
}
else {
// An export default clause with an expression exports a value
declareSymbol(container.symbol.exports, container.symbol, node, SymbolFlags.Property, SymbolFlags.PropertyExcludes | SymbolFlags.AliasExcludes);
const flags = node.kind === SyntaxKind.ExportAssignment && exportAssignmentIsAlias(<ExportAssignment>node)
// An export default clause with an EntityNameExpression exports all meanings of that identifier
? SymbolFlags.Alias
// An export default clause with any other expression exports a value
: SymbolFlags.Property;
declareSymbol(container.symbol.exports, container.symbol, node, flags, SymbolFlags.PropertyExcludes | SymbolFlags.AliasExcludes);
}
}
@@ -1939,7 +1935,7 @@ namespace ts {
}
}
file.symbol.globalExports = file.symbol.globalExports || {};
file.symbol.globalExports = file.symbol.globalExports || createMap<Symbol>();
declareSymbol(file.symbol.globalExports, file.symbol, node, SymbolFlags.Alias, SymbolFlags.AliasExcludes);
}
@@ -1981,20 +1977,25 @@ namespace ts {
}
function bindThisPropertyAssignment(node: BinaryExpression) {
// Declare a 'member' in case it turns out the container was an ES5 class or ES6 constructor
let assignee: Node;
if (container.kind === SyntaxKind.FunctionDeclaration || container.kind === SyntaxKind.FunctionDeclaration) {
assignee = container;
Debug.assert(isInJavaScriptFile(node));
// Declare a 'member' if the container is an ES5 class or ES6 constructor
if (container.kind === SyntaxKind.FunctionDeclaration || container.kind === SyntaxKind.FunctionExpression) {
container.symbol.members = container.symbol.members || createMap<Symbol>();
// It's acceptable for multiple 'this' assignments of the same identifier to occur
declareSymbol(container.symbol.members, container.symbol, node, SymbolFlags.Property, SymbolFlags.PropertyExcludes & ~SymbolFlags.Property);
}
else if (container.kind === SyntaxKind.Constructor) {
assignee = container.parent;
// this.foo assignment in a JavaScript class
// Bind this property to the containing class
const saveContainer = container;
container = container.parent;
const symbol = bindPropertyOrMethodOrAccessor(node, SymbolFlags.Property, SymbolFlags.None);
if (symbol) {
// constructor-declared symbols can be overwritten by subsequent method declarations
(symbol as Symbol).isReplaceableByMethod = true;
}
container = saveContainer;
}
else {
return;
}
assignee.symbol.members = assignee.symbol.members || {};
// It's acceptable for multiple 'this' assignments of the same identifier to occur
declareSymbol(assignee.symbol.members, assignee.symbol, node, SymbolFlags.Property, SymbolFlags.PropertyExcludes & ~SymbolFlags.Property);
}
function bindPrototypePropertyAssignment(node: BinaryExpression) {
@@ -2018,7 +2019,7 @@ namespace ts {
// Set up the members collection if it doesn't exist already
if (!funcSymbol.members) {
funcSymbol.members = {};
funcSymbol.members = createMap<Symbol>();
}
// Declare the method/property
@@ -2067,7 +2068,7 @@ namespace ts {
// module might have an exported variable called 'prototype'. We can't allow that as
// that would clash with the built-in 'prototype' for the class.
const prototypeSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Prototype, "prototype");
if (hasProperty(symbol.exports, prototypeSymbol.name)) {
if (symbol.exports[prototypeSymbol.name]) {
if (node.name) {
node.name.parent = node;
}
+1422 -830
View File
File diff suppressed because it is too large Load Diff
+132 -42
View File
@@ -61,10 +61,10 @@ namespace ts {
},
{
name: "jsx",
type: {
type: createMap({
"preserve": JsxEmit.Preserve,
"react": JsxEmit.React
},
}),
paramType: Diagnostics.KIND,
description: Diagnostics.Specify_JSX_code_generation_Colon_preserve_or_react,
},
@@ -91,7 +91,7 @@ namespace ts {
{
name: "module",
shortName: "m",
type: {
type: createMap({
"none": ModuleKind.None,
"commonjs": ModuleKind.CommonJS,
"amd": ModuleKind.AMD,
@@ -99,16 +99,16 @@ namespace ts {
"umd": ModuleKind.UMD,
"es6": ModuleKind.ES6,
"es2015": ModuleKind.ES2015,
},
}),
description: Diagnostics.Specify_module_code_generation_Colon_commonjs_amd_system_umd_or_es2015,
paramType: Diagnostics.KIND,
},
{
name: "newLine",
type: {
type: createMap({
"crlf": NewLineKind.CarriageReturnLineFeed,
"lf": NewLineKind.LineFeed
},
}),
description: Diagnostics.Specify_the_end_of_line_sequence_to_be_used_when_emitting_files_Colon_CRLF_dos_or_LF_unix,
paramType: Diagnostics.NEWLINE,
},
@@ -126,6 +126,10 @@ namespace ts {
type: "boolean",
description: Diagnostics.Do_not_emit_outputs_if_any_errors_were_reported,
},
{
name: "noErrorTruncation",
type: "boolean"
},
{
name: "noImplicitAny",
type: "boolean",
@@ -139,12 +143,12 @@ namespace ts {
{
name: "noUnusedLocals",
type: "boolean",
description: Diagnostics.Report_errors_on_unused_locals,
description: Diagnostics.Report_errors_on_unused_locals,
},
{
name: "noUnusedParameters",
type: "boolean",
description: Diagnostics.Report_errors_on_unused_parameters,
description: Diagnostics.Report_errors_on_unused_parameters,
},
{
name: "noLib",
@@ -250,12 +254,12 @@ namespace ts {
{
name: "target",
shortName: "t",
type: {
type: createMap({
"es3": ScriptTarget.ES3,
"es5": ScriptTarget.ES5,
"es6": ScriptTarget.ES6,
"es2015": ScriptTarget.ES2015,
},
}),
description: Diagnostics.Specify_ECMAScript_target_version_Colon_ES3_default_ES5_or_ES2015,
paramType: Diagnostics.VERSION,
},
@@ -284,10 +288,10 @@ namespace ts {
},
{
name: "moduleResolution",
type: {
type: createMap({
"node": ModuleResolutionKind.NodeJs,
"classic": ModuleResolutionKind.Classic,
},
}),
description: Diagnostics.Specify_module_resolution_strategy_Colon_node_Node_js_or_classic_TypeScript_pre_1_6,
},
{
@@ -392,7 +396,7 @@ namespace ts {
type: "list",
element: {
name: "lib",
type: {
type: createMap({
// JavaScript only
"es5": "lib.es5.d.ts",
"es6": "lib.es2015.d.ts",
@@ -417,7 +421,7 @@ namespace ts {
"es2016.array.include": "lib.es2016.array.include.d.ts",
"es2017.object": "lib.es2017.object.d.ts",
"es2017.sharedmemory": "lib.es2017.sharedmemory.d.ts"
},
}),
},
description: Diagnostics.Specify_library_files_to_be_included_in_the_compilation_Colon
},
@@ -462,6 +466,14 @@ namespace ts {
shortOptionNames: Map<string>;
}
/* @internal */
export const defaultInitCompilerOptions: CompilerOptions = {
module: ModuleKind.CommonJS,
target: ScriptTarget.ES5,
noImplicitAny: false,
sourceMap: false,
};
let optionNameMapCache: OptionNameMap;
/* @internal */
@@ -470,8 +482,8 @@ namespace ts {
return optionNameMapCache;
}
const optionNameMap: Map<CommandLineOption> = {};
const shortOptionNames: Map<string> = {};
const optionNameMap = createMap<CommandLineOption>();
const shortOptionNames = createMap<string>();
forEach(optionDeclarations, option => {
optionNameMap[option.name.toLowerCase()] = option;
if (option.shortName) {
@@ -486,10 +498,9 @@ namespace ts {
/* @internal */
export function createCompilerDiagnosticForInvalidCustomType(opt: CommandLineOptionOfCustomType): Diagnostic {
const namesOfType: string[] = [];
forEachKey(opt.type, key => {
for (const key in opt.type) {
namesOfType.push(` '${key}'`);
});
}
return createCompilerDiagnostic(Diagnostics.Argument_for_0_option_must_be_Colon_1, `--${opt.name}`, namesOfType);
}
@@ -497,7 +508,7 @@ namespace ts {
export function parseCustomTypeOption(opt: CommandLineOptionOfCustomType, value: string, errors: Diagnostic[]) {
const key = trimString((value || "")).toLowerCase();
const map = opt.type;
if (hasProperty(map, key)) {
if (key in map) {
return map[key];
}
else {
@@ -551,11 +562,11 @@ namespace ts {
s = s.slice(s.charCodeAt(1) === CharacterCodes.minus ? 2 : 1).toLowerCase();
// Try to translate short option names to their full equivalents.
if (hasProperty(shortOptionNames, s)) {
if (s in shortOptionNames) {
s = shortOptionNames[s];
}
if (hasProperty(optionNameMap, s)) {
if (s in optionNameMap) {
const opt = optionNameMap[s];
if (opt.isTSConfigOnly) {
@@ -668,6 +679,94 @@ namespace ts {
}
}
/**
* Generate tsconfig configuration when running command line "--init"
* @param options commandlineOptions to be generated into tsconfig.json
* @param fileNames array of filenames to be generated into tsconfig.json
*/
/* @internal */
export function generateTSConfig(options: CompilerOptions, fileNames: string[]): { compilerOptions: Map<CompilerOptionsValue> } {
const compilerOptions = extend(options, defaultInitCompilerOptions);
const configurations: any = {
compilerOptions: serializeCompilerOptions(compilerOptions)
};
if (fileNames && fileNames.length) {
// only set the files property if we have at least one file
configurations.files = fileNames;
}
return configurations;
function getCustomTypeMapOfCommandLineOption(optionDefinition: CommandLineOption): Map<string | number> | undefined {
if (optionDefinition.type === "string" || optionDefinition.type === "number" || optionDefinition.type === "boolean") {
// this is of a type CommandLineOptionOfPrimitiveType
return undefined;
}
else if (optionDefinition.type === "list") {
return getCustomTypeMapOfCommandLineOption((<CommandLineOptionOfListType>optionDefinition).element);
}
else {
return (<CommandLineOptionOfCustomType>optionDefinition).type;
}
}
function getNameOfCompilerOptionValue(value: CompilerOptionsValue, customTypeMap: MapLike<string | number>): string | undefined {
// There is a typeMap associated with this command-line option so use it to map value back to its name
for (const key in customTypeMap) {
if (customTypeMap[key] === value) {
return key;
}
}
return undefined;
}
function serializeCompilerOptions(options: CompilerOptions): Map<CompilerOptionsValue> {
const result = createMap<CompilerOptionsValue>();
const optionsNameMap = getOptionNameMap().optionNameMap;
for (const name in options) {
if (hasProperty(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
switch (name) {
case "init":
case "watch":
case "version":
case "help":
case "project":
break;
default:
const value = options[name];
let optionDefinition = optionsNameMap[name.toLowerCase()];
if (optionDefinition) {
const customTypeMap = getCustomTypeMapOfCommandLineOption(optionDefinition);
if (!customTypeMap) {
// There is no map associated with this compiler option then use the value as-is
// This is the case if the value is expect to be string, number, boolean or list of string
result[name] = value;
}
else {
if (optionDefinition.type === "list") {
const convertedValue: string[] = [];
for (const element of value as (string | number)[]) {
convertedValue.push(getNameOfCompilerOptionValue(element, customTypeMap));
}
result[name] = convertedValue;
}
else {
// There is a typeMap associated with this command-line option so use it to map value back to its name
result[name] = getNameOfCompilerOptionValue(value, customTypeMap);
}
}
}
break;
}
}
}
return result;
}
}
/**
* Remove the comments from a json like text.
* Comments can be single line comments (starting with # or //) or multiline comments using / * * /
@@ -693,9 +792,6 @@ namespace ts {
return output;
}
// Skip over any minified JavaScript files (ending in ".min.js")
// Skip over dotted files and folders as well
const ignoreFileNamePattern = /(\.min\.js$)|([\\/]\.[\w.])/;
/**
* Parse the contents of a config file (tsconfig.json).
* @param json The contents of the config file to parse
@@ -814,7 +910,7 @@ namespace ts {
const optionNameMap = arrayToMap(optionDeclarations, opt => opt.name);
for (const id in jsonOptions) {
if (hasProperty(optionNameMap, id)) {
if (id in optionNameMap) {
const opt = optionNameMap[id];
defaultOptions[opt.name] = convertJsonOption(opt, jsonOptions[id], basePath, errors);
}
@@ -851,7 +947,7 @@ namespace ts {
function convertJsonOptionOfCustomType(opt: CommandLineOptionOfCustomType, value: string, errors: Diagnostic[]) {
const key = value.toLowerCase();
if (hasProperty(opt.type, key)) {
if (key in opt.type) {
return opt.type[key];
}
else {
@@ -961,12 +1057,12 @@ namespace ts {
// Literal file names (provided via the "files" array in tsconfig.json) are stored in a
// file map with a possibly case insensitive key. We use this map later when when including
// wildcard paths.
const literalFileMap: Map<string> = {};
const literalFileMap = createMap<string>();
// Wildcard paths (provided via the "includes" array in tsconfig.json) are stored in a
// file map with a possibly case insensitive key. We use this map to store paths matched
// via wildcard, and to handle extension priority.
const wildcardFileMap: Map<string> = {};
const wildcardFileMap = createMap<string>();
if (include) {
include = validateSpecs(include, errors, /*allowTrailingRecursion*/ false);
@@ -1007,10 +1103,6 @@ namespace ts {
continue;
}
if (ignoreFileNamePattern.test(file)) {
continue;
}
// We may have included a wildcard path with a lower priority
// extension due to the user-defined order of entries in the
// "include" array. If there is a lower priority extension in the
@@ -1018,7 +1110,7 @@ namespace ts {
removeWildcardFilesWithLowerPriorityExtension(file, wildcardFileMap, supportedExtensions, keyMapper);
const key = keyMapper(file);
if (!hasProperty(literalFileMap, key) && !hasProperty(wildcardFileMap, key)) {
if (!(key in literalFileMap) && !(key in wildcardFileMap)) {
wildcardFileMap[key] = file;
}
}
@@ -1070,7 +1162,7 @@ namespace ts {
// /a/b/a?z - Watch /a/b directly to catch any new file matching a?z
const rawExcludeRegex = getRegularExpressionForWildcard(exclude, path, "exclude");
const excludeRegex = rawExcludeRegex && new RegExp(rawExcludeRegex, useCaseSensitiveFileNames ? "" : "i");
const wildcardDirectories: Map<WatchDirectoryFlags> = {};
const wildcardDirectories = createMap<WatchDirectoryFlags>();
if (include !== undefined) {
const recursiveKeys: string[] = [];
for (const file of include) {
@@ -1083,7 +1175,7 @@ namespace ts {
if (match) {
const key = useCaseSensitiveFileNames ? match[0] : match[0].toLowerCase();
const flags = watchRecursivePattern.test(name) ? WatchDirectoryFlags.Recursive : WatchDirectoryFlags.None;
const existingFlags = getProperty(wildcardDirectories, key);
const existingFlags = wildcardDirectories[key];
if (existingFlags === undefined || existingFlags < flags) {
wildcardDirectories[key] = flags;
if (flags === WatchDirectoryFlags.Recursive) {
@@ -1095,11 +1187,9 @@ namespace ts {
// Remove any subpaths under an existing recursively watched directory.
for (const key in wildcardDirectories) {
if (hasProperty(wildcardDirectories, key)) {
for (const recursiveKey of recursiveKeys) {
if (key !== recursiveKey && containsPath(recursiveKey, key, path, !useCaseSensitiveFileNames)) {
delete wildcardDirectories[key];
}
for (const recursiveKey of recursiveKeys) {
if (key !== recursiveKey && containsPath(recursiveKey, key, path, !useCaseSensitiveFileNames)) {
delete wildcardDirectories[key];
}
}
}
@@ -1122,7 +1212,7 @@ namespace ts {
for (let i = ExtensionPriority.Highest; i < adjustedExtensionPriority; i++) {
const higherPriorityExtension = extensions[i];
const higherPriorityPath = keyMapper(changeExtension(file, higherPriorityExtension));
if (hasProperty(literalFiles, higherPriorityPath) || hasProperty(wildcardFiles, higherPriorityPath)) {
if (higherPriorityPath in literalFiles || higherPriorityPath in wildcardFiles) {
return true;
}
}
+270 -100
View File
@@ -19,8 +19,28 @@ namespace ts {
True = -1
}
const createObject = Object.create;
export function createMap<T>(template?: MapLike<T>): Map<T> {
const map: Map<T> = createObject(null); // tslint:disable-line:no-null-keyword
// Using 'delete' on an object causes V8 to put the object in dictionary mode.
// This disables creation of hidden classes, which are expensive when an object is
// constantly changing shape.
map["__"] = undefined;
delete map["__"];
// Copies keys/values from template. Note that for..in will not throw if
// template is undefined, and instead will just exit the loop.
for (const key in template) if (hasOwnProperty.call(template, key)) {
map[key] = template[key];
}
return map;
}
export function createFileMap<T>(keyMapper?: (key: string) => string): FileMap<T> {
let files: Map<T> = {};
let files = createMap<T>();
return {
get,
set,
@@ -46,7 +66,7 @@ namespace ts {
}
function contains(path: Path) {
return hasProperty(files, toKey(path));
return toKey(path) in files;
}
function remove(path: Path) {
@@ -55,7 +75,7 @@ namespace ts {
}
function clear() {
files = {};
files = createMap<T>();
}
function toKey(path: Path): string {
@@ -81,7 +101,7 @@ namespace ts {
* returns a truthy value, then returns that value.
* If no such value is found, the callback is applied to each element of array and undefined is returned.
*/
export function forEach<T, U>(array: T[], callback: (element: T, index: number) => U): U {
export function forEach<T, U>(array: T[] | undefined, callback: (element: T, index: number) => U | undefined): U | undefined {
if (array) {
for (let i = 0, len = array.length; i < len; i++) {
const result = callback(array[i], i);
@@ -93,10 +113,21 @@ namespace ts {
return undefined;
}
export function contains<T>(array: T[], value: T, areEqual?: (a: T, b: T) => boolean): boolean {
/** Like `forEach`, but assumes existence of array and fails if no truthy value is found. */
export function find<T, U>(array: T[], callback: (element: T, index: number) => U | undefined): U {
for (let i = 0, len = array.length; i < len; i++) {
const result = callback(array[i], i);
if (result) {
return result;
}
}
Debug.fail();
}
export function contains<T>(array: T[], value: T): boolean {
if (array) {
for (const v of array) {
if (areEqual ? areEqual(v, value) : v === value) {
if (v === value) {
return true;
}
}
@@ -136,17 +167,44 @@ namespace ts {
return count;
}
/**
* Filters an array by a predicate function. Returns the same array instance if the predicate is
* true for all elements, otherwise returns a new array instance containing the filtered subset.
*/
export function filter<T>(array: T[], f: (x: T) => boolean): T[] {
let result: T[];
if (array) {
result = [];
for (const item of array) {
if (f(item)) {
result.push(item);
const len = array.length;
let i = 0;
while (i < len && f(array[i])) i++;
if (i < len) {
const result = array.slice(0, i);
i++;
while (i < len) {
const item = array[i];
if (f(item)) {
result.push(item);
}
i++;
}
return result;
}
}
return result;
return array;
}
export function removeWhere<T>(array: T[], f: (x: T) => boolean): boolean {
let outIndex = 0;
for (const item of array) {
if (!f(item)) {
array[outIndex] = item;
outIndex++;
}
}
if (outIndex !== array.length) {
array.length = outIndex;
return true;
}
return false;
}
export function filterMutate<T>(array: T[], f: (x: T) => boolean): void {
@@ -182,10 +240,13 @@ namespace ts {
let result: T[];
if (array) {
result = [];
for (const item of array) {
if (!contains(result, item, areEqual)) {
result.push(item);
loop: for (const item of array) {
for (const res of result) {
if (areEqual ? areEqual(res, item) : res === item) {
continue loop;
}
}
result.push(item);
}
}
return result;
@@ -308,78 +369,142 @@ namespace ts {
const hasOwnProperty = Object.prototype.hasOwnProperty;
export function hasProperty<T>(map: Map<T>, key: string): boolean {
/**
* Indicates whether a map-like contains an own property with the specified key.
*
* NOTE: This is intended for use only with MapLike<T> objects. For Map<T> objects, use
* the 'in' operator.
*
* @param map A map-like.
* @param key A property key.
*/
export function hasProperty<T>(map: MapLike<T>, key: string): boolean {
return hasOwnProperty.call(map, key);
}
export function getKeys<T>(map: Map<T>): string[] {
/**
* Gets the value of an owned property in a map-like.
*
* NOTE: This is intended for use only with MapLike<T> objects. For Map<T> objects, use
* an indexer.
*
* @param map A map-like.
* @param key A property key.
*/
export function getProperty<T>(map: MapLike<T>, key: string): T | undefined {
return hasOwnProperty.call(map, key) ? map[key] : undefined;
}
/**
* Gets the owned, enumerable property keys of a map-like.
*
* NOTE: This is intended for use with MapLike<T> objects. For Map<T> objects, use
* Object.keys instead as it offers better performance.
*
* @param map A map-like.
*/
export function getOwnKeys<T>(map: MapLike<T>): string[] {
const keys: string[] = [];
for (const key in map) {
for (const key in map) if (hasOwnProperty.call(map, key)) {
keys.push(key);
}
return keys;
}
export function getProperty<T>(map: Map<T>, key: string): T {
return hasOwnProperty.call(map, key) ? map[key] : undefined;
/**
* Enumerates the properties of a Map<T>, invoking a callback and returning the first truthy result.
*
* @param map A map for which properties should be enumerated.
* @param callback A callback to invoke for each property.
*/
export function forEachProperty<T, U>(map: Map<T>, callback: (value: T, key: string) => U): U {
let result: U;
for (const key in map) {
if (result = callback(map[key], key)) break;
}
return result;
}
export function isEmpty<T>(map: Map<T>) {
for (const id in map) {
if (hasProperty(map, id)) {
return false;
}
/**
* Returns true if a Map<T> has some matching property.
*
* @param map A map whose properties should be tested.
* @param predicate An optional callback used to test each property.
*/
export function someProperties<T>(map: Map<T>, predicate?: (value: T, key: string) => boolean) {
for (const key in map) {
if (!predicate || predicate(map[key], key)) return true;
}
return false;
}
/**
* Performs a shallow copy of the properties from a source Map<T> to a target MapLike<T>
*
* @param source A map from which properties should be copied.
* @param target A map to which properties should be copied.
*/
export function copyProperties<T>(source: Map<T>, target: MapLike<T>): void {
for (const key in source) {
target[key] = source[key];
}
}
/**
* Reduce the properties of a map.
*
* NOTE: This is intended for use with Map<T> objects. For MapLike<T> objects, use
* reduceOwnProperties instead as it offers better runtime safety.
*
* @param map The map to reduce
* @param callback An aggregation function that is called for each entry in the map
* @param initial The initial value for the reduction.
*/
export function reduceProperties<T, U>(map: Map<T>, callback: (aggregate: U, value: T, key: string) => U, initial: U): U {
let result = initial;
for (const key in map) {
result = callback(result, map[key], String(key));
}
return result;
}
/**
* Reduce the properties defined on a map-like (but not from its prototype chain).
*
* NOTE: This is intended for use with MapLike<T> objects. For Map<T> objects, use
* reduceProperties instead as it offers better performance.
*
* @param map The map-like to reduce
* @param callback An aggregation function that is called for each entry in the map
* @param initial The initial value for the reduction.
*/
export function reduceOwnProperties<T, U>(map: MapLike<T>, callback: (aggregate: U, value: T, key: string) => U, initial: U): U {
let result = initial;
for (const key in map) if (hasOwnProperty.call(map, key)) {
result = callback(result, map[key], String(key));
}
return result;
}
/**
* Performs a shallow equality comparison of the contents of two map-likes.
*
* @param left A map-like whose properties should be compared.
* @param right A map-like whose properties should be compared.
*/
export function equalOwnProperties<T>(left: MapLike<T>, right: MapLike<T>, equalityComparer?: (left: T, right: T) => boolean) {
if (left === right) return true;
if (!left || !right) return false;
for (const key in left) if (hasOwnProperty.call(left, key)) {
if (!hasOwnProperty.call(right, key) === undefined) return false;
if (equalityComparer ? !equalityComparer(left[key], right[key]) : left[key] !== right[key]) return false;
}
for (const key in right) if (hasOwnProperty.call(right, key)) {
if (!hasOwnProperty.call(left, key)) return false;
}
return true;
}
export function clone<T>(object: T): T {
const result: any = {};
for (const id in object) {
result[id] = (<any>object)[id];
}
return <T>result;
}
export function extend<T1 extends Map<{}>, T2 extends Map<{}>>(first: T1 , second: T2): T1 & T2 {
const result: T1 & T2 = <any>{};
for (const id in first) {
(result as any)[id] = first[id];
}
for (const id in second) {
if (!hasProperty(result, id)) {
(result as any)[id] = second[id];
}
}
return result;
}
export function forEachValue<T, U>(map: Map<T>, callback: (value: T) => U): U {
let result: U;
for (const id in map) {
if (result = callback(map[id])) break;
}
return result;
}
export function forEachKey<T, U>(map: Map<T>, callback: (key: string) => U): U {
let result: U;
for (const id in map) {
if (result = callback(id)) break;
}
return result;
}
export function lookUp<T>(map: Map<T>, key: string): T {
return hasProperty(map, key) ? map[key] : undefined;
}
export function copyMap<T>(source: Map<T>, target: Map<T>): void {
for (const p in source) {
target[p] = source[p];
}
}
/**
* Creates a map from the elements of an array.
*
@@ -390,33 +515,40 @@ namespace ts {
* the same key with the given 'makeKey' function, then the element with the higher
* index in the array will be the one associated with the produced key.
*/
export function arrayToMap<T>(array: T[], makeKey: (value: T) => string): Map<T> {
const result: Map<T> = {};
forEach(array, value => {
result[makeKey(value)] = value;
});
export function arrayToMap<T>(array: T[], makeKey: (value: T) => string): Map<T>;
export function arrayToMap<T, U>(array: T[], makeKey: (value: T) => string, makeValue: (value: T) => U): Map<U>;
export function arrayToMap<T, U>(array: T[], makeKey: (value: T) => string, makeValue?: (value: T) => U): Map<T | U> {
const result = createMap<T | U>();
for (const value of array) {
result[makeKey(value)] = makeValue ? makeValue(value) : value;
}
return result;
}
/**
* Reduce the properties of a map.
*
* @param map The map to reduce
* @param callback An aggregation function that is called for each entry in the map
* @param initial The initial value for the reduction.
*/
export function reduceProperties<T, U>(map: Map<T>, callback: (aggregate: U, value: T, key: string) => U, initial: U): U {
let result = initial;
if (map) {
for (const key in map) {
if (hasProperty(map, key)) {
result = callback(result, map[key], String(key));
}
export function cloneMap<T>(map: Map<T>) {
const clone = createMap<T>();
copyProperties(map, clone);
return clone;
}
export function clone<T>(object: T): T {
const result: any = {};
for (const id in object) {
if (hasOwnProperty.call(object, id)) {
result[id] = (<any>object)[id];
}
}
return result;
}
export function extend<T1, T2>(first: T1 , second: T2): T1 & T2 {
const result: T1 & T2 = <any>{};
for (const id in second) if (hasOwnProperty.call(second, id)) {
(result as any)[id] = (second as any)[id];
}
for (const id in first) if (hasOwnProperty.call(first, id)) {
(result as any)[id] = (first as any)[id];
}
return result;
}
@@ -447,9 +579,7 @@ namespace ts {
export let localizedDiagnosticMessages: Map<string> = undefined;
export function getLocaleSpecificMessage(message: DiagnosticMessage) {
return localizedDiagnosticMessages && localizedDiagnosticMessages[message.key]
? localizedDiagnosticMessages[message.key]
: message.message;
return localizedDiagnosticMessages && localizedDiagnosticMessages[message.key] || message.message;
}
export function createFileDiagnostic(file: SourceFile, start: number, length: number, message: DiagnosticMessage, ...args: any[]): Diagnostic;
@@ -932,11 +1062,29 @@ namespace ts {
const reservedCharacterPattern = /[^\w\s\/]/g;
const wildcardCharCodes = [CharacterCodes.asterisk, CharacterCodes.question];
/**
* Matches any single directory segment unless it is the last segment and a .min.js file
* Breakdown:
* [^./] # matches everything up to the first . character (excluding directory seperators)
* (\\.(?!min\\.js$))? # matches . characters but not if they are part of the .min.js file extension
*/
const singleAsteriskRegexFragmentFiles = "([^./]|(\\.(?!min\\.js$))?)*";
const singleAsteriskRegexFragmentOther = "[^/]*";
export function getRegularExpressionForWildcard(specs: string[], basePath: string, usage: "files" | "directories" | "exclude") {
if (specs === undefined || specs.length === 0) {
return undefined;
}
const replaceWildcardCharacter = usage === "files" ? replaceWildCardCharacterFiles : replaceWildCardCharacterOther;
const singleAsteriskRegexFragment = usage === "files" ? singleAsteriskRegexFragmentFiles : singleAsteriskRegexFragmentOther;
/**
* Regex for the ** wildcard. Matches any number of subdirectories. When used for including
* files or directories, does not match subdirectories that start with a . character
*/
const doubleAsteriskRegexFragment = usage === "exclude" ? "(/.+?)?" : "(/[^/.][^/]*)*?";
let pattern = "";
let hasWrittenSubpattern = false;
spec: for (const spec of specs) {
@@ -957,13 +1105,13 @@ namespace ts {
components[0] = removeTrailingDirectorySeparator(components[0]);
let optionalCount = 0;
for (const component of components) {
for (let component of components) {
if (component === "**") {
if (hasRecursiveDirectoryWildcard) {
continue spec;
}
subpattern += "(/.+?)?";
subpattern += doubleAsteriskRegexFragment;
hasRecursiveDirectoryWildcard = true;
hasWrittenComponent = true;
}
@@ -977,6 +1125,20 @@ namespace ts {
subpattern += directorySeparator;
}
if (usage !== "exclude") {
// The * and ? wildcards should not match directories or files that start with . if they
// appear first in a component. Dotted directories and files can be included explicitly
// like so: **/.*/.*
if (component.charCodeAt(0) === CharacterCodes.asterisk) {
subpattern += "([^./]" + singleAsteriskRegexFragment + ")?";
component = component.substr(1);
}
else if (component.charCodeAt(0) === CharacterCodes.question) {
subpattern += "[^./]";
component = component.substr(1);
}
}
subpattern += component.replace(reservedCharacterPattern, replaceWildcardCharacter);
hasWrittenComponent = true;
}
@@ -1002,8 +1164,16 @@ namespace ts {
return "^(" + pattern + (usage === "exclude" ? ")($|/)" : ")$");
}
function replaceWildcardCharacter(match: string) {
return match === "*" ? "[^/]*" : match === "?" ? "[^/]" : "\\" + match;
function replaceWildCardCharacterFiles(match: string) {
return replaceWildcardCharacter(match, singleAsteriskRegexFragmentFiles);
}
function replaceWildCardCharacterOther(match: string) {
return replaceWildcardCharacter(match, singleAsteriskRegexFragmentOther);
}
function replaceWildcardCharacter(match: string, singleAsteriskRegexFragment: string) {
return match === "*" ? singleAsteriskRegexFragment : match === "?" ? "[^/]" : "\\" + match;
}
export interface FileSystemEntries {
+10 -12
View File
@@ -157,9 +157,7 @@ namespace ts {
if (usedTypeDirectiveReferences) {
for (const directive in usedTypeDirectiveReferences) {
if (hasProperty(usedTypeDirectiveReferences, directive)) {
referencesOutput += `/// <reference types="${directive}" />${newLine}`;
}
referencesOutput += `/// <reference types="${directive}" />${newLine}`;
}
}
@@ -269,10 +267,10 @@ namespace ts {
}
if (!usedTypeDirectiveReferences) {
usedTypeDirectiveReferences = {};
usedTypeDirectiveReferences = createMap<string>();
}
for (const directive of typeReferenceDirectives) {
if (!hasProperty(usedTypeDirectiveReferences, directive)) {
if (!(directive in usedTypeDirectiveReferences)) {
usedTypeDirectiveReferences[directive] = directive;
}
}
@@ -397,7 +395,7 @@ namespace ts {
case SyntaxKind.NullKeyword:
case SyntaxKind.NeverKeyword:
case SyntaxKind.ThisType:
case SyntaxKind.StringLiteralType:
case SyntaxKind.LiteralType:
return writeTextOfNode(currentText, type);
case SyntaxKind.ExpressionWithTypeArguments:
return emitExpressionWithTypeArguments(<ExpressionWithTypeArguments>type);
@@ -441,7 +439,7 @@ namespace ts {
}
}
function emitEntityName(entityName: EntityName | PropertyAccessExpression) {
function emitEntityName(entityName: EntityNameOrEntityNameExpression) {
const visibilityResult = resolver.isEntityNameVisible(entityName,
// Aliases can be written asynchronously so use correct enclosing declaration
entityName.parent.kind === SyntaxKind.ImportEqualsDeclaration ? entityName.parent : enclosingDeclaration);
@@ -452,9 +450,9 @@ namespace ts {
}
function emitExpressionWithTypeArguments(node: ExpressionWithTypeArguments) {
if (isSupportedExpressionWithTypeArguments(node)) {
if (isEntityNameExpression(node.expression)) {
Debug.assert(node.expression.kind === SyntaxKind.Identifier || node.expression.kind === SyntaxKind.PropertyAccessExpression);
emitEntityName(<Identifier | PropertyAccessExpression>node.expression);
emitEntityName(node.expression);
if (node.typeArguments) {
write("<");
emitCommaList(node.typeArguments, emitType);
@@ -537,14 +535,14 @@ namespace ts {
// do not need to keep track of created temp names.
function getExportDefaultTempVariableName(): string {
const baseName = "_default";
if (!hasProperty(currentIdentifiers, baseName)) {
if (!(baseName in currentIdentifiers)) {
return baseName;
}
let count = 0;
while (true) {
count++;
const name = baseName + "_" + count;
if (!hasProperty(currentIdentifiers, name)) {
if (!(name in currentIdentifiers)) {
return name;
}
}
@@ -1019,7 +1017,7 @@ namespace ts {
}
function emitTypeOfTypeReference(node: ExpressionWithTypeArguments) {
if (isSupportedExpressionWithTypeArguments(node)) {
if (isEntityNameExpression(node.expression)) {
emitTypeWithNewGetSymbolAccessibilityDiagnostic(node, getHeritageClauseVisibilityError);
}
else if (!isImplementsList && node.expression.kind === SyntaxKind.NullKeyword) {
+19 -3
View File
@@ -1755,6 +1755,10 @@
"category": "Error",
"code": 2534
},
"Enum type '{0}' has members with initializers that are not literals.": {
"category": "Error",
"code": 2535
},
"JSX element attributes type '{0}' may not be a union type.": {
"category": "Error",
"code": 2600
@@ -1943,6 +1947,10 @@
"category": "Error",
"code": 2689
},
"A class must be declared after its base class.": {
"category": "Error",
"code": 2690
},
"Import declaration '{0}' is using private name '{1}'.": {
"category": "Error",
"code": 4000
@@ -2223,7 +2231,7 @@
"category": "Error",
"code": 4082
},
"Conflicting library definitions for '{0}' found at '{1}' and '{2}'. Copy the correct file to the 'typings' folder to resolve this conflict.": {
"Conflicting definitions for '{0}' found at '{1}' and '{2}'. Consider installing a specific version of this library to resolve the conflict.": {
"category": "Message",
"code": 4090
},
@@ -2336,6 +2344,10 @@
"category": "Error",
"code": 5065
},
"Substitutions for pattern '{0}' shouldn't be an empty array.": {
"category": "Error",
"code": 5066
},
"Concatenate and emit output to single file.": {
"category": "Message",
"code": 6001
@@ -2800,11 +2812,11 @@
"category": "Error",
"code": 6133
},
"Report errors on unused locals.": {
"Report errors on unused locals.": {
"category": "Message",
"code": 6134
},
"Report errors on unused parameters.": {
"Report errors on unused parameters.": {
"category": "Message",
"code": 6135
},
@@ -2816,6 +2828,10 @@
"category": "Message",
"code": 6137
},
"Property '{0}' is declared but never used.": {
"category": "Error",
"code": 6138
},
"Variable '{0}' implicitly has an '{1}' type.": {
"category": "Error",
"code": 7005
+55 -45
View File
@@ -24,7 +24,7 @@ namespace ts {
Return = 1 << 3
}
const entities: Map<number> = {
const entities = createMap({
"quot": 0x0022,
"amp": 0x0026,
"apos": 0x0027,
@@ -278,7 +278,7 @@ namespace ts {
"clubs": 0x2663,
"hearts": 0x2665,
"diams": 0x2666
};
});
// Flags enum to track count of temp variables and a few dedicated names
const enum TempFlags {
@@ -407,7 +407,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
function isUniqueLocalName(name: string, container: Node): boolean {
for (let node = container; isNodeDescendentOf(node, container); node = node.nextContainer) {
if (node.locals && hasProperty(node.locals, name)) {
if (node.locals && name in node.locals) {
// We conservatively include alias symbols to cover cases where they're emitted as locals
if (node.locals[name].flags & (SymbolFlags.Value | SymbolFlags.ExportValue | SymbolFlags.Alias)) {
return false;
@@ -489,13 +489,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
function setLabeledJump(state: ConvertedLoopState, isBreak: boolean, labelText: string, labelMarker: string): void {
if (isBreak) {
if (!state.labeledNonLocalBreaks) {
state.labeledNonLocalBreaks = {};
state.labeledNonLocalBreaks = createMap<string>();
}
state.labeledNonLocalBreaks[labelText] = labelMarker;
}
else {
if (!state.labeledNonLocalContinues) {
state.labeledNonLocalContinues = {};
state.labeledNonLocalContinues = createMap<string>();
}
state.labeledNonLocalContinues[labelText] = labelMarker;
}
@@ -577,27 +577,27 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
const setSourceMapWriterEmit = compilerOptions.sourceMap || compilerOptions.inlineSourceMap ? changeSourceMapEmit : function (writer: SourceMapWriter) { };
const moduleEmitDelegates: Map<(node: SourceFile, emitRelativePathAsModuleName?: boolean) => void> = {
const moduleEmitDelegates = createMap<(node: SourceFile, emitRelativePathAsModuleName?: boolean) => void>({
[ModuleKind.ES6]: emitES6Module,
[ModuleKind.AMD]: emitAMDModule,
[ModuleKind.System]: emitSystemModule,
[ModuleKind.UMD]: emitUMDModule,
[ModuleKind.CommonJS]: emitCommonJSModule,
};
});
const bundleEmitDelegates: Map<(node: SourceFile, emitRelativePathAsModuleName?: boolean) => void> = {
const bundleEmitDelegates = createMap<(node: SourceFile, emitRelativePathAsModuleName?: boolean) => void>({
[ModuleKind.ES6]() {},
[ModuleKind.AMD]: emitAMDModule,
[ModuleKind.System]: emitSystemModule,
[ModuleKind.UMD]() {},
[ModuleKind.CommonJS]() {},
};
});
return doEmit;
function doEmit(jsFilePath: string, sourceMapFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean) {
sourceMap.initialize(jsFilePath, sourceMapFilePath, sourceFiles, isBundledEmit);
generatedNameSet = {};
generatedNameSet = createMap<string>();
nodeToGeneratedName = [];
decoratedClassAliases = [];
isOwnFileEmit = !isBundledEmit;
@@ -669,8 +669,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
function isUniqueName(name: string): boolean {
return !resolver.hasGlobalName(name) &&
!hasProperty(currentFileIdentifiers, name) &&
!hasProperty(generatedNameSet, name);
!(name in currentFileIdentifiers) &&
!(name in generatedNameSet);
}
// Return the next available name in the pattern _a ... _z, _0, _1, ...
@@ -2578,7 +2578,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
operand = (<TypeAssertion | NonNullExpression>operand).expression;
}
// We have an expression of the form: (<Type>SubExpr)
// We have an expression of the form: (<Type>SubExpr) or (SubExpr as Type)
// Emitting this as (SubExpr) is really not desirable. We would like to emit the subexpr as is.
// Omitting the parentheses, however, could cause change in the semantics of the generated
// code if the casted expression has a lower precedence than the rest of the expression, e.g.:
@@ -2592,6 +2592,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
operand.kind !== SyntaxKind.DeleteExpression &&
operand.kind !== SyntaxKind.PostfixUnaryExpression &&
operand.kind !== SyntaxKind.NewExpression &&
!(operand.kind === SyntaxKind.BinaryExpression && node.expression.kind === SyntaxKind.AsExpression) &&
!(operand.kind === SyntaxKind.CallExpression && node.parent.kind === SyntaxKind.NewExpression) &&
!(operand.kind === SyntaxKind.FunctionExpression && node.parent.kind === SyntaxKind.CallExpression) &&
!(operand.kind === SyntaxKind.NumericLiteral && node.parent.kind === SyntaxKind.PropertyAccessExpression)) {
@@ -2645,7 +2646,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
return false;
}
return !exportEquals && exportSpecifiers && hasProperty(exportSpecifiers, (<Identifier>node).text);
return !exportEquals && exportSpecifiers && (<Identifier>node).text in exportSpecifiers;
}
function emitPrefixUnaryExpression(node: PrefixUnaryExpression) {
@@ -2667,7 +2668,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
isNameOfExportedDeclarationInNonES6Module(node.operand);
if (internalExportChanged) {
emitAliasEqual(<Identifier> node.operand);
emitAliasEqual(<Identifier>node.operand);
}
write(tokenToString(node.operator));
@@ -2722,7 +2723,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
}
}
else if (internalExportChanged) {
emitAliasEqual(<Identifier> node.operand);
emitAliasEqual(<Identifier>node.operand);
emit(node.operand);
if (node.operator === SyntaxKind.PlusPlusToken) {
write(" += 1");
@@ -3256,13 +3257,13 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
// Don't initialize seen unless we have at least one element.
// Emit a comma to separate for all but the first element.
if (!seen) {
seen = {};
seen = createMap<string>();
}
else {
write(", ");
}
if (!hasProperty(seen, id.text)) {
if (!(id.text in seen)) {
emit(id);
seen[id.text] = id.text;
}
@@ -3855,7 +3856,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
if (convertedLoopState) {
if (!convertedLoopState.labels) {
convertedLoopState.labels = {};
convertedLoopState.labels = createMap<string>();
}
convertedLoopState.labels[node.label.text] = node.label.text;
}
@@ -3969,7 +3970,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
return;
}
if (!exportEquals && exportSpecifiers && hasProperty(exportSpecifiers, name.text)) {
if (!exportEquals && exportSpecifiers && name.text in exportSpecifiers) {
for (const specifier of exportSpecifiers[name.text]) {
writeLine();
emitStart(specifier.name);
@@ -5310,18 +5311,22 @@ const _super = (function (geti, seti) {
emitSignatureParameters(ctor);
}
else {
// Based on EcmaScript6 section 14.5.14: Runtime Semantics: ClassDefinitionEvaluation.
// If constructor is empty, then,
// If ClassHeritageopt is present, then
// Let constructor be the result of parsing the String "constructor(... args){ super (...args);}" using the syntactic grammar with the goal symbol MethodDefinition.
// The ES2015 spec specifies in 14.5.14. Runtime Semantics: ClassDefinitionEvaluation:
// If constructor is empty, then
// If ClassHeritag_eopt is present and protoParent is not null, then
// Let constructor be the result of parsing the source text
// constructor(...args) { super (...args);}
// using the syntactic grammar with the goal symbol MethodDefinition[~Yield].
// Else,
// Let constructor be the result of parsing the String "constructor( ){ }" using the syntactic grammar with the goal symbol MethodDefinition
if (baseTypeElement) {
write("(...args)");
}
else {
write("()");
}
// Let constructor be the result of parsing the source text
// constructor( ){ }
// using the syntactic grammar with the goal symbol MethodDefinition[~Yield].
//
// While we could emit the '...args' rest parameter, certain later tools in the pipeline might
// downlevel the '...args' portion less efficiently by naively copying the contents of 'arguments' to an array.
// Instead, we'll avoid using a rest parameter and spread into the super call as
// 'super(...arguments)' instead of 'super(...args)', as you can see below.
write("()");
}
}
@@ -5359,7 +5364,8 @@ const _super = (function (geti, seti) {
write("_super.apply(this, arguments);");
}
else {
write("super(...args);");
// See comment above on using '...arguments' instead of '...args'.
write("super(...arguments);");
}
emitEnd(baseTypeElement);
}
@@ -5526,13 +5532,17 @@ const _super = (function (geti, seti) {
// If the class has static properties, and it's a class expression, then we'll need
// to specialize the emit a bit. for a class expression of the form:
//
// class C { static a = 1; static b = 2; ... }
// (class C { static a = 1; static b = 2; ... })
//
// We'll emit:
//
// let C_1 = class C{};
// C_1.a = 1;
// C_1.b = 2; // so forth and so on
// ((C_1 = class C {
// // Normal class body
// },
// C_1.a = 1,
// C_1.b = 2,
// C_1));
// var C_1;
//
// This keeps the expression as an expression, while ensuring that the static parts
// of it have been initialized by the time it is used.
@@ -5541,7 +5551,7 @@ const _super = (function (geti, seti) {
let generatedName: string;
if (isClassExpressionWithStaticProperties) {
generatedName = getGeneratedNameForNode(node.name);
generatedName = node.name ? getGeneratedNameForNode(node.name) : makeUniqueName("classExpression");
const synthesizedNode = <Identifier>createSynthesizedNode(SyntaxKind.Identifier);
synthesizedNode.text = generatedName;
recordTempDeclaration(synthesizedNode);
@@ -6041,7 +6051,7 @@ const _super = (function (geti, seti) {
return;
case SyntaxKind.StringKeyword:
case SyntaxKind.StringLiteralType:
case SyntaxKind.LiteralType:
write("String");
return;
@@ -6456,7 +6466,7 @@ const _super = (function (geti, seti) {
* Here we check if alternative name was provided for a given moduleName and return it if possible.
*/
function tryRenameExternalModule(moduleName: LiteralExpression): string {
if (renamedDependencies && hasProperty(renamedDependencies, moduleName.text)) {
if (renamedDependencies && moduleName.text in renamedDependencies) {
return `"${renamedDependencies[moduleName.text]}"`;
}
return undefined;
@@ -6798,7 +6808,7 @@ const _super = (function (geti, seti) {
function collectExternalModuleInfo(sourceFile: SourceFile) {
externalImports = [];
exportSpecifiers = {};
exportSpecifiers = createMap<ExportSpecifier[]>();
exportEquals = undefined;
hasExportStarsToExportValues = false;
for (const node of sourceFile.statements) {
@@ -6936,7 +6946,7 @@ const _super = (function (geti, seti) {
}
// local names set should only be added if we have anything exported
if (!exportedDeclarations && isEmpty(exportSpecifiers)) {
if (!exportedDeclarations && !someProperties(exportSpecifiers)) {
// no exported declarations (export var ...) or export specifiers (export {x})
// check if we have any non star export declarations.
let hasExportDeclarationWithExportClause = false;
@@ -7076,7 +7086,7 @@ const _super = (function (geti, seti) {
if (hoistedVars) {
writeLine();
write("var ");
const seen: Map<string> = {};
const seen = createMap<string>();
for (let i = 0; i < hoistedVars.length; i++) {
const local = hoistedVars[i];
const name = local.kind === SyntaxKind.Identifier
@@ -7086,7 +7096,7 @@ const _super = (function (geti, seti) {
if (name) {
// do not emit duplicate entries (in case of declaration merging) in the list of hoisted variables
const text = unescapeIdentifier(name.text);
if (hasProperty(seen, text)) {
if (text in seen) {
continue;
}
else {
@@ -7442,7 +7452,7 @@ const _super = (function (geti, seti) {
writeModuleName(node, emitRelativePathAsModuleName);
write("[");
const groupIndices: Map<number> = {};
const groupIndices = createMap<number>();
const dependencyGroups: DependencyGroup[] = [];
for (let i = 0; i < externalImports.length; i++) {
@@ -7455,7 +7465,7 @@ const _super = (function (geti, seti) {
// for deduplication purposes in key remove leading and trailing quotes so 'a' and "a" will be considered the same
const key = text.substr(1, text.length - 2);
if (hasProperty(groupIndices, key)) {
if (key in groupIndices) {
// deduplicate/group entries in dependency list by the dependency name
const groupIndex = groupIndices[key];
dependencyGroups[groupIndex].push(externalImports[i]);
+353 -312
View File
File diff suppressed because it is too large Load Diff
+52 -66
View File
@@ -2,75 +2,61 @@
namespace ts {
declare const performance: { now?(): number } | undefined;
/** Gets a timestamp with (at least) ms resolution */
export const timestamp = typeof performance !== "undefined" && performance.now ? performance.now : Date.now ? Date.now : () => +(new Date());
export const timestamp = typeof performance !== "undefined" && performance.now ? () => performance.now() : Date.now ? Date.now : () => +(new Date());
}
/*@internal*/
/** Performance measurements for the compiler. */
namespace ts.performance {
/** Performance measurements for the compiler. */
declare const onProfilerEvent: { (markName: string): void; profiler: boolean; };
let profilerEvent: (markName: string) => void;
let counters: Map<number>;
const profilerEvent = typeof onProfilerEvent === "function" && onProfilerEvent.profiler === true
? onProfilerEvent
: (markName: string) => { };
let enabled = false;
let profilerStart = 0;
let counts: Map<number>;
let marks: Map<number>;
let measures: Map<number>;
/**
* Emit a performance event if ts-profiler is connected. This is primarily used
* to generate heap snapshots.
* Marks a performance event.
*
* @param eventName A name for the event.
* @param markName The name of the mark.
*/
export function emit(eventName: string) {
if (profilerEvent) {
profilerEvent(eventName);
export function mark(markName: string) {
if (enabled) {
marks[markName] = timestamp();
counts[markName] = (counts[markName] || 0) + 1;
profilerEvent(markName);
}
}
/**
* Increments a counter with the specified name.
*
* @param counterName The name of the counter.
*/
export function increment(counterName: string) {
if (counters) {
counters[counterName] = (getProperty(counters, counterName) || 0) + 1;
}
}
/**
* Gets the value of the counter with the specified name.
*
* @param counterName The name of the counter.
*/
export function getCount(counterName: string) {
return counters && getProperty(counters, counterName) || 0;
}
/**
* Marks the start of a performance measurement.
*/
export function mark() {
return measures ? timestamp() : 0;
}
/**
* Adds a performance measurement with the specified name.
*
* @param measureName The name of the performance measurement.
* @param marker The timestamp of the starting mark.
* @param startMarkName The name of the starting mark. If not supplied, the point at which the
* profiler was enabled is used.
* @param endMarkName The name of the ending mark. If not supplied, the current timestamp is
* used.
*/
export function measure(measureName: string, marker: number) {
if (measures) {
measures[measureName] = (getProperty(measures, measureName) || 0) + (timestamp() - marker);
export function measure(measureName: string, startMarkName?: string, endMarkName?: string) {
if (enabled) {
const end = endMarkName && marks[endMarkName] || timestamp();
const start = startMarkName && marks[startMarkName] || profilerStart;
measures[measureName] = (measures[measureName] || 0) + (end - start);
}
}
/**
* Iterate over each measure, performing some action
*
* @param cb The action to perform for each measure
* Gets the number of times a marker was encountered.
*
* @param markName The name of the mark.
*/
export function forEachMeasure(cb: (measureName: string, duration: number) => void) {
return forEachKey(measures, key => cb(key, measures[key]));
export function getCount(markName: string) {
return counts && counts[markName] || 0;
}
/**
@@ -79,31 +65,31 @@ namespace ts.performance {
* @param measureName The name of the measure whose durations should be accumulated.
*/
export function getDuration(measureName: string) {
return measures && getProperty(measures, measureName) || 0;
return measures && measures[measureName] || 0;
}
/**
* Iterate over each measure, performing some action
*
* @param cb The action to perform for each measure
*/
export function forEachMeasure(cb: (measureName: string, duration: number) => void) {
for (const key in measures) {
cb(key, measures[key]);
}
}
/** Enables (and resets) performance measurements for the compiler. */
export function enable() {
counters = { };
measures = {
"I/O Read": 0,
"I/O Write": 0,
"Program": 0,
"Parse": 0,
"Bind": 0,
"Check": 0,
"Emit": 0,
};
profilerEvent = typeof onProfilerEvent === "function" && onProfilerEvent.profiler === true
? onProfilerEvent
: undefined;
counts = createMap<number>();
marks = createMap<number>();
measures = createMap<number>();
enabled = true;
profilerStart = timestamp();
}
/** Disables (and clears) performance measurements for the compiler. */
/** Disables performance measurements for the compiler. */
export function disable() {
counters = undefined;
measures = undefined;
profilerEvent = undefined;
enabled = false;
}
}
}
+100 -103
View File
@@ -119,49 +119,31 @@ namespace ts {
}
function tryReadTypesSection(packageJsonPath: string, baseDirectory: string, state: ModuleResolutionState): string {
let jsonContent: { typings?: string, types?: string, main?: string };
try {
const jsonText = state.host.readFile(packageJsonPath);
jsonContent = jsonText ? <{ typings?: string, types?: string, main?: string }>JSON.parse(jsonText) : {};
}
catch (e) {
// gracefully handle if readFile fails or returns not JSON
jsonContent = {};
const jsonContent = readJson(packageJsonPath, state.host);
function tryReadFromField(fieldName: string) {
if (hasProperty(jsonContent, fieldName)) {
const typesFile = (<any>jsonContent)[fieldName];
if (typeof typesFile === "string") {
const typesFilePath = normalizePath(combinePaths(baseDirectory, typesFile));
if (state.traceEnabled) {
trace(state.host, Diagnostics.package_json_has_0_field_1_that_references_2, fieldName, typesFile, typesFilePath);
}
return typesFilePath;
}
else {
if (state.traceEnabled) {
trace(state.host, Diagnostics.Expected_type_of_0_field_in_package_json_to_be_string_got_1, fieldName, typeof typesFile);
}
}
}
}
let typesFile: string;
let fieldName: string;
// first try to read content of 'typings' section (backward compatibility)
if (jsonContent.typings) {
if (typeof jsonContent.typings === "string") {
fieldName = "typings";
typesFile = jsonContent.typings;
}
else {
if (state.traceEnabled) {
trace(state.host, Diagnostics.Expected_type_of_0_field_in_package_json_to_be_string_got_1, "typings", typeof jsonContent.typings);
}
}
}
// then read 'types'
if (!typesFile && jsonContent.types) {
if (typeof jsonContent.types === "string") {
fieldName = "types";
typesFile = jsonContent.types;
}
else {
if (state.traceEnabled) {
trace(state.host, Diagnostics.Expected_type_of_0_field_in_package_json_to_be_string_got_1, "types", typeof jsonContent.types);
}
}
}
if (typesFile) {
const typesFilePath = normalizePath(combinePaths(baseDirectory, typesFile));
if (state.traceEnabled) {
trace(state.host, Diagnostics.package_json_has_0_field_1_that_references_2, fieldName, typesFile, typesFilePath);
}
const typesFilePath = tryReadFromField("typings") || tryReadFromField("types");
if (typesFilePath) {
return typesFilePath;
}
// Use the main module for inferring types if no types package specified and the allowJs is set
if (state.compilerOptions.allowJs && jsonContent.main && typeof jsonContent.main === "string") {
if (state.traceEnabled) {
@@ -173,6 +155,17 @@ namespace ts {
return undefined;
}
function readJson(path: string, host: ModuleResolutionHost): { typings?: string, types?: string, main?: string } {
try {
const jsonText = host.readFile(path);
return jsonText ? JSON.parse(jsonText) : {};
}
catch (e) {
// gracefully handle if readFile fails or returns not JSON
return {};
}
}
const typeReferenceExtensions = [".d.ts"];
function getEffectiveTypeRoots(options: CompilerOptions, host: ModuleResolutionHost) {
@@ -508,7 +501,7 @@ namespace ts {
if (state.traceEnabled) {
trace(state.host, Diagnostics.paths_option_is_specified_looking_for_a_pattern_to_match_module_name_0, moduleName);
}
matchedPattern = matchPatternOrExact(getKeys(state.compilerOptions.paths), moduleName);
matchedPattern = matchPatternOrExact(getOwnKeys(state.compilerOptions.paths), moduleName);
}
if (matchedPattern) {
@@ -717,7 +710,7 @@ namespace ts {
}
function loadNodeModuleFromDirectory(extensions: string[], candidate: string, failedLookupLocation: string[], onlyRecordFailures: boolean, state: ModuleResolutionState): string {
const packageJsonPath = combinePaths(candidate, "package.json");
const packageJsonPath = pathToPackageJson(candidate);
const directoryExists = !onlyRecordFailures && directoryProbablyExists(candidate, state.host);
if (directoryExists && state.host.fileExists(packageJsonPath)) {
if (state.traceEnabled) {
@@ -747,6 +740,10 @@ namespace ts {
return loadModuleFromFile(combinePaths(candidate, "index"), extensions, failedLookupLocation, !directoryExists, state);
}
function pathToPackageJson(directory: string): string {
return combinePaths(directory, "package.json");
}
function loadModuleFromNodeModulesFolder(moduleName: string, directory: string, failedLookupLocations: string[], state: ModuleResolutionState): string {
const nodeModulesFolder = combinePaths(directory, "node_modules");
const nodeModulesFolderExists = directoryProbablyExists(nodeModulesFolder, state.host);
@@ -831,14 +828,6 @@ namespace ts {
: { resolvedModule: undefined, failedLookupLocations };
}
/* @internal */
export const defaultInitCompilerOptions: CompilerOptions = {
module: ModuleKind.CommonJS,
target: ScriptTarget.ES5,
noImplicitAny: false,
sourceMap: false,
};
interface OutputFingerprint {
hash: string;
byteOrderMark: boolean;
@@ -846,7 +835,7 @@ namespace ts {
}
export function createCompilerHost(options: CompilerOptions, setParentNodes?: boolean): CompilerHost {
const existingDirectories: Map<boolean> = {};
const existingDirectories = createMap<boolean>();
function getCanonicalFileName(fileName: string): string {
// if underlying system can distinguish between two files whose names differs only in cases then file name already in canonical form.
@@ -860,9 +849,10 @@ namespace ts {
function getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile {
let text: string;
try {
const start = performance.mark();
performance.mark("beforeIORead");
text = sys.readFile(fileName, options.charset);
performance.measure("I/O Read", start);
performance.mark("afterIORead");
performance.measure("I/O Read", "beforeIORead", "afterIORead");
}
catch (e) {
if (onError) {
@@ -877,7 +867,7 @@ namespace ts {
}
function directoryExists(directoryPath: string): boolean {
if (hasProperty(existingDirectories, directoryPath)) {
if (directoryPath in existingDirectories) {
return true;
}
if (sys.directoryExists(directoryPath)) {
@@ -899,13 +889,13 @@ namespace ts {
function writeFileIfUpdated(fileName: string, data: string, writeByteOrderMark: boolean): void {
if (!outputFingerprints) {
outputFingerprints = {};
outputFingerprints = createMap<OutputFingerprint>();
}
const hash = sys.createHash(data);
const mtimeBefore = sys.getModifiedTime(fileName);
if (mtimeBefore && hasProperty(outputFingerprints, fileName)) {
if (mtimeBefore && fileName in outputFingerprints) {
const fingerprint = outputFingerprints[fileName];
// If output has not been changed, and the file has no external modification
@@ -929,7 +919,7 @@ namespace ts {
function writeFile(fileName: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void) {
try {
const start = performance.mark();
performance.mark("beforeIOWrite");
ensureDirectoriesExist(getDirectoryPath(normalizePath(fileName)));
if (isWatchSet(options) && sys.createHash && sys.getModifiedTime) {
@@ -939,7 +929,8 @@ namespace ts {
sys.writeFile(fileName, data, writeByteOrderMark);
}
performance.measure("I/O Write", start);
performance.mark("afterIOWrite");
performance.measure("I/O Write", "beforeIOWrite", "afterIOWrite");
}
catch (e) {
if (onError) {
@@ -1040,47 +1031,47 @@ namespace ts {
return [];
}
const resolutions: T[] = [];
const cache: Map<T> = {};
const cache = createMap<T>();
for (const name of names) {
let result: T;
if (hasProperty(cache, name)) {
result = cache[name];
}
else {
result = loader(name, containingFile);
cache[name] = result;
}
const result = name in cache
? cache[name]
: cache[name] = loader(name, containingFile);
resolutions.push(result);
}
return resolutions;
}
function getInferredTypesRoot(options: CompilerOptions, rootFiles: string[], host: CompilerHost) {
return computeCommonSourceDirectoryOfFilenames(rootFiles, host.getCurrentDirectory(), f => host.getCanonicalFileName(f));
}
/**
* Given a set of options and a set of root files, returns the set of type directive names
* Given a set of options, returns the set of type directive names
* that should be included for this program automatically.
* This list could either come from the config file,
* or from enumerating the types root + initial secondary types lookup location.
* More type directives might appear in the program later as a result of loading actual source files;
* this list is only the set of defaults that are implicitly included.
*/
export function getAutomaticTypeDirectiveNames(options: CompilerOptions, rootFiles: string[], host: CompilerHost): string[] {
export function getAutomaticTypeDirectiveNames(options: CompilerOptions, host: ModuleResolutionHost): string[] {
// Use explicit type list from tsconfig.json
if (options.types) {
return options.types;
}
// Walk the primary type lookup locations
let result: string[] = [];
const result: string[] = [];
if (host.directoryExists && host.getDirectories) {
const typeRoots = getEffectiveTypeRoots(options, host);
if (typeRoots) {
for (const root of typeRoots) {
if (host.directoryExists(root)) {
result = result.concat(host.getDirectories(root));
for (const typeDirectivePath of host.getDirectories(root)) {
const normalized = normalizePath(typeDirectivePath);
const packageJsonPath = pathToPackageJson(combinePaths(root, normalized));
// tslint:disable-next-line:no-null-keyword
const isNotNeededPackage = host.fileExists(packageJsonPath) && readJson(packageJsonPath, host).typings === null;
if (!isNotNeededPackage) {
// Return just the type directive names
result.push(getBaseFileName(normalized));
}
}
}
}
}
@@ -1096,7 +1087,7 @@ namespace ts {
let noDiagnosticsTypeChecker: TypeChecker;
let classifiableNames: Map<string>;
let resolvedTypeReferenceDirectives: Map<ResolvedTypeReferenceDirective> = {};
let resolvedTypeReferenceDirectives = createMap<ResolvedTypeReferenceDirective>();
let fileProcessingDiagnostics = createDiagnosticCollection();
// The below settings are to track if a .js file should be add to the program if loaded via searching under node_modules.
@@ -1111,12 +1102,12 @@ namespace ts {
// If a module has some of its imports skipped due to being at the depth limit under node_modules, then track
// this, as it may be imported at a shallower depth later, and then it will need its skipped imports processed.
const modulesWithElidedImports: Map<boolean> = {};
const modulesWithElidedImports = createMap<boolean>();
// Track source files that are source files found by searching under node_modules, as these shouldn't be compiled.
const sourceFilesFoundSearchingNodeModules: Map<boolean> = {};
const sourceFilesFoundSearchingNodeModules = createMap<boolean>();
const start = performance.mark();
performance.mark("beforeProgram");
host = host || createCompilerHost(options);
@@ -1155,11 +1146,11 @@ namespace ts {
forEach(rootNames, name => processRootFile(name, /*isDefaultLib*/ false));
// load type declarations specified via 'types' argument or implicitly from types/ and node_modules/@types folders
const typeReferences: string[] = getAutomaticTypeDirectiveNames(options, rootNames, host);
const typeReferences: string[] = getAutomaticTypeDirectiveNames(options, host);
if (typeReferences) {
const inferredRoot = getInferredTypesRoot(options, rootNames, host);
const containingFilename = combinePaths(inferredRoot, "__inferred type names__.ts");
// This containingFilename needs to match with the one used in managed-side
const containingFilename = combinePaths(host.getCurrentDirectory(), "__inferred type names__.ts");
const resolutions = resolveTypeReferenceDirectiveNamesWorker(typeReferences, containingFilename);
for (let i = 0; i < typeReferences.length; i++) {
processTypeReferenceDirective(typeReferences[i], resolutions[i]);
@@ -1214,8 +1205,8 @@ namespace ts {
};
verifyCompilerOptions();
performance.measure("Program", start);
performance.mark("afterProgram");
performance.measure("Program", "beforeProgram", "afterProgram");
return program;
@@ -1242,10 +1233,10 @@ namespace ts {
if (!classifiableNames) {
// Initialize a checker so that all our files are bound.
getTypeChecker();
classifiableNames = {};
classifiableNames = createMap<string>();
for (const sourceFile of files) {
copyMap(sourceFile.classifiableNames, classifiableNames);
copyProperties(sourceFile.classifiableNames, classifiableNames);
}
}
@@ -1273,7 +1264,7 @@ namespace ts {
(oldOptions.maxNodeModuleJsDepth !== options.maxNodeModuleJsDepth) ||
!arrayIsEqualTo(oldOptions.typeRoots, oldOptions.typeRoots) ||
!arrayIsEqualTo(oldOptions.rootDirs, options.rootDirs) ||
!mapIsEqualTo(oldOptions.paths, options.paths)) {
!equalOwnProperties(oldOptions.paths, options.paths)) {
return false;
}
@@ -1395,7 +1386,7 @@ namespace ts {
getSourceFile: program.getSourceFile,
getSourceFileByPath: program.getSourceFileByPath,
getSourceFiles: program.getSourceFiles,
isSourceFileFromExternalLibrary: (file: SourceFile) => !!lookUp(sourceFilesFoundSearchingNodeModules, file.path),
isSourceFileFromExternalLibrary: (file: SourceFile) => !!sourceFilesFoundSearchingNodeModules[file.path],
writeFile: writeFileCallback || (
(fileName, data, writeByteOrderMark, onError, sourceFiles) => host.writeFile(fileName, data, writeByteOrderMark, onError, sourceFiles)),
isEmitBlocked,
@@ -1458,14 +1449,15 @@ namespace ts {
// checked is to not pass the file to getEmitResolver.
const emitResolver = getDiagnosticsProducingTypeChecker().getEmitResolver((options.outFile || options.out) ? undefined : sourceFile);
const start = performance.mark();
performance.mark("beforeEmit");
const emitResult = emitFiles(
emitResolver,
getEmitHost(writeFileCallback),
sourceFile);
performance.measure("Emit", start);
performance.mark("afterEmit");
performance.measure("Emit", "beforeEmit", "afterEmit");
return emitResult;
}
@@ -1932,7 +1924,7 @@ namespace ts {
// If the file was previously found via a node_modules search, but is now being processed as a root file,
// then everything it sucks in may also be marked incorrectly, and needs to be checked again.
if (file && lookUp(sourceFilesFoundSearchingNodeModules, file.path) && currentNodeModulesDepth == 0) {
if (file && sourceFilesFoundSearchingNodeModules[file.path] && currentNodeModulesDepth == 0) {
sourceFilesFoundSearchingNodeModules[file.path] = false;
if (!options.noResolve) {
processReferencedFiles(file, getDirectoryPath(fileName), isDefaultLib);
@@ -1943,7 +1935,7 @@ namespace ts {
processImportedModules(file, getDirectoryPath(fileName));
}
// See if we need to reprocess the imports due to prior skipped imports
else if (file && lookUp(modulesWithElidedImports, file.path)) {
else if (file && modulesWithElidedImports[file.path]) {
if (currentNodeModulesDepth < maxNodeModulesJsDepth) {
modulesWithElidedImports[file.path] = false;
processImportedModules(file, getDirectoryPath(fileName));
@@ -2010,15 +2002,17 @@ namespace ts {
}
function processTypeReferenceDirectives(file: SourceFile) {
const typeDirectives = map(file.typeReferenceDirectives, l => l.fileName);
// We lower-case all type references because npm automatically lowercases all packages. See GH#9824.
const typeDirectives = map(file.typeReferenceDirectives, ref => ref.fileName.toLocaleLowerCase());
const resolutions = resolveTypeReferenceDirectiveNamesWorker(typeDirectives, file.fileName);
for (let i = 0; i < typeDirectives.length; i++) {
const ref = file.typeReferenceDirectives[i];
const resolvedTypeReferenceDirective = resolutions[i];
// store resolved type directive on the file
setResolvedTypeReferenceDirective(file, ref.fileName, resolvedTypeReferenceDirective);
processTypeReferenceDirective(ref.fileName, resolvedTypeReferenceDirective, file, ref.pos, ref.end);
const fileName = ref.fileName.toLocaleLowerCase();
setResolvedTypeReferenceDirective(file, fileName, resolvedTypeReferenceDirective);
processTypeReferenceDirective(fileName, resolvedTypeReferenceDirective, file, ref.pos, ref.end);
}
}
@@ -2043,7 +2037,7 @@ namespace ts {
const otherFileText = host.readFile(resolvedTypeReferenceDirective.resolvedFileName);
if (otherFileText !== getSourceFile(previousResolution.resolvedFileName).text) {
fileProcessingDiagnostics.add(createDiagnostic(refFile, refPos, refEnd,
Diagnostics.Conflicting_library_definitions_for_0_found_at_1_and_2_Copy_the_correct_file_to_the_typings_folder_to_resolve_this_conflict,
Diagnostics.Conflicting_definitions_for_0_found_at_1_and_2_Consider_installing_a_specific_version_of_this_library_to_resolve_the_conflict,
typeReferenceDirective,
resolvedTypeReferenceDirective.resolvedFileName,
previousResolution.resolvedFileName
@@ -2083,7 +2077,7 @@ namespace ts {
function processImportedModules(file: SourceFile, basePath: string) {
collectExternalModuleReferences(file);
if (file.imports.length || file.moduleAugmentations.length) {
file.resolvedModules = {};
file.resolvedModules = createMap<ResolvedModule>();
const moduleNames = map(concatenate(file.imports, file.moduleAugmentations), getTextOfLiteral);
const resolutions = resolveModuleNamesWorker(moduleNames, getNormalizedAbsolutePath(file.fileName, currentDirectory));
for (let i = 0; i < moduleNames.length; i++) {
@@ -2200,6 +2194,9 @@ namespace ts {
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Pattern_0_can_have_at_most_one_Asterisk_character, key));
}
if (isArray(options.paths[key])) {
if (options.paths[key].length === 0) {
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Substitutions_for_pattern_0_shouldn_t_be_an_empty_array, key));
}
for (const subst of options.paths[key]) {
const typeOfSubst = typeof subst;
if (typeOfSubst === "string") {
@@ -2252,7 +2249,7 @@ namespace ts {
const languageVersion = options.target || ScriptTarget.ES3;
const outFile = options.outFile || options.out;
const firstExternalModuleSourceFile = forEach(files, f => isExternalModule(f) ? f : undefined);
const firstNonAmbientExternalModuleSourceFile = forEach(files, f => isExternalModule(f) && !isDeclarationFile(f) ? f : undefined);
if (options.isolatedModules) {
if (options.module === ModuleKind.None && languageVersion < ScriptTarget.ES6) {
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_isolatedModules_can_only_be_used_when_either_option_module_is_provided_or_option_target_is_ES2015_or_higher));
@@ -2264,10 +2261,10 @@ namespace ts {
programDiagnostics.add(createFileDiagnostic(firstNonExternalModuleSourceFile, span.start, span.length, Diagnostics.Cannot_compile_namespaces_when_the_isolatedModules_flag_is_provided));
}
}
else if (firstExternalModuleSourceFile && languageVersion < ScriptTarget.ES6 && options.module === ModuleKind.None) {
else if (firstNonAmbientExternalModuleSourceFile && languageVersion < ScriptTarget.ES6 && options.module === ModuleKind.None) {
// We cannot use createDiagnosticFromNode because nodes do not have parents yet
const span = getErrorSpanForNode(firstExternalModuleSourceFile, firstExternalModuleSourceFile.externalModuleIndicator);
programDiagnostics.add(createFileDiagnostic(firstExternalModuleSourceFile, span.start, span.length, Diagnostics.Cannot_use_imports_exports_or_module_augmentations_when_module_is_none));
const span = getErrorSpanForNode(firstNonAmbientExternalModuleSourceFile, firstNonAmbientExternalModuleSourceFile.externalModuleIndicator);
programDiagnostics.add(createFileDiagnostic(firstNonAmbientExternalModuleSourceFile, span.start, span.length, Diagnostics.Cannot_use_imports_exports_or_module_augmentations_when_module_is_none));
}
// Cannot specify module gen that isn't amd or system with --out
@@ -2275,9 +2272,9 @@ namespace ts {
if (options.module && !(options.module === ModuleKind.AMD || options.module === ModuleKind.System)) {
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Only_amd_and_system_modules_are_supported_alongside_0, options.out ? "out" : "outFile"));
}
else if (options.module === undefined && firstExternalModuleSourceFile) {
const span = getErrorSpanForNode(firstExternalModuleSourceFile, firstExternalModuleSourceFile.externalModuleIndicator);
programDiagnostics.add(createFileDiagnostic(firstExternalModuleSourceFile, span.start, span.length, Diagnostics.Cannot_compile_modules_using_option_0_unless_the_module_flag_is_amd_or_system, options.out ? "out" : "outFile"));
else if (options.module === undefined && firstNonAmbientExternalModuleSourceFile) {
const span = getErrorSpanForNode(firstNonAmbientExternalModuleSourceFile, firstNonAmbientExternalModuleSourceFile.externalModuleIndicator);
programDiagnostics.add(createFileDiagnostic(firstNonAmbientExternalModuleSourceFile, span.start, span.length, Diagnostics.Cannot_compile_modules_using_option_0_unless_the_module_flag_is_amd_or_system, options.out ? "out" : "outFile"));
}
}
+3 -5
View File
@@ -55,7 +55,7 @@ namespace ts {
tryScan<T>(callback: () => T): T;
}
const textToToken: Map<SyntaxKind> = {
const textToToken = createMap({
"abstract": SyntaxKind.AbstractKeyword,
"any": SyntaxKind.AnyKeyword,
"as": SyntaxKind.AsKeyword,
@@ -179,7 +179,7 @@ namespace ts {
"|=": SyntaxKind.BarEqualsToken,
"^=": SyntaxKind.CaretEqualsToken,
"@": SyntaxKind.AtToken,
};
});
/*
As per ECMAScript Language Specification 3th Edition, Section 7.6: Identifiers
@@ -274,9 +274,7 @@ namespace ts {
function makeReverseMap(source: Map<number>): string[] {
const result: string[] = [];
for (const name in source) {
if (source.hasOwnProperty(name)) {
result[source[name]] = name;
}
result[source[name]] = name;
}
return result;
}
+8 -2
View File
@@ -46,6 +46,7 @@ namespace ts {
export function createSourceMapWriter(host: EmitHost, writer: EmitTextWriter): SourceMapWriter {
const compilerOptions = host.getCompilerOptions();
const extendedDiagnostics = compilerOptions.extendedDiagnostics;
let currentSourceFile: SourceFile;
let sourceMapDir: string; // The directory in which sourcemap will be
let stopOverridingSpan = false;
@@ -240,7 +241,9 @@ namespace ts {
return;
}
const start = performance.mark();
if (extendedDiagnostics) {
performance.mark("beforeSourcemap");
}
const sourceLinePos = getLineAndCharacterOfPosition(currentSourceFile, pos);
@@ -282,7 +285,10 @@ namespace ts {
updateLastEncodedAndRecordedSpans();
performance.measure("Source Map", start);
if (extendedDiagnostics) {
performance.mark("afterSourcemap");
performance.measure("Source Map", "beforeSourcemap", "afterSourcemap");
}
}
function getStartPos(range: TextRange) {
+12 -17
View File
@@ -233,15 +233,15 @@ namespace ts {
const useNonPollingWatchers = process.env["TSC_NONPOLLING_WATCHER"];
function createWatchedFileSet() {
const dirWatchers: Map<DirectoryWatcher> = {};
const dirWatchers = createMap<DirectoryWatcher>();
// One file can have multiple watchers
const fileWatcherCallbacks: Map<FileWatcherCallback[]> = {};
const fileWatcherCallbacks = createMap<FileWatcherCallback[]>();
return { addFile, removeFile };
function reduceDirWatcherRefCountForFile(fileName: string) {
const dirName = getDirectoryPath(fileName);
if (hasProperty(dirWatchers, dirName)) {
const watcher = dirWatchers[dirName];
const watcher = dirWatchers[dirName];
if (watcher) {
watcher.referenceCount -= 1;
if (watcher.referenceCount <= 0) {
watcher.close();
@@ -251,13 +251,12 @@ namespace ts {
}
function addDirWatcher(dirPath: string): void {
if (hasProperty(dirWatchers, dirPath)) {
const watcher = dirWatchers[dirPath];
let watcher = dirWatchers[dirPath];
if (watcher) {
watcher.referenceCount += 1;
return;
}
const watcher: DirectoryWatcher = _fs.watch(
watcher = _fs.watch(
dirPath,
{ persistent: true },
(eventName: string, relativeFileName: string) => fileEventHandler(eventName, relativeFileName, dirPath)
@@ -268,12 +267,7 @@ namespace ts {
}
function addFileWatcherCallback(filePath: string, callback: FileWatcherCallback): void {
if (hasProperty(fileWatcherCallbacks, filePath)) {
fileWatcherCallbacks[filePath].push(callback);
}
else {
fileWatcherCallbacks[filePath] = [callback];
}
(fileWatcherCallbacks[filePath] || (fileWatcherCallbacks[filePath] = [])).push(callback);
}
function addFile(fileName: string, callback: FileWatcherCallback): WatchedFile {
@@ -289,8 +283,9 @@ namespace ts {
}
function removeFileWatcherCallback(filePath: string, callback: FileWatcherCallback) {
if (hasProperty(fileWatcherCallbacks, filePath)) {
const newCallbacks = copyListRemovingItem(callback, fileWatcherCallbacks[filePath]);
const callbacks = fileWatcherCallbacks[filePath];
if (callbacks) {
const newCallbacks = copyListRemovingItem(callback, callbacks);
if (newCallbacks.length === 0) {
delete fileWatcherCallbacks[filePath];
}
@@ -306,7 +301,7 @@ namespace ts {
? undefined
: ts.getNormalizedAbsolutePath(relativeFileName, baseDirPath);
// Some applications save a working file via rename operations
if ((eventName === "change" || eventName === "rename") && hasProperty(fileWatcherCallbacks, fileName)) {
if ((eventName === "change" || eventName === "rename") && fileWatcherCallbacks[fileName]) {
for (const fileCallback of fileWatcherCallbacks[fileName]) {
fileCallback(fileName);
}
+11 -68
View File
@@ -122,11 +122,11 @@ namespace ts {
const gutterSeparator = " ";
const resetEscapeSequence = "\u001b[0m";
const ellipsis = "...";
const categoryFormatMap: Map<string> = {
const categoryFormatMap = createMap<string>({
[DiagnosticCategory.Warning]: yellowForegroundEscapeSequence,
[DiagnosticCategory.Error]: redForegroundEscapeSequence,
[DiagnosticCategory.Message]: blueForegroundEscapeSequence,
};
});
function formatAndReset(text: string, formatStyle: string) {
return formatStyle + text + resetEscapeSequence;
@@ -432,7 +432,7 @@ namespace ts {
}
// reset the cache of existing files
cachedExistingFiles = {};
cachedExistingFiles = createMap<boolean>();
const compileResult = compile(rootFileNames, compilerOptions, compilerHost);
@@ -445,10 +445,9 @@ namespace ts {
}
function cachedFileExists(fileName: string): boolean {
if (hasProperty(cachedExistingFiles, fileName)) {
return cachedExistingFiles[fileName];
}
return cachedExistingFiles[fileName] = hostFileExists(fileName);
return fileName in cachedExistingFiles
? cachedExistingFiles[fileName]
: cachedExistingFiles[fileName] = hostFileExists(fileName);
}
function getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void) {
@@ -676,7 +675,7 @@ namespace ts {
const usageColumn: string[] = []; // Things like "-d, --declaration" go in here.
const descriptionColumn: string[] = [];
const optionsDescriptionMap: Map<string[]> = {}; // Map between option.description and list of option.type if it is a kind
const optionsDescriptionMap = createMap<string[]>(); // 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];
@@ -704,9 +703,10 @@ namespace ts {
description = getDiagnosticText(option.description);
const options: string[] = [];
const element = (<CommandLineOptionOfListType>option).element;
forEachKey(<Map<number | string>>element.type, key => {
const typeMap = <Map<number | string>>element.type;
for (const key in typeMap) {
options.push(`'${key}'`);
});
}
optionsDescriptionMap[description] = options;
}
else {
@@ -763,68 +763,11 @@ namespace ts {
reportDiagnostic(createCompilerDiagnostic(Diagnostics.A_tsconfig_json_file_is_already_defined_at_Colon_0, file), /* host */ undefined);
}
else {
const compilerOptions = extend(options, defaultInitCompilerOptions);
const configurations: any = {
compilerOptions: serializeCompilerOptions(compilerOptions)
};
if (fileNames && fileNames.length) {
// only set the files property if we have at least one file
configurations.files = fileNames;
}
else {
configurations.exclude = ["node_modules"];
if (compilerOptions.outDir) {
configurations.exclude.push(compilerOptions.outDir);
}
}
sys.writeFile(file, JSON.stringify(configurations, undefined, 4));
sys.writeFile(file, JSON.stringify(generateTSConfig(options, fileNames), undefined, 4));
reportDiagnostic(createCompilerDiagnostic(Diagnostics.Successfully_created_a_tsconfig_json_file), /* host */ undefined);
}
return;
function serializeCompilerOptions(options: CompilerOptions): Map<string | number | boolean> {
const result: Map<string | number | boolean> = {};
const optionsNameMap = getOptionNameMap().optionNameMap;
for (const name in options) {
if (hasProperty(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 = <string | number | boolean>options[name];
switch (name) {
case "init":
case "watch":
case "version":
case "help":
case "project":
break;
default:
let optionDefinition = optionsNameMap[name.toLowerCase()];
if (optionDefinition) {
if (typeof optionDefinition.type === "string") {
// string, number or boolean
result[name] = value;
}
else {
// Enum
const typeMap = <Map<number>>optionDefinition.type;
for (const key in typeMap) {
if (hasProperty(typeMap, key)) {
if (typeMap[key] === value)
result[name] = key;
}
}
}
}
break;
}
}
}
return result;
}
}
}
+120 -67
View File
@@ -1,9 +1,13 @@
namespace ts {
export interface Map<T> {
export interface MapLike<T> {
[index: string]: T;
}
export interface Map<T> extends MapLike<T> {
__mapBrand: any;
}
// branded string type used to store absolute, normalized and canonicalized paths
// arbitrary file name can be converted to Path via toPath function
export type Path = string & { __pathBrand: any };
@@ -210,7 +214,7 @@ namespace ts {
IntersectionType,
ParenthesizedType,
ThisType,
StringLiteralType,
LiteralType,
// Binding patterns
ObjectBindingPattern,
ArrayBindingPattern,
@@ -346,6 +350,7 @@ namespace ts {
JSDocTypedefTag,
JSDocPropertyTag,
JSDocTypeLiteral,
JSDocLiteralType,
// Synthesized list
SyntaxList,
@@ -361,7 +366,7 @@ namespace ts {
FirstFutureReservedWord = ImplementsKeyword,
LastFutureReservedWord = YieldKeyword,
FirstTypeNode = TypePredicate,
LastTypeNode = StringLiteralType,
LastTypeNode = LiteralType,
FirstPunctuation = OpenBraceToken,
LastPunctuation = CaretEqualsToken,
FirstToken = Unknown,
@@ -376,9 +381,9 @@ namespace ts {
LastBinaryOperator = CaretEqualsToken,
FirstNode = QualifiedName,
FirstJSDocNode = JSDocTypeExpression,
LastJSDocNode = JSDocTypeLiteral,
LastJSDocNode = JSDocLiteralType,
FirstJSDocTagNode = JSDocComment,
LastJSDocTagNode = JSDocTypeLiteral
LastJSDocTagNode = JSDocLiteralType
}
export const enum NodeFlags {
@@ -794,8 +799,9 @@ namespace ts {
}
// @kind(SyntaxKind.StringLiteralType)
export interface StringLiteralTypeNode extends LiteralLikeNode, TypeNode {
export interface LiteralTypeNode extends TypeNode {
_stringLiteralTypeBrand: any;
literal: Expression;
}
// @kind(SyntaxKind.StringLiteral)
@@ -981,13 +987,19 @@ namespace ts {
multiLine?: boolean;
}
export type EntityNameExpression = Identifier | PropertyAccessEntityNameExpression;
export type EntityNameOrEntityNameExpression = EntityName | EntityNameExpression;
// @kind(SyntaxKind.PropertyAccessExpression)
export interface PropertyAccessExpression extends MemberExpression, Declaration {
expression: LeftHandSideExpression;
name: Identifier;
}
export type IdentifierOrPropertyAccess = Identifier | PropertyAccessExpression;
/** Brand for a PropertyAccessExpression which, like a QualifiedName, consists of a sequence of identifiers separated by dots. */
export interface PropertyAccessEntityNameExpression extends PropertyAccessExpression {
_propertyAccessExpressionLikeQualifiedNameBrand?: any;
expression: EntityNameExpression;
}
// @kind(SyntaxKind.ElementAccessExpression)
export interface ElementAccessExpression extends MemberExpression {
@@ -1491,6 +1503,10 @@ namespace ts {
type: JSDocType;
}
export interface JSDocLiteralType extends JSDocType {
literal: LiteralTypeNode;
}
export type JSDocTypeReferencingNode = JSDocThisType | JSDocConstructorType | JSDocVariadicType | JSDocOptionalType | JSDocNullableType | JSDocNonNullableType;
// @kind(SyntaxKind.JSDocRecordMember)
@@ -1605,6 +1621,16 @@ namespace ts {
antecedent: FlowNode;
}
export type FlowType = Type | IncompleteType;
// Incomplete types occur during control flow analysis of loops. An IncompleteType
// is distinguished from a regular type by a flags value of zero. Incomplete type
// objects are internal to the getFlowTypeOfRefecence function and never escape it.
export interface IncompleteType {
flags: TypeFlags; // No flags set
type: Type; // The type marked incomplete
}
export interface AmdDependency {
path: string;
name: string;
@@ -1916,6 +1942,7 @@ namespace ts {
InElementType = 0x00000040, // Writing an array or union element type
UseFullyQualifiedType = 0x00000080, // Write out the fully qualified type name (eg. Module.Type, instead of Type)
InFirstTypeArgument = 0x00000100, // Writing first type argument of the instantiated type
InTypeAlias = 0x00000200, // Writing type in type alias declaration
}
export const enum SymbolFormatFlags {
@@ -2019,7 +2046,7 @@ namespace ts {
writeTypeOfExpression(expr: Expression, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void;
writeBaseConstructorTypeOfClass(node: ClassLikeDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void;
isSymbolAccessible(symbol: Symbol, enclosingDeclaration: Node, meaning: SymbolFlags): SymbolAccessibilityResult;
isEntityNameVisible(entityName: EntityName | Expression, enclosingDeclaration: Node): SymbolVisibilityResult;
isEntityNameVisible(entityName: EntityNameOrEntityNameExpression, enclosingDeclaration: Node): SymbolVisibilityResult;
// Returns the constant value this property access resolves to, or 'undefined' for a non-constant
getConstantValue(node: EnumMember | PropertyAccessExpression | ElementAccessExpression): number;
getReferencedValueDeclaration(reference: Identifier): Declaration;
@@ -2028,7 +2055,7 @@ namespace ts {
moduleExportsSomeValue(moduleReferenceExpression: Expression): boolean;
isArgumentsLocalBinding(node: Identifier): boolean;
getExternalModuleFileFromDeclaration(declaration: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration | ModuleDeclaration): SourceFile;
getTypeReferenceDirectivesForEntityName(name: EntityName | PropertyAccessExpression): string[];
getTypeReferenceDirectivesForEntityName(name: EntityNameOrEntityNameExpression): string[];
getTypeReferenceDirectivesForSymbol(symbol: Symbol, meaning?: SymbolFlags): string[];
}
@@ -2069,8 +2096,8 @@ namespace ts {
Enum = RegularEnum | ConstEnum,
Variable = FunctionScopedVariable | BlockScopedVariable,
Value = Variable | Property | EnumMember | Function | Class | Enum | ValueModule | Method | GetAccessor | SetAccessor,
Type = Class | Interface | Enum | TypeLiteral | ObjectLiteral | TypeParameter | TypeAlias,
Namespace = ValueModule | NamespaceModule,
Type = Class | Interface | Enum | EnumMember | TypeLiteral | ObjectLiteral | TypeParameter | TypeAlias,
Namespace = ValueModule | NamespaceModule | Enum,
Module = ValueModule | NamespaceModule,
Accessor = GetAccessor | SetAccessor,
@@ -2084,7 +2111,7 @@ namespace ts {
ParameterExcludes = Value,
PropertyExcludes = None,
EnumMemberExcludes = Value,
EnumMemberExcludes = Value | Type,
FunctionExcludes = Value & ~(Function | ValueModule),
ClassExcludes = (Value | Type) & ~(ValueModule | Interface), // class-interface mergability done in checker.ts
InterfaceExcludes = Type & ~(Interface | Class),
@@ -2135,6 +2162,8 @@ namespace ts {
/* @internal */ exportSymbol?: Symbol; // Exported symbol associated with this symbol
/* @internal */ constEnumOnlyModule?: boolean; // True if module contains only const enums or other modules with only const enums
/* @internal */ isReferenced?: boolean; // True if the symbol is referenced elsewhere
/* @internal */ isReplaceableByMethod?: boolean; // Can this Javascript class property be replaced by a method symbol?
/* @internal */ isAssigned?: boolean; // True if the symbol is a parameter with assignments
}
/* @internal */
@@ -2148,6 +2177,8 @@ namespace ts {
mapper?: TypeMapper; // Type mapper for instantiation alias
referenced?: boolean; // True if alias symbol has been referenced as a value
containingType?: UnionOrIntersectionType; // Containing union or intersection type for synthetic property
hasCommonType?: boolean; // True if constituents of synthetic property all have same type
isDiscriminantProperty?: boolean; // True if discriminant synthetic property
resolvedExports?: SymbolTable; // Resolved exports of module
exportsChecked?: boolean; // True if exports of external module have been checked
isDeclarationWithCollidingName?: boolean; // True if symbol is block scoped redeclaration
@@ -2158,9 +2189,7 @@ namespace ts {
/* @internal */
export interface TransientSymbol extends Symbol, SymbolLinks { }
export interface SymbolTable {
[index: string]: Symbol;
}
export type SymbolTable = Map<Symbol>;
/** Represents a "prefix*suffix" pattern. */
/* @internal */
@@ -2187,23 +2216,24 @@ namespace ts {
AsyncMethodWithSuper = 0x00000800, // An async method that reads a value from a member of 'super'.
AsyncMethodWithSuperBinding = 0x00001000, // An async method that assigns a value to a member of 'super'.
CaptureArguments = 0x00002000, // Lexical 'arguments' used in body (for async functions)
EnumValuesComputed = 0x00004000, // Values for enum members have been computed, and any errors have been reported for them.
LexicalModuleMergesWithClass = 0x00008000, // Instantiated lexical module declaration is merged with a previous class declaration.
LoopWithCapturedBlockScopedBinding = 0x00010000, // Loop that contains block scoped variable captured in closure
CapturedBlockScopedBinding = 0x00020000, // Block-scoped binding that is captured in some function
BlockScopedBindingInLoop = 0x00040000, // Block-scoped binding with declaration nested inside iteration statement
ClassWithBodyScopedClassBinding = 0x00080000, // Decorated class that contains a binding to itself inside of the class body.
BodyScopedClassBinding = 0x00100000, // Binding to a decorated class inside of the class's body.
NeedsLoopOutParameter = 0x00200000, // Block scoped binding whose value should be explicitly copied outside of the converted loop
EnumValuesComputed = 0x00004000, // Values for enum members have been computed, and any errors have been reported for them.
LexicalModuleMergesWithClass = 0x00008000, // Instantiated lexical module declaration is merged with a previous class declaration.
LoopWithCapturedBlockScopedBinding = 0x00010000, // Loop that contains block scoped variable captured in closure
CapturedBlockScopedBinding = 0x00020000, // Block-scoped binding that is captured in some function
BlockScopedBindingInLoop = 0x00040000, // Block-scoped binding with declaration nested inside iteration statement
ClassWithBodyScopedClassBinding = 0x00080000, // Decorated class that contains a binding to itself inside of the class body.
BodyScopedClassBinding = 0x00100000, // Binding to a decorated class inside of the class's body.
NeedsLoopOutParameter = 0x00200000, // Block scoped binding whose value should be explicitly copied outside of the converted loop
AssignmentsMarked = 0x00400000, // Parameter assignments have been marked
}
/* @internal */
export interface NodeLinks {
flags?: NodeCheckFlags; // Set of flags specific to Node
resolvedType?: Type; // Cached type of type node
resolvedSignature?: Signature; // Cached signature of signature node or call expression
resolvedSymbol?: Symbol; // Cached name resolution result
resolvedIndexInfo?: IndexInfo; // Cached indexing info resolution result
flags?: NodeCheckFlags; // Set of flags specific to Node
enumMemberValue?: number; // Constant value of enum member
isVisible?: boolean; // Is this node visible
hasReportedStatementInAmbientContext?: boolean; // Cache boolean if we report statements in ambient context
@@ -2215,57 +2245,65 @@ namespace ts {
}
export const enum TypeFlags {
Any = 0x00000001,
String = 0x00000002,
Number = 0x00000004,
Boolean = 0x00000008,
Void = 0x00000010,
Undefined = 0x00000020,
Null = 0x00000040,
Enum = 0x00000080, // Enum type
StringLiteral = 0x00000100, // String literal type
TypeParameter = 0x00000200, // Type parameter
Class = 0x00000400, // Class
Interface = 0x00000800, // Interface
Reference = 0x00001000, // Generic type reference
Tuple = 0x00002000, // Tuple
Union = 0x00004000, // Union (T | U)
Intersection = 0x00008000, // Intersection (T & U)
Anonymous = 0x00010000, // Anonymous
Instantiated = 0x00020000, // Instantiated anonymous type
Any = 1 << 0,
String = 1 << 1,
Number = 1 << 2,
Boolean = 1 << 3,
Enum = 1 << 4,
StringLiteral = 1 << 5,
NumberLiteral = 1 << 6,
BooleanLiteral = 1 << 7,
EnumLiteral = 1 << 8,
ESSymbol = 1 << 9, // Type of symbol primitive introduced in ES6
Void = 1 << 10,
Undefined = 1 << 11,
Null = 1 << 12,
Never = 1 << 13, // Never type
TypeParameter = 1 << 14, // Type parameter
Class = 1 << 15, // Class
Interface = 1 << 16, // Interface
Reference = 1 << 17, // Generic type reference
Tuple = 1 << 18, // Tuple
Union = 1 << 19, // Union (T | U)
Intersection = 1 << 20, // Intersection (T & U)
Anonymous = 1 << 21, // Anonymous
Instantiated = 1 << 22, // Instantiated anonymous type
/* @internal */
FromSignature = 0x00040000, // Created for signature assignment check
ObjectLiteral = 0x00080000, // Originates in an object literal
ObjectLiteral = 1 << 23, // Originates in an object literal
/* @internal */
FreshObjectLiteral = 0x00100000, // Fresh object literal type
FreshObjectLiteral = 1 << 24, // Fresh object literal type
/* @internal */
ContainsWideningType = 0x00200000, // Type is or contains undefined or null widening type
ContainsWideningType = 1 << 25, // Type is or contains undefined or null widening type
/* @internal */
ContainsObjectLiteral = 0x00400000, // Type is or contains object literal type
ContainsObjectLiteral = 1 << 26, // Type is or contains object literal type
/* @internal */
ContainsAnyFunctionType = 0x00800000, // Type is or contains object literal type
ESSymbol = 0x01000000, // Type of symbol primitive introduced in ES6
ThisType = 0x02000000, // This type
ObjectLiteralPatternWithComputedProperties = 0x04000000, // Object literal type implied by binding pattern has computed properties
Never = 0x08000000, // Never type
ContainsAnyFunctionType = 1 << 27, // Type is or contains object literal type
ThisType = 1 << 28, // This type
ObjectLiteralPatternWithComputedProperties = 1 << 29, // Object literal type implied by binding pattern has computed properties
/* @internal */
Nullable = Undefined | Null,
Literal = StringLiteral | NumberLiteral | BooleanLiteral | EnumLiteral,
/* @internal */
Falsy = Void | Undefined | Null, // TODO: Add false, 0, and ""
DefinitelyFalsy = StringLiteral | NumberLiteral | BooleanLiteral | Void | Undefined | Null,
PossiblyFalsy = DefinitelyFalsy | String | Number | Boolean,
/* @internal */
Intrinsic = Any | String | Number | Boolean | ESSymbol | Void | Undefined | Null | Never,
Intrinsic = Any | String | Number | Boolean | BooleanLiteral | ESSymbol | Void | Undefined | Null | Never,
/* @internal */
Primitive = String | Number | Boolean | ESSymbol | Void | Undefined | Null | StringLiteral | Enum,
Primitive = String | Number | Boolean | Enum | ESSymbol | Void | Undefined | Null | Literal,
StringLike = String | StringLiteral,
NumberLike = Number | Enum,
NumberLike = Number | NumberLiteral | Enum | EnumLiteral,
BooleanLike = Boolean | BooleanLiteral,
EnumLike = Enum | EnumLiteral,
ObjectType = Class | Interface | Reference | Tuple | Anonymous,
UnionOrIntersection = Union | Intersection,
StructuredType = ObjectType | Union | Intersection,
StructuredOrTypeParameter = StructuredType | TypeParameter,
// 'Narrowable' types are types where narrowing actually narrows.
// This *should* be every type other than null, undefined, void, and never
Narrowable = Any | StructuredType | TypeParameter | StringLike | NumberLike | Boolean | ESSymbol,
Narrowable = Any | StructuredType | TypeParameter | StringLike | NumberLike | BooleanLike | ESSymbol,
NotUnionOrUnit = Any | String | Number | ESSymbol | ObjectType,
/* @internal */
RequiresWidening = ContainsWideningType | ContainsObjectLiteral,
/* @internal */
@@ -2280,6 +2318,8 @@ namespace ts {
/* @internal */ id: number; // Unique ID
symbol?: Symbol; // Symbol associated with type (if any)
pattern?: DestructuringPattern; // Destructuring pattern represented by type (if any)
aliasSymbol?: Symbol; // Alias associated with type
aliasTypeArguments?: Type[]; // Alias type arguments (if any)
}
/* @internal */
@@ -2289,10 +2329,20 @@ namespace ts {
}
// String literal types (TypeFlags.StringLiteral)
export interface StringLiteralType extends Type {
export interface LiteralType extends Type {
text: string; // Text of string literal
}
// Enum types (TypeFlags.Enum)
export interface EnumType extends Type {
memberTypes: Map<EnumLiteralType>;
}
// Enum types (TypeFlags.EnumLiteral)
export interface EnumLiteralType extends LiteralType {
baseType: EnumType & UnionType;
}
// Object types (TypeFlags.ObjectType)
export interface ObjectType extends Type { }
@@ -2337,14 +2387,15 @@ namespace ts {
export interface TupleType extends ObjectType {
elementTypes: Type[]; // Element types
thisType?: Type; // This-type of tuple (only needed for tuples that are constraints of type parameters)
}
export interface UnionOrIntersectionType extends Type {
types: Type[]; // Constituent types
/* @internal */
reducedType: Type; // Reduced union type (all subtypes removed)
/* @internal */
resolvedProperties: SymbolTable; // Cache of resolved properties
/* @internal */
couldContainTypeParameters: boolean;
}
export interface UnionType extends UnionOrIntersectionType { }
@@ -2413,7 +2464,7 @@ namespace ts {
/* @internal */
hasRestParameter: boolean; // True if last parameter is rest parameter
/* @internal */
hasStringLiterals: boolean; // True if specialized
hasLiteralTypes: boolean; // True if specialized
/* @internal */
target?: Signature; // Instantiation target
/* @internal */
@@ -2443,6 +2494,7 @@ namespace ts {
export interface TypeMapper {
(t: TypeParameter): Type;
mappedTypes?: Type[]; // Types mapped by this mapper
targetTypes?: Type[]; // Types substituted for mapped types
instantiations?: Type[]; // Cache of instantiations created using this type mapper.
context?: InferenceContext; // The inference context this mapper was created from.
// Only inference mappers have this set (in createInferenceMapper).
@@ -2522,7 +2574,7 @@ namespace ts {
}
export type RootPaths = string[];
export type PathSubstitutions = Map<string[]>;
export type PathSubstitutions = MapLike<string[]>;
export type TsConfigOnlyOptions = RootPaths | PathSubstitutions;
export type CompilerOptionsValue = string | number | boolean | (string | number)[] | TsConfigOnlyOptions;
@@ -2682,7 +2734,7 @@ namespace ts {
fileNames: string[];
raw?: any;
errors: Diagnostic[];
wildcardDirectories?: Map<WatchDirectoryFlags>;
wildcardDirectories?: MapLike<WatchDirectoryFlags>;
}
export const enum WatchDirectoryFlags {
@@ -2692,7 +2744,7 @@ namespace ts {
export interface ExpandResult {
fileNames: string[];
wildcardDirectories: Map<WatchDirectoryFlags>;
wildcardDirectories: MapLike<WatchDirectoryFlags>;
}
/* @internal */
@@ -2714,7 +2766,7 @@ namespace ts {
/* @internal */
export interface CommandLineOptionOfCustomType extends CommandLineOptionBase {
type: Map<number | string>; // an object literal mapping named values to actual values
type: Map<number | string>; // an object literal mapping named values to actual values
}
/* @internal */
@@ -2877,6 +2929,7 @@ namespace ts {
directoryExists?(directoryName: string): boolean;
realpath?(path: string): string;
getCurrentDirectory?(): string;
getDirectories?(path: string): string[];
}
export interface ResolvedModule {
+30 -62
View File
@@ -87,25 +87,6 @@ namespace ts {
return node.end - node.pos;
}
export function mapIsEqualTo<T>(map1: Map<T>, map2: Map<T>): boolean {
if (!map1 || !map2) {
return map1 === map2;
}
return containsAll(map1, map2) && containsAll(map2, map1);
}
function containsAll<T>(map: Map<T>, other: Map<T>): boolean {
for (const key in map) {
if (!hasProperty(map, key)) {
continue;
}
if (!hasProperty(other, key) || map[key] !== other[key]) {
return false;
}
}
return true;
}
export function arrayIsEqualTo<T>(array1: T[], array2: T[], equaler?: (a: T, b: T) => boolean): boolean {
if (!array1 || !array2) {
return array1 === array2;
@@ -126,7 +107,7 @@ namespace ts {
}
export function hasResolvedModule(sourceFile: SourceFile, moduleNameText: string): boolean {
return sourceFile.resolvedModules && hasProperty(sourceFile.resolvedModules, moduleNameText);
return !!(sourceFile.resolvedModules && sourceFile.resolvedModules[moduleNameText]);
}
export function getResolvedModule(sourceFile: SourceFile, moduleNameText: string): ResolvedModule {
@@ -135,7 +116,7 @@ namespace ts {
export function setResolvedModule(sourceFile: SourceFile, moduleNameText: string, resolvedModule: ResolvedModule): void {
if (!sourceFile.resolvedModules) {
sourceFile.resolvedModules = {};
sourceFile.resolvedModules = createMap<ResolvedModule>();
}
sourceFile.resolvedModules[moduleNameText] = resolvedModule;
@@ -143,7 +124,7 @@ namespace ts {
export function setResolvedTypeReferenceDirective(sourceFile: SourceFile, typeReferenceDirectiveName: string, resolvedTypeReferenceDirective: ResolvedTypeReferenceDirective): void {
if (!sourceFile.resolvedTypeReferenceDirectiveNames) {
sourceFile.resolvedTypeReferenceDirectiveNames = {};
sourceFile.resolvedTypeReferenceDirectiveNames = createMap<ResolvedTypeReferenceDirective>();
}
sourceFile.resolvedTypeReferenceDirectiveNames[typeReferenceDirectiveName] = resolvedTypeReferenceDirective;
@@ -166,7 +147,7 @@ namespace ts {
}
for (let i = 0; i < names.length; i++) {
const newResolution = newResolutions[i];
const oldResolution = oldResolutions && hasProperty(oldResolutions, names[i]) ? oldResolutions[names[i]] : undefined;
const oldResolution = oldResolutions && oldResolutions[names[i]];
const changed =
oldResolution
? !newResolution || !comparer(oldResolution, newResolution)
@@ -1033,14 +1014,14 @@ namespace ts {
&& (<PropertyAccessExpression | ElementAccessExpression>node).expression.kind === SyntaxKind.SuperKeyword;
}
export function getEntityNameFromTypeNode(node: TypeNode): EntityName | Expression {
export function getEntityNameFromTypeNode(node: TypeNode): EntityNameOrEntityNameExpression {
if (node) {
switch (node.kind) {
case SyntaxKind.TypeReference:
return (<TypeReferenceNode>node).typeName;
case SyntaxKind.ExpressionWithTypeArguments:
return (<ExpressionWithTypeArguments>node).expression;
Debug.assert(isEntityNameExpression((<ExpressionWithTypeArguments>node).expression));
return <EntityNameExpression>(<ExpressionWithTypeArguments>node).expression;
case SyntaxKind.Identifier:
case SyntaxKind.QualifiedName:
return (<EntityName><Node>node);
@@ -1523,7 +1504,7 @@ namespace ts {
continue;
}
return parent.kind === SyntaxKind.BinaryExpression &&
(<BinaryExpression>parent).operatorToken.kind === SyntaxKind.EqualsToken &&
isAssignmentOperator((<BinaryExpression>parent).operatorToken.kind) &&
(<BinaryExpression>parent).left === node ||
(parent.kind === SyntaxKind.ForInStatement || parent.kind === SyntaxKind.ForOfStatement) &&
(<ForInStatement | ForOfStatement>parent).initializer === node;
@@ -1569,6 +1550,7 @@ namespace ts {
case SyntaxKind.MethodSignature:
case SyntaxKind.ModuleDeclaration:
case SyntaxKind.NamespaceImport:
case SyntaxKind.NamespaceExportDeclaration:
case SyntaxKind.Parameter:
case SyntaxKind.PropertyAssignment:
case SyntaxKind.PropertyDeclaration:
@@ -1693,8 +1675,8 @@ namespace ts {
// import * as <symbol> from ...
// import { x as <symbol> } from ...
// export { x as <symbol> } from ...
// export = ...
// export default ...
// export = <EntityNameExpression>
// export default <EntityNameExpression>
export function isAliasSymbolDeclaration(node: Node): boolean {
return node.kind === SyntaxKind.ImportEqualsDeclaration ||
node.kind === SyntaxKind.NamespaceExportDeclaration ||
@@ -1702,7 +1684,11 @@ namespace ts {
node.kind === SyntaxKind.NamespaceImport ||
node.kind === SyntaxKind.ImportSpecifier ||
node.kind === SyntaxKind.ExportSpecifier ||
node.kind === SyntaxKind.ExportAssignment && (<ExportAssignment>node).expression.kind === SyntaxKind.Identifier;
node.kind === SyntaxKind.ExportAssignment && exportAssignmentIsAlias(<ExportAssignment>node);
}
export function exportAssignmentIsAlias(node: ExportAssignment): boolean {
return isEntityNameExpression(node.expression);
}
export function getClassExtendsHeritageClauseElement(node: ClassLikeDeclaration | InterfaceDeclaration) {
@@ -1965,7 +1951,7 @@ namespace ts {
export function createDiagnosticCollection(): DiagnosticCollection {
let nonFileDiagnostics: Diagnostic[] = [];
const fileDiagnostics: Map<Diagnostic[]> = {};
const fileDiagnostics = createMap<Diagnostic[]>();
let diagnosticsModified = false;
let modificationCount = 0;
@@ -1983,12 +1969,11 @@ namespace ts {
}
function reattachFileDiagnostics(newFile: SourceFile): void {
if (!hasProperty(fileDiagnostics, newFile.fileName)) {
return;
}
for (const diagnostic of fileDiagnostics[newFile.fileName]) {
diagnostic.file = newFile;
const diagnostics = fileDiagnostics[newFile.fileName];
if (diagnostics) {
for (const diagnostic of diagnostics) {
diagnostic.file = newFile;
}
}
}
@@ -2029,9 +2014,7 @@ namespace ts {
forEach(nonFileDiagnostics, pushDiagnostic);
for (const key in fileDiagnostics) {
if (hasProperty(fileDiagnostics, key)) {
forEach(fileDiagnostics[key], pushDiagnostic);
}
forEach(fileDiagnostics[key], pushDiagnostic);
}
return sortAndDeduplicateDiagnostics(allDiagnostics);
@@ -2046,9 +2029,7 @@ namespace ts {
nonFileDiagnostics = sortAndDeduplicateDiagnostics(nonFileDiagnostics);
for (const key in fileDiagnostics) {
if (hasProperty(fileDiagnostics, key)) {
fileDiagnostics[key] = sortAndDeduplicateDiagnostics(fileDiagnostics[key]);
}
fileDiagnostics[key] = sortAndDeduplicateDiagnostics(fileDiagnostics[key]);
}
}
}
@@ -2059,7 +2040,7 @@ namespace ts {
// the map below must be updated. Note that this regexp *does not* include the 'delete' character.
// There is no reason for this other than that JSON.stringify does not handle it either.
const escapedCharsRegExp = /[\\\"\u0000-\u001f\t\v\f\b\r\n\u2028\u2029\u0085]/g;
const escapedCharsMap: Map<string> = {
const escapedCharsMap = createMap({
"\0": "\\0",
"\t": "\\t",
"\v": "\\v",
@@ -2072,7 +2053,7 @@ namespace ts {
"\u2028": "\\u2028", // lineSeparator
"\u2029": "\\u2029", // paragraphSeparator
"\u0085": "\\u0085" // nextLine
};
});
/**
@@ -2680,22 +2661,9 @@ namespace ts {
isClassLike(node.parent.parent);
}
// Returns false if this heritage clause element's expression contains something unsupported
// (i.e. not a name or dotted name).
export function isSupportedExpressionWithTypeArguments(node: ExpressionWithTypeArguments): boolean {
return isSupportedExpressionWithTypeArgumentsRest(node.expression);
}
function isSupportedExpressionWithTypeArgumentsRest(node: Expression): boolean {
if (node.kind === SyntaxKind.Identifier) {
return true;
}
else if (isPropertyAccessExpression(node)) {
return isSupportedExpressionWithTypeArgumentsRest(node.expression);
}
else {
return false;
}
export function isEntityNameExpression(node: Expression): node is EntityNameExpression {
return node.kind === SyntaxKind.Identifier ||
node.kind === SyntaxKind.PropertyAccessExpression && isEntityNameExpression((<PropertyAccessExpression>node).expression);
}
export function isRightSideOfQualifiedNameOrPropertyAccess(node: Node) {
@@ -2805,7 +2773,7 @@ namespace ts {
}
function stringifyObject(value: any) {
return `{${reduceProperties(value, stringifyProperty, "")}}`;
return `{${reduceOwnProperties(value, stringifyProperty, "")}}`;
}
function stringifyProperty(memo: string, value: any, key: string) {