Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: rewrite createRule and RuleTester #72

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 0 additions & 37 deletions patches/@typescript-eslint+utils+7.4.0.patch

This file was deleted.

40 changes: 0 additions & 40 deletions patches/eslint-compat-utils+0.5.0.patch

This file was deleted.

5 changes: 2 additions & 3 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
import type { TSESLint } from '@typescript-eslint/utils'

// rules
import electron from './config/electron'
import errors from './config/errors'
Expand Down Expand Up @@ -56,6 +54,7 @@ import preferDefaultExport from './rules/prefer-default-export'
import unambiguous from './rules/unambiguous'
// configs
import type { PluginConfig } from './types'
import type { RuleModuleWithCustomMeta } from './utils'

const configs = {
recommended,
Expand Down Expand Up @@ -127,7 +126,7 @@ const rules = {

// deprecated aliases to rules
'imports-first': importsFirst,
} satisfies Record<string, TSESLint.RuleModule<string, readonly unknown[]>>
} satisfies Record<string, RuleModuleWithCustomMeta<string, readonly unknown[]>>

export = {
configs,
Expand Down
9 changes: 2 additions & 7 deletions src/rules/imports-first.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,10 @@
import { ESLintUtils } from '@typescript-eslint/utils'

import { docsUrl } from '../utils/docs-url'
import { createRule } from '../utils'

import first from './first'

const createRule = ESLintUtils.RuleCreator(ruleName =>
docsUrl(ruleName, '7b25c1cb95ee18acc1531002fd343e1e6031f9ed'),
)

export = createRule({
...first,
commitHash: '7b25c1cb95ee18acc1531002fd343e1e6031f9ed',
name: 'imports-first',
meta: {
...first.meta,
Expand Down
67 changes: 66 additions & 1 deletion src/utils/create-rule.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,70 @@
import type { TSESLint } from '@typescript-eslint/utils'
import { ESLintUtils } from '@typescript-eslint/utils'

import { docsUrl } from './docs-url'

export const createRule = ESLintUtils.RuleCreator(docsUrl)
// TSESLint.RuleMetaDataDocs, but with "category" property for eslint-doc-generator
type MetaDataDocsWithCategory<Options extends readonly unknown[]> = {
/**
* The category the rule falls under
*/
category?: string

recommended?:
| TSESLint.RuleRecommendation
| TSESLint.RuleRecommendationAcrossConfigs<Options>
| boolean
} & Omit<TSESLint.RuleMetaDataDocs<Options>, 'recommended'>

// TSESLint.RuleMetaData, but with "docs" property overriden for eslint-doc-generator
type MetadataWithCustomDocs<
MessageIDs extends string,
Options extends readonly unknown[],
> = {
docs: MetaDataDocsWithCategory<Options>
} & Omit<TSESLint.RuleMetaData<MessageIDs, Options>, 'docs'>

// TSESLint.RuleModule, but with "meta" property overriden for eslint-doc-generator
export type RuleModuleWithCustomMeta<
MessageIds extends string,
Options extends readonly unknown[] = [],
ExtendedRuleListener extends TSESLint.RuleListener = TSESLint.RuleListener,
> = {
meta: MetadataWithCustomDocs<MessageIds, Options>
} & Omit<TSESLint.RuleModule<MessageIds, Options, ExtendedRuleListener>, 'meta'>

type RuleCreateOption<
Options extends readonly unknown[],
MessageIds extends string,
> = {
meta: MetadataWithCustomDocs<MessageIds, Options>
commitHash?: string
} & Omit<ESLintUtils.RuleWithMetaAndName<Options, MessageIds>, 'meta'>

export function createRule<
Options extends readonly unknown[],
MessageIds extends string,
>({
name,
meta,
commitHash,
...rules
}: Readonly<RuleCreateOption<Options, MessageIds>>): RuleModuleWithCustomMeta<
MessageIds,
Options
> {
const { docs, ...metaWithoutDocs } = meta
return {
...ESLintUtils.RuleCreator.withoutDocs({
meta: metaWithoutDocs,
...rules,
}),
meta: {
...meta,
docs: {
...docs,
url: docsUrl(name, commitHash),
},
},
}
Comment on lines +57 to +69
Copy link
Collaborator Author

@SukkaW SukkaW Apr 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Under the hood we are still using ts-eslint's RuleCreator as much as possible, we are only overriding the returned meta property with our meta property.

}
12 changes: 6 additions & 6 deletions test/rules/consistent-type-specifier-style.spec.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { TSESLint, TSESTree } from '@typescript-eslint/utils'
import { TSESTree } from '@typescript-eslint/utils'

import { parsers, test } from '../utils'
import { parsers, test, RuleTester } from '../utils'

import rule from 'eslint-plugin-import-x/rules/consistent-type-specifier-style'

Expand Down Expand Up @@ -445,28 +445,28 @@ const FLOW_ONLY = {
} as const

describe('TypeScript', () => {
const ruleTester = new TSESLint.RuleTester({
const ruleTester = new RuleTester({
parser: parsers.TS,
parserOptions: {
ecmaVersion: 6,
sourceType: 'module',
},
})
ruleTester.run('consistent-type-specifier-style', rule, {
ruleTester.run$('consistent-type-specifier-style', rule, {
valid: [...COMMON_TESTS.valid, ...TS_ONLY.valid],
invalid: [...COMMON_TESTS.invalid, ...TS_ONLY.invalid],
})
})

describe('Babel/Flow', () => {
const ruleTester = new TSESLint.RuleTester({
const ruleTester = new RuleTester({
parser: parsers.BABEL,
parserOptions: {
ecmaVersion: 6,
sourceType: 'module',
},
})
ruleTester.run('consistent-type-specifier-style', rule, {
ruleTester.run$('consistent-type-specifier-style', rule, {
valid: [...COMMON_TESTS.valid, ...FLOW_ONLY.valid],
invalid: [...COMMON_TESTS.invalid, ...FLOW_ONLY.invalid],
})
Expand Down
12 changes: 5 additions & 7 deletions test/rules/default.spec.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,13 @@
import path from 'node:path'

import { TSESLint } from '@typescript-eslint/utils'

import { test, SYNTAX_CASES, parsers } from '../utils'
import { test, SYNTAX_CASES, parsers, RuleTester } from '../utils'

import rule from 'eslint-plugin-import-x/rules/default'
import { CASE_SENSITIVE_FS } from 'eslint-plugin-import-x/utils'

const ruleTester = new TSESLint.RuleTester()
const ruleTester = new RuleTester()

ruleTester.run('default', rule, {
ruleTester.run$('default', rule, {
valid: [
test({ code: 'import "./malformed.js"' }),

Expand Down Expand Up @@ -161,7 +159,7 @@ ruleTester.run('default', rule, {

// #311: import of mismatched case
if (!CASE_SENSITIVE_FS) {
ruleTester.run('default (path case-insensitivity)', rule, {
ruleTester.run$('default (path case-insensitivity)', rule, {
valid: [
test({
code: 'import foo from "./jsx/MyUncoolComponent.jsx"',
Expand All @@ -180,7 +178,7 @@ if (!CASE_SENSITIVE_FS) {

describe('TypeScript', () => {
const parser = parsers.TS
ruleTester.run(`default`, rule, {
ruleTester.run$(`default`, rule, {
valid: [
test({
code: `import foobar from "./typescript-default"`,
Expand Down
10 changes: 5 additions & 5 deletions test/rules/dynamic-import-chunkname.spec.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import { TSESLint, TSESTree } from '@typescript-eslint/utils'
import { TSESTree } from '@typescript-eslint/utils'

import { SYNTAX_CASES, parsers } from '../utils'
import { SYNTAX_CASES, parsers, RuleTester } from '../utils'

import rule from 'eslint-plugin-import-x/rules/dynamic-import-chunkname'

const ruleTester = new TSESLint.RuleTester()
const ruleTester = new RuleTester()

const pickyCommentFormat = '[a-zA-Z-_/.]+'

Expand Down Expand Up @@ -43,7 +43,7 @@ const pickyChunkNameFormatError = {
},
} as const

ruleTester.run('dynamic-import-chunkname', rule, {
ruleTester.run$('dynamic-import-chunkname', rule, {
valid: [
{
code: `dynamicImport(
Expand Down Expand Up @@ -971,7 +971,7 @@ describe('TypeScript', () => {
const typescriptParser = parsers.TS
const nodeType = TSESTree.AST_NODE_TYPES.ImportExpression

ruleTester.run('dynamic-import-chunkname', rule, {
ruleTester.run$('dynamic-import-chunkname', rule, {
valid: [
{
code: `import('test')`,
Expand Down
10 changes: 4 additions & 6 deletions test/rules/export.spec.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import { TSESLint } from '@typescript-eslint/utils'

import { test, testFilePath, SYNTAX_CASES, parsers } from '../utils'
import { test, testFilePath, SYNTAX_CASES, parsers, RuleTester } from '../utils'

import rule from 'eslint-plugin-import-x/rules/export'

const ruleTester = new TSESLint.RuleTester()
const ruleTester = new RuleTester()

ruleTester.run('export', rule, {
ruleTester.run$('export', rule, {
valid: [
test({ code: 'import "./malformed.js"' }),

Expand Down Expand Up @@ -166,7 +164,7 @@ describe('TypeScript', () => {
},
}

ruleTester.run('export', rule, {
ruleTester.run$('export', rule, {
valid: [
// type/value name clash
test({
Expand Down
7 changes: 3 additions & 4 deletions test/rules/exports-last.spec.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
import { TSESLint } from '@typescript-eslint/utils'
import type { TSESTree } from '@typescript-eslint/utils'

import { test } from '../utils'
import { test, RuleTester } from '../utils'

import rule from 'eslint-plugin-import-x/rules/exports-last'

const ruleTester = new TSESLint.RuleTester()
const ruleTester = new RuleTester()

const error = (type: `${TSESTree.AST_NODE_TYPES}`) =>
({
messageId: 'end',
type,
}) as const

ruleTester.run('exports-last', rule, {
ruleTester.run$('exports-last', rule, {
valid: [
// Empty file
test({
Expand Down
10 changes: 4 additions & 6 deletions test/rules/extensions.spec.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,10 @@
import { TSESLint } from '@typescript-eslint/utils'

import { test, testFilePath, parsers } from '../utils'
import { test, testFilePath, parsers, RuleTester } from '../utils'

import rule from 'eslint-plugin-import-x/rules/extensions'

const ruleTester = new TSESLint.RuleTester()
const ruleTester = new RuleTester()

ruleTester.run('extensions', rule, {
ruleTester.run$('extensions', rule, {
valid: [
test({ code: 'import a from "@/a"' }),
test({ code: 'import a from "a"' }),
Expand Down Expand Up @@ -662,7 +660,7 @@ ruleTester.run('extensions', rule, {
describe('TypeScript', () => {
const parser = parsers.TS

ruleTester.run(`${parser}: extensions ignore type-only`, rule, {
ruleTester.run$(`${parser}: extensions ignore type-only`, rule, {
valid: [
test({
code: 'import type T from "./typescript-declare";',
Expand Down
Loading
Loading