|                                                                                                                                                                                                                                                                                                                      |  | /** * @fileoverview Rule to flag non-quoted property names in object literals. * @author Mathias Bynens <http://mathiasbynens.be/>
 * @deprecated in ESLint v8.53.0 */"use strict";
//------------------------------------------------------------------------------
// Requirements
//------------------------------------------------------------------------------
const espree = require("espree");const astUtils = require("./utils/ast-utils");const keywords = require("./utils/keywords");
//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------
/** @type {import('../shared/types').Rule} */module.exports = {    meta: {        deprecated: true,        replacedBy: [],        type: "suggestion",
        docs: {            description: "Require quotes around object literal property names",            recommended: false,            url: "https://eslint.org/docs/latest/rules/quote-props"        },
        schema: {            anyOf: [                {                    type: "array",                    items: [                        {                            enum: ["always", "as-needed", "consistent", "consistent-as-needed"]                        }                    ],                    minItems: 0,                    maxItems: 1                },                {                    type: "array",                    items: [                        {                            enum: ["always", "as-needed", "consistent", "consistent-as-needed"]                        },                        {                            type: "object",                            properties: {                                keywords: {                                    type: "boolean"                                },                                unnecessary: {                                    type: "boolean"                                },                                numbers: {                                    type: "boolean"                                }                            },                            additionalProperties: false                        }                    ],                    minItems: 0,                    maxItems: 2                }            ]        },
        fixable: "code",        messages: {            requireQuotesDueToReservedWord: "Properties should be quoted as '{{property}}' is a reserved word.",            inconsistentlyQuotedProperty: "Inconsistently quoted property '{{key}}' found.",            unnecessarilyQuotedProperty: "Unnecessarily quoted property '{{property}}' found.",            unquotedReservedProperty: "Unquoted reserved word '{{property}}' used as key.",            unquotedNumericProperty: "Unquoted number literal '{{property}}' used as key.",            unquotedPropertyFound: "Unquoted property '{{property}}' found.",            redundantQuoting: "Properties shouldn't be quoted as all quotes are redundant."        }    },
    create(context) {
        const MODE = context.options[0],            KEYWORDS = context.options[1] && context.options[1].keywords,            CHECK_UNNECESSARY = !context.options[1] || context.options[1].unnecessary !== false,            NUMBERS = context.options[1] && context.options[1].numbers,
            sourceCode = context.sourceCode;
        /**         * Checks whether a certain string constitutes an ES3 token         * @param {string} tokenStr The string to be checked.         * @returns {boolean} `true` if it is an ES3 token.         */        function isKeyword(tokenStr) {            return keywords.includes(tokenStr);        }
        /**         * Checks if an espree-tokenized key has redundant quotes (i.e. whether quotes are unnecessary)         * @param {string} rawKey The raw key value from the source         * @param {espreeTokens} tokens The espree-tokenized node key         * @param {boolean} [skipNumberLiterals=false] Indicates whether number literals should be checked         * @returns {boolean} Whether or not a key has redundant quotes.         * @private         */        function areQuotesRedundant(rawKey, tokens, skipNumberLiterals) {            return tokens.length === 1 && tokens[0].start === 0 && tokens[0].end === rawKey.length &&                (["Identifier", "Keyword", "Null", "Boolean"].includes(tokens[0].type) ||                (tokens[0].type === "Numeric" && !skipNumberLiterals && String(+tokens[0].value) === tokens[0].value));        }
        /**         * Returns a string representation of a property node with quotes removed         * @param {ASTNode} key Key AST Node, which may or may not be quoted         * @returns {string} A replacement string for this property         */        function getUnquotedKey(key) {            return key.type === "Identifier" ? key.name : key.value;        }
        /**         * Returns a string representation of a property node with quotes added         * @param {ASTNode} key Key AST Node, which may or may not be quoted         * @returns {string} A replacement string for this property         */        function getQuotedKey(key) {            if (key.type === "Literal" && typeof key.value === "string") {
                // If the key is already a string literal, don't replace the quotes with double quotes.
                return sourceCode.getText(key);            }
            // Otherwise, the key is either an identifier or a number literal.
            return `"${key.type === "Identifier" ? key.name : key.value}"`;        }
        /**         * Ensures that a property's key is quoted only when necessary         * @param {ASTNode} node Property AST node         * @returns {void}         */        function checkUnnecessaryQuotes(node) {            const key = node.key;
            if (node.method || node.computed || node.shorthand) {                return;            }
            if (key.type === "Literal" && typeof key.value === "string") {                let tokens;
                try {                    tokens = espree.tokenize(key.value);                } catch {                    return;                }
                if (tokens.length !== 1) {                    return;                }
                const isKeywordToken = isKeyword(tokens[0].value);
                if (isKeywordToken && KEYWORDS) {                    return;                }
                if (CHECK_UNNECESSARY && areQuotesRedundant(key.value, tokens, NUMBERS)) {                    context.report({                        node,                        messageId: "unnecessarilyQuotedProperty",                        data: { property: key.value },                        fix: fixer => fixer.replaceText(key, getUnquotedKey(key))                    });                }            } else if (KEYWORDS && key.type === "Identifier" && isKeyword(key.name)) {                context.report({                    node,                    messageId: "unquotedReservedProperty",                    data: { property: key.name },                    fix: fixer => fixer.replaceText(key, getQuotedKey(key))                });            } else if (NUMBERS && key.type === "Literal" && astUtils.isNumericLiteral(key)) {                context.report({                    node,                    messageId: "unquotedNumericProperty",                    data: { property: key.value },                    fix: fixer => fixer.replaceText(key, getQuotedKey(key))                });            }        }
        /**         * Ensures that a property's key is quoted         * @param {ASTNode} node Property AST node         * @returns {void}         */        function checkOmittedQuotes(node) {            const key = node.key;
            if (!node.method && !node.computed && !node.shorthand && !(key.type === "Literal" && typeof key.value === "string")) {                context.report({                    node,                    messageId: "unquotedPropertyFound",                    data: { property: key.name || key.value },                    fix: fixer => fixer.replaceText(key, getQuotedKey(key))                });            }        }
        /**         * Ensures that an object's keys are consistently quoted, optionally checks for redundancy of quotes         * @param {ASTNode} node Property AST node         * @param {boolean} checkQuotesRedundancy Whether to check quotes' redundancy         * @returns {void}         */        function checkConsistency(node, checkQuotesRedundancy) {            const quotedProps = [],                unquotedProps = [];            let keywordKeyName = null,                necessaryQuotes = false;
            node.properties.forEach(property => {                const key = property.key;
                if (!key || property.method || property.computed || property.shorthand) {                    return;                }
                if (key.type === "Literal" && typeof key.value === "string") {
                    quotedProps.push(property);
                    if (checkQuotesRedundancy) {                        let tokens;
                        try {                            tokens = espree.tokenize(key.value);                        } catch {                            necessaryQuotes = true;                            return;                        }
                        necessaryQuotes = necessaryQuotes || !areQuotesRedundant(key.value, tokens) || KEYWORDS && isKeyword(tokens[0].value);                    }                } else if (KEYWORDS && checkQuotesRedundancy && key.type === "Identifier" && isKeyword(key.name)) {                    unquotedProps.push(property);                    necessaryQuotes = true;                    keywordKeyName = key.name;                } else {                    unquotedProps.push(property);                }            });
            if (checkQuotesRedundancy && quotedProps.length && !necessaryQuotes) {                quotedProps.forEach(property => {                    context.report({                        node: property,                        messageId: "redundantQuoting",                        fix: fixer => fixer.replaceText(property.key, getUnquotedKey(property.key))                    });                });            } else if (unquotedProps.length && keywordKeyName) {                unquotedProps.forEach(property => {                    context.report({                        node: property,                        messageId: "requireQuotesDueToReservedWord",                        data: { property: keywordKeyName },                        fix: fixer => fixer.replaceText(property.key, getQuotedKey(property.key))                    });                });            } else if (quotedProps.length && unquotedProps.length) {                unquotedProps.forEach(property => {                    context.report({                        node: property,                        messageId: "inconsistentlyQuotedProperty",                        data: { key: property.key.name || property.key.value },                        fix: fixer => fixer.replaceText(property.key, getQuotedKey(property.key))                    });                });            }        }
        return {            Property(node) {                if (MODE === "always" || !MODE) {                    checkOmittedQuotes(node);                }                if (MODE === "as-needed") {                    checkUnnecessaryQuotes(node);                }            },            ObjectExpression(node) {                if (MODE === "consistent") {                    checkConsistency(node, false);                }                if (MODE === "consistent-as-needed") {                    checkConsistency(node, true);                }            }        };
    }};
 |