2 * @fileoverview Rule to enforce consistent naming of "this" context variables
3 * @author Raphael Pigulla
4 * @copyright 2015 Timothy Jones. All rights reserved.
8 //------------------------------------------------------------------------------
10 //------------------------------------------------------------------------------
12 module.exports = function(context) {
13 var alias = context.options[0];
16 * Reports that a variable declarator or assignment expression is assigning
17 * a non-'this' value to the specified alias.
18 * @param {ASTNode} node - The assigning node.
21 function reportBadAssignment(node) {
23 "Designated alias '{{alias}}' is not assigned to 'this'.",
28 * Checks that an assignment to an identifier only assigns 'this' to the
29 * appropriate alias, and the alias is only assigned to 'this'.
30 * @param {ASTNode} node - The assigning node.
31 * @param {Identifier} name - The name of the variable assigned to.
32 * @param {Expression} value - The value of the assignment.
35 function checkAssignment(node, name, value) {
36 var isThis = value.type === "ThisExpression";
39 if (!isThis || node.operator && node.operator !== "=") {
40 reportBadAssignment(node);
44 "Unexpected alias '{{name}}' for 'this'.", { name: name });
49 * Ensures that a variable declaration of the alias in a program or function
50 * is assigned to the correct value.
53 function ensureWasAssigned() {
54 var scope = context.getScope();
56 scope.variables.some(function (variable) {
59 if (variable.name === alias) {
60 if (variable.defs.some(function (def) {
61 return def.node.type === "VariableDeclarator" &&
62 def.node.init !== null;
67 lookup = scope.type === "global" ? scope : variable;
69 // The alias has been declared and not assigned: check it was
70 // assigned later in the same scope.
71 if (!lookup.references.some(function (reference) {
72 var write = reference.writeExpr;
74 if (reference.from === scope &&
75 write && write.type === "ThisExpression" &&
76 write.parent.operator === "=") {
80 variable.defs.map(function (def) {
82 }).forEach(reportBadAssignment);
91 "Program:exit": ensureWasAssigned,
92 "FunctionExpression:exit": ensureWasAssigned,
93 "FunctionDeclaration:exit": ensureWasAssigned,
95 "VariableDeclarator": function (node) {
96 if (node.init !== null) {
97 checkAssignment(node, node.id.name, node.init);
101 "AssignmentExpression": function (node) {
102 if (node.left.type === "Identifier") {
103 checkAssignment(node, node.left.name, node.right);