Skip to content

Conversation

@connorshea
Copy link
Contributor

@connorshea connorshea commented Dec 14, 2025

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.

Copilot AI review requested due to automatic review settings December 14, 2025 03:50
@connorshea connorshea requested a review from camc314 as a code owner December 14, 2025 03:50
@github-actions github-actions bot added A-linter Area - Linter C-cleanup Category - technical debt or refactoring. Solution not expected to change behavior labels Dec 14, 2025
Copy link

@charliecreates charliecreates bot left a 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
    ReturnAwait is a wrapper around Box<ReturnAwaitOption>, but this change makes from_configuration deserialize DefaultRuleConfig<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 to DefaultRuleConfig<RuleStruct> requires the rule struct itself to be Deserialize, which you added. However, these wrapper structs are pub struct X(Box<Config>). Deriving Deserialize for the wrapper means the JSON is now expected to deserialize into that wrapper shape (a single-element tuple struct) unless DefaultRuleConfig has 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 of Default implementations. That’s fine as long as the serde default behavior 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_configuration to parse the rule type directly (e.g. DefaultRuleConfig<NoMisusedPromises>), removing explicit Self(Box::new(...)) wrappers across many rules.
  • Removed serde per-field defaults (e.g. #[serde(default = "default_true")]) in favor of the config structs’ Default impls.
  • Updated derives on multiple rule structs to include Deserialize so DefaultRuleConfig<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 including array_type, no_misused_promises, restrict_plus_operands, return_await, etc.).

Copy link
Contributor

Copilot AI left a 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_configuration methods by passing the rule struct to DefaultRuleConfig instead of the config struct
  • Added Deserialize derive to rule structs that wrap Box<Config>
  • Replaced field-level #[serde(default = "default_true")] with struct-level #[serde(default)] and explicit Default trait 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-hq
Copy link

codspeed-hq bot commented Dec 14, 2025

CodSpeed Performance Report

Merging #16818 will not alter performance

Comparing more-more-default-rule-config (bd27000) with main (bbafba5)

Summary

✅ 4 untouched
⏩ 41 skipped1

Footnotes

  1. 41 benchmarks were skipped, so the baseline results were used instead. If they were deleted from the codebase, click here and archive them to remove them from the performance reports.

Copy link
Contributor

@camc314 camc314 left a 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

@connorshea connorshea requested a review from camc314 December 14, 2025 16:34
@camc314 camc314 self-assigned this Dec 14, 2025
@camc314 camc314 added the 0-merge Merge with Graphite Merge Queue label Dec 14, 2025
Copy link
Contributor

camc314 commented Dec 14, 2025

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.
@graphite-app graphite-app bot force-pushed the more-more-default-rule-config branch from bd27000 to 59d589d Compare December 14, 2025 16:35
@graphite-app graphite-app bot merged commit 59d589d into main Dec 14, 2025
20 checks passed
@graphite-app graphite-app bot deleted the more-more-default-rule-config branch December 14, 2025 16:40
@graphite-app graphite-app bot removed the 0-merge Merge with Graphite Merge Queue label Dec 14, 2025
graphite-app bot pushed a commit that referenced this pull request Dec 14, 2025
…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.
graphite-app bot pushed a commit that referenced this pull request Dec 14, 2025
…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.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-linter Area - Linter C-cleanup Category - technical debt or refactoring. Solution not expected to change behavior

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants