Actualizacion maquina principal
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / eslint / lib / rules / no-self-assign.js
diff --git a/.config/coc/extensions/node_modules/coc-prettier/node_modules/eslint/lib/rules/no-self-assign.js b/.config/coc/extensions/node_modules/coc-prettier/node_modules/eslint/lib/rules/no-self-assign.js
new file mode 100644 (file)
index 0000000..705d0f4
--- /dev/null
@@ -0,0 +1,229 @@
+/**
+ * @fileoverview Rule to disallow assignments where both sides are exactly the same
+ * @author Toru Nagashima
+ */
+
+"use strict";
+
+//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+const astUtils = require("./utils/ast-utils");
+
+//------------------------------------------------------------------------------
+// Helpers
+//------------------------------------------------------------------------------
+
+const SPACES = /\s+/gu;
+
+/**
+ * Checks whether the property of 2 given member expression nodes are the same
+ * property or not.
+ * @param {ASTNode} left A member expression node to check.
+ * @param {ASTNode} right Another member expression node to check.
+ * @returns {boolean} `true` if the member expressions have the same property.
+ */
+function isSameProperty(left, right) {
+    if (left.property.type === "Identifier" &&
+        left.property.type === right.property.type &&
+        left.property.name === right.property.name &&
+        left.computed === right.computed
+    ) {
+        return true;
+    }
+
+    const lname = astUtils.getStaticPropertyName(left);
+    const rname = astUtils.getStaticPropertyName(right);
+
+    return lname !== null && lname === rname;
+}
+
+/**
+ * Checks whether 2 given member expression nodes are the reference to the same
+ * property or not.
+ * @param {ASTNode} left A member expression node to check.
+ * @param {ASTNode} right Another member expression node to check.
+ * @returns {boolean} `true` if the member expressions are the reference to the
+ *  same property or not.
+ */
+function isSameMember(left, right) {
+    if (!isSameProperty(left, right)) {
+        return false;
+    }
+
+    const lobj = left.object;
+    const robj = right.object;
+
+    if (lobj.type !== robj.type) {
+        return false;
+    }
+    if (lobj.type === "MemberExpression") {
+        return isSameMember(lobj, robj);
+    }
+    if (lobj.type === "ThisExpression") {
+        return true;
+    }
+    return lobj.type === "Identifier" && lobj.name === robj.name;
+}
+
+/**
+ * Traverses 2 Pattern nodes in parallel, then reports self-assignments.
+ * @param {ASTNode|null} left A left node to traverse. This is a Pattern or
+ *      a Property.
+ * @param {ASTNode|null} right A right node to traverse. This is a Pattern or
+ *      a Property.
+ * @param {boolean} props The flag to check member expressions as well.
+ * @param {Function} report A callback function to report.
+ * @returns {void}
+ */
+function eachSelfAssignment(left, right, props, report) {
+    if (!left || !right) {
+
+        // do nothing
+    } else if (
+        left.type === "Identifier" &&
+        right.type === "Identifier" &&
+        left.name === right.name
+    ) {
+        report(right);
+    } else if (
+        left.type === "ArrayPattern" &&
+        right.type === "ArrayExpression"
+    ) {
+        const end = Math.min(left.elements.length, right.elements.length);
+
+        for (let i = 0; i < end; ++i) {
+            const leftElement = left.elements[i];
+            const rightElement = right.elements[i];
+
+            // Avoid cases such as [...a] = [...a, 1]
+            if (
+                leftElement &&
+                leftElement.type === "RestElement" &&
+                i < right.elements.length - 1
+            ) {
+                break;
+            }
+
+            eachSelfAssignment(leftElement, rightElement, props, report);
+
+            // After a spread element, those indices are unknown.
+            if (rightElement && rightElement.type === "SpreadElement") {
+                break;
+            }
+        }
+    } else if (
+        left.type === "RestElement" &&
+        right.type === "SpreadElement"
+    ) {
+        eachSelfAssignment(left.argument, right.argument, props, report);
+    } else if (
+        left.type === "ObjectPattern" &&
+        right.type === "ObjectExpression" &&
+        right.properties.length >= 1
+    ) {
+
+        /*
+         * Gets the index of the last spread property.
+         * It's possible to overwrite properties followed by it.
+         */
+        let startJ = 0;
+
+        for (let i = right.properties.length - 1; i >= 0; --i) {
+            const propType = right.properties[i].type;
+
+            if (propType === "SpreadElement" || propType === "ExperimentalSpreadProperty") {
+                startJ = i + 1;
+                break;
+            }
+        }
+
+        for (let i = 0; i < left.properties.length; ++i) {
+            for (let j = startJ; j < right.properties.length; ++j) {
+                eachSelfAssignment(
+                    left.properties[i],
+                    right.properties[j],
+                    props,
+                    report
+                );
+            }
+        }
+    } else if (
+        left.type === "Property" &&
+        right.type === "Property" &&
+        right.kind === "init" &&
+        !right.method
+    ) {
+        const leftName = astUtils.getStaticPropertyName(left);
+
+        if (leftName !== null && leftName === astUtils.getStaticPropertyName(right)) {
+            eachSelfAssignment(left.value, right.value, props, report);
+        }
+    } else if (
+        props &&
+        left.type === "MemberExpression" &&
+        right.type === "MemberExpression" &&
+        isSameMember(left, right)
+    ) {
+        report(right);
+    }
+}
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = {
+    meta: {
+        type: "problem",
+
+        docs: {
+            description: "disallow assignments where both sides are exactly the same",
+            category: "Best Practices",
+            recommended: true,
+            url: "https://eslint.org/docs/rules/no-self-assign"
+        },
+
+        schema: [
+            {
+                type: "object",
+                properties: {
+                    props: {
+                        type: "boolean",
+                        default: true
+                    }
+                },
+                additionalProperties: false
+            }
+        ]
+    },
+
+    create(context) {
+        const sourceCode = context.getSourceCode();
+        const [{ props = true } = {}] = context.options;
+
+        /**
+         * Reports a given node as self assignments.
+         * @param {ASTNode} node A node to report. This is an Identifier node.
+         * @returns {void}
+         */
+        function report(node) {
+            context.report({
+                node,
+                message: "'{{name}}' is assigned to itself.",
+                data: {
+                    name: sourceCode.getText(node).replace(SPACES, "")
+                }
+            });
+        }
+
+        return {
+            AssignmentExpression(node) {
+                if (node.operator === "=") {
+                    eachSelfAssignment(node.left, node.right, props, report);
+                }
+            }
+        };
+    }
+};