Skip to content

Commit c96ce29

Browse files
committed
refactor(linter/plugins): rename RuleAndContext to RuleDetails (#15480)
Pure refactor. Give this type a better name. It now contains a lot more than just the `Rule` and `Context`.
1 parent bc731ff commit c96ce29

File tree

4 files changed

+43
-41
lines changed

4 files changed

+43
-41
lines changed

apps/oxlint/src-js/plugins/context.ts

Lines changed: 17 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ import { SOURCE_CODE } from './source_code.js';
3232
import { settings, initSettings } from './settings.js';
3333

3434
import type { Fix, FixFn } from './fix.ts';
35-
import type { RuleAndContext } from './load.ts';
35+
import type { RuleDetails } from './load.ts';
3636
import type { SourceCode } from './source_code.ts';
3737
import type { Location, Ranged } from './types.ts';
3838

@@ -256,10 +256,10 @@ export interface Context extends FileContext {
256256
/**
257257
* Create `Context` object for a rule.
258258
* @param fullRuleName - Full rule name, including plugin name e.g. `my-plugin/my-rule`
259-
* @param ruleAndContext - `RuleAndContext` object
259+
* @param ruleDetails - `RuleDetails` object
260260
* @returns `Context` object
261261
*/
262-
export function createContext(fullRuleName: string, ruleAndContext: RuleAndContext): Readonly<Context> {
262+
export function createContext(fullRuleName: string, ruleDetails: RuleDetails): Readonly<Context> {
263263
// Create `Context` object for rule.
264264
//
265265
// All properties are enumerable, to support a pattern which some ESLint plugins use:
@@ -290,31 +290,31 @@ export function createContext(fullRuleName: string, ruleAndContext: RuleAndConte
290290
// Getter for rule options for this rule on this file
291291
get options(): Readonly<unknown[]> {
292292
if (filePath === null) throw new Error('Cannot access `context.options` in `createOnce`');
293-
return ruleAndContext.options;
293+
return ruleDetails.options;
294294
},
295295
/**
296296
* Report error.
297297
* @param diagnostic - Diagnostic object
298298
* @throws {TypeError} If `diagnostic` is invalid
299299
*/
300300
report(diagnostic: Diagnostic): void {
301-
// Delegate to `reportImpl`, passing rule-specific details (`RuleAndContext`)
302-
reportImpl(diagnostic, ruleAndContext);
301+
// Delegate to `reportImpl`, passing rule-specific details (`RuleDetails`)
302+
reportImpl(diagnostic, ruleDetails);
303303
},
304304
} as unknown as Context); // It seems TS can't understand `__proto__: FILE_CONTEXT`
305305
}
306306

307307
/**
308308
* Report error.
309309
* @param diagnostic - Diagnostic object
310-
* @param ruleAndContext - `RuleAndContext` object, containing rule-specific details e.g. `isFixable`
310+
* @param ruleDetails - `RuleDetails` object, containing rule-specific details e.g. `isFixable`
311311
* @throws {TypeError} If `diagnostic` is invalid
312312
*/
313-
function reportImpl(diagnostic: Diagnostic, ruleAndContext: RuleAndContext): void {
313+
function reportImpl(diagnostic: Diagnostic, ruleDetails: RuleDetails): void {
314314
if (filePath === null) throw new Error('Cannot report errors in `createOnce`');
315315

316316
// Get message, resolving message from `messageId` if present
317-
let message = getMessage(diagnostic, ruleAndContext);
317+
let message = getMessage(diagnostic, ruleDetails);
318318

319319
// Interpolate placeholders {{key}} with data values
320320
if (hasOwn(diagnostic, 'data')) {
@@ -369,22 +369,22 @@ function reportImpl(diagnostic: Diagnostic, ruleAndContext: RuleAndContext): voi
369369
message,
370370
start,
371371
end,
372-
ruleIndex: ruleAndContext.ruleIndex,
373-
fixes: getFixes(diagnostic, ruleAndContext),
372+
ruleIndex: ruleDetails.ruleIndex,
373+
fixes: getFixes(diagnostic, ruleDetails),
374374
});
375375
}
376376

377377
/**
378378
* Get message from diagnostic.
379379
* @param diagnostic - Diagnostic object
380-
* @param ruleAndContext - `RuleAndContext` object, containing rule-specific `messages`
380+
* @param ruleDetails - `RuleDetails` object, containing rule-specific `messages`
381381
* @returns Message string
382382
* @throws {Error|TypeError} If neither `message` nor `messageId` provided, or of wrong type
383383
*/
384-
function getMessage(diagnostic: Diagnostic, ruleAndContext: RuleAndContext): string {
384+
function getMessage(diagnostic: Diagnostic, ruleDetails: RuleDetails): string {
385385
if (hasOwn(diagnostic, 'messageId')) {
386386
const { messageId } = diagnostic as { messageId: string | null | undefined };
387-
if (messageId != null) return resolveMessageFromMessageId(messageId, ruleAndContext);
387+
if (messageId != null) return resolveMessageFromMessageId(messageId, ruleDetails);
388388
}
389389

390390
if (hasOwn(diagnostic, 'message')) {
@@ -399,12 +399,12 @@ function getMessage(diagnostic: Diagnostic, ruleAndContext: RuleAndContext): str
399399
/**
400400
* Resolve a message ID to its message string, with optional data interpolation.
401401
* @param messageId - The message ID to resolve
402-
* @param ruleAndContext - `RuleAndContext` object, containing rule-specific `messages`
402+
* @param ruleDetails - `RuleDetails` object, containing rule-specific `messages`
403403
* @returns Resolved message string
404404
* @throws {Error} If `messageId` is not found in `messages`
405405
*/
406-
function resolveMessageFromMessageId(messageId: string, ruleAndContext: RuleAndContext): string {
407-
const { messages } = ruleAndContext;
406+
function resolveMessageFromMessageId(messageId: string, ruleDetails: RuleDetails): string {
407+
const { messages } = ruleDetails;
408408
if (messages === null) {
409409
throw new Error(`Cannot use messageId '${messageId}' - rule does not define any messages in \`meta.messages\``);
410410
}

apps/oxlint/src-js/plugins/fix.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { assertIs } from './utils.js';
22

33
import type { Diagnostic } from './context.ts';
4-
import type { RuleAndContext } from './load.ts';
4+
import type { RuleDetails } from './load.ts';
55
import type { Range, Ranged } from './types.ts';
66

77
const { prototype: ArrayPrototype, from: ArrayFrom } = Array,
@@ -78,12 +78,12 @@ export type Fixer = typeof FIXER;
7878
* with getters. As we're not managing to be 100% bulletproof anyway, maybe we don't need to be quite so defensive.
7979
*
8080
* @param diagnostic - Diagnostic object
81-
* @param ruleAndContext - `RuleAndContext` object, containing rule-specific `isFixable` value
81+
* @param ruleDetails - `RuleDetails` object, containing rule-specific `isFixable` value
8282
* @returns Non-empty array of `Fix` objects, or `null` if none
8383
* @throws {Error} If rule is not marked as fixable but `fix` function returns fixes,
8484
* or if `fix` function returns any invalid `Fix` objects
8585
*/
86-
export function getFixes(diagnostic: Diagnostic, ruleAndContext: RuleAndContext): Fix[] | null {
86+
export function getFixes(diagnostic: Diagnostic, ruleDetails: RuleDetails): Fix[] | null {
8787
// ESLint silently ignores non-function `fix` values, so we do the same
8888
const { fix } = diagnostic;
8989
if (typeof fix !== 'function') return null;
@@ -138,7 +138,7 @@ export function getFixes(diagnostic: Diagnostic, ruleAndContext: RuleAndContext)
138138

139139
// ESLint does not throw this error if `fix` function returns only falsy values.
140140
// We've already exited if that is the case, so we're reproducing that behavior.
141-
if (ruleAndContext.isFixable === false) {
141+
if (ruleDetails.isFixable === false) {
142142
throw new Error('Fixable rules must set the `meta.fixable` property to "code" or "whitespace".');
143143
}
144144

apps/oxlint/src-js/plugins/lint.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -127,20 +127,20 @@ function lintFileImpl(
127127

128128
for (let i = 0, len = ruleIds.length; i < len; i++) {
129129
const ruleId = ruleIds[i],
130-
ruleAndContext = registeredRules[ruleId];
130+
ruleDetails = registeredRules[ruleId];
131131

132132
// Set `ruleIndex` for rule. It's used when sending diagnostics back to Rust.
133-
ruleAndContext.ruleIndex = i;
133+
ruleDetails.ruleIndex = i;
134134

135-
const { rule, context } = ruleAndContext;
135+
const { rule, context } = ruleDetails;
136136

137-
let { visitor } = ruleAndContext;
137+
let { visitor } = ruleDetails;
138138
if (visitor === null) {
139139
// Rule defined with `create` method
140140
visitor = rule.create(context);
141141
} else {
142142
// Rule defined with `createOnce` method
143-
const { beforeHook, afterHook } = ruleAndContext;
143+
const { beforeHook, afterHook } = ruleDetails;
144144
if (beforeHook !== null) {
145145
// If `before` hook returns `false`, skip this rule
146146
const shouldRun = beforeHook();

apps/oxlint/src-js/plugins/load.ts

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -35,11 +35,13 @@ export interface CreateOnceRule {
3535
createOnce: (context: Context) => VisitorWithHooks;
3636
}
3737

38-
// Linter rule and context object.
39-
// If `rule` has a `createOnce` method, the visitor it returns is stored in `visitor`.
40-
export type RuleAndContext = CreateRuleAndContext | CreateOnceRuleAndContext;
38+
/**
39+
* Linter rule, context object, and other details of rule.
40+
* If `rule` has a `createOnce` method, the visitor it returns is stored in `visitor` property.
41+
*/
42+
export type RuleDetails = CreateRuleDetails | CreateOnceRuleDetails;
4143

42-
interface RuleAndContextBase {
44+
interface RuleDetailsBase {
4345
// Static properties of the rule
4446
readonly context: Readonly<Context>;
4547
readonly isFixable: boolean;
@@ -49,14 +51,14 @@ interface RuleAndContextBase {
4951
options: Readonly<unknown[]>;
5052
}
5153

52-
interface CreateRuleAndContext extends RuleAndContextBase {
54+
interface CreateRuleDetails extends RuleDetailsBase {
5355
rule: CreateRule;
5456
visitor: null;
5557
beforeHook: null;
5658
afterHook: null;
5759
}
5860

59-
interface CreateOnceRuleAndContext extends RuleAndContextBase {
61+
interface CreateOnceRuleDetails extends RuleDetailsBase {
6062
rule: CreateOnceRule;
6163
visitor: Visitor;
6264
beforeHook: BeforeHook | null;
@@ -68,7 +70,7 @@ const registeredPluginPaths = new Set<string>();
6870

6971
// Rule objects for loaded rules.
7072
// Indexed by `ruleId`, which is passed to `lintFile`.
71-
export const registeredRules: RuleAndContext[] = [];
73+
export const registeredRules: RuleDetails[] = [];
7274

7375
// `before` hook which makes rule never run.
7476
const neverRunBeforeHook: BeforeHook = () => false;
@@ -162,8 +164,8 @@ async function loadPluginImpl(path: string, packageName?: string): Promise<Plugi
162164
}
163165
}
164166

165-
// Create `RuleAndContext` object for rule.
166-
const ruleAndContext: RuleAndContext = {
167+
// Create `RuleDetails` object for rule.
168+
const ruleDetails: RuleDetails = {
167169
rule: rule as CreateRule, // Could also be `CreateOnceRule`, but just to satisfy type checker
168170
context: null, // Filled in below
169171
isFixable,
@@ -176,8 +178,8 @@ async function loadPluginImpl(path: string, packageName?: string): Promise<Plugi
176178
};
177179

178180
// Create `Context` object for rule. This will be re-used for every file.
179-
const context = createContext(`${pluginName}/${ruleName}`, ruleAndContext);
180-
(ruleAndContext as Writable<RuleAndContext>).context = context;
181+
const context = createContext(`${pluginName}/${ruleName}`, ruleDetails);
182+
(ruleDetails as Writable<RuleDetails>).context = context;
181183

182184
if ('createOnce' in rule) {
183185
// TODO: Compile visitor object to array here, instead of repeating compilation on each file
@@ -203,12 +205,12 @@ async function loadPluginImpl(path: string, packageName?: string): Promise<Plugi
203205
afterHook = null;
204206
}
205207

206-
(ruleAndContext as CreateOnceRuleAndContext).visitor = visitor;
207-
(ruleAndContext as CreateOnceRuleAndContext).beforeHook = beforeHook;
208-
(ruleAndContext as CreateOnceRuleAndContext).afterHook = afterHook;
208+
(ruleDetails as CreateOnceRuleDetails).visitor = visitor;
209+
(ruleDetails as CreateOnceRuleDetails).beforeHook = beforeHook;
210+
(ruleDetails as CreateOnceRuleDetails).afterHook = afterHook;
209211
}
210212

211-
registeredRules.push(ruleAndContext);
213+
registeredRules.push(ruleDetails);
212214
}
213215

214216
return { name: pluginName, offset, ruleNames };

0 commit comments

Comments
 (0)