or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

index.mddocs/

Babel Plugin Undeclared Variables Check

This Babel plugin provides compile-time validation for JavaScript code by detecting references to undeclared variables and throwing detailed error messages with helpful suggestions. It analyzes the abstract syntax tree during Babel's transformation process and throws ReferenceErrors with code frames pointing to undeclared variables, helping developers catch typos and missing declarations early in the build process.

Package Information

  • Package Name: babel-plugin-undeclared-variables-check
  • Package Type: npm (Babel plugin)
  • Language: JavaScript (ES6 modules)
  • Installation: npm install --save-dev babel-plugin-undeclared-variables-check

Core Imports

This is a Babel plugin that is configured rather than imported directly in code:

.babelrc

{
  "plugins": ["undeclared-variables-check"]
}

For programmatic usage:

const babel = require("babel-core");

babel.transform(code, {
  plugins: ["undeclared-variables-check"]
});

Basic Usage

The plugin automatically detects undeclared variables during compilation and throws helpful errors:

Input Code:

function calculateTotal(price, tax) {
  return price + tex; // typo: 'tex' instead of 'tax'
}

Plugin Output:

ReferenceError: Line 2: Reference to undeclared variable "tex" - did you mean "tax"?
  1 | function calculateTotal(price, tax) {
> 2 |   return price + tex;
    |                  ^
  3 | }

Configuration

Via .babelrc (Recommended)

{
  "plugins": ["undeclared-variables-check"]
}

Via CLI

babel --plugins undeclared-variables-check script.js

Via Node API

require("babel-core").transform(code, {
  plugins: ["undeclared-variables-check"]
});

Capabilities

Plugin Factory Function

The main export is a plugin factory function that creates a Babel plugin instance.

/**
 * Creates a Babel plugin for detecting undeclared variables
 * @param {Object} options - Babel plugin options
 * @param {Messages} options.messages - Babel message localization object
 * @returns {BabelPlugin} Babel plugin object with visitor pattern
 */
function pluginFactory({ messages }): BabelPlugin;

Plugin Visitor

The plugin implements the Babel visitor pattern to process AST nodes.

interface BabelPlugin {
  visitor: {
    ReferencedIdentifier(path: NodePath): void;
  };
}

Visitor Method Implementation

Processes each referenced identifier to check for undeclared variables.

/**
 * Babel AST visitor method that processes ReferencedIdentifier nodes
 * @param {Object} path - Babel AST path object
 * @param {Object} path.node - The AST node being visited
 * @param {Object} path.scope - Scope information for the current context
 * @throws {ReferenceError} When undeclared variable is found
 */
ReferencedIdentifier(path: {
  node: { name: string },
  scope: BabelScope,
  buildCodeFrameError: (message: string, ErrorType: Function) => Error,
  parentPath: { isFlow(): boolean }
}): void;

Error Handling

The plugin throws ReferenceError exceptions with detailed code frames in these cases:

Undeclared Variables

When a variable is referenced but not declared in any accessible scope:

// Input
function test() {
  return undeclaredVar; // throws ReferenceError
}

// Error: ReferenceError: Reference to undeclared variable "undeclaredVar"

Undeclared Variables with Suggestions

When a similar variable name exists (Levenshtein distance ≤ 3):

// Input  
function test() {
  const userName = "john";
  return username; // typo: lowercase 'n'
}

// Error: ReferenceError: Reference to undeclared variable "username" - did you mean "userName"?

Type Bindings Outside Flow Context

When Flow type bindings are used outside type annotations:

// Input (with Flow)
type MyType = string;
const value: MyType = "test"; // correct usage
const invalid = MyType; // incorrect - throws undeclaredVariableType error

// Error: ReferenceError: Reference to undeclared variable type "MyType"

Algorithm Details

Variable Suggestion Logic

The plugin uses the Levenshtein distance algorithm (via the leven package) to suggest corrections:

  1. Distance Calculation: Computes edit distance between undeclared variable and all bindings in scope
  2. Filter Candidates: Only considers variables with distance > 0 and ≤ 3
  3. Select Best Match: Chooses the last variable encountered with distance greater than current shortest (effectively the largest valid distance)
  4. Generate Message: Creates error message with or without suggestion

Scope Analysis

The plugin analyzes variable scope using Babel's scope system:

  • Binding Check: Uses scope.hasBinding() to verify variable declaration
  • Type Binding Check: Uses binding.kind === "type" to identify Flow types
  • Context Check: Uses path.parentPath.isFlow() to verify Flow annotation context
  • All Bindings: Uses scope.getAllBindings() to get suggestion candidates

Message Keys

The plugin uses specific message keys from Babel's message system:

/**
 * Message keys used by the plugin for error reporting
 */
interface PluginMessageKeys {
  /** "Reference to undeclared variable $1" */
  undeclaredVariable: string;
  /** "Referencing a type alias outside of a type annotation" */
  undeclaredVariableType: string;
  /** "Reference to undeclared variable $1 - did you mean $2?" */
  undeclaredVariableSuggestion: string;
}

Dependencies

External Dependencies

/**
 * Levenshtein distance calculation for variable name suggestions
 * @param {string} a - First string
 * @param {string} b - Second string  
 * @returns {number} Edit distance between strings
 */
import leven from "leven";

Package: leven@^1.0.2
Purpose: Calculate string similarity for generating variable name suggestions
Usage: leven(undeclaredVar, candidateVar) returns edit distance

Babel Dependencies

The plugin integrates with Babel's message system for localized error reporting:

/**
 * Example usage of Babel's message system within the plugin
 */
const errorMessage = messages.get("undeclaredVariable", variableName);
const suggestionMessage = messages.get("undeclaredVariableSuggestion", variableName, suggestion);
const typeMessage = messages.get("undeclaredVariableType", variableName);

Types

Babel Types

interface BabelScope {
  /**
   * Check if a variable name has a binding in current or parent scopes
   * @param {string} name - Variable name to check
   * @returns {boolean} True if binding exists
   */
  hasBinding(name: string): boolean;
  
  /**
   * Get binding information for a variable name
   * @param {string} name - Variable name
   * @returns {Binding|undefined} Binding object or undefined if not found
   */
  getBinding(name: string): Binding | undefined;
  
  /**
   * Get all variable bindings in current scope
   * @returns {Object} Object with variable names as keys
   */
  getAllBindings(): Record<string, Binding>;
}

interface Binding {
  /** Type of binding: "var", "let", "const", "param", "type", etc. */
  kind: string;
}

interface Messages {
  /**
   * Get localized message with placeholder substitution
   * @param {string} key - Message key
   * @param {...any} args - Arguments to substitute in message placeholders
   * @returns {string} Formatted message string
   */
  get(key: string, ...args: any[]): string;
}

interface NodePath {
  /** AST node being visited */
  node: { name: string };
  /** Scope information for current context */
  scope: BabelScope;
  /** Parent path for context checking */
  parentPath: { isFlow(): boolean };
  /** Build error with code frame */
  buildCodeFrameError(message: string, ErrorType: Function): Error;
}

Build Integration

This plugin is designed for development workflows and should be included in development builds only:

{
  "env": {
    "development": {
      "plugins": ["undeclared-variables-check"]
    }
  }
}

The plugin helps catch errors early in the development cycle, preventing runtime ReferenceError exceptions from reaching production code.