.gitignore added
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / eslint / lib / rules / consistent-this.js
1 /**
2  * @fileoverview Rule to enforce consistent naming of "this" context variables
3  * @author Raphael Pigulla
4  */
5 "use strict";
6
7 //------------------------------------------------------------------------------
8 // Rule Definition
9 //------------------------------------------------------------------------------
10
11 module.exports = {
12     meta: {
13         type: "suggestion",
14
15         docs: {
16             description: "enforce consistent naming when capturing the current execution context",
17             category: "Stylistic Issues",
18             recommended: false,
19             url: "https://eslint.org/docs/rules/consistent-this"
20         },
21
22         schema: {
23             type: "array",
24             items: {
25                 type: "string",
26                 minLength: 1
27             },
28             uniqueItems: true
29         },
30
31         messages: {
32             aliasNotAssignedToThis: "Designated alias '{{name}}' is not assigned to 'this'.",
33             unexpectedAlias: "Unexpected alias '{{name}}' for 'this'."
34         }
35     },
36
37     create(context) {
38         let aliases = [];
39
40         if (context.options.length === 0) {
41             aliases.push("that");
42         } else {
43             aliases = context.options;
44         }
45
46         /**
47          * Reports that a variable declarator or assignment expression is assigning
48          * a non-'this' value to the specified alias.
49          * @param {ASTNode} node The assigning node.
50          * @param {string}  name the name of the alias that was incorrectly used.
51          * @returns {void}
52          */
53         function reportBadAssignment(node, name) {
54             context.report({ node, messageId: "aliasNotAssignedToThis", data: { name } });
55         }
56
57         /**
58          * Checks that an assignment to an identifier only assigns 'this' to the
59          * appropriate alias, and the alias is only assigned to 'this'.
60          * @param {ASTNode} node The assigning node.
61          * @param {Identifier} name The name of the variable assigned to.
62          * @param {Expression} value The value of the assignment.
63          * @returns {void}
64          */
65         function checkAssignment(node, name, value) {
66             const isThis = value.type === "ThisExpression";
67
68             if (aliases.indexOf(name) !== -1) {
69                 if (!isThis || node.operator && node.operator !== "=") {
70                     reportBadAssignment(node, name);
71                 }
72             } else if (isThis) {
73                 context.report({ node, messageId: "unexpectedAlias", data: { name } });
74             }
75         }
76
77         /**
78          * Ensures that a variable declaration of the alias in a program or function
79          * is assigned to the correct value.
80          * @param {string} alias alias the check the assignment of.
81          * @param {Object} scope scope of the current code we are checking.
82          * @private
83          * @returns {void}
84          */
85         function checkWasAssigned(alias, scope) {
86             const variable = scope.set.get(alias);
87
88             if (!variable) {
89                 return;
90             }
91
92             if (variable.defs.some(def => def.node.type === "VariableDeclarator" &&
93                 def.node.init !== null)) {
94                 return;
95             }
96
97             /*
98              * The alias has been declared and not assigned: check it was
99              * assigned later in the same scope.
100              */
101             if (!variable.references.some(reference => {
102                 const write = reference.writeExpr;
103
104                 return (
105                     reference.from === scope &&
106                     write && write.type === "ThisExpression" &&
107                     write.parent.operator === "="
108                 );
109             })) {
110                 variable.defs.map(def => def.node).forEach(node => {
111                     reportBadAssignment(node, alias);
112                 });
113             }
114         }
115
116         /**
117          * Check each alias to ensure that is was assigned to the correct value.
118          * @returns {void}
119          */
120         function ensureWasAssigned() {
121             const scope = context.getScope();
122
123             aliases.forEach(alias => {
124                 checkWasAssigned(alias, scope);
125             });
126         }
127
128         return {
129             "Program:exit": ensureWasAssigned,
130             "FunctionExpression:exit": ensureWasAssigned,
131             "FunctionDeclaration:exit": ensureWasAssigned,
132
133             VariableDeclarator(node) {
134                 const id = node.id;
135                 const isDestructuring =
136                     id.type === "ArrayPattern" || id.type === "ObjectPattern";
137
138                 if (node.init !== null && !isDestructuring) {
139                     checkAssignment(node, id.name, node.init);
140                 }
141             },
142
143             AssignmentExpression(node) {
144                 if (node.left.type === "Identifier") {
145                     checkAssignment(node, node.left.name, node.right);
146                 }
147             }
148         };
149
150     }
151 };