Repository: eslint/eslint
Pull request #11369 (2019-02-09 11:06:15)

Docs: update typescript parser (refs #11368)
<!--
    ESLint adheres to the [JS Foundation Code of Conduct](https://js.foundation/community/code-of-conduct).
-->

**What is the purpose of this pull request? (put an "X" next to item)**

[x] Documentation update
[ ] Bug fix ([template](https://raw.githubusercontent.com/eslint/eslint/master/templates/bug-report.md))
[ ] 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 (https://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)**
updated the docs about typescript-eslint-parser(it has been deprecated)

**Is there anything you'd like reviewers to focus on?**
somewhere else?




Patch:
diff --git a/docs/developer-guide/working-with-custom-parsers.md b/docs/developer-guide/working-with-custom-parsers.md
index d6626862d..a7aa58f5e 100644
--- a/docs/developer-guide/working-with-custom-parsers.md
+++ b/docs/developer-guide/working-with-custom-parsers.md
@@ -9,7 +9,7 @@ If you want to use your own parser and provide additional capabilities for your
 * `visitorKeys` can be an object to customize AST traversal. The keys of the object are the type of AST nodes. Each value is an array of the property names which should be traversed. Default is [KEYS of `eslint-visitor-keys`](https://github.com/eslint/eslint-visitor-keys#evkkeys).
     * Support for `visitorKeys` was added in ESLint v4.14.0. ESLint versions which support `visitorKeys` will provide an `eslintVisitorKeys: true` property in `parserOptions`, which can be used for feature detection.
 
-You can find an ESLint parser project [here](https://github.com/eslint/typescript-eslint-parser).
+You can find an ESLint parser project [here](https://github.com/typescript-eslint/typescript-eslint).
 
 ```json
 {
diff --git a/docs/user-guide/configuring.md b/docs/user-guide/configuring.md
index 1eed790a2..c2400a99c 100644
--- a/docs/user-guide/configuring.md
+++ b/docs/user-guide/configuring.md
@@ -23,7 +23,7 @@ Please note that supporting JSX syntax is not the same as supporting React. Reac
 By the same token, supporting ES6 syntax is not the same as supporting new ES6 globals (e.g., new types such as
 `Set`).
 For ES6 syntax, use `{ "parserOptions": { "ecmaVersion": 6 } }`; for new ES6 global variables, use `{ "env":
-{ "es6": true } }` (this setting enables ES6 syntax automatically).
+{ "es6": true } }`. `{ env: { es6: true } }` enables ES6 syntax automatically, but `{ parserOptions: { ecmaVersion: 6 } }` does not enable ES6 globals automatically.
 Parser options are set in your `.eslintrc.*` file by using the `parserOptions` property. The available options are:
 
 * `ecmaVersion` - set to 3, 5 (default), 6, 7, 8, 9, or 10 to specify the version of ECMAScript syntax you want to use. You can also set to 2015 (same as 6), 2016 (same as 7), 2017 (same as 8), 2018 (same as 9), or 2019 (same as 10) to use the year-based naming.
@@ -81,7 +81,7 @@ The following parsers are compatible with ESLint:
 
 * [Esprima](https://www.npmjs.com/package/esprima)
 * [Babel-ESLint](https://www.npmjs.com/package/babel-eslint) - A wrapper around the [Babel](https://babeljs.io) parser that makes it compatible with ESLint.
-* [typescript-eslint-parser(Experimental)](https://www.npmjs.com/package/typescript-eslint-parser) - A parser that converts TypeScript into an ESTree-compatible form so it can be used in ESLint. The goal is to allow TypeScript files to be parsed by ESLint (though not necessarily pass all ESLint rules).
+* [@typescript-eslint/parser](https://www.npmjs.com/package/@typescript-eslint/parser) - A parser that converts TypeScript into an ESTree-compatible form so it can be used in ESLint.
 
 Note when using a custom parser, the `parserOptions` configuration property is still required for ESLint to work properly with features not in ECMAScript 5 by default. Parsers are all passed `parserOptions` and may or may not use them to determine which features to enable.
 
diff --git a/lib/rules/prefer-destructuring.js b/lib/rules/prefer-destructuring.js
index 119fae560..dec93d51f 100644
--- a/lib/rules/prefer-destructuring.js
+++ b/lib/rules/prefer-destructuring.js
@@ -19,6 +19,8 @@ module.exports = {
             url: "https://eslint.org/docs/rules/prefer-destructuring"
         },
 
+        fixable: "code",
+
         schema: [
             {
 
@@ -130,10 +132,55 @@ module.exports = {
          *
          * @param {ASTNode} reportNode the node to report
          * @param {string} type the type of destructuring that should have been done
+         * @param {Function|null} fix the fix function or null to pass to context.report
          * @returns {void}
          */
-        function report(reportNode, type) {
-            context.report({ node: reportNode, message: "Use {{type}} destructuring.", data: { type } });
+        function report(reportNode, type, fix) {
+            context.report({
+                node: reportNode,
+                message: "Use {{type}} destructuring.",
+                data: { type },
+                fix
+            });
+        }
+
+        /**
+         * Determines if a node should be fixed into object destructuring
+         *
+         * The fixer only fixes the simplest case of object destructuring,
+         * like: `let x = a.x`;
+         *
+         * Assignment expression is not fixed.
+         * Array destructuring is not fixed.
+         * Renamed property is not fixed.
+         *
+         * @param {ASTNode} node the the node to evaluate
+         * @returns {boolean} whether or not the node should be fixed
+         */
+        function shouldFix(node) {
+            return node.type === "VariableDeclarator" &&
+                node.id.type === "Identifier" &&
+                node.init.type === "MemberExpression" &&
+                node.id.name === node.init.property.name;
+        }
+
+        /**
+         * Fix a node into object destructuring.
+         * This function only handles the simplest case of object destructuring,
+         * see {@link shouldFix}.
+         *
+         * @param {SourceCodeFixer} fixer the fixer object
+         * @param {ASTNode} node the node to be fixed.
+         * @returns {Object} a fix for the node
+         */
+        function fixIntoObjectDestructuring(fixer, node) {
+            const rightNode = node.init;
+            const sourceCode = context.getSourceCode();
+
+            return fixer.replaceText(
+                node,
+                `{${rightNode.property.name}} = ${sourceCode.getText(rightNode.object)}`
+            );
         }
 
         /**
@@ -155,13 +202,17 @@ module.exports = {
 
             if (isArrayIndexAccess(rightNode)) {
                 if (shouldCheck(reportNode.type, "array")) {
-                    report(reportNode, "array");
+                    report(reportNode, "array", null);
                 }
                 return;
             }
 
+            const fix = shouldFix(reportNode)
+                ? fixer => fixIntoObjectDestructuring(fixer, reportNode)
+                : null;
+
             if (shouldCheck(reportNode.type, "object") && enforceForRenamedProperties) {
-                report(reportNode, "object");
+                report(reportNode, "object", fix);
                 return;
             }
 
@@ -172,7 +223,7 @@ module.exports = {
                     (property.type === "Literal" && leftNode.name === property.value) ||
                     (property.type === "Identifier" && leftNode.name === property.name && !rightNode.computed)
                 ) {
-                    report(reportNode, "object");
+                    report(reportNode, "object", fix);
                 }
             }
         }
diff --git a/lib/rules/prefer-spread.js b/lib/rules/prefer-spread.js
index 790fd3b82..5f3a47732 100644
--- a/lib/rules/prefer-spread.js
+++ b/lib/rules/prefer-spread.js
@@ -59,7 +59,7 @@ module.exports = {
         },
 
         schema: [],
-        fixable: "code"
+        fixable: null
     },
 
     create(context) {
@@ -78,18 +78,7 @@ module.exports = {
                 if (isValidThisArg(expectedThis, thisArg, sourceCode)) {
                     context.report({
                         node,
-                        message: "Use the spread operator instead of '.apply()'.",
-                        fix(fixer) {
-                            if (expectedThis && expectedThis.type !== "Identifier") {
-
-                                // Don't fix cases where the `this` value could be a computed expression.
-                                return null;
-                            }
-
-                            const propertyDot = sourceCode.getFirstTokenBetween(applied, node.callee.property, token => token.value === ".");
-
-                            return fixer.replaceTextRange([propertyDot.range[0], node.range[1]], `(...${sourceCode.getText(node.arguments[1])})`);
-                        }
+                        message: "Use the spread operator instead of '.apply()'."
                     });
                 }
             }


Test patch:
diff --git a/tests/lib/rules/prefer-destructuring.js b/tests/lib/rules/prefer-destructuring.js
index a0e4aa79b..5470079ef 100644
--- a/tests/lib/rules/prefer-destructuring.js
+++ b/tests/lib/rules/prefer-destructuring.js
@@ -133,12 +133,21 @@ ruleTester.run("prefer-destructuring", rule, {
         },
         "class Foo extends Bar { static foo() {var foo = super.foo} }",
         "foo = bar[foo];",
-        "var foo = bar[foo];"
+        "var foo = bar[foo];",
+        {
+            code: "var {foo: {bar}} = object;",
+            options: [{ object: true }]
+        },
+        {
+            code: "var {bar} = object.foo;",
+            options: [{ object: true }]
+        }
     ],
 
     invalid: [
         {
             code: "var foo = array[0];",
+            output: null,
             errors: [{
                 message: "Use array destructuring.",
                 type: "VariableDeclarator"
@@ -146,6 +155,7 @@ ruleTester.run("prefer-destructuring", rule, {
         },
         {
             code: "foo = array[0];",
+            output: null,
             errors: [{
                 message: "Use array destructuring.",
                 type: "AssignmentExpression"
@@ -153,6 +163,15 @@ ruleTester.run("prefer-destructuring", rule, {
         },
         {
             code: "var foo = object.foo;",
+            output: "var {foo} = object;",
+            errors: [{
+                message: "Use object destructuring.",
+                type: "VariableDeclarator"
+            }]
+        },
+        {
+            code: "var foo = object.bar.foo;",
+            output: "var {foo} = object.bar;",
             errors: [{
                 message: "Use object destructuring.",
                 type: "VariableDeclarator"
@@ -160,6 +179,7 @@ ruleTester.run("prefer-destructuring", rule, {
         },
         {
             code: "var foobar = object.bar;",
+            output: null,
             options: [{ VariableDeclarator: { object: true } }, { enforceForRenamedProperties: true }],
             errors: [{
                 message: "Use object destructuring.",
@@ -168,6 +188,7 @@ ruleTester.run("prefer-destructuring", rule, {
         },
         {
             code: "var foobar = object.bar;",
+            output: null,
             options: [{ object: true }, { enforceForRenamedProperties: true }],
             errors: [{
                 message: "Use object destructuring.",
@@ -176,6 +197,7 @@ ruleTester.run("prefer-destructuring", rule, {
         },
         {
             code: "var foo = object[bar];",
+            output: null,
             options: [{ VariableDeclarator: { object: true } }, { enforceForRenamedProperties: true }],
             errors: [{
                 message: "Use object destructuring.",
@@ -184,6 +206,7 @@ ruleTester.run("prefer-destructuring", rule, {
         },
         {
             code: "var foo = object[bar];",
+            output: null,
             options: [{ object: true }, { enforceForRenamedProperties: true }],
             errors: [{
                 message: "Use object destructuring.",
@@ -192,6 +215,7 @@ ruleTester.run("prefer-destructuring", rule, {
         },
         {
             code: "var foo = object['foo'];",
+            output: null,
             errors: [{
                 message: "Use object destructuring.",
                 type: "VariableDeclarator"
@@ -199,6 +223,7 @@ ruleTester.run("prefer-destructuring", rule, {
         },
         {
             code: "foo = object.foo;",
+            output: null,
             errors: [{
                 message: "Use object destructuring.",
                 type: "AssignmentExpression"
@@ -206,6 +231,7 @@ ruleTester.run("prefer-destructuring", rule, {
         },
         {
             code: "foo = object['foo'];",
+            output: null,
             errors: [{
                 message: "Use object destructuring.",
                 type: "AssignmentExpression"
@@ -213,6 +239,7 @@ ruleTester.run("prefer-destructuring", rule, {
         },
         {
             code: "var foo = array[0];",
+            output: null,
             options: [{ VariableDeclarator: { array: true } }, { enforceForRenamedProperties: true }],
             errors: [{
                 message: "Use array destructuring.",
@@ -221,6 +248,7 @@ ruleTester.run("prefer-destructuring", rule, {
         },
         {
             code: "foo = array[0];",
+            output: null,
             options: [{ AssignmentExpression: { array: true } }],
             errors: [{
                 message: "Use array destructuring.",
@@ -229,6 +257,7 @@ ruleTester.run("prefer-destructuring", rule, {
         },
         {
             code: "var foo = array[0];",
+            output: null,
             options: [
                 {
                     VariableDeclarator: { array: true },
@@ -243,6 +272,7 @@ ruleTester.run("prefer-destructuring", rule, {
         },
         {
             code: "var foo = array[0];",
+            output: null,
             options: [
                 {
                     VariableDeclarator: { array: true },
@@ -256,6 +286,7 @@ ruleTester.run("prefer-destructuring", rule, {
         },
         {
             code: "foo = array[0];",
+            output: null,
             options: [
                 {
                     VariableDeclarator: { array: false },
@@ -269,6 +300,7 @@ ruleTester.run("prefer-destructuring", rule, {
         },
         {
             code: "foo = object.foo;",
+            output: null,
             options: [
                 {
                     VariableDeclarator: { array: true, object: false },
@@ -282,6 +314,7 @@ ruleTester.run("prefer-destructuring", rule, {
         },
         {
             code: "class Foo extends Bar { static foo() {var bar = super.foo.bar} }",
+            output: "class Foo extends Bar { static foo() {var {bar} = super.foo} }",
             errors: [{
                 message: "Use object destructuring.",
                 type: "VariableDeclarator"
diff --git a/tests/lib/rules/prefer-spread.js b/tests/lib/rules/prefer-spread.js
index 7e9681770..1e11dd6c4 100644
--- a/tests/lib/rules/prefer-spread.js
+++ b/tests/lib/rules/prefer-spread.js
@@ -44,50 +44,34 @@ ruleTester.run("prefer-spread", rule, {
     invalid: [
         {
             code: "foo.apply(undefined, args);",
-            output: "foo(...args);",
             errors
         },
         {
             code: "foo.apply(void 0, args);",
-            output: "foo(...args);",
             errors
         },
         {
             code: "foo.apply(null, args);",
-            output: "foo(...args);",
             errors
         },
         {
             code: "obj.foo.apply(obj, args);",
-            output: "obj.foo(...args);",
             errors
         },
         {
-
-            // Not fixed: a.b.c might activate getters
             code: "a.b.c.foo.apply(a.b.c, args);",
-            output: null,
             errors
         },
         {
-
-            // Not fixed: a.b(x, y).c might activate getters
             code: "a.b(x, y).c.foo.apply(a.b(x, y).c, args);",
-            output: null,
             errors
         },
         {
-
-            // Not fixed (not an identifier)
             code: "[].concat.apply([ ], args);",
-            output: null,
             errors
         },
         {
-
-            // Not fixed (not an identifier)
             code: "[].concat.apply([\n/*empty*/\n], args);",
-            output: null,
             errors
         }
     ]