UNPKG

4.28 kBJavaScriptView Raw
1/**
2 * @fileoverview Rule to flag use of console object
3 * @author Nicholas C. Zakas
4 */
5
6"use strict";
7
8//------------------------------------------------------------------------------
9// Requirements
10//------------------------------------------------------------------------------
11
12const astUtils = require("../ast-utils");
13
14//------------------------------------------------------------------------------
15// Rule Definition
16//------------------------------------------------------------------------------
17
18module.exports = {
19 meta: {
20 docs: {
21 description: "disallow the use of `console`",
22 category: "Possible Errors",
23 recommended: true,
24 url: "https://eslint.org/docs/rules/no-console"
25 },
26
27 schema: [
28 {
29 type: "object",
30 properties: {
31 allow: {
32 type: "array",
33 items: {
34 type: "string"
35 },
36 minItems: 1,
37 uniqueItems: true
38 }
39 },
40 additionalProperties: false
41 }
42 ],
43
44 messages: {
45 unexpected: "Unexpected console statement."
46 }
47 },
48
49 create(context) {
50 const options = context.options[0] || {};
51 const allowed = options.allow || [];
52
53 /**
54 * Checks whether the given reference is 'console' or not.
55 *
56 * @param {eslint-scope.Reference} reference - The reference to check.
57 * @returns {boolean} `true` if the reference is 'console'.
58 */
59 function isConsole(reference) {
60 const id = reference.identifier;
61
62 return id && id.name === "console";
63 }
64
65 /**
66 * Checks whether the property name of the given MemberExpression node
67 * is allowed by options or not.
68 *
69 * @param {ASTNode} node - The MemberExpression node to check.
70 * @returns {boolean} `true` if the property name of the node is allowed.
71 */
72 function isAllowed(node) {
73 const propertyName = astUtils.getStaticPropertyName(node);
74
75 return propertyName && allowed.indexOf(propertyName) !== -1;
76 }
77
78 /**
79 * Checks whether the given reference is a member access which is not
80 * allowed by options or not.
81 *
82 * @param {eslint-scope.Reference} reference - The reference to check.
83 * @returns {boolean} `true` if the reference is a member access which
84 * is not allowed by options.
85 */
86 function isMemberAccessExceptAllowed(reference) {
87 const node = reference.identifier;
88 const parent = node.parent;
89
90 return (
91 parent.type === "MemberExpression" &&
92 parent.object === node &&
93 !isAllowed(parent)
94 );
95 }
96
97 /**
98 * Reports the given reference as a violation.
99 *
100 * @param {eslint-scope.Reference} reference - The reference to report.
101 * @returns {void}
102 */
103 function report(reference) {
104 const node = reference.identifier.parent;
105
106 context.report({
107 node,
108 loc: node.loc,
109 messageId: "unexpected"
110 });
111 }
112
113 return {
114 "Program:exit"() {
115 const scope = context.getScope();
116 const consoleVar = astUtils.getVariableByName(scope, "console");
117 const shadowed = consoleVar && consoleVar.defs.length > 0;
118
119 /*
120 * 'scope.through' includes all references to undefined
121 * variables. If the variable 'console' is not defined, it uses
122 * 'scope.through'.
123 */
124 const references = consoleVar
125 ? consoleVar.references
126 : scope.through.filter(isConsole);
127
128 if (!shadowed) {
129 references
130 .filter(isMemberAccessExceptAllowed)
131 .forEach(report);
132 }
133 }
134 };
135 }
136};