Skip to content

Commit

Permalink
New: Enhanced local plugin resolution.
Browse files Browse the repository at this point in the history
When writing presets sometimes it is desirable to include plugins as dependencies, since the preset may be explicitly for that dependency and that means one less thing users need to include and it offers an easy way to pin versions of a plugin with your preset. Unfortunately, the default `eslint` behavior is incapable of loading these local-style plugins for a couple of reasons:

 * `require` only resolves things relative to local eslint installation,
 * absolute paths are not supported,
 * developers don't want any code in `preset` definition files.

So with all those caveats in mind, the behavior has been altered to simply start the preset resolution process at the _caller_'s module (i.e. the preset) instead of the _callee_'s module (i.e. `eslint`).

This fixes #3458.
  • Loading branch information
izaakschroeder committed Dec 18, 2015
1 parent 4e38572 commit 11dc566
Show file tree
Hide file tree
Showing 4 changed files with 19 additions and 1 deletion.
8 changes: 7 additions & 1 deletion lib/cli-engine.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ var fs = require("fs"),
assign = require("object-assign"),
debug = require("debug"),
shell = require("shelljs"),
resolve = require("resolve"),

rules = require("./rules"),
eslint = require("./eslint"),
Expand Down Expand Up @@ -118,12 +119,17 @@ function loadPlugins(pluginNames) {
var pluginNamespace = util.getNamespace(pluginName),
pluginNameWithoutNamespace = util.removeNameSpace(pluginName),
pluginNameWithoutPrefix = util.removePluginPrefix(pluginNameWithoutNamespace),
pluginModuleName = pluginNamespace + util.PLUGIN_NAME_PREFIX + pluginNameWithoutPrefix,
plugin;

if (!loadedPlugins[pluginNameWithoutPrefix]) {
debug("Load plugin " + pluginNameWithoutPrefix);

plugin = require(pluginNamespace + util.PLUGIN_NAME_PREFIX + pluginNameWithoutPrefix);
plugin = require(resolve.sync(pluginModuleName, {
basedir: path.dirname(module.parent.parent.filename),
moduleDirectory: [ "node_modules" ]
}));

// if this plugin has rules, import them
if (plugin.rules) {
rules.import(plugin.rules, pluginNameWithoutPrefix);
Expand Down
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@
"optionator": "^0.7.1",
"path-is-absolute": "^1.0.0",
"path-is-inside": "^1.0.1",
"resolve": "^1.1.6",
"shelljs": "^0.5.3",
"strip-json-comments": "~1.0.1",
"text-table": "~0.2.0",
Expand Down
5 changes: 5 additions & 0 deletions tests/lib/cli-engine.js
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,11 @@ describe("CLIEngine", function() {
examplePreprocessorName = "eslint-plugin-processor",
fixtureDir;

requireStubs.resolve = {
sync: function(s) {
return s;
}
};
requireStubs[examplePluginName] = examplePlugin;
requireStubs[examplePluginNameWithNamespace] = examplePlugin;
requireStubs[examplePreprocessorName] = require("../fixtures/processors/custom-processor");
Expand Down
6 changes: 6 additions & 0 deletions tests/lib/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -615,9 +615,15 @@ describe("cli", function() {
examplePlugin = { rules: { "cli-example-rule": require(getFixturePath("rules", "custom-rule.js")) } },
exampleRuleConfig = "'example/cli-example-rule: 2'";

requireStubs.resolve = {
sync: function(s) {
return s;
}
};
requireStubs["./logging"] = log;
requireStubs[examplePluginName] = examplePlugin;
requireStubs[examplePluginName]["@global"] = true;
requireStubs["./cli-engine"] = proxyquire("../../lib/cli-engine", requireStubs);

cli = proxyquire("../../lib/cli", requireStubs);
var exit = cli.execute("--plugin " + examplePluginName + " --rule " + exampleRuleConfig + " " + filePath);
Expand Down

0 comments on commit 11dc566

Please sign in to comment.