Skip to content

⬅️ Back to Table of Contents

📄 PatternVisitor.ts

📊 Analysis Summary

Metric Count
🔧 Functions 13
🧱 Classes 1
📦 Imports 4
📊 Variables & Constants 1
📑 Type Aliases 2

📚 Table of Contents

🛠️ File Location:

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

📦 Imports

Name Source
TSESTree @typescript-eslint/types
AST_NODE_TYPES @typescript-eslint/types
VisitorOptions ./VisitorBase
VisitorBase ./VisitorBase

Variables & Constants

Name Type Kind Value Exported
nodeType any const node.type

Functions

`PatternVisitor.isPattern(node: TSESTree.Node): node is

| TSESTree.ArrayPattern
| TSESTree.AssignmentPattern
| TSESTree.Identifier
| TSESTree.ObjectPattern
| TSESTree.RestElement
| TSESTree.SpreadElement`
Code
public static isPattern(
    node: TSESTree.Node,
  ): node is
    | TSESTree.ArrayPattern
    | TSESTree.AssignmentPattern
    | TSESTree.Identifier
    | TSESTree.ObjectPattern
    | TSESTree.RestElement
    | TSESTree.SpreadElement {
    const nodeType = node.type;

    return (
      nodeType === AST_NODE_TYPES.Identifier ||
      nodeType === AST_NODE_TYPES.ObjectPattern ||
      nodeType === AST_NODE_TYPES.ArrayPattern ||
      nodeType === AST_NODE_TYPES.SpreadElement ||
      nodeType === AST_NODE_TYPES.RestElement ||
      nodeType === AST_NODE_TYPES.AssignmentPattern
    );
  }
  • Parameters:
  • node: TSESTree.Node
  • Return Type: node is | TSESTree.ArrayPattern | TSESTree.AssignmentPattern | TSESTree.Identifier | TSESTree.ObjectPattern | TSESTree.RestElement | TSESTree.SpreadElement

PatternVisitor.ArrayExpression(node: TSESTree.ArrayExpression): void

Code
protected ArrayExpression(node: TSESTree.ArrayExpression): void {
    node.elements.forEach(this.visit, this);
  }
  • Parameters:
  • node: TSESTree.ArrayExpression
  • Return Type: void
  • Calls:
  • node.elements.forEach

PatternVisitor.ArrayPattern(pattern: TSESTree.ArrayPattern): void

Code
protected ArrayPattern(pattern: TSESTree.ArrayPattern): void {
    for (const element of pattern.elements) {
      this.visit(element);
    }
  }
  • Parameters:
  • pattern: TSESTree.ArrayPattern
  • Return Type: void
  • Calls:
  • this.visit

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

Code
protected AssignmentExpression(node: TSESTree.AssignmentExpression): void {
    this.#assignments.push(node);
    this.visit(node.left);
    this.rightHandNodes.push(node.right);
    this.#assignments.pop();
  }
  • Parameters:
  • node: TSESTree.AssignmentExpression
  • Return Type: void
  • Calls:
  • this.#assignments.push
  • this.visit
  • this.rightHandNodes.push
  • this.#assignments.pop

PatternVisitor.AssignmentPattern(pattern: TSESTree.AssignmentPattern): void

Code
protected AssignmentPattern(pattern: TSESTree.AssignmentPattern): void {
    this.#assignments.push(pattern);
    this.visit(pattern.left);
    this.rightHandNodes.push(pattern.right);
    this.#assignments.pop();
  }
  • Parameters:
  • pattern: TSESTree.AssignmentPattern
  • Return Type: void
  • Calls:
  • this.#assignments.push
  • this.visit
  • this.rightHandNodes.push
  • this.#assignments.pop

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

