🌐 AI搜索 & 代理 主页
Skip to content
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
1 change: 1 addition & 0 deletions packages/rule-tester/src/RuleTester.ts
Original file line number Diff line number Diff line change
Expand Up @@ -427,6 +427,7 @@ export class RuleTester extends TestFramework {
defineRule(name: string, rule: AnyRuleModule): void {
this.#rules[name] = {
...rule,
name,
// Create a wrapper rule that freezes the `context` properties.
create(context): RuleListener {
freezeDeeply(context.options);
Expand Down
19 changes: 17 additions & 2 deletions packages/utils/src/eslint-utils/RuleCreator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ export interface RuleWithMeta<
Docs = unknown,
> extends RuleCreateAndOptions<Options, MessageIds> {
meta: RuleMetaData<MessageIds, Docs, Options>;
name?: string;
}

export interface RuleWithMetaAndName<
Expand All @@ -47,6 +48,15 @@ export interface RuleWithMetaAndName<
name: string;
}

type RuleModuleWithName<
MessageIds extends string,
Options extends readonly unknown[] = [],
Docs = unknown,
ExtendedRuleListener extends RuleListener = RuleListener,
> = RuleModule<MessageIds, Options, Docs, ExtendedRuleListener> & {
name: string;
};

/**
* Creates reusable function to create rules with default options and docs URLs.
*
Expand All @@ -67,17 +77,20 @@ export function RuleCreator<PluginDocs = unknown>(
...rule
}: Readonly<
RuleWithMetaAndName<Options, MessageIds, PluginDocs>
>): RuleModule<MessageIds, Options, PluginDocs> {
return createRule<Options, MessageIds, PluginDocs>({
>): RuleModuleWithName<MessageIds, Options, PluginDocs> {
const ruleWithDocs = createRule<Options, MessageIds, PluginDocs>({
meta: {
...meta,
docs: {
...meta.docs,
url: urlCreator(name),
},
},
name,
...rule,
});

return ruleWithDocs as RuleModuleWithName<MessageIds, Options, PluginDocs>;
};
}

Expand All @@ -89,6 +102,7 @@ function createRule<
create,
defaultOptions,
meta,
name,
}: Readonly<RuleWithMeta<Options, MessageIds, PluginDocs>>): RuleModule<
MessageIds,
Options,
Expand All @@ -101,6 +115,7 @@ function createRule<
},
defaultOptions,
meta,
name,
};
}

Expand Down
5 changes: 5 additions & 0 deletions packages/utils/src/ts-eslint/Rule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -737,6 +737,11 @@ export interface RuleModule<
* Metadata about the rule
*/
meta: RuleMetaData<MessageIds, Docs, Options>;

/**
* Rule name
*/
name?: string;
}

export type AnyRuleModule = RuleModule<string, readonly unknown[]>;
Expand Down
50 changes: 50 additions & 0 deletions packages/utils/tests/eslint-utils/RuleCreator.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,55 @@ describe(ESLintUtils.RuleCreator, () => {
schema: [],
type: 'problem',
});
expect(rule.name).toBe('test');
});

it('withoutDocs should work without a `name`', () => {
const rule = ESLintUtils.RuleCreator.withoutDocs({
create() {
return {};
},
defaultOptions: [],
meta: {
docs: {
description: 'some description',
},
messages: {
foo: 'some message',
},
schema: [],
type: 'problem',
},
});

expect(rule.meta.docs).toEqual({
description: 'some description',
});
expect(rule.name).toBeUndefined();
});

it('withoutDocs should work with a `name`', () => {
const rule = ESLintUtils.RuleCreator.withoutDocs({
create() {
return {};
},
defaultOptions: [],
meta: {
docs: {
description: 'some description',
},
messages: {
foo: 'some message',
},
schema: [],
type: 'problem',
},
name: 'some-name',
});

expect(rule.meta.docs).toEqual({
description: 'some description',
});
expect(rule.name).toBe('some-name');
});
});