UNPKG

4.55 kBJavaScriptView Raw
1/**
2 * @fileoverview Rule to warn about using dot notation instead of square bracket notation when possible.
3 * @author Josh Perez
4 */
5"use strict";
6
7//------------------------------------------------------------------------------
8// Rule Definition
9//------------------------------------------------------------------------------
10
11const validIdentifier = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/;
12const keywords = require("../util/keywords");
13
14module.exports = {
15 meta: {
16 docs: {
17 description: "enforce dot notation whenever possible",
18 category: "Best Practices",
19 recommended: false
20 },
21
22 schema: [
23 {
24 type: "object",
25 properties: {
26 allowKeywords: {
27 type: "boolean"
28 },
29 allowPattern: {
30 type: "string"
31 }
32 },
33 additionalProperties: false
34 }
35 ],
36
37 fixable: "code"
38 },
39
40 create(context) {
41 const options = context.options[0] || {};
42 const allowKeywords = options.allowKeywords === void 0 || !!options.allowKeywords;
43 const sourceCode = context.getSourceCode();
44
45 let allowPattern;
46
47 if (options.allowPattern) {
48 allowPattern = new RegExp(options.allowPattern);
49 }
50
51 return {
52 MemberExpression(node) {
53 if (
54 node.computed &&
55 node.property.type === "Literal" &&
56 validIdentifier.test(node.property.value) &&
57 (allowKeywords || keywords.indexOf(String(node.property.value)) === -1)
58 ) {
59 if (!(allowPattern && allowPattern.test(node.property.value))) {
60 context.report({
61 node: node.property,
62 message: "[{{propertyValue}}] is better written in dot notation.",
63 data: {
64 propertyValue: JSON.stringify(node.property.value)
65 },
66 fix(fixer) {
67 const leftBracket = sourceCode.getTokenBefore(node.property);
68 const rightBracket = sourceCode.getTokenAfter(node.property);
69 const textBeforeProperty = sourceCode.text.slice(leftBracket.range[1], node.property.range[0]);
70 const textAfterProperty = sourceCode.text.slice(node.property.range[1], rightBracket.range[0]);
71
72 if (textBeforeProperty.trim() || textAfterProperty.trim()) {
73
74 // Don't perform any fixes if there are comments inside the brackets.
75 return null;
76 }
77
78 return fixer.replaceTextRange(
79 [leftBracket.range[0], rightBracket.range[1]],
80 `.${node.property.value}`
81 );
82 }
83 });
84 }
85 }
86 if (
87 !allowKeywords &&
88 !node.computed &&
89 keywords.indexOf(String(node.property.name)) !== -1
90 ) {
91 context.report({
92 node: node.property,
93 message: ".{{propertyName}} is a syntax error.",
94 data: {
95 propertyName: node.property.name
96 },
97 fix(fixer) {
98 const dot = sourceCode.getTokenBefore(node.property);
99 const textAfterDot = sourceCode.text.slice(dot.range[1], node.property.range[0]);
100
101 if (textAfterDot.trim()) {
102
103 // Don't perform any fixes if there are comments between the dot and the property name.
104 return null;
105 }
106
107 return fixer.replaceTextRange(
108 [dot.range[0], node.property.range[1]],
109 `[${textAfterDot}"${node.property.name}"]`
110 );
111 }
112 });
113 }
114 }
115 };
116 }
117};