.gitignore added
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / eslint / lib / rules / no-dupe-keys.js
1 /**
2  * @fileoverview Rule to flag use of duplicate keys in an object.
3  * @author Ian Christian Myers
4  */
5
6 "use strict";
7
8 //------------------------------------------------------------------------------
9 // Requirements
10 //------------------------------------------------------------------------------
11
12 const astUtils = require("./utils/ast-utils");
13
14 //------------------------------------------------------------------------------
15 // Helpers
16 //------------------------------------------------------------------------------
17
18 const GET_KIND = /^(?:init|get)$/u;
19 const SET_KIND = /^(?:init|set)$/u;
20
21 /**
22  * The class which stores properties' information of an object.
23  */
24 class ObjectInfo {
25
26     // eslint-disable-next-line jsdoc/require-description
27     /**
28      * @param {ObjectInfo|null} upper The information of the outer object.
29      * @param {ASTNode} node The ObjectExpression node of this information.
30      */
31     constructor(upper, node) {
32         this.upper = upper;
33         this.node = node;
34         this.properties = new Map();
35     }
36
37     /**
38      * Gets the information of the given Property node.
39      * @param {ASTNode} node The Property node to get.
40      * @returns {{get: boolean, set: boolean}} The information of the property.
41      */
42     getPropertyInfo(node) {
43         const name = astUtils.getStaticPropertyName(node);
44
45         if (!this.properties.has(name)) {
46             this.properties.set(name, { get: false, set: false });
47         }
48         return this.properties.get(name);
49     }
50
51     /**
52      * Checks whether the given property has been defined already or not.
53      * @param {ASTNode} node The Property node to check.
54      * @returns {boolean} `true` if the property has been defined.
55      */
56     isPropertyDefined(node) {
57         const entry = this.getPropertyInfo(node);
58
59         return (
60             (GET_KIND.test(node.kind) && entry.get) ||
61             (SET_KIND.test(node.kind) && entry.set)
62         );
63     }
64
65     /**
66      * Defines the given property.
67      * @param {ASTNode} node The Property node to define.
68      * @returns {void}
69      */
70     defineProperty(node) {
71         const entry = this.getPropertyInfo(node);
72
73         if (GET_KIND.test(node.kind)) {
74             entry.get = true;
75         }
76         if (SET_KIND.test(node.kind)) {
77             entry.set = true;
78         }
79     }
80 }
81
82 //------------------------------------------------------------------------------
83 // Rule Definition
84 //------------------------------------------------------------------------------
85
86 module.exports = {
87     meta: {
88         type: "problem",
89
90         docs: {
91             description: "disallow duplicate keys in object literals",
92             category: "Possible Errors",
93             recommended: true,
94             url: "https://eslint.org/docs/rules/no-dupe-keys"
95         },
96
97         schema: [],
98
99         messages: {
100             unexpected: "Duplicate key '{{name}}'."
101         }
102     },
103
104     create(context) {
105         let info = null;
106
107         return {
108             ObjectExpression(node) {
109                 info = new ObjectInfo(info, node);
110             },
111             "ObjectExpression:exit"() {
112                 info = info.upper;
113             },
114
115             Property(node) {
116                 const name = astUtils.getStaticPropertyName(node);
117
118                 // Skip destructuring.
119                 if (node.parent.type !== "ObjectExpression") {
120                     return;
121                 }
122
123                 // Skip if the name is not static.
124                 if (name === null) {
125                     return;
126                 }
127
128                 // Reports if the name is defined already.
129                 if (info.isPropertyDefined(node)) {
130                     context.report({
131                         node: info.node,
132                         loc: node.key.loc,
133                         messageId: "unexpected",
134                         data: { name }
135                     });
136                 }
137
138                 // Update info.
139                 info.defineProperty(node);
140             }
141         };
142     }
143 };