/** * Ensures that a property's key is quoted only when necessary * @param {ASTNode} node Property AST node * @returns {void} */ function checkUnnecessaryQuotes(node) { var key = node.key, isKeywordToken, tokens; if (node.method || node.computed || node.shorthand) { return; } if (key.type === "Literal" && typeof key.value === "string") { try { tokens = espree.tokenize(key.value); } catch (e) { return; } if (tokens.length !== 1) { return; } isKeywordToken = isKeyword(tokens[0].value); if (isKeywordToken && KEYWORDS) { return; } if (CHECK_UNNECESSARY && areQuotesRedundant(tokens, NUMBERS)) { context.report(node, MESSAGE_UNNECESSARY, {property: key.value}); } } else if (KEYWORDS && key.type === "Identifier" && isKeyword(key.name)) { context.report(node, MESSAGE_RESERVED, {property: key.name}); } else if (NUMBERS && key.type === "Literal" && typeof key.value === "number") { context.report(node, MESSAGE_NUMERIC, {property: key.value}); } }
node.properties.forEach(function(property) { var key = property.key, tokens; if (!key || property.method || property.computed || property.shorthand) { return; } if (key.type === "Literal" && typeof key.value === "string") { quotes = true; if (checkQuotesRedundancy) { try { tokens = espree.tokenize(key.value); } catch (e) { necessaryQuotes = true; return; } necessaryQuotes = necessaryQuotes || !areQuotesRedundant(tokens) || KEYWORDS && isKeyword(tokens[0].value); } } else if (KEYWORDS && checkQuotesRedundancy && key.type === "Identifier" && isKeyword(key.name)) { necessaryQuotes = true; context.report(node, "Properties should be quoted as `{{property}}` is a reserved word.", {property: key.name}); } else { lackOfQuotes = true; } if (quotes && lackOfQuotes) { context.report(node, "Inconsistently quoted property `{{key}}` found.", { key: key.name || key.value }); } });
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 (e) { 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); } });
/** * 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 (e) { 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, message: MESSAGE_UNNECESSARY, data: { property: key.value }, fix: fixer => fixer.replaceText(key, getUnquotedKey(key)) }); } } else if (KEYWORDS && key.type === "Identifier" && isKeyword(key.name)) { context.report({ node, message: MESSAGE_RESERVED, data: { property: key.name }, fix: fixer => fixer.replaceText(key, getQuotedKey(key)) }); } else if (NUMBERS && key.type === "Literal" && typeof key.value === "number") { context.report({ node, message: MESSAGE_NUMERIC, data: { property: key.value }, fix: fixer => fixer.replaceText(key, getQuotedKey(key)) }); } }
/** * Ensures that a property's key is quoted only when necessary * @param {ASTNode} node Property AST node * @returns {void} */ function asNeeded(node) { var key = node.key, tokens; if (key.type === "Literal" && typeof key.value === "string") { try { tokens = espree.tokenize(key.value); } catch (e) { return; } if (tokens.length === 1 && (["Identifier", "Null", "Boolean"].indexOf(tokens[0].type) >= 0 || (tokens[0].type === "Numeric" && "" + +tokens[0].value === tokens[0].value)) ) { context.report(node, "Unnecessarily quoted property `{{value}}` found.", key); } } }
*/ return node.type === "Literal" && node.value === null && !node.regex; }, /** * Determines whether two tokens can safely be placed next to each other without merging into a single token * @param {Token|string} leftValue The left token. If this is a string, it will be tokenized and the last token will be used. * @param {Token|string} rightValue The right token. If this is a string, it will be tokenized and the first token will be used. * @returns {boolean} If the tokens cannot be safely placed next to each other, returns `false`. If the tokens can be placed * next to each other, behavior is undefined (although it should return `true` in most cases). */ canTokensBeAdjacent(leftValue, rightValue) { let leftToken; if (typeof leftValue === "string") { const leftTokens = espree.tokenize(leftValue, { ecmaVersion: 2015 }); leftToken = leftTokens[leftTokens.length - 1]; } else { leftToken = leftValue; } const rightToken = typeof rightValue === "string" ? espree.tokenize(rightValue, { ecmaVersion: 2015 })[0] : rightValue; if (leftToken.type === "Punctuator" || rightToken.type === "Punctuator") { if (leftToken.type === "Punctuator" && rightToken.type === "Punctuator") { const PLUS_TOKENS = new Set(["+", "++"]); const MINUS_TOKENS = new Set(["-", "--"]); return !( PLUS_TOKENS.has(leftToken.value) && PLUS_TOKENS.has(rightToken.value) ||