Merge branch 'master' into no_dom

This commit is contained in:
Andy Hanson committed 2017-01-17 14:35:33 -08:00
commit 7baeb9726a
211 files changed
+7820 -4046

No files matched your search

+15 -12
View File
@@ -349,17 +349,20 @@ 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 = symbolTable[name] || (symbolTable[name] = createSymbol(SymbolFlags.None, name));
symbol = symbolTable.get(name);
if (!symbol) {
symbolTable.set(name, symbol = createSymbol(SymbolFlags.None, name));
}
if (name && (includes & SymbolFlags.Classifiable)) {
classifiableNames[name] = name;
classifiableNames.set(name, name);
}
if (symbol.flags & excludes) {
if (symbol.isReplaceableByMethod) {
// Javascript constructor-declared symbols can be discarded in favor of
// prototype symbols like methods.
symbol = symbolTable[name] = createSymbol(SymbolFlags.None, name);
symbolTable.set(name, symbol = createSymbol(SymbolFlags.None, name));
}
else {
if (node.name) {
@@ -1570,7 +1573,7 @@ namespace ts {
const typeLiteralSymbol = createSymbol(SymbolFlags.TypeLiteral, "__type");
addDeclarationToSymbol(typeLiteralSymbol, node, SymbolFlags.TypeLiteral);
typeLiteralSymbol.members = createMap<Symbol>();
typeLiteralSymbol.members[symbol.name] = symbol;
typeLiteralSymbol.members.set(symbol.name, symbol);
}
function bindObjectLiteralExpression(node: ObjectLiteralExpression) {
@@ -1601,9 +1604,9 @@ namespace ts {
? ElementKind.Property
: ElementKind.Accessor;
const existingKind = seen[identifier.text];
const existingKind = seen.get(identifier.text);
if (!existingKind) {
seen[identifier.text] = currentKind;
seen.set(identifier.text, currentKind);
continue;
}
@@ -2208,7 +2211,7 @@ namespace ts {
constructorFunction.parent = classPrototype;
classPrototype.parent = leftSideOfAssignment;
const funcSymbol = container.locals[constructorFunction.text];
const funcSymbol = container.locals.get(constructorFunction.text);
if (!funcSymbol || !(funcSymbol.flags & SymbolFlags.Function || isDeclarationOfFunctionExpression(funcSymbol))) {
return;
}
@@ -2239,7 +2242,7 @@ namespace ts {
bindAnonymousDeclaration(node, SymbolFlags.Class, bindingName);
// Add name of class expression into the map for semantic classifier
if (node.name) {
classifiableNames[node.name.text] = node.name.text;
classifiableNames.set(node.name.text, node.name.text);
}
}
@@ -2255,14 +2258,14 @@ 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 (symbol.exports[prototypeSymbol.name]) {
const symbolExport = symbol.exports.get(prototypeSymbol.name);
if (symbolExport) {
if (node.name) {
node.name.parent = node;
}
file.bindDiagnostics.push(createDiagnosticForNode(symbol.exports[prototypeSymbol.name].declarations[0],
Diagnostics.Duplicate_identifier_0, prototypeSymbol.name));
file.bindDiagnostics.push(createDiagnosticForNode(symbolExport.declarations[0], Diagnostics.Duplicate_identifier_0, prototypeSymbol.name));
}
symbol.exports[prototypeSymbol.name] = prototypeSymbol;
symbol.exports.set(prototypeSymbol.name, prototypeSymbol);
prototypeSymbol.parent = symbol;
}
+361 -297
View File
File diff suppressed because it is too large. Load diff
+40 -51
View File
@@ -1,4 +1,4 @@
/// <reference path="sys.ts"/>
/// <reference path="sys.ts"/>
/// <reference path="types.ts"/>
/// <reference path="core.ts"/>
/// <reference path="diagnosticInformationMap.generated.ts"/>
@@ -65,7 +65,7 @@ namespace ts {
},
{
name: "jsx",
type: createMap({
type: createMapFromTemplate({
"preserve": JsxEmit.Preserve,
"react": JsxEmit.React
}),
@@ -100,7 +100,7 @@ namespace ts {
{
name: "module",
shortName: "m",
type: createMap({
type: createMapFromTemplate({
"none": ModuleKind.None,
"commonjs": ModuleKind.CommonJS,
"amd": ModuleKind.AMD,
@@ -114,7 +114,7 @@ namespace ts {
},
{
name: "newLine",
type: createMap({
type: createMapFromTemplate({
"crlf": NewLineKind.CarriageReturnLineFeed,
"lf": NewLineKind.LineFeed
}),
@@ -263,7 +263,7 @@ namespace ts {
{
name: "target",
shortName: "t",
type: createMap({
type: createMapFromTemplate({
"es3": ScriptTarget.ES3,
"es5": ScriptTarget.ES5,
"es6": ScriptTarget.ES2015,
@@ -300,7 +300,7 @@ namespace ts {
},
{
name: "moduleResolution",
type: createMap({
type: createMapFromTemplate({
"node": ModuleResolutionKind.NodeJs,
"classic": ModuleResolutionKind.Classic,
}),
@@ -409,7 +409,7 @@ namespace ts {
type: "list",
element: {
name: "lib",
type: createMap({
type: createMapFromTemplate({
// JavaScript only
"es5": "lib.es5.d.ts",
"es6": "lib.es2015.d.ts",
@@ -531,9 +531,9 @@ namespace ts {
const optionNameMap = createMap<CommandLineOption>();
const shortOptionNames = createMap<string>();
forEach(optionDeclarations, option => {
optionNameMap[option.name.toLowerCase()] = option;
optionNameMap.set(option.name.toLowerCase(), option);
if (option.shortName) {
shortOptionNames[option.shortName] = option.name;
shortOptionNames.set(option.shortName, option.name);
}
});
@@ -543,7 +543,7 @@ namespace ts {
/* @internal */
export function createCompilerDiagnosticForInvalidCustomType(opt: CommandLineOptionOfCustomType): Diagnostic {
const namesOfType = Object.keys(opt.type).map(key => `'${key}'`).join(", ");
const namesOfType = arrayFrom(opt.type.keys()).map(key => `'${key}'`).join(", ");
return createCompilerDiagnostic(Diagnostics.Argument_for_0_option_must_be_Colon_1, `--${opt.name}`, namesOfType);
}
@@ -597,13 +597,13 @@ namespace ts {
s = s.slice(s.charCodeAt(1) === CharacterCodes.minus ? 2 : 1).toLowerCase();
// Try to translate short option names to their full equivalents.
if (s in shortOptionNames) {
s = shortOptionNames[s];
const short = shortOptionNames.get(s);
if (short !== undefined) {
s = short;
}
if (s in optionNameMap) {
const opt = optionNameMap[s];
const opt = optionNameMap.get(s);
if (opt) {
if (opt.isTSConfigOnly) {
errors.push(createCompilerDiagnostic(Diagnostics.Option_0_can_only_be_specified_in_tsconfig_json_file, opt.name));
}
@@ -726,7 +726,7 @@ namespace ts {
* @param fileNames array of filenames to be generated into tsconfig.json
*/
/* @internal */
export function generateTSConfig(options: CompilerOptions, fileNames: string[]): { compilerOptions: Map<CompilerOptionsValue> } {
export function generateTSConfig(options: CompilerOptions, fileNames: string[]): { compilerOptions: MapLike<CompilerOptionsValue> } {
const compilerOptions = extend(options, defaultInitCompilerOptions);
const configurations: any = {
compilerOptions: serializeCompilerOptions(compilerOptions)
@@ -751,18 +751,17 @@ namespace ts {
}
}
function getNameOfCompilerOptionValue(value: CompilerOptionsValue, customTypeMap: MapLike<string | number>): string | undefined {
function getNameOfCompilerOptionValue(value: CompilerOptionsValue, customTypeMap: Map<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 forEachEntry(customTypeMap, (mapValue, key) => {
if (mapValue === value) {
return key;
}
}
return undefined;
});
}
function serializeCompilerOptions(options: CompilerOptions): Map<CompilerOptionsValue> {
const result = createMap<CompilerOptionsValue>();
function serializeCompilerOptions(options: CompilerOptions): MapLike<CompilerOptionsValue> {
const result: ts.MapLike<CompilerOptionsValue> = {};
const optionsNameMap = getOptionNameMap().optionNameMap;
for (const name in options) {
@@ -778,7 +777,7 @@ namespace ts {
break;
default:
const value = options[name];
const optionDefinition = optionsNameMap[name.toLowerCase()];
const optionDefinition = optionsNameMap.get(name.toLowerCase());
if (optionDefinition) {
const customTypeMap = getCustomTypeMapOfCommandLineOption(optionDefinition);
if (!customTypeMap) {
@@ -1049,8 +1048,8 @@ namespace ts {
const optionNameMap = arrayToMap(optionDeclarations, opt => opt.name);
for (const id in jsonOptions) {
if (id in optionNameMap) {
const opt = optionNameMap[id];
const opt = optionNameMap.get(id);
if (opt) {
defaultOptions[opt.name] = convertJsonOption(opt, jsonOptions[id], basePath, errors);
}
else {
@@ -1086,8 +1085,9 @@ namespace ts {
function convertJsonOptionOfCustomType(opt: CommandLineOptionOfCustomType, value: string, errors: Diagnostic[]) {
const key = value.toLowerCase();
if (key in opt.type) {
return opt.type[key];
const val = opt.type.get(key);
if (val !== undefined) {
return val;
}
else {
errors.push(createCompilerDiagnosticForInvalidCustomType(opt));
@@ -1215,7 +1215,7 @@ namespace ts {
// file map that marks whether it was a regular wildcard match (with a `*` or `?` token),
// or a recursive directory. This information is used by filesystem watchers to monitor for
// new entries in these paths.
const wildcardDirectories: Map<WatchDirectoryFlags> = getWildcardDirectories(include, exclude, basePath, host.useCaseSensitiveFileNames);
const wildcardDirectories = getWildcardDirectories(include, exclude, basePath, host.useCaseSensitiveFileNames);
// Rather than requery this for each file and filespec, we query the supported extensions
// once and store it on the expansion context.
@@ -1226,7 +1226,7 @@ namespace ts {
if (fileNames) {
for (const fileName of fileNames) {
const file = combinePaths(basePath, fileName);
literalFileMap[keyMapper(file)] = file;
literalFileMap.set(keyMapper(file), file);
}
}
@@ -1249,14 +1249,14 @@ namespace ts {
removeWildcardFilesWithLowerPriorityExtension(file, wildcardFileMap, supportedExtensions, keyMapper);
const key = keyMapper(file);
if (!(key in literalFileMap) && !(key in wildcardFileMap)) {
wildcardFileMap[key] = file;
if (!literalFileMap.has(key) && !wildcardFileMap.has(key)) {
wildcardFileMap.set(key, file);
}
}
}
const literalFiles = reduceProperties(literalFileMap, addFileToOutput, []);
const wildcardFiles = reduceProperties(wildcardFileMap, addFileToOutput, []);
const literalFiles = arrayFrom(literalFileMap.values());
const wildcardFiles = arrayFrom(wildcardFileMap.values());
wildcardFiles.sort(host.useCaseSensitiveFileNames ? compareStrings : compareStringsCaseInsensitive);
return {
fileNames: literalFiles.concat(wildcardFiles),
@@ -1287,7 +1287,7 @@ namespace ts {
/**
* Gets directories in a set of include patterns that should be watched for changes.
*/
function getWildcardDirectories(include: string[], exclude: string[], path: string, useCaseSensitiveFileNames: boolean): Map<WatchDirectoryFlags> {
function getWildcardDirectories(include: string[], exclude: string[], path: string, useCaseSensitiveFileNames: boolean): MapLike<WatchDirectoryFlags> {
// We watch a directory recursively if it contains a wildcard anywhere in a directory segment
// of the pattern:
//
@@ -1302,7 +1302,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 = createMap<WatchDirectoryFlags>();
const wildcardDirectories: ts.MapLike<WatchDirectoryFlags> = {};
if (include !== undefined) {
const recursiveKeys: string[] = [];
for (const file of include) {
@@ -1325,13 +1325,13 @@ namespace ts {
}
// Remove any subpaths under an existing recursively watched directory.
for (const key in wildcardDirectories) {
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];
}
}
}
};
}
return wildcardDirectories;
@@ -1365,7 +1365,7 @@ namespace ts {
for (let i = ExtensionPriority.Highest; i < adjustedExtensionPriority; i++) {
const higherPriorityExtension = extensions[i];
const higherPriorityPath = keyMapper(changeExtension(file, higherPriorityExtension));
if (higherPriorityPath in literalFiles || higherPriorityPath in wildcardFiles) {
if (literalFiles.has(higherPriorityPath) || wildcardFiles.has(higherPriorityPath)) {
return true;
}
}
@@ -1387,21 +1387,10 @@ namespace ts {
for (let i = nextExtensionPriority; i < extensions.length; i++) {
const lowerPriorityExtension = extensions[i];
const lowerPriorityPath = keyMapper(changeExtension(file, lowerPriorityExtension));
delete wildcardFiles[lowerPriorityPath];
wildcardFiles.delete(lowerPriorityPath);
}
}
/**
* Adds a file to an array of files.
*
* @param output The output array.
* @param file The file path.
*/
function addFileToOutput(output: string[], file: string) {
output.push(file);
return output;
}
/**
* Gets a case sensitive key.
*
+184 -119
View File
@@ -23,13 +23,12 @@ namespace ts {
True = -1
}
const createObject = Object.create;
// More efficient to create a collator once and use its `compare` than to call `a.localeCompare(b)` many times.
export const collator: { compare(a: string, b: string): number } = typeof Intl === "object" && typeof Intl.Collator === "function" ? new Intl.Collator() : undefined;
export function createMap<T>(template?: MapLike<T>): Map<T> {
const map: Map<T> = createObject(null); // tslint:disable-line:no-null-keyword
/** Create a MapLike with good performance. */
function createDictionaryObject<T>(): MapLike<T> {
const map = Object.create(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
@@ -37,17 +36,113 @@ namespace ts {
map["__"] = undefined;
delete map["__"];
return map;
}
/** Create a new map. If a template object is provided, the map will copy entries from it. */
export function createMap<T>(): Map<T> {
return new MapCtr<T>();
}
export function createMapFromTemplate<T>(template?: MapLike<T>): Map<T> {
const map: Map<T> = new MapCtr<T>();
// 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];
map.set(key, template[key]);
}
return map;
}
// The global Map object. This may not be available, so we must test for it.
declare const Map: { new<T>(): Map<T> } | undefined;
// Internet Explorer's Map doesn't support iteration, so don't use it.
// tslint:disable-next-line:no-in-operator
const MapCtr = typeof Map !== "undefined" && "entries" in Map.prototype ? Map : shimMap();
// Keep the class inside a function so it doesn't get compiled if it's not used.
function shimMap(): { new<T>(): Map<T> } {
class MapIterator<T, U extends (string | T | [string, T])> {
private data: MapLike<T>;
private keys: string[];
private index = 0;
private selector: (data: MapLike<T>, key: string) => U;
constructor(data: MapLike<T>, selector: (data: MapLike<T>, key: string) => U) {
this.data = data;
this.selector = selector;
this.keys = Object.keys(data);
}
public next(): { value: U, done: false } | { value: never, done: true } {
const index = this.index;
if (index < this.keys.length) {
this.index++;
return { value: this.selector(this.data, this.keys[index]), done: false };
}
return { value: undefined as never, done: true }
}
}
return class<T> implements Map<T> {
private data = createDictionaryObject<T>();
public size = 0;
get(key: string): T {
return this.data[key];
}
set(key: string, value: T): this {
if (!this.has(key)) {
this.size++;
}
this.data[key] = value;
return this;
}
has(key: string): boolean {
// tslint:disable-next-line:no-in-operator
return key in this.data;
}
delete(key: string): boolean {
if (this.has(key)) {
this.size--;
delete this.data[key];
return true;
}
return false;
}
clear(): void {
this.data = createDictionaryObject<T>();
this.size = 0;
}
keys() {
return new MapIterator(this.data, (_data, key) => key);
}
values() {
return new MapIterator(this.data, (data, key) => data[key]);
}
entries() {
return new MapIterator(this.data, (data, key) => [key, data[key]] as [string, T]);
}
forEach(action: (value: T, key: string) => void): void {
for (const key in this.data) {
action(this.data[key], key);
}
}
}
}
export function createFileMap<T>(keyMapper?: (key: string) => string): FileMap<T> {
let files = createMap<T>();
const files = createMap<T>();
return {
get,
set,
@@ -59,39 +154,34 @@ namespace ts {
};
function forEachValueInMap(f: (key: Path, value: T) => void) {
for (const key in files) {
f(<Path>key, files[key]);
}
files.forEach((file, key) => {
f(<Path>key, file);
});
}
function getKeys() {
const keys: Path[] = [];
for (const key in files) {
keys.push(<Path>key);
}
return keys;
return arrayFrom(files.keys()) as Path[];
}
// path should already be well-formed so it does not need to be normalized
function get(path: Path): T {
return files[toKey(path)];
return files.get(toKey(path));
}
function set(path: Path, value: T) {
files[toKey(path)] = value;
files.set(toKey(path), value);
}
function contains(path: Path) {
return toKey(path) in files;
return files.has(toKey(path));
}
function remove(path: Path) {
const key = toKey(path);
delete files[key];
files.delete(toKey(path));
}
function clear() {
files = createMap<T>();
files.clear();
}
function toKey(path: Path): string {
@@ -420,17 +510,16 @@ namespace ts {
return result;
}
export function mapObject<T, U>(object: MapLike<T>, f: (key: string, x: T) => [string, U]): MapLike<U> {
let result: MapLike<U>;
if (object) {
result = {};
for (const v of getOwnKeys(object)) {
const [key, value]: [string, U] = f(v, object[v]) || [undefined, undefined];
if (key !== undefined) {
result[key] = value;
}
}
export function mapEntries<T, U>(map: Map<T>, f: (key: string, value: T) => [string, U]): Map<U> {
if (!map) {
return undefined;
}
const result = createMap<U>();
map.forEach((value, key) => {
const [newKey, newValue] = f(key, value);
result.set(newKey, newValue);
});
return result;
}
@@ -748,9 +837,6 @@ namespace ts {
/**
* 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.
*/
@@ -761,9 +847,6 @@ namespace ts {
/**
* 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.
*/
@@ -787,50 +870,48 @@ namespace ts {
return keys;
}
/**
* 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;
/** Shims `Array.from`. */
export function arrayFrom<T>(iterator: Iterator<T>): T[] {
const result: T[] = [];
for (let { value, done } = iterator.next(); !done; { value, done } = iterator.next()) {
result.push(value);
}
return result;
}
/**
* 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.
* Calls `callback` for each entry in the map, returning the first truthy result.
* Use `map.forEach` instead for normal iteration.
*/
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;
export function forEachEntry<T, U>(map: Map<T>, callback: (value: T, key: string) => U | undefined): U | undefined {
const iterator = map.entries();
for (let { value: pair, done } = iterator.next(); !done; { value: pair, done } = iterator.next()) {
const [key, value] = pair;
const result = callback(value, key);
if (result) {
return result;
}
}
return false;
return undefined;
}
/**
* 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];
/** `forEachEntry` for just keys. */
export function forEachKey<T>(map: Map<{}>, callback: (key: string) => T | undefined): T | undefined {
const iterator = map.keys();
for (let { value: key, done } = iterator.next(); !done; { value: key, done } = iterator.next()) {
const result = callback(key);
if (result) {
return result;
}
}
return undefined;
}
export function appendProperty<T>(map: Map<T>, key: string | number, value: T): Map<T> {
if (key === undefined || value === undefined) return map;
if (map === undefined) map = createMap<T>();
map[key] = value;
return map;
/** Copy entries from `source` to `target`. */
export function copyEntries<T>(source: Map<T>, target: Map<T>): void {
source.forEach((value, key) => {
target.set(key, value);
});
}
export function assign<T1 extends MapLike<{}>, T2, T3>(t: T1, arg1: T2, arg2: T3): T1 & T2 & T3;
@@ -845,24 +926,6 @@ namespace ts {
return t;
}
/**
* 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;
}
/**
* Performs a shallow equality comparison of the contents of two map-likes.
*
@@ -897,23 +960,14 @@ namespace ts {
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;
result.set(makeKey(value), makeValue ? makeValue(value) : value);
}
return result;
}
export function isEmpty<T>(map: Map<T>) {
for (const id in map) {
if (hasProperty(map, id)) {
return false;
}
}
return true;
}
export function cloneMap<T>(map: Map<T>) {
const clone = createMap<T>();
copyProperties(map, clone);
copyEntries(map, clone);
return clone;
}
@@ -938,32 +992,43 @@ namespace ts {
return result;
}
/**
* Adds the value to an array of values associated with the key, and returns the array.
* Creates the array if it does not already exist.
*/
export function multiMapAdd<V>(map: Map<V[]>, key: string | number, value: V): V[] {
const values = map[key];
if (values) {
values.push(value);
return values;
}
else {
return map[key] = [value];
}
export interface MultiMap<T> extends Map<T[]> {
/**
* Adds the value to an array of values associated with the key, and returns the array.
* Creates the array if it does not already exist.
*/
add(key: string, value: T): T[];
/**
* Removes a value from an array of values associated with the key.
* Does not preserve the order of those values.
* Does nothing if `key` is not in `map`, or `value` is not in `map[key]`.
*/
remove(key: string, value: T): void;
}
/**
* Removes a value from an array of values associated with the key.
* Does not preserve the order of those values.
* Does nothing if `key` is not in `map`, or `value` is not in `map[key]`.
*/
export function multiMapRemove<V>(map: Map<V[]>, key: string, value: V): void {
const values = map[key];
export function createMultiMap<T>(): MultiMap<T> {
const map = createMap<T[]>() as MultiMap<T>;
map.add = multiMapAdd;
map.remove = multiMapRemove;
return map;
}
function multiMapAdd<T>(this: MultiMap<T>, key: string, value: T) {
let values = this.get(key);
if (values) {
values.push(value);
}
else {
this.set(key, values = [value]);
}
return values;
}
function multiMapRemove<T>(this: MultiMap<T>, key: string, value: T) {
const values = this.get(key);
if (values) {
unorderedRemoveItem(values, value);
if (!values.length) {
delete map[key];
this.delete(key);
}
}
}
@@ -1066,7 +1131,7 @@ namespace ts {
return text.replace(/{(\d+)}/g, (_match, index?) => args[+index + baseIndex]);
}
export let localizedDiagnosticMessages: Map<string> = undefined;
export let localizedDiagnosticMessages: MapLike<string> = undefined;
export function getLocaleSpecificMessage(message: DiagnosticMessage) {
return localizedDiagnosticMessages && localizedDiagnosticMessages[message.key] || message.message;
+7 -6
View File
@@ -156,9 +156,9 @@ namespace ts {
});
if (usedTypeDirectiveReferences) {
for (const directive in usedTypeDirectiveReferences) {
forEachKey(usedTypeDirectiveReferences, directive => {
referencesOutput += `/// <reference types="${directive}" />${newLine}`;
}
});
}
return {
@@ -271,8 +271,8 @@ namespace ts {
usedTypeDirectiveReferences = createMap<string>();
}
for (const directive of typeReferenceDirectives) {
if (!(directive in usedTypeDirectiveReferences)) {
usedTypeDirectiveReferences[directive] = directive;
if (!usedTypeDirectiveReferences.has(directive)) {
usedTypeDirectiveReferences.set(directive, directive);
}
}
}
@@ -390,6 +390,7 @@ namespace ts {
case SyntaxKind.StringKeyword:
case SyntaxKind.NumberKeyword:
case SyntaxKind.BooleanKeyword:
case SyntaxKind.ObjectKeyword:
case SyntaxKind.SymbolKeyword:
case SyntaxKind.VoidKeyword:
case SyntaxKind.UndefinedKeyword:
@@ -581,14 +582,14 @@ namespace ts {
// do not need to keep track of created temp names.
function getExportDefaultTempVariableName(): string {
const baseName = "_default";
if (!(baseName in currentIdentifiers)) {
if (!currentIdentifiers.has(baseName)) {
return baseName;
}
let count = 0;
while (true) {
count++;
const name = baseName + "_" + count;
if (!(name in currentIdentifiers)) {
if (!currentIdentifiers.has(name)) {
return name;
}
}
+4
View File
@@ -2015,6 +2015,10 @@
"category": "Error",
"code": 2698
},
"Static property '{0}' conflicts with built-in property 'Function.{0}' of constructor function '{1}'.": {
"category": "Error",
"code": 2699
},
"Rest types may only be created from object types.": {
"category": "Error",
"code": 2700
+9 -7
View File
@@ -2043,11 +2043,11 @@ namespace ts {
// Skip the helper if it can be bundled but hasn't already been emitted and we
// are emitting a bundled module.
if (shouldBundle) {
if (bundledHelpers[helper.name]) {
if (bundledHelpers.get(helper.name)) {
continue;
}
bundledHelpers[helper.name] = true;
bundledHelpers.set(helper.name, true);
}
}
else if (isBundle) {
@@ -2508,15 +2508,16 @@ namespace ts {
function isUniqueName(name: string): boolean {
return !resolver.hasGlobalName(name) &&
!hasProperty(currentFileIdentifiers, name) &&
!hasProperty(generatedNameSet, name);
!currentFileIdentifiers.has(name) &&
!generatedNameSet.has(name);
}
function isUniqueLocalName(name: string, container: Node): boolean {
for (let node = container; isNodeDescendantOf(node, container); node = node.nextContainer) {
if (node.locals && hasProperty(node.locals, name)) {
if (node.locals) {
const local = node.locals.get(name);
// 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)) {
if (local && local.flags & (SymbolFlags.Value | SymbolFlags.ExportValue | SymbolFlags.Alias)) {
return false;
}
}
@@ -2565,7 +2566,8 @@ namespace ts {
while (true) {
const generatedName = baseName + i;
if (isUniqueName(generatedName)) {
return generatedNameSet[generatedName] = generatedName;
generatedNameSet.set(generatedName, generatedName);
return generatedName;
}
i++;
}
+38 -26
View File
@@ -1,4 +1,4 @@
/// <reference path="core.ts"/>
/// <reference path="core.ts"/>
/// <reference path="utilities.ts"/>
/* @internal */
@@ -2646,9 +2646,11 @@ namespace ts {
return destEmitNode;
}
function mergeTokenSourceMapRanges(sourceRanges: Map<TextRange>, destRanges: Map<TextRange>) {
if (!destRanges) destRanges = createMap<TextRange>();
copyProperties(sourceRanges, destRanges);
function mergeTokenSourceMapRanges(sourceRanges: TextRange[], destRanges: TextRange[]) {
if (!destRanges) destRanges = [];
for (const key in sourceRanges) {
destRanges[key] = sourceRanges[key];
}
return destRanges;
}
@@ -2762,7 +2764,7 @@ namespace ts {
*/
export function setTokenSourceMapRange<T extends Node>(node: T, token: SyntaxKind, range: TextRange) {
const emitNode = getOrCreateEmitNode(node);
const tokenSourceMapRanges = emitNode.tokenSourceMapRanges || (emitNode.tokenSourceMapRanges = createMap<TextRange>());
const tokenSourceMapRanges = emitNode.tokenSourceMapRanges || (emitNode.tokenSourceMapRanges = []);
tokenSourceMapRanges[token] = range;
return node;
}
@@ -2974,10 +2976,8 @@ namespace ts {
* Here we check if alternative name was provided for a given moduleName and return it if possible.
*/
function tryRenameExternalModule(moduleName: LiteralExpression, sourceFile: SourceFile) {
if (sourceFile.renamedDependencies && hasProperty(sourceFile.renamedDependencies, moduleName.text)) {
return createLiteral(sourceFile.renamedDependencies[moduleName.text]);
}
return undefined;
const rename = sourceFile.renamedDependencies && sourceFile.renamedDependencies.get(moduleName.text);
return rename && createLiteral(rename);
}
/**
@@ -3277,7 +3277,7 @@ namespace ts {
externalImports: (ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration)[]; // imports of other external modules
externalHelpersImportDeclaration: ImportDeclaration | undefined; // import of external helpers
exportSpecifiers: Map<ExportSpecifier[]>; // export specifiers by name
exportedBindings: Map<Identifier[]>; // exported names of local declarations
exportedBindings: Identifier[][]; // exported names of local declarations
exportedNames: Identifier[]; // all exported names local to module
exportEquals: ExportAssignment | undefined; // an export= declaration if one was present
hasExportStarsToExportValues: boolean; // whether this module contains export*
@@ -3285,8 +3285,8 @@ namespace ts {
export function collectExternalModuleInfo(sourceFile: SourceFile, resolver: EmitResolver, compilerOptions: CompilerOptions): ExternalModuleInfo {
const externalImports: (ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration)[] = [];
const exportSpecifiers = createMap<ExportSpecifier[]>();
const exportedBindings = createMap<Identifier[]>();
const exportSpecifiers = createMultiMap<ExportSpecifier>();
const exportedBindings: Identifier[][] = [];
const uniqueExports = createMap<boolean>();
let exportedNames: Identifier[];
let hasExportDefault = false;
@@ -3337,18 +3337,18 @@ namespace ts {
else {
// export { x, y }
for (const specifier of (<ExportDeclaration>node).exportClause.elements) {
if (!uniqueExports[specifier.name.text]) {
if (!uniqueExports.get(specifier.name.text)) {
const name = specifier.propertyName || specifier.name;
multiMapAdd(exportSpecifiers, name.text, specifier);
exportSpecifiers.add(name.text, specifier);
const decl = resolver.getReferencedImportDeclaration(name)
|| resolver.getReferencedValueDeclaration(name);
if (decl) {
multiMapAdd(exportedBindings, getOriginalNodeId(decl), specifier.name);
multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(decl), specifier.name);
}
uniqueExports[specifier.name.text] = true;
uniqueExports.set(specifier.name.text, true);
exportedNames = append(exportedNames, specifier.name);
}
}
@@ -3375,16 +3375,16 @@ namespace ts {
if (hasModifier(node, ModifierFlags.Default)) {
// export default function() { }
if (!hasExportDefault) {
multiMapAdd(exportedBindings, getOriginalNodeId(node), getDeclarationName(<FunctionDeclaration>node));
multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(node), getDeclarationName(<FunctionDeclaration>node));
hasExportDefault = true;
}
}
else {
// export function x() { }
const name = (<FunctionDeclaration>node).name;
if (!uniqueExports[name.text]) {
multiMapAdd(exportedBindings, getOriginalNodeId(node), name);
uniqueExports[name.text] = true;
if (!uniqueExports.get(name.text)) {
multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(node), name);
uniqueExports.set(name.text, true);
exportedNames = append(exportedNames, name);
}
}
@@ -3396,16 +3396,16 @@ namespace ts {
if (hasModifier(node, ModifierFlags.Default)) {
// export default class { }
if (!hasExportDefault) {
multiMapAdd(exportedBindings, getOriginalNodeId(node), getDeclarationName(<ClassDeclaration>node));
multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(node), getDeclarationName(<ClassDeclaration>node));
hasExportDefault = true;
}
}
else {
// export class x { }
const name = (<ClassDeclaration>node).name;
if (!uniqueExports[name.text]) {
multiMapAdd(exportedBindings, getOriginalNodeId(node), name);
uniqueExports[name.text] = true;
if (!uniqueExports.get(name.text)) {
multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(node), name);
uniqueExports.set(name.text, true);
exportedNames = append(exportedNames, name);
}
}
@@ -3426,11 +3426,23 @@ namespace ts {
}
}
else if (!isGeneratedIdentifier(decl.name)) {
if (!uniqueExports[decl.name.text]) {
uniqueExports[decl.name.text] = true;
if (!uniqueExports.get(decl.name.text)) {
uniqueExports.set(decl.name.text, true);
exportedNames = append(exportedNames, decl.name);
}
}
return exportedNames;
}
/** Use a sparse array as a multi-map. */
function multiMapSparseArrayAdd<V>(map: V[][], key: number, value: V): V[] {
let values = map[key];
if (values) {
values.push(value);
}
else {
map[key] = values = [value];
}
return values;
}
}
+5 -4
View File
@@ -336,9 +336,10 @@ namespace ts {
if (!moduleHasNonRelativeName(nonRelativeModuleName)) {
return undefined;
}
let perModuleNameCache = moduleNameToDirectoryMap[nonRelativeModuleName];
let perModuleNameCache = moduleNameToDirectoryMap.get(nonRelativeModuleName);
if (!perModuleNameCache) {
moduleNameToDirectoryMap[nonRelativeModuleName] = perModuleNameCache = createPerModuleNameCache();
perModuleNameCache = createPerModuleNameCache();
moduleNameToDirectoryMap.set(nonRelativeModuleName, perModuleNameCache);
}
return perModuleNameCache;
}
@@ -422,7 +423,7 @@ namespace ts {
}
const containingDirectory = getDirectoryPath(containingFile);
const perFolderCache = cache && cache.getOrCreateCacheForDirectory(containingDirectory);
let result = perFolderCache && perFolderCache[moduleName];
let result = perFolderCache && perFolderCache.get(moduleName);
if (result) {
if (traceEnabled) {
@@ -453,7 +454,7 @@ namespace ts {
}
if (perFolderCache) {
perFolderCache[moduleName] = result;
perFolderCache.set(moduleName, result);
// put result in per-module name cache
const perModuleNameCache = cache.getOrCreateCacheForModuleName(moduleName);
if (perModuleNameCache) {
+5 -1
View File
@@ -1134,7 +1134,11 @@ namespace ts {
function internIdentifier(text: string): string {
text = escapeIdentifier(text);
return identifiers[text] || (identifiers[text] = text);
let identifier = identifiers.get(text);
if (identifier === undefined) {
identifiers.set(text, identifier = text);
}
return identifier;
}
// An identifier that starts with two underscores has an extra underscore character prepended to it to avoid issues
+10 -10
View File
@@ -27,8 +27,8 @@ namespace ts.performance {
*/
export function mark(markName: string) {
if (enabled) {
marks[markName] = timestamp();
counts[markName] = (counts[markName] || 0) + 1;
marks.set(markName, timestamp());
counts.set(markName, (counts.get(markName) || 0) + 1);
profilerEvent(markName);
}
}
@@ -44,9 +44,9 @@ namespace ts.performance {
*/
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);
const end = endMarkName && marks.get(endMarkName) || timestamp();
const start = startMarkName && marks.get(startMarkName) || profilerStart;
measures.set(measureName, (measures.get(measureName) || 0) + (end - start));
}
}
@@ -56,7 +56,7 @@ namespace ts.performance {
* @param markName The name of the mark.
*/
export function getCount(markName: string) {
return counts && counts[markName] || 0;
return counts && counts.get(markName) || 0;
}
/**
@@ -65,7 +65,7 @@ namespace ts.performance {
* @param measureName The name of the measure whose durations should be accumulated.
*/
export function getDuration(measureName: string) {
return measures && measures[measureName] || 0;
return measures && measures.get(measureName) || 0;
}
/**
@@ -74,9 +74,9 @@ namespace ts.performance {
* @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]);
}
measures.forEach((measure, key) => {
cb(key, measure);
});
}
/** Enables (and resets) performance measurements for the compiler. */
+26 -22
View File
@@ -111,11 +111,11 @@ namespace ts {
}
function directoryExists(directoryPath: string): boolean {
if (directoryPath in existingDirectories) {
if (existingDirectories.has(directoryPath)) {
return true;
}
if (sys.directoryExists(directoryPath)) {
existingDirectories[directoryPath] = true;
existingDirectories.set(directoryPath, true);
return true;
}
return false;
@@ -139,11 +139,11 @@ namespace ts {
const hash = sys.createHash(data);
const mtimeBefore = sys.getModifiedTime(fileName);
if (mtimeBefore && fileName in outputFingerprints) {
const fingerprint = outputFingerprints[fileName];
if (mtimeBefore) {
const fingerprint = outputFingerprints.get(fileName);
// If output has not been changed, and the file has no external modification
if (fingerprint.byteOrderMark === writeByteOrderMark &&
if (fingerprint &&
fingerprint.byteOrderMark === writeByteOrderMark &&
fingerprint.hash === hash &&
fingerprint.mtime.getTime() === mtimeBefore.getTime()) {
return;
@@ -154,11 +154,11 @@ namespace ts {
const mtimeAfter = sys.getModifiedTime(fileName);
outputFingerprints[fileName] = {
outputFingerprints.set(fileName, {
hash,
byteOrderMark: writeByteOrderMark,
mtime: mtimeAfter
};
});
}
function writeFile(fileName: string, data: string, writeByteOrderMark: boolean, onError?: (message: string) => void) {
@@ -278,9 +278,13 @@ namespace ts {
const resolutions: T[] = [];
const cache = createMap<T>();
for (const name of names) {
const result = name in cache
? cache[name]
: cache[name] = loader(name, containingFile);
let result: T;
if (cache.has(name)) {
result = cache.get(name);
}
else {
cache.set(name, result = loader(name, containingFile));
}
resolutions.push(result);
}
return resolutions;
@@ -460,7 +464,7 @@ namespace ts {
classifiableNames = createMap<string>();
for (const sourceFile of files) {
copyProperties(sourceFile.classifiableNames, classifiableNames);
copyEntries(sourceFile.classifiableNames, classifiableNames);
}
}
@@ -735,7 +739,7 @@ namespace ts {
}
function isSourceFileFromExternalLibrary(file: SourceFile): boolean {
return sourceFilesFoundSearchingNodeModules[file.path];
return sourceFilesFoundSearchingNodeModules.get(file.path);
}
function getDiagnosticsProducingTypeChecker() {
@@ -1298,20 +1302,20 @@ 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 && sourceFilesFoundSearchingNodeModules[file.path] && currentNodeModulesDepth == 0) {
sourceFilesFoundSearchingNodeModules[file.path] = false;
if (file && sourceFilesFoundSearchingNodeModules.get(file.path) && currentNodeModulesDepth == 0) {
sourceFilesFoundSearchingNodeModules.set(file.path, false);
if (!options.noResolve) {
processReferencedFiles(file, isDefaultLib);
processTypeReferenceDirectives(file);
}
modulesWithElidedImports[file.path] = false;
modulesWithElidedImports.set(file.path, false);
processImportedModules(file);
}
// See if we need to reprocess the imports due to prior skipped imports
else if (file && modulesWithElidedImports[file.path]) {
else if (file && modulesWithElidedImports.get(file.path)) {
if (currentNodeModulesDepth < maxNodeModuleJsDepth) {
modulesWithElidedImports[file.path] = false;
modulesWithElidedImports.set(file.path, false);
processImportedModules(file);
}
}
@@ -1332,7 +1336,7 @@ namespace ts {
filesByName.set(path, file);
if (file) {
sourceFilesFoundSearchingNodeModules[path] = (currentNodeModulesDepth > 0);
sourceFilesFoundSearchingNodeModules.set(path, currentNodeModulesDepth > 0);
file.path = path;
if (host.useCaseSensitiveFileNames()) {
@@ -1393,7 +1397,7 @@ namespace ts {
refFile?: SourceFile, refPos?: number, refEnd?: number): void {
// If we already found this library as a primary reference - nothing to do
const previousResolution = resolvedTypeReferenceDirectives[typeReferenceDirective];
const previousResolution = resolvedTypeReferenceDirectives.get(typeReferenceDirective);
if (previousResolution && previousResolution.primary) {
return;
}
@@ -1433,7 +1437,7 @@ namespace ts {
}
if (saveResolution) {
resolvedTypeReferenceDirectives[typeReferenceDirective] = resolvedTypeReferenceDirective;
resolvedTypeReferenceDirectives.set(typeReferenceDirective, resolvedTypeReferenceDirective);
}
}
@@ -1486,7 +1490,7 @@ namespace ts {
const shouldAddFile = resolvedFileName && !getResolutionDiagnostic(options, resolution) && !options.noResolve && i < file.imports.length && !elideImport;
if (elideImport) {
modulesWithElidedImports[file.path] = true;
modulesWithElidedImports.set(file.path, true);
}
else if (shouldAddFile) {
const path = toPath(resolvedFileName, currentDirectory, getCanonicalFileName);
+12 -11
View File
@@ -56,7 +56,7 @@ namespace ts {
tryScan<T>(callback: () => T): T;
}
const textToToken = createMap({
const textToToken = createMapFromTemplate({
"abstract": SyntaxKind.AbstractKeyword,
"any": SyntaxKind.AnyKeyword,
"as": SyntaxKind.AsKeyword,
@@ -276,9 +276,9 @@ namespace ts {
function makeReverseMap(source: Map<number>): string[] {
const result: string[] = [];
for (const name in source) {
result[source[name]] = name;
}
source.forEach((value, name) => {
result[value] = name;
});
return result;
}
@@ -290,7 +290,7 @@ namespace ts {
/* @internal */
export function stringToToken(s: string): SyntaxKind {
return textToToken[s];
return textToToken.get(s);
}
/* @internal */
@@ -364,8 +364,6 @@ namespace ts {
return computeLineAndCharacterOfPosition(getLineStarts(sourceFile), position);
}
const hasOwnProperty = Object.prototype.hasOwnProperty;
export function isWhiteSpace(ch: number): boolean {
return isWhiteSpaceSingleLine(ch) || isLineBreak(ch);
}
@@ -734,11 +732,11 @@ namespace ts {
return comments;
}
export function getLeadingCommentRanges(text: string, pos: number): CommentRange[] {
export function getLeadingCommentRanges(text: string, pos: number): CommentRange[] | undefined {
return reduceEachLeadingCommentRange(text, pos, appendCommentRange, undefined, undefined);
}
export function getTrailingCommentRanges(text: string, pos: number): CommentRange[] {
export function getTrailingCommentRanges(text: string, pos: number): CommentRange[] | undefined {
return reduceEachTrailingCommentRange(text, pos, appendCommentRange, undefined, undefined);
}
@@ -1184,8 +1182,11 @@ namespace ts {
const len = tokenValue.length;
if (len >= 2 && len <= 11) {
const ch = tokenValue.charCodeAt(0);
if (ch >= CharacterCodes.a && ch <= CharacterCodes.z && hasOwnProperty.call(textToToken, tokenValue)) {
return token = textToToken[tokenValue];
if (ch >= CharacterCodes.a && ch <= CharacterCodes.z) {
token = textToToken.get(tokenValue);
if (token !== undefined) {
return token;
}
}
}
return token = SyntaxKind.Identifier;
+14 -11
View File
@@ -1,4 +1,4 @@
/// <reference path="core.ts"/>
/// <reference path="core.ts"/>
declare function setTimeout(handler: (...args: any[]) => void, timeout: number): any;
declare function clearTimeout(handle: any): void;
@@ -246,23 +246,23 @@ namespace ts {
function createWatchedFileSet() {
const dirWatchers = createMap<DirectoryWatcher>();
// One file can have multiple watchers
const fileWatcherCallbacks = createMap<FileWatcherCallback[]>();
const fileWatcherCallbacks = createMultiMap<FileWatcherCallback>();
return { addFile, removeFile };
function reduceDirWatcherRefCountForFile(fileName: string) {
const dirName = getDirectoryPath(fileName);
const watcher = dirWatchers[dirName];
const watcher = dirWatchers.get(dirName);
if (watcher) {
watcher.referenceCount -= 1;
if (watcher.referenceCount <= 0) {
watcher.close();
delete dirWatchers[dirName];
dirWatchers.delete(dirName);
}
}
}
function addDirWatcher(dirPath: string): void {
let watcher = dirWatchers[dirPath];
let watcher = dirWatchers.get(dirPath);
if (watcher) {
watcher.referenceCount += 1;
return;
@@ -273,12 +273,12 @@ namespace ts {
(eventName: string, relativeFileName: string) => fileEventHandler(eventName, relativeFileName, dirPath)
);
watcher.referenceCount = 1;
dirWatchers[dirPath] = watcher;
dirWatchers.set(dirPath, watcher);
return;
}
function addFileWatcherCallback(filePath: string, callback: FileWatcherCallback): void {
multiMapAdd(fileWatcherCallbacks, filePath, callback);
fileWatcherCallbacks.add(filePath, callback);
}
function addFile(fileName: string, callback: FileWatcherCallback): WatchedFile {
@@ -294,7 +294,7 @@ namespace ts {
}
function removeFileWatcherCallback(filePath: string, callback: FileWatcherCallback) {
multiMapRemove(fileWatcherCallbacks, filePath, callback);
fileWatcherCallbacks.remove(filePath, callback);
}
function fileEventHandler(eventName: string, relativeFileName: string, baseDirPath: string) {
@@ -303,9 +303,12 @@ namespace ts {
? undefined
: ts.getNormalizedAbsolutePath(relativeFileName, baseDirPath);
// Some applications save a working file via rename operations
if ((eventName === "change" || eventName === "rename") && fileWatcherCallbacks[fileName]) {
for (const fileCallback of fileWatcherCallbacks[fileName]) {
fileCallback(fileName);
if ((eventName === "change" || eventName === "rename")) {
const callbacks = fileWatcherCallbacks.get(fileName);
if (callbacks) {
for (const fileCallback of callbacks) {
fileCallback(fileName);
}
}
}
}
+12 -10
View File
@@ -1,4 +1,4 @@
/// <reference path="visitor.ts" />
/// <reference path="visitor.ts" />
/// <reference path="transformers/ts.ts" />
/// <reference path="transformers/jsx.ts" />
/// <reference path="transformers/esnext.ts" />
@@ -13,14 +13,16 @@
/* @internal */
namespace ts {
const moduleTransformerMap = createMap<Transformer>({
[ModuleKind.ES2015]: transformES2015Module,
[ModuleKind.System]: transformSystemModule,
[ModuleKind.AMD]: transformModule,
[ModuleKind.CommonJS]: transformModule,
[ModuleKind.UMD]: transformModule,
[ModuleKind.None]: transformModule,
});
function getModuleTransformer(moduleKind: ModuleKind): Transformer {
switch (moduleKind) {
case ModuleKind.ES2015:
return transformES2015Module;
case ModuleKind.System:
return transformSystemModule;
default:
return transformModule;
}
}
const enum SyntaxKindFeatureFlags {
Substitution = 1 << 0,
@@ -56,7 +58,7 @@ namespace ts {
transformers.push(transformGenerators);
}
transformers.push(moduleTransformerMap[moduleKind] || moduleTransformerMap[ModuleKind.None]);
transformers.push(getModuleTransformer(moduleKind));
// The ES5 transformer is last so that it can substitute expressions like `exports.default`
// for ES3.
+8 -9
View File
@@ -599,7 +599,7 @@ namespace ts {
// - break/continue is non-labeled and located in non-converted loop/switch statement
const jump = node.kind === SyntaxKind.BreakStatement ? Jump.Break : Jump.Continue;
const canUseBreakOrContinue =
(node.label && convertedLoopState.labels && convertedLoopState.labels[node.label.text]) ||
(node.label && convertedLoopState.labels && convertedLoopState.labels.get(node.label.text)) ||
(!node.label && (convertedLoopState.allowedNonLabeledJumps & jump));
if (!canUseBreakOrContinue) {
@@ -2135,11 +2135,11 @@ namespace ts {
}
function recordLabel(node: LabeledStatement) {
convertedLoopState.labels[node.label.text] = node.label.text;
convertedLoopState.labels.set(node.label.text, node.label.text);
}
function resetLabel(node: LabeledStatement) {
convertedLoopState.labels[node.label.text] = undefined;
convertedLoopState.labels.set(node.label.text, undefined);
}
function visitLabeledStatement(node: LabeledStatement): VisitResult<Statement> {
@@ -2798,13 +2798,13 @@ namespace ts {
if (!state.labeledNonLocalBreaks) {
state.labeledNonLocalBreaks = createMap<string>();
}
state.labeledNonLocalBreaks[labelText] = labelMarker;
state.labeledNonLocalBreaks.set(labelText, labelMarker);
}
else {
if (!state.labeledNonLocalContinues) {
state.labeledNonLocalContinues = createMap<string>();
}
state.labeledNonLocalContinues[labelText] = labelMarker;
state.labeledNonLocalContinues.set(labelText, labelMarker);
}
}
@@ -2812,13 +2812,12 @@ namespace ts {
if (!table) {
return;
}
for (const labelText in table) {
const labelMarker = table[labelText];
table.forEach((labelMarker, labelText) => {
const statements: Statement[] = [];
// if there are no outer converted loop or outer label in question is located inside outer converted loop
// then emit labeled break\continue
// otherwise propagate pair 'label -> marker' to outer converted loop and emit 'return labelMarker' so outer loop can later decide what to do
if (!outerLoop || (outerLoop.labels && outerLoop.labels[labelText])) {
if (!outerLoop || (outerLoop.labels && outerLoop.labels.get(labelText))) {
const label = createIdentifier(labelText);
statements.push(isBreak ? createBreak(label) : createContinue(label));
}
@@ -2827,7 +2826,7 @@ namespace ts {
statements.push(createReturn(loopResultName));
}
caseClauses.push(createCaseClause(createLiteral(labelMarker), statements));
}
});
}
function processLoopVariableDeclaration(decl: VariableDeclaration | BindingElement, loopParameters: ParameterDeclaration[], loopOutParameters: LoopOutParameter[]) {
+16 -14
View File
@@ -1,4 +1,4 @@
/// <reference path="../factory.ts" />
/// <reference path="../factory.ts" />
/// <reference path="../visitor.ts" />
// Transforms generator functions into a compatible ES5 representation with similar runtime
@@ -217,13 +217,15 @@ namespace ts {
Endfinally = 7,
}
const instructionNames = createMap<string>({
[Instruction.Return]: "return",
[Instruction.Break]: "break",
[Instruction.Yield]: "yield",
[Instruction.YieldStar]: "yield*",
[Instruction.Endfinally]: "endfinally",
});
function getInstructionName(instruction: Instruction): string {
switch (instruction) {
case Instruction.Return: return "return";
case Instruction.Break: return "break";
case Instruction.Yield: return "yield";
case Instruction.YieldStar: return "yield*";
case Instruction.Endfinally: return "endfinally";
}
}
export function transformGenerators(context: TransformationContext) {
const {
@@ -241,7 +243,7 @@ namespace ts {
let currentSourceFile: SourceFile;
let renamedCatchVariables: Map<boolean>;
let renamedCatchVariableDeclarations: Map<Identifier>;
let renamedCatchVariableDeclarations: Identifier[];
let inGeneratorFunctionBody: boolean;
let inStatementContainingYield: boolean;
@@ -1923,12 +1925,12 @@ namespace ts {
}
function substituteExpressionIdentifier(node: Identifier) {
if (renamedCatchVariables && hasProperty(renamedCatchVariables, node.text)) {
if (renamedCatchVariables && renamedCatchVariables.has(node.text)) {
const original = getOriginalNode(node);
if (isIdentifier(original) && original.parent) {
const declaration = resolver.getReferencedValueDeclaration(original);
if (declaration) {
const name = getProperty(renamedCatchVariableDeclarations, String(getOriginalNodeId(declaration)));
const name = renamedCatchVariableDeclarations[getOriginalNodeId(declaration)];
if (name) {
const clone = getMutableClone(name);
setSourceMapRange(clone, node);
@@ -2094,11 +2096,11 @@ namespace ts {
if (!renamedCatchVariables) {
renamedCatchVariables = createMap<boolean>();
renamedCatchVariableDeclarations = createMap<Identifier>();
renamedCatchVariableDeclarations = [];
context.enableSubstitution(SyntaxKind.Identifier);
}
renamedCatchVariables[text] = true;
renamedCatchVariables.set(text, true);
renamedCatchVariableDeclarations[getOriginalNodeId(variable)] = name;
const exception = <ExceptionBlock>peekBlock();
@@ -2403,7 +2405,7 @@ namespace ts {
*/
function createInstruction(instruction: Instruction): NumericLiteral {
const literal = createLiteral(instruction);
literal.trailingComment = instructionNames[instruction];
literal.trailingComment = getInstructionName(instruction);
return literal;
}
+2 -2
View File
@@ -238,7 +238,7 @@ namespace ts {
return String.fromCharCode(parseInt(hex, 16));
}
else {
const ch = entities[word];
const ch = entities.get(word);
// If this is not a valid entity, then just use `match` (replace it with itself, i.e. don't replace)
return ch ? String.fromCharCode(ch) : match;
}
@@ -286,7 +286,7 @@ namespace ts {
}
}
const entities = createMap<number>({
const entities = createMapFromTemplate<number>({
"quot": 0x0022,
"amp": 0x0026,
"apos": 0x0027,
+17 -15
View File
@@ -1,4 +1,4 @@
/// <reference path="../../factory.ts" />
/// <reference path="../../factory.ts" />
/// <reference path="../../visitor.ts" />
/*@internal*/
@@ -10,12 +10,13 @@ namespace ts {
importAliasNames: ParameterDeclaration[];
}
const transformModuleDelegates = createMap<(node: SourceFile) => SourceFile>({
[ModuleKind.None]: transformCommonJSModule,
[ModuleKind.CommonJS]: transformCommonJSModule,
[ModuleKind.AMD]: transformAMDModule,
[ModuleKind.UMD]: transformUMDModule,
});
function getTransformModuleDelegate(moduleKind: ModuleKind): (node: SourceFile) => SourceFile {
switch (moduleKind) {
case ModuleKind.AMD: return transformAMDModule;
case ModuleKind.UMD: return transformUMDModule;
default: return transformCommonJSModule;
}
}
const {
startLexicalEnvironment,
@@ -38,12 +39,12 @@ namespace ts {
context.enableSubstitution(SyntaxKind.ShorthandPropertyAssignment); // Substitutes shorthand property assignments for imported/exported symbols.
context.enableEmitNotification(SyntaxKind.SourceFile); // Restore state when substituting nodes in a file.
const moduleInfoMap = createMap<ExternalModuleInfo>(); // The ExternalModuleInfo for each file.
const deferredExports = createMap<Statement[]>(); // Exports to defer until an EndOfDeclarationMarker is found.
const moduleInfoMap: ExternalModuleInfo[] = []; // The ExternalModuleInfo for each file.
const deferredExports: Statement[][] = []; // Exports to defer until an EndOfDeclarationMarker is found.
let currentSourceFile: SourceFile; // The current file.
let currentModuleInfo: ExternalModuleInfo; // The ExternalModuleInfo for the current file.
let noSubstitution: Map<boolean>; // Set of nodes for which substitution rules should be ignored.
let noSubstitution: boolean[]; // Set of nodes for which substitution rules should be ignored.
return transformSourceFile;
@@ -60,10 +61,11 @@ namespace ts {
}
currentSourceFile = node;
currentModuleInfo = moduleInfoMap[getOriginalNodeId(node)] = collectExternalModuleInfo(node, resolver, compilerOptions);
currentModuleInfo = collectExternalModuleInfo(node, resolver, compilerOptions);
moduleInfoMap[getOriginalNodeId(node)] = currentModuleInfo;
// Perform the transformation.
const transformModule = transformModuleDelegates[moduleKind] || transformModuleDelegates[ModuleKind.None];
const transformModule = getTransformModuleDelegate(moduleKind);
const updated = transformModule(node);
currentSourceFile = undefined;
@@ -1083,7 +1085,7 @@ namespace ts {
*/
function appendExportsOfDeclaration(statements: Statement[] | undefined, decl: Declaration): Statement[] | undefined {
const name = getDeclarationName(decl);
const exportSpecifiers = currentModuleInfo.exportSpecifiers[name.text];
const exportSpecifiers = currentModuleInfo.exportSpecifiers.get(name.text);
if (exportSpecifiers) {
for (const exportSpecifier of exportSpecifiers) {
statements = appendExportStatement(statements, exportSpecifier.name, name, /*location*/ exportSpecifier.name);
@@ -1107,7 +1109,7 @@ namespace ts {
function appendExportStatement(statements: Statement[] | undefined, exportName: Identifier, expression: Expression, location?: TextRange, allowComments?: boolean): Statement[] | undefined {
if (exportName.text === "default") {
const sourceFile = getOriginalNode(currentSourceFile, isSourceFile);
if (sourceFile && !sourceFile.symbol.exports["___esModule"]) {
if (sourceFile && !sourceFile.symbol.exports.get("___esModule")) {
if (languageVersion === ScriptTarget.ES3) {
statements = append(statements,
createStatement(
@@ -1213,7 +1215,7 @@ namespace ts {
if (node.kind === SyntaxKind.SourceFile) {
currentSourceFile = <SourceFile>node;
currentModuleInfo = moduleInfoMap[getOriginalNodeId(currentSourceFile)];
noSubstitution = createMap<boolean>();
noSubstitution = [];
previousOnEmitNode(emitContext, node, emitCallback);
+14 -13
View File
@@ -1,4 +1,4 @@
/// <reference path="../../factory.ts" />
/// <reference path="../../factory.ts" />
/// <reference path="../../visitor.ts" />
/*@internal*/
@@ -28,10 +28,10 @@ namespace ts {
context.enableSubstitution(SyntaxKind.PostfixUnaryExpression); // Substitutes updates to exported symbols.
context.enableEmitNotification(SyntaxKind.SourceFile); // Restore state when substituting nodes in a file.
const moduleInfoMap = createMap<ExternalModuleInfo>(); // The ExternalModuleInfo for each file.
const deferredExports = createMap<Statement[]>(); // Exports to defer until an EndOfDeclarationMarker is found.
const exportFunctionsMap = createMap<Identifier>(); // The export function associated with a source file.
const noSubstitutionMap = createMap<Map<boolean>>(); // Set of nodes for which substitution rules should be ignored for each file.
const moduleInfoMap: ExternalModuleInfo[] = []; // The ExternalModuleInfo for each file.
const deferredExports: Statement[][] = []; // Exports to defer until an EndOfDeclarationMarker is found.
const exportFunctionsMap: Identifier[] = []; // The export function associated with a source file.
const noSubstitutionMap: boolean[][] = []; // Set of nodes for which substitution rules should be ignored for each file.
let currentSourceFile: SourceFile; // The current file.
let moduleInfo: ExternalModuleInfo; // ExternalModuleInfo for the current file.
@@ -39,7 +39,7 @@ namespace ts {
let contextObject: Identifier; // The context object for the current file.
let hoistedStatements: Statement[];
let enclosingBlockScopedContainer: Node;
let noSubstitution: Map<boolean>; // Set of nodes for which substitution rules should be ignored.
let noSubstitution: boolean[]; // Set of nodes for which substitution rules should be ignored.
return transformSourceFile;
@@ -77,7 +77,8 @@ namespace ts {
// Make sure that the name of the 'exports' function does not conflict with
// existing identifiers.
exportFunction = exportFunctionsMap[id] = createUniqueName("exports");
exportFunction = createUniqueName("exports");
exportFunctionsMap[id] = exportFunction;
contextObject = createUniqueName("context");
// Add the body of the module.
@@ -148,13 +149,13 @@ namespace ts {
const externalImport = externalImports[i];
const externalModuleName = getExternalModuleNameLiteral(externalImport, currentSourceFile, host, resolver, compilerOptions);
const text = externalModuleName.text;
if (hasProperty(groupIndices, text)) {
const groupIndex = groupIndices.get(text);
if (groupIndex !== undefined) {
// deduplicate/group entries in dependency list by the dependency name
const groupIndex = groupIndices[text];
dependencyGroups[groupIndex].externalImports.push(externalImport);
}
else {
groupIndices[text] = dependencyGroups.length;
groupIndices.set(text, dependencyGroups.length);
dependencyGroups.push({
name: externalModuleName,
externalImports: [externalImport]
@@ -306,7 +307,7 @@ namespace ts {
// this set is used to filter names brought by star expors.
// local names set should only be added if we have anything exported
if (!moduleInfo.exportedNames && isEmpty(moduleInfo.exportSpecifiers)) {
if (!moduleInfo.exportedNames && moduleInfo.exportSpecifiers.size === 0) {
// no exported declarations (export var ...) or export specifiers (export {x})
// check if we have any non star export declarations.
let hasExportDeclarationWithExportClause = false;
@@ -1081,7 +1082,7 @@ namespace ts {
}
const name = getDeclarationName(decl);
const exportSpecifiers = moduleInfo.exportSpecifiers[name.text];
const exportSpecifiers = moduleInfo.exportSpecifiers.get(name.text);
if (exportSpecifiers) {
for (const exportSpecifier of exportSpecifiers) {
if (exportSpecifier.name.text !== excludeName) {
@@ -1770,7 +1771,7 @@ namespace ts {
* @param node The node which should not be substituted.
*/
function preventSubstitution<T extends Node>(node: T): T {
if (noSubstitution === undefined) noSubstitution = createMap<boolean>();
if (noSubstitution === undefined) noSubstitution = [];
noSubstitution[getNodeId(node)] = true;
return node;
}
+6 -6
View File
@@ -1,4 +1,4 @@
/// <reference path="../factory.ts" />
/// <reference path="../factory.ts" />
/// <reference path="../visitor.ts" />
/// <reference path="./destructuring.ts" />
@@ -60,7 +60,7 @@ namespace ts {
* A map that keeps track of aliases created for classes with decorators to avoid issues
* with the double-binding behavior of classes.
*/
let classAliases: Map<Identifier>;
let classAliases: Identifier[];
/**
* Keeps track of whether we are within any containing namespaces when performing
@@ -2538,8 +2538,8 @@ namespace ts {
currentScopeFirstDeclarationsOfName = createMap<Node>();
}
if (!(name in currentScopeFirstDeclarationsOfName)) {
currentScopeFirstDeclarationsOfName[name] = node;
if (!currentScopeFirstDeclarationsOfName.has(name)) {
currentScopeFirstDeclarationsOfName.set(name, node);
}
}
}
@@ -2552,7 +2552,7 @@ namespace ts {
if (currentScopeFirstDeclarationsOfName) {
const name = node.symbol && node.symbol.name;
if (name) {
return currentScopeFirstDeclarationsOfName[name] === node;
return currentScopeFirstDeclarationsOfName.get(name) === node;
}
}
@@ -3125,7 +3125,7 @@ namespace ts {
context.enableSubstitution(SyntaxKind.Identifier);
// Keep track of class aliases.
classAliases = createMap<Identifier>();
classAliases = [];
}
}
+17 -17
View File
@@ -1,4 +1,4 @@
/// <reference path="program.ts"/>
/// <reference path="program.ts"/>
/// <reference path="commandLineParser.ts"/>
namespace ts {
@@ -67,11 +67,13 @@ namespace ts {
const gutterSeparator = " ";
const resetEscapeSequence = "\u001b[0m";
const ellipsis = "...";
const categoryFormatMap = createMap<string>({
[DiagnosticCategory.Warning]: yellowForegroundEscapeSequence,
[DiagnosticCategory.Error]: redForegroundEscapeSequence,
[DiagnosticCategory.Message]: blueForegroundEscapeSequence,
});
function getCategoryFormat(category: DiagnosticCategory): string {
switch (category) {
case DiagnosticCategory.Warning: return yellowForegroundEscapeSequence;
case DiagnosticCategory.Error: return redForegroundEscapeSequence;
case DiagnosticCategory.Message: return blueForegroundEscapeSequence;
}
}
function formatAndReset(text: string, formatStyle: string) {
return formatStyle + text + resetEscapeSequence;
@@ -139,7 +141,7 @@ namespace ts {
output += `${ relativeFileName }(${ firstLine + 1 },${ firstLineChar + 1 }): `;
}
const categoryColor = categoryFormatMap[diagnostic.category];
const categoryColor = getCategoryFormat(diagnostic.category);
const category = DiagnosticCategory[diagnostic.category].toLowerCase();
output += `${ formatAndReset(category, categoryColor) } TS${ diagnostic.code }: ${ flattenDiagnosticMessageText(diagnostic.messageText, sys.newLine) }`;
output += sys.newLine + sys.newLine;
@@ -155,7 +157,7 @@ namespace ts {
output += `${ diagnostic.file.fileName }(${ loc.line + 1 },${ loc.character + 1 }): `;
}
output += `${ flattenDiagnosticMessageText(diagnostic.messageText, sys.newLine) }${ sys.newLine }`;
output += `${ flattenDiagnosticMessageText(diagnostic.messageText, sys.newLine) }${ sys.newLine + sys.newLine + sys.newLine }`;
sys.write(output);
}
@@ -378,9 +380,11 @@ namespace ts {
}
function cachedFileExists(fileName: string): boolean {
return fileName in cachedExistingFiles
? cachedExistingFiles[fileName]
: cachedExistingFiles[fileName] = hostFileExists(fileName);
let fileExists = cachedExistingFiles.get(fileName);
if (fileExists === undefined) {
cachedExistingFiles.set(fileName, fileExists = hostFileExists(fileName));
}
return fileExists;
}
function getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void) {
@@ -674,13 +678,9 @@ namespace ts {
if (option.name === "lib") {
description = getDiagnosticText(option.description);
const options: string[] = [];
const element = (<CommandLineOptionOfListType>option).element;
const typeMap = <Map<number | string>>element.type;
for (const key in typeMap) {
options.push(`'${key}'`);
}
optionsDescriptionMap[description] = options;
optionsDescriptionMap.set(description, arrayFrom(typeMap.keys()).map(key => `'${key}'`));
}
else {
description = getDiagnosticText(option.description);
@@ -702,7 +702,7 @@ namespace ts {
for (let i = 0; i < usageColumn.length; i++) {
const usage = usageColumn[i];
const description = descriptionColumn[i];
const kindsList = optionsDescriptionMap[description];
const kindsList = optionsDescriptionMap.get(description);
output.push(usage + makePadding(marginLength - usage.length + 2) + description + sys.newLine);
if (kindsList) {
+1 -2
View File
@@ -3,8 +3,7 @@
"compilerOptions": {
"removeComments": true,
"outFile": "../../built/local/tsc.js",
"declaration": true,
"types": [ ]
"declaration": true
},
"files": [
"core.ts",
+32 -6
View File
@@ -1,11 +1,30 @@
namespace ts {
namespace ts {
/**
* Type of objects whose values are all of the same type.
* The `in` and `for-in` operators can *not* be safely used,
* since `Object.prototype` may be modified by outside code.
*/
export interface MapLike<T> {
[index: string]: T;
}
export interface Map<T> extends MapLike<T> {
__mapBrand: any;
/** ES6 Map interface. */
export interface Map<T> {
get(key: string): T;
has(key: string): boolean;
set(key: string, value: T): this;
delete(key: string): boolean;
clear(): void;
forEach(action: (value: T, key: string) => void): void;
readonly size: number;
keys(): Iterator<string>;
values(): Iterator<T>;
entries(): Iterator<[string, T]>;
}
/** ES6 Iterator type. */
export interface Iterator<T> {
next(): { value: T, done: false } | { value: never, done: true };
}
// branded string type used to store absolute, normalized and canonicalized paths
@@ -2341,6 +2360,11 @@ namespace ts {
getIndexTypeOfType(type: Type, kind: IndexKind): Type;
getBaseTypes(type: InterfaceType): ObjectType[];
getReturnTypeOfSignature(signature: Signature): Type;
/**
* Gets the type of a parameter at a given position in a signature.
* Returns `any` if the index is not valid.
*/
/* @internal */ getParameterType(signature: Signature, parameterIndex: number): Type;
getNonNullableType(type: Type): Type;
getSymbolsInScope(location: Node, meaning: SymbolFlags): Symbol[];
@@ -2370,6 +2394,8 @@ namespace ts {
isValidPropertyAccess(node: PropertyAccessExpression | QualifiedName, propertyName: string): boolean;
getAliasedSymbol(symbol: Symbol): Symbol;
getExportsOfModule(moduleSymbol: Symbol): Symbol[];
/** Unlike `getExportsOfModule`, this includes properties of an `export =` value. */
/* @internal */ getExportsAndPropertiesOfModule(moduleSymbol: Symbol): Symbol[];
getJsxElementAttributesType(elementNode: JsxOpeningLikeElement): Type;
getJsxIntrinsicTagNames(): Symbol[];
@@ -2847,7 +2873,7 @@ namespace ts {
// Enum types (TypeFlags.Enum)
export interface EnumType extends Type {
memberTypes: Map<EnumLiteralType>;
memberTypes: EnumLiteralType[];
}
// Enum types (TypeFlags.EnumLiteral)
@@ -3682,7 +3708,7 @@ namespace ts {
flags?: EmitFlags; // Flags that customize emit
commentRange?: TextRange; // The text range to use when emitting leading or trailing comments
sourceMapRange?: TextRange; // The text range to use when emitting leading or trailing source mappings
tokenSourceMapRanges?: Map<TextRange>; // The text range to use when emitting source mappings for tokens
tokenSourceMapRanges?: TextRange[]; // The text range to use when emitting source mappings for tokens
constantValue?: number; // The constant value of an expression
externalHelpersModuleName?: Identifier; // The local name for an imported helpers module
helpers?: EmitHelper[]; // Emit helpers for the node
+25 -28
View File
@@ -1,4 +1,4 @@
/// <reference path="sys.ts" />
/// <reference path="sys.ts" />
/* @internal */
namespace ts {
@@ -70,11 +70,11 @@ namespace ts {
}
export function hasResolvedModule(sourceFile: SourceFile, moduleNameText: string): boolean {
return !!(sourceFile && sourceFile.resolvedModules && sourceFile.resolvedModules[moduleNameText]);
return !!(sourceFile && sourceFile.resolvedModules && sourceFile.resolvedModules.get(moduleNameText));
}
export function getResolvedModule(sourceFile: SourceFile, moduleNameText: string): ResolvedModuleFull {
return hasResolvedModule(sourceFile, moduleNameText) ? sourceFile.resolvedModules[moduleNameText] : undefined;
return hasResolvedModule(sourceFile, moduleNameText) ? sourceFile.resolvedModules.get(moduleNameText) : undefined;
}
export function setResolvedModule(sourceFile: SourceFile, moduleNameText: string, resolvedModule: ResolvedModuleFull): void {
@@ -82,7 +82,7 @@ namespace ts {
sourceFile.resolvedModules = createMap<ResolvedModuleFull>();
}
sourceFile.resolvedModules[moduleNameText] = resolvedModule;
sourceFile.resolvedModules.set(moduleNameText, resolvedModule);
}
export function setResolvedTypeReferenceDirective(sourceFile: SourceFile, typeReferenceDirectiveName: string, resolvedTypeReferenceDirective: ResolvedTypeReferenceDirective): void {
@@ -90,7 +90,7 @@ namespace ts {
sourceFile.resolvedTypeReferenceDirectiveNames = createMap<ResolvedTypeReferenceDirective>();
}
sourceFile.resolvedTypeReferenceDirectiveNames[typeReferenceDirectiveName] = resolvedTypeReferenceDirective;
sourceFile.resolvedTypeReferenceDirectiveNames.set(typeReferenceDirectiveName, resolvedTypeReferenceDirective);
}
/* @internal */
@@ -112,7 +112,7 @@ namespace ts {
}
for (let i = 0; i < names.length; i++) {
const newResolution = newResolutions[i];
const oldResolution = oldResolutions && oldResolutions[names[i]];
const oldResolution = oldResolutions && oldResolutions.get(names[i]);
const changed =
oldResolution
? !newResolution || !comparer(oldResolution, newResolution)
@@ -2285,22 +2285,16 @@ namespace ts {
}
function reattachFileDiagnostics(newFile: SourceFile): void {
if (!hasProperty(fileDiagnostics, newFile.fileName)) {
return;
}
for (const diagnostic of fileDiagnostics[newFile.fileName]) {
diagnostic.file = newFile;
}
forEach(fileDiagnostics.get(newFile.fileName), diagnostic => diagnostic.file = newFile);
}
function add(diagnostic: Diagnostic): void {
let diagnostics: Diagnostic[];
if (diagnostic.file) {
diagnostics = fileDiagnostics[diagnostic.file.fileName];
diagnostics = fileDiagnostics.get(diagnostic.file.fileName);
if (!diagnostics) {
diagnostics = [];
fileDiagnostics[diagnostic.file.fileName] = diagnostics;
fileDiagnostics.set(diagnostic.file.fileName, diagnostics);
}
}
else {
@@ -2320,7 +2314,7 @@ namespace ts {
function getDiagnostics(fileName?: string): Diagnostic[] {
sortAndDeduplicate();
if (fileName) {
return fileDiagnostics[fileName] || [];
return fileDiagnostics.get(fileName) || [];
}
const allDiagnostics: Diagnostic[] = [];
@@ -2330,9 +2324,9 @@ namespace ts {
forEach(nonFileDiagnostics, pushDiagnostic);
for (const key in fileDiagnostics) {
forEach(fileDiagnostics[key], pushDiagnostic);
}
fileDiagnostics.forEach(diagnostics => {
forEach(diagnostics, pushDiagnostic);
});
return sortAndDeduplicateDiagnostics(allDiagnostics);
}
@@ -2345,9 +2339,9 @@ namespace ts {
diagnosticsModified = false;
nonFileDiagnostics = sortAndDeduplicateDiagnostics(nonFileDiagnostics);
for (const key in fileDiagnostics) {
fileDiagnostics[key] = sortAndDeduplicateDiagnostics(fileDiagnostics[key]);
}
fileDiagnostics.forEach((diagnostics, key) => {
fileDiagnostics.set(key, sortAndDeduplicateDiagnostics(diagnostics));
});
}
}
@@ -2357,7 +2351,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 = createMap({
const escapedCharsMap = createMapFromTemplate({
"\0": "\\0",
"\t": "\\t",
"\v": "\\v",
@@ -2383,7 +2377,7 @@ namespace ts {
}
function getReplacement(c: string) {
return escapedCharsMap[c] || get16BitUnicodeEscapeSequence(c.charCodeAt(0));
return escapedCharsMap.get(c) || get16BitUnicodeEscapeSequence(c.charCodeAt(0));
}
export function isIntrinsicJsxName(name: string) {
@@ -3383,18 +3377,21 @@ namespace ts {
return false;
}
const syntaxKindCache = createMap<string>();
const syntaxKindCache: string[] = [];
export function formatSyntaxKind(kind: SyntaxKind): string {
const syntaxKindEnum = (<any>ts).SyntaxKind;
if (syntaxKindEnum) {
if (syntaxKindCache[kind]) {
return syntaxKindCache[kind];
const cached = syntaxKindCache[kind];
if (cached !== undefined) {
return cached;
}
for (const name in syntaxKindEnum) {
if (syntaxKindEnum[name] === kind) {
return syntaxKindCache[kind] = kind.toString() + " (" + name + ")";
const result = `${kind} (${name})`;
syntaxKindCache[kind] = result;
return result;
}
}
}
+54 -52
View File
@@ -1,4 +1,4 @@
/// <reference path="checker.ts" />
/// <reference path="checker.ts" />
/// <reference path="factory.ts" />
/// <reference path="utilities.ts" />
@@ -46,54 +46,56 @@ namespace ts {
* supplant the existing `forEachChild` implementation if performance is not
* significantly impacted.
*/
const nodeEdgeTraversalMap = createMap<NodeTraversalPath>({
[SyntaxKind.QualifiedName]: [
{ name: "left", test: isEntityName },
{ name: "right", test: isIdentifier }
],
[SyntaxKind.Decorator]: [
{ name: "expression", test: isLeftHandSideExpression }
],
[SyntaxKind.TypeAssertionExpression]: [
{ name: "type", test: isTypeNode },
{ name: "expression", test: isUnaryExpression }
],
[SyntaxKind.AsExpression]: [
{ name: "expression", test: isExpression },
{ name: "type", test: isTypeNode }
],
[SyntaxKind.NonNullExpression]: [
{ name: "expression", test: isLeftHandSideExpression }
],
[SyntaxKind.EnumDeclaration]: [
{ name: "decorators", test: isDecorator },
{ name: "modifiers", test: isModifier },
{ name: "name", test: isIdentifier },
{ name: "members", test: isEnumMember }
],
[SyntaxKind.ModuleDeclaration]: [
{ name: "decorators", test: isDecorator },
{ name: "modifiers", test: isModifier },
{ name: "name", test: isModuleName },
{ name: "body", test: isModuleBody }
],
[SyntaxKind.ModuleBlock]: [
{ name: "statements", test: isStatement }
],
[SyntaxKind.ImportEqualsDeclaration]: [
{ name: "decorators", test: isDecorator },
{ name: "modifiers", test: isModifier },
{ name: "name", test: isIdentifier },
{ name: "moduleReference", test: isModuleReference }
],
[SyntaxKind.ExternalModuleReference]: [
{ name: "expression", test: isExpression, optional: true }
],
[SyntaxKind.EnumMember]: [
{ name: "name", test: isPropertyName },
{ name: "initializer", test: isExpression, optional: true, parenthesize: parenthesizeExpressionForList }
]
});
function getNodeEdgeTraversal(kind: SyntaxKind): NodeTraversalPath {
switch (kind) {
case SyntaxKind.QualifiedName: return [
{ name: "left", test: isEntityName },
{ name: "right", test: isIdentifier }
];
case SyntaxKind.Decorator: return [
{ name: "expression", test: isLeftHandSideExpression }
];
case SyntaxKind.TypeAssertionExpression: return [
{ name: "type", test: isTypeNode },
{ name: "expression", test: isUnaryExpression }
];
case SyntaxKind.AsExpression: return [
{ name: "expression", test: isExpression },
{ name: "type", test: isTypeNode }
];
case SyntaxKind.NonNullExpression: return [
{ name: "expression", test: isLeftHandSideExpression }
];
case SyntaxKind.EnumDeclaration: return [
{ name: "decorators", test: isDecorator },
{ name: "modifiers", test: isModifier },
{ name: "name", test: isIdentifier },
{ name: "members", test: isEnumMember }
];
case SyntaxKind.ModuleDeclaration: return [
{ name: "decorators", test: isDecorator },
{ name: "modifiers", test: isModifier },
{ name: "name", test: isModuleName },
{ name: "body", test: isModuleBody }
];
case SyntaxKind.ModuleBlock: return [
{ name: "statements", test: isStatement }
];
case SyntaxKind.ImportEqualsDeclaration: return [
{ name: "decorators", test: isDecorator },
{ name: "modifiers", test: isModifier },
{ name: "name", test: isIdentifier },
{ name: "moduleReference", test: isModuleReference }
];
case SyntaxKind.ExternalModuleReference: return [
{ name: "expression", test: isExpression, optional: true }
];
case SyntaxKind.EnumMember: return [
{ name: "name", test: isPropertyName },
{ name: "initializer", test: isExpression, optional: true, parenthesize: parenthesizeExpressionForList }
];
}
}
function reduceNode<T>(node: Node, f: (memo: T, node: Node) => T, initial: T) {
return node ? f(initial, node) : initial;
@@ -530,7 +532,7 @@ namespace ts {
break;
default:
const edgeTraversalPath = nodeEdgeTraversalMap[kind];
const edgeTraversalPath = getNodeEdgeTraversal(kind);
if (edgeTraversalPath) {
for (const edge of edgeTraversalPath) {
const value = (<MapLike<any>>node)[edge.name];
@@ -1188,10 +1190,10 @@ namespace ts {
default:
let updated: Node & MapLike<any>;
const edgeTraversalPath = nodeEdgeTraversalMap[kind];
const edgeTraversalPath = getNodeEdgeTraversal(kind);
if (edgeTraversalPath) {
for (const edge of edgeTraversalPath) {
const value = <Node | NodeArray<Node>>(<Node & Map<any>>node)[edge.name];
const value = <Node | NodeArray<Node>>(<Node & MapLike<any>>node)[edge.name];
if (value !== undefined) {
const visited = isArray(value)
? visitNodes(value, visitor, edge.test, 0, value.length, edge.parenthesize, node)