Skip to content

Conversation

@connorshea
Copy link
Contributor

The original rule has a config option in the format of ["error", "element"] or ["error", "syntax"]. We required a config object like ["error", { "mode": "element" }], which is technically incompatible for existing configs that get migrated to oxlint.

This fixes that in the generated docs, and also makes it work correctly in the oxlint config. We retain compatibility with the object syntax in case anyone has set up oxlint with it already, and I've added tests to ensure both formats of the config option work.

Generated docs now:

## Configuration

This rule accepts one of the following string values:

### `"syntax"`

This is the default mode. It will enforce the shorthand syntax for React fragments, with one exception.
Keys or attributes are not supported by the shorthand syntax, so the rule will not warn on standard-form fragments that use those.

Examples of **incorrect** code for this rule:
\```jsx
<React.Fragment><Foo /></React.Fragment>
\```

Examples of **correct** code for this rule:
\```jsx
<><Foo /></>
\```

\```jsx
<React.Fragment key="key"><Foo /></React.Fragment>
\```

### `"element"`

This mode enforces the standard form for React fragments.

Examples of **incorrect** code for this rule:
\```jsx
<><Foo /></>
\```

Examples of **correct** code for this rule:
\```jsx
<React.Fragment><Foo /></React.Fragment>
\```

\```jsx
<React.Fragment key="key"><Foo /></React.Fragment>
\```

The original rule has a config option in the format of `["error", "element"]` or `["error", "syntax"]`. We required a config object, which is technically incorrect.

This fixes that in the docs, but we still need to fix the code to accept a string argument instead of an object. I guess we have to make this backward-compatible and accept either?
@connorshea connorshea requested a review from camc314 as a code owner November 26, 2025 23:55
Copilot AI review requested due to automatic review settings November 26, 2025 23:55
@graphite-app
Copy link
Contributor

graphite-app bot commented Nov 26, 2025

How to use the Graphite Merge Queue

Add either label to this PR to merge it via the merge queue:

  • 0-merge - adds this PR to the back of the merge queue
  • hotfix - for urgent hot fixes, skip the queue and merge this PR next

You must have a Graphite account in order to use the merge queue. Sign up using this link.

An organization admin has enabled the Graphite Merge Queue in this repository.

Please do not merge from GitHub as this will restart CI on PRs being processed by the merge queue.

@github-actions github-actions bot added A-linter Area - Linter C-bug Category - Bug labels Nov 26, 2025
Copilot finished reviewing on behalf of connorshea November 26, 2025 23:57
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 fixes the react/jsx-fragments rule configuration to accept string arguments (e.g., ["syntax"] or ["element"]) for compatibility with the original ESLint rule, while maintaining backward compatibility with the previously-implemented object syntax (e.g., [{"mode": "element"}]).

Key Changes

  • Modified configuration parsing to support both string-based and object-based argument formats
  • Updated diagnostic messages and help text with improved formatting (backticks and periods)
  • Added comprehensive test cases for both configuration formats

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
crates/oxc_linter/src/rules/react/jsx_fragments.rs Refactored configuration parsing to accept both string and object arguments; improved diagnostic message formatting; added test cases for both configuration formats
crates/oxc_linter/src/snapshots/react_jsx_fragments.snap Updated test snapshots to reflect improved diagnostic message formatting with backticks and periods

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@codspeed-hq
Copy link

codspeed-hq bot commented Nov 27, 2025

CodSpeed Performance Report

Merging #16175 will not alter performance

Comparing react-fragment-string-arg (5379f68) with main (75249e0)1

Summary

✅ 4 untouched
⏩ 41 skipped2

Footnotes

  1. No successful run was found on main (91a1833) during the generation of this report, so 75249e0 was used instead as the comparison base. There might be some changes unrelated to this pull request in this report.

  2. 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.

Comment on lines 26 to 28
pub struct JsxFragments {
/// `syntax` mode:
///
mode: FragmentMode,
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you can support both by doing an enum, something like this i think

#[schemars(untagged)]
pub enum JsxFragments {
  StringFragmentMode(FragmentMode);
  ObjectFragmentMode({ mode: FragmentMode });
}

Copy link
Contributor Author

@connorshea connorshea Nov 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This almost works, but not quite, as it breaks the self.mode throughout the file. I can do it like this and it compiles, but unwrapping in from_configuration apparently panics in some cases.

#[derive(Debug, Clone, JsonSchema, Deserialize)]
#[serde(untagged)]
pub enum JsxFragments {
    Mode(FragmentMode),
    Object { mode: FragmentMode },
}

impl Default for JsxFragments {
    fn default() -> Self {
        JsxFragments::Mode(FragmentMode::Syntax)
    }
}

impl JsxFragments {
    fn mode(&self) -> FragmentMode {
        match self {
            JsxFragments::Mode(m) => *m,
            JsxFragments::Object { mode } => *mode,
        }
    }
}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unwrap_or_default in from_configuration fixes the panic! Although I have apparently broken the behavior in the tests somehow. 🤔

Copy link
Contributor

@PeterCardenas PeterCardenas Nov 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ah hm didn't consider that it makes the code weird, might need a helper function to convert the mode from the enum to the fragment mode
edit: oh i see that's what you did

Copy link
Contributor

@PeterCardenas PeterCardenas Nov 27, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

hm unwrap would be preferable i think to enforce that the config they pass in is correct. panicking is a bit harsh but that's a separate problem

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've pushed up a commit to use this pattern, although I'm not really sure it's particularly better than the previous version. I'll probably let cam decide on whatever is preferred.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

imo it's better because it codifies the config in the type rather than some adhoc deserialization code

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also you can get config doc generation hopefully that describes these two options if you put this enum in the config value

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unfortunately we'll need to make it possible to serialize a value of this type for the website to generate it, right now it can't handle an enum that is more than just simple types.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

DefaultRuleConfig definitely makes it better: 65f8344

@camc314 camc314 self-assigned this Nov 27, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-linter Area - Linter C-bug Category - Bug

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants