Skip to content

Commit c199e38

Browse files
committed
feat(linter): implement config for all tsgolint rules supporting options (#15659)
NOTE: This was largely generated by AI. I've looked over its work and it seems mostly correct, but please do apply some additional scrutiny. This is implementing the boilerplate to add all of the config parsing and docs generation code so we can fully support configuring these rules for tsgolint.
1 parent 7598b3e commit c199e38

18 files changed

+777
-151
lines changed

crates/oxc_linter/src/config/config_store.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1016,7 +1016,7 @@ mod test {
10161016
let base_rules = vec![
10171017
(RuleEnum::EslintCurly(EslintCurly::default()), AllowWarnDeny::Deny),
10181018
(
1019-
RuleEnum::TypescriptNoMisusedPromises(TypescriptNoMisusedPromises),
1019+
RuleEnum::TypescriptNoMisusedPromises(TypescriptNoMisusedPromises::default()),
10201020
AllowWarnDeny::Deny,
10211021
),
10221022
];

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

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,25 @@
11
use oxc_macros::declare_oxc_lint;
2+
use schemars::JsonSchema;
3+
use serde::{Deserialize, Serialize};
24

3-
use crate::rule::Rule;
5+
use crate::rule::{DefaultRuleConfig, Rule};
46

57
#[derive(Debug, Default, Clone)]
6-
pub struct NoConfusingVoidExpression;
8+
pub struct NoConfusingVoidExpression(Box<NoConfusingVoidExpressionConfig>);
9+
10+
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema, Default)]
11+
#[serde(rename_all = "camelCase", default)]
12+
pub struct NoConfusingVoidExpressionConfig {
13+
/// Whether to ignore arrow function shorthand that returns void.
14+
/// When true, allows expressions like `() => someVoidFunction()`.
15+
pub ignore_arrow_shorthand: bool,
16+
/// Whether to ignore expressions using the void operator.
17+
/// When true, allows `void someExpression`.
18+
pub ignore_void_operator: bool,
19+
/// Whether to ignore calling functions that are declared to return void.
20+
/// When true, allows expressions like `x = voidReturningFunction()`.
21+
pub ignore_void_returning_functions: bool,
22+
}
723

824
declare_oxc_lint!(
925
/// ### What it does
@@ -53,6 +69,19 @@ declare_oxc_lint!(
5369
typescript,
5470
pedantic,
5571
pending,
72+
config = NoConfusingVoidExpressionConfig,
5673
);
5774

58-
impl Rule for NoConfusingVoidExpression {}
75+
impl Rule for NoConfusingVoidExpression {
76+
fn from_configuration(value: serde_json::Value) -> Self {
77+
Self(Box::new(
78+
serde_json::from_value::<DefaultRuleConfig<NoConfusingVoidExpressionConfig>>(value)
79+
.unwrap_or_default()
80+
.into_inner(),
81+
))
82+
}
83+
84+
fn to_configuration(&self) -> Option<Result<serde_json::Value, serde_json::Error>> {
85+
Some(serde_json::to_value(&*self.0))
86+
}
87+
}

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

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,22 @@
11
use oxc_macros::declare_oxc_lint;
2+
use schemars::JsonSchema;
3+
use serde::{Deserialize, Serialize};
24

3-
use crate::rule::Rule;
5+
use crate::rule::{DefaultRuleConfig, Rule};
46

57
#[derive(Debug, Default, Clone)]
6-
pub struct NoDuplicateTypeConstituents;
8+
pub struct NoDuplicateTypeConstituents(Box<NoDuplicateTypeConstituentsConfig>);
9+
10+
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema, Default)]
11+
#[serde(rename_all = "camelCase", default)]
12+
pub struct NoDuplicateTypeConstituentsConfig {
13+
/// Whether to ignore duplicate types in intersection types.
14+
/// When true, allows `type T = A & A`.
15+
pub ignore_intersections: bool,
16+
/// Whether to ignore duplicate types in union types.
17+
/// When true, allows `type T = A | A`.
18+
pub ignore_unions: bool,
19+
}
720