Code
protected CallExpression(node: TSESTree.CallExpression): void {
    // arguments are right hand nodes.
    node.arguments.forEach(a => {
      this.rightHandNodes.push(a);
    });
    this.visit(node.callee);
  }
  • Parameters:
  • node: TSESTree.CallExpression
  • Return Type: void
  • Calls:
  • node.arguments.forEach
  • this.rightHandNodes.push
  • this.visit
  • Internal Comments:
    // arguments are right hand nodes. (x5)
    

PatternVisitor.Decorator(): void

Code
protected Decorator(): void {
    // don't visit any decorators when exploring a pattern
  }
  • Return Type: void

PatternVisitor.Identifier(pattern: TSESTree.Identifier): void

Code
protected Identifier(pattern: TSESTree.Identifier): void {
    const lastRestElement = this.#restElements.at(-1);

    this.#callback(pattern, {
      assignments: this.#assignments,
      rest: lastRestElement?.argument === pattern,
      topLevel: pattern === this.#rootPattern,
    });
  }
  • Parameters:
  • pattern: TSESTree.Identifier
  • Return Type: void
  • Calls:
  • this.#restElements.at
  • this.#callback

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

Code
protected MemberExpression(node: TSESTree.MemberExpression): void {
    // Computed property's key is a right hand node.
    if (node.computed) {
      this.rightHandNodes.push(node.property);
    }

    // the object is only read, write to its property.
    this.rightHandNodes.push(node.object);
  }
  • Parameters:
  • node: TSESTree.MemberExpression
  • Return Type: void
  • Calls:
  • this.rightHandNodes.push
  • Internal Comments:
    // Computed property's key is a right hand node.
    // the object is only read, write to its property. (x5)
    

PatternVisitor.Property(property: TSESTree.Property): void

Code
protected Property(property: TSESTree.Property): void {
    // Computed property's key is a right hand node.
    if (property.computed) {
      this.rightHandNodes.push(property.key);
    }

    // If it's shorthand, its key is same as its value.
    // If it's shorthand and has its default value, its key is same as its value.left (the value is AssignmentPattern).
    // If it's not shorthand, the name of new variable is its value's.
    this.visit(property.value);
  }
  • Parameters:
  • property: TSESTree.Property
  • Return Type: void
  • Calls:
  • this.rightHandNodes.push
  • this.visit
  • Internal Comments:
    // Computed property's key is a right hand node.
    // If it's shorthand, its key is same as its value. (x4)
    // If it's shorthand and has its default value, its key is same as its value.left (the value is AssignmentPattern). (x4)
    // If it's not shorthand, the name of new variable is its value's. (x4)
    

PatternVisitor.RestElement(pattern: TSESTree.RestElement): void

Code
protected RestElement(pattern: TSESTree.RestElement): void {
    this.#restElements.push(pattern);
    this.visit(pattern.argument);
    this.#restElements.pop();
  }
  • Parameters:
  • pattern: TSESTree.RestElement
  • Return Type: void
  • Calls:
  • this.#restElements.push
  • this.visit
  • this.#restElements.pop

PatternVisitor.SpreadElement(node: TSESTree.SpreadElement): void

Code
protected SpreadElement(node: TSESTree.SpreadElement): void {
    this.visit(node.argument);
  }
  • Parameters:
  • node: TSESTree.SpreadElement
  • Return Type: void
  • Calls:
  • this.visit

PatternVisitor.TSTypeAnnotation(): void

Code
protected TSTypeAnnotation(): void {
    // we don't want to visit types
  }
  • Return Type: void

Classes

PatternVisitor

