use Map instead of StringHashTable

This commit is contained in:
Mohamed Hegazy 2014-07-23 16:52:43 -07:00
parent 346809ba2b
commit 212c184602
2 changed files with 143 additions and 138 deletions

View file

@ -43,145 +43,145 @@ module TypeScript {
return new BlockIntrinsics<T>();
}
export interface IHashTable<T> {
getAllKeys(): string[];
add(key: string, data: T): boolean;
addOrUpdate(key: string, data: T): boolean;
map(fn: (k: string, value: T, context: any) => void , context: any): void;
every(fn: (k: string, value: T, context: any) => void , context: any): boolean;
some(fn: (k: string, value: T, context: any) => void , context: any): boolean;
count(): number;
lookup(key: string): T;
}
//export interface IHashTable<T> {
// getAllKeys(): string[];
// add(key: string, data: T): boolean;
// addOrUpdate(key: string, data: T): boolean;
// map(fn: (k: string, value: T, context: any) => void , context: any): void;
// every(fn: (k: string, value: T, context: any) => void , context: any): boolean;
// some(fn: (k: string, value: T, context: any) => void , context: any): boolean;
// count(): number;
// lookup(key: string): T;
//}
export class StringHashTable<T> implements IHashTable<T> {
private itemCount = 0;
private table: IIndexable<T> = createIntrinsicsObject<T>();
//export class StringHashTable<T> implements IHashTable<T> {
// private itemCount = 0;
// private table: IIndexable<T> = createIntrinsicsObject<T>();
public getAllKeys(): string[] {
var result: string[] = [];
// public getAllKeys(): string[] {
// var result: string[] = [];
for (var k in this.table) {
if (this.table[k] !== undefined) {
result.push(k);
}
}
// for (var k in this.table) {
// if (this.table[k] !== undefined) {
// result.push(k);
// }
// }
return result;
}
// return result;
// }
public add(key: string, data: T): boolean {
if (this.table[key] !== undefined) {
return false;
}
// public add(key: string, data: T): boolean {
// if (this.table[key] !== undefined) {
// return false;
// }
this.table[key] = data;
this.itemCount++;
return true;
}
// this.table[key] = data;
// this.itemCount++;
// return true;
// }
public addOrUpdate(key: string, data: T): boolean {
if (this.table[key] !== undefined) {
this.table[key] = data;
return false;
}
// public addOrUpdate(key: string, data: T): boolean {
// if (this.table[key] !== undefined) {
// this.table[key] = data;
// return false;
// }
this.table[key] = data;
this.itemCount++;
return true;
}
// this.table[key] = data;
// this.itemCount++;
// return true;
// }
public map(fn: (k: string, value: T, context: any) => void , context: any) {
for (var k in this.table) {
var data = this.table[k];
// public map(fn: (k: string, value: T, context: any) => void , context: any) {
// for (var k in this.table) {
// var data = this.table[k];
if (data !== undefined) {
fn(k, this.table[k], context);
}
}
}
// if (data !== undefined) {
// fn(k, this.table[k], context);
// }
// }
// }
public every(fn: (k: string, value: T, context: any) => void , context: any) {
for (var k in this.table) {
var data = this.table[k];
// public every(fn: (k: string, value: T, context: any) => void , context: any) {
// for (var k in this.table) {
// var data = this.table[k];
if (data !== undefined) {
if (!fn(k, this.table[k], context)) {
return false;
}
}
}
// if (data !== undefined) {
// if (!fn(k, this.table[k], context)) {
// return false;
// }
// }
// }
return true;
}
// return true;
// }
public some(fn: (k: string, value: T, context: any) => void , context: any) {
for (var k in this.table) {
var data = this.table[k];
// public some(fn: (k: string, value: T, context: any) => void , context: any) {
// for (var k in this.table) {
// var data = this.table[k];
if (data !== undefined) {
if (fn(k, this.table[k], context)) {
return true;
}
}
}
// if (data !== undefined) {
// if (fn(k, this.table[k], context)) {
// return true;
// }
// }
// }
return false;
}
// return false;
// }
public count(): number {
return this.itemCount;
}
// public count(): number {
// return this.itemCount;
// }
public lookup(key: string) : T {
var data = this.table[key];
return data === undefined ? null : data;
}
// public lookup(key: string) : T {
// var data = this.table[key];
// return data === undefined ? null : data;
// }
public remove(key: string): void {
if (this.table[key] !== undefined) {
this.table[key] = undefined;
this.itemCount--;
}
}
}
// public remove(key: string): void {
// if (this.table[key] !== undefined) {
// this.table[key] = undefined;
// this.itemCount--;
// }
// }
//}
export class IdentiferNameHashTable<T> extends StringHashTable<T> {
public getAllKeys(): string[]{
var result: string[] = [];
//export class IdentiferNameHashTable<T> extends StringHashTable<T> {
// public getAllKeys(): string[]{
// var result: string[] = [];
super.map((k, v, c) => {
if (v !== undefined) {
result.push(k.substring(1));
}
}, null);
// super.map((k, v, c) => {
// if (v !== undefined) {
// result.push(k.substring(1));
// }
// }, null);
return result;
}
// return result;
// }
public add(key: string, data: T): boolean {
return super.add("#" + key, data);
}
// public add(key: string, data: T): boolean {
// return super.add("#" + key, data);
// }
public addOrUpdate(key: string, data: T): boolean {
return super.addOrUpdate("#" + key, data);
}
// public addOrUpdate(key: string, data: T): boolean {
// return super.addOrUpdate("#" + key, data);
// }
public map(fn: (k: string, value: T, context: any) => void , context: any) {
return super.map((k, v, c) => fn(k.substring(1), v, c), context);
}
// public map(fn: (k: string, value: T, context: any) => void , context: any) {
// return super.map((k, v, c) => fn(k.substring(1), v, c), context);
// }
public every(fn: (k: string, value: T, context: any) => void , context: any) {
return super.every((k, v, c) => fn(k.substring(1), v, c), context);
}
// public every(fn: (k: string, value: T, context: any) => void , context: any) {
// return super.every((k, v, c) => fn(k.substring(1), v, c), context);
// }
public some(fn: (k: string, value: any, context: any) => void , context: any) {
return super.some((k, v, c) => fn(k.substring(1), v, c), context);
}
// public some(fn: (k: string, value: any, context: any) => void , context: any) {
// return super.some((k, v, c) => fn(k.substring(1), v, c), context);
// }
public lookup(key: string): T {
return super.lookup("#" + key);
}
}
// public lookup(key: string): T {
// return super.lookup("#" + key);
// }
//}
}

