CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-eslint-utils

Utilities for ESLint plugins providing AST manipulation, static analysis, and rule development helpers.

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

reference-tracking.mddocs/

Reference Tracking

Sophisticated system for tracking variable and module references across different import/export patterns. The ReferenceTracker class enables ESLint rules to understand cross-module dependencies and trace variable usage through complex import/export scenarios.

Capabilities

Reference Tracker Class

Core class for tracking references across modules and scopes.

/**
 * The reference tracker for tracking variable references across modules
 * @param globalScope - The global scope to start tracking from
 * @param options - Optional configuration for tracking behavior
 */
class ReferenceTracker {
  constructor(globalScope: Scope, options?: ReferenceTrackerOptions);
  
  /**
   * Iterate the references of global variables
   * @param traceMap - Map defining what to track
   * @returns Iterator of reference results
   */
  iterateGlobalReferences(traceMap: TraceMap): IterableIterator<ReferenceResult>;
  
  /**
   * Iterate the references of CommonJS modules
   * @param traceMap - Map defining what to track
   * @returns Iterator of reference results
   */
  iterateCjsReferences(traceMap: TraceMap): IterableIterator<ReferenceResult>;
  
  /**
   * Iterate the references of ES modules
   * @param traceMap - Map defining what to track
   * @returns Iterator of reference results
   */
  iterateEsmReferences(traceMap: TraceMap): IterableIterator<ReferenceResult>;
}

interface ReferenceTrackerOptions {
  mode?: "legacy" | "strict";
  globalObjectNames?: string[];
}

interface ReferenceResult {
  node: Node;
  path: string[];
  type: symbol;
  info: any;
}

interface TraceMap {
  [key: string]: {
    [READ]?: any;
    [CALL]?: any;
    [CONSTRUCT]?: any;
    [key: string]: TraceMap | any;
  };
}

Reference Type Constants

Symbols used to specify what types of references to track.

/**
 * Symbol representing read access tracking
 */
const READ: symbol;

/**
 * Symbol representing function call tracking  
 */
const CALL: symbol;

/**
 * Symbol representing constructor call tracking
 */
const CONSTRUCT: symbol;

/**
 * Symbol representing ECMAScript module tracking
 */
const ESM: symbol;

Static Properties:

ReferenceTracker class also provides these constants as static properties:

/**
 * Static property for read access tracking
 */
static READ: symbol;

/**
 * Static property for function call tracking
 */
static CALL: symbol;

/**
 * Static property for constructor call tracking
 */
static CONSTRUCT: symbol;

/**
 * Static property for ECMAScript module tracking
 */
static ESM: symbol;

Static Access:

// Available as static properties
ReferenceTracker.READ
ReferenceTracker.CALL
ReferenceTracker.CONSTRUCT
ReferenceTracker.ESM

Usage Examples

Basic Global Reference Tracking

Track usage of global variables and objects.

import { ReferenceTracker, READ, CALL } from "eslint-utils";

create(context) {
  return {
    Program() {
      const scope = context.getScope();
      const tracker = new ReferenceTracker(scope);
      
      const traceMap = {
        console: {
          [READ]: true,
          log: { [CALL]: true },
          warn: { [CALL]: true },
          error: { [CALL]: true }
        },
        setTimeout: { [CALL]: true },
        setInterval: { [CALL]: true }
      };
      
      for (const { node, path, type } of tracker.iterateGlobalReferences(traceMap)) {
        if (type === READ) {
          context.report(node, `Reading global: ${path.join('.')}`);
        } else if (type === CALL) {
          context.report(node, `Calling global: ${path.join('.')}`);
        }
      }
    }
  };
}

CommonJS Module Tracking

Track CommonJS require() calls and their usage.

import { ReferenceTracker, READ, CALL, CONSTRUCT } from "eslint-utils";

create(context) {
  return {
    Program() {
      const scope = context.getScope();
      const tracker = new ReferenceTracker(scope);
      
      const traceMap = {
        "lodash": {
          [READ]: true,
          map: { [CALL]: true },
          filter: { [CALL]: true },
          reduce: { [CALL]: true }
        },
        "express": {
          [CALL]: true,  // express()
          Router: { [CONSTRUCT]: true }  // new express.Router()
        },
        "fs": {
          readFile: { [CALL]: true },
          writeFile: { [CALL]: true }
        }
      };
      
      for (const { node, path, type } of tracker.iterateCjsReferences(traceMap)) {
        if (path[0] === "lodash" && type === CALL) {
          context.report(node, `Using lodash.${path.slice(1).join('.')}`);
        } else if (path[0] === "fs") {
          context.report(node, `File system operation: ${path.join('.')}`);
        }
      }
    }
  };
}

ES Module Tracking

Track ES6 import statements and their usage.

import { ReferenceTracker, READ, CALL, ESM } from "eslint-utils";

