Skip to content

⬅️ Back to Table of Contents

📄 Referencer

📊 Analysis Summary

Metric Count
🔧 Functions 67
🧱 Classes 1
📦 Imports 26
📐 Interfaces 1

📚 Table of Contents

🛠️ File Location:

📂 packages/scope-manager/src/referencer/Referencer.ts

📦 Imports

Name Source
Lib @typescript-eslint/types
TSESTree @typescript-eslint/types
AST_NODE_TYPES @typescript-eslint/types
GlobalScope ../scope
Scope ../scope
ScopeManager ../ScopeManager
LibDefinition ../variable
ReferenceImplicitGlobal ./Reference
VisitorOptions ./Visitor
assert ../assert
CatchClauseDefinition ../definition
FunctionNameDefinition ../definition
ImportBindingDefinition ../definition
ParameterDefinition ../definition
TSEnumMemberDefinition ../definition
TSEnumNameDefinition ../definition
TSModuleNameDefinition ../definition
VariableDefinition ../definition
TSLibraries ../lib
ClassVisitor ./ClassVisitor
ExportVisitor ./ExportVisitor
ImportVisitor ./ImportVisitor
PatternVisitor ./PatternVisitor
ReferenceFlag ./Reference
TypeVisitor ./TypeVisitor
Visitor ./Visitor

Functions

Referencer.populateGlobalsFromLib(globalScope: GlobalScope): void

Parameters:

  • globalScope GlobalScope

Returns: void

Calls:

  • this.resolveLibDefinitions
  • globalScope.defineImplicitVariable

Internal Comments:

// Special implicit global for const assertions (`{} as const`, `<const>{}`) (x4)

Code
private populateGlobalsFromLib(globalScope: GlobalScope): void {
    const libs = this.resolveLibDefinitions();

    for (const lib of libs) {
      for (const [name, variable] of lib.variables) {
        globalScope.defineImplicitVariable(name, variable);
      }
    }

    // Special implicit global for const assertions (`{} as const`, `<const>{}`)
    globalScope.defineImplicitVariable('const', {
      eslintImplicitGlobalSetting: 'readonly',
      isTypeVariable: true,
      isValueVariable: false,
    });
  }

Referencer.resolveLibDefinitions(): Set<LibDefinition>

Resolves lib names into a deduplicated set of LibDefinitions, including all transitive dependencies.

Raw JSDoc
/**
   * Resolves lib names into a deduplicated set of LibDefinitions,
   * including all transitive dependencies.
   */

Calls:

  • TSLibraries.get
  • resolvedLibs.add

Internal Comments:

// Resolve the top-level lib names into LibDefinition objects
// Expand transitive lib dependencies.
// New entries added to the Set during iteration will be visited exactly once.

Code
private resolveLibDefinitions(): Set<LibDefinition> {
    const resolvedLibs = new Set<LibDefinition>();

    // Resolve the top-level lib names into LibDefinition objects
    for (const lib of this.#lib) {
      const definition = TSLibraries.get(lib);
      if (!definition) {
        throw new Error(`Invalid value for lib provided: ${lib}`);
      }
      resolvedLibs.add(definition);
    }

    // Expand transitive lib dependencies.
    // New entries added to the Set during iteration will be visited exactly once.
    for (const lib of resolvedLibs) {
      for (const dependency of lib.libs) {
        resolvedLibs.add(dependency);
      }
    }

    return resolvedLibs;
  }

Referencer.close(node: TSESTree.Node): void

Parameters:

  • node TSESTree.Node

Returns: void

Calls:

  • this.currentScope
  • this.currentScope().close
Code
public close(node: TSESTree.Node): void {
    while (this.currentScope(true) && node === this.currentScope().block) {
      this.scopeManager.currentScope = this.currentScope().close(
        this.scopeManager,
      );
    }
  }

Referencer.currentScope(): Scope

Returns: Scope

Code
public currentScope(): Scope;

Referencer.referencingDefaultValue(…): void

Parameters:

  • pattern TSESTree.Identifier
  • assignments (TSESTree.AssignmentExpression | TSESTree.AssignmentPattern)[]
  • maybeImplicitGlobal ReferenceImplicitGlobal | null
  • init boolean

Returns: void

Calls:

  • assignments.forEach
  • this.currentScope().referenceValue
Code
public referencingDefaultValue(
    pattern: TSESTree.Identifier,
    assignments: (TSESTree.AssignmentExpression | TSESTree.AssignmentPattern)[],
    maybeImplicitGlobal: ReferenceImplicitGlobal | null,
    init: boolean,
  ): void {
    assignments.forEach(assignment => {
      this.currentScope().referenceValue(
        pattern,
        ReferenceFlag.Write,
        assignment.right,
        maybeImplicitGlobal,
        init,
      );
    });
  }

Referencer.referenceInSomeUpperScope(name: string): boolean

Searches for a variable named "name" in the upper scopes and adds a pseudo-reference from itself to itself

Raw JSDoc
/**
   * Searches for a variable named "name" in the upper scopes and adds a pseudo-reference from itself to itself
   */

Calls:

  • scope.set.get
  • scope.referenceValue
Code
private referenceInSomeUpperScope(name: string): boolean {
    let scope = this.scopeManager.currentScope;
    while (scope) {
      const variable = scope.set.get(name);
      if (!variable) {
        scope = scope.upper;
        continue;
      }

      scope.referenceValue(variable.identifiers[0]);
      return true;
    }

    return false;
  }

Referencer.referenceJsxFragment(): void

Returns: void

Calls:

  • this.referenceInSomeUpperScope
