introduce branded type for TypingsArray

This commit is contained in:
Vladimir Matveev 2016-08-17 16:42:05 -07:00
parent dbd5249ded
commit 3f18fbc145
4 changed files with 24 additions and 17 deletions

View File

@ -87,7 +87,7 @@ namespace ts {
return node.end - node.pos;
}
export function arrayIsEqualTo<T>(array1: T[], array2: T[], equaler?: (a: T, b: T) => boolean): boolean {
export function arrayIsEqualTo<T>(array1: ReadonlyArray<T>, array2: ReadonlyArray<T>, equaler?: (a: T, b: T) => boolean): boolean {
if (!array1 || !array2) {
return array1 === array2;
}

View File

@ -214,7 +214,6 @@ namespace ts.server {
switch (response.kind) {
case "set":
this.typingsCache.updateTypingsForProject(response.projectName, response.compilerOptions, response.typingOptions, response.typings);
project.setTypings(response.typings);
project.updateGraph();
break;
case "invalidate":

View File

@ -47,7 +47,7 @@ namespace ts.server {
*/
private projectStateVersion = 0;
private typingFiles: string[];
private typingFiles: TypingsArray;
constructor(
readonly projectKind: ProjectKind,
@ -226,18 +226,19 @@ namespace ts.server {
if (!this.languageServiceEnabled) {
return true;
}
const hasChanges = this.updateGraphWorker();
let hasChanges = this.updateGraphWorker();
const cachedTypings = this.projectService.typingsCache.getTypingsForProject(this);
if (this.setTypings(cachedTypings)) {
hasChanges = this.updateGraphWorker() || hasChanges;
}
if (hasChanges) {
if (this.setTypings(this.projectService.typingsCache.getTypingsForProject(this))) {
this.updateGraphWorker();
}
this.projectStructureVersion++;
}
return !hasChanges;
}
setTypings(typings: string[]): boolean {
if (typings === this.typingFiles) {
private setTypings(typings: TypingsArray): boolean {
if (arrayIsEqualTo(this.typingFiles, typings)) {
return false;
}
this.typingFiles = typings;

View File

@ -16,7 +16,7 @@ namespace ts.server {
class TypingsCacheEntry {
readonly typingOptions: TypingOptions;
readonly compilerOptions: CompilerOptions;
readonly typings: string[];
readonly typings: TypingsArray;
}
const emptyArray: any[] = [];
@ -43,9 +43,7 @@ namespace ts.server {
if ((arr1 || emptyArray).length === 0 && (arr2 || emptyArray).length === 0) {
return true;
}
/* tslint:disable:no-null-keyword */
const set: Map<boolean> = Object.create(null);
/* tslint:enable:no-null-keyword */
const set: Map<boolean> = createMap<boolean>();
let unique = 0;
for (const v of arr1) {
@ -77,24 +75,33 @@ namespace ts.server {
return opt1.allowJs != opt2.allowJs;
}
export interface TypingsArray extends ReadonlyArray<string> {
" __typingsArrayBrand": any;
}
function toTypingsArray(arr: string[]): TypingsArray {
arr.sort();
return <any>arr;
}
export class TypingsCache {
private readonly perProjectCache: Map<TypingsCacheEntry> = createMap<TypingsCacheEntry>();
constructor(private readonly installer: ITypingsInstaller) {
}
getTypingsForProject(project: Project): Path[] {
getTypingsForProject(project: Project): TypingsArray {
const typingOptions = getTypingOptionsForProjects(project);
if (!typingOptions.enableAutoDiscovery) {
return emptyArray;
return <any>emptyArray;
}
const entry = this.perProjectCache[project.getProjectName()];
if (!entry || typingOptionsChanged(typingOptions, entry.typingOptions) || compilerOptionsChanged(project.getCompilerOptions(), entry.compilerOptions)) {
this.installer.enqueueInstallTypingsRequest(project, typingOptions);
}
return entry ? entry.typings : emptyArray;
return entry ? entry.typings : <any>emptyArray;
}
invalidateCachedTypingsForProject(project: Project) {
@ -109,7 +116,7 @@ namespace ts.server {
this.perProjectCache[projectName] = {
compilerOptions,
typingOptions,
typings: newTypings
typings: toTypingsArray(newTypings)
};
}