-
-
Notifications
You must be signed in to change notification settings - Fork 741
refactor(linter): Use DefaultRuleConfig more and simplify from_configuration for tsgolint rules #16818
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Overall the refactor is mechanically consistent, but it risks configuration compatibility changes in rules where from_configuration previously had custom parsing/fallback behavior (notably array_type) or where the rule wrapper type (ReturnAwait) may not deserialize identically to the prior config type. These are subtle but user-visible differences because they affect how invalid/unknown config values are handled. Consider adding targeted config parsing/round-trip tests or keeping the older parsing in the few cases where behavior is intentionally non-Serde-default.
Additional notes (3)
- Compatibility |
crates/oxc_linter/src/rules/typescript/return_await.rs:105-110
ReturnAwaitis a wrapper aroundBox<ReturnAwaitOption>, but this change makesfrom_configurationdeserializeDefaultRuleConfig<ReturnAwait>and then.into_inner().
That only works correctly if DefaultRuleConfig<ReturnAwait> deserializes into the wrapper shape (i.e. it can parse a config value into ReturnAwait), rather than the previous behavior which clearly parsed ReturnAwaitOption and then wrapped it.
Given the rule’s declare_oxc_lint!(..., config = ReturnAwaitOption, ...), it’s important that the JSON format expected by users remains the same (kebab-case string/enum form), and that to_configuration() continues to serialize ReturnAwaitOption (which it does). The risk here is an unintended config format regression if Deserialize for ReturnAwait doesn’t match the old representation exactly.
- Maintainability |
crates/oxc_linter/src/rules/typescript/no_confusing_void_expression.rs:5-10
Switching toDefaultRuleConfig<RuleStruct>requires the rule struct itself to beDeserialize, which you added. However, these wrapper structs arepub struct X(Box<Config>). DerivingDeserializefor the wrapper means the JSON is now expected to deserialize into that wrapper shape (a single-element tuple struct) unlessDefaultRuleConfighas custom logic to treat the rule as its config.
Given the intent described in the PR context, this likely depends on a DefaultRuleConfig implementation detail (e.g., deserializing via the rule’s inner config). If that assumption ever changes, config parsing will break in a non-obvious way. It’s worth making that coupling explicit via a small comment or a unit test.
- Maintainability |
crates/oxc_linter/src/rules/typescript/no_misused_promises.rs:10-10
You removed#[serde(default = "default_true")]in favor ofDefaultimplementations. That’s fine as long as the serdedefaultbehavior remains enabled for the struct (it is via#[serde(..., default)]).
However, for checks_void_return you kept a custom #[serde(default = "default_checks_void_return")] which defaults to Boolean(true). This is inconsistent with the rest of the config defaults which are expressed via Default impls. It also means serde-default behavior differs between top-level booleans and this field.
Not necessarily wrong, but it increases mental overhead and makes it easier to accidentally change default behavior later.
Summary of changes
Summary
This PR refactors several tsgolint-based TypeScript rules to rely more heavily on DefaultRuleConfig<T> and to simplify Rule::from_configuration implementations.
Key changes
- Switched
from_configurationto parse the rule type directly (e.g.DefaultRuleConfig<NoMisusedPromises>), removing explicitSelf(Box::new(...))wrappers across many rules. - Removed
serdeper-field defaults (e.g.#[serde(default = "default_true")]) in favor of the config structs’Defaultimpls. - Updated derives on multiple rule structs to include
DeserializesoDefaultRuleConfig<RuleType>can deserialize the rule wrapper. - Minor refactors/formatting:
no_non_null_asserted_nullish_coalescing: moved diagnostic helper to the top for consistency.- Wrapped long doc comments in a couple rules for readability.
Files touched
crates/oxc_linter/src/rules/typescript/*(multiple rules includingarray_type,no_misused_promises,restrict_plus_operands,return_await, etc.).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR refactors TypeScript linter rules to use DefaultRuleConfig<RuleStruct> instead of DefaultRuleConfig<ConfigStruct>, simplifying the from_configuration implementations. The changes eliminate the need for explicit Self(Box::new()) wrapping by having DefaultRuleConfig deserialize the rule struct directly.
Key changes:
- Simplified
from_configurationmethods by passing the rule struct toDefaultRuleConfiginstead of the config struct - Added
Deserializederive to rule structs that wrapBox<Config> - Replaced field-level
#[serde(default = "default_true")]with struct-level#[serde(default)]and explicitDefaulttrait implementations - Minor documentation formatting improvements (line wrapping and backtick usage)
Reviewed changes
Copilot reviewed 11 out of 11 changed files in this pull request and generated no comments.
Show a summary per file
| File | Description |
|---|---|
return_await.rs |
Simplified from_configuration using DefaultRuleConfig<ReturnAwait>, added Deserialize to rule struct, improved doc formatting |
restrict_plus_operands.rs |
Simplified from_configuration, removed default_true helper usage in favor of Default trait impl |
promise_function_async.rs |
Simplified from_configuration, removed default_true helper usage in favor of Default trait impl |
prefer_promise_reject_errors.rs |
Simplified from_configuration using new pattern |
no_unnecessary_type_assertion.rs |
Simplified from_configuration using new pattern |
no_unnecessary_boolean_literal_compare.rs |
Simplified from_configuration, removed default_true helper usage |
no_non_null_asserted_nullish_coalescing.rs |
Moved diagnostic function before struct definition (code organization only) |
no_misused_promises.rs |
Simplified from_configuration, removed default_true usage, improved doc formatting with backticks |
no_duplicate_type_constituents.rs |
Simplified from_configuration using new pattern |
no_confusing_void_expression.rs |
Simplified from_configuration using new pattern |
array_type.rs |
Replaced manual config parsing with simplified DefaultRuleConfig pattern |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
CodSpeed Performance ReportMerging #16818 will not alter performanceComparing Summary
Footnotes
|
camc314
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
question about default_true
Merge activity
|
…uration for tsgolint rules (#16818) This removes the `Self(Box::new())` wrapper for various tsgolint-based rules in order to simplify the implementation of the `from_configuration` method for those rules. If I understand correctly, the box wrapping is still used, it's just not referenced explicitly in the `from_configuration` method for these rules anymore, as we've moved the `DefaultRuleConfig<>` from taking the config object over to taking the rule itself. This PR also removes various uses of `#[serde(default = "default_true")]`, as it's unnecessary when Default is defined. Will wait to merge this until cam (either of them 😛) can review this and confirm that I'm not about to break anything here. But I'm fairly confident this should not cause any problems.
bd27000 to
59d589d
Compare
…les. (#16851) This updates all the tsgolint rules that were using a box wrapper + `DefaultRuleConfig<RuleNameConfig>`. And also one react rule. The default_true utility is also unneeded, as the defaults will work fine without it. The `impl Default` sets the defaults for the relevant fields on each of these rules. Basically the same kind of change as #16818.
…les. (#16851) This updates all the tsgolint rules that were using a box wrapper + `DefaultRuleConfig<RuleNameConfig>`. And also one react rule. The default_true utility is also unneeded, as the defaults will work fine without it. The `impl Default` sets the defaults for the relevant fields on each of these rules. Basically the same kind of change as #16818.
This removes the
Self(Box::new())wrapper for various tsgolint-based rules in order to simplify the implementation of thefrom_configurationmethod for those rules. If I understand correctly, the box wrapping is still used, it's just not referenced explicitly in thefrom_configurationmethod for these rules anymore, as we've moved theDefaultRuleConfig<>from taking the config object over to taking the rule itself.This PR also removes various uses of
#[serde(default = "default_true")], as it's unnecessary when Default is defined.Will wait to merge this until cam (either of them 😛) can review this and confirm that I'm not about to break anything here. But I'm fairly confident this should not cause any problems.