minor adjustment to readme
[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
67     create(context) {
68         const restrictedCalls = context.options;
69
70         if (restrictedCalls.length === 0) {
71             return {};
72         }
73
74         const restrictedProperties = new Map();
75         const globallyRestrictedObjects = new Map();
76         const globallyRestrictedProperties = new Map();
77
78         restrictedCalls.forEach(option => {
79             const objectName = option.object;
80             const propertyName = option.property;
81
82             if (typeof objectName === "undefined") {
83                 globallyRestrictedProperties.set(propertyName, { message: option.message });
84             } else if (typeof propertyName === "undefined") {
85                 globallyRestrictedObjects.set(objectName, { message: option.message });
86             } else {
87                 if (!restrictedProperties.has(objectName)) {
88                     restrictedProperties.set(objectName, new Map());
89                 }
90
91                 restrictedProperties.get(objectName).set(propertyName, {
92                     message: option.message
93                 });
94             }
95         });
96
97         /**
98          * Checks to see whether a property access is restricted, and reports it if so.
99          * @param {ASTNode} node The node to report
100          * @param {string} objectName The name of the object
101          * @param {string} propertyName The name of the property
102          * @returns {undefined}
103          */
104         function checkPropertyAccess(node, objectName, propertyName) {
105             if (propertyName === null) {
106                 return;
107             }
108             const matchedObject = restrictedProperties.get(objectName);
109             const matchedObjectProperty = matchedObject ? matchedObject.get(propertyName) : globallyRestrictedObjects.get(objectName);
110             const globalMatchedProperty = globallyRestrictedProperties.get(propertyName);
111
112             if (matchedObjectProperty) {
113                 const message = matchedObjectProperty.message ? ` ${matchedObjectProperty.message}` : "";
114
115                 context.report({
116                     node,
117                     // eslint-disable-next-line eslint-plugin/report-message-format
118                     message: "'{{objectName}}.{{propertyName}}' is restricted from being used.{{message}}",
119                     data: {
120                         objectName,
121                         propertyName,
122                         message
123                     }
124                 });
125             } else if (globalMatchedProperty) {
126                 const message = globalMatchedProperty.message ? ` ${globalMatchedProperty.message}` : "";
127
128                 context.report({
129                     node,
130                     // eslint-disable-next-line eslint-plugin/report-message-format
131                     message: "'{{propertyName}}' is restricted from being used.{{message}}",
132                     data: {
133                         propertyName,
134                         message
135                     }
136                 });
137             }
138         }
139
140         /**
141          * Checks property accesses in a destructuring assignment expression, e.g. `var foo; ({foo} = bar);`
142          * @param {ASTNode} node An AssignmentExpression or AssignmentPattern node
143          * @returns {undefined}
144          */
145         function checkDestructuringAssignment(node) {
146             if (node.right.type === "Identifier") {
147                 const objectName = node.right.name;
148
149                 if (node.left.type === "ObjectPattern") {
150                     node.left.properties.forEach(property => {
151                         checkPropertyAccess(node.left, objectName, astUtils.getStaticPropertyName(property));
152                     });
153                 }
154             }
155         }
156
157         return {
158             MemberExpression(node) {
159                 checkPropertyAccess(node, node.object && node.object.name, astUtils.getStaticPropertyName(node));
160             },
161             VariableDeclarator(node) {
162                 if (node.init && node.init.type === "Identifier") {
163                     const objectName = node.init.name;
164
165                     if (node.id.type === "ObjectPattern") {
166                         node.id.properties.forEach(property => {
167                             checkPropertyAccess(node.id, objectName, astUtils.getStaticPropertyName(property));
168                         });
169                     }
170                 }
171             },
172             AssignmentExpression: checkDestructuringAssignment,
173             AssignmentPattern: checkDestructuringAssignment
174         };
175     }
176 };