Skip to content

Commit fa3b070

Browse files
committed
refactor(linter/plugins): prepare for rule options (#16158)
Preparatory work for supporting rule options. Store options for all rules in an `allOptions` array. Currently this array only contains a single value for empty options, but in future we'll populate it with options extracted from configs, sent over from Rust side. Am adding this now, before full implementation (#14825), as it's required for rule tester.
1 parent 3543adf commit fa3b070

File tree

5 files changed

+37
-14
lines changed

5 files changed

+37
-14
lines changed

apps/oxlint/src-js/index.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ import type { SetNullable } from "./utils/types.ts";
1010
export type * as ESTree from "./generated/types.d.ts";
1111
export type { Context, LanguageOptions } from "./plugins/context.ts";
1212
export type { Fix, Fixer, FixFn } from "./plugins/fix.ts";
13-
export type { CreateOnceRule, CreateRule, Options, Plugin, Rule } from "./plugins/load.ts";
13+
export type { CreateOnceRule, CreateRule, Plugin, Rule } from "./plugins/load.ts";
14+
export type { Options } from "./plugins/options.ts";
1415
export type { Diagnostic, Suggestion } from "./plugins/report.ts";
1516
export type {
1617
Definition,

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

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ import { report } from "./report.js";
3131
import { settings, initSettings } from "./settings.js";
3232
import { debugAssertIsNonNull } from "../utils/asserts.js";
3333

34-
import type { Options, RuleDetails } from "./load.ts";
34+
import type { RuleDetails } from "./load.ts";
35+
import type { Options } from "./options.ts";
3536
import type { Diagnostic } from "./report.ts";
3637
import type { Settings } from "./settings.ts";
3738
import type { SourceCode } from "./source_code.ts";
@@ -363,6 +364,7 @@ export function createContext(fullRuleName: string, ruleDetails: RuleDetails): R
363364
// Getter for rule options for this rule on this file
364365
get options(): Readonly<Options> {
365366
if (filePath === null) throw new Error("Cannot access `context.options` in `createOnce`");
367+
debugAssertIsNonNull(ruleDetails.options);
366368
return ruleDetails.options;
367369
},
368370
/**

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

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { setupFileContext, resetFileContext } from "./context.js";
22
import { registeredRules } from "./load.js";
3+
import { allOptions, DEFAULT_OPTIONS_ID } from "./options.js";
34
import { diagnostics } from "./report.js";
45
import { setSettingsForFile, resetSettings } from "./settings.js";
56
import { ast, initAst, resetSourceAndAst, setupSourceForFile } from "./source_code.js";
@@ -55,8 +56,11 @@ export function lintFile(
5556
ruleIds: number[],
5657
settingsJSON: string,
5758
): string {
59+
// TODO: Get `optionsIds` from Rust side
60+
const optionsIds = ruleIds.map((_) => DEFAULT_OPTIONS_ID);
61+
5862
try {
59-
lintFileImpl(filePath, bufferId, buffer, ruleIds, settingsJSON);
63+
lintFileImpl(filePath, bufferId, buffer, ruleIds, optionsIds, settingsJSON);
6064
return JSON.stringify({ Success: diagnostics });
6165
} catch (err) {
6266
return JSON.stringify({ Failure: getErrorMessage(err) });
@@ -72,6 +76,7 @@ export function lintFile(
7276
* @param bufferId - ID of buffer containing file data
7377
* @param buffer - Buffer containing file data, or `null` if buffer with this ID was previously sent to JS
7478
* @param ruleIds - IDs of rules to run on this file
79+
* @param optionsIds - IDs of options to use for rules on this file
7580
* @param settingsJSON - Stringified settings for this file
7681
* @returns Diagnostics to send back to Rust
7782
* @throws {Error} If any parameters are invalid
@@ -82,6 +87,7 @@ function lintFileImpl(
8287
bufferId: number,
8388
buffer: Uint8Array | null,
8489
ruleIds: number[],
90+
optionsIds: number[],
8591
settingsJSON: string,
8692
) {
8793
// If new buffer, add it to `buffers` array. Otherwise, get existing buffer from array.
@@ -141,6 +147,9 @@ function lintFileImpl(
141147
// Set `ruleIndex` for rule. It's used when sending diagnostics back to Rust.
142148
ruleDetails.ruleIndex = i;
143149

150+
// Set `options` for rule
151+
ruleDetails.options = allOptions[optionsIds[i]];
152+
144153
let { visitor } = ruleDetails;
145154
if (visitor === null) {
146155
// Rule defined with `create` method

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

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { getErrorMessage } from "../utils/utils.js";
55

66
import type { Writable } from "type-fest";
77
import type { Context } from "./context.ts";
8-
import type { JsonValue } from "./json.ts";
8+
import type { Options } from "./options.ts";
99
import type { RuleMeta } from "./rule_meta.ts";
1010
import type { AfterHook, BeforeHook, Visitor, VisitorWithHooks } from "./types.ts";
1111
import type { SetNullable } from "../utils/types.ts";
@@ -46,11 +46,6 @@ export interface CreateOnceRule {
4646
createOnce: (context: Context) => VisitorWithHooks;
4747
}
4848

49-
/**
50-
* Options for a rule on a file.
51-
*/
52-
export type Options = JsonValue[];
53-
5449
/**
5550
* Linter rule, context object, and other details of rule.
5651
* If `rule` has a `createOnce` method, the visitor it returns is stored in `visitor` property.
@@ -64,7 +59,7 @@ interface RuleDetailsBase {
6459
readonly messages: Readonly<Record<string, string>> | null;
6560
// Updated for each file
6661
ruleIndex: number;
67-
options: Readonly<Options>;
62+
options: Readonly<Options> | null; // Initially `null`, set to options object before linting a file
6863
}
6964

7065
interface CreateRuleDetails extends RuleDetailsBase {
@@ -91,9 +86,6 @@ export const registeredRules: RuleDetails[] = [];
9186
// `before` hook which makes rule never run.
9287
const neverRunBeforeHook: BeforeHook = () => false;
9388

94-
// Default rule options
95-
const DEFAULT_OPTIONS: Readonly<Options> = Object.freeze([]);
96-
9789
// Plugin details returned to Rust
9890
interface PluginDetails {
9991
// Plugin name
@@ -186,7 +178,7 @@ async function loadPluginImpl(path: string, packageName: string | null): Promise
186178
isFixable,
187179
messages,
188180
ruleIndex: 0,
189-
options: DEFAULT_OPTIONS,
181+
options: null,
190182
visitor: null,
191183
beforeHook: null,
192184
afterHook: null,
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/*
2+
* Options for rules.
3+
*/
4+
5+
import type { JsonValue } from "./json.ts";
6+
7+
/**
8+
* Options for a rule on a file.
9+
*/
10+
export type Options = JsonValue[];
11+
12+
// Default rule options
13+
const DEFAULT_OPTIONS: Readonly<Options> = Object.freeze([]);
14+
15+
// All rule options
16+
export const allOptions: Readonly<Options>[] = [DEFAULT_OPTIONS];
17+
18+
// Index into `allOptions` for default options
19+
export const DEFAULT_OPTIONS_ID = 0;

0 commit comments

Comments
 (0)