use Map instead of StringHashTable
This commit is contained in:
parent
346809ba2b
commit
212c184602
|
@ -43,145 +43,145 @@ module TypeScript {
|
||||||
return new BlockIntrinsics<T>();
|
return new BlockIntrinsics<T>();
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IHashTable<T> {
|
//export interface IHashTable<T> {
|
||||||
getAllKeys(): string[];
|
// getAllKeys(): string[];
|
||||||
add(key: string, data: T): boolean;
|
// add(key: string, data: T): boolean;
|
||||||
addOrUpdate(key: string, data: T): boolean;
|
// addOrUpdate(key: string, data: T): boolean;
|
||||||
map(fn: (k: string, value: T, context: any) => void , context: any): void;
|
// map(fn: (k: string, value: T, context: any) => void , context: any): void;
|
||||||
every(fn: (k: string, value: T, context: any) => void , context: any): boolean;
|
// every(fn: (k: string, value: T, context: any) => void , context: any): boolean;
|
||||||
some(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;
|
// count(): number;
|
||||||
lookup(key: string): T;
|
// lookup(key: string): T;
|
||||||
}
|
//}
|
||||||
|
|
||||||
export class StringHashTable<T> implements IHashTable<T> {
|
//export class StringHashTable<T> implements IHashTable<T> {
|
||||||
private itemCount = 0;
|
// private itemCount = 0;
|
||||||
private table: IIndexable<T> = createIntrinsicsObject<T>();
|
// private table: IIndexable<T> = createIntrinsicsObject<T>();
|
||||||
|
|
||||||
public getAllKeys(): string[] {
|
// public getAllKeys(): string[] {
|
||||||
var result: string[] = [];
|
// var result: string[] = [];
|
||||||
|
|
||||||
for (var k in this.table) {
|
// for (var k in this.table) {
|
||||||
if (this.table[k] !== undefined) {
|
// if (this.table[k] !== undefined) {
|
||||||
result.push(k);
|
// result.push(k);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
return result;
|
// return result;
|
||||||
}
|
// }
|
||||||
|
|
||||||
public add(key: string, data: T): boolean {
|
// public add(key: string, data: T): boolean {
|
||||||
if (this.table[key] !== undefined) {
|
// if (this.table[key] !== undefined) {
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
|
|
||||||
this.table[key] = data;
|
// this.table[key] = data;
|
||||||
this.itemCount++;
|
// this.itemCount++;
|
||||||
return true;
|
// return true;
|
||||||
}
|
// }
|
||||||
|
|
||||||
public addOrUpdate(key: string, data: T): boolean {
|
// public addOrUpdate(key: string, data: T): boolean {
|
||||||
if (this.table[key] !== undefined) {
|
// if (this.table[key] !== undefined) {
|
||||||
this.table[key] = data;
|
// this.table[key] = data;
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
|
|
||||||
this.table[key] = data;
|
// this.table[key] = data;
|
||||||
this.itemCount++;
|
// this.itemCount++;
|
||||||
return true;
|
// return true;
|
||||||
}
|
// }
|
||||||
|
|
||||||
public map(fn: (k: string, value: T, context: any) => void , context: any) {
|
// public map(fn: (k: string, value: T, context: any) => void , context: any) {
|
||||||
for (var k in this.table) {
|
// for (var k in this.table) {
|
||||||
var data = this.table[k];
|
// var data = this.table[k];
|
||||||
|
|
||||||
if (data !== undefined) {
|
// if (data !== undefined) {
|
||||||
fn(k, this.table[k], context);
|
// fn(k, this.table[k], context);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
public every(fn: (k: string, value: T, context: any) => void , context: any) {
|
// public every(fn: (k: string, value: T, context: any) => void , context: any) {
|
||||||
for (var k in this.table) {
|
// for (var k in this.table) {
|
||||||
var data = this.table[k];
|
// var data = this.table[k];
|
||||||
|
|
||||||
if (data !== undefined) {
|
// if (data !== undefined) {
|
||||||
if (!fn(k, this.table[k], context)) {
|
// if (!fn(k, this.table[k], context)) {
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
return true;
|
// return true;
|
||||||
}
|
// }
|
||||||
|
|
||||||
public some(fn: (k: string, value: T, context: any) => void , context: any) {
|
// public some(fn: (k: string, value: T, context: any) => void , context: any) {
|
||||||
for (var k in this.table) {
|
// for (var k in this.table) {
|
||||||
var data = this.table[k];
|
// var data = this.table[k];
|
||||||
|
|
||||||
if (data !== undefined) {
|
// if (data !== undefined) {
|
||||||
if (fn(k, this.table[k], context)) {
|
// if (fn(k, this.table[k], context)) {
|
||||||
return true;
|
// return true;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
|
||||||
return false;
|
// return false;
|
||||||
}
|
// }
|
||||||
|
|
||||||
public count(): number {
|
// public count(): number {
|
||||||
return this.itemCount;
|
// return this.itemCount;
|
||||||
}
|
// }
|
||||||
|
|
||||||
public lookup(key: string) : T {
|
// public lookup(key: string) : T {
|
||||||
var data = this.table[key];
|
// var data = this.table[key];
|
||||||
return data === undefined ? null : data;
|
// return data === undefined ? null : data;
|
||||||
}
|
// }
|
||||||
|
|
||||||
public remove(key: string): void {
|
// public remove(key: string): void {
|
||||||
if (this.table[key] !== undefined) {
|
// if (this.table[key] !== undefined) {
|
||||||
this.table[key] = undefined;
|
// this.table[key] = undefined;
|
||||||
this.itemCount--;
|
// this.itemCount--;
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
|
|
||||||
|
|
||||||
export class IdentiferNameHashTable<T> extends StringHashTable<T> {
|
//export class IdentiferNameHashTable<T> extends StringHashTable<T> {
|
||||||
public getAllKeys(): string[]{
|
// public getAllKeys(): string[]{
|
||||||
var result: string[] = [];
|
// var result: string[] = [];
|
||||||
|
|
||||||
super.map((k, v, c) => {
|
// super.map((k, v, c) => {
|
||||||
if (v !== undefined) {
|
// if (v !== undefined) {
|
||||||
result.push(k.substring(1));
|
// result.push(k.substring(1));
|
||||||
}
|
// }
|
||||||
}, null);
|
// }, null);
|
||||||
|
|
||||||
return result;
|
// return result;
|
||||||
}
|
// }
|
||||||
|
|
||||||
public add(key: string, data: T): boolean {
|
// public add(key: string, data: T): boolean {
|
||||||
return super.add("#" + key, data);
|
// return super.add("#" + key, data);
|
||||||
}
|
// }
|
||||||
|
|
||||||
public addOrUpdate(key: string, data: T): boolean {
|
// public addOrUpdate(key: string, data: T): boolean {
|
||||||
return super.addOrUpdate("#" + key, data);
|
// return super.addOrUpdate("#" + key, data);
|
||||||
}
|
// }
|
||||||
|
|
||||||
public map(fn: (k: string, value: T, context: any) => void , context: any) {
|
// 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);
|
// 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) {
|
// 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);
|
// 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) {
|
// 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);
|
// return super.some((k, v, c) => fn(k.substring(1), v, c), context);
|
||||||
}
|
// }
|
||||||
|
|
||||||
public lookup(key: string): T {
|
// public lookup(key: string): T {
|
||||||
return super.lookup("#" + key);
|
// return super.lookup("#" + key);
|
||||||
}
|
// }
|
||||||
}
|
//}
|
||||||
}
|
}
|
|
@ -50,18 +50,18 @@ module TypeScript.Services {
|
||||||
// at each language service public entry point, since we don't know when
|
// at each language service public entry point, since we don't know when
|
||||||
// set of scripts handled by the host changes.
|
// set of scripts handled by the host changes.
|
||||||
class HostCache {
|
class HostCache {
|
||||||
private _filenameToEntry: TypeScript.StringHashTable<HostFileInformation>;
|
private _filenameToEntry: ts.Map<HostFileInformation>;
|
||||||
private _compilationSettings: ts.CompilerOptions;
|
private _compilationSettings: ts.CompilerOptions;
|
||||||
|
|
||||||
constructor(host: ILanguageServiceHost) {
|
constructor(host: ILanguageServiceHost) {
|
||||||
// script id => script index
|
// script id => script index
|
||||||
this._filenameToEntry = new TypeScript.StringHashTable<HostFileInformation>();
|
this._filenameToEntry = {};
|
||||||
|
|
||||||
var filenames = host.getScriptFileNames();
|
var filenames = host.getScriptFileNames();
|
||||||
for (var i = 0, n = filenames.length; i < n; i++) {
|
for (var i = 0, n = filenames.length; i < n; i++) {
|
||||||
var filename = filenames[i];
|
var filename = filenames[i];
|
||||||
this._filenameToEntry.add(TypeScript.switchToForwardSlashes(filename), new HostFileInformation(
|
this._filenameToEntry[TypeScript.switchToForwardSlashes(filename)] = new HostFileInformation(
|
||||||
filename, host, host.getScriptVersion(filename), host.getScriptIsOpen(filename), host.getScriptByteOrderMark(filename)));
|
filename, host, host.getScriptVersion(filename), host.getScriptIsOpen(filename), host.getScriptByteOrderMark(filename));
|
||||||
}
|
}
|
||||||
|
|
||||||
this._compilationSettings = host.getCompilationSettings() || getDefaultCompilerOptions();
|
this._compilationSettings = host.getCompilationSettings() || getDefaultCompilerOptions();
|
||||||
|
@ -72,35 +72,39 @@ module TypeScript.Services {
|
||||||
}
|
}
|
||||||
|
|
||||||
public contains(filename: string): boolean {
|
public contains(filename: string): boolean {
|
||||||
return this._filenameToEntry.lookup(TypeScript.switchToForwardSlashes(filename)) !== null;
|
return !!this._filenameToEntry[TypeScript.switchToForwardSlashes(filename)];
|
||||||
}
|
}
|
||||||
|
|
||||||
public getHostfilename(filename: string) {
|
public getHostfilename(filename: string) {
|
||||||
var hostCacheEntry = this._filenameToEntry.lookup(TypeScript.switchToForwardSlashes(filename));
|
var hostCacheEntry = this._filenameToEntry[TypeScript.switchToForwardSlashes(filename)];
|
||||||
if (hostCacheEntry) {
|
if (hostCacheEntry) {
|
||||||
return hostCacheEntry.filename;
|
return hostCacheEntry.filename;
|
||||||
}
|
}
|
||||||
return filename;
|
return filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
public getfilenames(): string[] {
|
public getfilenames(): string[]{
|
||||||
return this._filenameToEntry.getAllKeys();
|
var fileNames: string[] = [];
|
||||||
|
for (var id in this._filenameToEntry) {
|
||||||
|
fileNames.push(id);
|
||||||
|
}
|
||||||
|
return fileNames;
|
||||||
}
|
}
|
||||||
|
|
||||||
public getVersion(filename: string): number {
|
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 {
|
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 {
|
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 {
|
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 {
|
public getScriptTextChangeRangeSinceVersion(filename: string, lastKnownVersion: number): TypeScript.TextChangeRange {
|
||||||
|
@ -325,17 +329,17 @@ module TypeScript.Services {
|
||||||
}
|
}
|
||||||
|
|
||||||
export class DocumentRegistry implements IDocumentRegistry {
|
export class DocumentRegistry implements IDocumentRegistry {
|
||||||
private buckets: IIndexable<StringHashTable<DocumentRegistryEntry>> = {};
|
private buckets: ts.Map<ts.Map<DocumentRegistryEntry>> = {};
|
||||||
|
|
||||||
private getKeyFromCompilationSettings(settings: ts.CompilerOptions): string {
|
private getKeyFromCompilationSettings(settings: ts.CompilerOptions): string {
|
||||||
return "_" + ts.ScriptTarget[settings.target]; // + "|" + settings.propagateEnumConstants.toString()
|
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 key = this.getKeyFromCompilationSettings(settings);
|
||||||
var bucket = this.buckets[key];
|
var bucket = this.buckets[key];
|
||||||
if (!bucket && createIfMissing) {
|
if (!bucket && createIfMissing) {
|
||||||
this.buckets[key] = bucket = new StringHashTable<DocumentRegistryEntry>();
|
this.buckets[key] = bucket = {};
|
||||||
}
|
}
|
||||||
return bucket;
|
return bucket;
|
||||||
}
|
}
|
||||||
|
@ -343,14 +347,15 @@ module TypeScript.Services {
|
||||||
public reportStats() {
|
public reportStats() {
|
||||||
var bucketInfoArray = Object.keys(this.buckets).filter(name => name && name.charAt(0) === '_').map(name => {
|
var bucketInfoArray = Object.keys(this.buckets).filter(name => name && name.charAt(0) === '_').map(name => {
|
||||||
var entries = this.buckets[name];
|
var entries = this.buckets[name];
|
||||||
var documents = entries.getAllKeys().map((name) => {
|
var documents = [];
|
||||||
var entry = entries.lookup(name);
|
for (var i in entries) {
|
||||||
return {
|
var entry = entries[i];
|
||||||
name: name,
|
documents.push({
|
||||||
|
name: i,
|
||||||
refCount: entry.refCount,
|
refCount: entry.refCount,
|
||||||
references: entry.owners.slice(0)
|
references: entry.owners.slice(0)
|
||||||
};
|
});
|
||||||
});
|
}
|
||||||
documents.sort((x, y) => y.refCount - x.refCount);
|
documents.sort((x, y) => y.refCount - x.refCount);
|
||||||
return { bucket: name, documents: documents }
|
return { bucket: name, documents: documents }
|
||||||
});
|
});
|
||||||
|
@ -367,12 +372,12 @@ module TypeScript.Services {
|
||||||
referencedFiles: string[]= []): TypeScript.Document {
|
referencedFiles: string[]= []): TypeScript.Document {
|
||||||
|
|
||||||
var bucket = this.getBucketForCompilationSettings(compilationSettings, /*createIfMissing*/ true);
|
var bucket = this.getBucketForCompilationSettings(compilationSettings, /*createIfMissing*/ true);
|
||||||
var entry = bucket.lookup(filename);
|
var entry = bucket[filename];
|
||||||
if (!entry) {
|
if (!entry) {
|
||||||
var document = Document.create(compilationSettings, filename, scriptSnapshot, byteOrderMark, version, isOpen, referencedFiles);
|
var document = Document.create(compilationSettings, filename, scriptSnapshot, byteOrderMark, version, isOpen, referencedFiles);
|
||||||
|
|
||||||
entry = new DocumentRegistryEntry(document);
|
entry = new DocumentRegistryEntry(document);
|
||||||
bucket.add(filename, entry);
|
bucket[filename] = entry;
|
||||||
}
|
}
|
||||||
entry.refCount++;
|
entry.refCount++;
|
||||||
|
|
||||||
|
@ -391,7 +396,7 @@ module TypeScript.Services {
|
||||||
|
|
||||||
var bucket = this.getBucketForCompilationSettings(compilationSettings, /*createIfMissing*/ false);
|
var bucket = this.getBucketForCompilationSettings(compilationSettings, /*createIfMissing*/ false);
|
||||||
Debug.assert(bucket);
|
Debug.assert(bucket);
|
||||||
var entry = bucket.lookup(filename);
|
var entry = bucket[filename];
|
||||||
Debug.assert(entry);
|
Debug.assert(entry);
|
||||||
|
|
||||||
if (entry.document.isOpen === isOpen && entry.document.version === version) {
|
if (entry.document.isOpen === isOpen && entry.document.version === version) {
|
||||||
|
@ -406,12 +411,12 @@ module TypeScript.Services {
|
||||||
var bucket = this.getBucketForCompilationSettings(compilationSettings, false);
|
var bucket = this.getBucketForCompilationSettings(compilationSettings, false);
|
||||||
Debug.assert(bucket);
|
Debug.assert(bucket);
|
||||||
|
|
||||||
var entry = bucket.lookup(filename);
|
var entry = bucket[filename];
|
||||||
entry.refCount--;
|
entry.refCount--;
|
||||||
|
|
||||||
Debug.assert(entry.refCount >= 0);
|
Debug.assert(entry.refCount >= 0);
|
||||||
if (entry.refCount === 0) {
|
if (entry.refCount === 0) {
|
||||||
bucket.remove(filename);
|
delete bucket[filename];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue