Actualizacion maquina principal
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / eslint / lib / rules / array-callback-return.js
diff --git a/.config/coc/extensions/node_modules/coc-prettier/node_modules/eslint/lib/rules/array-callback-return.js b/.config/coc/extensions/node_modules/coc-prettier/node_modules/eslint/lib/rules/array-callback-return.js
new file mode 100644 (file)
index 0000000..d632a3f
--- /dev/null
@@ -0,0 +1,253 @@
+/**
+ * @fileoverview Rule to enforce return statements in callbacks of array's methods
+ * @author Toru Nagashima
+ */
+
+"use strict";
+
+//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+const lodash = require("lodash");
+
+const astUtils = require("./utils/ast-utils");
+
+//------------------------------------------------------------------------------
+// Helpers
+//------------------------------------------------------------------------------
+
+const TARGET_NODE_TYPE = /^(?:Arrow)?FunctionExpression$/u;
+const TARGET_METHODS = /^(?:every|filter|find(?:Index)?|map|reduce(?:Right)?|some|sort)$/u;
+
+/**
+ * Checks a given code path segment is reachable.
+ * @param {CodePathSegment} segment A segment to check.
+ * @returns {boolean} `true` if the segment is reachable.
+ */
+function isReachable(segment) {
+    return segment.reachable;
+}
+
+/**
+ * Gets a readable location.
+ *
+ * - FunctionExpression -> the function name or `function` keyword.
+ * - ArrowFunctionExpression -> `=>` token.
+ * @param {ASTNode} node A function node to get.
+ * @param {SourceCode} sourceCode A source code to get tokens.
+ * @returns {ASTNode|Token} The node or the token of a location.
+ */
+function getLocation(node, sourceCode) {
+    if (node.type === "ArrowFunctionExpression") {
+        return sourceCode.getTokenBefore(node.body);
+    }
+    return node.id || node;
+}
+
+/**
+ * Checks a given node is a MemberExpression node which has the specified name's
+ * property.
+ * @param {ASTNode} node A node to check.
+ * @returns {boolean} `true` if the node is a MemberExpression node which has
+ *      the specified name's property
+ */
+function isTargetMethod(node) {
+    return (
+        node.type === "MemberExpression" &&
+        TARGET_METHODS.test(astUtils.getStaticPropertyName(node) || "")
+    );
+}
+
+/**
+ * Checks whether or not a given node is a function expression which is the
+ * callback of an array method.
+ * @param {ASTNode} node A node to check. This is one of
+ *      FunctionExpression or ArrowFunctionExpression.
+ * @returns {boolean} `true` if the node is the callback of an array method.
+ */
+function isCallbackOfArrayMethod(node) {
+    let currentNode = node;
+
+    while (currentNode) {
+        const parent = currentNode.parent;
+
+        switch (parent.type) {
+
+            /*
+             * Looks up the destination. e.g.,
+             * foo.every(nativeFoo || function foo() { ... });
+             */
+            case "LogicalExpression":
+            case "ConditionalExpression":
+                currentNode = parent;
+                break;
+
+            /*
+             * If the upper function is IIFE, checks the destination of the return value.
+             * e.g.
+             *   foo.every((function() {
+             *     // setup...
+             *     return function callback() { ... };
+             *   })());
+             */
+            case "ReturnStatement": {
+                const func = astUtils.getUpperFunction(parent);
+
+                if (func === null || !astUtils.isCallee(func)) {
+                    return false;
+                }
+                currentNode = func.parent;
+                break;
+            }
+
+            /*
+             * e.g.
+             *   Array.from([], function() {});
+             *   list.every(function() {});
+             */
+            case "CallExpression":
+                if (astUtils.isArrayFromMethod(parent.callee)) {
+                    return (
+                        parent.arguments.length >= 2 &&
+                        parent.arguments[1] === currentNode
+                    );
+                }
+                if (isTargetMethod(parent.callee)) {
+                    return (
+                        parent.arguments.length >= 1 &&
+                        parent.arguments[0] === currentNode
+                    );
+                }
+                return false;
+
+            // Otherwise this node is not target.
+            default:
+                return false;
+        }
+    }
+
+    /* istanbul ignore next: unreachable */
+    return false;
+}
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = {
+    meta: {
+        type: "problem",
+
+        docs: {
+            description: "enforce `return` statements in callbacks of array methods",
+            category: "Best Practices",
+            recommended: false,
+            url: "https://eslint.org/docs/rules/array-callback-return"
+        },
+
+        schema: [
+            {
+                type: "object",
+                properties: {
+                    allowImplicit: {
+                        type: "boolean",
+                        default: false
+                    }
+                },
+                additionalProperties: false
+            }
+        ],
+
+        messages: {
+            expectedAtEnd: "Expected to return a value at the end of {{name}}.",
+            expectedInside: "Expected to return a value in {{name}}.",
+            expectedReturnValue: "{{name}} expected a return value."
+        }
+    },
+
+    create(context) {
+
+        const options = context.options[0] || { allowImplicit: false };
+
+        let funcInfo = {
+            upper: null,
+            codePath: null,
+            hasReturn: false,
+            shouldCheck: false,
+            node: null
+        };
+
+        /**
+         * Checks whether or not the last code path segment is reachable.
+         * Then reports this function if the segment is reachable.
+         *
+         * If the last code path segment is reachable, there are paths which are not
+         * returned or thrown.
+         * @param {ASTNode} node A node to check.
+         * @returns {void}
+         */
+        function checkLastSegment(node) {
+            if (funcInfo.shouldCheck &&
+                funcInfo.codePath.currentSegments.some(isReachable)
+            ) {
+                context.report({
+                    node,
+                    loc: getLocation(node, context.getSourceCode()).loc.start,
+                    messageId: funcInfo.hasReturn
+                        ? "expectedAtEnd"
+                        : "expectedInside",
+                    data: {
+                        name: astUtils.getFunctionNameWithKind(funcInfo.node)
+                    }
+                });
+            }
+        }
+
+        return {
+
+            // Stacks this function's information.
+            onCodePathStart(codePath, node) {
+                funcInfo = {
+                    upper: funcInfo,
+                    codePath,
+                    hasReturn: false,
+                    shouldCheck:
+                        TARGET_NODE_TYPE.test(node.type) &&
+                        node.body.type === "BlockStatement" &&
+                        isCallbackOfArrayMethod(node) &&
+                        !node.async &&
+                        !node.generator,
+                    node
+                };
+            },
+
+            // Pops this function's information.
+            onCodePathEnd() {
+                funcInfo = funcInfo.upper;
+            },
+
+            // Checks the return statement is valid.
+            ReturnStatement(node) {
+                if (funcInfo.shouldCheck) {
+                    funcInfo.hasReturn = true;
+
+                    // if allowImplicit: false, should also check node.argument
+                    if (!options.allowImplicit && !node.argument) {
+                        context.report({
+                            node,
+                            messageId: "expectedReturnValue",
+                            data: {
+                                name: lodash.upperFirst(astUtils.getFunctionNameWithKind(funcInfo.node))
+                            }
+                        });
+                    }
+                }
+            },
+
+            // Reports a given function if the last path is reachable.
+            "FunctionExpression:exit": checkLastSegment,
+            "ArrowFunctionExpression:exit": checkLastSegment
+        };
+    }
+};