Class Code
export class PatternVisitor extends VisitorBase {
  readonly #assignments: (
    | TSESTree.AssignmentExpression
    | TSESTree.AssignmentPattern
  )[] = [];
  readonly #callback: PatternVisitorCallback;
  readonly #restElements: TSESTree.RestElement[] = [];
  readonly #rootPattern: TSESTree.Node;

  public readonly rightHandNodes: TSESTree.Node[] = [];

  constructor(
    options: PatternVisitorOptions,
    rootPattern: TSESTree.Node,
    callback: PatternVisitorCallback,
  ) {
    super(options);
    this.#rootPattern = rootPattern;
    this.#callback = callback;
  }

  public static isPattern(
    node: TSESTree.Node,
  ): node is
    | TSESTree.ArrayPattern
    | TSESTree.AssignmentPattern
    | TSESTree.Identifier
    | TSESTree.ObjectPattern
    | TSESTree.RestElement
    | TSESTree.SpreadElement {
    const nodeType = node.type;

    return (
      nodeType === AST_NODE_TYPES.Identifier ||
      nodeType === AST_NODE_TYPES.ObjectPattern ||
      nodeType === AST_NODE_TYPES.ArrayPattern ||
      nodeType === AST_NODE_TYPES.SpreadElement ||
      nodeType === AST_NODE_TYPES.RestElement ||
      nodeType === AST_NODE_TYPES.AssignmentPattern
    );
  }

  protected ArrayExpression(node: TSESTree.ArrayExpression): void {
    node.elements.forEach(this.visit, this);
  }

  protected ArrayPattern(pattern: TSESTree.ArrayPattern): void {
    for (const element of pattern.elements) {
      this.visit(element);
    }
  }

  protected AssignmentExpression(node: TSESTree.AssignmentExpression): void {
    this.#assignments.push(node);
    this.visit(node.left);
    this.rightHandNodes.push(node.right);
    this.#assignments.pop();
  }

  protected AssignmentPattern(pattern: TSESTree.AssignmentPattern): void {
    this.#assignments.push(pattern);
    this.visit(pattern.left);
    this.rightHandNodes.push(pattern.right);
    this.#assignments.pop();
  }

  protected CallExpression(node: TSESTree.CallExpression): void {
    // arguments are right hand nodes.
    node.arguments.forEach(a => {
      this.rightHandNodes.push(a);
    });
    this.visit(node.callee);
  }

  protected Decorator(): void {
    // don't visit any decorators when exploring a pattern
  }

  protected Identifier(pattern: TSESTree.Identifier): void {
    const lastRestElement = this.#restElements.at(-1);

    this.#callback(pattern, {
      assignments: this.#assignments,
      rest: lastRestElement?.argument === pattern,
      topLevel: pattern === this.#rootPattern,
    });
  }

  protected MemberExpression(node: TSESTree.MemberExpression): void {
    // Computed property's key is a right hand node.
    if (node.computed) {
      this.rightHandNodes.push(node.property);
    }

    // the object is only read, write to its property.
    this.rightHandNodes.push(node.object);
  }

  protected Property(property: TSESTree.Property): void {
    // Computed property's key is a right hand node.
    if (property.computed) {
      this.rightHandNodes.push(property.key);
    }

    // If it's shorthand, its key is same as its value.
    // If it's shorthand and has its default value, its key is same as its value.left (the value is AssignmentPattern).
    // If it's not shorthand, the name of new variable is its value's.
    this.visit(property.value);
  }

  protected RestElement(pattern: TSESTree.RestElement): void {
    this.#restElements.push(pattern);
    this.visit(pattern.argument);
    this.#restElements.pop();
  }

  protected SpreadElement(node: TSESTree.SpreadElement): void {
    this.visit(node.argument);
  }

  protected TSTypeAnnotation(): void {
    // we don't want to visit types
  }
}

Methods

`isPattern(node: TSESTree.Node): node is
| TSESTree.ArrayPattern
| TSESTree.AssignmentPattern
| TSESTree.Identifier
| TSESTree.ObjectPattern
| TSESTree.RestElement
| TSESTree.SpreadElement`
Code
public static isPattern(
    node: TSESTree.Node,
  ): node is
    | TSESTree.ArrayPattern
    | TSESTree.AssignmentPattern
    | TSESTree.Identifier
    | TSESTree.ObjectPattern
    | TSESTree.RestElement
    | TSESTree.SpreadElement {
    const nodeType = node.type;

    return (
      nodeType === AST_NODE_TYPES.Identifier ||
      nodeType === AST_NODE_TYPES.ObjectPattern ||
      nodeType === AST_NODE_TYPES.ArrayPattern ||
      nodeType === AST_NODE_TYPES.SpreadElement ||
      nodeType === AST_NODE_TYPES.RestElement ||
      nodeType === AST_NODE_TYPES.AssignmentPattern
    );
  }
