{"record":{"id":"e4c344801db0cd8f","repo":"oxc-project/oxc","slug":"capture-group-should-be-named","errorCode":null,"errorMessage":"Capture group should be named.","messagePattern":"Capture group should be named\\.","errorType":"validation","errorClass":"OxcDiagnostic","httpStatus":null,"severity":"warning","filePath":"crates/oxc_linter/src/rules/eslint/prefer_named_capture_group.rs","lineNumber":23,"sourceCode":"};\nuse oxc_diagnostics::OxcDiagnostic;\nuse oxc_macros::declare_oxc_lint;\nuse oxc_regular_expression::{\n    LiteralParser, Options,\n    ast::Pattern,\n    visit::{RegExpAstKind, Visit},\n};\nuse oxc_span::{GetSpan, Span};\n\nuse crate::{\n    AstNode,\n    context::LintContext,\n    rule::Rule,\n    utils::{is_regexp_callee, run_on_regex_node, static_string_value},\n};\n\nfn prefer_named_capture_group_diagnostic(span: Span, unnamed_count: usize) -> OxcDiagnostic {\n    OxcDiagnostic::warn(\"Capture group should be named.\")\n        .with_help(format!(\n            \"Use a named capture group like \\\"(?<name>...)\\\" — this regex has {unnamed_count} unnamed group{}.\",\n            if unnamed_count == 1 { \"\" } else { \"s\" }\n        ))\n        .with_label(span)\n}\n\n#[derive(Debug, Default, Clone)]\npub struct PreferNamedCaptureGroup;\n\ndeclare_oxc_lint!(\n    /// ### What it does\n    ///\n    /// Enforces the use of named capture groups in regular expressions.\n    ///\n    /// ### Why is this bad?\n    ///\n    /// Unnamed capturing groups (`(...)`) are referenced only by position, which","sourceCodeStart":5,"sourceCodeEnd":41,"githubUrl":"https://github.com/oxc-project/oxc/blob/e1e7af627c8843ab64044ed466b128fcc21a035b/crates/oxc_linter/src/rules/eslint/prefer_named_capture_group.rs#L5-L41","documentation":"Diagnostic from the oxlint `prefer-named-capture-group` rule. It fires when a regular expression literal or `new RegExp(...)` contains unnamed capture groups; the help text (prefer_named_capture_group.rs:23-31) reports the count of unnamed groups and shows the named syntax `(?<name>...)`. Named groups (ES2018) make match indices addressable by name instead of position.","triggerScenarios":"Enable the rule and write any regex with a bare group: `/@(\\w+)/`, `/(\\d{4})-(\\d{2})/`, or a dynamic regex passed through run_on_regex_node (imported in the file, which also runs on `new RegExp` strings when static).","commonSituations":"Date/URL parsing regexes written before ES2018; porting ESLint configs that include this rule; regexes shared with older tooling that cannot parse named groups; multi-group regexes where positional matches (`m[1]`, `m[2]`) silently break after group reordering — exactly the bug named groups prevent.","solutions":["Name every group: `(\\d+)` becomes `(?<num>\\d+)` and update consumers to `match.groups.num`.","Drop groups that do not need capturing: `(?:...)` for non-capturing grouping.","If you must support runtimes without named groups (or older transpilers), disable the rule for that file.","For `new RegExp` strings, apply the same naming inside the pattern string."],"exampleFix":"// before\nconst m = /(\\d{4})-(\\d{2})/.exec(s);\n\n// after\nconst m = /(?<year>\\d{4})-(?<month>\\d{2})/.exec(s);\nconst { year, month } = m.groups;","handlingStrategy":"validation","validationCode":"// pre-check regexes in review; lint gate:\n// package.json script: \"lint:regex\": \"oxlint --rules prefer-named-capture-group=warn src/\"","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Name every capture group when writing new regexes: `(?<year>\\\\d{4})`.","Use `(?:...)` for groups you never read back.","Consume matches via `match.groups.name` so group reordering cannot break code."],"tags":["oxlint","eslint","regex","es2018","modernization"],"backgroundTag":"eslint-named-capture-group","analyzedSha":"e1e7af627c8843ab64044ed466b128fcc21a035b","analyzedAt":"2026-08-20T07:01:07.079Z","contentChangedAt":"2026-08-20T07:01:07.079Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}