Code
private referenceJsxFragment(): void {
    if (
      this.#jsxFragmentName == null ||
      this.#hasReferencedJsxFragmentFactory
    ) {
      return;
    }
    this.#hasReferencedJsxFragmentFactory = this.referenceInSomeUpperScope(
      this.#jsxFragmentName,
    );
  }

Referencer.referenceJsxPragma(): void

Returns: void

Calls:

  • this.referenceInSomeUpperScope
Code
private referenceJsxPragma(): void {
    if (this.#jsxPragma == null || this.#hasReferencedJsxFactory) {
      return;
    }
    this.#hasReferencedJsxFactory = this.referenceInSomeUpperScope(
      this.#jsxPragma,
    );
  }

Referencer.visitClass(node: TSESTree.ClassDeclaration | TSESTree.Cl…): void

Parameters:

  • node TSESTree.ClassDeclaration | TSESTree.ClassExpression

Returns: void

Calls:

  • ClassVisitor.visit
Code
protected visitClass(
    node: TSESTree.ClassDeclaration | TSESTree.ClassExpression,
  ): void {
    ClassVisitor.visit(this, node);
  }

Referencer.visitForIn(node: TSESTree.ForInStatement | TSESTree.ForO…): void

Parameters:

  • node TSESTree.ForInStatement | TSESTree.ForOfStatement

Returns: void

Calls:

  • this.scopeManager.nestForScope
  • this.visit
  • this.visitPattern
  • this.currentScope().referenceValue
  • this.currentScope
  • this.referencingDefaultValue
  • this.close
Code
protected visitForIn(
    node: TSESTree.ForInStatement | TSESTree.ForOfStatement,
  ): void {
    if (
      node.left.type === AST_NODE_TYPES.VariableDeclaration &&
      node.left.kind !== 'var'
    ) {
      this.scopeManager.nestForScope(node);
    }

    if (node.left.type === AST_NODE_TYPES.VariableDeclaration) {
      this.visit(node.left);
      this.visitPattern(node.left.declarations[0].id, pattern => {
        this.currentScope().referenceValue(
          pattern,
          ReferenceFlag.Write,
          node.right,
          null,
          true,
        );
      });
    } else {
      this.visitPattern(
        node.left,
        (pattern, info) => {
          const maybeImplicitGlobal = !this.currentScope().isStrict
            ? {
                node,
                pattern,
              }
            : null;
          this.referencingDefaultValue(
            pattern,
            info.assignments,
            maybeImplicitGlobal,
            false,
          );
          this.currentScope().referenceValue(
            pattern,
            ReferenceFlag.Write,
            node.right,
            maybeImplicitGlobal,
            false,
          );
        },
        { processRightHandNodes: true },
      );
    }
    this.visit(node.right);
    this.visit(node.body);

    this.close(node);
  }

Referencer.visitFunction(node: | TSESTree.ArrowFunctionExpression | TS…): void

Parameters:

  • node | TSESTree.ArrowFunctionExpression | TSESTree.FunctionDeclaration | TSESTree.FunctionExpression | TSESTree.TSDeclareFunction | TSESTree.TSEmptyBodyFunctionExpression

Returns: void

Calls:

  • this.scopeManager.nestFunctionExpressionNameScope
  • this.currentScope().defineIdentifier
  • this.scopeManager.nestFunctionScope
  • this.visitPattern
  • this.referencingDefaultValue
  • this.visitFunctionParameterTypeAnnotation
  • param.decorators.forEach
  • this.visit
  • this.visitType
  • this.visitChildren
  • this.close

Internal Comments:

// FunctionDeclaration name is defined in upper scope
// NOTE: Not referring variableScope. It is intended.
// Since
//  in ES5, FunctionDeclaration should be in FunctionBody.
//  in ES6, FunctionDeclaration should be block scoped.
// FunctionExpression with name creates its special scope; (x5)
// FunctionExpressionNameScope. (x5)
// id is defined in upper scope (x6)
// Consider this function is in the MethodDefinition. (x5)
// Process parameter declarations.
// In TypeScript there are a number of function-like constructs which have no body,
// so check it exists before traversing
// Skip BlockStatement to prevent creating BlockStatement scope.

Code
protected visitFunction(
    node:
      | TSESTree.ArrowFunctionExpression
      | TSESTree.FunctionDeclaration
      | TSESTree.FunctionExpression
      | TSESTree.TSDeclareFunction
      | TSESTree.TSEmptyBodyFunctionExpression,
  ): void {
    // FunctionDeclaration name is defined in upper scope
    // NOTE: Not referring variableScope. It is intended.
    // Since
    //  in ES5, FunctionDeclaration should be in FunctionBody.
    //  in ES6, FunctionDeclaration should be block scoped.

    if (node.type === AST_NODE_TYPES.FunctionExpression) {
      if (node.id) {
        // FunctionExpression with name creates its special scope;
        // FunctionExpressionNameScope.
        this.scopeManager.nestFunctionExpressionNameScope(node);
      }
    } else if (node.id) {
      // id is defined in upper scope
      this.currentScope().defineIdentifier(
        node.id,
        new FunctionNameDefinition(node.id, node),
      );
    }

    // Consider this function is in the MethodDefinition.
    this.scopeManager.nestFunctionScope(node, false);

    // Process parameter declarations.
    for (const param of node.params) {
      this.visitPattern(
        param,
        (pattern, info) => {
          this.currentScope().defineIdentifier(
            pattern,
            new ParameterDefinition(pattern, node, info.rest),
          );

          this.referencingDefaultValue(pattern, info.assignments, null, true);
        },
        { processRightHandNodes: true },
      );
      this.visitFunctionParameterTypeAnnotation(param);
      param.decorators.forEach(d => this.visit(d));
    }

    this.visitType(node.returnType);
    this.visitType(node.typeParameters);

    // In TypeScript there are a number of function-like constructs which have no body,
    // so check it exists before traversing
    if (node.body) {
      // Skip BlockStatement to prevent creating BlockStatement scope.
      if (node.body.type === AST_NODE_TYPES.BlockStatement) {
        this.visitChildren(node.body);
      } else {
        this.visit(node.body);
      }
    }

    this.close(node);
  }

