Repository: eslint/eslint (js)

Issue:
New default parserOptions in eslint 4.0 breaks babel-eslint
As of eslint 4.0 there is no way anymore for a parser to determine what parser options the user supplied, because there are [default parserOptions](https://github.com/eslint/eslint/blob/master/conf/default-config-options.js#L28-L32) now merged into the user supplied options before they are handed over to the parser.

This breaks the behaviour of babel-eslint, as we were relying on getting the raw parserOptions from the user and if not set applying our [own defaults](https://github.com/babel/babel-eslint/blob/master/index.js#L362-L369) for this options.

With the current defaults in eslint 4.0 there is no way for us to know what the user supplied.

It would be nice to have the possibility to influence the default parserOptions in some standardized way. We are also [monkeypatching](https://github.com/babel/babel-eslint/blob/master/index.js#L64-L74) escope to be able to set our default values, which is really ugly and could probably be removed if the parser creates the default config. There are probably even more cases where eslint does different things based on this options, which are now out of sync with the options babel-eslint uses. (see babel/babel-eslint#458)

Maybe it would be possible that a parser exposes an optional API that sets the default values for the parser options.

```js
export function getDefaultOptions(rawConfig) {
  return {...};
}
```

Then eslint could consume this if available and merge it with your own default configs.

```js
let parserOptions = Object.assign({}, defaultConfig.parserOptions, parser.getDefaultOptions(config.parserOptions));
```

Would that be something you would be open to? Or can you think of any other solutions.

Pull request description:
Fix: don't pass default parserOptions to custom parsers (fixes #8744)
**What is the purpose of this pull request? (put an "X" next to item)**

[ ] Documentation update
[x] Bug fix (#8744)
[ ] New rule ([template](https://raw.githubusercontent.com/eslint/eslint/master/templates/rule-proposal.md))
[ ] Changes an existing rule ([template](https://raw.githubusercontent.com/eslint/eslint/master/templates/rule-change-proposal.md))
[ ] Add autofixing to a rule
[ ] Add a CLI option
[ ] Add something to the core
[ ] Other, please explain:

<!--
    If the item you've checked above has a template, please paste the template questions below and answer them. (If this pull request is addressing an issue, you can just paste a link to the issue here instead.)
-->

<!--
    Please ensure your pull request is ready:

    - Read the pull request guide (http://eslint.org/docs/developer-guide/contributing/pull-requests)
    - Include tests for this change
    - Update documentation for this change (if appropriate)
-->

<!--
    The following is required for all pull requests:
-->

**What changes did you make? (Give an overview)**

afbea78d4b94839ec6d59d2c98321901aeb76313 accidentally introduced a regression where parsers would get passed additional "default" options even when the user did not specify them. This updates the default parserOptions to prevent any unexpected options from getting passed to parsers.

**Is there anything you'd like reviewers to focus on?**

Nothing in particular


Patch:
diff --git a/conf/default-config-options.js b/conf/default-config-options.js
index 63d28c48b..96fe25ce6 100644
--- a/conf/default-config-options.js
+++ b/conf/default-config-options.js
@@ -25,9 +25,5 @@ module.exports = deepFreeze({
     rules: {},
     settings: {},
     parser: "espree",
-    parserOptions: {
-        ecmaVersion: 5,
-        sourceType: "script",
-        ecmaFeatures: {}
-    }
+    parserOptions: {}
 });
diff --git a/lib/cli-engine.js b/lib/cli-engine.js
index f53c2e76a..ebca4cb81 100644
--- a/lib/cli-engine.js
+++ b/lib/cli-engine.js
@@ -318,7 +318,7 @@ function getCacheFile(cacheFile, cwd) {
     cacheFile = path.normalize(cacheFile);
 
     const resolvedCacheFile = path.resolve(cwd, cacheFile);
-    const looksLikeADirectory = cacheFile[cacheFile.length - 1 ] === path.sep;
+    const looksLikeADirectory = cacheFile[cacheFile.length - 1] === path.sep;
 
     /**
      * return the name for the cache file in case the provided parameter is a directory
diff --git a/lib/code-path-analysis/code-path-state.js b/lib/code-path-analysis/code-path-state.js
index a5adb554f..7c8abb207 100644
--- a/lib/code-path-analysis/code-path-state.js
+++ b/lib/code-path-analysis/code-path-state.js
@@ -240,7 +240,7 @@ class CodePathState {
         this.breakContext = null;
 
         this.currentSegments = [];
-        this.initialSegment = this.forkContext.head[ 0 ];
+        this.initialSegment = this.forkContext.head[0];
 
         // returnedSegments and thrownSegments push elements into finalSegments also.
         const final = this.finalSegments = [];
diff --git a/lib/config.js b/lib/config.js
index 5407134d6..5c04ee4e1 100644
--- a/lib/config.js
+++ b/lib/config.js
@@ -198,7 +198,7 @@ class Config {
         this.useEslintrc = (options.useEslintrc !== false);
 
         this.env = (options.envs || []).reduce((envs, name) => {
-            envs[ name ] = true;
+            envs[name] = true;
             return envs;
         }, {});
 
diff --git a/lib/linter.js b/lib/linter.js
index 0b0d06a86..d2f1f4657 100755
--- a/lib/linter.js
+++ b/lib/linter.js
@@ -455,8 +455,8 @@ function normalizeEcmaVersion(ecmaVersion, isModule) {
  */
 function prepareConfig(config, envContext) {
     config.globals = config.globals || {};
-    const copiedRules = Object.assign({}, defaultConfig.rules);
-    let parserOptions = Object.assign({}, defaultConfig.parserOptions);
+    const copiedRules = {};
+    let parserOptions = {};
 
     if (typeof config.rules === "object") {
         Object.keys(config.rules).forEach(k => {
diff --git a/packages/eslint-config-eslint/default.yml b/packages/eslint-config-eslint/default.yml
index 9180f7525..634fd4624 100644
--- a/packages/eslint-config-eslint/default.yml
+++ b/packages/eslint-config-eslint/default.yml
@@ -16,6 +16,7 @@ rules:
     comma-dangle: "error"
     comma-spacing: "error"
     comma-style: ["error", "last"]
+    computed-property-spacing: "error"
     consistent-return: "error"
     curly: ["error", "all"]
     default-case: "error"
diff --git a/templates/formatter-examples.md.ejs b/templates/formatter-examples.md.ejs
index 0e7443390..3231ea44d 100644
--- a/templates/formatter-examples.md.ejs
+++ b/templates/formatter-examples.md.ejs
@@ -6,6 +6,8 @@ layout: doc
 
 ESLint comes with several built-in formatters to control the appearance of the linting results, and supports third-party formatters as well.
 
+You can specify a formatter using the `--format` or `-f` flag on the command line. For example, `--format codeframe` uses the `codeframe` formatter.
+
 The built-in formatter options are:
 
 <% Object.keys(formatterResults).forEach(function(formatterName) { -%>


Test patch:
diff --git a/tests/fixtures/parsers/throws-with-options.js b/tests/fixtures/parsers/throws-with-options.js
new file mode 100644
index 000000000..95857751a
--- /dev/null
+++ b/tests/fixtures/parsers/throws-with-options.js
@@ -0,0 +1,10 @@
+"use strict";
+
+const espree = require("espree");
+
+exports.parse = (sourceText, options) => {
+    if (options.ecmaVersion) {
+        throw new Error("Expected no parserOptions to be used");
+    }
+    return espree.parse(sourceText, options);
+};
diff --git a/tests/lib/linter.js b/tests/lib/linter.js
index 01eec7bba..4acc46b3f 100644
--- a/tests/lib/linter.js
+++ b/tests/lib/linter.js
@@ -3905,6 +3905,13 @@ describe("eslint", () => {
                 assert.equal(messages[0].message, errorPrefix + require(parser).expectedError);
             });
 
+            it("should not pass any default parserOptions to the parser", () => {
+                const parser = path.join(parserFixtures, "throws-with-options.js");
+
+                const messages = linter.verify(";", { parser }, "filename");
+
+                assert.strictEqual(messages.length, 0);
+            });
         });
     }