diff --git a/spec/compile-cache-spec.coffee b/spec/compile-cache-spec.coffee new file mode 100644 index 000000000..94910bb58 --- /dev/null +++ b/spec/compile-cache-spec.coffee @@ -0,0 +1,71 @@ +path = require 'path' +temp = require('temp').track() +Babel = require 'babel-core' +CoffeeScript = require 'coffee-script' +{TypeScriptSimple} = require 'typescript-simple' +CSON = require 'season' +CSONParser = require 'season/node_modules/cson-parser' +CompileCache = require '../src/compile-cache' + +describe 'CompileCache', -> + [atomHome, fixtures] = [] + + beforeEach -> + fixtures = atom.project.getPaths()[0] + atomHome = temp.mkdirSync('fake-atom-home') + + CSON.setCacheDir(null) + CompileCache.resetCacheStats() + + spyOn(Babel, 'transform').andReturn {code: 'the-babel-code'} + spyOn(CoffeeScript, 'compile').andReturn {js: 'the-coffee-code', v3SourceMap: {}} + spyOn(TypeScriptSimple::, 'compile').andReturn 'the-typescript-code' + spyOn(CSONParser, 'parse').andReturn {the: 'cson-data'} + + afterEach -> + CSON.setCacheDir(CompileCache.getCacheDirectory()) + CompileCache.setAtomHomeDirectory(process.env.ATOM_HOME) + + describe 'addPathToCache(filePath, atomHome)', -> + describe 'when the given file is plain javascript', -> + it 'does not compile or cache the file', -> + CompileCache.addPathToCache(path.join(fixtures, 'sample.js'), atomHome) + expect(CompileCache.getCacheStats()['.js']).toEqual {hits: 0, misses: 0} + + describe 'when the given file uses babel', -> + it 'compiles the file with babel and caches it', -> + CompileCache.addPathToCache(path.join(fixtures, 'babel', 'babel-comment.js'), atomHome) + expect(CompileCache.getCacheStats()['.js']).toEqual {hits: 0, misses: 1} + expect(Babel.transform.callCount).toBe 1 + + CompileCache.addPathToCache(path.join(fixtures, 'babel', 'babel-comment.js'), atomHome) + expect(CompileCache.getCacheStats()['.js']).toEqual {hits: 1, misses: 1} + expect(Babel.transform.callCount).toBe 1 + + describe 'when the given file is coffee-script', -> + it 'compiles the file with coffee-script and caches it', -> + CompileCache.addPathToCache(path.join(fixtures, 'coffee.coffee'), atomHome) + expect(CompileCache.getCacheStats()['.coffee']).toEqual {hits: 0, misses: 1} + expect(CoffeeScript.compile.callCount).toBe 1 + + CompileCache.addPathToCache(path.join(fixtures, 'coffee.coffee'), atomHome) + expect(CompileCache.getCacheStats()['.coffee']).toEqual {hits: 1, misses: 1} + expect(CoffeeScript.compile.callCount).toBe 1 + + describe 'when the given file is typescript', -> + it 'compiles the file with typescript and caches it', -> + CompileCache.addPathToCache(path.join(fixtures, 'typescript', 'valid.ts'), atomHome) + expect(CompileCache.getCacheStats()['.ts']).toEqual {hits: 0, misses: 1} + expect(TypeScriptSimple::compile.callCount).toBe 1 + + CompileCache.addPathToCache(path.join(fixtures, 'typescript', 'valid.ts'), atomHome) + expect(CompileCache.getCacheStats()['.ts']).toEqual {hits: 1, misses: 1} + expect(TypeScriptSimple::compile.callCount).toBe 1 + + describe 'when the given file is CSON', -> + it 'compiles the file to JSON and caches it', -> + CompileCache.addPathToCache(path.join(fixtures, 'cson.cson'), atomHome) + expect(CSONParser.parse.callCount).toBe 1 + + CompileCache.addPathToCache(path.join(fixtures, 'cson.cson'), atomHome) + expect(CSONParser.parse.callCount).toBe 1 diff --git a/src/compile-cache.js b/src/compile-cache.js index 63ba008ae..6c8c6cb88 100644 --- a/src/compile-cache.js +++ b/src/compile-cache.js @@ -10,21 +10,9 @@ var COMPILERS = { '.coffee': require('./coffee-script') } +var cacheStats = {} var cacheDirectory = null -Object.keys(COMPILERS).forEach(function (extension) { - var compiler = COMPILERS[extension] - - Object.defineProperty(require.extensions, extension, { - enumerable: true, - writable: false, - value: function (module, filePath) { - var code = compileFileAtPath(compiler, filePath, extension) - return module._compile(code, filePath) - } - }) -}) - exports.setAtomHomeDirectory = function (atomHome) { var cacheDir = path.join(atomHome, 'compile-cache') if (process.env.USER === 'root' && process.env.SUDO_USER && process.env.SUDO_USER !== process.env.USER) { @@ -46,7 +34,10 @@ exports.addPathToCache = function (filePath, atomHome) { var extension = path.extname(filePath) if (extension === '.cson') { - CSON = CSON || require('season') + if (!CSON) { + CSON = require('season') + CSON.setCacheDir(this.getCacheDirectory()) + } CSON.readFileSync(filePath) } else { var compiler = COMPILERS[extension] @@ -56,12 +47,28 @@ exports.addPathToCache = function (filePath, atomHome) { } } +exports.getCacheStats = function () { + return cacheStats +} + +exports.resetCacheStats = function () { + Object.keys(COMPILERS).forEach(function (extension) { + cacheStats[extension] = { + hits: 0, + misses: 0 + } + }) +} + function compileFileAtPath (compiler, filePath, extension) { var sourceCode = fs.readFileSync(filePath, 'utf8') if (compiler.shouldCompile(sourceCode, filePath)) { var cachePath = compiler.getCachePath(sourceCode, filePath) var compiledCode = readCachedJavascript(cachePath) - if (compiledCode == null) { + if (compiledCode != null) { + cacheStats[extension].hits++ + } else { + cacheStats[extension].misses++ compiledCode = addSourceURL(compiler.compile(sourceCode, filePath), filePath) writeCachedJavascript(cachePath, compiledCode) } @@ -139,3 +146,18 @@ Object.defineProperty(Error, 'prepareStackTrace', { enumerable: true, writable: false }) + +Object.keys(COMPILERS).forEach(function (extension) { + var compiler = COMPILERS[extension] + + Object.defineProperty(require.extensions, extension, { + enumerable: true, + writable: false, + value: function (module, filePath) { + var code = compileFileAtPath(compiler, filePath, extension) + return module._compile(code, filePath) + } + }) +}) + +exports.resetCacheStats()