Skip to content

Commit df3c4ed

Browse files
committed
refactor(eslint): add defineRules and deprecate convertRules
1 parent 25342bb commit df3c4ed

4 files changed

Lines changed: 59 additions & 22 deletions

File tree

packages/eslint/index.ts

Lines changed: 51 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -29,25 +29,26 @@ const loader = async (moduleName: string) => {
2929
return mod as any;
3030
};
3131

32+
type S = 'error' | 'warn' | 'suggestion' | 'off' | 0 | 1 | 2;
33+
type O<T extends any[]> = S | [S, ...options: T];
34+
3235
/**
33-
* Converts an ESLint rules configuration to TSSLint rules.
34-
*
35-
* The type definitions are generated when `@tsslint/eslint` is installed.
36-
* If the type definitions become outdated, please run
37-
* `node node_modules/@tsslint/eslint/scripts/generateDts.js` to update them.
36+
* @deprecated Use `defineRules` instead
3837
*/
3938
export async function convertRules(
40-
rulesConfig: ESLintRulesConfig,
39+
rulesConfig: { [K in keyof ESLintRulesConfig]: O<ESLintRulesConfig[K]> },
4140
context: Partial<ESLint.Rule.RuleContext> = {}
4241
) {
4342
const rules: TSSLint.Rules = {};
4443
for (const [rule, severityOrOptions] of Object.entries(rulesConfig)) {
4544
let severity: boolean;
4645
let options: any[];
4746
if (Array.isArray(severityOrOptions)) {
47+
// @ts-expect-error
4848
[severity, ...options] = severityOrOptions;
4949
}
5050
else {
51+
// @ts-expect-error
5152
severity = severityOrOptions;
5253
options = [];
5354
}
@@ -59,7 +60,47 @@ export async function convertRules(
5960
rules[rule] = noop;
6061
continue;
6162
}
62-
const ruleModule = await getRuleByKey(rule);
63+
const ruleModule = await loadRuleByKey(rule);
64+
if (!ruleModule) {
65+
throw new Error(`Failed to resolve rule "${rule}".`);
66+
}
67+
rules[rule] = convertRule(
68+
ruleModule,
69+
options,
70+
{ id: rule, ...context }
71+
);
72+
}
73+
return rules;
74+
}
75+
76+
/**
77+
* Converts an ESLint rules configuration to TSSLint rules.
78+
*
79+
* The type definitions are generated when `@tsslint/eslint` is installed.
80+
* If the type definitions become outdated, please run
81+
* `node node_modules/@tsslint/eslint/scripts/generateDts.js` to update them.
82+
*/
83+
export async function defineRules(
84+
rulesConfig: { [K in keyof ESLintRulesConfig]: boolean | ESLintRulesConfig[K] },
85+
context: Partial<ESLint.Rule.RuleContext> = {}
86+
) {
87+
const rules: TSSLint.Rules = {};
88+
for (const [rule, severityOrOptions] of Object.entries(rulesConfig)) {
89+
let severity: boolean;
90+
let options: any[];
91+
if (Array.isArray(severityOrOptions)) {
92+
severity = true;
93+
options = severityOrOptions;
94+
}
95+
else {
96+
severity = severityOrOptions;
97+
options = [];
98+
}
99+
if (!severity) {
100+
rules[rule] = noop;
101+
continue;
102+
}
103+
const ruleModule = await loadRuleByKey(rule);
63104
if (!ruleModule) {
64105
throw new Error(`Failed to resolve rule "${rule}".`);
65106
}
@@ -96,16 +137,16 @@ function* resolveRuleKey(rule: string): Generator<[
96137
}
97138
}
98139

99-
async function getRuleByKey(rule: string): Promise<ESLint.Rule.RuleModule | undefined> {
140+
async function loadRuleByKey(rule: string): Promise<ESLint.Rule.RuleModule | undefined> {
100141
for (const resolved of resolveRuleKey(rule)) {
101-
const ruleModule = await getRule(...resolved);
142+
const ruleModule = await loadRule(...resolved);
102143
if (ruleModule) {
103144
return ruleModule;
104145
}
105146
}
106147
}
107148

108-
async function getRule(pluginName: string | undefined, ruleName: string): Promise<ESLint.Rule.RuleModule | undefined> {
149+
async function loadRule(pluginName: string | undefined, ruleName: string): Promise<ESLint.Rule.RuleModule | undefined> {
109150
if (pluginName) {
110151
plugins[pluginName] ??= loader(pluginName);
111152
const plugin = await plugins[pluginName];

packages/eslint/lib/dtsGenerate.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,6 @@ export async function generate(
1717
let dts = '';
1818
let defId = 0;
1919

20-
line(`export type O<T extends any[]> = boolean | [boolean, ...options: T];`);
21-
line(``);
2220
line(`export interface ESLintRulesConfig {`);
2321
indentLevel++;
2422

@@ -136,9 +134,9 @@ export async function generate(
136134
}
137135

138136
if (optionsType) {
139-
line(`'${ruleKey}'?: O<${optionsType}>,`);
137+
line(`'${ruleKey}'?: ${optionsType},`);
140138
} else {
141-
line(`'${ruleKey}'?: O<any[]>,`);
139+
line(`'${ruleKey}'?: any[],`);
142140
}
143141
}
144142

packages/eslint/lib/types.ts

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
export type O<T extends any[]> = boolean | [boolean, ...options: T];
2-
3-
export interface ESLintRulesConfig {
4-
[key: string]: O<any[]>;
1+
export interface ESLintRulesConfig extends Record<string, any[]> {
2+
[key: string]: any[];
53
}

tsslint.config.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import { defineConfig } from '@tsslint/config';
2-
import { convertRules } from '@tsslint/eslint';
2+
import { defineRules } from '@tsslint/eslint';
33

44
export default defineConfig({
5-
rules: await convertRules({
6-
'@typescript-eslint/consistent-type-imports': ['warn', {
5+
rules: await defineRules({
6+
'@typescript-eslint/consistent-type-imports': [{
77
disallowTypeAnnotations: false,
88
fixStyle: 'inline-type-imports',
99
}],
10-
'@typescript-eslint/no-unnecessary-type-assertion': 'warn',
10+
'@typescript-eslint/no-unnecessary-type-assertion': true,
1111
}),
1212
});

0 commit comments

Comments
 (0)