]>
git.proxmox.com Git - pve-eslint.git/blob - eslint/lib/rules/dot-notation.js
2 * @fileoverview Rule to warn about using dot notation instead of square bracket notation when possible.
7 //------------------------------------------------------------------------------
9 //------------------------------------------------------------------------------
11 const astUtils
= require("./utils/ast-utils");
12 const keywords
= require("./utils/keywords");
14 //------------------------------------------------------------------------------
16 //------------------------------------------------------------------------------
18 const validIdentifier
= /^[a-zA-Z_$][a-zA-Z0-9_$]*$/u;
20 // `null` literal must be handled separately.
21 const literalTypesToCheck
= new Set(["string", "boolean"]);
28 description
: "enforce dot notation whenever possible",
29 category
: "Best Practices",
31 url
: "https://eslint.org/docs/rules/dot-notation"
47 additionalProperties
: false
54 useDot
: "[{{key}}] is better written in dot notation.",
55 useBrackets
: ".{{key}} is a syntax error."
60 const options
= context
.options
[0] || {};
61 const allowKeywords
= options
.allowKeywords
=== void 0 || options
.allowKeywords
;
62 const sourceCode
= context
.getSourceCode();
66 if (options
.allowPattern
) {
67 allowPattern
= new RegExp(options
.allowPattern
, "u");
71 * Check if the property is valid dot notation
72 * @param {ASTNode} node The dot notation node
73 * @param {string} value Value which is to be checked
76 function checkComputedProperty(node
, value
) {
78 validIdentifier
.test(value
) &&
79 (allowKeywords
|| keywords
.indexOf(String(value
)) === -1) &&
80 !(allowPattern
&& allowPattern
.test(value
))
82 const formattedValue
= node
.property
.type
=== "Literal" ? JSON
.stringify(value
) : `\`${value}
\``;
91 const leftBracket
= sourceCode
.getTokenAfter(node
.object
, astUtils
.isOpeningBracketToken
);
92 const rightBracket
= sourceCode
.getLastToken(node
);
93 const nextToken
= sourceCode
.getTokenAfter(node
);
95 // Don't perform any fixes if there are comments inside the brackets.
96 if (sourceCode
.commentsExistBetween(leftBracket
, rightBracket
)) {
97 return; // eslint-disable-line eslint-plugin/fixer-return -- false positive
100 // Replace the brackets by an identifier.
101 if (!node
.optional
) {
102 yield fixer
.insertTextBefore(
104 astUtils
.isDecimalInteger(node
.object
) ? " ." : "."
107 yield fixer
.replaceTextRange(
108 [leftBracket
.range
[0], rightBracket
.range
[1]],
112 // Insert a space after the property if it will be connected to the next token.
115 rightBracket
.range
[1] === nextToken
.range
[0] &&
116 !astUtils
.canTokensBeAdjacent(String(value
), nextToken
)
118 yield fixer
.insertTextAfter(node
, " ");
126 MemberExpression(node
) {
129 node
.property
.type
=== "Literal" &&
130 (literalTypesToCheck
.has(typeof node
.property
.value
) || astUtils
.isNullLiteral(node
.property
))
132 checkComputedProperty(node
, node
.property
.value
);
136 node
.property
.type
=== "TemplateLiteral" &&
137 node
.property
.expressions
.length
=== 0
139 checkComputedProperty(node
, node
.property
.quasis
[0].value
.cooked
);
144 keywords
.indexOf(String(node
.property
.name
)) !== -1
148 messageId
: "useBrackets",
150 key
: node
.property
.name
153 const dotToken
= sourceCode
.getTokenBefore(node
.property
);
155 // A statement that starts with `let[` is parsed as a destructuring variable declaration, not a MemberExpression.
156 if (node
.object
.type
=== "Identifier" && node
.object
.name
=== "let" && !node
.optional
) {
157 return; // eslint-disable-line eslint-plugin/fixer-return -- false positive
160 // Don't perform any fixes if there are comments between the dot and the property name.
161 if (sourceCode
.commentsExistBetween(dotToken
, node
.property
)) {
162 return; // eslint-disable-line eslint-plugin/fixer-return -- false positive
165 // Replace the identifier to brackets.
166 if (!node
.optional
) {
167 yield fixer
.remove(dotToken
);
169 yield fixer
.replaceText(node
.property
, `["${node.property.name}"]`);