821
declare_oxc_lint!(
922
/// ### What it does
@@ -51,6 +64,19 @@ declare_oxc_lint!(
5164
typescript,
5265
correctness,
5366
pending,
67+
config = NoDuplicateTypeConstituentsConfig,
5468
);
5569

56-
impl Rule for NoDuplicateTypeConstituents {}
70+
impl Rule for NoDuplicateTypeConstituents {
71+
fn from_configuration(value: serde_json::Value) -> Self {
72+
Self(Box::new(
73+
serde_json::from_value::<DefaultRuleConfig<NoDuplicateTypeConstituentsConfig>>(value)
74+
.unwrap_or_default()
75+
.into_inner(),
76+
))
77+
}
78+
79+
fn to_configuration(&self) -> Option<Result<serde_json::Value, serde_json::Error>> {
80+
Some(serde_json::to_value(&*self.0))
81+
}
82+
}

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

Lines changed: 4 additions & 106 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@ use oxc_macros::declare_oxc_lint;
22
use schemars::JsonSchema;
33
use serde::{Deserialize, Serialize};
44

5-
use crate::rule::{DefaultRuleConfig, Rule};
5+
use crate::{
6+
rule::{DefaultRuleConfig, Rule},
7+
utils::TypeOrValueSpecifier,
8+
};
69

710
#[derive(Debug, Default, Clone)]
811
pub struct NoFloatingPromises(Box<NoFloatingPromisesConfig>);
@@ -23,111 +26,6 @@ pub struct NoFloatingPromisesConfig {
2326
pub ignore_void: bool,
2427
}
2528

26-
/// Type or value specifier for matching specific declarations
27-
///
28-
/// Supports four types of specifiers:
29-
///
30-
/// 1. **String specifier** (deprecated): Universal match by name
31-
/// ```json
32-
/// "Promise"
33-
/// ```
34-
///
35-
/// 2. **File specifier**: Match types/values declared in local files
36-
/// ```json
37-
/// { "from": "file", "name": "MyType" }
38-
/// { "from": "file", "name": ["Type1", "Type2"] }
39-
/// { "from": "file", "name": "MyType", "path": "./types.ts" }
40-
/// ```
41-
///
42-
/// 3. **Lib specifier**: Match TypeScript built-in lib types
43-
/// ```json
44-
/// { "from": "lib", "name": "Promise" }
45-
/// { "from": "lib", "name": ["Promise", "PromiseLike"] }
46-
/// ```
47-
///
48-
/// 4. **Package specifier**: Match types/values from npm packages
49-
/// ```json
50-
/// { "from": "package", "name": "Observable", "package": "rxjs" }
51-
/// { "from": "package", "name": ["Observable", "Subject"], "package": "rxjs" }
52-
/// ```
53-
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
54-
#[serde(untagged)]
55-
pub enum TypeOrValueSpecifier {
56-
/// Universal string specifier - matches all types and values with this name regardless of declaration source.
57-
/// Not recommended - will be removed in a future major version.
58-
String(String),
59-
/// Describes specific types or values declared in local files.
60-
File(FileSpecifier),
61-
/// Describes specific types or values declared in TypeScript's built-in lib.*.d.ts types.
62-
Lib(LibSpecifier),
63-
/// Describes specific types or values imported from packages.
64-
Package(PackageSpecifier),
65-
}
66-
67-
/// Describes specific types or values declared in local files.
68-
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
69-
#[serde(rename_all = "camelCase")]
70-
pub struct FileSpecifier {
71-
/// Must be "file"
72-
from: FileFrom,
73-
/// The name(s) of the type or value to match
74-
name: NameSpecifier,
75-
/// Optional file path to specify where the types or values must be declared.
76-
/// If omitted, all files will be matched.
77-
#[serde(skip_serializing_if = "Option::is_none")]
78-
path: Option<String>,
79-
}
80-
81-
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
82-
#[serde(rename_all = "lowercase")]
83-
enum FileFrom {
84-
File,
85-
}
86-
87-
/// Describes specific types or values declared in TypeScript's built-in lib.*.d.ts types.
88-
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
89-
#[serde(rename_all = "camelCase")]
90-
pub struct LibSpecifier {
91-
/// Must be "lib"
92-
from: LibFrom,
93-
/// The name(s) of the lib type or value to match
94-
name: NameSpecifier,
95-
}
96-
97-
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
98-
#[serde(rename_all = "lowercase")]
99-
enum LibFrom {
100-
Lib,
101-
}
102-
103-
/// Describes specific types or values imported from packages.
104-
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
105-
#[serde(rename_all = "camelCase")]
106-
pub struct PackageSpecifier {
107-
/// Must be "package"
108-
from: PackageFrom,
109-
/// The name(s) of the type or value to match
110-
name: NameSpecifier,
111-
/// The package name to match
112-
package: String,
113-
}
114-
115-
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
116-
#[serde(rename_all = "lowercase")]
117-
enum PackageFrom {
118-
Package,
119-
}
120-
121-
/// Name specifier that can be a single string or array of strings
122-
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
123-
#[serde(untagged)]
124-
pub enum NameSpecifier {
125-
/// Single name
126-
Single(String),
127-
/// Multiple names
128-
Multiple(Vec<String>),
129-
}
130-
13129
impl Default for NoFloatingPromisesConfig {
13230
fn default() -> Self {
13331
Self {

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

Lines changed: 96 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,89 @@
11
use oxc_macros::declare_oxc_lint;
2+
use schemars::JsonSchema;
3+
use serde::{Deserialize, Serialize};
24

3-
use crate::rule::Rule;
5+
use crate::{
6+
rule::{DefaultRuleConfig, Rule},
7+
utils::default_true,
8+
};
9+
10+
fn default_checks_void_return() -> ChecksVoidReturn {
11+
ChecksVoidReturn::Boolean(true)
12+
}
413

514
#[derive(Debug, Default, Clone)]
6-
pub struct NoMisusedPromises;
15+
pub struct NoMisusedPromises(Box<NoMisusedPromisesConfig>);
16+
17+
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
18+
#[serde(rename_all = "camelCase", default)]
19+
#[expect(clippy::struct_field_names)]
20+
pub struct NoMisusedPromisesConfig {
21+
/// Whether to check if Promises are used in conditionals.
22+
/// When true, disallows using Promises in conditions where a boolean is expected.
23+
#[serde(default = "default_true")]
24+
pub checks_conditionals: bool,
25+
/// Whether to check if Promises are used in spread syntax.
26+
/// When true, disallows spreading Promise values.
27+
#[serde(default = "default_true")]
28+
pub checks_spreads: bool,
29+
/// Configuration for checking if Promises are returned in contexts expecting void.
30+
/// Can be a boolean to enable/disable all checks, or an object for granular control.
31+
#[serde(default = "default_checks_void_return")]
32+
pub checks_void_return: ChecksVoidReturn,
33+
}
34+
35+
impl Default for NoMisusedPromisesConfig {
36+
fn default() -> Self {
37+
Self {
38+
checks_conditionals: true,
39+
checks_spreads: true,
40+
checks_void_return: ChecksVoidReturn::Boolean(true),
41+
}
42+
}
43+
}
44+
45+
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
46+
#[serde(untagged)]
47+
pub enum ChecksVoidReturn {
48+
Boolean(bool),
49+
Options(ChecksVoidReturnOptions),
50+
}
51+
52+
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
53+
#[serde(rename_all = "camelCase", default)]
54+
pub struct ChecksVoidReturnOptions {
55+
/// Whether to check Promise-returning functions passed as arguments to void-returning functions.
56+
#[serde(default = "default_true")]
57+
pub arguments: bool,
58+
/// Whether to check Promise-returning functions in JSX attributes expecting void.
59+
#[serde(default = "default_true")]
60+
pub attributes: bool,
61+
/// Whether to check Promise-returning methods that override void-returning inherited methods.
62+
#[serde(default = "default_true")]
63+
pub inherited_methods: bool,
64+
/// Whether to check Promise-returning functions assigned to object properties expecting void.
65+
#[serde(default = "default_true")]
66+
pub properties: bool,
67+
/// Whether to check Promise values returned from void-returning functions.
68+
#[serde(default = "default_true")]
69+
pub returns: bool,
70+
/// Whether to check Promise-returning functions assigned to variables typed as void-returning.
71+
#[serde(default = "default_true")]
72+
pub variables: bool,
73+
}
74+
75+
impl Default for ChecksVoidReturnOptions {
76+
fn default() -> Self {
77+
Self {
78+
arguments: true,
79+
attributes: true,
80+
inherited_methods: true,
81+
properties: true,
82+
returns: true,
83+
variables: true,
84+
}
85+
}
86+
}
787

888
declare_oxc_lint!(
989
/// ### What it does
@@ -55,6 +135,19 @@ declare_oxc_lint!(
55135
typescript,
56136
pedantic,
57137
pending,
138+
config = NoMisusedPromisesConfig,
58139
);
59140

60-
impl Rule for NoMisusedPromises {}
141+
impl Rule for NoMisusedPromises {
142+
fn from_configuration(value: serde_json::Value) -> Self {
143+
Self(Box::new(
144+
serde_json::from_value::<DefaultRuleConfig<NoMisusedPromisesConfig>>(value)
145+
.unwrap_or_default()
146+
.into_inner(),
147+
))
148+
}
149+
150+
fn to_configuration(&self) -> Option<Result<serde_json::Value, serde_json::Error>> {
151+
Some(serde_json::to_value(&*self.0))
152+
}
153+
}

0 commit comments

Comments
 (0)