massive update, probably broken
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / eslint / lib / rules / arrow-body-style.js
index 8d3b400037a6d5e10d8e0181e39bc0cf51d02544..5b8a5f0116717aa456ecb64b7f4f1c20882553e5 100644 (file)
@@ -75,6 +75,7 @@ module.exports = {
         const never = options[0] === "never";
         const requireReturnForObjectLiteral = options[1] && options[1].requireReturnForObjectLiteral;
         const sourceCode = context.getSourceCode();
+        let funcInfo = null;
 
         /**
          * Checks whether the given node has ASI problem or not.
@@ -86,17 +87,32 @@ module.exports = {
         }
 
         /**
-         * Gets the closing parenthesis which is the pair of the given opening parenthesis.
-         * @param {Token} token The opening parenthesis token to get.
+         * Gets the closing parenthesis by the given node.
+         * @param {ASTNode} node first node after an opening parenthesis.
          * @returns {Token} The found closing parenthesis token.
          */
-        function findClosingParen(token) {
-            let node = sourceCode.getNodeByRangeIndex(token.range[1]);
+        function findClosingParen(node) {
+            let nodeToCheck = node;
 
-            while (!astUtils.isParenthesised(sourceCode, node)) {
-                node = node.parent;
+            while (!astUtils.isParenthesised(sourceCode, nodeToCheck)) {
+                nodeToCheck = nodeToCheck.parent;
             }
-            return sourceCode.getTokenAfter(node);
+            return sourceCode.getTokenAfter(nodeToCheck);
+        }
+
+        /**
+         * Check whether the node is inside of a for loop's init
+         * @param {ASTNode} node node is inside for loop
+         * @returns {boolean} `true` if the node is inside of a for loop, else `false`
+         */
+        function isInsideForLoopInitializer(node) {
+            if (node && node.parent) {
+                if (node.parent.type === "ForStatement" && node.parent.init === node) {
+                    return true;
+                }
+                return isInsideForLoopInitializer(node.parent);
+            }
+            return false;
         }
 
         /**
@@ -136,7 +152,7 @@ module.exports = {
 
                     context.report({
                         node,
-                        loc: arrowBody.loc.start,
+                        loc: arrowBody.loc,
                         messageId,
                         fix(fixer) {
                             const fixes = [];
@@ -175,14 +191,16 @@ module.exports = {
                             }
 
                             /*
-                             * If the first token of the reutrn value is `{` or the return value is a sequence expression,
+                             * If the first token of the return value is `{` or the return value is a sequence expression,
                              * enclose the return value by parentheses to avoid syntax error.
                              */
-                            if (astUtils.isOpeningBraceToken(firstValueToken) || blockBody[0].argument.type === "SequenceExpression") {
-                                fixes.push(
-                                    fixer.insertTextBefore(firstValueToken, "("),
-                                    fixer.insertTextAfter(lastValueToken, ")")
-                                );
+                            if (astUtils.isOpeningBraceToken(firstValueToken) || blockBody[0].argument.type === "SequenceExpression" || (funcInfo.hasInOperator && isInsideForLoopInitializer(node))) {
+                                if (!astUtils.isParenthesised(sourceCode, blockBody[0].argument)) {
+                                    fixes.push(
+                                        fixer.insertTextBefore(firstValueToken, "("),
+                                        fixer.insertTextAfter(lastValueToken, ")")
+                                    );
+                                }
                             }
 
                             /*
@@ -201,29 +219,50 @@ module.exports = {
                 if (always || (asNeeded && requireReturnForObjectLiteral && arrowBody.type === "ObjectExpression")) {
                     context.report({
                         node,
-                        loc: arrowBody.loc.start,
+                        loc: arrowBody.loc,
                         messageId: "expectedBlock",
                         fix(fixer) {
                             const fixes = [];
                             const arrowToken = sourceCode.getTokenBefore(arrowBody, astUtils.isArrowToken);
-                            const firstBodyToken = sourceCode.getTokenAfter(arrowToken);
-                            const lastBodyToken = sourceCode.getLastToken(node);
-                            const isParenthesisedObjectLiteral =
-                                astUtils.isOpeningParenToken(firstBodyToken) &&
-                                astUtils.isOpeningBraceToken(sourceCode.getTokenAfter(firstBodyToken));
-
-                            // Wrap the value by a block and a return statement.
-                            fixes.push(
-                                fixer.insertTextBefore(firstBodyToken, "{return "),
-                                fixer.insertTextAfter(lastBodyToken, "}")
-                            );
+                            const [firstTokenAfterArrow, secondTokenAfterArrow] = sourceCode.getTokensAfter(arrowToken, { count: 2 });
+                            const lastToken = sourceCode.getLastToken(node);
+
+                            let parenthesisedObjectLiteral = null;
+
+                            if (
+                                astUtils.isOpeningParenToken(firstTokenAfterArrow) &&
+                                astUtils.isOpeningBraceToken(secondTokenAfterArrow)
+                            ) {
+                                const braceNode = sourceCode.getNodeByRangeIndex(secondTokenAfterArrow.range[0]);
+
+                                if (braceNode.type === "ObjectExpression") {
+                                    parenthesisedObjectLiteral = braceNode;
+                                }
+                            }
 
                             // If the value is object literal, remove parentheses which were forced by syntax.
-                            if (isParenthesisedObjectLiteral) {
-                                fixes.push(
-                                    fixer.remove(firstBodyToken),
-                                    fixer.remove(findClosingParen(firstBodyToken))
-                                );
+                            if (parenthesisedObjectLiteral) {
+                                const openingParenToken = firstTokenAfterArrow;
+                                const openingBraceToken = secondTokenAfterArrow;
+
+                                if (astUtils.isTokenOnSameLine(openingParenToken, openingBraceToken)) {
+                                    fixes.push(fixer.replaceText(openingParenToken, "{return "));
+                                } else {
+
+                                    // Avoid ASI
+                                    fixes.push(
+                                        fixer.replaceText(openingParenToken, "{"),
+                                        fixer.insertTextBefore(openingBraceToken, "return ")
+                                    );
+                                }
+
+                                // Closing paren for the object doesn't have to be lastToken, e.g.: () => ({}).foo()
+                                fixes.push(fixer.remove(findClosingParen(parenthesisedObjectLiteral)));
+                                fixes.push(fixer.insertTextAfter(lastToken, "}"));
+
+                            } else {
+                                fixes.push(fixer.insertTextBefore(firstTokenAfterArrow, "{return "));
+                                fixes.push(fixer.insertTextAfter(lastToken, "}"));
                             }
 
                             return fixes;
@@ -234,7 +273,24 @@ module.exports = {
         }
 
         return {
-            "ArrowFunctionExpression:exit": validate
+            "BinaryExpression[operator='in']"() {
+                let info = funcInfo;
+
+                while (info) {
+                    info.hasInOperator = true;
+                    info = info.upper;
+                }
+            },
+            ArrowFunctionExpression() {
+                funcInfo = {
+                    upper: funcInfo,
+                    hasInOperator: false
+                };
+            },
+            "ArrowFunctionExpression:exit"(node) {
+                validate(node);
+                funcInfo = funcInfo.upper;
+            }
         };
     }
 };