Use also mtime to validate source file cache

This commit is contained in:
Alex Dima
2019-01-07 11:58:25 +01:00
parent a1a6c1e801
commit ec4652f1cc
2 changed files with 72 additions and 22 deletions

View File

@@ -547,14 +547,24 @@ export class FSProvider {
public existsSync(filePath: string): boolean {
return fs.existsSync(filePath);
}
public statSync(filePath: string): fs.Stats {
return fs.statSync(filePath);
}
public readFileSync(_moduleId: string, filePath: string): Buffer {
return fs.readFileSync(filePath);
}
}
class CacheEntry {
constructor(
public readonly sourceFile: ts.SourceFile,
public readonly mtime: number
) {}
}
export class DeclarationResolver {
private _sourceFileCache: { [moduleId: string]: ts.SourceFile | null; };
private _sourceFileCache: { [moduleId: string]: CacheEntry | null; };
constructor(private readonly _fsProvider: FSProvider) {
this._sourceFileCache = Object.create(null);
@@ -565,32 +575,51 @@ export class DeclarationResolver {
}
public getDeclarationSourceFile(moduleId: string): ts.SourceFile | null {
if (this._sourceFileCache[moduleId]) {
// Since we cannot trust file watching to invalidate the cache, check also the mtime
const fileName = this._getFileName(moduleId);
const mtime = this._fsProvider.statSync(fileName).mtime.getTime();
if (this._sourceFileCache[moduleId]!.mtime !== mtime) {
this._sourceFileCache[moduleId] = null;
}
}
if (!this._sourceFileCache[moduleId]) {
this._sourceFileCache[moduleId] = this._getDeclarationSourceFile(moduleId);
}
return this._sourceFileCache[moduleId];
return this._sourceFileCache[moduleId] ? this._sourceFileCache[moduleId]!.sourceFile : null;
}
private _getDeclarationSourceFile(moduleId: string): ts.SourceFile | null {
private _getFileName(moduleId: string): string {
if (/\.d\.ts$/.test(moduleId)) {
const fileName = path.join(SRC, moduleId);
if (!this._fsProvider.existsSync(fileName)) {
return null;
}
const fileContents = this._fsProvider.readFileSync(moduleId, fileName).toString();
return ts.createSourceFile(fileName, fileContents, ts.ScriptTarget.ES5);
return path.join(SRC, moduleId);
}
const fileName = path.join(SRC, `${moduleId}.ts`);
return path.join(SRC, `${moduleId}.ts`);
}
private _getDeclarationSourceFile(moduleId: string): CacheEntry | null {
const fileName = this._getFileName(moduleId);
if (!this._fsProvider.existsSync(fileName)) {
return null;
}
const mtime = this._fsProvider.statSync(fileName).mtime.getTime();
if (/\.d\.ts$/.test(moduleId)) {
// const mtime = this._fsProvider.statFileSync()
const fileContents = this._fsProvider.readFileSync(moduleId, fileName).toString();
return new CacheEntry(
ts.createSourceFile(fileName, fileContents, ts.ScriptTarget.ES5),
mtime
);
}
const fileContents = this._fsProvider.readFileSync(moduleId, fileName).toString();
const fileMap: IFileMap = {
'file.ts': fileContents
};
const service = ts.createLanguageService(new TypeScriptLanguageServiceHost({}, fileMap, {}));
const text = service.getEmitOutput('file.ts', true).outputFiles[0].text;
return ts.createSourceFile(fileName, text, ts.ScriptTarget.ES5);
return new CacheEntry(
ts.createSourceFile(fileName, text, ts.ScriptTarget.ES5),
mtime
);
}
}