UNPKG

3.84 kBJavaScriptView Raw
1/**
2 * @fileoverview Rule to disallow unnecessary computed property keys in object literals
3 * @author Burak Yigit Kaya
4 */
5"use strict";
6
7//------------------------------------------------------------------------------
8// Requirements
9//------------------------------------------------------------------------------
10
11const lodash = require("lodash");
12const astUtils = require("./utils/ast-utils");
13
14//------------------------------------------------------------------------------
15// Rule Definition
16//------------------------------------------------------------------------------
17
18module.exports = {
19 meta: {
20 type: "suggestion",
21
22 docs: {
23 description: "disallow unnecessary computed property keys in objects and classes",
24 category: "ECMAScript 6",
25 recommended: false,
26 url: "https://eslint.org/docs/rules/no-useless-computed-key"
27 },
28
29 schema: [{
30 type: "object",
31 properties: {
32 enforceForClassMembers: {
33 type: "boolean",
34 default: false
35 }
36 },
37 additionalProperties: false
38 }],
39 fixable: "code",
40
41 messages: {
42 unnecessarilyComputedProperty: "Unnecessarily computed property [{{property}}] found."
43 }
44 },
45 create(context) {
46 const sourceCode = context.getSourceCode();
47 const enforceForClassMembers = context.options[0] && context.options[0].enforceForClassMembers;
48
49 /**
50 * Reports a given node if it violated this rule.
51 * @param {ASTNode} node The node to check.
52 * @returns {void}
53 */
54 function check(node) {
55 if (!node.computed) {
56 return;
57 }
58
59 const key = node.key,
60 nodeType = typeof key.value;
61
62 let allowedKey;
63
64 if (node.type === "MethodDefinition") {
65 allowedKey = node.static ? "prototype" : "constructor";
66 } else {
67 allowedKey = "__proto__";
68 }
69
70 if (key.type === "Literal" && (nodeType === "string" || nodeType === "number") && key.value !== allowedKey) {
71 context.report({
72 node,
73 messageId: "unnecessarilyComputedProperty",
74 data: { property: sourceCode.getText(key) },
75 fix(fixer) {
76 const leftSquareBracket = sourceCode.getTokenBefore(key, astUtils.isOpeningBracketToken);
77 const rightSquareBracket = sourceCode.getTokenAfter(key, astUtils.isClosingBracketToken);
78
79 // If there are comments between the brackets and the property name, don't do a fix.
80 if (sourceCode.commentsExistBetween(leftSquareBracket, rightSquareBracket)) {
81 return null;
82 }
83
84 const tokenBeforeLeftBracket = sourceCode.getTokenBefore(leftSquareBracket);
85
86 // Insert a space before the key to avoid changing identifiers, e.g. ({ get[2]() {} }) to ({ get2() {} })
87 const needsSpaceBeforeKey = tokenBeforeLeftBracket.range[1] === leftSquareBracket.range[0] &&
88 !astUtils.canTokensBeAdjacent(tokenBeforeLeftBracket, sourceCode.getFirstToken(key));
89
90 const replacementKey = (needsSpaceBeforeKey ? " " : "") + key.raw;
91
92 return fixer.replaceTextRange([leftSquareBracket.range[0], rightSquareBracket.range[1]], replacementKey);
93 }
94 });
95 }
96 }
97
98 return {
99 Property: check,
100 MethodDefinition: enforceForClassMembers ? check : lodash.noop
101 };
102 }
103};