UNPKG

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