From bcc0807198ca89a80878e50bb9fd9258c6970d07 Mon Sep 17 00:00:00 2001 From: Andy Hanson Date: Thu, 27 Oct 2016 13:14:56 -0700 Subject: [PATCH] Respond to PR comments --- scripts/processDiagnosticMessages.ts | 2 +- src/compiler/binder.ts | 20 +++--- src/compiler/checker.ts | 72 +++++++++---------- src/compiler/collections.ts | 71 ++++++++++-------- src/compiler/commandLineParser.ts | 12 ++-- src/compiler/core.ts | 2 +- src/compiler/declarationEmitter.ts | 2 +- src/compiler/emitter.ts | 2 +- src/compiler/factory.ts | 6 +- src/compiler/parser.ts | 2 +- src/compiler/performance.ts | 6 +- src/compiler/program.ts | 14 ++-- src/compiler/sys.ts | 4 +- src/compiler/transformer.ts | 2 +- src/compiler/transformers/es2015.ts | 8 +-- src/compiler/transformers/generators.ts | 6 +- src/compiler/transformers/module/module.ts | 8 +-- src/compiler/transformers/module/system.ts | 12 ++-- src/compiler/transformers/ts.ts | 6 +- src/compiler/tsc.ts | 6 +- src/compiler/types.ts | 4 +- src/compiler/utilities.ts | 14 ++-- src/compiler/visitor.ts | 2 +- src/harness/fourslash.ts | 6 +- src/harness/harness.ts | 6 +- src/harness/loggedIO.ts | 2 +- .../unittests/cachingInServerLSHost.ts | 2 +- src/harness/unittests/moduleResolution.ts | 2 +- src/harness/unittests/session.ts | 4 +- .../unittests/tsserverProjectSystem.ts | 6 +- src/harness/unittests/typingsInstaller.ts | 2 +- src/server/builder.ts | 2 +- src/server/client.ts | 2 +- src/server/editorServices.ts | 10 +-- src/server/lsHost.ts | 2 +- src/server/project.ts | 4 +- src/server/typingsCache.ts | 4 +- .../typingsInstaller/typingsInstaller.ts | 10 +-- src/server/utilities.ts | 2 +- src/services/codefixes/codeFixProvider.ts | 2 +- src/services/completions.ts | 10 +-- src/services/documentHighlights.ts | 2 +- src/services/documentRegistry.ts | 2 +- src/services/findAllReferences.ts | 6 +- src/services/jsTyping.ts | 4 +- src/services/navigationBar.ts | 12 ++-- src/services/patternMatcher.ts | 2 +- src/services/services.ts | 4 +- 48 files changed, 203 insertions(+), 190 deletions(-) diff --git a/scripts/processDiagnosticMessages.ts b/scripts/processDiagnosticMessages.ts index d6133e6dab0a5..a7e2f24fdb885 100644 --- a/scripts/processDiagnosticMessages.ts +++ b/scripts/processDiagnosticMessages.ts @@ -69,7 +69,7 @@ function checkForUniqueCodes(messages: string[], diagnosticTable: InputDiagnosti } function buildUniqueNameMap(names: string[]): ts.Map { - var nameMap = new ts.StringMap(); + var nameMap = ts.createMap(); var uniqueNames = NameGenerator.ensureUniqueness(names, /* isCaseSensitive */ false, /* isFixed */ undefined); diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index e3c460ad2ad6f..9bf8d4846ce12 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -147,7 +147,7 @@ namespace ts { options = opts; languageVersion = getEmitScriptTarget(options); inStrictMode = bindInStrictMode(file, opts); - classifiableNames = new StringSet(); + classifiableNames = createSet(); symbolCount = 0; skipTransformFlagAggregation = isDeclarationFile(file); @@ -207,11 +207,11 @@ namespace ts { symbol.declarations.push(node); if (symbolFlags & SymbolFlags.HasExports && !symbol.exports) { - symbol.exports = new StringMap(); + symbol.exports = createMap(); } if (symbolFlags & SymbolFlags.HasMembers && !symbol.members) { - symbol.members = new StringMap(); + symbol.members = createMap(); } if (symbolFlags & SymbolFlags.Value) { @@ -484,7 +484,7 @@ namespace ts { if (containerFlags & ContainerFlags.IsContainer) { container = blockScopeContainer = node; if (containerFlags & ContainerFlags.HasLocals) { - container.locals = new StringMap(); + container.locals = createMap(); } addToContainerChain(container); } @@ -1525,7 +1525,7 @@ namespace ts { const typeLiteralSymbol = createSymbol(SymbolFlags.TypeLiteral, "__type"); addDeclarationToSymbol(typeLiteralSymbol, node, SymbolFlags.TypeLiteral); - typeLiteralSymbol.members = new StringMap([[symbol.name, symbol]]); + typeLiteralSymbol.members = createMap([[symbol.name, symbol]]); } function bindObjectLiteralExpression(node: ObjectLiteralExpression) { @@ -1535,7 +1535,7 @@ namespace ts { } if (inStrictMode) { - const seen = new StringMap(); + const seen = createMap(); for (const prop of node.properties) { if (prop.name.kind !== SyntaxKind.Identifier) { @@ -1591,7 +1591,7 @@ namespace ts { // fall through. default: if (!blockScopeContainer.locals) { - blockScopeContainer.locals = new StringMap(); + blockScopeContainer.locals = createMap(); addToContainerChain(blockScopeContainer); } declareSymbol(blockScopeContainer.locals, undefined, node, symbolFlags, symbolExcludes); @@ -2071,7 +2071,7 @@ namespace ts { } } - file.symbol.globalExports = file.symbol.globalExports || new StringMap(); + file.symbol.globalExports = file.symbol.globalExports || createMap(); declareSymbol(file.symbol.globalExports, file.symbol, node, SymbolFlags.Alias, SymbolFlags.AliasExcludes); } @@ -2118,7 +2118,7 @@ namespace ts { 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 || new StringMap(); + container.symbol.members = container.symbol.members || createMap(); // 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); } @@ -2157,7 +2157,7 @@ namespace ts { // Set up the members collection if it doesn't exist already if (!funcSymbol.members) { - funcSymbol.members = new StringMap(); + funcSymbol.members = createMap(); } // Declare the method/property diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index fbb155a1d5a6b..281190d325653 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -47,7 +47,7 @@ namespace ts { let symbolCount = 0; const emptyArray: any[] = []; - const emptySymbols = new StringMap(); + const emptySymbols = createMap(); const compilerOptions = host.getCompilerOptions(); const languageVersion = compilerOptions.target || ScriptTarget.ES3; @@ -111,10 +111,10 @@ namespace ts { }; const tupleTypes: GenericType[] = []; - const unionTypes = new StringMap(); - const intersectionTypes = new StringMap(); - const stringLiteralTypes = new StringMap(); - const numericLiteralTypes = new StringMap(); + const unionTypes = createMap(); + const intersectionTypes = createMap(); + const stringLiteralTypes = createMap(); + const numericLiteralTypes = createMap(); const evolvingArrayTypes: EvolvingArrayType[] = []; const unknownSymbol = createSymbol(SymbolFlags.Property | SymbolFlags.Transient, "unknown"); @@ -139,7 +139,7 @@ namespace ts { const emptyObjectType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); const emptyGenericType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); - emptyGenericType.instantiations = new StringMap(); + emptyGenericType.instantiations = createMap(); const anyFunctionType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); // The anyFunctionType contains the anyFunctionType by definition. The flag is further propagated @@ -155,7 +155,7 @@ namespace ts { const enumNumberIndexInfo = createIndexInfo(stringType, /*isReadonly*/ true); - const globals = new StringMap(); + const globals = createMap(); /** * List of every ambient module with a "*" wildcard. * Unlike other ambient modules, these can't be stored in `globals` because symbol tables only deal with exact matches. @@ -325,7 +325,7 @@ namespace ts { let jsxElementType: Type; /** Things we lazy load from the JSX namespace */ - const jsxTypes = new StringMap(); + const jsxTypes = createMap(); const JsxNames = { JSX: "JSX", IntrinsicElements: "IntrinsicElements", @@ -336,11 +336,11 @@ namespace ts { IntrinsicClassAttributes: "IntrinsicClassAttributes" }; - const subtypeRelation = new StringMap(); - const assignableRelation = new StringMap(); - const comparableRelation = new StringMap(); - const identityRelation = new StringMap(); - const enumRelation = new StringMap(); + const subtypeRelation = createMap(); + const assignableRelation = createMap(); + const comparableRelation = createMap(); + const identityRelation = createMap(); + const enumRelation = createMap(); // This is for caching the result of getSymbolDisplayBuilder. Do not access directly. let _displayBuilder: SymbolDisplayBuilder; @@ -354,7 +354,7 @@ namespace ts { ResolvedReturnType } - const builtinGlobals = new StringMap([[undefinedSymbol.name, undefinedSymbol]]); + const builtinGlobals = createMap([[undefinedSymbol.name, undefinedSymbol]]); initializeTypeChecker(); @@ -437,11 +437,11 @@ namespace ts { target.declarations.push(node); }); if (source.members) { - if (!target.members) target.members = new StringMap(); + if (!target.members) target.members = createMap(); mergeSymbolTable(target.members, source.members); } if (source.exports) { - if (!target.exports) target.exports = new StringMap(); + if (!target.exports) target.exports = createMap(); mergeSymbolTable(target.exports, source.exports); } recordMergedSymbol(target, source); @@ -1418,7 +1418,7 @@ namespace ts { // This provides a name to the module. See the test tests/cases/fourslash/untypedModuleImport.ts const newSymbol = createSymbol(SymbolFlags.ValueModule, quotedName); // Module symbols are expected to have 'exports', although since this is an untyped module it can be empty. - newSymbol.exports = new StringMap(); + newSymbol.exports = createMap(); // Cache it so subsequent accesses will return the same module. globals.set(quotedName, newSymbol); return newSymbol; @@ -1531,8 +1531,8 @@ namespace ts { // All export * declarations are collected in an __export symbol by the binder const exportStars = symbol.exports.get("__export"); if (exportStars) { - const nestedSymbols = new StringMap(); - const lookupTable = new StringMap(); + const nestedSymbols = createMap(); + const lookupTable = createMap(); for (const node of exportStars.declarations) { const resolvedModule = resolveExternalModuleName(node, (node as ExportDeclaration).moduleSpecifier); const exportedSymbols = visit(resolvedModule); @@ -3237,7 +3237,7 @@ namespace ts { // Return the type implied by an object binding pattern function getTypeFromObjectBindingPattern(pattern: ObjectBindingPattern, includePatternInType: boolean, reportErrors: boolean): Type { - const members = new StringMap(); + const members = createMap(); let hasComputedProperties = false; forEach(pattern.elements, e => { const name = e.propertyName || e.name; @@ -3842,7 +3842,7 @@ namespace ts { type.typeParameters = concatenate(outerTypeParameters, localTypeParameters); type.outerTypeParameters = outerTypeParameters; type.localTypeParameters = localTypeParameters; - (type).instantiations = new StringMap([[getTypeListId(type.typeParameters), type]]); + (type).instantiations = createMap([[getTypeListId(type.typeParameters), type]]); (type).target = type; (type).typeArguments = type.typeParameters; type.thisType = createType(TypeFlags.TypeParameter); @@ -3884,7 +3884,7 @@ namespace ts { if (typeParameters) { // Initialize the instantiation cache for generic type aliases. The declared type corresponds to // an instantiation of the type alias with the type parameters supplied as type arguments. - links.instantiations = new StringMap([[getTypeListId(links.typeParameters), type]]); + links.instantiations = createMap([[getTypeListId(links.typeParameters), type]]); } } else { @@ -4572,7 +4572,7 @@ namespace ts { // these partial properties when identifying discriminant properties, but otherwise they are filtered out // and do not appear to be present in the union type. function getUnionOrIntersectionProperty(type: UnionOrIntersectionType, name: string): Symbol { - const properties = type.resolvedProperties || (type.resolvedProperties = new StringMap()); + const properties = type.resolvedProperties || (type.resolvedProperties = createMap()); let property = properties.get(name); if (!property) { property = createUnionOrIntersectionProperty(type, name); @@ -5393,7 +5393,7 @@ namespace ts { type.typeParameters = typeParameters; type.outerTypeParameters = undefined; type.localTypeParameters = typeParameters; - type.instantiations = new StringMap([[getTypeListId(type.typeParameters), type]]); + type.instantiations = createMap([[getTypeListId(type.typeParameters), type]]); type.target = type; type.typeArguments = type.typeParameters; type.thisType = createType(TypeFlags.TypeParameter); @@ -6906,7 +6906,7 @@ namespace ts { } sourceStack[depth] = source; targetStack[depth] = target; - maybeStack[depth] = new StringMap([[id, RelationComparisonResult.Succeeded]]); + maybeStack[depth] = createMap([[id, RelationComparisonResult.Succeeded]]); depth++; const saveExpandingFlags = expandingFlags; if (!(expandingFlags & 1) && isDeeplyNestedGeneric(source, sourceStack, depth)) expandingFlags |= 1; @@ -7591,7 +7591,7 @@ namespace ts { } function transformTypeOfMembers(type: Type, f: (propertyType: Type) => Type) { - const members = new StringMap(); + const members = createMap(); for (const property of getPropertiesOfObjectType(type)) { const original = getTypeOfSymbol(property); const updated = f(original); @@ -7814,7 +7814,7 @@ namespace ts { let targetStack: Type[]; let depth = 0; let inferiority = 0; - const visited = new StringSet(); + const visited = createSet(); inferFromTypes(originalSource, originalTarget); function isInProcess(source: Type, target: Type) { @@ -8894,7 +8894,7 @@ namespace ts { // If we have previously computed the control flow type for the reference at // this flow loop junction, return the cached type. const id = getFlowNodeId(flow); - const cache = flowLoopCaches[id] || (flowLoopCaches[id] = new StringMap()); + const cache = flowLoopCaches[id] || (flowLoopCaches[id] = createMap()); if (!key) { key = getFlowCacheKey(reference); } @@ -10594,7 +10594,7 @@ namespace ts { // Grammar checking checkGrammarObjectLiteralExpression(node, inDestructuringPattern); - const propertiesTable = new StringMap(); + const propertiesTable = createMap(); const propertiesArray: Symbol[] = []; const contextualType = getApparentTypeOfContextualType(node); const contextualTypeHasPattern = contextualType && contextualType.pattern && @@ -11145,7 +11145,7 @@ namespace ts { const targetAttributesType = getJsxElementAttributesType(node); - const nameTable = new StringSet(); + const nameTable = createSet(); // Process this array in right-to-left order so we know which // attributes (mostly from spreads) are being overwritten and // thus should have their types ignored @@ -14622,8 +14622,8 @@ namespace ts { Property = Getter | Setter } - const instanceNames = new StringMap(); - const staticNames = new StringMap(); + const instanceNames = createMap(); + const staticNames = createMap(); for (const member of node.members) { if (member.kind === SyntaxKind.Constructor) { for (const param of (member as ConstructorDeclaration).parameters) { @@ -14672,7 +14672,7 @@ namespace ts { } function checkObjectTypeForDuplicateDeclarations(node: TypeLiteralNode | InterfaceDeclaration) { - const names = new StringSet(); + const names = createSet(); for (const member of node.members) { if (member.kind == SyntaxKind.PropertySignature) { let memberName: string; @@ -18490,7 +18490,7 @@ namespace ts { } function getSymbolsInScope(location: Node, meaning: SymbolFlags): Symbol[] { - const symbols = new StringMap(); + const symbols = createMap(); let memberFlags: ModifierFlags = ModifierFlags.None; if (isInsideWithStatementBody(location)) { @@ -20315,7 +20315,7 @@ namespace ts { } function checkGrammarObjectLiteralExpression(node: ObjectLiteralExpression, inDestructuring: boolean) { - const seen = new StringMap(); + const seen = createMap(); const Property = 1; const GetAccessor = 2; const SetAccessor = 4; @@ -20402,7 +20402,7 @@ namespace ts { } function checkGrammarJsxElement(node: JsxOpeningLikeElement) { - const seen = new StringSet(); + const seen = createSet(); for (const attr of node.attributes) { if (attr.kind === SyntaxKind.JsxSpreadAttribute) { continue; diff --git a/src/compiler/collections.ts b/src/compiler/collections.ts index 5aa4c010875d8..01f3da2b9d342 100644 --- a/src/compiler/collections.ts +++ b/src/compiler/collections.ts @@ -2,10 +2,11 @@ /* @internal */ namespace ts { // The global Map object. This may not be available, so we must test for it. - declare const Map: { new(pairs?: [K, V][]): Map } | undefined; + // Non-ES6 native maps don't support constructor arguments, so `createMap` must provide that functionality. + declare const Map: { new(): Map } | undefined; const usingNativeMaps = typeof Map !== "undefined"; // tslint:disable-next-line:no-in-operator - const fullyFeaturedMaps = usingNativeMaps && "keys" in Map.prototype && "values" in Map.prototype && "entries" in Map.prototype; + const usingES6NativeMaps = usingNativeMaps && "keys" in Map.prototype && "values" in Map.prototype && "entries" in Map.prototype; /** Extra Map methods that may not be available, so we must provide fallbacks. */ interface ES6Map extends Map { @@ -32,20 +33,18 @@ namespace ts { However, `forEach` will iterate over strings because values are stringified before being put in the map. */ - constructor(pairs?: [K, V][]) { - if (pairs) { - for (const [key, value] of pairs) { - this.data[key as string] = value; - } - } - } + constructor() {} clear(): void { this.data = createDictionaryModeObject(); } - delete(key: K): void { - delete this.data[key as string]; + delete(key: K): boolean { + const had = this.has(key); + if (had) { + delete this.data[key as string]; + } + return had; } get(key: K): V { @@ -68,14 +67,22 @@ namespace ts { } } + const MapCtr = usingNativeMaps ? Map : ShimMap; /** * In runtimes without Maps, this is implemented using an object. * `pairs` is an optional list of entries to add to the new map. */ - export const StringMap: { new(pairs?: [string, T][]): Map; } = usingNativeMaps ? Map : ShimMap; + export function createMap(pairs?: [K, V][]): Map { + const map = new MapCtr(); + + if (pairs) { + for (const [key, value] of pairs) { + map.set(key, value); + } + } - /** This is generic over the key type because it is usually an enum. */ - export const NumberMap: { new(pairs?: [K, V][]): Map } = usingNativeMaps ? Map : ShimMap; + return map; + } const createObject = Object.create; function createDictionaryModeObject(): MapLike { @@ -94,7 +101,7 @@ namespace ts { * Iterates over entries in the map, returning the first output of `getResult` that is not `undefined`. * Only works for strings because shims iterate with `for-in`. */ - export const findInMap: (map: Map, getResult: (value: V, key: string) => U | undefined) => U | undefined = fullyFeaturedMaps + export const findInMap: (map: Map, getResult: (value: V, key: string) => U | undefined) => U | undefined = usingES6NativeMaps ? (map: ES6Map, f: (value: V, key: string) => U | undefined) => { const iter = map.entries(); while (true) { @@ -122,7 +129,7 @@ namespace ts { * Whether `predicate` is true for at least one entry in the map. * Only works for strings because shims iterate with `for-in`. */ - export const someInMap: (map: Map, predicate: (value: V, key: string) => boolean) => boolean = fullyFeaturedMaps + export const someInMap: (map: Map, predicate: (value: V, key: string) => boolean) => boolean = usingES6NativeMaps ? (map: ES6Map, predicate: (value: V, key: string) => boolean) => someInIterator(map.entries(), ([key, value]) => predicate(value, key)) : (map: Map, predicate: (value: V, key: string) => boolean) => { @@ -137,13 +144,13 @@ namespace ts { * Whether `predicate` is true for at least one key in the map. * Only works for strings because shims iterate with `for-in`. */ - export const someKeyInMap: (map: Map, predicate: (key: string) => boolean) => boolean = fullyFeaturedMaps + export const someKeyInMap: (map: Map, predicate: (key: string) => boolean) => boolean = usingES6NativeMaps ? (map: ES6Map, predicate: (key: string) => boolean) => someInIterator(map.keys(), predicate) : (map: Map, predicate: (key: string) => boolean) => someInMap(map, (_value, key) => predicate(key)); /** Whether `predicate` is true for at least one value in the map. */ - export const someValueInMap: (map: Map, predicate: (value: T) => boolean) => boolean = fullyFeaturedMaps + export const someValueInMap: (map: Map, predicate: (value: T) => boolean) => boolean = usingES6NativeMaps ? (map: ES6Map, predicate: (value: T) => boolean) => someInIterator(map.values(), predicate) : someInMap; @@ -165,7 +172,7 @@ namespace ts { * `for (const key of map.keys()) action(key);` * Only works for strings because shims iterate with `for-in`. */ - export const forEachKeyInMap: (map: Map, action: (key: string) => void) => void = fullyFeaturedMaps + export const forEachKeyInMap: (map: Map, action: (key: string) => void) => void = usingES6NativeMaps ? (map: ES6Map, action: (key: string) => void) => { const iter: Iterator = map.keys(); while (true) { @@ -200,7 +207,7 @@ namespace ts { /** Create a map from a MapLike. This is useful for writing large maps as object literals. */ export function mapOfMapLike(object: MapLike): Map { - const map = new StringMap(); + const map = createMap(); // 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 object) if (hasProperty(object, key)) { @@ -222,8 +229,12 @@ namespace ts { this.data = createDictionaryModeObject(); } - delete(value: string) { - delete this.data[value]; + delete(value: string): boolean { + const had = this.has(value); + if (had) { + delete this.data[value]; + } + return had; } forEach(action: (value: string) => void) { @@ -250,8 +261,10 @@ namespace ts { declare const Set: { new(): Set } | undefined; const usingNativeSets = typeof Set !== "undefined"; - /** In runtimes without Sets, this is implemented using an object. */ - export const StringSet: { new(): Set } = usingNativeSets ? Set : ShimStringSet; + const SetCtr = usingNativeSets ? Set : ShimStringSet; + export function createSet(): Set { + return new SetCtr(); + } /** False if there are any values in the set. */ export const setIsEmpty: (set: Set) => boolean = usingNativeSets @@ -273,7 +286,7 @@ namespace ts { /** Create a new copy of a Map. */ export function cloneMap(map: Map) { - const clone = new StringMap(); + const clone = createMap(); copyMapEntriesFromTo(map, clone); return clone; } @@ -309,7 +322,7 @@ namespace ts { /** Return a new map with each key transformed by `getNewKey`. */ export function transformKeys(map: Map, getNewKey: (key: string) => string): Map { - const newMap = new StringMap(); + const newMap = createMap(); map.forEach((value, key) => { newMap.set(getNewKey(key), value); }); @@ -382,7 +395,7 @@ namespace ts { export function arrayToMap(array: T[], makeKey: (value: T) => string): Map; export function arrayToMap(array: T[], makeKey: (value: T) => string, makeValue: (value: T) => U): Map; export function arrayToMap(array: T[], makeKey: (value: T) => string, makeValue?: (value: T) => U): Map { - const result = new StringMap(); + const result = createMap(); for (const value of array) { result.set(makeKey(value), makeValue ? makeValue(value) : value); } @@ -437,7 +450,7 @@ namespace ts { * Creates a sorted array of keys. * Sorts keys according to the iteration order they would have if they were in an object, instead of from a Map. * This is so that tests run consistently whether or not we have a Map shim in place. - * The difference between Map iteration order and V8 object insertion order is that V8 moves natrual-number-like keys to the front. + * The difference between Map iteration order and V8 object insertion order is that V8 moves natural-number-like keys to the front. */ export function sortInV8ObjectInsertionOrder(values: T[], toKey: (t: T) => string): T[] { const naturalNumberKeys: T[] = []; @@ -458,7 +471,7 @@ namespace ts { /** Union of the `getSet` of each element in the array. */ export function setAggregate(array: T[], getSet: (t: T) => Set): Set { - const result = new StringSet(); + const result = createSet(); for (const value of array) { copySetValuesFromTo(getSet(value), result); } diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 691d9f60c9418..87337cb1e2e5c 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -500,8 +500,8 @@ namespace ts { return optionNameMapCache; } - const optionNameMap = new StringMap(); - const shortOptionNames = new StringMap(); + const optionNameMap = createMap(); + const shortOptionNames = createMap(); forEach(optionDeclarations, option => { optionNameMap.set(option.name.toLowerCase(), option); if (option.shortName) { @@ -741,7 +741,7 @@ namespace ts { } function serializeCompilerOptions(options: CompilerOptions): MapLike { - const result = new StringMap(); + const result = createMap(); const optionsNameMap = getOptionNameMap().optionNameMap; for (const name in options) { @@ -1172,12 +1172,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 = new StringMap(); + const literalFileMap = createMap(); // 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 = new StringMap(); + const wildcardFileMap = createMap(); if (include) { include = validateSpecs(include, errors, /*allowTrailingRecursion*/ false); @@ -1276,7 +1276,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 = new StringMap(); + const wildcardDirectories = createMap(); if (include !== undefined) { const recursiveKeys: string[] = []; for (const file of include) { diff --git a/src/compiler/core.ts b/src/compiler/core.ts index 3784a3d0fc712..208b4d0931a82 100644 --- a/src/compiler/core.ts +++ b/src/compiler/core.ts @@ -23,7 +23,7 @@ namespace ts { export const collator: { compare(a: string, b: string): number } = typeof Intl === "object" && typeof Intl.Collator === "function" ? new Intl.Collator() : undefined; export function createFileMap(keyMapper?: (key: string) => string): FileMap { - const files = new StringMap(); + const files = createMap(); return { get, set, diff --git a/src/compiler/declarationEmitter.ts b/src/compiler/declarationEmitter.ts index 63d5864b5b229..0c3b2abf3f04d 100644 --- a/src/compiler/declarationEmitter.ts +++ b/src/compiler/declarationEmitter.ts @@ -267,7 +267,7 @@ namespace ts { } if (!usedTypeDirectiveReferences) { - usedTypeDirectiveReferences = new StringSet(); + usedTypeDirectiveReferences = createSet(); } for (const directive of typeReferenceDirectives) { if (!usedTypeDirectiveReferences.has(directive)) { diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index be9cb8914288f..d0568293eb7a5 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -292,7 +292,7 @@ const _super = (function (geti, seti) { sourceMap.initialize(jsFilePath, sourceMapFilePath, sourceFiles, isBundledEmit); nodeIdToGeneratedName = []; autoGeneratedIdToGeneratedName = []; - generatedNameSet = new StringSet(); + generatedNameSet = createSet(); isOwnFileEmit = !isBundledEmit; // Emit helpers from all the files diff --git a/src/compiler/factory.ts b/src/compiler/factory.ts index d121755013a77..13f1230896e84 100644 --- a/src/compiler/factory.ts +++ b/src/compiler/factory.ts @@ -1622,7 +1622,7 @@ namespace ts { // flag and setting a parent node. const react = createIdentifier(reactNamespace || "React"); react.flags &= ~NodeFlags.Synthesized; - // Set the parent that is in parse tree + // Set the parent that is in parse tree // this makes sure that parent chain is intact for checker to traverse complete scope tree react.parent = getParseTreeNode(parent); return react; @@ -2806,7 +2806,7 @@ namespace ts { } function mergeTokenSourceMapRanges(sourceRanges: Map, destRanges: Map): Map { - if (!destRanges) destRanges = new NumberMap(); + if (!destRanges) destRanges = createMap(); copyMapEntriesFromTo(sourceRanges, destRanges); return destRanges; } @@ -2899,7 +2899,7 @@ namespace ts { */ export function setTokenSourceMapRange(node: T, token: SyntaxKind, range: TextRange) { const emitNode = getOrCreateEmitNode(node); - const tokenSourceMapRanges = emitNode.tokenSourceMapRanges || (emitNode.tokenSourceMapRanges = new NumberMap()); + const tokenSourceMapRanges = emitNode.tokenSourceMapRanges || (emitNode.tokenSourceMapRanges = createMap()); tokenSourceMapRanges.set(token, range); return node; } diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 6eab34e622c7f..ea33473fe40a6 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -601,7 +601,7 @@ namespace ts { parseDiagnostics = []; parsingContext = 0; - identifiers = new StringMap(); + identifiers = createMap(); identifierCount = 0; nodeCount = 0; diff --git a/src/compiler/performance.ts b/src/compiler/performance.ts index 9ac9b755570c7..6cb73e4d058c7 100644 --- a/src/compiler/performance.ts +++ b/src/compiler/performance.ts @@ -79,9 +79,9 @@ namespace ts.performance { /** Enables (and resets) performance measurements for the compiler. */ export function enable() { - counts = new StringMap(); - marks = new StringMap(); - measures = new StringMap(); + counts = createMap(); + marks = createMap(); + measures = createMap(); enabled = true; profilerStart = timestamp(); } diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 5d19f2a908c3b..8a2b4d86671bf 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -82,7 +82,7 @@ namespace ts { } export function createCompilerHost(options: CompilerOptions, setParentNodes?: boolean): CompilerHost { - const existingDirectories = new StringSet(); + const existingDirectories = createSet(); 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. @@ -136,7 +136,7 @@ namespace ts { function writeFileIfUpdated(fileName: string, data: string, writeByteOrderMark: boolean): void { if (!outputFingerprints) { - outputFingerprints = new StringMap(); + outputFingerprints = createMap(); } const hash = sys.createHash(data); @@ -279,7 +279,7 @@ namespace ts { return []; } const resolutions: T[] = []; - const cache = new StringMap(); + const cache = createMap(); for (const name of names) { const result = cache.has(name) ? cache.get(name) @@ -297,7 +297,7 @@ namespace ts { let noDiagnosticsTypeChecker: TypeChecker; let classifiableNames: Set; - let resolvedTypeReferenceDirectives = new StringMap(); + let resolvedTypeReferenceDirectives = createMap(); 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. @@ -312,10 +312,10 @@ 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 = new StringMap(); + const modulesWithElidedImports = createMap(); // Track source files that are source files found by searching under node_modules, as these shouldn't be compiled. - const sourceFilesFoundSearchingNodeModules = new StringMap(); + const sourceFilesFoundSearchingNodeModules = createMap(); performance.mark("beforeProgram"); @@ -1290,7 +1290,7 @@ namespace ts { function processImportedModules(file: SourceFile) { collectExternalModuleReferences(file); if (file.imports.length || file.moduleAugmentations.length) { - file.resolvedModules = new StringMap(); + file.resolvedModules = createMap(); const moduleNames = map(concatenate(file.imports, file.moduleAugmentations), getTextOfLiteral); const resolutions = resolveModuleNamesWorker(moduleNames, getNormalizedAbsolutePath(file.fileName, currentDirectory)); Debug.assert(resolutions.length === moduleNames.length); diff --git a/src/compiler/sys.ts b/src/compiler/sys.ts index a35692c48f8b3..5df1976f98e34 100644 --- a/src/compiler/sys.ts +++ b/src/compiler/sys.ts @@ -237,9 +237,9 @@ namespace ts { const useNonPollingWatchers = process.env["TSC_NONPOLLING_WATCHER"]; function createWatchedFileSet() { - const dirWatchers = new StringMap(); + const dirWatchers = createMap(); // One file can have multiple watchers - const fileWatcherCallbacks = new StringMap(); + const fileWatcherCallbacks = createMap(); return { addFile, removeFile }; function reduceDirWatcherRefCountForFile(fileName: string) { diff --git a/src/compiler/transformer.ts b/src/compiler/transformer.ts index cb501bdb6e40b..4534564a854a4 100644 --- a/src/compiler/transformer.ts +++ b/src/compiler/transformer.ts @@ -12,7 +12,7 @@ /* @internal */ namespace ts { - const moduleTransformerMap = new NumberMap([ + const moduleTransformerMap = createMap([ [ModuleKind.ES2015, transformES2015Module], [ModuleKind.System, transformSystemModule], [ModuleKind.AMD, transformModule], diff --git a/src/compiler/transformers/es2015.ts b/src/compiler/transformers/es2015.ts index 54c61819d7d96..4e0b0749d3a97 100644 --- a/src/compiler/transformers/es2015.ts +++ b/src/compiler/transformers/es2015.ts @@ -279,7 +279,7 @@ namespace ts { else if (node.transformFlags & TransformFlags.ContainsES2015 || (isInConstructorWithCapturedSuper && !isExpression(node))) { // we want to dive in this branch either if node has children with ES2015 specific syntax // or we are inside constructor that captures result of the super call so all returns without expression should be - // rewritten. Note: we skip expressions since returns should never appear there + // rewritten. Note: we skip expressions since returns should never appear there return visitEachChild(node, visitor, context); } else { @@ -1880,7 +1880,7 @@ namespace ts { function visitLabeledStatement(node: LabeledStatement): VisitResult { if (convertedLoopState) { if (!convertedLoopState.labels) { - convertedLoopState.labels = new StringMap(); + convertedLoopState.labels = createMap(); } convertedLoopState.labels.set(node.label.text, node.label.text); } @@ -2497,13 +2497,13 @@ namespace ts { function setLabeledJump(state: ConvertedLoopState, isBreak: boolean, labelText: string, labelMarker: string): void { if (isBreak) { if (!state.labeledNonLocalBreaks) { - state.labeledNonLocalBreaks = new StringMap(); + state.labeledNonLocalBreaks = createMap(); } state.labeledNonLocalBreaks.set(labelText, labelMarker); } else { if (!state.labeledNonLocalContinues) { - state.labeledNonLocalContinues = new StringMap(); + state.labeledNonLocalContinues = createMap(); } state.labeledNonLocalContinues.set(labelText, labelMarker); } diff --git a/src/compiler/transformers/generators.ts b/src/compiler/transformers/generators.ts index 37629bfc6a042..74bc4ef4f0a56 100644 --- a/src/compiler/transformers/generators.ts +++ b/src/compiler/transformers/generators.ts @@ -217,7 +217,7 @@ namespace ts { Endfinally = 7, } - const instructionNames = new NumberMap([ + const instructionNames = createMap([ [Instruction.Return, "return"], [Instruction.Break, "break"], [Instruction.Yield, "yield"], @@ -2078,8 +2078,8 @@ namespace ts { const name = declareLocal(text); if (!renamedCatchVariables) { - renamedCatchVariables = new StringSet(); - renamedCatchVariableDeclarations = new NumberMap(); + renamedCatchVariables = createSet(); + renamedCatchVariableDeclarations = createMap(); context.enableSubstitution(SyntaxKind.Identifier); } diff --git a/src/compiler/transformers/module/module.ts b/src/compiler/transformers/module/module.ts index d26958bb90220..11a2a3dccad96 100644 --- a/src/compiler/transformers/module/module.ts +++ b/src/compiler/transformers/module/module.ts @@ -10,7 +10,7 @@ namespace ts { importAliasNames: ParameterDeclaration[]; } - const transformModuleDelegates = new NumberMap SourceFile>([ + const transformModuleDelegates = createMap SourceFile>([ [ModuleKind.None, transformCommonJSModule], [ModuleKind.CommonJS, transformCommonJSModule], [ModuleKind.AMD, transformAMDModule], @@ -40,8 +40,8 @@ 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 = new NumberMap(); // The ExternalModuleInfo for each file. - const deferredExports = new NumberMap(); // Exports to defer until an EndOfDeclarationMarker is found. + const moduleInfoMap = createMap(); // The ExternalModuleInfo for each file. + const deferredExports = createMap(); // Exports to defer until an EndOfDeclarationMarker is found. let currentSourceFile: SourceFile; // The current file. let currentModuleInfo: ExternalModuleInfo; // The ExternalModuleInfo for the current file. @@ -1101,7 +1101,7 @@ namespace ts { if (node.kind === SyntaxKind.SourceFile) { currentSourceFile = node; currentModuleInfo = moduleInfoMap.get(getOriginalNodeId(currentSourceFile)); - noSubstitution = new NumberMap(); + noSubstitution = createMap(); previousOnEmitNode(emitContext, node, emitCallback); diff --git a/src/compiler/transformers/module/system.ts b/src/compiler/transformers/module/system.ts index ca3db346a23ba..f3db63287b238 100644 --- a/src/compiler/transformers/module/system.ts +++ b/src/compiler/transformers/module/system.ts @@ -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 = new NumberMap(); // The ExternalModuleInfo for each file. - const deferredExports = new NumberMap(); // Exports to defer until an EndOfDeclarationMarker is found. - const exportFunctionsMap = new NumberMap(); // The export function associated with a source file. - const noSubstitutionMap = new NumberMap>(); // Set of nodes for which substitution rules should be ignored for each file. + const moduleInfoMap = createMap(); // The ExternalModuleInfo for each file. + const deferredExports = createMap(); // Exports to defer until an EndOfDeclarationMarker is found. + const exportFunctionsMap = createMap(); // The export function associated with a source file. + const noSubstitutionMap = createMap>(); // 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. @@ -138,7 +138,7 @@ namespace ts { * @param externalImports The imports for the file. */ function collectDependencyGroups(externalImports: (ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration)[]) { - const groupIndices = new StringMap(); + const groupIndices = createMap(); const dependencyGroups: DependencyGroup[] = []; for (let i = 0; i < externalImports.length; i++) { const externalImport = externalImports[i]; @@ -1739,7 +1739,7 @@ namespace ts { * @param node The node which should not be substituted. */ function preventSubstitution(node: T): T { - if (noSubstitution === undefined) noSubstitution = new NumberMap(); + if (noSubstitution === undefined) noSubstitution = createMap(); noSubstitution.set(getNodeId(node), true); return node; } diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index 6d22dc12bc7f7..3e9a9855f7e7a 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -2245,7 +2245,7 @@ namespace ts { const savedCurrentScope = currentScope; const savedCurrentScopeFirstDeclarationsOfName = currentScopeFirstDeclarationsOfName; currentScope = body; - currentScopeFirstDeclarationsOfName = new StringMap(); + currentScopeFirstDeclarationsOfName = createMap(); startLexicalEnvironment(); const statements = visitNodes(body.statements, visitor, isStatement, start); @@ -2630,7 +2630,7 @@ namespace ts { const name = node.symbol && node.symbol.name; if (name) { if (!currentScopeFirstDeclarationsOfName) { - currentScopeFirstDeclarationsOfName = new StringMap(); + currentScopeFirstDeclarationsOfName = createMap(); } setIfNotSet(currentScopeFirstDeclarationsOfName, name, node); @@ -3218,7 +3218,7 @@ namespace ts { context.enableSubstitution(SyntaxKind.Identifier); // Keep track of class aliases. - classAliases = new NumberMap(); + classAliases = createMap(); } } diff --git a/src/compiler/tsc.ts b/src/compiler/tsc.ts index 5286c24d1f6b9..28b3b9f3068b9 100644 --- a/src/compiler/tsc.ts +++ b/src/compiler/tsc.ts @@ -127,7 +127,7 @@ namespace ts { const gutterSeparator = " "; const resetEscapeSequence = "\u001b[0m"; const ellipsis = "..."; - const categoryFormatMap = new NumberMap([ + const categoryFormatMap = createMap([ [DiagnosticCategory.Warning, yellowForegroundEscapeSequence], [DiagnosticCategory.Error, redForegroundEscapeSequence], [DiagnosticCategory.Message, blueForegroundEscapeSequence], @@ -425,7 +425,7 @@ namespace ts { } // reset the cache of existing files - cachedExistingFiles = new StringMap(); + cachedExistingFiles = createMap(); const compileResult = compile(rootFileNames, compilerOptions, compilerHost); @@ -706,7 +706,7 @@ namespace ts { const usageColumn: string[] = []; // Things like "-d, --declaration" go in here. const descriptionColumn: string[] = []; - const optionsDescriptionMap = new StringMap(); // Map between option.description and list of option.type if it is a kind + const optionsDescriptionMap = createMap(); // 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]; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index a14586daf65f7..12f46751f6414 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -17,7 +17,7 @@ namespace ts { */ export interface Map { clear(): void; - delete(key: K): void; + delete(key: K): boolean; /** * Call `action` for each entry in the map. * Since we use a `for-in` loop for our shims, `key` may be a string. @@ -38,7 +38,7 @@ namespace ts { export interface Set { add(value: T): void; clear(): void; - delete(value: T): void; + delete(value: T): boolean; forEach(action: (value: T) => void): void; has(value: T): boolean; } diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index d6bb132c2afb4..bd77d5b2138f3 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -93,7 +93,7 @@ namespace ts { export function setResolvedModule(sourceFile: SourceFile, moduleNameText: string, resolvedModule: ResolvedModuleFull): void { if (!sourceFile.resolvedModules) { - sourceFile.resolvedModules = new StringMap(); + sourceFile.resolvedModules = createMap(); } sourceFile.resolvedModules.set(moduleNameText, resolvedModule); @@ -101,7 +101,7 @@ namespace ts { export function setResolvedTypeReferenceDirective(sourceFile: SourceFile, typeReferenceDirectiveName: string, resolvedTypeReferenceDirective: ResolvedTypeReferenceDirective): void { if (!sourceFile.resolvedTypeReferenceDirectiveNames) { - sourceFile.resolvedTypeReferenceDirectiveNames = new StringMap(); + sourceFile.resolvedTypeReferenceDirectiveNames = createMap(); } sourceFile.resolvedTypeReferenceDirectiveNames.set(typeReferenceDirectiveName, resolvedTypeReferenceDirective); @@ -2201,7 +2201,7 @@ namespace ts { export function createDiagnosticCollection(): DiagnosticCollection { let nonFileDiagnostics: Diagnostic[] = []; - const fileDiagnostics = new StringMap(); + const fileDiagnostics = createMap(); let diagnosticsModified = false; let modificationCount = 0; @@ -3349,7 +3349,7 @@ namespace ts { return false; } - const syntaxKindCache = new NumberMap(); + const syntaxKindCache = createMap(); export function formatSyntaxKind(kind: SyntaxKind): string { const syntaxKindEnum = (ts).SyntaxKind; @@ -3507,9 +3507,9 @@ namespace ts { export function collectExternalModuleInfo(sourceFile: SourceFile, resolver: EmitResolver): ExternalModuleInfo { const externalImports: (ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration)[] = []; - const exportSpecifiers = new StringMap(); - const exportedBindings = new NumberMap(); - const uniqueExports = new StringMap(); + const exportSpecifiers = createMap(); + const exportedBindings = createMap(); + const uniqueExports = createMap(); let hasExportDefault = false; let exportEquals: ExportAssignment = undefined; let hasExportStarsToExportValues = false; diff --git a/src/compiler/visitor.ts b/src/compiler/visitor.ts index fabd5079bfc96..fb1c572f08241 100644 --- a/src/compiler/visitor.ts +++ b/src/compiler/visitor.ts @@ -46,7 +46,7 @@ namespace ts { * supplant the existing `forEachChild` implementation if performance is not * significantly impacted. */ - const nodeEdgeTraversalMap = new NumberMap([ + const nodeEdgeTraversalMap = createMap([ [SyntaxKind.QualifiedName, [ { name: "left", test: isEntityName }, { name: "right", test: isIdentifier } diff --git a/src/harness/fourslash.ts b/src/harness/fourslash.ts index 3b64092f2eae4..88181d5edd27b 100644 --- a/src/harness/fourslash.ts +++ b/src/harness/fourslash.ts @@ -189,7 +189,7 @@ namespace FourSlash { public formatCodeSettings: ts.FormatCodeSettings; - private inputFiles = new ts.StringMap(); // Map between inputFile's fileName and its content for easily looking up when resolving references + private inputFiles = ts.createMap(); // Map between inputFile's fileName and its content for easily looking up when resolving references private static getDisplayPartsJson(displayParts: ts.SymbolDisplayPart[]) { let result = ""; @@ -674,7 +674,7 @@ namespace FourSlash { public noItemsWithSameNameButDifferentKind(): void { const completions = this.getCompletionListAtCaret(); - const uniqueItems = new ts.StringMap(); + const uniqueItems = ts.createMap(); for (const item of completions.entries) { if (!ts.setIfNotSet(uniqueItems, item.name, item.kind)) { const uniqueItem = uniqueItems.get(item.name); @@ -1777,7 +1777,7 @@ namespace FourSlash { } private rangesByTextMap(): ts.Map { - const result = new ts.StringMap(); + const result = ts.createMap(); for (const range of this.getRanges()) { const text = this.rangeText(range); ts.multiMapAdd(result, text, range); diff --git a/src/harness/harness.ts b/src/harness/harness.ts index 8cdaa326cea75..a029dfc38014d 100644 --- a/src/harness/harness.ts +++ b/src/harness/harness.ts @@ -922,7 +922,7 @@ namespace Harness { export const defaultLibFileName = "lib.d.ts"; export const es2015DefaultLibFileName = "lib.es2015.d.ts"; - const libFileNameSourceFileMap = new ts.StringMap([[ + const libFileNameSourceFileMap = ts.createMap([[ defaultLibFileName, createSourceFileAndAssertInvariants(defaultLibFileName, IO.readFile(libFolder + "lib.es5.d.ts"), /*languageVersion*/ ts.ScriptTarget.Latest) ]]); @@ -1089,7 +1089,7 @@ namespace Harness { let optionsIndex: ts.Map; function getCommandLineOption(name: string): ts.CommandLineOption { if (!optionsIndex) { - optionsIndex = new ts.StringMap(); + optionsIndex = ts.createMap(); const optionDeclarations = harnessOptionDeclarations.concat(ts.optionDeclarations); for (const option of optionDeclarations) { optionsIndex.set(option.name.toLowerCase(), option); @@ -1452,7 +1452,7 @@ namespace Harness { const fullWalker = new TypeWriterWalker(program, /*fullTypeCheck*/ true); - const fullResults = new ts.StringMap(); + const fullResults = ts.createMap(); for (const sourceFile of allFiles) { fullResults.set(sourceFile.unitName, fullWalker.getTypeAndSymbols(sourceFile.unitName)); diff --git a/src/harness/loggedIO.ts b/src/harness/loggedIO.ts index 1b1c8130ba376..a4cd4d36b39da 100644 --- a/src/harness/loggedIO.ts +++ b/src/harness/loggedIO.ts @@ -91,7 +91,7 @@ namespace Playback { } function memoize(func: (s: string) => T): Memoized { - const lookup = new ts.StringMap(); + const lookup = ts.createMap(); const run: Memoized = >((s: string) => ts.getOrUpdateAndAllowUndefined(lookup, s, func)); run.reset = () => { diff --git a/src/harness/unittests/cachingInServerLSHost.ts b/src/harness/unittests/cachingInServerLSHost.ts index ec009e118fbc1..1bfff0bf6a920 100644 --- a/src/harness/unittests/cachingInServerLSHost.ts +++ b/src/harness/unittests/cachingInServerLSHost.ts @@ -7,7 +7,7 @@ namespace ts { } function createDefaultServerHost(fileMap: Map): server.ServerHost { - const existingDirectories = new StringSet(); + const existingDirectories = createSet(); forEachKeyInMap(fileMap, name => { let dir = getDirectoryPath(name); let previous: string; diff --git a/src/harness/unittests/moduleResolution.ts b/src/harness/unittests/moduleResolution.ts index d732f8ddabec4..5f07e46cbcfca 100644 --- a/src/harness/unittests/moduleResolution.ts +++ b/src/harness/unittests/moduleResolution.ts @@ -32,7 +32,7 @@ namespace ts { const map = arrayToMap(files, f => f.name); if (hasDirectoryExists) { - const directories = new StringSet(); + const directories = createSet(); for (const f of files) { let name = getDirectoryPath(f.name); while (true) { diff --git a/src/harness/unittests/session.ts b/src/harness/unittests/session.ts index 8d1b01ebfda2e..53f3ec3deb287 100644 --- a/src/harness/unittests/session.ts +++ b/src/harness/unittests/session.ts @@ -411,8 +411,8 @@ namespace ts.server { class InProcClient { private server: InProcSession; private seq = 0; - private callbacks = new NumberMap void>(); - private eventHandlers = new StringMap<(args: any) => void>(); + private callbacks = createMap void>(); + private eventHandlers = createMap void>(); handle(msg: protocol.Message): void { if (msg.type === "response") { diff --git a/src/harness/unittests/tsserverProjectSystem.ts b/src/harness/unittests/tsserverProjectSystem.ts index b18a21350e103..8972da33bb1eb 100644 --- a/src/harness/unittests/tsserverProjectSystem.ts +++ b/src/harness/unittests/tsserverProjectSystem.ts @@ -298,7 +298,7 @@ namespace ts.projectSystem { } export class Callbacks { - private map = new NumberMap(); + private map = createMap(); private nextId = 1; register(cb: (...args: any[]) => void, args: any[]) { @@ -335,8 +335,8 @@ namespace ts.projectSystem { private timeoutCallbacks = new Callbacks(); private immediateCallbacks = new Callbacks(); - readonly watchedDirectories = new StringMap<{ cb: DirectoryWatcherCallback, recursive: boolean }[]>(); - readonly watchedFiles = new StringMap(); + readonly watchedDirectories = createMap(); + readonly watchedFiles = createMap(); private filesOrFolders: FileOrFolder[]; diff --git a/src/harness/unittests/typingsInstaller.ts b/src/harness/unittests/typingsInstaller.ts index 121de92a2ed76..e101b932ef9f3 100644 --- a/src/harness/unittests/typingsInstaller.ts +++ b/src/harness/unittests/typingsInstaller.ts @@ -955,7 +955,7 @@ namespace ts.projectSystem { content: "" }; const host = createServerHost([f]); - const cache = new StringMap(); + const cache = createMap(); for (const name of JsTyping.nodeCoreModuleList) { const result = JsTyping.discoverTypings(host, [f.path], getDirectoryPath(f.path), /*safeListPath*/ undefined, cache, { enableAutoDiscovery: true }, [name, "somename"]); assert.deepEqual(result.newTypingNames.sort(), ["node", "somename"]); diff --git a/src/server/builder.ts b/src/server/builder.ts index 915d2e01efeee..59948f32df6f5 100644 --- a/src/server/builder.ts +++ b/src/server/builder.ts @@ -346,7 +346,7 @@ namespace ts.server { // Use slice to clone the array to avoid manipulating in place const queue = fileInfo.referencedBy.slice(0); - const fileNameSet = new StringMap(); + const fileNameSet = createMap(); fileNameSet.set(scriptInfo.fileName, scriptInfo); while (queue.length > 0) { const processingFileInfo = queue.pop(); diff --git a/src/server/client.ts b/src/server/client.ts index 3989161c9611f..f4912025527e5 100644 --- a/src/server/client.ts +++ b/src/server/client.ts @@ -15,7 +15,7 @@ namespace ts.server { export class SessionClient implements LanguageService { private sequence: number = 0; - private lineMaps = new ts.StringMap(); + private lineMaps = ts.createMap(); private messages: string[] = []; private lastRenameEntry: RenameEntry; diff --git a/src/server/editorServices.ts b/src/server/editorServices.ts index 8ddd659aad393..109a372f8312a 100644 --- a/src/server/editorServices.ts +++ b/src/server/editorServices.ts @@ -18,7 +18,7 @@ namespace ts.server { } function prepareConvertersForEnumLikeCompilerOptions(commandLineOptions: CommandLineOption[]): Map> { - const map = new StringMap>(); + const map = createMap>(); for (const option of commandLineOptions) { if (typeof option.type === "object") { const optionMap = >option.type; @@ -159,12 +159,12 @@ namespace ts.server { /** * a path to directory watcher map that detects added tsconfig files **/ - private readonly directoryWatchersForTsconfig = new StringMap(); + private readonly directoryWatchersForTsconfig = createMap(); /** * count of how many projects are using the directory watcher. * If the number becomes 0 for a watcher, then we should close it. **/ - private readonly directoryWatchersRefCount = new StringMap(); + private readonly directoryWatchersRefCount = createMap(); constructor(private readonly projectService: ProjectService) { } @@ -212,7 +212,7 @@ namespace ts.server { /** * maps external project file name to list of config files that were the part of this project */ - private readonly externalProjectToConfiguredProjectMap = new StringMap(); + private readonly externalProjectToConfiguredProjectMap = createMap(); /** * external projects (configuration and list of root files is not controlled by tsserver) @@ -902,7 +902,7 @@ namespace ts.server { private updateNonInferredProject(project: ExternalProject | ConfiguredProject, newUncheckedFiles: T[], propertyReader: FilePropertyReader, newOptions: CompilerOptions, newTypingOptions: TypingOptions, compileOnSave: boolean, configFileErrors: Diagnostic[]) { const oldRootScriptInfos = project.getRootScriptInfos(); const newRootScriptInfos: ScriptInfo[] = []; - const newRootScriptInfoMap: Map = new StringMap(); + const newRootScriptInfoMap: Map = createMap(); let projectErrors: Diagnostic[]; let rootFilesChanged = false; diff --git a/src/server/lsHost.ts b/src/server/lsHost.ts index b59a53e649d23..26da70c53899d 100644 --- a/src/server/lsHost.ts +++ b/src/server/lsHost.ts @@ -63,7 +63,7 @@ namespace ts.server { const path = toPath(containingFile, this.host.getCurrentDirectory(), this.getCanonicalFileName); const currentResolutionsInFile = cache.get(path); - const newResolutions = new StringMap(); + const newResolutions = createMap(); const resolvedModules: R[] = []; const compilerOptions = this.getCompilationSettings(); const lastDeletedFileName = this.project.projectService.lastDeletedFile && this.project.projectService.lastDeletedFile.fileName; diff --git a/src/server/project.ts b/src/server/project.ts index 7181448bee19a..92431c08543b4 100644 --- a/src/server/project.ts +++ b/src/server/project.ts @@ -603,7 +603,7 @@ namespace ts.server { // We need to use a set here since the code can contain the same import twice, // but that will only be one dependency. // To avoid invernal conversion, the key of the referencedFiles map must be of type Path - const referencedFiles = new StringSet(); + const referencedFiles = createSet(); if (sourceFile.imports && sourceFile.imports.length > 0) { const checker: TypeChecker = this.program.getTypeChecker(); for (const importName of sourceFile.imports) { @@ -778,7 +778,7 @@ namespace ts.server { } const configDirectoryPath = getDirectoryPath(this.configFileName); - this.directoriesWatchedForWildcards = new StringMap(); + this.directoriesWatchedForWildcards = createMap(); this.wildcardDirectories.forEach((flag, directory) => { if (comparePaths(configDirectoryPath, directory, ".", !this.projectService.host.useCaseSensitiveFileNames) !== Comparison.EqualTo) { const recursive = (flag & WatchDirectoryFlags.Recursive) !== 0; diff --git a/src/server/typingsCache.ts b/src/server/typingsCache.ts index 577589c9c3677..399a0788c4744 100644 --- a/src/server/typingsCache.ts +++ b/src/server/typingsCache.ts @@ -31,7 +31,7 @@ namespace ts.server { if ((arr1 || emptyArray).length === 0 && (arr2 || emptyArray).length === 0) { return true; } - const set = new StringMap(); + const set = createMap(); let unique = 0; for (const v of arr1) { @@ -72,7 +72,7 @@ namespace ts.server { } export class TypingsCache { - private readonly perProjectCache = new StringMap(); + private readonly perProjectCache = createMap(); constructor(private readonly installer: ITypingsInstaller) { } diff --git a/src/server/typingsInstaller/typingsInstaller.ts b/src/server/typingsInstaller/typingsInstaller.ts index dbebcd7567f8a..18c16b0d90ca5 100644 --- a/src/server/typingsInstaller/typingsInstaller.ts +++ b/src/server/typingsInstaller/typingsInstaller.ts @@ -78,10 +78,10 @@ namespace ts.server.typingsInstaller { }; export abstract class TypingsInstaller { - private readonly packageNameToTypingLocation = new StringMap(); - private readonly missingTypingsSet = new StringSet(); - private readonly knownCachesSet = new StringSet(); - private readonly projectWatchers = new StringMap(); + private readonly packageNameToTypingLocation = createMap(); + private readonly missingTypingsSet = createSet(); + private readonly knownCachesSet = createSet(); + private readonly projectWatchers = createMap(); readonly pendingRunRequests: PendingRequest[] = []; private installRunCount = 1; @@ -296,7 +296,7 @@ namespace ts.server.typingsInstaller { if (this.log.isEnabled()) { this.log.writeLine(`Requested to install typings ${JSON.stringify(typingsToInstall)}, installed typings ${JSON.stringify(installedTypings)}`); } - const installedPackages = new StringSet(); + const installedPackages = createSet(); const installedTypingFiles: string[] = []; for (const t of installedTypings) { const packageName = getBaseFileName(t); diff --git a/src/server/utilities.ts b/src/server/utilities.ts index 291058a973ec2..8cf2fbfe24218 100644 --- a/src/server/utilities.ts +++ b/src/server/utilities.ts @@ -225,7 +225,7 @@ namespace ts.server { } export class ThrottledOperations { - private pendingTimeouts = new StringMap(); + private pendingTimeouts = createMap(); constructor(private readonly host: ServerHost) { } diff --git a/src/services/codefixes/codeFixProvider.ts b/src/services/codefixes/codeFixProvider.ts index 6571f11f79ee9..6b27b11e4369f 100644 --- a/src/services/codefixes/codeFixProvider.ts +++ b/src/services/codefixes/codeFixProvider.ts @@ -14,7 +14,7 @@ namespace ts { } export namespace codefix { - const codeFixes = new NumberMap(); + const codeFixes = createMap(); export function registerCodeFix(action: CodeFix) { forEach(action.errorCodes, error => { diff --git a/src/services/completions.ts b/src/services/completions.ts index 4e7e27f771a5d..5005343ca9273 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -115,7 +115,7 @@ namespace ts.Completions { function getCompletionEntriesFromSymbols(symbols: Symbol[], entries: CompletionEntry[], location: Node, performCharacterChecks: boolean): Set { const start = timestamp(); - const uniqueNames = new StringSet(); + const uniqueNames = createSet(); if (symbols) { for (const symbol of symbols) { const entry = createCompletionEntry(symbol, location, performCharacterChecks); @@ -363,7 +363,7 @@ namespace ts.Completions { * * both foo.ts and foo.tsx become foo */ - const foundFiles = new StringSet(); + const foundFiles = createSet(); for (let filePath of files) { filePath = normalizePath(filePath); if (exclude && comparePaths(filePath, exclude, scriptPath, ignoreCase) === Comparison.EqualTo) { @@ -1553,7 +1553,7 @@ namespace ts.Completions { * do not occur at the current position and have not otherwise been typed. */ function filterNamedImportOrExportCompletionItems(exportsOfModule: Symbol[], namedImportsOrExports: ImportOrExportSpecifier[]): Symbol[] { - const existingImportsOrExports = new StringSet(); + const existingImportsOrExports = createSet(); for (const element of namedImportsOrExports) { // If this is the current item we are editing right now, do not filter it out @@ -1583,7 +1583,7 @@ namespace ts.Completions { return contextualMemberSymbols; } - const existingMemberNames = new StringSet(); + const existingMemberNames = createSet(); for (const m of existingMembers) { // Ignore omitted expressions for missing members if (m.kind !== SyntaxKind.PropertyAssignment && @@ -1628,7 +1628,7 @@ namespace ts.Completions { * do not occur at the current position and have not otherwise been typed. */ function filterJsxAttributes(symbols: Symbol[], attributes: NodeArray): Symbol[] { - const seenNames = new StringSet(); + const seenNames = createSet(); for (const attr of attributes) { // If this is the current item we are editing right now, do not filter it out if (attr.getStart() <= position && position <= attr.getEnd()) { diff --git a/src/services/documentHighlights.ts b/src/services/documentHighlights.ts index d2c9ff5df7f34..791ad48d9d682 100644 --- a/src/services/documentHighlights.ts +++ b/src/services/documentHighlights.ts @@ -39,7 +39,7 @@ namespace ts.DocumentHighlights { return undefined; } - const fileNameToDocumentHighlights = new StringMap(); + const fileNameToDocumentHighlights = createMap(); const result: DocumentHighlights[] = []; for (const referencedSymbol of referencedSymbols) { for (const referenceEntry of referencedSymbol.references) { diff --git a/src/services/documentRegistry.ts b/src/services/documentRegistry.ts index 7179daeae3a50..5c5a7797d2d09 100644 --- a/src/services/documentRegistry.ts +++ b/src/services/documentRegistry.ts @@ -105,7 +105,7 @@ namespace ts { export function createDocumentRegistry(useCaseSensitiveFileNames?: boolean, currentDirectory = ""): DocumentRegistry { // Maps from compiler setting target (ES3, ES5, etc.) to all the cached documents we have // for those settings. - const buckets = new StringMap>(); + const buckets = createMap>(); const getCanonicalFileName = createGetCanonicalFileName(!!useCaseSensitiveFileNames); function getKeyForCompilationSettings(settings: CompilerOptions): DocumentRegistryBucketKey { diff --git a/src/services/findAllReferences.ts b/src/services/findAllReferences.ts index 597eda404e282..fa86aba26aaa4 100644 --- a/src/services/findAllReferences.ts +++ b/src/services/findAllReferences.ts @@ -378,7 +378,7 @@ namespace ts.FindAllReferences { const possiblePositions = getPossibleSymbolReferencePositions(sourceFile, searchText, start, container.getEnd()); const parents = getParentSymbolsOfPropertyAccess(); - const inheritsFromCache = new StringMap(); + const inheritsFromCache = createMap(); if (possiblePositions.length) { // Build the set of symbols to search for, initially it has only the current symbol @@ -1047,7 +1047,7 @@ namespace ts.FindAllReferences { // Add symbol of properties/methods of the same name in base classes and implemented interfaces definitions if (!implementations && rootSymbol.parent && rootSymbol.parent.flags & (SymbolFlags.Class | SymbolFlags.Interface)) { - getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.getName(), result, /*previousIterationSymbolsCache*/ new StringMap()); + getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.getName(), result, /*previousIterationSymbolsCache*/ createMap()); } }); @@ -1177,7 +1177,7 @@ namespace ts.FindAllReferences { } const result: Symbol[] = []; - getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.getName(), result, /*previousIterationSymbolsCache*/ new StringMap()); + getPropertySymbolsFromBaseTypes(rootSymbol.parent, rootSymbol.getName(), result, /*previousIterationSymbolsCache*/ createMap()); return forEach(result, s => searchSymbols.indexOf(s) >= 0 ? s : undefined); } diff --git a/src/services/jsTyping.ts b/src/services/jsTyping.ts index 5e021c3b058ed..a4841a17752b0 100644 --- a/src/services/jsTyping.ts +++ b/src/services/jsTyping.ts @@ -29,7 +29,7 @@ namespace ts.JsTyping { // that we are confident require typings let safeList: Map; - const EmptySafeList = new StringMap(); + const EmptySafeList = createMap(); /* @internal */ export const nodeCoreModuleList: ReadonlyArray = [ @@ -62,7 +62,7 @@ namespace ts.JsTyping { { cachedTypingPaths: string[], newTypingNames: string[], filesToWatch: string[] } { // A typing name to typing file path mapping - const inferredTypings = new StringMap(); + const inferredTypings = createMap(); if (!typingOptions || !typingOptions.enableAutoDiscovery) { return { cachedTypingPaths: [], newTypingNames: [], filesToWatch: [] }; diff --git a/src/services/navigationBar.ts b/src/services/navigationBar.ts index 26b9d3d979832..00472f46c74bb 100644 --- a/src/services/navigationBar.ts +++ b/src/services/navigationBar.ts @@ -239,7 +239,7 @@ namespace ts.NavigationBar { /** Merge declarations of the same kind. */ function mergeChildren(children: NavigationBarNode[]): void { - const nameToItems = new StringMap(); + const nameToItems = createMap(); filterMutate(children, child => { const decl = child.node; const name = decl.name && nodeText(decl.name); @@ -626,15 +626,15 @@ namespace ts.NavigationBar { /** * Matches all whitespace characters in a string. Eg: - * + * * "app. - * + * * onactivated" - * + * * matches because of the newline, whereas - * + * * "app.onactivated" - * + * * does not match. */ const whiteSpaceRegex = /\s+/g; diff --git a/src/services/patternMatcher.ts b/src/services/patternMatcher.ts index ec7a2bbfa124f..cf107d8984bf3 100644 --- a/src/services/patternMatcher.ts +++ b/src/services/patternMatcher.ts @@ -113,7 +113,7 @@ namespace ts { // we see the name of a module that is used everywhere, or the name of an overload). As // such, we cache the information we compute about the candidate for the life of this // pattern matcher so we don't have to compute it multiple times. - const stringToWordSpans = new StringMap(); + const stringToWordSpans = createMap(); pattern = pattern.trim(); diff --git a/src/services/services.ts b/src/services/services.ts index 5cde409a01123..ac77391cc1211 100644 --- a/src/services/services.ts +++ b/src/services/services.ts @@ -502,7 +502,7 @@ namespace ts { } private computeNamedDeclarations(): Map { - const result = new StringMap(); + const result = createMap(); forEachChild(this, visit); @@ -1931,7 +1931,7 @@ namespace ts { } function initializeNameTable(sourceFile: SourceFile): void { - const nameTable = new StringMap(); + const nameTable = createMap(); walk(sourceFile); sourceFile.nameTable = nameTable;