diff --git a/.release-please-manifest.json b/.release-please-manifest.json index 351a7a484..1ebd51424 100644 --- a/.release-please-manifest.json +++ b/.release-please-manifest.json @@ -1,10 +1,10 @@ { - "packages/compat": "2.0.1", + "packages/compat": "2.0.2", "packages/config-array": "0.23.0", - "packages/config-helpers": "0.5.1", - "packages/core": "1.0.1", + "packages/config-helpers": "0.5.2", + "packages/core": "1.1.0", "packages/mcp": "0.2.0", - "packages/migrate-config": "2.0.1", + "packages/migrate-config": "2.0.2", "packages/object-schema": "3.0.0", - "packages/plugin-kit": "0.5.1" + "packages/plugin-kit": "0.6.0" } diff --git a/README.md b/README.md index bd28db4cd..34805e80d 100644 --- a/README.md +++ b/README.md @@ -33,8 +33,8 @@ to get your logo on our READMEs and [website](https://eslint.org/sponsors).

Platinum Sponsors

Automattic

Gold Sponsors

Qlty Software Shopify

Silver Sponsors

-

Vite Liftoff American Express StackBlitz

Bronze Sponsors

-

Cybozu CrawlJobs Syntax N-iX Ltd Icons8 Discord GitBook Nx HeroCoders LambdaTest

+

Vite Liftoff American Express StackBlitz

Bronze Sponsors

+

Cybozu SAP CrawlJobs Syntax N-iX Ltd Icons8 Discord GitBook Nx HeroCoders LambdaTest

Technology Sponsors

Technology sponsors allow us to use their products and services for free as part of a contribution to the open source ecosystem and our work.

Netlify Algolia 1Password

diff --git a/knip.json b/knip.json index 8b84e6971..fb248cb6d 100644 --- a/knip.json +++ b/knip.json @@ -27,7 +27,7 @@ "project": ["src/**/*.{cts,js,ts}", "tests/*.{cts,js,ts}"] }, "packages/object-schema": { - "entry": ["tests/**/*.{cts,js,ts}", "src/types.ts"], + "entry": ["tests/**/*.{cts,js,ts}"], "project": ["src/**/*.{cts,js,ts}", "tests/**/*.{cts,js,ts}"] }, "packages/plugin-kit": { diff --git a/package.json b/package.json index bada0037f..b35111c86 100644 --- a/package.json +++ b/package.json @@ -44,7 +44,7 @@ "knip": "^5.62.0", "lint-staged": "^16.0.0", "mocha": "^11.5.0", - "prettier": "^3.7.3", + "prettier": "3.8.1", "rollup": "^4.52.3", "typescript": "^5.8.3", "typescript-eslint": "^8.0.0", diff --git a/packages/compat/CHANGELOG.md b/packages/compat/CHANGELOG.md index a952d1817..b361a1ed0 100644 --- a/packages/compat/CHANGELOG.md +++ b/packages/compat/CHANGELOG.md @@ -1,5 +1,19 @@ # Changelog +## [2.0.2](https://github.com/eslint/rewrite/compare/compat-v2.0.1...compat-v2.0.2) (2026-01-29) + + +### Bug Fixes + +* add eslint 10 as peer dependency ([#361](https://github.com/eslint/rewrite/issues/361)) ([ecb37dc](https://github.com/eslint/rewrite/commit/ecb37dcafc6513649c03f245f0f2505e7eb10dd1)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @eslint/core bumped from ^1.0.1 to ^1.1.0 + ## [2.0.1](https://github.com/eslint/rewrite/compare/compat-v2.0.0...compat-v2.0.1) (2026-01-08) diff --git a/packages/compat/README.md b/packages/compat/README.md index cfddbca29..64986e26f 100644 --- a/packages/compat/README.md +++ b/packages/compat/README.md @@ -203,8 +203,8 @@ to get your logo on our READMEs and [website](https://eslint.org/sponsors).

Platinum Sponsors

Automattic

Gold Sponsors

Qlty Software Shopify

Silver Sponsors

-

Vite Liftoff American Express StackBlitz

Bronze Sponsors

-

Cybozu CrawlJobs Syntax N-iX Ltd Icons8 Discord GitBook Nx HeroCoders LambdaTest

+

Vite Liftoff American Express StackBlitz

Bronze Sponsors

+

Cybozu SAP CrawlJobs Syntax N-iX Ltd Icons8 Discord GitBook Nx HeroCoders LambdaTest

Technology Sponsors

Technology sponsors allow us to use their products and services for free as part of a contribution to the open source ecosystem and our work.

Netlify Algolia 1Password

diff --git a/packages/compat/jsr.json b/packages/compat/jsr.json index 7f2a53fa5..b4dbbc65f 100644 --- a/packages/compat/jsr.json +++ b/packages/compat/jsr.json @@ -1,6 +1,6 @@ { "name": "@eslint/compat", - "version": "2.0.1", + "version": "2.0.2", "exports": "./dist/esm/index.js", "publish": { "include": [ diff --git a/packages/compat/package.json b/packages/compat/package.json index 09893a10a..9dd1cf8b7 100644 --- a/packages/compat/package.json +++ b/packages/compat/package.json @@ -1,6 +1,6 @@ { "name": "@eslint/compat", - "version": "2.0.1", + "version": "2.0.2", "description": "Compatibility utilities for ESLint", "type": "module", "main": "dist/esm/index.js", @@ -50,14 +50,14 @@ }, "homepage": "https://github.com/eslint/rewrite/tree/main/packages/compat#readme", "dependencies": { - "@eslint/core": "^1.0.1" + "@eslint/core": "^1.1.0" }, "devDependencies": { "@types/node": "^24.7.2", "eslint": "^9.27.0" }, "peerDependencies": { - "eslint": "^8.40 || 9" + "eslint": "^8.40 || 9 || 10" }, "peerDependenciesMeta": { "eslint": { diff --git a/packages/config-array/README.md b/packages/config-array/README.md index 5603ae1e5..fb7bfeadb 100644 --- a/packages/config-array/README.md +++ b/packages/config-array/README.md @@ -360,8 +360,8 @@ to get your logo on our READMEs and [website](https://eslint.org/sponsors).

Platinum Sponsors

Automattic

Gold Sponsors

Qlty Software Shopify

Silver Sponsors

-

Vite Liftoff American Express StackBlitz

Bronze Sponsors

-

Cybozu CrawlJobs Syntax N-iX Ltd Icons8 Discord GitBook Nx HeroCoders LambdaTest

+

Vite Liftoff American Express StackBlitz

Bronze Sponsors

+

Cybozu SAP CrawlJobs Syntax N-iX Ltd Icons8 Discord GitBook Nx HeroCoders LambdaTest

Technology Sponsors

Technology sponsors allow us to use their products and services for free as part of a contribution to the open source ecosystem and our work.

Netlify Algolia 1Password

diff --git a/packages/config-helpers/CHANGELOG.md b/packages/config-helpers/CHANGELOG.md index 40f4d73d5..822afa70f 100644 --- a/packages/config-helpers/CHANGELOG.md +++ b/packages/config-helpers/CHANGELOG.md @@ -1,5 +1,14 @@ # Changelog +## [0.5.2](https://github.com/eslint/rewrite/compare/config-helpers-v0.5.1...config-helpers-v0.5.2) (2026-01-29) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @eslint/core bumped from ^1.0.1 to ^1.1.0 + ## [0.5.1](https://github.com/eslint/rewrite/compare/config-helpers-v0.5.0...config-helpers-v0.5.1) (2026-01-08) diff --git a/packages/config-helpers/README.md b/packages/config-helpers/README.md index c31eaa4fc..42edbdebd 100644 --- a/packages/config-helpers/README.md +++ b/packages/config-helpers/README.md @@ -89,8 +89,8 @@ to get your logo on our READMEs and [website](https://eslint.org/sponsors).

Platinum Sponsors

Automattic

Gold Sponsors

Qlty Software Shopify

Silver Sponsors

-

Vite Liftoff American Express StackBlitz

Bronze Sponsors

-

Cybozu CrawlJobs Syntax N-iX Ltd Icons8 Discord GitBook Nx HeroCoders LambdaTest

+

Vite Liftoff American Express StackBlitz

Bronze Sponsors

+

Cybozu SAP CrawlJobs Syntax N-iX Ltd Icons8 Discord GitBook Nx HeroCoders LambdaTest

Technology Sponsors

Technology sponsors allow us to use their products and services for free as part of a contribution to the open source ecosystem and our work.

Netlify Algolia 1Password

diff --git a/packages/config-helpers/jsr.json b/packages/config-helpers/jsr.json index 6017258b1..216e923c1 100644 --- a/packages/config-helpers/jsr.json +++ b/packages/config-helpers/jsr.json @@ -1,6 +1,6 @@ { "name": "@eslint/config-helpers", - "version": "0.5.1", + "version": "0.5.2", "exports": "./dist/esm/index.js", "publish": { "include": [ diff --git a/packages/config-helpers/package.json b/packages/config-helpers/package.json index ea8319735..9487d83f1 100644 --- a/packages/config-helpers/package.json +++ b/packages/config-helpers/package.json @@ -1,6 +1,6 @@ { "name": "@eslint/config-helpers", - "version": "0.5.1", + "version": "0.5.2", "description": "Helper utilities for creating ESLint configuration", "type": "module", "main": "dist/esm/index.js", @@ -49,7 +49,7 @@ }, "homepage": "https://github.com/eslint/rewrite/tree/main/packages/config-helpers#readme", "dependencies": { - "@eslint/core": "^1.0.1" + "@eslint/core": "^1.1.0" }, "devDependencies": { "rollup-plugin-copy": "^3.5.0" diff --git a/packages/config-helpers/tests/pnpm/pnpm-workspace.yaml b/packages/config-helpers/tests/pnpm/pnpm-workspace.yaml new file mode 100644 index 000000000..e49fded65 --- /dev/null +++ b/packages/config-helpers/tests/pnpm/pnpm-workspace.yaml @@ -0,0 +1,3 @@ +overrides: + # Prevents an ERR_PNPM_NO_MATCHING_VERSION error when @eslint/core is bumped to a yet unpublished version. + "@eslint/core": file:../../../core diff --git a/packages/core/CHANGELOG.md b/packages/core/CHANGELOG.md index 6701fd20f..e95c4d2f7 100644 --- a/packages/core/CHANGELOG.md +++ b/packages/core/CHANGELOG.md @@ -1,5 +1,12 @@ # Changelog +## [1.1.0](https://github.com/eslint/rewrite/compare/core-v1.0.1...core-v1.1.0) (2026-01-29) + + +### Features + +* Add custom rule type helpers to `@eslint/plugin-kit` ([#355](https://github.com/eslint/rewrite/issues/355)) ([8ac8530](https://github.com/eslint/rewrite/commit/8ac853046aa1d4288d06d639be234c09988ade5e)) + ## [1.0.1](https://github.com/eslint/rewrite/compare/core-v1.0.0...core-v1.0.1) (2026-01-08) diff --git a/packages/core/README.md b/packages/core/README.md index 7469d712a..496c91e4f 100644 --- a/packages/core/README.md +++ b/packages/core/README.md @@ -21,8 +21,8 @@ to get your logo on our READMEs and [website](https://eslint.org/sponsors).

Platinum Sponsors

Automattic

Gold Sponsors

Qlty Software Shopify

Silver Sponsors

-

Vite Liftoff American Express StackBlitz

Bronze Sponsors

-

Cybozu CrawlJobs Syntax N-iX Ltd Icons8 Discord GitBook Nx HeroCoders LambdaTest

+

Vite Liftoff American Express StackBlitz

Bronze Sponsors

+

Cybozu SAP CrawlJobs Syntax N-iX Ltd Icons8 Discord GitBook Nx HeroCoders LambdaTest

Technology Sponsors

Technology sponsors allow us to use their products and services for free as part of a contribution to the open source ecosystem and our work.

Netlify Algolia 1Password

diff --git a/packages/core/jsr.json b/packages/core/jsr.json index cde9d68e6..f342dd745 100644 --- a/packages/core/jsr.json +++ b/packages/core/jsr.json @@ -1,6 +1,6 @@ { "name": "@eslint/core", - "version": "1.0.1", + "version": "1.1.0", "exports": "./dist/esm/types.d.ts", "publish": { "include": [ diff --git a/packages/core/package.json b/packages/core/package.json index d473559f9..86984e2e6 100644 --- a/packages/core/package.json +++ b/packages/core/package.json @@ -1,6 +1,6 @@ { "name": "@eslint/core", - "version": "1.0.1", + "version": "1.1.0", "description": "Runtime-agnostic core of ESLint", "type": "module", "types": "./dist/esm/types.d.ts", diff --git a/packages/core/src/types.ts b/packages/core/src/types.ts index 84e198b3e..8f3f44ddf 100644 --- a/packages/core/src/types.ts +++ b/packages/core/src/types.ts @@ -602,6 +602,7 @@ export interface RuleDefinition< /** * Defaults for non-language-related `RuleDefinition` options. + * @deprecated Use the same type from `@eslint/plugin-kit` instead. */ export interface CustomRuleTypeDefinitions { RuleOptions: unknown[]; @@ -611,6 +612,7 @@ export interface CustomRuleTypeDefinitions { /** * A helper type to define language specific specializations of the `RuleDefinition` type. + * @deprecated Use the same type from `@eslint/plugin-kit` instead. * * @example * ```ts diff --git a/packages/mcp/README.md b/packages/mcp/README.md index 291b0c867..3a43924c3 100644 --- a/packages/mcp/README.md +++ b/packages/mcp/README.md @@ -35,8 +35,8 @@ to get your logo on our READMEs and [website](https://eslint.org/sponsors).

Platinum Sponsors

Automattic

Gold Sponsors

Qlty Software Shopify

Silver Sponsors

-

Vite Liftoff American Express StackBlitz

Bronze Sponsors

-

Cybozu CrawlJobs Syntax N-iX Ltd Icons8 Discord GitBook Nx HeroCoders LambdaTest

+

Vite Liftoff American Express StackBlitz

Bronze Sponsors

+

Cybozu SAP CrawlJobs Syntax N-iX Ltd Icons8 Discord GitBook Nx HeroCoders LambdaTest

Technology Sponsors

Technology sponsors allow us to use their products and services for free as part of a contribution to the open source ecosystem and our work.

Netlify Algolia 1Password

diff --git a/packages/migrate-config/CHANGELOG.md b/packages/migrate-config/CHANGELOG.md index aca15943e..fb23e747e 100644 --- a/packages/migrate-config/CHANGELOG.md +++ b/packages/migrate-config/CHANGELOG.md @@ -1,5 +1,16 @@ # Changelog +## [2.0.2](https://github.com/eslint/rewrite/compare/migrate-config-v2.0.1...migrate-config-v2.0.2) (2026-01-29) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @eslint/compat bumped from ^2.0.1 to ^2.0.2 + * devDependencies + * @eslint/core bumped from ^1.0.1 to ^1.1.0 + ## [2.0.1](https://github.com/eslint/rewrite/compare/migrate-config-v2.0.0...migrate-config-v2.0.1) (2026-01-08) diff --git a/packages/migrate-config/README.md b/packages/migrate-config/README.md index 12ca07f51..7ed6b3e54 100644 --- a/packages/migrate-config/README.md +++ b/packages/migrate-config/README.md @@ -102,8 +102,8 @@ to get your logo on our READMEs and [website](https://eslint.org/sponsors).

Platinum Sponsors

Automattic

Gold Sponsors

Qlty Software Shopify

Silver Sponsors

-

Vite Liftoff American Express StackBlitz

Bronze Sponsors

-

Cybozu CrawlJobs Syntax N-iX Ltd Icons8 Discord GitBook Nx HeroCoders LambdaTest

+

Vite Liftoff American Express StackBlitz

Bronze Sponsors

+

Cybozu SAP CrawlJobs Syntax N-iX Ltd Icons8 Discord GitBook Nx HeroCoders LambdaTest

Technology Sponsors

Technology sponsors allow us to use their products and services for free as part of a contribution to the open source ecosystem and our work.

Netlify Algolia 1Password

diff --git a/packages/migrate-config/package.json b/packages/migrate-config/package.json index f4b0bd0d2..9beec7127 100644 --- a/packages/migrate-config/package.json +++ b/packages/migrate-config/package.json @@ -1,6 +1,6 @@ { "name": "@eslint/migrate-config", - "version": "2.0.1", + "version": "2.0.2", "description": "Configuration migration for ESLint", "type": "module", "bin": { @@ -39,14 +39,14 @@ }, "homepage": "https://github.com/eslint/rewrite/tree/main/packages/migrate-config#readme", "devDependencies": { - "@eslint/core": "^1.0.1", + "@eslint/core": "^1.1.0", "eslint": "^9.27.0" }, "engines": { "node": "^20.19.0 || ^22.13.0 || >=24" }, "dependencies": { - "@eslint/compat": "^2.0.1", + "@eslint/compat": "^2.0.2", "@eslint/eslintrc": "^3.3.3", "camelcase": "^8.0.0", "espree": "^10.4.0", diff --git a/packages/object-schema/README.md b/packages/object-schema/README.md index 291e50b29..36ea30cbf 100644 --- a/packages/object-schema/README.md +++ b/packages/object-schema/README.md @@ -232,8 +232,8 @@ to get your logo on our READMEs and [website](https://eslint.org/sponsors).

Platinum Sponsors

Automattic

Gold Sponsors

Qlty Software Shopify

Silver Sponsors

-

Vite Liftoff American Express StackBlitz

Bronze Sponsors

-

Cybozu CrawlJobs Syntax N-iX Ltd Icons8 Discord GitBook Nx HeroCoders LambdaTest

+

Vite Liftoff American Express StackBlitz

Bronze Sponsors

+

Cybozu SAP CrawlJobs Syntax N-iX Ltd Icons8 Discord GitBook Nx HeroCoders LambdaTest

Technology Sponsors

Technology sponsors allow us to use their products and services for free as part of a contribution to the open source ecosystem and our work.

Netlify Algolia 1Password

diff --git a/packages/plugin-kit/CHANGELOG.md b/packages/plugin-kit/CHANGELOG.md index 5bbc0c57c..22134e4fa 100644 --- a/packages/plugin-kit/CHANGELOG.md +++ b/packages/plugin-kit/CHANGELOG.md @@ -1,5 +1,20 @@ # Changelog +## [0.6.0](https://github.com/eslint/rewrite/compare/plugin-kit-v0.5.1...plugin-kit-v0.6.0) (2026-01-29) + + +### Features + +* add `CustomRuleVisitorWithExit` type to `@eslint/plugin-kit` ([#351](https://github.com/eslint/rewrite/issues/351)) ([e7d1be4](https://github.com/eslint/rewrite/commit/e7d1be4066b38142b38e21e7877bf9b530b65ec9)) +* Add custom rule type helpers to `@eslint/plugin-kit` ([#355](https://github.com/eslint/rewrite/issues/355)) ([8ac8530](https://github.com/eslint/rewrite/commit/8ac853046aa1d4288d06d639be234c09988ade5e)) + + +### Dependencies + +* The following workspace dependencies were updated + * dependencies + * @eslint/core bumped from ^1.0.1 to ^1.1.0 + ## [0.5.1](https://github.com/eslint/rewrite/compare/plugin-kit-v0.5.0...plugin-kit-v0.5.1) (2026-01-08) diff --git a/packages/plugin-kit/README.md b/packages/plugin-kit/README.md index 9cfc36de7..3b6ab70ff 100644 --- a/packages/plugin-kit/README.md +++ b/packages/plugin-kit/README.md @@ -265,8 +265,8 @@ to get your logo on our READMEs and [website](https://eslint.org/sponsors).

Platinum Sponsors

Automattic

Gold Sponsors

Qlty Software Shopify

Silver Sponsors

-

Vite Liftoff American Express StackBlitz

Bronze Sponsors

-

Cybozu CrawlJobs Syntax N-iX Ltd Icons8 Discord GitBook Nx HeroCoders LambdaTest

+

Vite Liftoff American Express StackBlitz

Bronze Sponsors

+

Cybozu SAP CrawlJobs Syntax N-iX Ltd Icons8 Discord GitBook Nx HeroCoders LambdaTest

Technology Sponsors

Technology sponsors allow us to use their products and services for free as part of a contribution to the open source ecosystem and our work.

Netlify Algolia 1Password

diff --git a/packages/plugin-kit/jsr.json b/packages/plugin-kit/jsr.json index cf7c0b152..5b9455139 100644 --- a/packages/plugin-kit/jsr.json +++ b/packages/plugin-kit/jsr.json @@ -1,6 +1,6 @@ { "name": "@eslint/plugin-kit", - "version": "0.5.1", + "version": "0.6.0", "exports": "./dist/esm/index.js", "publish": { "include": [ diff --git a/packages/plugin-kit/package.json b/packages/plugin-kit/package.json index d3388eb4f..ca0a191bf 100644 --- a/packages/plugin-kit/package.json +++ b/packages/plugin-kit/package.json @@ -1,6 +1,6 @@ { "name": "@eslint/plugin-kit", - "version": "0.5.1", + "version": "0.6.0", "description": "Utilities for building ESLint plugins.", "author": "Nicholas C. Zakas", "type": "module", @@ -49,7 +49,7 @@ ], "license": "Apache-2.0", "dependencies": { - "@eslint/core": "^1.0.1", + "@eslint/core": "^1.1.0", "levn": "^0.4.1" }, "devDependencies": { diff --git a/packages/plugin-kit/src/source-code.js b/packages/plugin-kit/src/source-code.js index c02da02f3..3f661b465 100644 --- a/packages/plugin-kit/src/source-code.js +++ b/packages/plugin-kit/src/source-code.js @@ -19,9 +19,20 @@ /** @typedef {import("@eslint/core").DirectiveType} DirectiveType */ /** @typedef {import("@eslint/core").SourceCodeBaseTypeOptions} SourceCodeBaseTypeOptions */ /** - * @typedef {import("@eslint/core").TextSourceCode} TextSourceCode + * @typedef {import("@eslint/core").TextSourceCode} TextSourceCode * @template {SourceCodeBaseTypeOptions} [Options=SourceCodeBaseTypeOptions] */ +/** @typedef {import("@eslint/core").RuleVisitor} RuleVisitor */ +/** + * @typedef {import("./types.ts").CustomRuleVisitorWithExit} CustomRuleVisitorWithExit + * @template {RuleVisitor} RuleVisitorType + */ +/** @typedef {import("./types.ts").CustomRuleTypeDefinitions} CustomRuleTypeDefinitions */ +/** + * @typedef {import("./types.ts").CustomRuleDefinitionType} CustomRuleDefinitionType + * @template {Omit} LanguageSpecificOptions + * @template {Partial} Options + */ //----------------------------------------------------------------------------- // Helpers diff --git a/packages/plugin-kit/src/types.ts b/packages/plugin-kit/src/types.ts index d3f6a888d..19a5c672c 100644 --- a/packages/plugin-kit/src/types.ts +++ b/packages/plugin-kit/src/types.ts @@ -3,5 +3,79 @@ * @author Nicholas C. Zakas */ +//------------------------------------------------------------------------------ +// Imports +//------------------------------------------------------------------------------ + +import type { + RuleDefinition, + RuleDefinitionTypeOptions, + RuleVisitor, +} from "@eslint/core"; + +//------------------------------------------------------------------------------ +// Exports +//------------------------------------------------------------------------------ + +/** + * Defaults for non-language-related `RuleDefinition` options. + */ +export interface CustomRuleTypeDefinitions { + RuleOptions: unknown[]; + MessageIds: string; + ExtRuleDocs: Record; +} + +/** + * A helper type to define language specific specializations of the `RuleDefinition` type. + * + * @example + * ```ts + * type YourRuleDefinition< + * Options extends Partial = {}, + * > = CustomRuleDefinitionType< + * { + * LangOptions: YourLanguageOptions; + * Code: YourSourceCode; + * Visitor: YourRuleVisitor; + * Node: YourNode; + * }, + * Options + * >; + * ``` + */ +export type CustomRuleDefinitionType< + LanguageSpecificOptions extends Omit< + RuleDefinitionTypeOptions, + keyof CustomRuleTypeDefinitions + >, + Options extends Partial, +> = RuleDefinition< + // Language specific type options (non-configurable) + LanguageSpecificOptions & + Required< + // Rule specific type options (custom) + Options & + // Rule specific type options (defaults) + Omit + > +>; + +/** + * Adds matching `:exit` selector properties for each key of a `RuleVisitor`. + */ +export type CustomRuleVisitorWithExit = { + [Key in keyof RuleVisitorType as + | Key + | `${Key & string}:exit`]: RuleVisitorType[Key]; +}; + +/** + * A map of names to string values, or `null` when no value is provided. + */ export type StringConfig = Record; + +/** + * A map of names to boolean flags. + */ export type BooleanConfig = Record; diff --git a/packages/plugin-kit/tests/types/types.test.ts b/packages/plugin-kit/tests/types/types.test.ts index 0f2eaa0de..53868c5aa 100644 --- a/packages/plugin-kit/tests/types/types.test.ts +++ b/packages/plugin-kit/tests/types/types.test.ts @@ -7,16 +7,20 @@ // Imports //----------------------------------------------------------------------------- +import type { LanguageOptions, RuleVisitor } from "@eslint/core"; import { - BooleanConfig, + type BooleanConfig, CallMethodStep, ConfigCommentParser, + type CustomRuleDefinitionType, + type CustomRuleTypeDefinitions, + type CustomRuleVisitorWithExit, Directive, - DirectiveType, - RulesConfig, - SourceLocation, - SourceRange, - StringConfig, + type DirectiveType, + type RulesConfig, + type SourceLocation, + type SourceRange, + type StringConfig, TextSourceCodeBase, VisitNodeStep, } from "@eslint/plugin-kit"; @@ -182,3 +186,168 @@ step1.kind satisfies 1; step1.phase satisfies 1 | 2; step1.target satisfies object; step1.type satisfies "visit"; + +// CustomRuleDefinitionType +interface TestNode { + type: string; + start: number; +} + +interface TestLanguageOptions extends LanguageOptions { + ecmaVersion?: number; +} + +interface TestRuleVisitor extends RuleVisitor { + Foo?: (node: TestNode) => void; +} + +type TestRuleDefinition< + Options extends Partial = + CustomRuleTypeDefinitions, +> = CustomRuleDefinitionType< + { + LangOptions: TestLanguageOptions; + Code: TestTextSourceCode; + Visitor: TestRuleVisitor; + Node: TestNode; + }, + Options +>; + +const testRule: TestRuleDefinition<{ + RuleOptions: [{ foo: string; bar: number }]; + MessageIds: "badFoo" | "wrongBar"; + ExtRuleDocs: { foo: boolean; bar: number }; +}> = { + meta: { + type: "problem", + fixable: "code", + docs: { + recommended: true, + foo: true, + // @ts-expect-error -- bar should be number, not string + bar: "1", + }, + deprecated: { + message: "use something else", + url: "https://example.com", + replacedBy: [ + { + message: "use this instead", + url: "https://example.com", + rule: { + name: "new-rule", + url: "https://example.com/rules/new-rule", + }, + plugin: { + name: "new-plugin", + url: "https://example.com/plugins/new-plugin", + }, + }, + ], + }, + schema: [ + { + type: "object", + properties: { + foo: { + type: "string", + }, + bar: { + type: "integer", + }, + }, + additionalProperties: false, + }, + ], + defaultOptions: [ + { + foo: "always", + bar: 5, + // @ts-expect-error -- invalid default option "baz" + baz: "invalid", + }, + ], + messages: { + badFoo: "change this foo", + wrongBar: "fix this bar", + // @ts-expect-error -- invalid message id "baz" + baz: "invalid message", + }, + language: "javascript", + dialects: ["javascript", "typescript"], + }, + + create(context) { + context.languageOptions.ecmaVersion satisfies number | undefined; + context.options satisfies [{ foo: string; bar: number }]; + context.sourceCode satisfies TestTextSourceCode; + + return { + Foo(node) { + if (context.options[0].foo === "always") { + context.report({ + messageId: "badFoo", + loc: { + start: { line: node.start, column: 1 }, + end: { line: node.start + 1, column: Infinity }, + }, + }); + } + }, + }; + }, +}; + +type Rule1 = TestRuleDefinition; +type Rule2 = TestRuleDefinition<{}>; +type Rule3 = TestRuleDefinition<{ + RuleOptions: [number, string]; + MessageIds: "foo" | "bar"; + ExtRuleDocs: { baz: number; qux: string }; +}>; +// @ts-expect-error -- non-object not allowed +type Rule4 = TestRuleDefinition; +// @ts-expect-error -- non-customizable properties not allowed +type Rule5 = TestRuleDefinition<{ Code: TestTextSourceCode }>; +// @ts-expect-error -- undefined value not allowed for optional property +type Rule6 = TestRuleDefinition<{ RuleOptions: undefined }>; + +// CustomRuleVisitorWithExit +type TestVisitor = { + Program: (node: { type: "Program" }) => void; + Identifier: (node: { type: "Identifier"; name: string }) => void; + "FunctionDeclaration > Identifier": (node: { type: "Identifier" }) => void; +}; + +type VisitorWithExit = CustomRuleVisitorWithExit; + +const visitor: VisitorWithExit = { + Program(node) { + node.type satisfies "Program"; + }, + Identifier(node) { + node.type satisfies "Identifier"; + node.name satisfies string; + }, + "FunctionDeclaration > Identifier"(node) { + node.type satisfies "Identifier"; + }, + "Program:exit"(node) { + node.type satisfies "Program"; + }, + "Identifier:exit"(node) { + node.type satisfies "Identifier"; + node.name satisfies string; + }, + "FunctionDeclaration > Identifier:exit"(node) { + node.type satisfies "Identifier"; + }, + // @ts-expect-error -- Extra keys should not be allowed + Foo() {}, +}; + +visitor.Program satisfies TestVisitor["Program"]; +visitor["Program:exit"] satisfies TestVisitor["Program"]; +// @ts-expect-error -- Exit key must correspond to an existing selector +visitor["Expression:exit"] = () => {}; diff --git a/tools/build-cts.js b/tools/build-cts.js index 35a976bb8..bed0ae74a 100644 --- a/tools/build-cts.js +++ b/tools/build-cts.js @@ -24,9 +24,6 @@ if (!newFilename) { } const oldSourceText = await readFile(filename, "utf-8"); -const newSourceText = oldSourceText.replaceAll( - ' from "./types.ts";\n', - ' from "./types.cts";\n', -); +const newSourceText = oldSourceText.replaceAll('"./types.ts"', '"./types.cts"'); await writeFile(newFilename, newSourceText);