You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
			
				
					347 lines
				
				8.7 KiB
			
		
		
			
		
	
	
					347 lines
				
				8.7 KiB
			| 
								 
											4 years ago
										 
									 | 
							
								"use strict";
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const t = require("@babel/types");
							 | 
						||
| 
								 | 
							
								const requireFromESLint = require("./require-from-eslint");
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const escope = requireFromESLint("eslint-scope");
							 | 
						||
| 
								 | 
							
								const Definition = requireFromESLint("eslint-scope/lib/definition").Definition;
							 | 
						||
| 
								 | 
							
								const OriginalPatternVisitor = requireFromESLint(
							 | 
						||
| 
								 | 
							
								  "eslint-scope/lib/pattern-visitor"
							 | 
						||
| 
								 | 
							
								);
							 | 
						||
| 
								 | 
							
								const OriginalReferencer = requireFromESLint("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);
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  EnumDeclaration(node) {
							 | 
						||
| 
								 | 
							
								    this._createScopeVariable(node, node.id);
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  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,
							 | 
						||
| 
								 | 
							
								  };
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  options.childVisitorKeys = childVisitorKeys;
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  const scopeManager = new escope.ScopeManager(options);
							 | 
						||
| 
								 | 
							
								  const referencer = new Referencer(options, scopeManager);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  referencer.visit(ast);
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								  return scopeManager;
							 | 
						||
| 
								 | 
							
								};
							 |