.gitignore added
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / eslint / lib / rules / no-restricted-properties.js
1 /**
2  * @fileoverview Rule to disallow certain object properties
3  * @author Will Klein & Eli White
4  */
5
6 "use strict";
7
8 const astUtils = require("./utils/ast-utils");
9
10 //------------------------------------------------------------------------------
11 // Rule Definition
12 //------------------------------------------------------------------------------
13
14 module.exports = {
15     meta: {
16         type: "suggestion",
17
18         docs: {
19             description: "disallow certain properties on certain objects",
20             category: "Best Practices",
21             recommended: false,
22             url: "https://eslint.org/docs/rules/no-restricted-properties"
23         },
24
25         schema: {
26             type: "array",
27             items: {
28                 anyOf: [ // `object` and `property` are both optional, but at least one of them must be provided.
29                     {
30                         type: "object",
31                         properties: {
32                             object: {
33                                 type: "string"
34                             },
35                             property: {
36                                 type: "string"
37                             },
38                             message: {
39                                 type: "string"
40                             }
41                         },
42                         additionalProperties: false,
43                         required: ["object"]
44                     },
45                     {
46                         type: "object",
47                         properties: {
48                             object: {
49                                 type: "string"
50                             },
51                             property: {
52                                 type: "string"
53                             },
54                             message: {
55                                 type: "string"
56                             }
57                         },
58                         additionalProperties: false,
59                         required: ["property"]
60                     }
61                 ]
62             },
63             uniqueItems: true
64         },
65
66         messages: {
67             // eslint-disable-next-line eslint-plugin/report-message-format
68             restrictedObjectProperty: "'{{objectName}}.{{propertyName}}' is restricted from being used.{{message}}",
69             // eslint-disable-next-line eslint-plugin/report-message-format
70             restrictedProperty: "'{{propertyName}}' is restricted from being used.{{message}}"
71         }
72     },
73
74     create(context) {
75         const restrictedCalls = context.options;
76
77         if (restrictedCalls.length === 0) {
78             return {};
79         }
80
81         const restrictedProperties = new Map();
82         const globallyRestrictedObjects = new Map();
83         const globallyRestrictedProperties = new Map();
84
85         restrictedCalls.forEach(option => {
86             const objectName = option.object;
87             const propertyName = option.property;
88
89             if (typeof objectName === "undefined") {
90                 globallyRestrictedProperties.set(propertyName, { message: option.message });
91             } else if (typeof propertyName === "undefined") {
92                 globallyRestrictedObjects.set(objectName, { message: option.message });
93             } else {
94                 if (!restrictedProperties.has(objectName)) {
95                     restrictedProperties.set(objectName, new Map());
96                 }
97
98                 restrictedProperties.get(objectName).set(propertyName, {
99                     message: option.message
100                 });
101             }
102         });
103
104         /**
105          * Checks to see whether a property access is restricted, and reports it if so.
106          * @param {ASTNode} node The node to report
107          * @param {string} objectName The name of the object
108          * @param {string} propertyName The name of the property
109          * @returns {undefined}
110          */
111         function checkPropertyAccess(node, objectName, propertyName) {
112             if (propertyName === null) {
113                 return;
114             }
115             const matchedObject = restrictedProperties.get(objectName);
116             const matchedObjectProperty = matchedObject ? matchedObject.get(propertyName) : globallyRestrictedObjects.get(objectName);
117             const globalMatchedProperty = globallyRestrictedProperties.get(propertyName);
118
119             if (matchedObjectProperty) {
120                 const message = matchedObjectProperty.message ? ` ${matchedObjectProperty.message}` : "";
121
122                 context.report({
123                     node,
124                     messageId: "restrictedObjectProperty",
125                     data: {
126                         objectName,
127                         propertyName,
128                         message
129                     }
130                 });
131             } else if (globalMatchedProperty) {
132                 const message = globalMatchedProperty.message ? ` ${globalMatchedProperty.message}` : "";
133
134                 context.report({
135                     node,
136                     messageId: "restrictedProperty",
137                     data: {
138                         propertyName,
139                         message
140                     }
141                 });
142             }
143         }
144
145         /**
146          * Checks property accesses in a destructuring assignment expression, e.g. `var foo; ({foo} = bar);`
147          * @param {ASTNode} node An AssignmentExpression or AssignmentPattern node
148          * @returns {undefined}
149          */
150         function checkDestructuringAssignment(node) {
151             if (node.right.type === "Identifier") {
152                 const objectName = node.right.name;
153
154                 if (node.left.type === "ObjectPattern") {
155                     node.left.properties.forEach(property => {
156                         checkPropertyAccess(node.left, objectName, astUtils.getStaticPropertyName(property));
157                     });
158                 }
159             }
160         }
161
162         return {
163             MemberExpression(node) {
164                 checkPropertyAccess(node, node.object && node.object.name, astUtils.getStaticPropertyName(node));
165             },
166             VariableDeclarator(node) {
167                 if (node.init && node.init.type === "Identifier") {
168                     const objectName = node.init.name;
169
170                     if (node.id.type === "ObjectPattern") {
171                         node.id.properties.forEach(property => {
172                             checkPropertyAccess(node.id, objectName, astUtils.getStaticPropertyName(property));
173                         });
174                     }
175                 }
176             },
177             AssignmentExpression: checkDestructuringAssignment,
178             AssignmentPattern: checkDestructuringAssignment
179         };
180     }
181 };