Referencer.visitFunctionParameterTypeAnnotation(node: TSESTree.Parameter): void

Parameters:

  • node TSESTree.Parameter

Returns: void

Calls:

  • this.visitType
  • this.visitFunctionParameterTypeAnnotation
Code
protected visitFunctionParameterTypeAnnotation(
    node: TSESTree.Parameter,
  ): void {
    switch (node.type) {
      case AST_NODE_TYPES.AssignmentPattern:
        this.visitType(node.left.typeAnnotation);
        break;
      case AST_NODE_TYPES.TSParameterProperty:
        this.visitFunctionParameterTypeAnnotation(node.parameter);
        break;
      default:
        this.visitType(node.typeAnnotation);
        break;
    }
  }

Referencer.visitJSXElement(node: TSESTree.JSXClosingElement | TSESTree.J…): void

Parameters:

  • node TSESTree.JSXClosingElement | TSESTree.JSXOpeningElement

Returns: void

Calls:

  • node.name.name[0].toUpperCase
  • this.visit

Internal Comments:

// lower cased component names are always treated as "intrinsic" names, and are converted to a string, (x4)
// not a variable by JSX transforms: (x4)
// <div /> => React.createElement("div", null) (x4)
// the only case we want to visit a lower-cased component has its name as "this", (x4)

Code
protected visitJSXElement(
    node: TSESTree.JSXClosingElement | TSESTree.JSXOpeningElement,
  ): void {
    if (node.name.type === AST_NODE_TYPES.JSXIdentifier) {
      if (
        node.name.name[0].toUpperCase() === node.name.name[0] ||
        node.name.name === 'this'
      ) {
        // lower cased component names are always treated as "intrinsic" names, and are converted to a string,
        // not a variable by JSX transforms:
        // <div /> => React.createElement("div", null)

        // the only case we want to visit a lower-cased component has its name as "this",
        this.visit(node.name);
      }
    } else {
      this.visit(node.name);
    }
  }

Referencer.visitProperty(node: TSESTree.Property): void

Parameters:

  • node TSESTree.Property

Returns: void

Calls:

  • this.visit
Code
protected visitProperty(node: TSESTree.Property): void {
    if (node.computed) {
      this.visit(node.key);
    }

    this.visit(node.value);
  }

Referencer.visitType(node: TSESTree.Node | null | undefined): void

Parameters:

  • node TSESTree.Node | null | undefined

Returns: void

Calls:

  • TypeVisitor.visit
Code
protected visitType(node: TSESTree.Node | null | undefined): void {
    if (!node) {
      return;
    }
    TypeVisitor.visit(this, node);
  }

Referencer.visitTypeAssertion(node: | TSESTree.TSAsExpression | TSESTree.TS…): void

Parameters:

  • node | TSESTree.TSAsExpression | TSESTree.TSSatisfiesExpression | TSESTree.TSTypeAssertion

Returns: void

Calls:

  • this.visit
  • this.visitType
Code
protected visitTypeAssertion(
    node:
      | TSESTree.TSAsExpression
      | TSESTree.TSSatisfiesExpression
      | TSESTree.TSTypeAssertion,
  ): void {
    this.visit(node.expression);
    this.visitType(node.typeAnnotation);
  }

Referencer.ArrowFunctionExpression(node: TSESTree.ArrowFunctionExpression): void

Parameters:

  • node TSESTree.ArrowFunctionExpression

Returns: void

Calls:

  • this.visitFunction
Code
protected ArrowFunctionExpression(
    node: TSESTree.ArrowFunctionExpression,
  ): void {
    this.visitFunction(node);
  }

Referencer.AssignmentExpression(node: TSESTree.AssignmentExpression): void

Parameters:

  • node TSESTree.AssignmentExpression

Returns: void

Calls:

  • this.visitExpressionTarget
  • PatternVisitor.isPattern
  • this.visitPattern
  • this.currentScope
  • this.referencingDefaultValue
  • this.currentScope().referenceValue
  • this.visit
Code
protected AssignmentExpression(node: TSESTree.AssignmentExpression): void {
    const left = this.visitExpressionTarget(node.left);

    if (PatternVisitor.isPattern(left)) {
      if (node.operator === '=') {
        this.visitPattern(
          left,
          (pattern, info) => {
            const maybeImplicitGlobal = !this.currentScope().isStrict
              ? {
                  node,
                  pattern,
                }
              : null;
            this.referencingDefaultValue(
              pattern,
              info.assignments,
              maybeImplicitGlobal,
              false,
            );
            this.currentScope().referenceValue(
              pattern,
              ReferenceFlag.Write,
              node.right,
              maybeImplicitGlobal,
              false,
            );
          },
          { processRightHandNodes: true },
        );
      } else if (left.type === AST_NODE_TYPES.Identifier) {
        this.currentScope().referenceValue(
          left,
          ReferenceFlag.ReadWrite,
          node.right,
        );
      }
    } else {
      this.visit(left);
    }
    this.visit(node.right);
  }

Referencer.BlockStatement(node: TSESTree.BlockStatement): void

Parameters:

  • node TSESTree.BlockStatement

Returns: void

Calls:

  • this.scopeManager.nestBlockScope
  • this.visitChildren
  • this.close
Code
protected BlockStatement(node: TSESTree.BlockStatement): void {
    this.scopeManager.nestBlockScope(node);

    this.visitChildren(node);

    this.close(node);
  }

