• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/**
2 * @fileoverview Rule to flag references to the undefined variable.
3 * @author Michael Ficarra
4 */
5"use strict";
6
7//------------------------------------------------------------------------------
8// Rule Definition
9//------------------------------------------------------------------------------
10
11module.exports = {
12    meta: {
13        type: "suggestion",
14
15        docs: {
16            description: "disallow the use of `undefined` as an identifier",
17            category: "Variables",
18            recommended: false,
19            url: "https://eslint.org/docs/rules/no-undefined"
20        },
21
22        schema: [],
23
24        messages: {
25            unexpectedUndefined: "Unexpected use of undefined."
26        }
27    },
28
29    create(context) {
30
31        /**
32         * Report an invalid "undefined" identifier node.
33         * @param {ASTNode} node The node to report.
34         * @returns {void}
35         */
36        function report(node) {
37            context.report({
38                node,
39                messageId: "unexpectedUndefined"
40            });
41        }
42
43        /**
44         * Checks the given scope for references to `undefined` and reports
45         * all references found.
46         * @param {eslint-scope.Scope} scope The scope to check.
47         * @returns {void}
48         */
49        function checkScope(scope) {
50            const undefinedVar = scope.set.get("undefined");
51
52            if (!undefinedVar) {
53                return;
54            }
55
56            const references = undefinedVar.references;
57
58            const defs = undefinedVar.defs;
59
60            // Report non-initializing references (those are covered in defs below)
61            references
62                .filter(ref => !ref.init)
63                .forEach(ref => report(ref.identifier));
64
65            defs.forEach(def => report(def.name));
66        }
67
68        return {
69            "Program:exit"() {
70                const globalScope = context.getScope();
71
72                const stack = [globalScope];
73
74                while (stack.length) {
75                    const scope = stack.pop();
76
77                    stack.push(...scope.childScopes);
78                    checkScope(scope);
79                }
80            }
81        };
82
83    }
84};
85