Skip to content

Commit 6dbfe29

Browse files
committed
feat(linter): implement config for all tsgolint rules supporting options
1 parent 07e377e commit 6dbfe29

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)