Referencer.BreakStatement(): void

Returns: void

Code
protected BreakStatement(): void {
    // don't reference the break statement's label
  }

Referencer.CallExpression(node: TSESTree.CallExpression): void

Parameters:

  • node TSESTree.CallExpression

Returns: void

Calls:

  • this.visitChildren
  • this.visitType
Code
protected CallExpression(node: TSESTree.CallExpression): void {
    this.visitChildren(node, ['typeArguments']);
    this.visitType(node.typeArguments);
  }

Referencer.CatchClause(node: TSESTree.CatchClause): void

Parameters:

  • node TSESTree.CatchClause

Returns: void

Calls:

  • this.scopeManager.nestCatchScope
  • this.visitPattern
  • this.currentScope().defineIdentifier
  • this.referencingDefaultValue
  • this.visit
  • this.close
Code
protected CatchClause(node: TSESTree.CatchClause): void {
    this.scopeManager.nestCatchScope(node);

    if (node.param) {
      this.visitPattern(
        node.param,
        (pattern, info) => {
          this.currentScope().defineIdentifier(
            pattern,
            new CatchClauseDefinition(pattern, node),
          );
          this.referencingDefaultValue(pattern, info.assignments, null, true);
        },
        { processRightHandNodes: true },
      );
    }
    this.visit(node.body);

    this.close(node);
  }

Referencer.ClassDeclaration(node: TSESTree.ClassDeclaration): void

Parameters:

  • node TSESTree.ClassDeclaration

Returns: void

Calls:

  • this.visitClass
Code
protected ClassDeclaration(node: TSESTree.ClassDeclaration): void {
    this.visitClass(node);
  }

Referencer.ClassExpression(node: TSESTree.ClassExpression): void

Parameters:

  • node TSESTree.ClassExpression

Returns: void

Calls:

  • this.visitClass
Code
protected ClassExpression(node: TSESTree.ClassExpression): void {
    this.visitClass(node);
  }

Referencer.ContinueStatement(): void

Returns: void

Code
protected ContinueStatement(): void {
    // don't reference the continue statement's label
  }

Referencer.ExportAllDeclaration(): void

Returns: void

Code
protected ExportAllDeclaration(): void {
    // this defines no local variables
  }

Referencer.ExportDefaultDeclaration(node: TSESTree.ExportDefaultDeclaration): void

Parameters:

  • node TSESTree.ExportDefaultDeclaration

Returns: void

Calls:

  • ExportVisitor.visit
  • this.visit
Code
protected ExportDefaultDeclaration(
    node: TSESTree.ExportDefaultDeclaration,
  ): void {
    if (node.declaration.type === AST_NODE_TYPES.Identifier) {
      ExportVisitor.visit(this, node);
    } else {
      this.visit(node.declaration);
    }
  }

Referencer.ExportNamedDeclaration(node: TSESTree.ExportNamedDeclaration): void

Parameters:

  • node TSESTree.ExportNamedDeclaration

Returns: void

Calls:

  • this.visit
  • ExportVisitor.visit
Code
protected ExportNamedDeclaration(
    node: TSESTree.ExportNamedDeclaration,
  ): void {
    if (node.declaration) {
      this.visit(node.declaration);
    } else {
      ExportVisitor.visit(this, node);
    }
  }

Referencer.ForInStatement(node: TSESTree.ForInStatement): void

Parameters:

  • node TSESTree.ForInStatement

Returns: void

Calls:

  • this.visitForIn
Code
protected ForInStatement(node: TSESTree.ForInStatement): void {
    this.visitForIn(node);
  }

Referencer.ForOfStatement(node: TSESTree.ForOfStatement): void

Parameters:

  • node TSESTree.ForOfStatement

Returns: void

Calls:

  • this.visitForIn
Code
protected ForOfStatement(node: TSESTree.ForOfStatement): void {
    this.visitForIn(node);
  }

Referencer.ForStatement(node: TSESTree.ForStatement): void

Parameters:

  • node TSESTree.ForStatement

Returns: void

Calls:

  • this.scopeManager.nestForScope
  • this.visitChildren
  • this.close

Internal Comments:

// Create ForStatement declaration.
// NOTE: In ES6, ForStatement dynamically generates per iteration environment. However, this is
// a static analyzer, we only generate one scope for ForStatement.

Code
protected ForStatement(node: TSESTree.ForStatement): void {
    // Create ForStatement declaration.
    // NOTE: In ES6, ForStatement dynamically generates per iteration environment. However, this is
    // a static analyzer, we only generate one scope for ForStatement.
    if (
      node.init?.type === AST_NODE_TYPES.VariableDeclaration &&
      node.init.kind !== 'var'
    ) {
      this.scopeManager.nestForScope(node);
    }

    this.visitChildren(node);

    this.close(node);
  }

Referencer.FunctionDeclaration(node: TSESTree.FunctionDeclaration): void

Parameters:

  • node TSESTree.FunctionDeclaration

Returns: void

Calls:

  • this.visitFunction
Code
protected FunctionDeclaration(node: TSESTree.FunctionDeclaration): void {
    this.visitFunction(node);
  }

Referencer.FunctionExpression(node: TSESTree.FunctionExpression): void

Parameters:

  • node TSESTree.FunctionExpression

Returns: void

Calls:

  • this.visitFunction
Code
protected FunctionExpression(node: TSESTree.FunctionExpression): void {
    this.visitFunction(node);
  }

Referencer.Identifier(node: TSESTree.Identifier): void

Parameters:

  • node TSESTree.Identifier

Returns: void

Calls:

  • this.currentScope().referenceValue
  • this.visitType