View file

@ -50,18 +50,18 @@ module TypeScript.Services {
// at each language service public entry point, since we don't know when
// set of scripts handled by the host changes.
class HostCache {
private _filenameToEntry: TypeScript.StringHashTable<HostFileInformation>;
private _filenameToEntry: ts.Map<HostFileInformation>;
private _compilationSettings: ts.CompilerOptions;
constructor(host: ILanguageServiceHost) {
// script id => script index
this._filenameToEntry = new TypeScript.StringHashTable<HostFileInformation>();
this._filenameToEntry = {};
var filenames = host.getScriptFileNames();
for (var i = 0, n = filenames.length; i < n; i++) {
var filename = filenames[i];
this._filenameToEntry.add(TypeScript.switchToForwardSlashes(filename), new HostFileInformation(
filename, host, host.getScriptVersion(filename), host.getScriptIsOpen(filename), host.getScriptByteOrderMark(filename)));
this._filenameToEntry[TypeScript.switchToForwardSlashes(filename)] = new HostFileInformation(
filename, host, host.getScriptVersion(filename), host.getScriptIsOpen(filename), host.getScriptByteOrderMark(filename));
}
this._compilationSettings = host.getCompilationSettings() || getDefaultCompilerOptions();
@ -72,35 +72,39 @@ module TypeScript.Services {
}
public contains(filename: string): boolean {
return this._filenameToEntry.lookup(TypeScript.switchToForwardSlashes(filename)) !== null;
return !!this._filenameToEntry[TypeScript.switchToForwardSlashes(filename)];
}
public getHostfilename(filename: string) {
var hostCacheEntry = this._filenameToEntry.lookup(TypeScript.switchToForwardSlashes(filename));
var hostCacheEntry = this._filenameToEntry[TypeScript.switchToForwardSlashes(filename)];
if (hostCacheEntry) {
return hostCacheEntry.filename;
}
return filename;
}
public getfilenames(): string[] {
return this._filenameToEntry.getAllKeys();
public getfilenames(): string[]{
var fileNames: string[] = [];
for (var id in this._filenameToEntry) {
fileNames.push(id);
}
return fileNames;
}
public getVersion(filename: string): number {
return this._filenameToEntry.lookup(TypeScript.switchToForwardSlashes(filename)).version;
return this._filenameToEntry[TypeScript.switchToForwardSlashes(filename)].version;
}
public isOpen(filename: string): boolean {
return this._filenameToEntry.lookup(TypeScript.switchToForwardSlashes(filename)).isOpen;
return this._filenameToEntry[TypeScript.switchToForwardSlashes(filename)].isOpen;
}
public getByteOrderMark(filename: string): TypeScript.ByteOrderMark {
return this._filenameToEntry.lookup(TypeScript.switchToForwardSlashes(filename)).byteOrderMark;
return this._filenameToEntry[TypeScript.switchToForwardSlashes(filename)].byteOrderMark;
}
public getScriptSnapshot(filename: string): TypeScript.IScriptSnapshot {
return this._filenameToEntry.lookup(TypeScript.switchToForwardSlashes(filename)).getScriptSnapshot();
return this._filenameToEntry[TypeScript.switchToForwardSlashes(filename)].getScriptSnapshot();
}
public getScriptTextChangeRangeSinceVersion(filename: string, lastKnownVersion: number): TypeScript.TextChangeRange {
@ -325,17 +329,17 @@ module TypeScript.Services {
}
export class DocumentRegistry implements IDocumentRegistry {
private buckets: IIndexable<StringHashTable<DocumentRegistryEntry>> = {};
private buckets: ts.Map<ts.Map<DocumentRegistryEntry>> = {};
private getKeyFromCompilationSettings(settings: ts.CompilerOptions): string {
return "_" + ts.ScriptTarget[settings.target]; // + "|" + settings.propagateEnumConstants.toString()
}
private getBucketForCompilationSettings(settings: ts.CompilerOptions, createIfMissing: boolean): StringHashTable<DocumentRegistryEntry> {
private getBucketForCompilationSettings(settings: ts.CompilerOptions, createIfMissing: boolean): ts.Map<DocumentRegistryEntry> {
var key = this.getKeyFromCompilationSettings(settings);
var bucket = this.buckets[key];
if (!bucket && createIfMissing) {
this.buckets[key] = bucket = new StringHashTable<DocumentRegistryEntry>();
this.buckets[key] = bucket = {};
}
return bucket;
}
@ -343,14 +347,15 @@ module TypeScript.Services {
public reportStats() {
var bucketInfoArray = Object.keys(this.buckets).filter(name => name && name.charAt(0) === '_').map(name => {
var entries = this.buckets[name];
var documents = entries.getAllKeys().map((name) => {
var entry = entries.lookup(name);
return {
name: name,
var documents = [];
for (var i in entries) {
var entry = entries[i];
documents.push({
name: i,
refCount: entry.refCount,
references: entry.owners.slice(0)
};
});
});
}
documents.sort((x, y) => y.refCount - x.refCount);
return { bucket: name, documents: documents }
});
@ -367,12 +372,12 @@ module TypeScript.Services {
referencedFiles: string[]= []): TypeScript.Document {
var bucket = this.getBucketForCompilationSettings(compilationSettings, /*createIfMissing*/ true);
var entry = bucket.lookup(filename);
var entry = bucket[filename];
if (!entry) {
var document = Document.create(compilationSettings, filename, scriptSnapshot, byteOrderMark, version, isOpen, referencedFiles);
entry = new DocumentRegistryEntry(document);
bucket.add(filename, entry);
bucket[filename] = entry;
}
entry.refCount++;
@ -391,7 +396,7 @@ module TypeScript.Services {
var bucket = this.getBucketForCompilationSettings(compilationSettings, /*createIfMissing*/ false);
Debug.assert(bucket);
var entry = bucket.lookup(filename);
var entry = bucket[filename];
Debug.assert(entry);
if (entry.document.isOpen === isOpen && entry.document.version === version) {
@ -406,12 +411,12 @@ module TypeScript.Services {
var bucket = this.getBucketForCompilationSettings(compilationSettings, false);
Debug.assert(bucket);
var entry = bucket.lookup(filename);
var entry = bucket[filename];
entry.refCount--;
Debug.assert(entry.refCount >= 0);
if (entry.refCount === 0) {
bucket.remove(filename);
delete bucket[filename];
}
}
}