summaryrefslogtreecommitdiff
path: root/tools/node_modules/eslint/lib/rules/dot-notation.js
diff options
context:
space:
mode:
Diffstat (limited to 'tools/node_modules/eslint/lib/rules/dot-notation.js')
-rw-r--r--tools/node_modules/eslint/lib/rules/dot-notation.js159
1 files changed, 159 insertions, 0 deletions
diff --git a/tools/node_modules/eslint/lib/rules/dot-notation.js b/tools/node_modules/eslint/lib/rules/dot-notation.js
new file mode 100644
index 0000000000..21e3df1741
--- /dev/null
+++ b/tools/node_modules/eslint/lib/rules/dot-notation.js
@@ -0,0 +1,159 @@
+/**
+ * @fileoverview Rule to warn about using dot notation instead of square bracket notation when possible.
+ * @author Josh Perez
+ */
+"use strict";
+
+//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+const astUtils = require("../ast-utils");
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+const validIdentifier = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
+const keywords = require("../util/keywords");
+
+module.exports = {
+ meta: {
+ docs: {
+ description: "enforce dot notation whenever possible",
+ category: "Best Practices",
+ recommended: false
+ },
+
+ schema: [
+ {
+ type: "object",
+ properties: {
+ allowKeywords: {
+ type: "boolean"
+ },
+ allowPattern: {
+ type: "string"
+ }
+ },
+ additionalProperties: false
+ }
+ ],
+
+ fixable: "code"
+ },
+
+ create(context) {
+ const options = context.options[0] || {};
+ const allowKeywords = options.allowKeywords === void 0 || !!options.allowKeywords;
+ const sourceCode = context.getSourceCode();
+
+ let allowPattern;
+
+ if (options.allowPattern) {
+ allowPattern = new RegExp(options.allowPattern);
+ }
+
+ /**
+ * Check if the property is valid dot notation
+ * @param {ASTNode} node The dot notation node
+ * @param {string} value Value which is to be checked
+ * @returns {void}
+ */
+ function checkComputedProperty(node, value) {
+ if (
+ validIdentifier.test(value) &&
+ (allowKeywords || keywords.indexOf(String(value)) === -1) &&
+ !(allowPattern && allowPattern.test(value))
+ ) {
+ const formattedValue = node.property.type === "Literal" ? JSON.stringify(value) : `\`${value}\``;
+
+ context.report({
+ node: node.property,
+ message: "[{{propertyValue}}] is better written in dot notation.",
+ data: {
+ propertyValue: formattedValue
+ },
+ fix(fixer) {
+ const leftBracket = sourceCode.getTokenAfter(node.object, astUtils.isOpeningBracketToken);
+ const rightBracket = sourceCode.getLastToken(node);
+
+ if (sourceCode.getFirstTokenBetween(leftBracket, rightBracket, { includeComments: true, filter: astUtils.isCommentToken })) {
+
+ // Don't perform any fixes if there are comments inside the brackets.
+ return null;
+ }
+
+ const tokenAfterProperty = sourceCode.getTokenAfter(rightBracket);
+ const needsSpaceAfterProperty = tokenAfterProperty &&
+ rightBracket.range[1] === tokenAfterProperty.range[0] &&
+ !astUtils.canTokensBeAdjacent(String(value), tokenAfterProperty);
+
+ const textBeforeDot = astUtils.isDecimalInteger(node.object) ? " " : "";
+ const textAfterProperty = needsSpaceAfterProperty ? " " : "";
+
+ return fixer.replaceTextRange(
+ [leftBracket.range[0], rightBracket.range[1]],
+ `${textBeforeDot}.${value}${textAfterProperty}`
+ );
+ }
+ });
+ }
+ }
+
+ return {
+ MemberExpression(node) {
+ if (
+ node.computed &&
+ node.property.type === "Literal"
+ ) {
+ checkComputedProperty(node, node.property.value);
+ }
+ if (
+ node.computed &&
+ node.property.type === "TemplateLiteral" &&
+ node.property.expressions.length === 0
+ ) {
+ checkComputedProperty(node, node.property.quasis[0].value.cooked);
+ }
+ if (
+ !allowKeywords &&
+ !node.computed &&
+ keywords.indexOf(String(node.property.name)) !== -1
+ ) {
+ context.report({
+ node: node.property,
+ message: ".{{propertyName}} is a syntax error.",
+ data: {
+ propertyName: node.property.name
+ },
+ fix(fixer) {
+ const dot = sourceCode.getTokenBefore(node.property);
+ const textAfterDot = sourceCode.text.slice(dot.range[1], node.property.range[0]);
+
+ if (textAfterDot.trim()) {
+
+ // Don't perform any fixes if there are comments between the dot and the property name.
+ return null;
+ }
+
+ if (node.object.type === "Identifier" && node.object.name === "let") {
+
+ /*
+ * A statement that starts with `let[` is parsed as a destructuring variable declaration, not
+ * a MemberExpression.
+ */
+ return null;
+ }
+
+ return fixer.replaceTextRange(
+ [dot.range[0], node.property.range[1]],
+ `[${textAfterDot}"${node.property.name}"]`
+ );
+ }
+ });
+ }
+ }
+ };
+ }
+};