Code
protected Identifier(node: TSESTree.Identifier): void {
    this.currentScope().referenceValue(node);
    this.visitType(node.typeAnnotation);
  }

Referencer.ImportAttribute(): void

Returns: void

Code
protected ImportAttribute(): void {
    // import assertions are module metadata and thus have no variables to reference
  }

Referencer.ImportDeclaration(node: TSESTree.ImportDeclaration): void

Parameters:

  • node TSESTree.ImportDeclaration

Returns: void

Calls:

  • assert (from ../assert)
  • this.scopeManager.isModule
  • ImportVisitor.visit
Code
protected ImportDeclaration(node: TSESTree.ImportDeclaration): void {
    assert(
      this.scopeManager.isModule(),
      'ImportDeclaration should appear when the mode is ES6 and in the module context.',
    );

    ImportVisitor.visit(this, node);
  }

Referencer.JSXAttribute(node: TSESTree.JSXAttribute): void

Parameters:

  • node TSESTree.JSXAttribute

Returns: void

Calls:

  • this.visit
Code
protected JSXAttribute(node: TSESTree.JSXAttribute): void {
    this.visit(node.value);
  }

Referencer.JSXClosingElement(node: TSESTree.JSXClosingElement): void

Parameters:

  • node TSESTree.JSXClosingElement

Returns: void

Calls:

  • this.visitJSXElement
Code
protected JSXClosingElement(node: TSESTree.JSXClosingElement): void {
    this.visitJSXElement(node);
  }

Referencer.JSXFragment(node: TSESTree.JSXFragment): void

Parameters:

  • node TSESTree.JSXFragment

Returns: void

Calls:

  • this.referenceJsxPragma
  • this.referenceJsxFragment
  • this.visitChildren
Code
protected JSXFragment(node: TSESTree.JSXFragment): void {
    this.referenceJsxPragma();
    this.referenceJsxFragment();
    this.visitChildren(node);
  }

Referencer.JSXIdentifier(node: TSESTree.JSXIdentifier): void

Parameters:

  • node TSESTree.JSXIdentifier

Returns: void

Calls:

  • this.currentScope().referenceValue
Code
protected JSXIdentifier(node: TSESTree.JSXIdentifier): void {
    this.currentScope().referenceValue(node);
  }

Referencer.JSXMemberExpression(node: TSESTree.JSXMemberExpression): void

Parameters:

  • node TSESTree.JSXMemberExpression

Returns: void

Calls:

  • this.visit
Code
protected JSXMemberExpression(node: TSESTree.JSXMemberExpression): void {
    if (
      node.object.type !== AST_NODE_TYPES.JSXIdentifier ||
      node.object.name !== 'this'
    ) {
      this.visit(node.object);
    }
    // we don't ever reference the property as it's always going to be a property on the thing
  }

Referencer.JSXOpeningElement(node: TSESTree.JSXOpeningElement): void

Parameters:

  • node TSESTree.JSXOpeningElement

Returns: void

Calls:

  • this.referenceJsxPragma
  • this.visitJSXElement
  • this.visitType
  • this.visit
Code
protected JSXOpeningElement(node: TSESTree.JSXOpeningElement): void {
    this.referenceJsxPragma();
    this.visitJSXElement(node);
    this.visitType(node.typeArguments);
    for (const attr of node.attributes) {
      this.visit(attr);
    }
  }

Referencer.LabeledStatement(node: TSESTree.LabeledStatement): void

Parameters:

  • node TSESTree.LabeledStatement

Returns: void

Calls:

  • this.visit
Code
protected LabeledStatement(node: TSESTree.LabeledStatement): void {
    this.visit(node.body);
  }

Referencer.MemberExpression(node: TSESTree.MemberExpression): void

Parameters:

  • node TSESTree.MemberExpression

Returns: void

Calls:

  • this.visit
Code
protected MemberExpression(node: TSESTree.MemberExpression): void {
    this.visit(node.object);
    if (node.computed) {
      this.visit(node.property);
    }
  }

Referencer.MetaProperty(): void

Returns: void

Code
protected MetaProperty(): void {
    // meta properties all builtin globals
  }

Referencer.NewExpression(node: TSESTree.NewExpression): void

Parameters:

  • node TSESTree.NewExpression

Returns: void

Calls:

  • this.visitChildren
  • this.visitType
Code
protected NewExpression(node: TSESTree.NewExpression): void {
    this.visitChildren(node, ['typeArguments']);
    this.visitType(node.typeArguments);
  }

Referencer.PrivateIdentifier(): void

Returns: void

Code
protected PrivateIdentifier(): void {
    // private identifiers are members on classes and thus have no variables to reference
  }

Referencer.Program(node: TSESTree.Program): void

Parameters:

  • node TSESTree.Program

Returns: void

Calls:

  • this.scopeManager.nestGlobalScope
  • this.populateGlobalsFromLib
  • this.scopeManager.isGlobalReturn
  • this.currentScope
  • this.scopeManager.nestFunctionScope
  • this.scopeManager.isModule
  • this.scopeManager.nestModuleScope
  • this.scopeManager.isImpliedStrict
  • this.visitChildren
  • this.close

Internal Comments:

// Force strictness of GlobalScope to false when using node.js scope. (x6)

Code
protected Program(node: TSESTree.Program): void {
    const globalScope = this.scopeManager.nestGlobalScope(node);
    this.populateGlobalsFromLib(globalScope);

    if (this.scopeManager.isGlobalReturn()) {
      // Force strictness of GlobalScope to false when using node.js scope.
      this.currentScope().isStrict = false;
      this.scopeManager.nestFunctionScope(node, false);
    }

    if (this.scopeManager.isModule()) {
      this.scopeManager.nestModuleScope(node);
    }

    if (this.scopeManager.isImpliedStrict()) {
      this.currentScope().isStrict = true;
    }

    this.visitChildren(node);
    this.close(node);
  }

