From 505f1a6234099ed8d10f73d377888f1482fe8418 Mon Sep 17 00:00:00 2001 From: "Nicholas C. Zakas" Date: Thu, 21 Jan 2016 11:11:57 -0800 Subject: [PATCH] Update: Allow parser to be relative to config (fixes #4985) --- .gitignore | 4 +-- docs/developer-guide/working-with-rules.md | 2 +- lib/config/config-file.js | 9 +++++++ lib/rule-context.js | 6 ++--- package.json | 1 + .../config-file/js/.eslintrc.parser.js | 6 +++++ .../config-file/js/.eslintrc.parser2.js | 6 +++++ .../config-file/js/node_modules/foo/index.js | 1 + tests/fixtures/config-file/js/not-a-config.js | 1 + tests/lib/config/config-file.js | 26 +++++++++++++++++++ tests/lib/eslint.js | 8 +++--- 11 files changed, 60 insertions(+), 10 deletions(-) create mode 100644 tests/fixtures/config-file/js/.eslintrc.parser.js create mode 100644 tests/fixtures/config-file/js/.eslintrc.parser2.js create mode 100644 tests/fixtures/config-file/js/node_modules/foo/index.js create mode 100644 tests/fixtures/config-file/js/not-a-config.js diff --git a/.gitignore b/.gitignore index bb9871737273..b874943cdab8 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -node_modules/ +/node_modules test.js coverage/ build/ @@ -11,4 +11,4 @@ versions.json *.iml .eslintcache .cache -**/node_modules +/packages/**/node_modules diff --git a/docs/developer-guide/working-with-rules.md b/docs/developer-guide/working-with-rules.md index 428b0f2d2de0..694c40de83bd 100644 --- a/docs/developer-guide/working-with-rules.md +++ b/docs/developer-guide/working-with-rules.md @@ -74,7 +74,7 @@ The `context` object contains additional functionality that is helpful for rules * `id` - the rule ID. * `options` - an array of rule options. * `settings` - the `settings` from configuration. -* `parserName` - the `parser` from configuration. +* `parserPath` - the full path to the `parser` from configuration. Additionally, the `context` object has the following methods: diff --git a/lib/config/config-file.js b/lib/config/config-file.js index c04d7209ce6d..d584648d90df 100644 --- a/lib/config/config-file.js +++ b/lib/config/config-file.js @@ -17,6 +17,7 @@ var debug = require("debug"), ConfigOps = require("./config-ops"), validator = require("./config-validator"), Plugins = require("./plugins"), + resolveModule = require("resolve"), stripComments = require("strip-json-comments"), isAbsolutePath = require("path-is-absolute"); @@ -395,6 +396,14 @@ function load(filePath, applyEnvironments) { Plugins.loadAll(config.plugins); } + // include full path of parser if present + if (config.parser) { + config.parser = resolveModule.sync(config.parser, { + // be careful of https://github.com/substack/node-resolve/issues/78 + basedir: path.dirname(path.resolve(filePath)) + }); + } + // validate the configuration before continuing validator.validate(config, filePath); diff --git a/lib/rule-context.js b/lib/rule-context.js index 9d04a5c81bd2..e70ba6686ace 100644 --- a/lib/rule-context.js +++ b/lib/rule-context.js @@ -69,16 +69,16 @@ var PASSTHROUGHS = [ * @param {Array} options The configuration information to be added to the rule. * @param {Object} settings The configuration settings passed from the config file. * @param {Object} parserOptions The parserOptions settings passed from the config file. - * @param {Object} parserName The parser setting passed from the config file. + * @param {Object} parserPath The parser setting passed from the config file. * @param {Object} meta The metadata of the rule */ -function RuleContext(ruleId, eslint, severity, options, settings, parserOptions, parserName, meta) { +function RuleContext(ruleId, eslint, severity, options, settings, parserOptions, parserPath, meta) { // public. this.id = ruleId; this.options = options; this.settings = settings; this.parserOptions = parserOptions; - this.parserName = parserName; + this.parserPath = parserPath; this.meta = meta; // private. diff --git a/package.json b/package.json index 454b95367e38..df40196ee8eb 100644 --- a/package.json +++ b/package.json @@ -64,6 +64,7 @@ "optionator": "^0.8.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", diff --git a/tests/fixtures/config-file/js/.eslintrc.parser.js b/tests/fixtures/config-file/js/.eslintrc.parser.js new file mode 100644 index 000000000000..6625b0313b59 --- /dev/null +++ b/tests/fixtures/config-file/js/.eslintrc.parser.js @@ -0,0 +1,6 @@ +module.exports = { + parser: "foo", + rules: { + semi: [2, "always"] + } +}; diff --git a/tests/fixtures/config-file/js/.eslintrc.parser2.js b/tests/fixtures/config-file/js/.eslintrc.parser2.js new file mode 100644 index 000000000000..065c6c78c2c8 --- /dev/null +++ b/tests/fixtures/config-file/js/.eslintrc.parser2.js @@ -0,0 +1,6 @@ +module.exports = { + parser: "./not-a-config", + rules: { + semi: [2, "always"] + } +}; diff --git a/tests/fixtures/config-file/js/node_modules/foo/index.js b/tests/fixtures/config-file/js/node_modules/foo/index.js new file mode 100644 index 000000000000..c8ac80af70b8 --- /dev/null +++ b/tests/fixtures/config-file/js/node_modules/foo/index.js @@ -0,0 +1 @@ +"use strict": diff --git a/tests/fixtures/config-file/js/not-a-config.js b/tests/fixtures/config-file/js/not-a-config.js new file mode 100644 index 000000000000..5664ceb3ad85 --- /dev/null +++ b/tests/fixtures/config-file/js/not-a-config.js @@ -0,0 +1 @@ +"not a config"; diff --git a/tests/lib/config/config-file.js b/tests/lib/config/config-file.js index 34a01b03e938..12272d12eaf7 100644 --- a/tests/lib/config/config-file.js +++ b/tests/lib/config/config-file.js @@ -255,6 +255,32 @@ describe("ConfigFile", function() { }, /Cannot read config file/); }); + it("should interpret parser module name when present in a JavaScript file", function() { + var config = ConfigFile.load(getFixturePath("js/.eslintrc.parser.js")); + assert.deepEqual(config, { + parser: path.resolve(getFixturePath("js/node_modules/foo/index.js")), + parserOptions: {}, + env: {}, + globals: {}, + rules: { + semi: [2, "always"] + } + }); + }); + + it("should interpret parser path when present in a JavaScript file", function() { + var config = ConfigFile.load(getFixturePath("js/.eslintrc.parser2.js")); + assert.deepEqual(config, { + parser: path.resolve(getFixturePath("js/not-a-config.js")), + parserOptions: {}, + env: {}, + globals: {}, + rules: { + semi: [2, "always"] + } + }); + }); + it("should load information from a JSON file", function() { var config = ConfigFile.load(getFixturePath("json/.eslintrc.json")); assert.deepEqual(config, { diff --git a/tests/lib/eslint.js b/tests/lib/eslint.js index b3671b2a6bf4..35903a2c6c1b 100644 --- a/tests/lib/eslint.js +++ b/tests/lib/eslint.js @@ -1087,13 +1087,13 @@ describe("eslint", function() { // custom parser unsupported in browser, only test in Node if (typeof window === "undefined") { - it("should pass parser as parserName to all rules when provided on config", function() { + it("should pass parser as parserPath to all rules when provided on config", function() { var alternateParser = "esprima-fb"; eslint.reset(); eslint.defineRule("test-rule", sandbox.mock().withArgs( - sinon.match({parserName: alternateParser}) + sinon.match({parserPath: alternateParser}) ).returns({})); var config = { rules: { "test-rule": 2 }, parser: alternateParser }; @@ -1102,13 +1102,13 @@ describe("eslint", function() { }); } - it("should pass parser as parserName to all rules when default parser is used", function() { + it("should pass parser as parserPath to all rules when default parser is used", function() { var DEFAULT_PARSER = eslint.defaults().parser; eslint.reset(); eslint.defineRule("test-rule", sandbox.mock().withArgs( - sinon.match({parserName: DEFAULT_PARSER}) + sinon.match({parserPath: DEFAULT_PARSER}) ).returns({})); var config = { rules: { "test-rule": 2 } };