| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343 | "use strict";const t = require("@babel/types");const escope = require("eslint-scope");const Definition = require("eslint-scope/lib/definition").Definition;const OriginalPatternVisitor = require("eslint-scope/lib/pattern-visitor");const OriginalReferencer = require("eslint-scope/lib/referencer");const fallback = require("eslint-visitor-keys").getKeys;const childVisitorKeys = require("./visitor-keys");const flowFlippedAliasKeys = t.FLIPPED_ALIAS_KEYS.Flow.concat([  "ArrayPattern",  "ClassDeclaration",  "ClassExpression",  "FunctionDeclaration",  "FunctionExpression",  "Identifier",  "ObjectPattern",  "RestElement",]);const visitorKeysMap = Object.keys(t.VISITOR_KEYS).reduce(function(acc, key) {  const value = t.VISITOR_KEYS[key];  if (flowFlippedAliasKeys.indexOf(value) === -1) {    acc[key] = value;  }  return acc;}, {});const propertyTypes = {  // loops  callProperties: { type: "loop", values: ["value"] },  indexers: { type: "loop", values: ["key", "value"] },  properties: { type: "loop", values: ["argument", "value"] },  types: { type: "loop" },  params: { type: "loop" },  // single property  argument: { type: "single" },  elementType: { type: "single" },  qualification: { type: "single" },  rest: { type: "single" },  returnType: { type: "single" },  // others  typeAnnotation: { type: "typeAnnotation" },  typeParameters: { type: "typeParameters" },  id: { type: "id" },};class PatternVisitor extends OriginalPatternVisitor {  ArrayPattern(node) {    node.elements.forEach(this.visit, this);  }  ObjectPattern(node) {    node.properties.forEach(this.visit, this);  }}class Referencer extends OriginalReferencer {  // inherits.  visitPattern(node, options, callback) {    if (!node) {      return;    }    // Visit type annotations.    this._checkIdentifierOrVisit(node.typeAnnotation);    if (t.isAssignmentPattern(node)) {      this._checkIdentifierOrVisit(node.left.typeAnnotation);    }    // Overwrite `super.visitPattern(node, options, callback)` in order to not visit `ArrayPattern#typeAnnotation` and `ObjectPattern#typeAnnotation`.    if (typeof options === "function") {      callback = options;      options = { processRightHandNodes: false };    }    const visitor = new PatternVisitor(this.options, node, callback);    visitor.visit(node);    // Process the right hand nodes recursively.    if (options.processRightHandNodes) {      visitor.rightHandNodes.forEach(this.visit, this);    }  }  // inherits.  visitClass(node) {    // Decorators.    this._visitArray(node.decorators);    // Flow type parameters.    const typeParamScope = this._nestTypeParamScope(node);    // Flow super types.    this._visitTypeAnnotation(node.implements);    this._visitTypeAnnotation(      node.superTypeParameters && node.superTypeParameters.params    );    // Basic.    super.visitClass(node);    // Close the type parameter scope.    if (typeParamScope) {      this.close(node);    }  }  // inherits.  visitFunction(node) {    const typeParamScope = this._nestTypeParamScope(node);    // Flow return types.    this._checkIdentifierOrVisit(node.returnType);    // Basic.    super.visitFunction(node);    // Close the type parameter scope.    if (typeParamScope) {      this.close(node);    }  }  // inherits.  visitProperty(node) {    if (node.value && node.value.type === "TypeCastExpression") {      this._visitTypeAnnotation(node.value);    }    this._visitArray(node.decorators);    super.visitProperty(node);  }  InterfaceDeclaration(node) {    this._createScopeVariable(node, node.id);    const typeParamScope = this._nestTypeParamScope(node);    // TODO: Handle mixins    this._visitArray(node.extends);    this.visit(node.body);    if (typeParamScope) {      this.close(node);    }  }  TypeAlias(node) {    this._createScopeVariable(node, node.id);    const typeParamScope = this._nestTypeParamScope(node);    this.visit(node.right);    if (typeParamScope) {      this.close(node);    }  }  ClassProperty(node) {    this._visitClassProperty(node);  }  ClassPrivateProperty(node) {    this._visitClassProperty(node);  }  DeclareModule(node) {    this._visitDeclareX(node);  }  DeclareFunction(node) {    this._visitDeclareX(node);  }  DeclareVariable(node) {    this._visitDeclareX(node);  }  DeclareClass(node) {    this._visitDeclareX(node);  }  // visit OptionalMemberExpression as a MemberExpression.  OptionalMemberExpression(node) {    super.MemberExpression(node);  }  _visitClassProperty(node) {    this._visitTypeAnnotation(node.typeAnnotation);    this.visitProperty(node);  }  _visitDeclareX(node) {    if (node.id) {      this._createScopeVariable(node, node.id);    }    const typeParamScope = this._nestTypeParamScope(node);    if (typeParamScope) {      this.close(node);    }  }  _createScopeVariable(node, name) {    this.currentScope().variableScope.__define(      name,      new Definition("Variable", name, node, null, null, null)    );  }  _nestTypeParamScope(node) {    if (!node.typeParameters) {      return null;    }    const parentScope = this.scopeManager.__currentScope;    const scope = new escope.Scope(      this.scopeManager,      "type-parameters",      parentScope,      node,      false    );    this.scopeManager.__nestScope(scope);    for (let j = 0; j < node.typeParameters.params.length; j++) {      const name = node.typeParameters.params[j];      scope.__define(name, new Definition("TypeParameter", name, name));      if (name.typeAnnotation) {        this._checkIdentifierOrVisit(name);      }    }    scope.__define = function() {      return parentScope.__define.apply(parentScope, arguments);    };    return scope;  }  _visitTypeAnnotation(node) {    if (!node) {      return;    }    if (Array.isArray(node)) {      node.forEach(this._visitTypeAnnotation, this);      return;    }    // get property to check (params, id, etc...)    const visitorValues = visitorKeysMap[node.type];    if (!visitorValues) {      return;    }    // can have multiple properties    for (let i = 0; i < visitorValues.length; i++) {      const visitorValue = visitorValues[i];      const propertyType = propertyTypes[visitorValue];      const nodeProperty = node[visitorValue];      // check if property or type is defined      if (propertyType == null || nodeProperty == null) {        continue;      }      if (propertyType.type === "loop") {        for (let j = 0; j < nodeProperty.length; j++) {          if (Array.isArray(propertyType.values)) {            for (let k = 0; k < propertyType.values.length; k++) {              const loopPropertyNode = nodeProperty[j][propertyType.values[k]];              if (loopPropertyNode) {                this._checkIdentifierOrVisit(loopPropertyNode);              }            }          } else {            this._checkIdentifierOrVisit(nodeProperty[j]);          }        }      } else if (propertyType.type === "single") {        this._checkIdentifierOrVisit(nodeProperty);      } else if (propertyType.type === "typeAnnotation") {        this._visitTypeAnnotation(node.typeAnnotation);      } else if (propertyType.type === "typeParameters") {        for (let l = 0; l < node.typeParameters.params.length; l++) {          this._checkIdentifierOrVisit(node.typeParameters.params[l]);        }      } else if (propertyType.type === "id") {        if (node.id.type === "Identifier") {          this._checkIdentifierOrVisit(node.id);        } else {          this._visitTypeAnnotation(node.id);        }      }    }  }  _checkIdentifierOrVisit(node) {    if (node && node.typeAnnotation) {      this._visitTypeAnnotation(node.typeAnnotation);    } else if (node && node.type === "Identifier") {      this.visit(node);    } else {      this._visitTypeAnnotation(node);    }  }  _visitArray(nodeList) {    if (nodeList) {      for (const node of nodeList) {        this.visit(node);      }    }  }}module.exports = function(ast, parserOptions) {  const options = {    ignoreEval: true,    optimistic: false,    directive: false,    nodejsScope:      ast.sourceType === "script" &&      (parserOptions.ecmaFeatures &&        parserOptions.ecmaFeatures.globalReturn) === true,    impliedStrict: false,    sourceType: ast.sourceType,    ecmaVersion: parserOptions.ecmaVersion || 2018,    fallback,  };  if (OriginalReferencer._babelEslintPatched) {    require("./patch-eslint-scope")(parserOptions);    return escope.analyze(ast, options);  }  options.childVisitorKeys = childVisitorKeys;  const scopeManager = new escope.ScopeManager(options);  const referencer = new Referencer(options, scopeManager);  referencer.visit(ast);  return scopeManager;};
 |