Referencer.Property(node: TSESTree.Property): void

Parameters:

  • node TSESTree.Property

Returns: void

Calls:

  • this.visitProperty
Code
protected Property(node: TSESTree.Property): void {
    this.visitProperty(node);
  }

Referencer.SwitchStatement(node: TSESTree.SwitchStatement): void

Parameters:

  • node TSESTree.SwitchStatement

Returns: void

Calls:

  • this.visit
  • this.scopeManager.nestSwitchScope
  • this.close
Code
protected SwitchStatement(node: TSESTree.SwitchStatement): void {
    this.visit(node.discriminant);

    this.scopeManager.nestSwitchScope(node);

    for (const switchCase of node.cases) {
      this.visit(switchCase);
    }

    this.close(node);
  }

Referencer.TaggedTemplateExpression(node: TSESTree.TaggedTemplateExpression): void

Parameters:

  • node TSESTree.TaggedTemplateExpression

Returns: void

Calls:

  • this.visit
  • this.visitType
Code
protected TaggedTemplateExpression(
    node: TSESTree.TaggedTemplateExpression,
  ): void {
    this.visit(node.tag);
    this.visit(node.quasi);
    this.visitType(node.typeArguments);
  }

Referencer.TSAsExpression(node: TSESTree.TSAsExpression): void

Parameters:

  • node TSESTree.TSAsExpression

Returns: void

Calls:

  • this.visitTypeAssertion
Code
protected TSAsExpression(node: TSESTree.TSAsExpression): void {
    this.visitTypeAssertion(node);
  }

Referencer.TSDeclareFunction(node: TSESTree.TSDeclareFunction): void

Parameters:

  • node TSESTree.TSDeclareFunction

Returns: void

Calls:

  • this.visitFunction
Code
protected TSDeclareFunction(node: TSESTree.TSDeclareFunction): void {
    this.visitFunction(node);
  }

Referencer.TSEmptyBodyFunctionExpression(node: TSESTree.TSEmptyBodyFunctionExpression): void

Parameters:

  • node TSESTree.TSEmptyBodyFunctionExpression

Returns: void

Calls:

  • this.visitFunction
Code
protected TSEmptyBodyFunctionExpression(
    node: TSESTree.TSEmptyBodyFunctionExpression,
  ): void {
    this.visitFunction(node);
  }

Referencer.TSEnumDeclaration(node: TSESTree.TSEnumDeclaration): void

Parameters:

  • node TSESTree.TSEnumDeclaration

Returns: void

Calls:

  • this.currentScope().defineIdentifier
  • this.scopeManager.nestTSEnumScope
  • this.currentScope().defineLiteralIdentifier
  • this.visit
  • this.close

Internal Comments:

// enum members can be referenced within the enum body (x5)
// TS resolves literal named members to be actual names
// enum Foo {
//   'a' = 1,
//   b = a, // this references the 'a' member
// }

Code
protected TSEnumDeclaration(node: TSESTree.TSEnumDeclaration): void {
    this.currentScope().defineIdentifier(
      node.id,
      new TSEnumNameDefinition(node.id, node),
    );

    // enum members can be referenced within the enum body
    this.scopeManager.nestTSEnumScope(node);

    for (const member of node.body.members) {
      // TS resolves literal named members to be actual names
      // enum Foo {
      //   'a' = 1,
      //   b = a, // this references the 'a' member
      // }
      if (
        member.id.type === AST_NODE_TYPES.Literal &&
        typeof member.id.value === 'string'
      ) {
        const name = member.id;
        this.currentScope().defineLiteralIdentifier(
          name,
          new TSEnumMemberDefinition(name, member),
        );
      } else if (member.id.type === AST_NODE_TYPES.Identifier) {
        this.currentScope().defineIdentifier(
          member.id,
          new TSEnumMemberDefinition(member.id, member),
        );
      }

      this.visit(member.initializer);
    }

    this.close(node);
  }

Referencer.TSExportAssignment(node: TSESTree.TSExportAssignment): void

Parameters:

  • node TSESTree.TSExportAssignment

Returns: void

Calls:

  • this.currentScope().referenceDualValueType
  • this.visit

Internal Comments:

// this is a special case - you can `export = T` where `T` is a type OR a (x6)
// value however `T[U]` is illegal when `T` is a type and `T.U` is illegal (x6)
// when `T.U` is a type (x6)
// i.e. if the expression is JUST an Identifier - it could be either ref (x6)
// kind; otherwise the standard rules apply (x6)

Code
protected TSExportAssignment(node: TSESTree.TSExportAssignment): void {
    if (node.expression.type === AST_NODE_TYPES.Identifier) {
      // this is a special case - you can `export = T` where `T` is a type OR a
      // value however `T[U]` is illegal when `T` is a type and `T.U` is illegal
      // when `T.U` is a type
      // i.e. if the expression is JUST an Identifier - it could be either ref
      // kind; otherwise the standard rules apply
      this.currentScope().referenceDualValueType(node.expression);
    } else {
      this.visit(node.expression);
    }
  }

Referencer.TSImportEqualsDeclaration(node: TSESTree.TSImportEqualsDeclaration): void

Parameters:

  • node TSESTree.TSImportEqualsDeclaration

Returns: void

Calls:

  • this.currentScope().defineIdentifier
  • this.visit
