Skip to content

Commit 4ba1bca

Browse files
docs(linter): Add configuration option docs for 5 rules. (#15199)
Part of #14743. - typescript/no-namespace - react/exhaustive-deps - typescript/array-type - promise/always-return - eslint/curly Generated docs: ```md ## Configuration This rule accepts a configuration object with the following properties: ### consistent type: `boolean` default: `false` Whether to enforce consistent use of curly braces in if-else chains. ### curlyType type: `"all" | "multi" | "multi-line" | "multi-or-nest"` default: `"all"` Which type of curly brace enforcement to use. - `"all"`: require braces in all cases - `"multi"`: require braces only for multi-statement blocks - `"multi-line"`: require braces only for multi-line blocks - `"multi-or-nest"`: require braces for multi-line blocks or when nested ``` ```md ## Configuration This rule accepts a configuration object with the following properties: ### default type: `"array" | "array-simple" | "generic"` default: `"array"` The array type expected for mutable cases. ### readonly type: `"array" | "array-simple" | "generic"` default: `null` The array type expected for readonly cases. If omitted, the value for `default` will be used. ``` ```md ## Configuration This rule accepts a configuration object with the following properties: ### ignoreAssignmentVariable type: `string[]` default: `["globalThis"]` You can pass an `{ ignoreAssignmentVariable: [] }` as an option to this rule with a list of variable names so that the last `then()` callback in a promise chain does not warn if it does an assignment to a global variable. Default is `["globalThis"]`. \```javascript /* eslint promise/always-return: ["error", { ignoreAssignmentVariable: ["globalThis"] }] */ // OK promise.then((x) => { globalThis = x }) promise.then((x) => { globalThis.x = x }) // OK promise.then((x) => { globalThis.x.y = x }) // NG promise.then((x) => { anyOtherVariable = x }) // NG promise.then((x) => { anyOtherVariable.x = x }) // NG promise.then((x) => { x() }) \``` ### ignoreLastCallback type: `boolean` default: `false` You can pass an `{ ignoreLastCallback: true }` as an option to this rule so that the last `then()` callback in a promise chain does not warn if it does not have a `return`. Default is `false`. \```javascript // OK promise.then((x) => { console.log(x) }) // OK void promise.then((x) => { console.log(x) }) // OK await promise.then((x) => { console.log(x) }) promise // NG .then((x) => { console.log(x) }) // OK .then((x) => { console.log(x) }) // NG const v = promise.then((x) => { console.log(x) }) // NG const v = await promise.then((x) => { console.log(x) }) function foo() { // NG return promise.then((x) => { console.log(x) }) } \``` ``` ```md ## Configuration This rule accepts a configuration object with the following properties: ### additionalHooks type: `[ string, null ]` default: `null` Optionally provide a regex of additional hooks to check. ``` ```md ## Configuration This rule accepts a configuration object with the following properties: ### allowDeclarations type: `boolean` default: `false` Whether to allow declare with custom TypeScript namespaces. Examples of **incorrect** code for this rule when `{ "allowDeclarations": true }` \```typescript module foo {} namespace foo {} \``` Examples of **correct** code for this rule when `{ "allowDeclarations": true }` \```typescript declare module 'foo' {} declare module foo {} declare namespace foo {} declare global { namespace foo {} } declare module foo { namespace foo {} } \``` Examples of **incorrect** code for this rule when `{ "allowDeclarations": false }` \```typescript module foo {} namespace foo {} declare module foo {} declare namespace foo {} \``` Examples of **correct** code for this rule when `{ "allowDeclarations": false }` \```typescript declare module 'foo' {} \``` ### allowDefinitionFiles type: `boolean` default: `true` Examples of **incorrect** code for this rule when `{ "allowDefinitionFiles": true }` \```typescript // if outside a d.ts file module foo {} namespace foo {} // if outside a d.ts file module foo {} namespace foo {} declare module foo {} declare namespace foo {} \``` Examples of **correct** code for this rule when `{ "allowDefinitionFiles": true }` \```typescript declare module 'foo' {} // anything inside a d.ts file \``` ``` --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
1 parent ab46187 commit 4ba1bca

File tree

5 files changed

+142
-193
lines changed

5 files changed

+142
-193
lines changed

crates/oxc_linter/src/rules/eslint/curly.rs

Lines changed: 15 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ use oxc_ast::{AstKind, ast::IfStatement, ast::Statement};
44
use oxc_diagnostics::OxcDiagnostic;
55
use oxc_macros::declare_oxc_lint;
66
use oxc_span::{GetSpan, Span};
7+
use schemars::JsonSchema;
8+
use serde::{Deserialize, Serialize};
79
use serde_json::Value;
810

911
fn curly_diagnostic(span: Span, keyword: &str, expected: bool) -> OxcDiagnostic {
@@ -15,7 +17,8 @@ fn curly_diagnostic(span: Span, keyword: &str, expected: bool) -> OxcDiagnostic
1517
OxcDiagnostic::warn(message).with_label(span)
1618
}
1719

18-
#[derive(Debug, Default, Clone, PartialEq)]
20+
#[derive(Debug, Default, Clone, PartialEq, JsonSchema, Deserialize, Serialize)]
21+
#[serde(rename_all = "kebab-case")]
1922
enum CurlyType {
2023
#[default]
2124
All,
@@ -38,9 +41,17 @@ impl CurlyType {
3841
#[derive(Debug, Default, Clone)]
3942
pub struct Curly(CurlyConfig);
4043

41-
#[derive(Debug, Clone)]
44+
#[derive(Debug, Clone, JsonSchema, Deserialize, Serialize)]
45+
#[serde(rename_all = "camelCase", default)]
4246
pub struct CurlyConfig {
47+
/// Which type of curly brace enforcement to use.
48+
///
49+
/// - `"all"`: require braces in all cases
50+
/// - `"multi"`: require braces only for multi-statement blocks
51+
/// - `"multi-line"`: require braces only for multi-line blocks
52+
/// - `"multi-or-nest"`: require braces for multi-line blocks or when nested
4353
curly_type: CurlyType,
54+
/// Whether to enforce consistent use of curly braces in if-else chains.
4455
consistent: bool,
4556
}
4657

@@ -70,32 +81,6 @@ declare_oxc_lint!(
7081
/// It can also lead to bugs if additional statements are added later without properly enclosing them in braces.
7182
/// Using curly braces consistently makes the code safer and easier to modify.
7283
///
73-
/// ### Options
74-
///
75-
/// First option:
76-
/// - Type: `string`
77-
/// - Default: `"all"`
78-
/// - Possible values:
79-
/// - `"all"`: require braces in all cases
80-
/// - `"multi"`: require braces only for multi-statement blocks
81-
/// - `"multi-line"`: require braces only for multi-line blocks
82-
/// - `"multi-or-nest"`: require braces for multi-line blocks or when nested
83-
///
84-
/// Second option:
85-
/// - Type: `string`
86-
/// - Default: `undefined`
87-
/// - Possible values:
88-
/// - `"consistent"`: require braces if any other branch in the `if-else` chain has braces
89-
///
90-
/// Note : The second option can only be used in conjunction with the first option.
91-
///
92-
/// Example configuration:
93-
/// ```json
94-
/// {
95-
/// "curly": ["error", "multi-or-nest", "consistent"]
96-
/// }
97-
/// ```
98-
///
9984
/// ### Examples
10085
///
10186
/// #### `"all"` (default)
@@ -272,7 +257,8 @@ declare_oxc_lint!(
272257
Curly,
273258
eslint,
274259
style,
275-
fix
260+
fix,
261+
config = CurlyConfig,
276262
);
277263

278264
impl Rule for Curly {

crates/oxc_linter/src/rules/promise/always_return.rs

Lines changed: 68 additions & 77 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use oxc_macros::declare_oxc_lint;
1616
use oxc_semantic::NodeId;
1717
use oxc_span::{GetSpan, Span};
1818
use rustc_hash::FxHashSet;
19+
use schemars::JsonSchema;
1920
use serde::Deserialize;
2021

2122
use crate::{AstNode, context::LintContext, rule::Rule};
@@ -27,81 +28,9 @@ fn always_return_diagnostic(span: Span) -> OxcDiagnostic {
2728
#[derive(Debug, Default, Clone)]
2829
pub struct AlwaysReturn(Box<AlwaysReturnConfig>);
2930

30-
#[derive(Debug, Clone, Deserialize)]
31-
#[serde(rename_all = "camelCase")]
31+
#[derive(Debug, Clone, JsonSchema, Deserialize)]
32+
#[serde(rename_all = "camelCase", default)]
3233
pub struct AlwaysReturnConfig {
33-
#[serde(default)]
34-
ignore_last_callback: bool,
35-
#[serde(default)]
36-
ignore_assignment_variable: FxHashSet<Cow<'static, str>>,
37-
}
38-
39-
impl Default for AlwaysReturnConfig {
40-
fn default() -> Self {
41-
Self {
42-
ignore_last_callback: false,
43-
ignore_assignment_variable: FxHashSet::from_iter([Cow::Borrowed("globalThis")]),
44-
}
45-
}
46-
}
47-
48-
impl std::ops::Deref for AlwaysReturn {
49-
type Target = AlwaysReturnConfig;
50-
51-
fn deref(&self) -> &Self::Target {
52-
&self.0
53-
}
54-
}
55-
56-
declare_oxc_lint!(
57-
/// ### What it does
58-
///
59-
/// Require returning inside each `then()` to create readable and reusable Promise chains.
60-
/// We also allow someone to throw inside a `then()` which is essentially the same as return `Promise.reject()`.
61-
///
62-
/// ### Why is this bad?
63-
///
64-
/// Broken Promise Chain.
65-
/// Inside the first `then()` callback, a function is called but not returned.
66-
/// This causes the next `then()` in the chain to execute immediately without waiting for the called function to complete.
67-
///
68-
/// ### Examples
69-
///
70-
/// Examples of **incorrect** code for this rule:
71-
/// ```javascript
72-
/// myPromise.then(function (val) {})
73-
/// myPromise.then(() => {
74-
/// doSomething()
75-
/// })
76-
/// myPromise.then((b) => {
77-
/// if (b) {
78-
/// return 'yes'
79-
/// } else {
80-
/// forgotToReturn()
81-
/// }
82-
/// })
83-
/// ```
84-
///
85-
/// Examples of **correct** code for this rule:
86-
/// ```javascript
87-
/// myPromise.then((val) => val * 2)
88-
/// myPromise.then(function (val) {
89-
/// return val * 2
90-
///})
91-
/// myPromise.then(doSomething) // could be either
92-
/// myPromise.then((b) => {
93-
/// if (b) {
94-
/// return 'yes'
95-
/// } else {
96-
/// return 'no'
97-
/// }
98-
/// })
99-
/// ```
100-
///
101-
/// ### Options
102-
///
103-
/// #### `ignoreLastCallback`
104-
///
10534
/// You can pass an `{ ignoreLastCallback: true }` as an option to this rule so that
10635
/// the last `then()` callback in a promise chain does not warn if it does not have
10736
/// a `return`. Default is `false`.
@@ -145,9 +74,7 @@ declare_oxc_lint!(
14574
/// })
14675
/// }
14776
/// ```
148-
///
149-
/// #### `ignoreAssignmentVariable`
150-
///
77+
ignore_last_callback: bool,
15178
/// You can pass an `{ ignoreAssignmentVariable: [] }` as an option to this rule
15279
/// with a list of variable names so that the last `then()` callback in a promise
15380
/// chain does not warn if it does an assignment to a global variable. Default is
@@ -185,10 +112,74 @@ declare_oxc_lint!(
185112
/// x()
186113
/// })
187114
/// ```
115+
ignore_assignment_variable: FxHashSet<Cow<'static, str>>,
116+
}
117+
118+
impl Default for AlwaysReturnConfig {
119+
fn default() -> Self {
120+
Self {
121+
ignore_last_callback: false,
122+
ignore_assignment_variable: FxHashSet::from_iter([Cow::Borrowed("globalThis")]),
123+
}
124+
}
125+
}
126+
127+
impl std::ops::Deref for AlwaysReturn {
128+
type Target = AlwaysReturnConfig;
188129

130+
fn deref(&self) -> &Self::Target {
131+
&self.0
132+
}
133+
}
134+
135+
declare_oxc_lint!(
136+
/// ### What it does
137+
///
138+
/// Require returning inside each `then()` to create readable and reusable Promise chains.
139+
/// We also allow someone to throw inside a `then()` which is essentially the same as return `Promise.reject()`.
140+
///
141+
/// ### Why is this bad?
142+
///
143+
/// Broken Promise Chain.
144+
/// Inside the first `then()` callback, a function is called but not returned.
145+
/// This causes the next `then()` in the chain to execute immediately without waiting for the called function to complete.
146+
///
147+
/// ### Examples
148+
///
149+
/// Examples of **incorrect** code for this rule:
150+
/// ```javascript
151+
/// myPromise.then(function (val) {})
152+
/// myPromise.then(() => {
153+
/// doSomething()
154+
/// })
155+
/// myPromise.then((b) => {
156+
/// if (b) {
157+
/// return 'yes'
158+
/// } else {
159+
/// forgotToReturn()
160+
/// }
161+
/// })
162+
/// ```
163+
///
164+
/// Examples of **correct** code for this rule:
165+
/// ```javascript
166+
/// myPromise.then((val) => val * 2)
167+
/// myPromise.then(function (val) {
168+
/// return val * 2
169+
/// })
170+
/// myPromise.then(doSomething) // could be either
171+
/// myPromise.then((b) => {
172+
/// if (b) {
173+
/// return 'yes'
174+
/// } else {
175+
/// return 'no'
176+
/// }
177+
/// })
178+
/// ```
189179
AlwaysReturn,
190180
promise,
191181
suspicious,
182+
config = AlwaysReturnConfig,
192183
);
193184

194185
const PROCESS_METHODS: [&str; 2] = ["exit", "abort"];

crates/oxc_linter/src/rules/react/exhaustive_deps.rs

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use std::{borrow::Cow, hash::Hash};
33
use itertools::Itertools;
44
use lazy_regex::Regex;
55
use rustc_hash::FxHashSet;
6+
use schemars::JsonSchema;
67
use serde::{Deserialize, Serialize};
78

89
use oxc_ast::{
@@ -207,9 +208,10 @@ pub struct ExhaustiveDepsConfig {
207208
additional_hooks: Option<Regex>,
208209
}
209210

210-
#[derive(Debug, Deserialize, Serialize)]
211+
#[derive(Debug, Default, Deserialize, Serialize, JsonSchema)]
212+
#[serde(rename_all = "camelCase", default)]
211213
struct ExhaustiveDepsConfigJson {
212-
#[serde(rename = "additionalHooks")]
214+
/// Optionally provide a regex of additional hooks to check.
213215
additional_hooks: Option<String>,
214216
}
215217

@@ -244,24 +246,11 @@ declare_oxc_lint!(
244246
/// return <div />;
245247
/// }
246248
/// ```
247-
///
248-
/// ### Options
249-
///
250-
/// #### additionalHooks
251-
///
252-
/// `{ type: string }`
253-
///
254-
/// Optionally provide a regex of additional hooks to check.
255-
///
256-
/// Example:
257-
///
258-
/// ```json
259-
/// { "react/exhaustive-deps": ["error", { "additionalHooks": "useSpecialEffect" }] }
260-
/// ```
261249
ExhaustiveDeps,
262250
react,
263251
correctness,
264-
safe_fixes_and_dangerous_suggestions
252+
safe_fixes_and_dangerous_suggestions,
253+
config = ExhaustiveDepsConfigJson,
265254
);
266255

267256
const HOOKS_USELESS_WITHOUT_DEPENDENCIES: [&str; 2] = ["useCallback", "useMemo"];

crates/oxc_linter/src/rules/typescript/array_type.rs

Lines changed: 12 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ use oxc_diagnostics::OxcDiagnostic;
99
use oxc_macros::declare_oxc_lint;
1010
use oxc_semantic::AstNode;
1111
use oxc_span::Span;
12+
use schemars::JsonSchema;
13+
use serde::{Deserialize, Serialize};
1214

1315
use crate::{
1416
ast_util::outermost_paren_parent,
@@ -67,27 +69,11 @@ declare_oxc_lint!(
6769
/// const c: string[] = ['a', 'b'];
6870
/// const d: MyType[] = ['a', 'b'];
6971
/// ```
70-
///
71-
/// ### Options
72-
///
73-
/// ```json
74-
/// {
75-
/// "typescript/array-type": ["error", { "default": "array", "readonly": "array" }]
76-
/// }
77-
/// ```
78-
/// - `default`: The array type expected for mutable cases.
79-
/// - `readonly`: The array type expected for readonly cases. If omitted, the value for `default` will be used.
80-
///
81-
/// Both `default` and `readonly` can be one of:
82-
/// - `"array"`
83-
/// - `"generic"`
84-
/// - `"array-simple"`
85-
///
86-
/// The default config will enforce that all mutable and readonly arrays use the 'array' syntax.
8772
ArrayType,
8873
typescript,
8974
style,
90-
fix
75+
fix,
76+
config = ArrayTypeConfig,
9177
);
9278

9379
fn generic(readonly_prefix: &str, name: &str, type_name: &str, span: Span) -> OxcDiagnostic {
@@ -123,11 +109,13 @@ fn array_simple(
123109
.with_label(span)
124110
}
125111

126-
#[derive(Debug, Default, Clone)]
112+
#[derive(Debug, Default, Clone, JsonSchema, Deserialize, Serialize)]
113+
#[serde(rename_all = "camelCase", default)]
127114
pub struct ArrayTypeConfig {
128-
// The array type expected for mutable cases.
115+
/// The array type expected for mutable cases.
129116
default: ArrayOption,
130-
// The array type expected for readonly cases. If omitted, the value for `default` will be used.
117+
/// The array type expected for readonly cases. If omitted, the value for `default` will be used.
118+
#[schemars(with = "ArrayOption")]
131119
readonly: Option<ArrayOption>,
132120
}
133121

@@ -138,7 +126,9 @@ impl std::ops::Deref for ArrayType {
138126
&self.0
139127
}
140128
}
141-
#[derive(Debug, Default, Clone)]
129+
130+
#[derive(Debug, Default, Clone, JsonSchema, Deserialize, Serialize)]
131+
#[serde(rename_all = "kebab-case")]
142132
pub enum ArrayOption {
143133
#[default]
144134
Array,

0 commit comments

Comments
 (0)