@eslint/v8-to-v9-custom-rules
Automatically migrate your custom ESLint rules from v8 to v9 format.
Overview
This codemod transforms your custom ESLint rules to be compatible with ESLint v9. It handles all breaking changes in the custom rule API, including context method removals, new rule structure requirements, and deprecated APIs.
Supported export styles:
- CommonJS:
module.exports = function(context) { ... } - ES Modules:
export default function(context) { ... }
What This Codemod Does
This codemod performs a comprehensive migration of custom ESLint rules from v8 to v9. It handles the following breaking changes from the official ESLint v9 migration guide:
- ✅ Removed multiple
contextmethods - migrates tosourceCodeequivalents - ✅ Removed
context.getComments()- converts to combination ofgetCommentsBefore/Inside/After - ✅ Removed
CodePath#currentSegments- adds code path tracking logic - ✅ Function-style rules are no longer supported - converts to object format with
metaandcreate - ✅ Removed
sourceCode.getComments()- converts togetCommentsBefore/Inside/Aftercombinations - ✅
FlatRuleTester→RuleTester- renames imports/usages and movesparserOptionstolanguageOptionsin tests - ✅
FlatESLint→ESLintandLinter#verifyflat config - updates integration API usage
Detailed Transformations:
Custom Rule Migration
Transforms your custom ESLint rules to the new format:
CommonJS:
javascript
ES Modules:
javascript
- Converts old function-based rule exports to the new object format with
metaandcreateproperties - Updates
contextmethod calls to usecontext.sourceCode(e.g.,context.getSource()→contextSourceCode.getText()) - Migrates deprecated methods:
getSource→getTextgetSourceLines→getLinesgetComments→[...getCommentsBefore(), ...getCommentsInside(), ...getCommentsAfter()]getAncestors,getScope,markVariableAsUsed— auto-migrated with inferrednodeparameters (verify manually)
- Handles
currentSegmentsAPI changes by adding necessary code path tracking - Detects fixable rules and adds
fixable: "code"to meta
Usage
Migrate Custom Rules
Run the codemod and provide paths to your rule files or directories:
bash
Manual Steps Required
After running this codemod, you need to:
-
Review TODO comments - If your rule uses
context.options, the codemod may leave a schema placeholder:TODO Comment Action Required // TODO: Define schema - this rule uses context.optionsDefine a proper JSON schema for your rule's options -
Fix schema for rules using options - If your rule uses
context.options, you must define the schema:javascript -
Verify scope-related migrations - The codemod automatically migrates
getScope,getAncestors, andmarkVariableAsUsedwith inferrednodeparameters. It does not leave TODO comments for these. Review the output to confirm the inferrednodeis correct, especially in nested helpers or non-standard visitor signatures. Parameterless visitors such asProgram() {}get(node)injected automatically.For
getAncestors, the codemod also adds a v8 compatibility fallback:javascriptOther deprecated
contextmethods are replaced automatically as well:Removed on contextReplacement on SourceCodecontext.getAncestors()sourceCode.getAncestors(node)context.getScope()sourceCode.getScope(node)context.markVariableAsUsed(name)sourceCode.markVariableAsUsed(name, node)context.getDeclaredVariables(node)sourceCode.getDeclaredVariables(node)context.getSource(node)sourceCode.getText(node)context.getSourceLines()sourceCode.getLines()context.getAllComments()sourceCode.getAllComments()context.getComments()[...sourceCode.getCommentsBefore(), ...sourceCode.getCommentsInside(), ...sourceCode.getCommentsAfter()] -
Test your custom rules:
bash