Reduce the amount of shared code between CompilerPlugin's and LinterPlugin's

This commit is contained in:
Slava Kim
2015-04-17 18:30:39 -07:00
committed by David Glasser
parent e7811a67fa
commit ee4bd65fa7
6 changed files with 402 additions and 369 deletions

View File

@@ -1,17 +1,14 @@
var archinfo = require('./archinfo.js');
var colonConverter = require('./colon-converter.js');
var files = require('./files.js');
var linker = require('./linker.js');
var compiler = require('./compiler.js');
var _ = require('underscore');
exports.BuildPluginDefintion = function (options, factoryFunction) {
var self = this;
self.id = options.id;
self.type = options.type;
self.extensions = options.extensions.slice();
self.archMatching = options.archMatching;
self.isTemplate = !! options.isTemplate;
self.buildPluginClass = options.buildPluginClass;
self.factoryFunction = factoryFunction;
};
_.extend(exports.BuildPluginDefintion.prototype, {
@@ -20,315 +17,11 @@ _.extend(exports.BuildPluginDefintion.prototype, {
// XXX BBP proper error handling --- this is running user-supplied plugin
// code
var userPlugin = self.factoryFunction();
return new BuildPlugin(self, userPlugin);
return new self.buildPluginClass(self, userPlugin);
},
relevantForArch: function (arch) {
var self = this;
return ! self.archMatching || archinfo.matches(arch, self.archMatching);
},
getInputFileClass: function () {
throw new Error("getInputFileClass should be implemented by a subclass of BuildPluginDefinition");
}
});
var BuildPlugin = function (pluginDefinition, userPlugin) {
var self = this;
// The actual object returned from the user-supplied factory.
self.userPlugin = userPlugin;
self.pluginDefinition = pluginDefinition;
};
_.extend(BuildPlugin.prototype, {
// XXX BBP full docs
run: function (resourceSlots) {
var self = this;
var InputFile = self.pluginDefinition.getInputFileClass();
var inputFiles = _.map(resourceSlots, function (resourceSlot) {
return new InputFile(resourceSlot);
});
// XXX BBP proper error handling --- this is running user-supplied plugin
// code
self.userPlugin.processFilesForTarget(inputFiles);
}
});
exports.BuildPluginProcessor = function (options) {
var self = this;
self.type = options.type;
self.unibuilds = options.unibuilds;
self.arch = options.arch;
self.isopackCache = options.isopackCache;
// id -> {buildPlugin, resourceSlots}
self.buildPlugins = null;
};
_.extend(exports.BuildPluginProcessor.prototype, {
// XXX BBP don't re-instantiate buildPlugins on every rebuild
_loadPluginsAndInstantiatePlugins: function () {
var self = this;
self.buildPlugins = {};
_.each(self.unibuilds, function (unibuild) {
var isopack = unibuild.pkg;
isopack.ensurePluginsInitialized();
_.each(isopack.sourceProcessors[self.type], function (buildPlugin, id) {
if (_.has(self.buildPlugins, id)) {
throw Error("duplicate buildPlugin plugin ID! " + id);
}
self.buildPlugins[id] = {
buildPlugin: buildPlugin.instantiatePlugin(),
resourceSlots: []
};
});
});
},
runBuildPlugins: function () {
var self = this;
self._loadPluginsAndInstantiatePlugins();
var sourceBatches = _.map(self.unibuilds, function (unibuild) {
return new PackageSourceBatch(unibuild, self);
});
// Find out which files go with which buildPlugins.
_.each(sourceBatches, function (sourceBatch) {
_.each(sourceBatch.resourceSlots, function (resourceSlot) {
var buildPlugin = resourceSlot.buildPlugin;
// Skip non-sources.
if (! buildPlugin)
return;
if (! _.has(self.buildPlugins, buildPlugin.id)) {
throw Error("uninstantiated buildPlugin plugin " + buildPlugin.id);
}
self.buildPlugins[buildPlugin.id].resourceSlots.push(resourceSlot);
});
});
// Now actually run the handlers.
_.each(self.buildPlugins, function (buildPluginInfo, id) {
var buildPlugin = buildPluginInfo.buildPlugin;
var resourceSlots = buildPluginInfo.resourceSlots;
// Don't run buildPlugins with no files.
if (! resourceSlots.length)
return;
buildPlugin.run(resourceSlots);
});
return sourceBatches;
}
});
// XXX BBP doc
var ResourceSlot = function (unibuildResourceInfo,
buildPlugin,
packageSourceBatch) {
var self = this;
self.inputResource = unibuildResourceInfo; // XXX BBP prototype?
self.outputResources = [];
self.buildPlugin = buildPlugin;
self.packageSourceBatch = packageSourceBatch;
if (self.inputResource.type === "source") {
if (! buildPlugin) {
throw Error("no buildPlugin plugin for source? " +
JSON.stringify(unibuildResourceInfo));
}
} else {
if (buildPlugin) {
throw Error("buildPlugin plugin for non-source? " +
JSON.stringify(unibuildResourceInfo));
}
// Any resource that isn't handled by buildPlugin plugins just gets passed
// through.
self.outputResources.push(self.inputResource);
}
};
_.extend(ResourceSlot.prototype, {
// XXX BBP check args
addStylesheet: function (options) {
var self = this;
if (! self.buildPlugin)
throw Error("addStylesheet on non-source ResourceSlot?");
// XXX BBP this is wrong (eg totally broken for in app) and is in the wrong
// place
var unibuild = self.packageSourceBatch.unibuild;
var serveRoot;
if (unibuild.pkg.name) {
serveRoot = files.pathJoin('/packages/', unibuild.pkg.name);
} else {
serveRoot = '/';
}
// XXX BBP prototype?
self.outputResources.push({
type: "css",
refreshable: true,
data: new Buffer(files.convertToStandardLineEndings(options.data), 'utf8'),
servePath: colonConverter.convert(
files.pathJoin(
serveRoot,
// XXX BBP should we decide in our API that everything is / ?
files.convertToStandardPath(options.path, true)))
});
}
});
// XXX BBP ???
var PackageSourceBatch = function (unibuild, processor) {
var self = this;
self.type = processor.type;
self.unibuild = unibuild;
self.processor = processor;
var buildPluginsByExtension = self._getBuildPluginsByExtension();
self.resourceSlots = _.map(unibuild.resources, function (resource) {
var buildPlugin = null;
if (resource.type === "source") {
var basename = files.pathBasename(resource.path);
var parts = basename.split('.');
for (var i = 1; i < parts.length; i++) {
var extension = parts.slice(i).join('.');
if (_.has(buildPluginsByExtension, extension)) {
buildPlugin = buildPluginsByExtension[extension];
break;
}
}
if (! buildPlugin) {
// XXX BBP better error handling
throw Error("no plugin found for " + resource.path);
}
}
return new ResourceSlot(resource, buildPlugin, self);
});
};
_.extend(PackageSourceBatch.prototype, {
_getBuildPluginsByExtension: function () {
var self = this;
var isopack = self.unibuild.pkg;
// Packages always get plugins from themselves.
var activePluginPackages = [isopack];
// We don't use plugins from weak dependencies, because the ability to build
// a certain type of file shouldn't depend on whether or not some unrelated
// package in the target has a dependency. And we skip unordered
// dependencies, because it's not going to work to have circular build-time
// dependencies.
//
// eachUsedUnibuild takes care of pulling in implied dependencies for us
// (eg, templating from standard-app-packages).
//
// We pass archinfo.host here, not self.arch, because it may be more
// specific, and because plugins always have to run on the host
// architecture.
compiler.eachUsedUnibuild({
dependencies: self.unibuild.uses,
arch: archinfo.host(),
isopackCache: self.processor.isopackCache,
skipUnordered: true
}, function (otherUnibuild) {
if (! _.isEmpty(otherUnibuild.pkg.plugins)) {
activePluginPackages.push(otherUnibuild.pkg);
}
});
activePluginPackages = _.uniq(activePluginPackages);
var buildPluginsByExtension = {};
_.each(activePluginPackages, function (otherPkg) {
// self.type is "compiler" or "linter" or similar
_.each(otherPkg.sourceProcessors[self.type], function (buildPlugin, id) {
if (! buildPlugin.relevantForArch(self.processor.arch)) {
return;
}
_.each(buildPlugin.extensions, function (ext) {
if (_.has(buildPluginsByExtension, ext)) {
// XXX BBP use buildmessage
throw Error("duplicate extension " + JSON.stringify({
package: isopack.name,
ext: ext
}));
}
buildPluginsByExtension[ext] = buildPlugin;
});
});
});
return buildPluginsByExtension;
},
getResources: function () {
var self = this;
var resources = Array.prototype.concat.apply(
[],
_.pluck(self.resourceSlots, 'outputResources'));
return resources.concat(self._getPrelinkedJsResources());
},
// XXX BBP copied from Unibuild.getResources, which should get deleted
// XXX BBP this should also support JS resources produced by buildPlugin plugins
_getPrelinkedJsResources: function () {
var self = this;
var isopackCache = self.processor.isopackCache;
var bundleArch = self.processor.arch;
if (! archinfo.matches(bundleArch, self.unibuild.arch))
throw new Error(
"unibuild of arch '" + self.unibuild.arch + "' does not support '" +
bundleArch + "'?");
// Compute imports by merging the exports of all of the packages we
// use. Note that in the case of conflicting symbols, later packages get
// precedence.
//
// We don't get imports from unordered dependencies (since they may not be
// defined yet) or from weak/debugOnly dependencies (because the meaning of
// a name shouldn't be affected by the non-local decision of whether or not
// an unrelated package in the target depends on something).
var imports = {}; // map from symbol to supplying package name
var addImportsForUnibuild = function (depUnibuild) {
_.each(depUnibuild.packageVariables, function (symbol) {
// Slightly hacky implementation of test-only exports.
if (symbol.export === true ||
(symbol.export === "tests" && self.unibuild.pkg.isTest))
imports[symbol.name] = depUnibuild.pkg.name;
});
};
compiler.eachUsedUnibuild({
dependencies: self.unibuild.uses,
arch: bundleArch,
isopackCache: isopackCache,
skipUnordered: true,
skipDebugOnly: true
}, addImportsForUnibuild);
// Phase 2 link
var isApp = ! self.unibuild.pkg.name;
var files = linker.link({
imports: imports,
useGlobalNamespace: isApp,
// XXX report an error if there is a package called global-imports
importStubServePath: isApp && '/packages/global-imports.js',
prelinkFiles: self.unibuild.prelinkFiles,
packageVariables: self.unibuild.packageVariables,
includeSourceMapInstructions: archinfo.matches(self.unibuild.arch, "web"),
name: self.unibuild.pkg.name || null
});
// Add each output as a resource
var jsResources = _.map(files, function (file) {
return {
type: "js",
data: new Buffer(file.source, 'utf8'), // XXX encoding
servePath: file.servePath,
sourceMap: file.sourceMap
};
});
return jsResources;
}
});
@@ -337,25 +30,24 @@ _.extend(PackageSourceBatch.prototype, {
// XXX BBP decide if the API always presents / to the code (it probably
// should because you're not supposed to do your own IO anyway)
exports.InputFile = function (resourceSlot) {
var self = this;
// We use underscored attributes here because this is user-visible code and we
// don't want users to be accessing anything that we don't document.
self._resourceSlot = resourceSlot;
};
_.extend(exports.InputFile.prototype, {
// XXX BBP refine this API and document it
getContentsAsBuffer: function () {
var self = this;
return self._resourceSlot.inputResource.data;
throw new Error("Not Implemented");
},
// XXX is this null for app?
getPackageName: function () {
throw new Error("Not Implemented");
},
getPathInPackage: function () {
throw new Error("Not Implemented");
},
getContentsAsString: function () {
var self = this;
return self.getContentsAsBuffer().toString('utf8');
},
getPathInPackage: function () {
var self = this;
return self._resourceSlot.inputResource.path;
},
getBasename: function () {
var self = this;
return files.pathBasename(self.getPathInPackage());
@@ -364,13 +56,15 @@ _.extend(exports.InputFile.prototype, {
var self = this;
return files.pathDirname(self.getPathInPackage());
},
// XXX is this null for app?
getPackageName: function () {
var self = this;
return self._resourceSlot.packageSourceBatch.unibuild.pkg.name;
},
error: function (options) {
var self = this;
var relPath = self.getPathInPackage();
buildmessage.error(options.message || ("error building " + relPath), {
file: options.sourcePath || relPath,
line: options.line ? options.line : undefined,
column: options.column ? options.column : undefined,
func: options.func ? options.func : undefined
});
// XXX BBP handle errors here
}
});

View File

@@ -166,7 +166,7 @@ var Profile = require('./profile.js').Profile;
var compiler = require('./compiler.js');
var packageVersionParser = require('./package-version-parser.js');
var colonConverter = require('./colon-converter.js');
var buildPluginModule = require('./build-plugin.js');
var compilerPluginModule = require('./compiler-plugin.js');
// files to ignore when bundling. node has no globs, so use regexps
exports.ignoreFiles = [
@@ -664,8 +664,7 @@ _.extend(Target.prototype, {
_runCompilerPlugins: function () {
var self = this;
var processor = new buildPluginModule.BuildPluginProcessor({
type: "compiler",
var processor = new compilerPluginModule.CompilerPluginProcessor({
unibuilds: self.unibuilds,
arch: self.arch,
isopackCache: self.isopackCache

View File

@@ -1,29 +1,122 @@
var archinfo = require('./archinfo.js');
var buildPluginModule = require('./build-plugin.js');
var colonConverter = require('./colon-converter.js');
var files = require('./files.js');
var compiler = require('./compiler.js');
var linker = require('./linker.js');
var util = require('util');
var _ = require('underscore');
exports.CompilerPluginDefinition = function (options, factory) {
buildPluginModule.BuildPluginDefintion.call(this, _.extend({
type: "compiler"
}, options), factory);
exports.CompilerPlugin = function (pluginDefinition, userPlugin) {
var self = this;
// The actual object returned from the user-supplied factory.
self.userPlugin = userPlugin;
self.pluginDefinition = pluginDefinition;
};
_.extend(exports.CompilerPlugin.prototype, {
// XXX BBP full docs
run: function (resourceSlots) {
var self = this;
util.inherits(exports.CompilerPluginDefinition, buildPluginModule.BuildPluginDefintion);
var inputFiles = _.map(resourceSlots, function (resourceSlot) {
return new InputFile(resourceSlot);
});
_.extend(exports.CompilerPluginDefinition.prototype, {
getInputFileClass: function () {
return InputFile;
// XXX BBP proper error handling --- this is running user-supplied plugin
// code
self.userPlugin.processFilesForTarget(inputFiles);
}
});
var InputFile = function () {
buildPluginModule.InputFile.apply(this, arguments);
exports.CompilerPluginProcessor = function (options) {
var self = this;
self.unibuilds = options.unibuilds;
self.arch = options.arch;
self.isopackCache = options.isopackCache;
// id -> {buildPlugin, resourceSlots}
self.buildPlugins = null;
};
_.extend(exports.CompilerPluginProcessor.prototype, {
// XXX BBP don't re-instantiate buildPlugins on every rebuild
_loadPluginsAndInstantiatePlugins: function () {
var self = this;
self.buildPlugins = {};
_.each(self.unibuilds, function (unibuild) {
var isopack = unibuild.pkg;
isopack.ensurePluginsInitialized();
_.each(isopack.sourceProcessors.compiler, function (buildPlugin, id) {
if (_.has(self.buildPlugins, id)) {
throw Error("duplicate buildPlugin plugin ID! " + id);
}
self.buildPlugins[id] = {
buildPlugin: buildPlugin.instantiatePlugin(),
resourceSlots: []
};
});
});
},
runBuildPlugins: function () {
var self = this;
self._loadPluginsAndInstantiatePlugins();
var sourceBatches = _.map(self.unibuilds, function (unibuild) {
return new PackageSourceBatch(unibuild, self);
});
// Find out which files go with which buildPlugins.
_.each(sourceBatches, function (sourceBatch) {
_.each(sourceBatch.resourceSlots, function (resourceSlot) {
var buildPlugin = resourceSlot.buildPlugin;
// Skip non-sources.
if (! buildPlugin)
return;
if (! _.has(self.buildPlugins, buildPlugin.id)) {
throw Error("uninstantiated buildPlugin plugin " + buildPlugin.id);
}
self.buildPlugins[buildPlugin.id].resourceSlots.push(resourceSlot);
});
});
// Now actually run the handlers.
_.each(self.buildPlugins, function (buildPluginInfo, id) {
var buildPlugin = buildPluginInfo.buildPlugin;
var resourceSlots = buildPluginInfo.resourceSlots;
// Don't run buildPlugins with no files.
if (! resourceSlots.length)
return;
buildPlugin.run(resourceSlots);
});
return sourceBatches;
}
});
var InputFile = function (resourceSlot) {
var self = this;
// We use underscored attributes here because this is user-visible code and we
// don't want users to be accessing anything that we don't document.
self._resourceSlot = resourceSlot;
};
util.inherits(InputFile, buildPluginModule.InputFile);
_.extend(InputFile.prototype, {
getContentsAsBuffer: function () {
var self = this;
return self._resourceSlot.inputResource.data;
},
// XXX is this null for app?
getPackageName: function () {
var self = this;
return self._resourceSlot.packageSourceBatch.unibuild.pkg.name;
},
getPathInPackage: function () {
var self = this;
return self._resourceSlot.inputResource.path;
},
// XXX BBP remove these, they are duplicated in build-plugin.js
xxxContentsAsBuffer: function () {
var self = this;
@@ -53,3 +146,213 @@ _.extend(InputFile.prototype, {
}
});
// XXX BBP doc
var ResourceSlot = function (unibuildResourceInfo,
buildPlugin,
packageSourceBatch) {
var self = this;
self.inputResource = unibuildResourceInfo; // XXX BBP prototype?
self.outputResources = [];
self.buildPlugin = buildPlugin;
self.packageSourceBatch = packageSourceBatch;
if (self.inputResource.type === "source") {
if (! buildPlugin) {
throw Error("no buildPlugin plugin for source? " +
JSON.stringify(unibuildResourceInfo));
}
} else {
if (buildPlugin) {
throw Error("buildPlugin plugin for non-source? " +
JSON.stringify(unibuildResourceInfo));
}
// Any resource that isn't handled by buildPlugin plugins just gets passed
// through.
self.outputResources.push(self.inputResource);
}
};
_.extend(ResourceSlot.prototype, {
// XXX BBP check args
addStylesheet: function (options) {
var self = this;
if (! self.buildPlugin)
throw Error("addStylesheet on non-source ResourceSlot?");
// XXX BBP this is wrong (eg totally broken for in app) and is in the wrong
// place
var unibuild = self.packageSourceBatch.unibuild;
var serveRoot;
if (unibuild.pkg.name) {
serveRoot = files.pathJoin('/packages/', unibuild.pkg.name);
} else {
serveRoot = '/';
}
// XXX BBP prototype?
self.outputResources.push({
type: "css",
refreshable: true,
data: new Buffer(files.convertToStandardLineEndings(options.data), 'utf8'),
servePath: colonConverter.convert(
files.pathJoin(
serveRoot,
// XXX BBP should we decide in our API that everything is / ?
files.convertToStandardPath(options.path, true)))
});
}
});
// XXX BBP ???
var PackageSourceBatch = function (unibuild, processor) {
var self = this;
self.unibuild = unibuild;
self.processor = processor;
var buildPluginsByExtension = self._getBuildPluginsByExtension();
self.resourceSlots = _.map(unibuild.resources, function (resource) {
var buildPlugin = null;
if (resource.type === "source") {
var basename = files.pathBasename(resource.path);
var parts = basename.split('.');
for (var i = 1; i < parts.length; i++) {
var extension = parts.slice(i).join('.');
if (_.has(buildPluginsByExtension, extension)) {
buildPlugin = buildPluginsByExtension[extension];
break;
}
}
if (! buildPlugin) {
// XXX BBP better error handling
throw Error("no plugin found for " + resource.path);
}
}
return new ResourceSlot(resource, buildPlugin, self);
});
};
_.extend(PackageSourceBatch.prototype, {
_getBuildPluginsByExtension: function () {
var self = this;
var isopack = self.unibuild.pkg;
// Packages always get plugins from themselves.
var activePluginPackages = [isopack];
// We don't use plugins from weak dependencies, because the ability to build
// a certain type of file shouldn't depend on whether or not some unrelated
// package in the target has a dependency. And we skip unordered
// dependencies, because it's not going to work to have circular build-time
// dependencies.
//
// eachUsedUnibuild takes care of pulling in implied dependencies for us
// (eg, templating from standard-app-packages).
//
// We pass archinfo.host here, not self.arch, because it may be more
// specific, and because plugins always have to run on the host
// architecture.
compiler.eachUsedUnibuild({
dependencies: self.unibuild.uses,
arch: archinfo.host(),
isopackCache: self.processor.isopackCache,
skipUnordered: true
}, function (otherUnibuild) {
if (! _.isEmpty(otherUnibuild.pkg.plugins)) {
activePluginPackages.push(otherUnibuild.pkg);
}
});
activePluginPackages = _.uniq(activePluginPackages);
var buildPluginsByExtension = {};
_.each(activePluginPackages, function (otherPkg) {
// self.type is "compiler" or "linter" or similar
_.each(otherPkg.sourceProcessors.compiler, function (buildPlugin, id) {
if (! buildPlugin.relevantForArch(self.processor.arch)) {
return;
}
_.each(buildPlugin.extensions, function (ext) {
if (_.has(buildPluginsByExtension, ext)) {
// XXX BBP use buildmessage
throw Error("duplicate extension " + JSON.stringify({
package: isopack.name,
ext: ext
}));
}
buildPluginsByExtension[ext] = buildPlugin;
});
});
});
return buildPluginsByExtension;
},
getResources: function () {
var self = this;
var resources = Array.prototype.concat.apply(
[],
_.pluck(self.resourceSlots, 'outputResources'));
return resources.concat(self._getPrelinkedJsResources());
},
// XXX BBP copied from Unibuild.getResources, which should get deleted
// XXX BBP this should also support JS resources produced by buildPlugin plugins
_getPrelinkedJsResources: function () {
var self = this;
var isopackCache = self.processor.isopackCache;
var bundleArch = self.processor.arch;
if (! archinfo.matches(bundleArch, self.unibuild.arch))
throw new Error(
"unibuild of arch '" + self.unibuild.arch + "' does not support '" +
bundleArch + "'?");
// Compute imports by merging the exports of all of the packages we
// use. Note that in the case of conflicting symbols, later packages get
// precedence.
//
// We don't get imports from unordered dependencies (since they may not be
// defined yet) or from weak/debugOnly dependencies (because the meaning of
// a name shouldn't be affected by the non-local decision of whether or not
// an unrelated package in the target depends on something).
var imports = {}; // map from symbol to supplying package name
var addImportsForUnibuild = function (depUnibuild) {
_.each(depUnibuild.packageVariables, function (symbol) {
// Slightly hacky implementation of test-only exports.
if (symbol.export === true ||
(symbol.export === "tests" && self.unibuild.pkg.isTest))
imports[symbol.name] = depUnibuild.pkg.name;
});
};
compiler.eachUsedUnibuild({
dependencies: self.unibuild.uses,
arch: bundleArch,
isopackCache: isopackCache,
skipUnordered: true,
skipDebugOnly: true
}, addImportsForUnibuild);
// Phase 2 link
var isApp = ! self.unibuild.pkg.name;
var files = linker.link({
imports: imports,
useGlobalNamespace: isApp,
// XXX report an error if there is a package called global-imports
importStubServePath: isApp && '/packages/global-imports.js',
prelinkFiles: self.unibuild.prelinkFiles,
packageVariables: self.unibuild.packageVariables,
includeSourceMapInstructions: archinfo.matches(self.unibuild.arch, "web"),
name: self.unibuild.pkg.name || null
});
// Add each output as a resource
var jsResources = _.map(files, function (file) {
return {
type: "js",
data: new Buffer(file.source, 'utf8'), // XXX encoding
servePath: file.servePath,
sourceMap: file.sourceMap
};
});
return jsResources;
}
});

View File

@@ -231,6 +231,7 @@ var compileUnibuild = function (options) {
// XXX BBP redoc
var allHandlersWithPkgs = {};
var compilerPluginsByExtension = {};
var linterPluginsByExtension = {};
var sourceExtensions = {}; // maps source extensions to isTemplate
sourceExtensions['js'] = false;
@@ -307,6 +308,14 @@ var compileUnibuild = function (options) {
sourceExtensions[ext] = compilerPlugin.isTemplate;
});
});
// Iterate over the linters
_.each(otherPkg.sourceProcessors.linter, function (linterPlugin, id) {
_.each(linterPlugin.extensions, function (ext) {
linterPluginsByExtension[ext] = linterPluginsByExtension[ext] || [];
linterPluginsByExtension[ext].push(linterPlugin);
});
});
});
// *** Determine source files
@@ -362,11 +371,7 @@ var compileUnibuild = function (options) {
return JSON.stringify(srcmap);
};
_.each(sourceItems, function (source) {
var relPath = source.relPath;
var fileOptions = _.clone(source.fileOptions) || {};
var absPath = files.pathResolve(inputSourceArch.pkg.sourceRoot, relPath);
var filename = files.pathBasename(relPath);
var wrappedSourceItems = _.map(sourceItems, function (source) {
var fileWatchSet = new watch.WatchSet;
// readAndWatchFileWithHash returns an object carrying a buffer with the
// file-contents. The buffer contains the original data of the file (no EOL
@@ -374,8 +379,35 @@ var compileUnibuild = function (options) {
// We don't put this into the unibuild's watchSet immediately since we want
// to avoid putting it there if it turns out not to be relevant to our
// arch.
var absPath = files.pathResolve(
inputSourceArch.pkg.sourceRoot, source.relPath);
var file = watch.readAndWatchFileWithHash(fileWatchSet, absPath);
var contents = file.contents;
Console.nudge(true);
return {
relPath: source.relPath,
watchset: fileWatchSet,
contents: file.contents,
hash: file.hash,
source: source,
'package': isopk.name
};
});
_.each(linterPluginsByExtension, function (linters, ext) {
// XXX would run linters here
});
_.each(wrappedSourceItems, function (wrappedSource) {
var source = wrappedSource.source;
var relPath = source.relPath;
var fileOptions = _.clone(source.fileOptions) || {};
var absPath = files.pathResolve(inputSourceArch.pkg.sourceRoot, relPath);
var filename = files.pathBasename(relPath);
var contents = wrappedSource.contents;
var hash = wrappedSource.hash;
var fileWatchSet = wrappedSource.watchset;
Console.nudge(true);
@@ -398,7 +430,7 @@ var compileUnibuild = function (options) {
// Find the handler for source files with this extension.
var handler = null;
var isCompilerPluginSource = false;
var isBuildPluginSource = false;
if (! fileOptions.isAsset) {
var parts = filename.split('.');
// don't use iteration functions, so we can return/break
@@ -412,7 +444,7 @@ var compileUnibuild = function (options) {
// the server.)
return;
}
isCompilerPluginSource = true;
isBuildPluginSource = true;
break;
}
if (_.has(allHandlersWithPkgs, extension)) {
@@ -425,14 +457,14 @@ var compileUnibuild = function (options) {
// OK, this is relevant to this arch, so watch it.
watchSet.merge(fileWatchSet);
if (isCompilerPluginSource) {
if (isBuildPluginSource) {
// This is source used by a new-style compiler plugin; it will be fully
// processed later in the bundler.
resources.push({
type: "source",
data: contents,
path: relPath,
hash: file.hash
hash: hash
});
return;
}
@@ -443,7 +475,7 @@ var compileUnibuild = function (options) {
//
// XXX This is pretty confusing, especially if you've
// accidentally forgotten a plugin -- revisit?
addAsset(contents, relPath, file.hash);
addAsset(contents, relPath, hash);
return;
}
@@ -596,7 +628,7 @@ var compileUnibuild = function (options) {
_fullInputPath: files.convertToOSPath(absPath), // avoid, see above..
// Used for one optimization. Don't rely on this otherwise.
_hash: file.hash,
_hash: hash,
// XXX duplicates _pathForSourceMap() in linker
/**

View File

@@ -13,6 +13,7 @@ var packageMapModule = require('./package-map.js');
var colonConverter = require('./colon-converter.js');
var compilerPluginModule = require('./compiler-plugin.js');
var linterPluginModule = require('./linter-plugin.js');
var BuildPluginDefintion = require('./build-plugin.js').BuildPluginDefintion;
var Future = require('fibers/future');
var Console = require('./console.js').Console;
var Profile = require('./profile.js').Profile;
@@ -659,11 +660,12 @@ _.extend(Isopack.prototype, {
// We're finally done validating! Save the processor plugin, and mark
// all its extensions as used.
self.sourceProcessors[type][processorPluginId] =
new additionalOptions.pluginDefinitionClass({
new BuildPluginDefintion({
id: processorPluginId,
extensions: options.extensions,
archMatching: options.archMatching,
isTemplate: options.isTemplate
isTemplate: options.isTemplate,
buildPluginClass: additionalOptions.buildPluginClass
}, factory);
_.each(options.extensions, function (ext) {
pluginSourceExtensions[ext] = true;
@@ -675,7 +677,7 @@ _.extend(Isopack.prototype, {
var self = this;
self._registerSourceProcessor(options, factory, {
type: "compiler",
pluginDefinitionClass: compilerPluginModule.CompilerPluginDefinition,
buildPluginClass: compilerPluginModule.CompilerPlugin,
skipUniqExtCheck: false
});
},
@@ -686,7 +688,7 @@ _.extend(Isopack.prototype, {
isopack.sourceProcessors.linter = isopack.sourceProcessors.linter || {};
self._registerSourceProcessor(options, factory, {
type: "linter",
pluginDefinitionClass: linterPluginModule.LinterPluginDefinition,
buildPluginClass: linterPluginModule.LinterPlugin,
// Several linters can handle the same extension
skipUniqExtCheck: true
});

View File

@@ -1,30 +1,33 @@
var CompilerPluginDefinition = require('./compiler-plugin.js').CompilerPluginDefinition;
var buildPluginModule = require('./build-plugin.js');
var util = require('util');
var _ = require('underscore');
var LinterPluginDefinition = function () {
CompilerPluginDefinition.apply(this, arguments);
exports.LinterPlugin = function (pluginDefinition, userPlugin) {
var self = this;
self.userPlugin = userPlugin;
self.pluginDefinition = pluginDefinition;
};
util.inherits(LinterPluginDefinition, CompilerPluginDefinition);
exports.LinterPluginDefinition = LinterPluginDefinition;
_.extend(exports.LinterPluginDefinition.prototype, {
getInputFileClass: function () {
return LintingFile;
}
_.extend(exports.LinterPlugin.prototype, {
run: function () {}
});
var LintingFile = function () {
buildPluginModule.InputFile.apply(this, arguments);
var LintingFile = function (source) {
var self = this;
self._source = source;
};
util.inherits(LintingFile, buildPluginModule.InputFile);
_.extend(LintingFile.prototype, {
getContentsAsBuffer: function () {
return this._source.contents;
},
getPathInPackage: function () {
return this._source.relPath;
},
getPackageName: function () {
return this._source['package'];
},
getPackageImports: function () {
// XXX
}