From 93042e103e2fbcb9154e5e65791fe1bf76f57b63 Mon Sep 17 00:00:00 2001 From: Eugene Zolenko Date: Tue, 7 Feb 2017 18:46:44 -0700 Subject: [PATCH] - cache for transpiled code and diagnostics --- package.json | 9 ++++- rollup.config.js | 4 +- src/cache.ts | 99 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 109 insertions(+), 3 deletions(-) create mode 100644 src/cache.ts diff --git a/package.json b/package.json index d3113ca..d90553b 100644 --- a/package.json +++ b/package.json @@ -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", diff --git a/rollup.config.js b/rollup.config.js index ff8c2c4..0264deb 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -10,7 +10,9 @@ export default { 'fs', 'object-assign', 'rollup-pluginutils', - 'typescript' + 'typescript', + 'graphlib', + 'object-hash' ], plugins: [ diff --git a/src/cache.ts b/src/cache.ts new file mode 100644 index 0000000..e13c792 --- /dev/null +++ b/src/cache.ts @@ -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 })}`; + } +}