ArrayExpression(node: TSESTree.ArrayExpression): void
Code
protected ArrayExpression(node: TSESTree.ArrayExpression): void {
    node.elements.forEach(this.visit, this);
  }
ArrayPattern(pattern: TSESTree.ArrayPattern): void
Code
protected ArrayPattern(pattern: TSESTree.ArrayPattern): void {
    for (const element of pattern.elements) {
      this.visit(element);
    }
  }
AssignmentExpression(node: TSESTree.AssignmentExpression): void
Code
protected AssignmentExpression(node: TSESTree.AssignmentExpression): void {
    this.#assignments.push(node);
    this.visit(node.left);
    this.rightHandNodes.push(node.right);
    this.#assignments.pop();
  }
AssignmentPattern(pattern: TSESTree.AssignmentPattern): void
Code
protected AssignmentPattern(pattern: TSESTree.AssignmentPattern): void {
    this.#assignments.push(pattern);
    this.visit(pattern.left);
    this.rightHandNodes.push(pattern.right);
    this.#assignments.pop();
  }
CallExpression(node: TSESTree.CallExpression): void
Code
protected CallExpression(node: TSESTree.CallExpression): void {
    // arguments are right hand nodes.
    node.arguments.forEach(a => {
      this.rightHandNodes.push(a);
    });
    this.visit(node.callee);
  }
Decorator(): void
Code
protected Decorator(): void {
    // don't visit any decorators when exploring a pattern
  }
Identifier(pattern: TSESTree.Identifier): void
Code
protected Identifier(pattern: TSESTree.Identifier): void {
    const lastRestElement = this.#restElements.at(-1);

    this.#callback(pattern, {
      assignments: this.#assignments,
      rest: lastRestElement?.argument === pattern,
      topLevel: pattern === this.#rootPattern,
    });
  }
MemberExpression(node: TSESTree.MemberExpression): void
Code
protected MemberExpression(node: TSESTree.MemberExpression): void {
    // Computed property's key is a right hand node.
    if (node.computed) {
      this.rightHandNodes.push(node.property);
    }

    // the object is only read, write to its property.
    this.rightHandNodes.push(node.object);
  }
Property(property: TSESTree.Property): void
Code
protected Property(property: TSESTree.Property): void {
    // Computed property's key is a right hand node.
    if (property.computed) {
      this.rightHandNodes.push(property.key);
    }

    // If it's shorthand, its key is same as its value.
    // If it's shorthand and has its default value, its key is same as its value.left (the value is AssignmentPattern).
    // If it's not shorthand, the name of new variable is its value's.
    this.visit(property.value);
  }
RestElement(pattern: TSESTree.RestElement): void
Code
protected RestElement(pattern: TSESTree.RestElement): void {
    this.#restElements.push(pattern);
    this.visit(pattern.argument);
    this.#restElements.pop();
  }
SpreadElement(node: TSESTree.SpreadElement): void
Code
protected SpreadElement(node: TSESTree.SpreadElement): void {
    this.visit(node.argument);
  }
TSTypeAnnotation(): void
Code
protected TSTypeAnnotation(): void {
    // we don't want to visit types
  }

Type Aliases

PatternVisitorCallback

type PatternVisitorCallback = (
  pattern: TSESTree.Identifier,
  info: {
    assignments: (TSESTree.AssignmentExpression | TSESTree.AssignmentPattern)[];
    rest: boolean;
    topLevel: boolean;
  },
) => void;

PatternVisitorOptions

type PatternVisitorOptions = VisitorOptions;