create(context) {
  return {
    Program() {
      const scope = context.getScope();
      const tracker = new ReferenceTracker(scope);
      
      const traceMap = {
        "react": {
          [ESM]: true,  // Mark as ES module
          createElement: { [CALL]: true },
          useState: { [CALL]: true },
          useEffect: { [CALL]: true },
          Component: { [READ]: true }
        },
        "vue": {
          [ESM]: true,
          createApp: { [CALL]: true },
          ref: { [CALL]: true },
          computed: { [CALL]: true }
        }
      };
      
      for (const { node, path, type } of tracker.iterateEsmReferences(traceMap)) {
        if (path[0] === "react" && path[1] === "useState" && type === CALL) {
          context.report(node, "useState hook detected");
        } else if (path[0] === "vue" && type === CALL) {
          context.report(node, `Vue composition API: ${path.slice(1).join('.')}`);
        }
      }
    }
  };
}

Advanced Trace Maps

Complex trace maps with nested structures.

import { ReferenceTracker, READ, CALL, CONSTRUCT } from "eslint-utils";

create(context) {
  return {
    Program() {
      const scope = context.getScope();
      const tracker = new ReferenceTracker(scope, {
        mode: "strict",
        globalObjectNames: ["window", "global", "globalThis"]
      });
      
      const traceMap = {
        "axios": {
          [CALL]: { info: "axios direct call" },
          get: { [CALL]: { info: "axios.get" } },
          post: { [CALL]: { info: "axios.post" } },
          create: { 
            [CALL]: { info: "axios.create" },
            // Track methods on axios instances
            "*": {
              get: { [CALL]: { info: "instance.get" } },
              post: { [CALL]: { info: "instance.post" } }
            }
          }
        },
        "jquery": {
          [CALL]: { info: "jQuery function" },
          [READ]: { info: "jQuery object" },
          ajax: { [CALL]: { info: "jQuery.ajax" } },
          fn: {
            [READ]: { info: "jQuery.fn" },
            extend: { [CALL]: { info: "jQuery.fn.extend" } }
          }
        }
      };
      
      // Track CommonJS requires
      for (const { node, path, type, info } of tracker.iterateCjsReferences(traceMap)) {
        context.report({
          node,
          message: `${info}: ${path.join('.')} (${type.toString()})`
        });
      }
      
      // Track ES module imports
      for (const { node, path, type, info } of tracker.iterateEsmReferences(traceMap)) {
        context.report({
          node,
          message: `ES Module ${info}: ${path.join('.')}`
        });
      }
    }
  };
}

Tracking Destructured Imports

Handle destructuring patterns in imports.

import { ReferenceTracker, READ, CALL } from "eslint-utils";

create(context) {
  return {
    Program() {
      const scope = context.getScope();
      const tracker = new ReferenceTracker(scope);
      
      // This will track:
      // const { readFile, writeFile } = require('fs');
      // import { useState, useEffect } from 'react';
      const traceMap = {
        "fs": {
          readFile: { [CALL]: true },
          writeFile: { [CALL]: true },
          promises: {
            readFile: { [CALL]: true },
            writeFile: { [CALL]: true }
          }
        },
        "react": {
          [ESM]: true,
          useState: { [CALL]: true },
          useEffect: { [CALL]: true },
          useMemo: { [CALL]: true }
        }
      };
      
      for (const { node, path, type } of tracker.iterateCjsReferences(traceMap)) {
        if (path.length > 1 && type === CALL) {
          context.report(node, `Destructured call: ${path.join('.')}`);
        }
      }
      
      for (const { node, path, type } of tracker.iterateEsmReferences(traceMap)) {
        if (path[0] === "react" && type === CALL) {
          context.report(node, `React hook: ${path[1]}`);
        }
      }
    }
  };
}

Configuration Options

Mode Setting

Control how the tracker handles import declarations:

  • "strict": Only track explicit default imports for CJS modules
  • "legacy": Track both default and named imports for CJS modules
const tracker = new ReferenceTracker(scope, { mode: "legacy" });

Global Object Names

Customize which global object names to consider:

const tracker = new ReferenceTracker(scope, {
  globalObjectNames: ["window", "global", "globalThis", "self"]
});

Common Patterns

Library Deprecation Warnings

const traceMap = {
  "deprecated-lib": {
    [READ]: { deprecated: true },
    "*": { [CALL]: { deprecated: true } }
  }
};

for (const { node, info } of tracker.iterateCjsReferences(traceMap)) {
  if (info.deprecated) {
    context.report(node, "This library is deprecated");
  }
}

Security Auditing

const traceMap = {
  "eval": { [CALL]: { security: "dangerous" } },
  "child_process": {
    exec: { [CALL]: { security: "review-required" } },
    spawn: { [CALL]: { security: "review-required" } }
  }
};

Performance Monitoring

const traceMap = {
  "heavy-library": {
    [READ]: { performance: "expensive" },
    heavyOperation: { [CALL]: { performance: "very-expensive" } }
  }
};

docs

ast-utils.md

index.md

pattern-matching.md

reference-tracking.md

static-analysis.md

token-predicates.md

tile.json