Actualizacion maquina principal
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / eslint / lib / rules / key-spacing.js
diff --git a/.config/coc/extensions/node_modules/coc-prettier/node_modules/eslint/lib/rules/key-spacing.js b/.config/coc/extensions/node_modules/coc-prettier/node_modules/eslint/lib/rules/key-spacing.js
new file mode 100644 (file)
index 0000000..6d1b912
--- /dev/null
@@ -0,0 +1,671 @@
+/**
+ * @fileoverview Rule to specify spacing of object literal keys and values
+ * @author Brandon Mills
+ */
+"use strict";
+
+//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+const astUtils = require("./utils/ast-utils");
+
+//------------------------------------------------------------------------------
+// Helpers
+//------------------------------------------------------------------------------
+
+/**
+ * Checks whether a string contains a line terminator as defined in
+ * http://www.ecma-international.org/ecma-262/5.1/#sec-7.3
+ * @param {string} str String to test.
+ * @returns {boolean} True if str contains a line terminator.
+ */
+function containsLineTerminator(str) {
+    return astUtils.LINEBREAK_MATCHER.test(str);
+}
+
+/**
+ * Gets the last element of an array.
+ * @param {Array} arr An array.
+ * @returns {any} Last element of arr.
+ */
+function last(arr) {
+    return arr[arr.length - 1];
+}
+
+/**
+ * Checks whether a node is contained on a single line.
+ * @param {ASTNode} node AST Node being evaluated.
+ * @returns {boolean} True if the node is a single line.
+ */
+function isSingleLine(node) {
+    return (node.loc.end.line === node.loc.start.line);
+}
+
+/**
+ * Checks whether the properties on a single line.
+ * @param {ASTNode[]} properties List of Property AST nodes.
+ * @returns {boolean} True if all properies is on a single line.
+ */
+function isSingleLineProperties(properties) {
+    const [firstProp] = properties,
+        lastProp = last(properties);
+
+    return firstProp.loc.start.line === lastProp.loc.end.line;
+}
+
+/**
+ * Initializes a single option property from the configuration with defaults for undefined values
+ * @param {Object} toOptions Object to be initialized
+ * @param {Object} fromOptions Object to be initialized from
+ * @returns {Object} The object with correctly initialized options and values
+ */
+function initOptionProperty(toOptions, fromOptions) {
+    toOptions.mode = fromOptions.mode || "strict";
+
+    // Set value of beforeColon
+    if (typeof fromOptions.beforeColon !== "undefined") {
+        toOptions.beforeColon = +fromOptions.beforeColon;
+    } else {
+        toOptions.beforeColon = 0;
+    }
+
+    // Set value of afterColon
+    if (typeof fromOptions.afterColon !== "undefined") {
+        toOptions.afterColon = +fromOptions.afterColon;
+    } else {
+        toOptions.afterColon = 1;
+    }
+
+    // Set align if exists
+    if (typeof fromOptions.align !== "undefined") {
+        if (typeof fromOptions.align === "object") {
+            toOptions.align = fromOptions.align;
+        } else { // "string"
+            toOptions.align = {
+                on: fromOptions.align,
+                mode: toOptions.mode,
+                beforeColon: toOptions.beforeColon,
+                afterColon: toOptions.afterColon
+            };
+        }
+    }
+
+    return toOptions;
+}
+
+/**
+ * Initializes all the option values (singleLine, multiLine and align) from the configuration with defaults for undefined values
+ * @param {Object} toOptions Object to be initialized
+ * @param {Object} fromOptions Object to be initialized from
+ * @returns {Object} The object with correctly initialized options and values
+ */
+function initOptions(toOptions, fromOptions) {
+    if (typeof fromOptions.align === "object") {
+
+        // Initialize the alignment configuration
+        toOptions.align = initOptionProperty({}, fromOptions.align);
+        toOptions.align.on = fromOptions.align.on || "colon";
+        toOptions.align.mode = fromOptions.align.mode || "strict";
+
+        toOptions.multiLine = initOptionProperty({}, (fromOptions.multiLine || fromOptions));
+        toOptions.singleLine = initOptionProperty({}, (fromOptions.singleLine || fromOptions));
+
+    } else { // string or undefined
+        toOptions.multiLine = initOptionProperty({}, (fromOptions.multiLine || fromOptions));
+        toOptions.singleLine = initOptionProperty({}, (fromOptions.singleLine || fromOptions));
+
+        // If alignment options are defined in multiLine, pull them out into the general align configuration
+        if (toOptions.multiLine.align) {
+            toOptions.align = {
+                on: toOptions.multiLine.align.on,
+                mode: toOptions.multiLine.align.mode || toOptions.multiLine.mode,
+                beforeColon: toOptions.multiLine.align.beforeColon,
+                afterColon: toOptions.multiLine.align.afterColon
+            };
+        }
+    }
+
+    return toOptions;
+}
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = {
+    meta: {
+        type: "layout",
+
+        docs: {
+            description: "enforce consistent spacing between keys and values in object literal properties",
+            category: "Stylistic Issues",
+            recommended: false,
+            url: "https://eslint.org/docs/rules/key-spacing"
+        },
+
+        fixable: "whitespace",
+
+        schema: [{
+            anyOf: [
+                {
+                    type: "object",
+                    properties: {
+                        align: {
+                            anyOf: [
+                                {
+                                    enum: ["colon", "value"]
+                                },
+                                {
+                                    type: "object",
+                                    properties: {
+                                        mode: {
+                                            enum: ["strict", "minimum"]
+                                        },
+                                        on: {
+                                            enum: ["colon", "value"]
+                                        },
+                                        beforeColon: {
+                                            type: "boolean"
+                                        },
+                                        afterColon: {
+                                            type: "boolean"
+                                        }
+                                    },
+                                    additionalProperties: false
+                                }
+                            ]
+                        },
+                        mode: {
+                            enum: ["strict", "minimum"]
+                        },
+                        beforeColon: {
+                            type: "boolean"
+                        },
+                        afterColon: {
+                            type: "boolean"
+                        }
+                    },
+                    additionalProperties: false
+                },
+                {
+                    type: "object",
+                    properties: {
+                        singleLine: {
+                            type: "object",
+                            properties: {
+                                mode: {
+                                    enum: ["strict", "minimum"]
+                                },
+                                beforeColon: {
+                                    type: "boolean"
+                                },
+                                afterColon: {
+                                    type: "boolean"
+                                }
+                            },
+                            additionalProperties: false
+                        },
+                        multiLine: {
+                            type: "object",
+                            properties: {
+                                align: {
+                                    anyOf: [
+                                        {
+                                            enum: ["colon", "value"]
+                                        },
+                                        {
+                                            type: "object",
+                                            properties: {
+                                                mode: {
+                                                    enum: ["strict", "minimum"]
+                                                },
+                                                on: {
+                                                    enum: ["colon", "value"]
+                                                },
+                                                beforeColon: {
+                                                    type: "boolean"
+                                                },
+                                                afterColon: {
+                                                    type: "boolean"
+                                                }
+                                            },
+                                            additionalProperties: false
+                                        }
+                                    ]
+                                },
+                                mode: {
+                                    enum: ["strict", "minimum"]
+                                },
+                                beforeColon: {
+                                    type: "boolean"
+                                },
+                                afterColon: {
+                                    type: "boolean"
+                                }
+                            },
+                            additionalProperties: false
+                        }
+                    },
+                    additionalProperties: false
+                },
+                {
+                    type: "object",
+                    properties: {
+                        singleLine: {
+                            type: "object",
+                            properties: {
+                                mode: {
+                                    enum: ["strict", "minimum"]
+                                },
+                                beforeColon: {
+                                    type: "boolean"
+                                },
+                                afterColon: {
+                                    type: "boolean"
+                                }
+                            },
+                            additionalProperties: false
+                        },
+                        multiLine: {
+                            type: "object",
+                            properties: {
+                                mode: {
+                                    enum: ["strict", "minimum"]
+                                },
+                                beforeColon: {
+                                    type: "boolean"
+                                },
+                                afterColon: {
+                                    type: "boolean"
+                                }
+                            },
+                            additionalProperties: false
+                        },
+                        align: {
+                            type: "object",
+                            properties: {
+                                mode: {
+                                    enum: ["strict", "minimum"]
+                                },
+                                on: {
+                                    enum: ["colon", "value"]
+                                },
+                                beforeColon: {
+                                    type: "boolean"
+                                },
+                                afterColon: {
+                                    type: "boolean"
+                                }
+                            },
+                            additionalProperties: false
+                        }
+                    },
+                    additionalProperties: false
+                }
+            ]
+        }],
+        messages: {
+            extraKey: "Extra space after {{computed}}key '{{key}}'.",
+            extraValue: "Extra space before value for {{computed}}key '{{key}}'.",
+            missingKey: "Missing space after {{computed}}key '{{key}}'.",
+            missingValue: "Missing space before value for {{computed}}key '{{key}}'."
+        }
+    },
+
+    create(context) {
+
+        /**
+         * OPTIONS
+         * "key-spacing": [2, {
+         *     beforeColon: false,
+         *     afterColon: true,
+         *     align: "colon" // Optional, or "value"
+         * }
+         */
+        const options = context.options[0] || {},
+            ruleOptions = initOptions({}, options),
+            multiLineOptions = ruleOptions.multiLine,
+            singleLineOptions = ruleOptions.singleLine,
+            alignmentOptions = ruleOptions.align || null;
+
+        const sourceCode = context.getSourceCode();
+
+        /**
+         * Checks whether a property is a member of the property group it follows.
+         * @param {ASTNode} lastMember The last Property known to be in the group.
+         * @param {ASTNode} candidate The next Property that might be in the group.
+         * @returns {boolean} True if the candidate property is part of the group.
+         */
+        function continuesPropertyGroup(lastMember, candidate) {
+            const groupEndLine = lastMember.loc.start.line,
+                candidateStartLine = candidate.loc.start.line;
+
+            if (candidateStartLine - groupEndLine <= 1) {
+                return true;
+            }
+
+            /*
+             * Check that the first comment is adjacent to the end of the group, the
+             * last comment is adjacent to the candidate property, and that successive
+             * comments are adjacent to each other.
+             */
+            const leadingComments = sourceCode.getCommentsBefore(candidate);
+
+            if (
+                leadingComments.length &&
+                leadingComments[0].loc.start.line - groupEndLine <= 1 &&
+                candidateStartLine - last(leadingComments).loc.end.line <= 1
+            ) {
+                for (let i = 1; i < leadingComments.length; i++) {
+                    if (leadingComments[i].loc.start.line - leadingComments[i - 1].loc.end.line > 1) {
+                        return false;
+                    }
+                }
+                return true;
+            }
+
+            return false;
+        }
+
+        /**
+         * Determines if the given property is key-value property.
+         * @param {ASTNode} property Property node to check.
+         * @returns {boolean} Whether the property is a key-value property.
+         */
+        function isKeyValueProperty(property) {
+            return !(
+                (property.method ||
+                property.shorthand ||
+                property.kind !== "init" || property.type !== "Property") // Could be "ExperimentalSpreadProperty" or "SpreadElement"
+            );
+        }
+
+        /**
+         * Starting from the given a node (a property.key node here) looks forward
+         * until it finds the last token before a colon punctuator and returns it.
+         * @param {ASTNode} node The node to start looking from.
+         * @returns {ASTNode} The last token before a colon punctuator.
+         */
+        function getLastTokenBeforeColon(node) {
+            const colonToken = sourceCode.getTokenAfter(node, astUtils.isColonToken);
+
+            return sourceCode.getTokenBefore(colonToken);
+        }
+
+        /**
+         * Starting from the given a node (a property.key node here) looks forward
+         * until it finds the colon punctuator and returns it.
+         * @param {ASTNode} node The node to start looking from.
+         * @returns {ASTNode} The colon punctuator.
+         */
+        function getNextColon(node) {
+            return sourceCode.getTokenAfter(node, astUtils.isColonToken);
+        }
+
+        /**
+         * Gets an object literal property's key as the identifier name or string value.
+         * @param {ASTNode} property Property node whose key to retrieve.
+         * @returns {string} The property's key.
+         */
+        function getKey(property) {
+            const key = property.key;
+
+            if (property.computed) {
+                return sourceCode.getText().slice(key.range[0], key.range[1]);
+            }
+
+            return property.key.name || property.key.value;
+        }
+
+        /**
+         * Reports an appropriately-formatted error if spacing is incorrect on one
+         * side of the colon.
+         * @param {ASTNode} property Key-value pair in an object literal.
+         * @param {string} side Side being verified - either "key" or "value".
+         * @param {string} whitespace Actual whitespace string.
+         * @param {int} expected Expected whitespace length.
+         * @param {string} mode Value of the mode as "strict" or "minimum"
+         * @returns {void}
+         */
+        function report(property, side, whitespace, expected, mode) {
+            const diff = whitespace.length - expected,
+                nextColon = getNextColon(property.key),
+                tokenBeforeColon = sourceCode.getTokenBefore(nextColon, { includeComments: true }),
+                tokenAfterColon = sourceCode.getTokenAfter(nextColon, { includeComments: true }),
+                isKeySide = side === "key",
+                locStart = isKeySide ? tokenBeforeColon.loc.start : tokenAfterColon.loc.start,
+                isExtra = diff > 0,
+                diffAbs = Math.abs(diff),
+                spaces = Array(diffAbs + 1).join(" ");
+
+            if ((
+                diff && mode === "strict" ||
+                diff < 0 && mode === "minimum" ||
+                diff > 0 && !expected && mode === "minimum") &&
+                !(expected && containsLineTerminator(whitespace))
+            ) {
+                let fix;
+
+                if (isExtra) {
+                    let range;
+
+                    // Remove whitespace
+                    if (isKeySide) {
+                        range = [tokenBeforeColon.range[1], tokenBeforeColon.range[1] + diffAbs];
+                    } else {
+                        range = [tokenAfterColon.range[0] - diffAbs, tokenAfterColon.range[0]];
+                    }
+                    fix = function(fixer) {
+                        return fixer.removeRange(range);
+                    };
+                } else {
+
+                    // Add whitespace
+                    if (isKeySide) {
+                        fix = function(fixer) {
+                            return fixer.insertTextAfter(tokenBeforeColon, spaces);
+                        };
+                    } else {
+                        fix = function(fixer) {
+                            return fixer.insertTextBefore(tokenAfterColon, spaces);
+                        };
+                    }
+                }
+
+                let messageId = "";
+
+                if (isExtra) {
+                    messageId = side === "key" ? "extraKey" : "extraValue";
+                } else {
+                    messageId = side === "key" ? "missingKey" : "missingValue";
+                }
+
+                context.report({
+                    node: property[side],
+                    loc: locStart,
+                    messageId,
+                    data: {
+                        computed: property.computed ? "computed " : "",
+                        key: getKey(property)
+                    },
+                    fix
+                });
+            }
+        }
+
+        /**
+         * Gets the number of characters in a key, including quotes around string
+         * keys and braces around computed property keys.
+         * @param {ASTNode} property Property of on object literal.
+         * @returns {int} Width of the key.
+         */
+        function getKeyWidth(property) {
+            const startToken = sourceCode.getFirstToken(property);
+            const endToken = getLastTokenBeforeColon(property.key);
+
+            return endToken.range[1] - startToken.range[0];
+        }
+
+        /**
+         * Gets the whitespace around the colon in an object literal property.
+         * @param {ASTNode} property Property node from an object literal.
+         * @returns {Object} Whitespace before and after the property's colon.
+         */
+        function getPropertyWhitespace(property) {
+            const whitespace = /(\s*):(\s*)/u.exec(sourceCode.getText().slice(
+                property.key.range[1], property.value.range[0]
+            ));
+
+            if (whitespace) {
+                return {
+                    beforeColon: whitespace[1],
+                    afterColon: whitespace[2]
+                };
+            }
+            return null;
+        }
+
+        /**
+         * Creates groups of properties.
+         * @param  {ASTNode} node ObjectExpression node being evaluated.
+         * @returns {Array.<ASTNode[]>} Groups of property AST node lists.
+         */
+        function createGroups(node) {
+            if (node.properties.length === 1) {
+                return [node.properties];
+            }
+
+            return node.properties.reduce((groups, property) => {
+                const currentGroup = last(groups),
+                    prev = last(currentGroup);
+
+                if (!prev || continuesPropertyGroup(prev, property)) {
+                    currentGroup.push(property);
+                } else {
+                    groups.push([property]);
+                }
+
+                return groups;
+            }, [
+                []
+            ]);
+        }
+
+        /**
+         * Verifies correct vertical alignment of a group of properties.
+         * @param {ASTNode[]} properties List of Property AST nodes.
+         * @returns {void}
+         */
+        function verifyGroupAlignment(properties) {
+            const length = properties.length,
+                widths = properties.map(getKeyWidth), // Width of keys, including quotes
+                align = alignmentOptions.on; // "value" or "colon"
+            let targetWidth = Math.max(...widths),
+                beforeColon, afterColon, mode;
+
+            if (alignmentOptions && length > 1) { // When aligning values within a group, use the alignment configuration.
+                beforeColon = alignmentOptions.beforeColon;
+                afterColon = alignmentOptions.afterColon;
+                mode = alignmentOptions.mode;
+            } else {
+                beforeColon = multiLineOptions.beforeColon;
+                afterColon = multiLineOptions.afterColon;
+                mode = alignmentOptions.mode;
+            }
+
+            // Conditionally include one space before or after colon
+            targetWidth += (align === "colon" ? beforeColon : afterColon);
+
+            for (let i = 0; i < length; i++) {
+                const property = properties[i];
+                const whitespace = getPropertyWhitespace(property);
+
+                if (whitespace) { // Object literal getters/setters lack a colon
+                    const width = widths[i];
+
+                    if (align === "value") {
+                        report(property, "key", whitespace.beforeColon, beforeColon, mode);
+                        report(property, "value", whitespace.afterColon, targetWidth - width, mode);
+                    } else { // align = "colon"
+                        report(property, "key", whitespace.beforeColon, targetWidth - width, mode);
+                        report(property, "value", whitespace.afterColon, afterColon, mode);
+                    }
+                }
+            }
+        }
+
+        /**
+         * Verifies spacing of property conforms to specified options.
+         * @param  {ASTNode} node Property node being evaluated.
+         * @param {Object} lineOptions Configured singleLine or multiLine options
+         * @returns {void}
+         */
+        function verifySpacing(node, lineOptions) {
+            const actual = getPropertyWhitespace(node);
+
+            if (actual) { // Object literal getters/setters lack colons
+                report(node, "key", actual.beforeColon, lineOptions.beforeColon, lineOptions.mode);
+                report(node, "value", actual.afterColon, lineOptions.afterColon, lineOptions.mode);
+            }
+        }
+
+        /**
+         * Verifies spacing of each property in a list.
+         * @param {ASTNode[]} properties List of Property AST nodes.
+         * @param {Object} lineOptions Configured singleLine or multiLine options
+         * @returns {void}
+         */
+        function verifyListSpacing(properties, lineOptions) {
+            const length = properties.length;
+
+            for (let i = 0; i < length; i++) {
+                verifySpacing(properties[i], lineOptions);
+            }
+        }
+
+        /**
+         * Verifies vertical alignment, taking into account groups of properties.
+         * @param  {ASTNode} node ObjectExpression node being evaluated.
+         * @returns {void}
+         */
+        function verifyAlignment(node) {
+            createGroups(node).forEach(group => {
+                const properties = group.filter(isKeyValueProperty);
+
+                if (properties.length > 0 && isSingleLineProperties(properties)) {
+                    verifyListSpacing(properties, multiLineOptions);
+                } else {
+                    verifyGroupAlignment(properties);
+                }
+            });
+        }
+
+        //--------------------------------------------------------------------------
+        // Public API
+        //--------------------------------------------------------------------------
+
+        if (alignmentOptions) { // Verify vertical alignment
+
+            return {
+                ObjectExpression(node) {
+                    if (isSingleLine(node)) {
+                        verifyListSpacing(node.properties.filter(isKeyValueProperty), singleLineOptions);
+                    } else {
+                        verifyAlignment(node);
+                    }
+                }
+            };
+
+        }
+
+        // Obey beforeColon and afterColon in each property as configured
+        return {
+            Property(node) {
+                verifySpacing(node, isSingleLine(node.parent) ? singleLineOptions : multiLineOptions);
+            }
+        };
+
+
+    }
+};