Code
protected TSImportEqualsDeclaration(
    node: TSESTree.TSImportEqualsDeclaration,
  ): void {
    this.currentScope().defineIdentifier(
      node.id,
      new ImportBindingDefinition(node.id, node, node),
    );

    if (node.moduleReference.type === AST_NODE_TYPES.TSQualifiedName) {
      let moduleIdentifier = node.moduleReference.left;
      while (moduleIdentifier.type === AST_NODE_TYPES.TSQualifiedName) {
        moduleIdentifier = moduleIdentifier.left;
      }
      this.visit(moduleIdentifier);
    } else {
      this.visit(node.moduleReference);
    }
  }

Referencer.TSInstantiationExpression(node: TSESTree.TSInstantiationExpression): void

Parameters:

  • node TSESTree.TSInstantiationExpression

Returns: void

Calls:

  • this.visitChildren
  • this.visitType
Code
protected TSInstantiationExpression(
    node: TSESTree.TSInstantiationExpression,
  ): void {
    this.visitChildren(node, ['typeArguments']);
    this.visitType(node.typeArguments);
  }

Referencer.TSInterfaceDeclaration(node: TSESTree.TSInterfaceDeclaration): void

Parameters:

  • node TSESTree.TSInterfaceDeclaration

Returns: void

Calls:

  • this.visitType
Code
protected TSInterfaceDeclaration(
    node: TSESTree.TSInterfaceDeclaration,
  ): void {
    this.visitType(node);
  }

Referencer.TSModuleDeclaration(node: TSESTree.TSModuleDeclaration): void

Parameters:

  • node TSESTree.TSModuleDeclaration

Returns: void

Calls:

  • this.currentScope().defineIdentifier
  • this.scopeManager.nestTSModuleScope
  • this.visit
  • this.close
Code
protected TSModuleDeclaration(node: TSESTree.TSModuleDeclaration): void {
    if (node.id.type === AST_NODE_TYPES.Identifier && node.kind !== 'global') {
      this.currentScope().defineIdentifier(
        node.id,
        new TSModuleNameDefinition(node.id, node),
      );
    }

    this.scopeManager.nestTSModuleScope(node);

    this.visit(node.body);

    this.close(node);
  }

Referencer.TSSatisfiesExpression(node: TSESTree.TSSatisfiesExpression): void

Parameters:

  • node TSESTree.TSSatisfiesExpression

Returns: void

Calls:

  • this.visitTypeAssertion
Code
protected TSSatisfiesExpression(node: TSESTree.TSSatisfiesExpression): void {
    this.visitTypeAssertion(node);
  }

Referencer.TSTypeAliasDeclaration(node: TSESTree.TSTypeAliasDeclaration): void

Parameters:

  • node TSESTree.TSTypeAliasDeclaration

Returns: void

Calls:

  • this.visitType
Code
protected TSTypeAliasDeclaration(
    node: TSESTree.TSTypeAliasDeclaration,
  ): void {
    this.visitType(node);
  }

Referencer.TSTypeAssertion(node: TSESTree.TSTypeAssertion): void

Parameters:

  • node TSESTree.TSTypeAssertion

Returns: void

Calls:

  • this.visitTypeAssertion
Code
protected TSTypeAssertion(node: TSESTree.TSTypeAssertion): void {
    this.visitTypeAssertion(node);
  }

Referencer.UpdateExpression(node: TSESTree.UpdateExpression): void

Parameters:

  • node TSESTree.UpdateExpression

Returns: void

Calls:

  • this.visitExpressionTarget
  • PatternVisitor.isPattern
  • this.visitPattern
  • this.currentScope().referenceValue
  • this.visitChildren
Code
protected UpdateExpression(node: TSESTree.UpdateExpression): void {
    const argument = this.visitExpressionTarget(node.argument);

    if (PatternVisitor.isPattern(argument)) {
      this.visitPattern(argument, pattern => {
        this.currentScope().referenceValue(
          pattern,
          ReferenceFlag.ReadWrite,
          null,
        );
      });
    } else {
      this.visitChildren(node);
    }
  }

Referencer.VariableDeclaration(node: TSESTree.VariableDeclaration): void

Parameters:

  • node TSESTree.VariableDeclaration

Returns: void

Calls:

  • this.currentScope
  • this.visitPattern
  • variableTargetScope.defineIdentifier
  • this.referencingDefaultValue
  • this.currentScope().referenceValue
  • this.visit
  • this.visitType
Code
protected VariableDeclaration(node: TSESTree.VariableDeclaration): void {
    const variableTargetScope =
      node.kind === 'var'
        ? this.currentScope().variableScope
        : this.currentScope();

    for (const decl of node.declarations) {
      const init = decl.init;

      this.visitPattern(
        decl.id,
        (pattern, info) => {
          variableTargetScope.defineIdentifier(
            pattern,
            new VariableDefinition(pattern, decl, node),
          );

          this.referencingDefaultValue(pattern, info.assignments, null, true);
          if (init) {
            this.currentScope().referenceValue(
              pattern,
              ReferenceFlag.Write,
              init,
              null,
              true,
            );
          }
        },
        { processRightHandNodes: true },
      );

      this.visit(decl.init);
      this.visitType(decl.id.typeAnnotation);
    }
  }

Referencer.WithStatement(node: TSESTree.WithStatement): void

Parameters:

  • node TSESTree.WithStatement

Returns: void

Calls:

  • this.visit
  • this.scopeManager.nestWithScope
  • this.close

Internal Comments:

// Then nest scope for WithStatement. (x5)

Code
protected WithStatement(node: TSESTree.WithStatement): void {
    this.visit(node.object);

    // Then nest scope for WithStatement.
    this.scopeManager.nestWithScope(node);

    this.visit(node.body);

    this.close(node);
  }

Referencer.visitExpressionTarget(left: TSESTree.Node): Node

Parameters:

  • left TSESTree.Node

Returns: Node

Calls:

  • this.visitType

Internal Comments:

// explicitly visit the type annotation (x4)
// intentional fallthrough
// unwrap the expression (x3)

Code
private visitExpressionTarget(left: TSESTree.Node) {
    switch (left.type) {
      case AST_NODE_TYPES.TSAsExpression:
      case AST_NODE_TYPES.TSTypeAssertion:
        // explicitly visit the type annotation
        this.visitType(left.typeAnnotation);
      // intentional fallthrough
      case AST_NODE_TYPES.TSNonNullExpression:
        // unwrap the expression
        left = left.expression;
    }

    return left;
  }

Classes

Referencer

Extends: Visitor

Methods (69) — full entries under Functions

Method Signature
populateGlobalsFromLib (globalScope: GlobalScope): void
resolveLibDefinitions (): Set<LibDefinition>
close (node: TSESTree.Node): void
currentScope (): Scope
currentScope (throwOnNull: true): Scope \| null
currentScope (dontThrowOnNull: true): Scope \| null
referencingDefaultValue (pattern: TSESTree.Identifier, assignments: (TSESTree.AssignmentExpression \| TSESTree.Assignment...
referenceInSomeUpperScope (name: string): boolean
referenceJsxFragment (): void
referenceJsxPragma (): void
visitClass (node: TSESTree.ClassDeclaration \| TSESTree.ClassExpression): void
visitForIn (node: TSESTree.ForInStatement \| TSESTree.ForOfStatement): void
visitFunction (node: \| TSESTree.ArrowFunctionExpression \| TSESTree.FunctionDeclaration \| TSESTree.FunctionEx...
visitFunctionParameterTypeAnnotation (node: TSESTree.Parameter): void
visitJSXElement (node: TSESTree.JSXClosingElement \| TSESTree.JSXOpeningElement): void
visitProperty (node: TSESTree.Property): void
visitType (node: TSESTree.Node \| null \| undefined): void
visitTypeAssertion (node: \| TSESTree.TSAsExpression \| TSESTree.TSSatisfiesExpression \| TSESTree.TSTypeAssertion):...
ArrowFunctionExpression (node: TSESTree.ArrowFunctionExpression): void
AssignmentExpression (node: TSESTree.AssignmentExpression): void
BlockStatement (node: TSESTree.BlockStatement): void
BreakStatement (): void
CallExpression (node: TSESTree.CallExpression): void
CatchClause (node: TSESTree.CatchClause): void
ClassDeclaration (node: TSESTree.ClassDeclaration): void
ClassExpression (node: TSESTree.ClassExpression): void
ContinueStatement (): void
ExportAllDeclaration (): void
ExportDefaultDeclaration (node: TSESTree.ExportDefaultDeclaration): void
ExportNamedDeclaration (node: TSESTree.ExportNamedDeclaration): void
ForInStatement (node: TSESTree.ForInStatement): void
ForOfStatement (node: TSESTree.ForOfStatement): void
ForStatement (node: TSESTree.ForStatement): void
FunctionDeclaration (node: TSESTree.FunctionDeclaration): void
FunctionExpression (node: TSESTree.FunctionExpression): void
Identifier (node: TSESTree.Identifier): void
ImportAttribute (): void
ImportDeclaration (node: TSESTree.ImportDeclaration): void
JSXAttribute (node: TSESTree.JSXAttribute): void
JSXClosingElement (node: TSESTree.JSXClosingElement): void
JSXFragment (node: TSESTree.JSXFragment): void
JSXIdentifier (node: TSESTree.JSXIdentifier): void
JSXMemberExpression (node: TSESTree.JSXMemberExpression): void
JSXOpeningElement (node: TSESTree.JSXOpeningElement): void
LabeledStatement (node: TSESTree.LabeledStatement): void
MemberExpression (node: TSESTree.MemberExpression): void
MetaProperty (): void
NewExpression (node: TSESTree.NewExpression): void
PrivateIdentifier (): void
Program (node: TSESTree.Program): void
Property (node: TSESTree.Property): void
SwitchStatement (node: TSESTree.SwitchStatement): void
TaggedTemplateExpression (node: TSESTree.TaggedTemplateExpression): void
TSAsExpression (node: TSESTree.TSAsExpression): void
TSDeclareFunction (node: TSESTree.TSDeclareFunction): void
TSEmptyBodyFunctionExpression (node: TSESTree.TSEmptyBodyFunctionExpression): void
TSEnumDeclaration (node: TSESTree.TSEnumDeclaration): void
TSExportAssignment (node: TSESTree.TSExportAssignment): void
TSImportEqualsDeclaration (node: TSESTree.TSImportEqualsDeclaration): void
TSInstantiationExpression (node: TSESTree.TSInstantiationExpression): void
TSInterfaceDeclaration (node: TSESTree.TSInterfaceDeclaration): void
TSModuleDeclaration (node: TSESTree.TSModuleDeclaration): void
TSSatisfiesExpression (node: TSESTree.TSSatisfiesExpression): void
TSTypeAliasDeclaration (node: TSESTree.TSTypeAliasDeclaration): void
TSTypeAssertion (node: TSESTree.TSTypeAssertion): void
UpdateExpression (node: TSESTree.UpdateExpression): void
VariableDeclaration (node: TSESTree.VariableDeclaration): void
WithStatement (node: TSESTree.WithStatement): void
visitExpressionTarget (left: TSESTree.Node): Node

Interfaces

ReferencerOptions

Interface Code
export interface ReferencerOptions extends VisitorOptions {
  jsxFragmentName: string | null;
  jsxPragma: string | null;
  lib: Lib[];
}

Properties

Name Type Optional Description
jsxFragmentName string \| null not shown
jsxPragma string \| null not shown
lib Lib[] not shown

Generated by Syntax Scribe