text: /**
   * @fileoverview Rule to flag use of console object
   * @author Nicholas C. Zakas
   */
  
  "use strict";
  
  //------------------------------------------------------------------------------
  // Requirements
  //------------------------------------------------------------------------------
  
  const astUtils = require("./utils/ast-utils");
  
  //------------------------------------------------------------------------------
  // Rule Definition
  //------------------------------------------------------------------------------
  
  module.exports = {
      meta: {
          type: "suggestion",
  
          docs: {
              description: "disallow the use of `console`",
              category: "Possible Errors",
              recommended: false,
              url: "https://eslint.org/docs/rules/no-console"
          },
  
          schema: [
              {
                  type: "object",
                  properties: {
                      allow: {
                          type: "array",
                          items: {
                              type: "string"
                          },
                          minItems: 1,
                          uniqueItems: true
                      }
                  },
                  additionalProperties: false
              }
          ],
  
          messages: {
              unexpected: "Unexpected console statement."
          }
      },
  
      create(context) {
          const options = context.options[0] || {};
          const allowed = options.allow || [];
  
          /**
           * Checks whether the given reference is 'console' or not.
           *
           * @param {eslint-scope.Reference} reference - The reference to check.
           * @returns {boolean} `true` if the reference is 'console'.
           */
          function isConsole(reference) {
              const id = reference.identifier;
  
              return id && id.name === "console";
          }
  
          /**
           * Checks whether the property name of the given MemberExpression node
           * is allowed by options or not.
           *
           * @param {ASTNode} node - The MemberExpression node to check.
           * @returns {boolean} `true` if the property name of the node is allowed.
           */
          function isAllowed(node) {
              const propertyName = astUtils.getStaticPropertyName(node);
  
              return propertyName && allowed.indexOf(propertyName) !== -1;
          }
  
          /**
           * Checks whether the given reference is a member access which is not
           * allowed by options or not.
           *
           * @param {eslint-scope.Reference} reference - The reference to check.
           * @returns {boolean} `true` if the reference is a member access which
           *      is not allowed by options.
           */
          function isMemberAccessExceptAllowed(reference) {
              const node = reference.identifier;
              const parent = node.parent;
  
              return (
                  parent.type === "MemberExpression" &&
                  parent.object === node &&
                  !isAllowed(parent)
              );
          }
  
          /**
           * Reports the given reference as a violation.
           *
           * @param {eslint-scope.Reference} reference - The reference to report.
           * @returns {void}
           */
          function report(reference) {
              const node = reference.identifier.parent;
  
              context.report({
                  node,
                  loc: node.loc,
                  messageId: "unexpected"
              });
          }
  
          return {
              "Program:exit"() {
                  const scope = context.getScope();
                  const consoleVar = astUtils.getVariableByName(scope, "console");
                  const shadowed = consoleVar && consoleVar.defs.length > 0;
  
                  /*
                   * 'scope.through' includes all references to undefined
                   * variables. If the variable 'console' is not defined, it uses
                   * 'scope.through'.
                   */
                  const references = consoleVar
                      ? consoleVar.references
                      : scope.through.filter(isConsole);
  
                  if (!shadowed) {
                      references
                          .filter(isMemberAccessExceptAllowed)
                          .forEach(report);
                  }
              }
          };
      }
  };
  