Migrated more MapLikes to Maps

This commit is contained in:
Ron Buckton 2016-08-15 12:03:39 -07:00
parent 4e04b75d4b
commit 7f0a02ff02
23 changed files with 319 additions and 252 deletions

View File

@ -403,8 +403,8 @@ namespace ts {
result.parent = symbol.parent;
if (symbol.valueDeclaration) result.valueDeclaration = symbol.valueDeclaration;
if (symbol.constEnumOnlyModule) result.constEnumOnlyModule = true;
if (symbol.members) result.members = cloneSymbolTable(symbol.members);
if (symbol.exports) result.exports = cloneSymbolTable(symbol.exports);
if (symbol.members) result.members = cloneMap(symbol.members);
if (symbol.exports) result.exports = cloneMap(symbol.exports);
recordMergedSymbol(result, symbol);
return result;
}
@ -447,14 +447,6 @@ namespace ts {
}
}
function cloneSymbolTable(symbolTable: SymbolTable): SymbolTable {
const result = createMap<Symbol>();
for (const id in symbolTable) {
result[id] = symbolTable[id];
}
return result;
}
function mergeSymbolTable(target: SymbolTable, source: SymbolTable) {
for (const id in source) {
let targetSymbol = target[id];
@ -1450,7 +1442,7 @@ namespace ts {
return;
}
visitedSymbols.push(symbol);
const symbols = cloneSymbolTable(symbol.exports);
const symbols = cloneMap(symbol.exports);
// All export * declarations are collected in an __export symbol by the binder
const exportStars = symbol.exports["__export"];
if (exportStars) {
@ -1655,12 +1647,12 @@ namespace ts {
}
// If symbol is directly available by its name in the symbol table
if (isAccessible(lookUp(symbols, symbol.name))) {
if (isAccessible(symbols[symbol.name])) {
return [symbol];
}
// Check if symbol is any of the alias
return forEachValue(symbols, symbolFromSymbolTable => {
return forEachProperty(symbols, symbolFromSymbolTable => {
if (symbolFromSymbolTable.flags & SymbolFlags.Alias
&& symbolFromSymbolTable.name !== "export="
&& !getDeclarationOfKind(symbolFromSymbolTable, SyntaxKind.ExportSpecifier)) {
@ -6622,7 +6614,7 @@ namespace ts {
const maybeCache = maybeStack[depth];
// If result is definitely true, copy assumptions to global cache, else copy to next level up
const destinationCache = (result === Ternary.True || depth === 0) ? relation : maybeStack[depth - 1];
copyMap(maybeCache, destinationCache);
copyProperties(maybeCache, destinationCache);
}
else {
// A false result goes straight into global cache (when something is false under assumptions it
@ -7934,7 +7926,7 @@ namespace ts {
// check. This gives us a quicker out in the common case where an object type is not a function.
const resolved = resolveStructuredTypeMembers(type);
return !!(resolved.callSignatures.length || resolved.constructSignatures.length ||
hasProperty(resolved.members, "bind") && isTypeSubtypeOf(type, globalFunctionType));
resolved.members["bind"] && isTypeSubtypeOf(type, globalFunctionType));
}
function getTypeFacts(type: Type): TypeFacts {
@ -18192,7 +18184,7 @@ namespace ts {
// otherwise - check if at least one export is value
symbolLinks.exportsSomeValue = hasExportAssignment
? !!(moduleSymbol.flags & SymbolFlags.Value)
: forEachValue(getExportsOfModule(moduleSymbol), isValue);
: forEachProperty(getExportsOfModule(moduleSymbol), isValue);
}
return symbolLinks.exportsSomeValue;

View File

@ -486,10 +486,11 @@ namespace ts {
/* @internal */
export function createCompilerDiagnosticForInvalidCustomType(opt: CommandLineOptionOfCustomType): Diagnostic {
const namesOfType: string[] = [];
forEachKey(opt.type, key => {
namesOfType.push(` '${key}'`);
});
for (const key in opt.type) {
if (hasProperty(opt.type, key)) {
namesOfType.push(` '${key}'`);
}
}
return createCompilerDiagnostic(Diagnostics.Argument_for_0_option_must_be_Colon_1, `--${opt.name}`, namesOfType);
}
@ -551,11 +552,11 @@ namespace ts {
s = s.slice(s.charCodeAt(1) === CharacterCodes.minus ? 2 : 1).toLowerCase();
// Try to translate short option names to their full equivalents.
if (hasProperty(shortOptionNames, s)) {
if (s in shortOptionNames) {
s = shortOptionNames[s];
}
if (hasProperty(optionNameMap, s)) {
if (s in optionNameMap) {
const opt = optionNameMap[s];
if (opt.isTSConfigOnly) {
@ -811,7 +812,7 @@ namespace ts {
const optionNameMap = arrayToMap(optionDeclarations, opt => opt.name);
for (const id in jsonOptions) {
if (hasProperty(optionNameMap, id)) {
if (id in optionNameMap) {
const opt = optionNameMap[id];
defaultOptions[opt.name] = convertJsonOption(opt, jsonOptions[id], basePath, errors);
}
@ -1011,14 +1012,14 @@ namespace ts {
removeWildcardFilesWithLowerPriorityExtension(file, wildcardFileMap, supportedExtensions, keyMapper);
const key = keyMapper(file);
if (!hasProperty(literalFileMap, key) && !hasProperty(wildcardFileMap, key)) {
if (!(key in literalFileMap) && !(key in wildcardFileMap)) {
wildcardFileMap[key] = file;
}
}
}
const literalFiles = reduceProperties(literalFileMap, addFileToOutput, []);
const wildcardFiles = reduceProperties(wildcardFileMap, addFileToOutput, []);
const literalFiles = reduceOwnProperties(literalFileMap, addFileToOutput, []);
const wildcardFiles = reduceOwnProperties(wildcardFileMap, addFileToOutput, []);
wildcardFiles.sort(host.useCaseSensitiveFileNames ? compareStrings : compareStringsCaseInsensitive);
return {
fileNames: literalFiles.concat(wildcardFiles),
@ -1076,7 +1077,7 @@ namespace ts {
if (match) {
const key = useCaseSensitiveFileNames ? match[0] : match[0].toLowerCase();
const flags = watchRecursivePattern.test(name) ? WatchDirectoryFlags.Recursive : WatchDirectoryFlags.None;
const existingFlags = getProperty(wildcardDirectories, key);
const existingFlags = wildcardDirectories[key];
if (existingFlags === undefined || existingFlags < flags) {
wildcardDirectories[key] = flags;
if (flags === WatchDirectoryFlags.Recursive) {
@ -1088,11 +1089,9 @@ namespace ts {
// Remove any subpaths under an existing recursively watched directory.
for (const key in wildcardDirectories) {
if (hasProperty(wildcardDirectories, key)) {
for (const recursiveKey of recursiveKeys) {
if (key !== recursiveKey && containsPath(recursiveKey, key, path, !useCaseSensitiveFileNames)) {
delete wildcardDirectories[key];
}
for (const recursiveKey of recursiveKeys) {
if (key !== recursiveKey && containsPath(recursiveKey, key, path, !useCaseSensitiveFileNames)) {
delete wildcardDirectories[key];
}
}
}
@ -1115,7 +1114,7 @@ namespace ts {
for (let i = ExtensionPriority.Highest; i < adjustedExtensionPriority; i++) {
const higherPriorityExtension = extensions[i];
const higherPriorityPath = keyMapper(changeExtension(file, higherPriorityExtension));
if (hasProperty(literalFiles, higherPriorityPath) || hasProperty(wildcardFiles, higherPriorityPath)) {
if (higherPriorityPath in literalFiles || higherPriorityPath in wildcardFiles) {
return true;
}
}

View File

@ -21,10 +21,8 @@ namespace ts {
const createObject = Object.create;
export function createMap<T>(): Map<T> {
/* tslint:disable:no-null-keyword */
const map: Map<T> = createObject(null);
/* tslint:enable:no-null-keyword */
export function createMap<T>(template?: MapLike<T>): Map<T> {
const map: Map<T> = createObject(null); // tslint:disable-line:no-null-keyword
// Using 'delete' on an object causes V8 to put the object in dictionary mode.
// This disables creation of hidden classes, which are expensive when an object is
@ -32,6 +30,10 @@ namespace ts {
map["__"] = undefined;
delete map["__"];
if (template) {
copyOwnProperties(template, map);
}
return map;
}
@ -62,7 +64,7 @@ namespace ts {
}
function contains(path: Path) {
return hasProperty(files, toKey(path));
return toKey(path) in files;
}
function remove(path: Path) {
@ -350,82 +352,192 @@ namespace ts {
const hasOwnProperty = Object.prototype.hasOwnProperty;
/**
* Indicates whether a map-like contains an own property with the specified key.
*
* NOTE: This is intended for use only with MapLike<T> objects. For Map<T> objects, use
* the 'in' operator.
*
* @param map A map-like.
* @param key A property key.
*/
export function hasProperty<T>(map: MapLike<T>, key: string): boolean {
return hasOwnProperty.call(map, key);
}
export function getKeys<T>(map: MapLike<T>): string[] {
/**
* Gets the value of an owned property in a map-like.
*
* NOTE: This is intended for use only with MapLike<T> objects. For Map<T> objects, use
* an indexer.
*
* @param map A map-like.
* @param key A property key.
*/
export function getProperty<T>(map: MapLike<T>, key: string): T | undefined {
return hasOwnProperty.call(map, key) ? map[key] : undefined;
}
/**
* Gets the owned, enumerable property keys of a map-like.
*
* @param map A map-like.
*/
export function getOwnKeys<T>(map: MapLike<T>): string[] {
const keys: string[] = [];
for (const key in map) {
for (const key in map) if (hasOwnProperty.call(map, key)) {
keys.push(key);
}
return keys;
}
export function getProperty<T>(map: MapLike<T>, key: string): T | undefined {
return hasProperty(map, key) ? map[key] : undefined;
/**
* Enumerates the properties of a Map<T>, invoking a callback and returning the first truthy result.
*
* NOTE: This is intended for use with Map<T> objects. For MapLike<T> objects, use
* forEachOwnProperties instead as it offers better runtime safety.
*
* @param map A map for which properties should be enumerated.
* @param callback A callback to invoke for each property.
*/
export function forEachProperty<T, U>(map: Map<T>, callback: (value: T, key: string) => U): U {
let result: U;
for (const key in map) {
if (result = callback(map[key], key)) break;
}
return result;
}
export function getOrUpdateProperty<T>(map: MapLike<T>, key: string, makeValue: () => T): T {
return hasProperty(map, key) ? map[key] : map[key] = makeValue();
/**
* Enumerates the owned properties of a MapLike<T>, invoking a callback and returning the first truthy result.
*
* NOTE: This is intended for use with MapLike<T> objects. For Map<T> objects, use
* forEachProperty instead as it offers better performance.
*
* @param map A map for which properties should be enumerated.
* @param callback A callback to invoke for each property.
*/
export function forEachOwnProperty<T, U>(map: MapLike<T>, callback: (value: T, key: string) => U): U {
let result: U;
for (const key in map) if (hasOwnProperty.call(map, key)) {
if (result = callback(map[key], key)) break;
}
return result;
}
export function isEmpty<T>(map: MapLike<T>) {
for (const id in map) {
if (hasProperty(map, id)) {
return false;
/**
* Returns true if a Map<T> has some matching property.
*
* @param map A map whose properties should be tested.
* @param predicate An optional callback used to test each property.
*/
export function someProperties<T>(map: Map<T>, predicate?: (value: T, key: string) => boolean) {
for (const key in map) {
if (!predicate || predicate(map[key], key)) return true;
}
return false;
}
/**
* Performs a shallow copy of the properties from a source Map<T> to a target MapLike<T>
*
* NOTE: This is intended for use with Map<T> objects. For MapLike<T> objects, use
* copyOwnProperties instead as it offers better runtime safety.
*
* @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];
}
}
/**
* Performs a shallow copy of the owned properties from a source map to a target map-like.
*
* NOTE: This is intended for use with MapLike<T> objects. For Map<T> objects, use
* copyProperties instead as it offers better performance.
*
* @param source A map-like from which properties should be copied.
* @param target A map-like to which properties should be copied.
*/
export function copyOwnProperties<T>(source: MapLike<T>, target: MapLike<T>): void {
for (const key in source) if (hasOwnProperty.call(source, key)) {
target[key] = source[key];
}
}
/**
* Reduce the properties of a map.
*
* NOTE: This is intended for use with Map<T> objects. For MapLike<T> objects, use
* reduceOwnProperties instead as it offers better runtime safety.
*
* @param map The map to reduce
* @param callback An aggregation function that is called for each entry in the map
* @param initial The initial value for the reduction.
*/
export function reduceProperties<T, U>(map: Map<T>, callback: (aggregate: U, value: T, key: string) => U, initial: U): U {
let result = initial;
for (const key in map) {
result = callback(result, map[key], String(key));
}
return result;
}
/**
* Reduce the properties defined on a map-like (but not from its prototype chain).
*
* NOTE: This is intended for use with MapLike<T> objects. For Map<T> objects, use
* reduceProperties instead as it offers better performance.
*
* @param map The map-like to reduce
* @param callback An aggregation function that is called for each entry in the map
* @param initial The initial value for the reduction.
*/
export function reduceOwnProperties<T, U>(map: MapLike<T>, callback: (aggregate: U, value: T, key: string) => U, initial: U): U {
let result = initial;
for (const key in map) if (hasOwnProperty.call(map, key)) {
result = callback(result, map[key], String(key));
}
return result;
}
/**
* Counts the owned properties of a map-like.
*
* @param map A map-like whose properties should be counted.
* @param predicate An optional callback used to limit which properties should be counted.
*/
export function countOwnProperties<T>(map: MapLike<T>, predicate?: (value: T, key: string) => boolean) {
let count = 0;
for (const key in map) if (hasOwnProperty.call(map, key)) {
if (!predicate || predicate(map[key], key)) {
count++;
}
}
return count;
}
/**
* Performs a shallow equality comparison of the contents of two map-likes.
*
* @param left A map whose properties should be compared.
* @param right A map whose properties should be compared.
*/
export function equalOwnProperties<T>(left: MapLike<T>, right: MapLike<T>) {
if (left === right) return true;
if (!left || !right) return false;
for (const key in left) if (hasOwnProperty.call(left, key)) {
if (!hasOwnProperty.call(right, key) === undefined || left[key] !== right[key]) return false;
}
for (const key in right) if (hasOwnProperty.call(right, key)) {
if (!hasOwnProperty.call(left, key)) return false;
}
return true;
}
export function clone<T>(object: T): T {
const result: any = {};
for (const id in object) {
result[id] = (<any>object)[id];
}
return <T>result;
}
export function extend<T1 extends MapLike<{}>, T2 extends MapLike<{}>>(first: T1 , second: T2): T1 & T2 {
const result: T1 & T2 = <any>{};
for (const id in first) {
(result as any)[id] = first[id];
}
for (const id in second) {
if (!hasProperty(result, id)) {
(result as any)[id] = second[id];
}
}
return result;
}
export function forEachValue<T, U>(map: MapLike<T>, callback: (value: T) => U): U {
let result: U;
for (const id in map) {
if (result = callback(map[id])) break;
}
return result;
}
export function forEachKey<T, U>(map: MapLike<T>, callback: (key: string) => U): U {
let result: U;
for (const id in map) {
if (result = callback(id)) break;
}
return result;
}
export function lookUp<T>(map: MapLike<T>, key: string): T {
return hasProperty(map, key) ? map[key] : undefined;
}
export function copyMap<T>(source: MapLike<T>, target: MapLike<T>): void {
for (const p in source) {
target[p] = source[p];
}
}
/**
* Creates a map from the elements of an array.
*
@ -436,33 +548,42 @@ namespace ts {
* the same key with the given 'makeKey' function, then the element with the higher
* index in the array will be the one associated with the produced key.
*/
export function arrayToMap<T>(array: T[], makeKey: (value: T) => string): Map<T> {
const result = createMap<T>();
forEach(array, value => {
result[makeKey(value)] = value;
});
export function arrayToMap<T>(array: T[], makeKey: (value: T) => string): Map<T>;
export function arrayToMap<T, U>(array: T[], makeKey: (value: T) => string, makeValue: (value: T) => U): Map<U>;
export function arrayToMap<T, U>(array: T[], makeKey: (value: T) => string, makeValue?: (value: T) => U): Map<T | U> {
const result = createMap<T | U>();
for (const value of array) {
result[makeKey(value)] = makeValue ? makeValue(value) : value;
}
return result;
}
/**
* Reduce the properties of a map.
*
* @param map The map to reduce
* @param callback An aggregation function that is called for each entry in the map
* @param initial The initial value for the reduction.
*/
export function reduceProperties<T, U>(map: MapLike<T>, callback: (aggregate: U, value: T, key: string) => U, initial: U): U {
let result = initial;
if (map) {
for (const key in map) {
if (hasProperty(map, key)) {
result = callback(result, map[key], String(key));
}
export function cloneMap<T>(map: Map<T>) {
const clone = createMap<T>();
copyProperties(map, clone);
return clone;
}
export function clone<T>(object: T): T {
const result: any = {};
for (const id in object) {
if (hasOwnProperty.call(object, id)) {
result[id] = (<any>object)[id];
}
}
return result;
}
export function extend<T1 extends MapLike<{}>, T2 extends MapLike<{}>>(first: T1 , second: T2): T1 & T2 {
const result: T1 & T2 = <any>{};
for (const id in first) {
(result as any)[id] = first[id];
}
for (const id in second) {
if (!hasProperty(result, id)) {
(result as any)[id] = second[id];
}
}
return result;
}

View File

@ -157,9 +157,7 @@ namespace ts {
if (usedTypeDirectiveReferences) {
for (const directive in usedTypeDirectiveReferences) {
if (hasProperty(usedTypeDirectiveReferences, directive)) {
referencesOutput += `/// <reference types="${directive}" />${newLine}`;
}
referencesOutput += `/// <reference types="${directive}" />${newLine}`;
}
}
@ -272,7 +270,7 @@ namespace ts {
usedTypeDirectiveReferences = createMap<string>();
}
for (const directive of typeReferenceDirectives) {
if (!hasProperty(usedTypeDirectiveReferences, directive)) {
if (!(directive in usedTypeDirectiveReferences)) {
usedTypeDirectiveReferences[directive] = directive;
}
}
@ -537,14 +535,14 @@ namespace ts {
// do not need to keep track of created temp names.
function getExportDefaultTempVariableName(): string {
const baseName = "_default";
if (!hasProperty(currentIdentifiers, baseName)) {
if (!(baseName in currentIdentifiers)) {
return baseName;
}
let count = 0;
while (true) {
count++;
const name = baseName + "_" + count;
if (!hasProperty(currentIdentifiers, name)) {
if (!(name in currentIdentifiers)) {
return name;
}
}

View File

@ -407,7 +407,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
function isUniqueLocalName(name: string, container: Node): boolean {
for (let node = container; isNodeDescendentOf(node, container); node = node.nextContainer) {
if (node.locals && hasProperty(node.locals, name)) {
if (node.locals && name in node.locals) {
// We conservatively include alias symbols to cover cases where they're emitted as locals
if (node.locals[name].flags & (SymbolFlags.Value | SymbolFlags.ExportValue | SymbolFlags.Alias)) {
return false;
@ -669,8 +669,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
function isUniqueName(name: string): boolean {
return !resolver.hasGlobalName(name) &&
!hasProperty(currentFileIdentifiers, name) &&
!hasProperty(generatedNameSet, name);
!(name in currentFileIdentifiers) &&
!(name in generatedNameSet);
}
// Return the next available name in the pattern _a ... _z, _0, _1, ...
@ -2646,7 +2646,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
return false;
}
return !exportEquals && exportSpecifiers && hasProperty(exportSpecifiers, (<Identifier>node).text);
return !exportEquals && exportSpecifiers && (<Identifier>node).text in exportSpecifiers;
}
function emitPrefixUnaryExpression(node: PrefixUnaryExpression) {
@ -3263,7 +3263,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
write(", ");
}
if (!hasProperty(seen, id.text)) {
if (!(id.text in seen)) {
emit(id);
seen[id.text] = id.text;
}
@ -3970,7 +3970,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
return;
}
if (!exportEquals && exportSpecifiers && hasProperty(exportSpecifiers, name.text)) {
if (!exportEquals && exportSpecifiers && name.text in exportSpecifiers) {
for (const specifier of exportSpecifiers[name.text]) {
writeLine();
emitStart(specifier.name);
@ -6842,7 +6842,7 @@ const _super = (function (geti, seti) {
// export { x, y }
for (const specifier of (<ExportDeclaration>node).exportClause.elements) {
const name = (specifier.propertyName || specifier.name).text;
getOrUpdateProperty(exportSpecifiers, name, () => []).push(specifier);
(exportSpecifiers[name] || (exportSpecifiers[name] = [])).push(specifier);
}
}
break;
@ -6941,7 +6941,7 @@ const _super = (function (geti, seti) {
}
// local names set should only be added if we have anything exported
if (!exportedDeclarations && isEmpty(exportSpecifiers)) {
if (!exportedDeclarations && !someProperties(exportSpecifiers)) {
// no exported declarations (export var ...) or export specifiers (export {x})
// check if we have any non star export declarations.
let hasExportDeclarationWithExportClause = false;
@ -7091,7 +7091,7 @@ const _super = (function (geti, seti) {
if (name) {
// do not emit duplicate entries (in case of declaration merging) in the list of hoisted variables
const text = unescapeIdentifier(name.text);
if (hasProperty(seen, text)) {
if (text in seen) {
continue;
}
else {
@ -7460,7 +7460,7 @@ const _super = (function (geti, seti) {
// for deduplication purposes in key remove leading and trailing quotes so 'a' and "a" will be considered the same
const key = text.substr(1, text.length - 2);
if (hasProperty(groupIndices, key)) {
if (key in groupIndices) {
// deduplicate/group entries in dependency list by the dependency name
const groupIndex = groupIndices[key];
dependencyGroups[groupIndex].push(externalImports[i]);

View File

@ -501,7 +501,7 @@ namespace ts {
if (state.traceEnabled) {
trace(state.host, Diagnostics.paths_option_is_specified_looking_for_a_pattern_to_match_module_name_0, moduleName);
}
matchedPattern = matchPatternOrExact(getKeys(state.compilerOptions.paths), moduleName);
matchedPattern = matchPatternOrExact(getOwnKeys(state.compilerOptions.paths), moduleName);
}
if (matchedPattern) {
@ -875,7 +875,7 @@ namespace ts {
}
function directoryExists(directoryPath: string): boolean {
if (hasProperty(existingDirectories, directoryPath)) {
if (directoryPath in existingDirectories) {
return true;
}
if (sys.directoryExists(directoryPath)) {
@ -903,7 +903,7 @@ namespace ts {
const hash = sys.createHash(data);
const mtimeBefore = sys.getModifiedTime(fileName);
if (mtimeBefore && hasProperty(outputFingerprints, fileName)) {
if (mtimeBefore && fileName in outputFingerprints) {
const fingerprint = outputFingerprints[fileName];
// If output has not been changed, and the file has no external modification
@ -1041,14 +1041,9 @@ namespace ts {
const resolutions: T[] = [];
const cache = createMap<T>();
for (const name of names) {
let result: T;
if (hasProperty(cache, name)) {
result = cache[name];
}
else {
result = loader(name, containingFile);
cache[name] = result;
}
const result = name in cache
? cache[name]
: cache[name] = loader(name, containingFile);
resolutions.push(result);
}
return resolutions;
@ -1249,7 +1244,7 @@ namespace ts {
classifiableNames = createMap<string>();
for (const sourceFile of files) {
copyMap(sourceFile.classifiableNames, classifiableNames);
copyProperties(sourceFile.classifiableNames, classifiableNames);
}
}
@ -1277,7 +1272,7 @@ namespace ts {
(oldOptions.maxNodeModuleJsDepth !== options.maxNodeModuleJsDepth) ||
!arrayIsEqualTo(oldOptions.typeRoots, oldOptions.typeRoots) ||
!arrayIsEqualTo(oldOptions.rootDirs, options.rootDirs) ||
!mapIsEqualTo(oldOptions.paths, options.paths)) {
!equalOwnProperties(oldOptions.paths, options.paths)) {
return false;
}
@ -1399,7 +1394,7 @@ namespace ts {
getSourceFile: program.getSourceFile,
getSourceFileByPath: program.getSourceFileByPath,
getSourceFiles: program.getSourceFiles,
isSourceFileFromExternalLibrary: (file: SourceFile) => !!lookUp(sourceFilesFoundSearchingNodeModules, file.path),
isSourceFileFromExternalLibrary: (file: SourceFile) => !!sourceFilesFoundSearchingNodeModules[file.path],
writeFile: writeFileCallback || (
(fileName, data, writeByteOrderMark, onError, sourceFiles) => host.writeFile(fileName, data, writeByteOrderMark, onError, sourceFiles)),
isEmitBlocked,
@ -1937,7 +1932,7 @@ namespace ts {
// If the file was previously found via a node_modules search, but is now being processed as a root file,
// then everything it sucks in may also be marked incorrectly, and needs to be checked again.
if (file && lookUp(sourceFilesFoundSearchingNodeModules, file.path) && currentNodeModulesDepth == 0) {
if (file && sourceFilesFoundSearchingNodeModules[file.path] && currentNodeModulesDepth == 0) {
sourceFilesFoundSearchingNodeModules[file.path] = false;
if (!options.noResolve) {
processReferencedFiles(file, getDirectoryPath(fileName), isDefaultLib);
@ -1948,7 +1943,7 @@ namespace ts {
processImportedModules(file, getDirectoryPath(fileName));
}
// See if we need to reprocess the imports due to prior skipped imports
else if (file && lookUp(modulesWithElidedImports, file.path)) {
else if (file && modulesWithElidedImports[file.path]) {
if (currentNodeModulesDepth < maxNodeModulesJsDepth) {
modulesWithElidedImports[file.path] = false;
processImportedModules(file, getDirectoryPath(fileName));

View File

@ -445,10 +445,9 @@ namespace ts {
}
function cachedFileExists(fileName: string): boolean {
if (hasProperty(cachedExistingFiles, fileName)) {
return cachedExistingFiles[fileName];
}
return cachedExistingFiles[fileName] = hostFileExists(fileName);
return fileName in cachedExistingFiles
? cachedExistingFiles[fileName]
: cachedExistingFiles[fileName] = hostFileExists(fileName);
}
function getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void) {
@ -704,9 +703,12 @@ namespace ts {
description = getDiagnosticText(option.description);
const options: string[] = [];
const element = (<CommandLineOptionOfListType>option).element;
forEachKey(<Map<number | string>>element.type, key => {
options.push(`'${key}'`);
});
const typeMap = <MapLike<number | string>>element.type;
for (const key in typeMap) {
if (hasProperty(typeMap, key)) {
options.push(`'${key}'`);
}
}
optionsDescriptionMap[description] = options;
}
else {

View File

@ -87,25 +87,6 @@ namespace ts {
return node.end - node.pos;
}
export function mapIsEqualTo<T>(map1: MapLike<T>, map2: MapLike<T>): boolean {
if (!map1 || !map2) {
return map1 === map2;
}
return containsAll(map1, map2) && containsAll(map2, map1);
}
function containsAll<T>(map: MapLike<T>, other: MapLike<T>): boolean {
for (const key in map) {
if (!hasProperty(map, key)) {
continue;
}
if (!hasProperty(other, key) || map[key] !== other[key]) {
return false;
}
}
return true;
}
export function arrayIsEqualTo<T>(array1: T[], array2: T[], equaler?: (a: T, b: T) => boolean): boolean {
if (!array1 || !array2) {
return array1 === array2;
@ -2792,7 +2773,7 @@ namespace ts {
}
function stringifyObject(value: any) {
return `{${reduceProperties(value, stringifyProperty, "")}}`;
return `{${reduceOwnProperties(value, stringifyProperty, "")}}`;
}
function stringifyProperty(memo: string, value: any, key: string) {

View File

@ -204,7 +204,7 @@ namespace FourSlash {
public formatCodeOptions: ts.FormatCodeOptions;
private inputFiles: ts.MapLike<string> = {}; // Map between inputFile's fileName and its content for easily looking up when resolving references
private inputFiles = ts.createMap<string>(); // Map between inputFile's fileName and its content for easily looking up when resolving references
// Add input file which has matched file name with the given reference-file path.
// This is necessary when resolveReference flag is specified
@ -300,11 +300,11 @@ namespace FourSlash {
}
else {
// resolveReference file-option is not specified then do not resolve any files and include all inputFiles
ts.forEachKey(this.inputFiles, fileName => {
for (const fileName in this.inputFiles) {
if (!Harness.isDefaultLibraryFile(fileName)) {
this.languageServiceAdapterHost.addScript(fileName, this.inputFiles[fileName], /*isRootFile*/ true);
}
});
}
this.languageServiceAdapterHost.addScript(Harness.Compiler.defaultLibFileName,
Harness.Compiler.getDefaultLibrarySourceFile().text, /*isRootFile*/ false);
}
@ -773,7 +773,7 @@ namespace FourSlash {
}
public verifyRangesWithSameTextReferenceEachOther() {
ts.forEachValue(this.rangesByText(), ranges => this.verifyRangesReferenceEachOther(ranges));
ts.forEachOwnProperty(this.rangesByText(), ranges => this.verifyRangesReferenceEachOther(ranges));
}
private verifyReferencesWorker(references: ts.ReferenceEntry[], fileName: string, start: number, end: number, isWriteAccess?: boolean, isDefinition?: boolean) {

View File

@ -1011,7 +1011,7 @@ namespace Harness {
optionsIndex[option.name.toLowerCase()] = option;
}
}
return ts.lookUp(optionsIndex, name.toLowerCase());
return ts.getProperty(optionsIndex, name.toLowerCase());
}
export function setCompilerOptionsFromHarnessSetting(settings: Harness.TestCaseParser.CompilerSettings, options: ts.CompilerOptions & HarnessOptions): void {

View File

@ -135,7 +135,7 @@ namespace Harness.LanguageService {
public getFilenames(): string[] {
const fileNames: string[] = [];
ts.forEachValue(this.fileNameToScript, (scriptInfo) => {
ts.forEachOwnProperty(this.fileNameToScript, (scriptInfo) => {
if (scriptInfo.isRootFile) {
// only include root files here
// usually it means that we won't include lib.d.ts in the list of root files so it won't mess the computation of compilation root dir.
@ -146,7 +146,7 @@ namespace Harness.LanguageService {
}
public getScriptInfo(fileName: string): ScriptInfo {
return ts.lookUp(this.fileNameToScript, fileName);
return ts.getProperty(this.fileNameToScript, fileName);
}
public addScript(fileName: string, content: string, isRootFile: boolean): void {

View File

@ -8,7 +8,7 @@ namespace ts {
function createDefaultServerHost(fileMap: MapLike<File>): server.ServerHost {
const existingDirectories: MapLike<boolean> = {};
forEachValue(fileMap, v => {
forEachOwnProperty(fileMap, v => {
let dir = getDirectoryPath(v.name);
let previous: string;
do {

View File

@ -130,7 +130,7 @@ namespace ts {
},
fileExists: fileName => hasProperty(files, fileName),
readFile: fileName => {
const file = lookUp(files, fileName);
const file = getProperty(files, fileName);
return file && file.text;
}
};
@ -152,16 +152,6 @@ namespace ts {
return program;
}
function getSizeOfMap(map: MapLike<any>): number {
let size = 0;
for (const id in map) {
if (hasProperty(map, id)) {
size++;
}
}
return size;
}
function checkResolvedModule(expected: ResolvedModule, actual: ResolvedModule): void {
assert.isTrue(actual !== undefined);
assert.isTrue(expected.resolvedFileName === actual.resolvedFileName, `'resolvedFileName': expected '${expected.resolvedFileName}' to be equal to '${actual.resolvedFileName}'`);
@ -183,8 +173,8 @@ namespace ts {
}
else {
assert.isTrue(cache !== undefined, `expected ${caption} to be set`);
const actualCacheSize = getSizeOfMap(cache);
const expectedSize = getSizeOfMap(expectedContent);
const actualCacheSize = countOwnProperties(cache);
const expectedSize = countOwnProperties(expectedContent);
assert.isTrue(actualCacheSize === expectedSize, `expected actual size: ${actualCacheSize} to be equal to ${expectedSize}`);
for (const id in expectedContent) {

View File

@ -68,20 +68,10 @@ namespace ts {
return entry;
}
function sizeOfMap(map: MapLike<any>): number {
let n = 0;
for (const name in map) {
if (hasProperty(map, name)) {
n++;
}
}
return n;
}
function checkMapKeys(caption: string, map: MapLike<any>, expectedKeys: string[]) {
assert.equal(sizeOfMap(map), expectedKeys.length, `${caption}: incorrect size of map`);
assert.equal(countOwnProperties(map), expectedKeys.length, `${caption}: incorrect size of map`);
for (const name of expectedKeys) {
assert.isTrue(hasProperty(map, name), `${caption} is expected to contain ${name}, actual keys: ${getKeys(map)}`);
assert.isTrue(hasProperty(map, name), `${caption} is expected to contain ${name}, actual keys: ${getOwnKeys(map)}`);
}
}
@ -208,7 +198,7 @@ namespace ts {
watchDirectory(directoryName: string, callback: DirectoryWatcherCallback, recursive: boolean): DirectoryWatcher {
const path = this.toPath(directoryName);
const callbacks = lookUp(this.watchedDirectories, path) || (this.watchedDirectories[path] = []);
const callbacks = getProperty(this.watchedDirectories, path) || (this.watchedDirectories[path] = []);
callbacks.push({ cb: callback, recursive });
return {
referenceCount: 0,
@ -229,7 +219,7 @@ namespace ts {
triggerDirectoryWatcherCallback(directoryName: string, fileName: string): void {
const path = this.toPath(directoryName);
const callbacks = lookUp(this.watchedDirectories, path);
const callbacks = getProperty(this.watchedDirectories, path);
if (callbacks) {
for (const callback of callbacks) {
callback.cb(fileName);
@ -239,7 +229,7 @@ namespace ts {
triggerFileWatcherCallback(fileName: string, removed?: boolean): void {
const path = this.toPath(fileName);
const callbacks = lookUp(this.watchedFiles, path);
const callbacks = getProperty(this.watchedFiles, path);
if (callbacks) {
for (const callback of callbacks) {
callback(path, removed);
@ -249,7 +239,7 @@ namespace ts {
watchFile(fileName: string, callback: FileWatcherCallback) {
const path = this.toPath(fileName);
const callbacks = lookUp(this.watchedFiles, path) || (this.watchedFiles[path] = []);
const callbacks = getProperty(this.watchedFiles, path) || (this.watchedFiles[path] = []);
callbacks.push(callback);
return {
close: () => {
@ -594,7 +584,7 @@ namespace ts {
content: `{
"compilerOptions": {
"target": "es6"
},
},
"files": [ "main.ts" ]
}`
};
@ -621,7 +611,7 @@ namespace ts {
content: `{
"compilerOptions": {
"target": "es6"
},
},
"files": [ "main.ts" ]
}`
};

View File

@ -37,7 +37,7 @@ namespace ts.server {
}
private getLineMap(fileName: string): number[] {
let lineMap = ts.lookUp(this.lineMaps, fileName);
let lineMap = this.lineMaps[fileName];
if (!lineMap) {
const scriptSnapshot = this.host.getScriptSnapshot(fileName);
lineMap = this.lineMaps[fileName] = ts.computeLineStarts(scriptSnapshot.getText(0, scriptSnapshot.getLength()));

View File

@ -136,9 +136,9 @@ namespace ts.server {
for (const name of names) {
// check if this is a duplicate entry in the list
let resolution = lookUp(newResolutions, name);
let resolution = newResolutions[name];
if (!resolution) {
const existingResolution = currentResolutionsInFile && ts.lookUp(currentResolutionsInFile, name);
const existingResolution = currentResolutionsInFile && currentResolutionsInFile[name];
if (moduleResolutionIsValid(existingResolution)) {
// ok, it is safe to use existing name resolution results
resolution = existingResolution;
@ -563,7 +563,7 @@ namespace ts.server {
}
let strBuilder = "";
ts.forEachValue(this.filenameToSourceFile,
ts.forEachProperty(this.filenameToSourceFile,
sourceFile => { strBuilder += sourceFile.fileName + "\n"; });
return strBuilder;
}
@ -857,7 +857,7 @@ namespace ts.server {
if (project.isConfiguredProject()) {
project.projectFileWatcher.close();
project.directoryWatcher.close();
forEachValue(project.directoriesWatchedForWildcards, watcher => { watcher.close(); });
forEachProperty(project.directoriesWatchedForWildcards, watcher => { watcher.close(); });
delete project.directoriesWatchedForWildcards;
this.configuredProjects = copyListRemovingItem(project, this.configuredProjects);
}
@ -1124,7 +1124,7 @@ namespace ts.server {
getScriptInfo(filename: string) {
filename = ts.normalizePath(filename);
return ts.lookUp(this.filenameToScriptInfo, filename);
return this.filenameToScriptInfo[filename];
}
/**
@ -1133,7 +1133,7 @@ namespace ts.server {
*/
openFile(fileName: string, openedByClient: boolean, fileContent?: string, scriptKind?: ScriptKind) {
fileName = ts.normalizePath(fileName);
let info = ts.lookUp(this.filenameToScriptInfo, fileName);
let info = this.filenameToScriptInfo[fileName];
if (!info) {
let content: string;
if (this.host.fileExists(fileName)) {
@ -1246,7 +1246,7 @@ namespace ts.server {
* @param filename is absolute pathname
*/
closeClientFile(filename: string) {
const info = ts.lookUp(this.filenameToScriptInfo, filename);
const info = this.filenameToScriptInfo[filename];
if (info) {
this.closeOpenFile(info);
info.isOpen = false;
@ -1255,14 +1255,14 @@ namespace ts.server {
}
getProjectForFile(filename: string) {
const scriptInfo = ts.lookUp(this.filenameToScriptInfo, filename);
const scriptInfo = this.filenameToScriptInfo[filename];
if (scriptInfo) {
return scriptInfo.defaultProject;
}
}
printProjectsForFile(filename: string) {
const scriptInfo = ts.lookUp(this.filenameToScriptInfo, filename);
const scriptInfo = this.filenameToScriptInfo[filename];
if (scriptInfo) {
this.psLogger.startGroup();
this.psLogger.info("Projects for " + filename);
@ -1419,7 +1419,7 @@ namespace ts.server {
/*recursive*/ true
);
project.directoriesWatchedForWildcards = reduceProperties(projectOptions.wildcardDirectories, (watchers, flag, directory) => {
project.directoriesWatchedForWildcards = reduceOwnProperties(projectOptions.wildcardDirectories, (watchers, flag, directory) => {
if (comparePaths(configDirectoryPath, directory, ".", !this.host.useCaseSensitiveFileNames) !== Comparison.EqualTo) {
const recursive = (flag & WatchDirectoryFlags.Recursive) !== 0;
this.log(`Add ${ recursive ? "recursive " : ""}watcher for: ${directory}`);

View File

@ -139,16 +139,16 @@ namespace ts.JsTyping {
const jsonConfig: PackageJson = result.config;
filesToWatch.push(jsonPath);
if (jsonConfig.dependencies) {
mergeTypings(getKeys(jsonConfig.dependencies));
mergeTypings(getOwnKeys(jsonConfig.dependencies));
}
if (jsonConfig.devDependencies) {
mergeTypings(getKeys(jsonConfig.devDependencies));
mergeTypings(getOwnKeys(jsonConfig.devDependencies));
}
if (jsonConfig.optionalDependencies) {
mergeTypings(getKeys(jsonConfig.optionalDependencies));
mergeTypings(getOwnKeys(jsonConfig.optionalDependencies));
}
if (jsonConfig.peerDependencies) {
mergeTypings(getKeys(jsonConfig.peerDependencies));
mergeTypings(getOwnKeys(jsonConfig.peerDependencies));
}
}
}

View File

@ -15,7 +15,7 @@ namespace ts.NavigateTo {
const nameToDeclarations = sourceFile.getNamedDeclarations();
for (const name in nameToDeclarations) {
const declarations = getProperty(nameToDeclarations, name);
const declarations = nameToDeclarations[name];
if (declarations) {
// First do a quick check to see if the name of the declaration matches the
// last portion of the (possibly) dotted name they're searching for.

View File

@ -243,7 +243,7 @@ namespace ts.NavigationBar {
return true;
}
const itemsWithSameName = getProperty(nameToItems, name);
const itemsWithSameName = nameToItems[name];
if (!itemsWithSameName) {
nameToItems[name] = child;
return true;

View File

@ -990,7 +990,7 @@ namespace ts {
}
function getDeclarations(name: string) {
return getProperty(result, name) || (result[name] = []);
return result[name] || (result[name] = []);
}
function getDeclarationName(declaration: Declaration) {
@ -2042,7 +2042,7 @@ namespace ts {
function fixupCompilerOptions(options: CompilerOptions, diagnostics: Diagnostic[]): CompilerOptions {
// Lazily create this value to fix module loading errors.
commandLineOptionsStringToEnum = commandLineOptionsStringToEnum || <CommandLineOptionOfCustomType[]>filter(optionDeclarations, o =>
typeof o.type === "object" && !forEachValue(<Map<any>>o.type, v => typeof v !== "number"));
typeof o.type === "object" && !forEachOwnProperty(<MapLike<any>>o.type, v => typeof v !== "number"));
options = clone(options);
@ -2058,7 +2058,7 @@ namespace ts {
options[opt.name] = parseCustomTypeOption(opt, value, diagnostics);
}
else {
if (!forEachValue(opt.type, v => v === value)) {
if (!forEachOwnProperty(opt.type, v => v === value)) {
// Supplied value isn't a valid enum value.
diagnostics.push(createCompilerDiagnosticForInvalidCustomType(opt));
}
@ -2251,7 +2251,7 @@ namespace ts {
}
function getBucketForCompilationSettings(key: DocumentRegistryBucketKey, createIfMissing: boolean): FileMap<DocumentRegistryEntry> {
let bucket = lookUp(buckets, key);
let bucket = buckets[key];
if (!bucket && createIfMissing) {
buckets[key] = bucket = createFileMap<DocumentRegistryEntry>();
}
@ -2260,7 +2260,7 @@ namespace ts {
function reportStats() {
const bucketInfoArray = Object.keys(buckets).filter(name => name && name.charAt(0) === "_").map(name => {
const entries = lookUp(buckets, name);
const entries = buckets[name];
const sourceFiles: { name: string; refCount: number; references: string[]; }[] = [];
entries.forEachValue((key, entry) => {
sourceFiles.push({
@ -3099,7 +3099,7 @@ namespace ts {
oldSettings.allowJs !== newSettings.allowJs ||
oldSettings.disableSizeLimit !== oldSettings.disableSizeLimit ||
oldSettings.baseUrl !== newSettings.baseUrl ||
!mapIsEqualTo(oldSettings.paths, newSettings.paths));
!equalOwnProperties(oldSettings.paths, newSettings.paths));
// Now create a new compiler
const compilerHost: CompilerHost = {
@ -4114,11 +4114,11 @@ namespace ts {
existingImportsOrExports[name.text] = true;
}
if (isEmpty(existingImportsOrExports)) {
if (!someProperties(existingImportsOrExports)) {
return filter(exportsOfModule, e => e.name !== "default");
}
return filter(exportsOfModule, e => e.name !== "default" && !lookUp(existingImportsOrExports, e.name));
return filter(exportsOfModule, e => e.name !== "default" && !existingImportsOrExports[e.name]);
}
/**
@ -4165,7 +4165,7 @@ namespace ts {
existingMemberNames[existingName] = true;
}
return filter(contextualMemberSymbols, m => !lookUp(existingMemberNames, m.name));
return filter(contextualMemberSymbols, m => !existingMemberNames[m.name]);
}
/**
@ -4187,7 +4187,7 @@ namespace ts {
}
}
return filter(symbols, a => !lookUp(seenNames, a.name));
return filter(symbols, a => !seenNames[a.name]);
}
}
@ -4323,7 +4323,7 @@ namespace ts {
const entry = createCompletionEntry(symbol, location, performCharacterChecks);
if (entry) {
const id = escapeIdentifier(entry.name);
if (!lookUp(uniqueNames, id)) {
if (!uniqueNames[id]) {
entries.push(entry);
uniqueNames[id] = id;
}
@ -5151,7 +5151,7 @@ namespace ts {
// Type reference directives
const typeReferenceDirective = findReferenceInPosition(sourceFile.typeReferenceDirectives, position);
if (typeReferenceDirective) {
const referenceFile = lookUp(program.getResolvedTypeReferenceDirectives(), typeReferenceDirective.fileName);
const referenceFile = program.getResolvedTypeReferenceDirectives()[typeReferenceDirective.fileName];
if (referenceFile && referenceFile.resolvedFileName) {
return [getDefinitionInfoForFileReference(typeReferenceDirective.fileName, referenceFile.resolvedFileName)];
}
@ -5323,7 +5323,7 @@ namespace ts {
for (const referencedSymbol of referencedSymbols) {
for (const referenceEntry of referencedSymbol.references) {
const fileName = referenceEntry.fileName;
let documentHighlights = getProperty(fileNameToDocumentHighlights, fileName);
let documentHighlights = fileNameToDocumentHighlights[fileName];
if (!documentHighlights) {
documentHighlights = { fileName, highlightSpans: [] };
@ -6068,7 +6068,7 @@ namespace ts {
const nameTable = getNameTable(sourceFile);
if (lookUp(nameTable, internedName) !== undefined) {
if (nameTable[internedName] !== undefined) {
result = result || [];
getReferencesInNode(sourceFile, symbol, declaredName, node, searchMeaning, findInStrings, findInComments, result, symbolToIndex);
}

View File

@ -311,9 +311,9 @@ namespace ts {
// 'in' does not have this effect.
if ("getModuleResolutionsForFile" in this.shimHost) {
this.resolveModuleNames = (moduleNames: string[], containingFile: string) => {
const resolutionsInFile = <Map<string>>JSON.parse(this.shimHost.getModuleResolutionsForFile(containingFile));
const resolutionsInFile = <MapLike<string>>JSON.parse(this.shimHost.getModuleResolutionsForFile(containingFile));
return map(moduleNames, name => {
const result = lookUp(resolutionsInFile, name);
const result = getProperty(resolutionsInFile, name);
return result ? { resolvedFileName: result } : undefined;
});
};
@ -323,8 +323,8 @@ namespace ts {
}
if ("getTypeReferenceDirectiveResolutionsForFile" in this.shimHost) {
this.resolveTypeReferenceDirectives = (typeDirectiveNames: string[], containingFile: string) => {
const typeDirectivesForFile = <Map<ResolvedTypeReferenceDirective>>JSON.parse(this.shimHost.getTypeReferenceDirectiveResolutionsForFile(containingFile));
return map(typeDirectiveNames, name => lookUp(typeDirectivesForFile, name));
const typeDirectivesForFile = <MapLike<ResolvedTypeReferenceDirective>>JSON.parse(this.shimHost.getTypeReferenceDirectiveResolutionsForFile(containingFile));
return map(typeDirectiveNames, name => getProperty(typeDirectivesForFile, name));
};
}
}

View File

@ -237,7 +237,7 @@ namespace ts.SignatureHelp {
const typeChecker = program.getTypeChecker();
for (const sourceFile of program.getSourceFiles()) {
const nameToDeclarations = sourceFile.getNamedDeclarations();
const declarations = getProperty(nameToDeclarations, name.text);
const declarations = nameToDeclarations[name.text];
if (declarations) {
for (const declaration of declarations) {

View File

@ -32,7 +32,7 @@
"property-declaration": "nospace",
"variable-declaration": "nospace"
}],
"next-line": [true,
"next-line": [true,
"check-catch",
"check-else"
],
@ -44,7 +44,6 @@
"boolean-trivia": true,
"type-operator-spacing": true,
"prefer-const": true,
"no-in-operator": true,
"no-increment-decrement": true,
"object-literal-surrounding-space": true,
"no-type-assertion-whitespace": true