summaryrefslogtreecommitdiff
path: root/tools/eslint/lib/rules/no-use-before-define.js
diff options
context:
space:
mode:
Diffstat (limited to 'tools/eslint/lib/rules/no-use-before-define.js')
-rw-r--r--tools/eslint/lib/rules/no-use-before-define.js67
1 files changed, 67 insertions, 0 deletions
diff --git a/tools/eslint/lib/rules/no-use-before-define.js b/tools/eslint/lib/rules/no-use-before-define.js
new file mode 100644
index 0000000000..3f175dc78b
--- /dev/null
+++ b/tools/eslint/lib/rules/no-use-before-define.js
@@ -0,0 +1,67 @@
+/**
+ * @fileoverview Rule to flag use of variables before they are defined
+ * @author Ilya Volodin
+ * @copyright 2013 Ilya Volodin. All rights reserved.
+ */
+
+"use strict";
+
+//------------------------------------------------------------------------------
+// Constants
+//------------------------------------------------------------------------------
+
+var NO_FUNC = "nofunc";
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = function(context) {
+
+ function findDeclaration(name, scope) {
+ // try searching in the current scope first
+ for (var i = 0, l = scope.variables.length; i < l; i++) {
+ if (scope.variables[i].name === name) {
+ return scope.variables[i];
+ }
+ }
+ // check if there's upper scope and call recursivly till we find the variable
+ if (scope.upper) {
+ return findDeclaration(name, scope.upper);
+ }
+ }
+
+ function findVariables() {
+ var scope = context.getScope();
+ var typeOption = context.options[0];
+
+ function checkLocationAndReport(reference, declaration) {
+ if (typeOption !== NO_FUNC || declaration.defs[0].type !== "FunctionName") {
+ if (declaration.identifiers[0].range[1] > reference.identifier.range[1]) {
+ context.report(reference.identifier, "{{a}} was used before it was defined", {a: reference.identifier.name});
+ }
+ }
+ }
+
+ scope.references.forEach(function(reference) {
+ // if the reference is resolved check for declaration location
+ // if not, it could be function invocation, try to find manually
+ if (reference.resolved && reference.resolved.identifiers.length > 0) {
+ checkLocationAndReport(reference, reference.resolved);
+ } else {
+ var declaration = findDeclaration(reference.identifier.name, scope);
+ // if there're no identifiers, this is a global environment variable
+ if (declaration && declaration.identifiers.length !== 0) {
+ checkLocationAndReport(reference, declaration);
+ }
+ }
+ });
+ }
+
+ return {
+ "Program": findVariables,
+ "FunctionExpression": findVariables,
+ "FunctionDeclaration": findVariables,
+ "ArrowFunctionExpression": findVariables
+ };
+};