Skip to content

axetroy/eslint-utils

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

50 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

@axetroy/eslint-utils

A comprehensive utility library for developing ESLint plugins. This package provides a collection of helper functions for AST manipulation, node checking, code fixing, and TypeScript annotation handling.

Installation

npm install @axetroy/eslint-utils

Features

  • Checker Utilities: Functions to check and validate AST nodes
  • Fixer Utilities: Functions to fix and transform code
  • AST Utilities: Functions to work with Abstract Syntax Trees
  • Annotation Utilities: Functions to handle TypeScript annotations

API Reference

Checker Utilities

isFunctionCall(node, target, options?)

Check if a node is a function call with the given target name.

Parameters:

  • node (Node): The AST node to check
  • target (string): The function name or member expression (e.g., 'foo', 'bar.foo', '*.foo')
  • options (object, optional):
    • argCount (number): Exact number of arguments
    • minArgCount (number): Minimum number of arguments
    • maxArgCount (number): Maximum number of arguments

Returns: boolean

Examples:

import { isFunctionCall } from '@axetroy/eslint-utils';

isFunctionCall(node, 'foo', { argCount: 2 }) // true if node is `foo(1, 2)`
isFunctionCall(node, 'bar.foo') // true if node is `bar.foo()`
isFunctionCall(node, 'foo', { minArgCount: 2 }) // true if node is `foo(1, 2, 3)`
isFunctionCall(node, 'foo', { maxArgCount: 2 }) // true if node is `foo(1)` or `foo(1, 2)`
isFunctionCall(node, '*.foo') // true if node is `bar.foo()` or `baz.foo()`

isInControlFlow(node)

Determine whether a node is in a control flow position (if, while, for, switch, etc.).

Parameters:

  • node (Node): The AST node to check

Returns: boolean

Example:

import { isInControlFlow } from '@axetroy/eslint-utils';

// Returns true for nodes in positions like:
// if (node) { ... }
// while (node) { ... }
// for (; node; ) { ... }

isNodeEqual(node1, node2)

Compare two AST nodes for equality by structure and value. Ignores location properties (loc, start, end, parent, range).

Parameters:

  • node1 (Node): The first AST node
  • node2 (Node): The second AST node

Returns: boolean

Example:

import { isNodeEqual } from '@axetroy/eslint-utils';

const node1 = { type: 'Identifier', name: 'foo' };
const node2 = { type: 'Identifier', name: 'foo' };
isNodeEqual(node1, node2); // true

isLiteral(node)

Check if a node is a literal value or literal constructor call.

Parameters:

  • node (Node): The AST node to check

Returns: boolean

Example:

import { isLiteral } from '@axetroy/eslint-utils';

// Returns true for:
// - Literal nodes: 'string', 123, true
// - Constructor calls: Boolean(true), String('text'), Number(42)
// - New expressions: new Boolean(true), new String('text')

isBooleanExpression(sourceCode, node, depth?)

Determine whether a node is a Boolean expression.

Parameters:

  • sourceCode (SourceCode): The ESLint source code object
  • node (Expression): The AST node to check
  • depth (number, optional): Maximum recursion depth (default: 0, max: 10)

Returns: boolean

Example:

import { isBooleanExpression } from '@axetroy/eslint-utils';

// Returns true for:
// - Boolean literals: true, false
// - Boolean expressions: age > 18, !flag, a && b
// - Boolean functions: Boolean(), Array.isArray()

isBooleanExpressionFunction(sourceCode, node)

Determine whether a function returns a Boolean value.

Parameters:

  • sourceCode (SourceCode): The ESLint source code object
  • node (Function): The function node to check

Returns: boolean

Fixer Utilities

replaceText(fixer, sourceCode, node, text)

Replace the text of a given node with new text. Handles special cases for await and yield expressions.

Parameters:

  • fixer (RuleFixer): The ESLint rule fixer
  • sourceCode (SourceCode): The ESLint source code object
  • node (Node): The node to replace
  • text (string): The replacement text

Returns: Generator

Example:

import { replaceText } from '@axetroy/eslint-utils';

context.report({
  node,
  message: 'Replace with true',
  *fix(fixer) {
    yield* replaceText(fixer, sourceCode, node, 'true');
  }
});

replaceVariableName(fixer, sourceCode, scope, identifier, variableName)

Replace a variable name and all its references. Handles exports, shorthand properties, and type annotations.

Parameters:

  • fixer (RuleFixer): The ESLint rule fixer
  • sourceCode (SourceCode): The ESLint source code object
  • scope (Scope): The scope containing the variable
  • identifier (Identifier): The identifier node to rename
  • variableName (string): The new variable name

Returns: Generator

Example:

import { replaceVariableName } from '@axetroy/eslint-utils';

context.report({
  node,
  message: 'Rename variable to newName',
  *fix(fixer) {
    yield* replaceVariableName(fixer, sourceCode, scope, identifier, 'newName');
  }
});

insertImportDeclaration(fixer, sourceCode, specifier, source)

Insert or update an import declaration.

Parameters:

  • fixer (RuleFixer): The ESLint rule fixer
  • sourceCode (SourceCode): The ESLint source code object
  • specifier (object):
    • default (string, optional): Default import name
    • namespaces (string[], optional): Named imports
  • source (string): The module source

Returns: Generator

Example:

import { insertImportDeclaration } from '@axetroy/eslint-utils';

context.report({
  node,
  message: 'Add missing import',
  *fix(fixer) {
    yield* insertImportDeclaration(
      fixer,
      sourceCode,
      { default: 'React', namespaces: ['useState', 'useEffect'] },
      'react'
    );
  }
});

AST Utilities

getText(sourceCode, node)

Get the text of a node. Handles special cases like SequenceExpression.

Parameters:

  • sourceCode (SourceCode): The ESLint source code object
  • node (Node): The AST node

Returns: string

Example:

import { getText } from '@axetroy/eslint-utils';

const text = getText(sourceCode, node);
console.log(text); // "foo(bar, baz)"

Annotation Utilities

isBooleanAnnotation(annotation)

Check if a TypeScript annotation is a Boolean type.

Parameters:

  • annotation (Node): The type annotation node

Returns: boolean

Example:

import { isBooleanAnnotation } from '@axetroy/eslint-utils';

// Returns true for TypeScript types:
// - boolean
// - Boolean
// Supports both @typescript-eslint/parser and babel-eslint9

Usage Example

Here's a complete example of an ESLint rule using these utilities:

import {
  isFunctionCall,
  isBooleanExpression,
  replaceText,
  getText
} from '@axetroy/eslint-utils';

module.exports = {
  meta: {
    type: 'suggestion',
    fixable: 'code',
  },
  create(context) {
    const sourceCode = context.getSourceCode();

    return {
      CallExpression(node) {
        if (isFunctionCall(node, 'Boolean', { argCount: 1 })) {
          const arg = node.arguments[0];
          
          if (isBooleanExpression(sourceCode, arg)) {
            context.report({
              node,
              message: 'Unnecessary Boolean() call',
              *fix(fixer) {
                const text = getText(sourceCode, arg);
                yield* replaceText(fixer, sourceCode, node, text);
              }
            });
          }
        }
      }
    };
  }
};

TypeScript Support

This package includes TypeScript definitions for all exported functions.

import type { Node } from 'estree';
import type { SourceCode, Rule, Scope } from 'eslint';
import { isFunctionCall, replaceVariableName } from '@axetroy/eslint-utils';

License

The Anti-996 License

About

A set of eslint tools for developing eslint plugins

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors