Clean up/move some Map helper functions.

This commit is contained in:
Ron Buckton 2016-08-16 11:15:15 -07:00
parent 1dc495adf8
commit 889e5ac7ae
9 changed files with 18 additions and 151 deletions

View File

@ -1016,8 +1016,8 @@ namespace ts {
}
}
const literalFiles = reduceOwnProperties(literalFileMap, addFileToOutput, []);
const wildcardFiles = reduceOwnProperties(wildcardFileMap, addFileToOutput, []);
const literalFiles = reduceProperties(literalFileMap, addFileToOutput, []);
const wildcardFiles = reduceProperties(wildcardFileMap, addFileToOutput, []);
wildcardFiles.sort(host.useCaseSensitiveFileNames ? compareStrings : compareStringsCaseInsensitive);
return {
fileNames: literalFiles.concat(wildcardFiles),

View File

@ -30,8 +30,10 @@ namespace ts {
map["__"] = undefined;
delete map["__"];
if (template) {
copyOwnProperties(template, map);
// Copies keys/values from template. Note that for..in will not throw if
// template is undefined, and instead will just exit the loop.
for (const key in template) if (hasOwnProperty.call(template, key)) {
map[key] = template[key];
}
return map;
@ -412,9 +414,6 @@ namespace ts {
/**
* 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.
*/
@ -426,53 +425,6 @@ namespace ts {
return result;
}
/**
* 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;
}
/**
* Maps key-value pairs of a map into a new map.
*
* NOTE: The key-value pair passed to the callback is *not* safe to cache between invocations
* of the callback.
*
* @param map A map.
* @param callback A callback that maps a key-value pair into a new key-value pair.
*/
export function mapPairs<T, U>(map: Map<T>, callback: (entry: [string, T]) => [string, U]): Map<U> {
let result: Map<U>;
if (map) {
result = createMap<U>();
let inPair: [string, T];
for (const key in map) {
if (inPair) {
inPair[0] = key;
inPair[1] = map[key];
}
else {
inPair = [key, map[key]];
}
const outPair = callback(inPair);
result[outPair[0]] = outPair[1];
}
}
return result;
}
/**
* Returns true if a Map<T> has some matching property.
*
@ -489,9 +441,6 @@ namespace ts {
/**
* 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.
*/
@ -501,21 +450,6 @@ namespace ts {
}
}
/**
* 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.
*
@ -552,72 +486,9 @@ namespace ts {
return result;
}
/**
* Counts the properties of a map.
*
* NOTE: This is intended for use with Map<T> objects. For MapLike<T> objects, use
* countOwnProperties instead as it offers better runtime safety.
*
* @param map A map whose properties should be counted.
* @param predicate An optional callback used to limit which properties should be counted.
*/
export function countProperties<T>(map: Map<T>, predicate?: (value: T, key: string) => boolean) {
let count = 0;
for (const key in map) {
if (!predicate || predicate(map[key], key)) {
count++;
}
}
return count;
}
/**
* Counts the owned properties of a map-like.
*
* NOTE: This is intended for use with MapLike<T> objects. For Map<T> objects, use
* countProperties instead as it offers better performance.
*
* @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 maps.
*
* NOTE: This is intended for use with Map<T> objects. For MapLike<T> objects, use
* equalOwnProperties instead as it offers better runtime safety.
*
* @param left A map whose properties should be compared.
* @param right A map whose properties should be compared.
*/
export function equalProperties<T>(left: Map<T>, right: Map<T>, equalityComparer?: (left: T, right: T) => boolean) {
if (left === right) return true;
if (!left || !right) return false;
for (const key in left) {
if (!(key in right)) return false;
if (equalityComparer ? !equalityComparer(left[key], right[key]) : left[key] !== right[key]) return false;
}
for (const key in right) {
if (!(key in left)) return false;
}
return true;
}
/**
* Performs a shallow equality comparison of the contents of two map-likes.
*
* NOTE: This is intended for use with MapLike<T> objects. For Map<T> objects, use
* equalProperties instead as it offers better performance.
*
* @param left A map-like whose properties should be compared.
* @param right A map-like whose properties should be compared.
*/
@ -670,17 +541,13 @@ namespace ts {
return result;
}
export function extend<T1 extends MapLike<{}>, T2 extends MapLike<{}>>(first: T1 , second: T2): T1 & T2 {
export function extend<T1, T2>(first: T1 , second: T2): T1 & T2 {
const result: T1 & T2 = <any>{};
for (const id in first) {
if (hasOwnProperty.call(first, id)) {
(result as any)[id] = first[id];
}
for (const id in second) if (hasOwnProperty.call(second, id)) {
(result as any)[id] = (second as any)[id];
}
for (const id in second) {
if (hasOwnProperty.call(second, id) && !hasOwnProperty.call(result, id)) {
(result as any)[id] = second[id];
}
for (const id in first) if (hasOwnProperty.call(first, id)) {
(result as any)[id] = (first as any)[id];
}
return result;
}

View File

@ -773,7 +773,7 @@ namespace FourSlash {
}
public verifyRangesWithSameTextReferenceEachOther() {
ts.forEachOwnProperty(this.rangesByText(), ranges => this.verifyRangesReferenceEachOther(ranges));
ts.forEachProperty(this.rangesByText(), ranges => this.verifyRangesReferenceEachOther(ranges));
}
private verifyReferencesWorker(references: ts.ReferenceEntry[], fileName: string, start: number, end: number, isWriteAccess?: boolean, isDefinition?: boolean) {

View File

@ -135,7 +135,7 @@ namespace Harness.LanguageService {
public getFilenames(): string[] {
const fileNames: string[] = [];
ts.forEachOwnProperty(this.fileNameToScript, (scriptInfo) => {
ts.forEachProperty(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.

View File

@ -358,7 +358,7 @@ export = C;
function test(files: Map<string>, options: CompilerOptions, currentDirectory: string, useCaseSensitiveFileNames: boolean, rootFiles: string[], diagnosticCodes: number[]): void {
const getCanonicalFileName = createGetCanonicalFileName(useCaseSensitiveFileNames);
if (!useCaseSensitiveFileNames) {
files = mapPairs(files, ([fileName, file]) => [getCanonicalFileName(fileName), file]);
files = reduceProperties(files, (files, file, fileName) => (files[getCanonicalFileName(fileName)] = file, files), createMap<string>());
}
const host: CompilerHost = {

View File

@ -183,7 +183,7 @@ namespace ts {
}
else {
assert.isTrue(cache !== undefined, `expected ${caption} to be set`);
assert.isTrue(equalProperties(expectedContent, cache, entryChecker), `contents of ${caption} did not match the expected contents.`);
assert.isTrue(equalOwnProperties(expectedContent, cache, entryChecker), `contents of ${caption} did not match the expected contents.`);
}
}

View File

@ -69,7 +69,7 @@ namespace ts {
}
function checkMapKeys(caption: string, map: Map<any>, expectedKeys: string[]) {
assert.equal(countProperties(map), expectedKeys.length, `${caption}: incorrect size of map`);
assert.equal(reduceProperties(map, count => count + 1, 0), expectedKeys.length, `${caption}: incorrect size of map`);
for (const name of expectedKeys) {
assert.isTrue(name in map, `${caption} is expected to contain ${name}, actual keys: ${Object.keys(map)}`);
}

View File

@ -1419,7 +1419,7 @@ namespace ts.server {
/*recursive*/ true
);
project.directoriesWatchedForWildcards = reduceOwnProperties(projectOptions.wildcardDirectories, (watchers, flag, directory) => {
project.directoriesWatchedForWildcards = reduceProperties(createMap(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

@ -2058,7 +2058,7 @@ namespace ts {
options[opt.name] = parseCustomTypeOption(opt, value, diagnostics);
}
else {
if (!forEachOwnProperty(opt.type, v => v === value)) {
if (!forEachProperty(opt.type, v => v === value)) {
// Supplied value isn't a valid enum value.
diagnostics.push(createCompilerDiagnosticForInvalidCustomType(opt));
}