- cache for transpiled code and diagnostics

This commit is contained in:
Eugene Zolenko 2017-02-07 18:46:44 -07:00
parent 74bafa142c
commit 93042e103e
3 changed files with 109 additions and 3 deletions

View File

@ -23,19 +23,24 @@
"lint": "tslint -c ./tslint.json src/*.ts",
"postinstall": "typings install"
},
"dependencies": {},
"dependencies": {
"graphlib": "^2.1.1",
"object-hash": "^1.1.5",
"rollup-pluginutils": "^2.0.1",
},
"peerDependencies": {
"typescript": "^2.1.5"
},
"devDependencies": {
"@alexlur/rollup-plugin-typescript": "^0.8.1",
"@types/graphlib": "^2.1.3",
"@types/node": "^6.0.53",
"@types/object-hash": "^0.5.28",
"glob": "^7.1.1",
"glob-fs": "^0.1.6",
"lodash": "^4.17.4",
"rimraf": "^2.5.4",
"rollup": "^0.41.4",
"rollup-pluginutils": "^2.0.1",
"tslib": "^1.5.0",
"tslint": "^4.1.1",
"typescript": "^2.1.5",

View File

@ -10,7 +10,9 @@ export default {
'fs',
'object-assign',
'rollup-pluginutils',
'typescript'
'typescript',
'graphlib',
'object-hash'
],
plugins: [

99
src/cache.ts Normal file
View File

@ -0,0 +1,99 @@
import * as ts from "typescript";
import * as graph from "graphlib";
import * as hash from "object-hash";
import * as fs from "fs";
interface ICode
{
code: string;
map: string;
}
interface INodeLabel
{
dirty?: boolean;
hash?: string;
}
export class Cache
{
private dependencyTree: graph.Graph;
private treeComplete: boolean = false;
constructor(private cacheRoot: string, private options: ts.CompilerOptions, rootFilenames: string[])
{
this.cacheRoot = `${this.cacheRoot}/${hash.sha1({ rootFilenames, options: this.options })}`;
fs.mkdirSync(this.cacheRoot);
let dependencyTreeFile = `${this.cacheRoot}/tree`;
if (fs.existsSync(dependencyTreeFile))
{
let data = fs.readFileSync(`${this.cacheRoot}/tree`, "utf8");
this.dependencyTree = graph.json.read(JSON.parse(data));
}
else
this.dependencyTree = new graph.Graph();
}
public setDependency(importee: string, importer: string): void
{
this.dependencyTree.setEdge(importer, importee);
}
public lastDependencySet()
{
this.treeComplete = true;
}
public markAsDirty(fileName: string, snapshot: ts.IScriptSnapshot)
{
this.dependencyTree.setNode(fileName, { dirty: true });
}
public isDirty(fileName: string, snapshot: ts.IScriptSnapshot): boolean
{
let label = this.dependencyTree.node(fileName) as INodeLabel;
// TODO: also if any dependencies are dirty
return label.dirty;
}
public getCompiled(fileName: string, snapshot: ts.IScriptSnapshot, transform: () => ICode | undefined): ICode | undefined
{
let path = this.makePath(fileName, snapshot);
if (!fs.existsSync(path) || this.isDirty(fileName, snapshot))
{
let data = transform();
this.setCompiled(path, fileName, snapshot, data);
return data;
}
return JSON.parse(fs.readFileSync(path, "utf8")) as ICode;
}
public getDiagnostics(fileName: string, snapshot: ts.IScriptSnapshot, check: () => ts.Diagnostic[]): ts.Diagnostic[]
{
}
private setDiagnostics(path: string, fileName: string, snapshot: ts.IScriptSnapshot, data: ts.Diagnostic[]): void
{
}
private setCompiled(path: string, fileName: string, snapshot: ts.IScriptSnapshot, data: ICode)
{
fs.writeFileSync(path, JSON.stringify(data));
this.markAsDirty(fileName, snapshot);
}
private makePath(fileName: string, snapshot: ts.IScriptSnapshot): string
{
let data = snapshot.getText(0, snapshot.getLength());
return `${this.cacheRoot}/${hash.sha1({ data, fileName })}`;
}
}