mirror of
https://github.com/pulsar-edit/pulsar.git
synced 2024-11-10 10:17:11 +03:00
First pass at per-package transpilation
This commit is contained in:
parent
0860f354ca
commit
ad448184b4
@ -7,12 +7,24 @@
|
||||
|
||||
var path = require('path')
|
||||
var fs = require('fs-plus')
|
||||
|
||||
var PackageTranspilationRegistry = require('./package-transpilation-registry')
|
||||
var CSON = null
|
||||
|
||||
var packageTranspilationRegistry = new PackageTranspilationRegistry()
|
||||
|
||||
var COMPILERS = {
|
||||
'.js': require('./babel'),
|
||||
'.ts': require('./typescript'),
|
||||
'.coffee': require('./coffee-script')
|
||||
'.js': packageTranspilationRegistry.wrapTranspiler(require('./babel')),
|
||||
'.ts': packageTranspilationRegistry.wrapTranspiler(require('./typescript')),
|
||||
'.coffee': packageTranspilationRegistry.wrapTranspiler(require('./coffee-script'))
|
||||
}
|
||||
|
||||
exports.addTranspilerConfigForPath = function (packagePath, config) {
|
||||
packageTranspilationRegistry.addTranspilerConfigForPath(packagePath, config)
|
||||
}
|
||||
|
||||
exports.removeTranspilerConfigForPath = function (packagePath) {
|
||||
packageTranspilationRegistry.removeTranspilerConfigForPath(packagePath)
|
||||
}
|
||||
|
||||
var cacheStats = {}
|
||||
|
122
src/package-transpilation-registry.js
Normal file
122
src/package-transpilation-registry.js
Normal file
@ -0,0 +1,122 @@
|
||||
var crypto = require('crypto')
|
||||
var fs = require('fs')
|
||||
var path = require('path')
|
||||
|
||||
var Resolve = null
|
||||
|
||||
function PackageTranspilationRegistry () {
|
||||
this.configByPackagePath = {}
|
||||
this.configByFilePath = {}
|
||||
this.transpilerPaths = {}
|
||||
this.transpilerHashes = {}
|
||||
}
|
||||
|
||||
PackageTranspilationRegistry.prototype.addTranspilerConfigForPath = function (packagePath, config) {
|
||||
packagePath = fs.realpathSync(packagePath)
|
||||
this.configByPackagePath[packagePath] = Object.assign({}, config, {
|
||||
path: packagePath
|
||||
})
|
||||
}
|
||||
|
||||
PackageTranspilationRegistry.prototype.removeTranspilerConfigForPath = function (packagePath) {
|
||||
packagePath = fs.realpathSync(packagePath)
|
||||
delete this.configByPackagePath[path]
|
||||
}
|
||||
|
||||
// Wraps the transpiler in an object with the same interface
|
||||
// that falls back to the original transpiler implementation if and
|
||||
// only if a package hasn't registered its desire to transpile its own source.
|
||||
PackageTranspilationRegistry.prototype.wrapTranspiler = function (transpiler) {
|
||||
var self = this
|
||||
return {
|
||||
getCachePath: function (sourceCode, filePath) {
|
||||
var config = self.getPackageTranspilerConfigForFilePath(filePath)
|
||||
if (config) {
|
||||
return self.getCachePath(sourceCode, filePath, config)
|
||||
}
|
||||
|
||||
return transpiler.getCachePath(sourceCode, filePath)
|
||||
},
|
||||
|
||||
compile: function (sourceCode, filePath) {
|
||||
var config = self.getPackageTranspilerConfigForFilePath(filePath)
|
||||
if (config) {
|
||||
return self.transpileWithPackageTranspiler(sourceCode, filePath, config)
|
||||
}
|
||||
|
||||
return transpiler.compile(sourceCode, filePath)
|
||||
},
|
||||
|
||||
shouldCompile: function (sourceCode, filePath) {
|
||||
if (self.transpilerPaths[filePath]) {
|
||||
return false
|
||||
}
|
||||
var config = self.getPackageTranspilerConfigForFilePath(filePath)
|
||||
if (config) {
|
||||
return true
|
||||
}
|
||||
|
||||
return transpiler.shouldCompile(sourceCode, filePath)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PackageTranspilationRegistry.prototype.getPackageTranspilerConfigForFilePath = function (filePath) {
|
||||
if (this.configByFilePath[filePath] !== undefined) return this.configByFilePath[filePath]
|
||||
|
||||
var config = null
|
||||
var thisPath = filePath
|
||||
var lastPath = null
|
||||
// Iterate parents from the file path to the root, checking at each level
|
||||
// to see if a package manages transpilation for that directory.
|
||||
// This means searching for a config for `/path/to/file/here.js` only
|
||||
// only iterates four times, even if there are hundreds of configs registered.
|
||||
while (thisPath !== lastPath) { // until we reach the root
|
||||
if (config = this.configByPackagePath[thisPath]) {
|
||||
this.configByFilePath[filePath] = config
|
||||
return config
|
||||
}
|
||||
|
||||
lastPath = thisPath
|
||||
thisPath = path.resolve(thisPath, '..')
|
||||
}
|
||||
|
||||
this.configByFilePath[filePath] = null
|
||||
return null
|
||||
}
|
||||
|
||||
PackageTranspilationRegistry.prototype.getCachePath = function (sourceCode, filePath, config) {
|
||||
var transpilerPath = path.join(config.path, config.transpiler)
|
||||
var transpilerSource = config._transpilerSource || fs.readFileSync(transpilerPath, 'utf8')
|
||||
config._transpilerSource = transpilerSource
|
||||
return path.join(
|
||||
"package-transpile",
|
||||
crypto
|
||||
.createHash('sha1')
|
||||
.update(transpilerSource, 'utf8')
|
||||
.update(sourceCode, 'utf8')
|
||||
.digest('hex')
|
||||
)
|
||||
}
|
||||
|
||||
PackageTranspilationRegistry.prototype.transpileWithPackageTranspiler = function (sourceCode, filePath) {
|
||||
var config = this.configByFilePath[filePath]
|
||||
|
||||
Resolve = Resolve || require('resolve')
|
||||
var transpilerPath = Resolve.sync(config.transpiler, {basedir: config.path, extensions: Object.keys(require.extensions)})
|
||||
if (transpilerPath) {
|
||||
this.transpilerPaths[transpilerPath] = true
|
||||
var transpiler = require(transpilerPath)
|
||||
var result = transpiler.compile(sourceCode, filePath)
|
||||
if (result === undefined) {
|
||||
return sourceCode
|
||||
} else {
|
||||
return result
|
||||
}
|
||||
} else {
|
||||
var err = new Error("Could not find transpiler '" + config.transpiler + "' from '" + config.path + "'")
|
||||
console.error(err)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = PackageTranspilationRegistry
|
@ -6,6 +6,7 @@ CSON = require 'season'
|
||||
fs = require 'fs-plus'
|
||||
{Emitter, CompositeDisposable} = require 'event-kit'
|
||||
|
||||
CompileCache = require './compile-cache'
|
||||
ModuleCache = require './module-cache'
|
||||
ScopedProperties = require './scoped-properties'
|
||||
BufferedProcess = require './buffered-process'
|
||||
@ -86,6 +87,7 @@ class Package
|
||||
@loadStylesheets()
|
||||
@registerDeserializerMethods()
|
||||
@activateCoreStartupServices()
|
||||
@registerTranspilerConfig()
|
||||
@configSchemaRegisteredOnLoad = @registerConfigSchemaFromMetadata()
|
||||
@settingsPromise = @loadSettings()
|
||||
if @shouldRequireMainModuleOnLoad() and not @mainModule?
|
||||
@ -94,6 +96,9 @@ class Package
|
||||
@handleError("Failed to load the #{@name} package", error)
|
||||
this
|
||||
|
||||
unload: ->
|
||||
@unregisterTranspilerConfig()
|
||||
|
||||
shouldRequireMainModuleOnLoad: ->
|
||||
not (
|
||||
@metadata.deserializers? or
|
||||
@ -247,6 +252,16 @@ class Package
|
||||
@activationDisposables.add @packageManager.serviceHub.consume(name, version, @mainModule[methodName].bind(@mainModule))
|
||||
return
|
||||
|
||||
registerTranspilerConfig: ->
|
||||
if @metadata.atomTranspilers
|
||||
for transpiler in @metadata.atomTranspilers
|
||||
CompileCache.addTranspilerConfigForPath(@path, transpiler)
|
||||
|
||||
unregisterTranspilerConfig: ->
|
||||
if @metadata.atomTranspilers
|
||||
for transpiler in @metadata.atomTranspilers
|
||||
CompileCache.removeTranspilerConfigForPath(@path)
|
||||
|
||||
loadKeymaps: ->
|
||||
if @bundledPackage and @packageManager.packagesCache[@name]?
|
||||
@keymaps = (["#{@packageManager.resourcePath}#{path.sep}#{keymapPath}", keymapObject] for keymapPath, keymapObject of @packageManager.packagesCache[@name].keymaps)
|
||||
|
Loading…
Reference in New Issue
Block a user