summaryrefslogtreecommitdiff
path: root/tools/eslint/lib/rules/consistent-this.js
diff options
context:
space:
mode:
Diffstat (limited to 'tools/eslint/lib/rules/consistent-this.js')
-rw-r--r--tools/eslint/lib/rules/consistent-this.js108
1 files changed, 108 insertions, 0 deletions
diff --git a/tools/eslint/lib/rules/consistent-this.js b/tools/eslint/lib/rules/consistent-this.js
new file mode 100644
index 0000000000..3efb2cd372
--- /dev/null
+++ b/tools/eslint/lib/rules/consistent-this.js
@@ -0,0 +1,108 @@
+/**
+ * @fileoverview Rule to enforce consistent naming of "this" context variables
+ * @author Raphael Pigulla
+ * @copyright 2015 Timothy Jones. All rights reserved.
+ */
+"use strict";
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = function(context) {
+ var alias = context.options[0];
+
+ /**
+ * Reports that a variable declarator or assignment expression is assigning
+ * a non-'this' value to the specified alias.
+ * @param {ASTNode} node - The assigning node.
+ * @returns {void}
+ */
+ function reportBadAssignment(node) {
+ context.report(node,
+ "Designated alias '{{alias}}' is not assigned to 'this'.",
+ { alias: alias });
+ }
+
+ /**
+ * Checks that an assignment to an identifier only assigns 'this' to the
+ * appropriate alias, and the alias is only assigned to 'this'.
+ * @param {ASTNode} node - The assigning node.
+ * @param {Identifier} name - The name of the variable assigned to.
+ * @param {Expression} value - The value of the assignment.
+ * @returns {void}
+ */
+ function checkAssignment(node, name, value) {
+ var isThis = value.type === "ThisExpression";
+
+ if (name === alias) {
+ if (!isThis || node.operator && node.operator !== "=") {
+ reportBadAssignment(node);
+ }
+ } else if (isThis) {
+ context.report(node,
+ "Unexpected alias '{{name}}' for 'this'.", { name: name });
+ }
+ }
+
+ /**
+ * Ensures that a variable declaration of the alias in a program or function
+ * is assigned to the correct value.
+ * @returns {void}
+ */
+ function ensureWasAssigned() {
+ var scope = context.getScope();
+
+ scope.variables.some(function (variable) {
+ var lookup;
+
+ if (variable.name === alias) {
+ if (variable.defs.some(function (def) {
+ return def.node.type === "VariableDeclarator" &&
+ def.node.init !== null;
+ })) {
+ return true;
+ }
+
+ lookup = scope.type === "global" ? scope : variable;
+
+ // The alias has been declared and not assigned: check it was
+ // assigned later in the same scope.
+ if (!lookup.references.some(function (reference) {
+ var write = reference.writeExpr;
+
+ if (reference.from === scope &&
+ write && write.type === "ThisExpression" &&
+ write.parent.operator === "=") {
+ return true;
+ }
+ })) {
+ variable.defs.map(function (def) {
+ return def.node;
+ }).forEach(reportBadAssignment);
+ }
+
+ return true;
+ }
+ });
+ }
+
+ return {
+ "Program:exit": ensureWasAssigned,
+ "FunctionExpression:exit": ensureWasAssigned,
+ "FunctionDeclaration:exit": ensureWasAssigned,
+
+ "VariableDeclarator": function (node) {
+ if (node.init !== null) {
+ checkAssignment(node, node.id.name, node.init);
+ }
+ },
+
+ "AssignmentExpression": function (node) {
+ if (node.left.type === "Identifier") {
+ checkAssignment(node, node.left.name, node.right);
+ }
+ }
+ };
+
+};