fix: prevent EXPORT_DECAL_RE from crossing newlines into multi-line object literals#347
Conversation
…bject literals
The extraNames capture group in EXPORT_DECAL_RE used \s* and [\s\w:[\]{}]*
which allowed the regex to span across newlines, causing object property keys
(e.g. `actions`) in multi-line call arguments to be picked up as false-positive
export names.
Replace \s* with [^\S\n]* and drop \s from [\s\w:[\]{}]* so the group only
matches horizontal whitespace, keeping it confined to a single line.
Fixes unjs#303, related to nuxt/nuxt#34997
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
ℹ️ Recent review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughThis PR tightens the ChangesExport Pattern Refinement
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Suggested labels
Suggested reviewers
Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Tip 💬 Introducing Slack Agent: The best way for teams to turn conversations into code.Slack Agent is built on CodeRabbit's deep understanding of your code, so your team can collaborate across the entire SDLC without losing context.
Built for teams:
One agent for your entire SDLC. Right inside Slack. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
test/exports.test.ts (1)
469-475: ⚡ Quick winRegression test placed in the wrong
describeblockThe new test exercises
findExports, but it sits insidedescribe("resolveModuleExportNames"). It should be moved intodescribe("findExports")alongside the other single-export declaration tests.♻️ Suggested move
Remove lines 469–475 from the
resolveModuleExportNamesblock and add them to thefindExportsdescribe block (before its closing}):- // https://github.com/unjs/mlly/issues/303 - it("does not pick up object property keys from multi-line object literals as extra export names", () => { - const code = `export const useStore = defineStore('id', {\n state: () => ({}),\n actions: { foo() {} }\n})`; - const matches = findExports(code); - expect(matches).toHaveLength(1); - expect(matches[0].names).toEqual(["useStore"]); - });// Inside describe("findExports") — before its closing }); + // https://github.com/unjs/mlly/issues/303 + it("does not pick up object property keys from multi-line object literals as extra export names", () => { + const code = `export const useStore = defineStore('id', {\n state: () => ({}),\n actions: { foo() {} }\n})`; + const matches = findExports(code); + expect(matches).toHaveLength(1); + expect(matches[0].names).toEqual(["useStore"]); + });🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@test/exports.test.ts` around lines 469 - 475, The test for "does not pick up object property keys..." is exercising findExports but was added under describe("resolveModuleExportNames"); move that it(...) block out of the resolveModuleExportNames describe and insert it into the describe("findExports") block (place it with the other single-export declaration tests, before that describe's closing brace) so the test logically lives with other findExports tests and uses the same context for findExports.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/analyze.ts`:
- Line 262: The EXPORT_DECAL_RE regex no longer matches comma-separated sibling
bindings that occur on subsequent lines (e.g., "export const a = longFn(...), b
= 1" where b is on the next line); add a concise comment immediately above the
EXPORT_DECAL_RE declaration explaining this limitation: note that extraNames is
intentionally constrained to not cross newlines, so multi-line comma-separated
export bindings will be missed and are a known limitation (include an example
and rationale that this avoids false positives), and reference the
EXPORT_DECAL_RE symbol and the named capture groups (declaration, name,
extraNames) so future maintainers can find and adjust the regex if needed.
---
Nitpick comments:
In `@test/exports.test.ts`:
- Around line 469-475: The test for "does not pick up object property keys..."
is exercising findExports but was added under
describe("resolveModuleExportNames"); move that it(...) block out of the
resolveModuleExportNames describe and insert it into the describe("findExports")
block (place it with the other single-export declaration tests, before that
describe's closing brace) so the test logically lives with other findExports
tests and uses the same context for findExports.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 85bae9b0-059b-4707-b123-4df8ad1f250b
📒 Files selected for processing (2)
src/analyze.tstest/exports.test.ts
- Move regression test into describe("findExports") where it belongs
- Add comment on EXPORT_DECAL_RE documenting the known limitation that
sibling bindings starting on a new line won't be captured by extraNames,
with rationale and issue reference (unjs#303)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Summary
Fixes #303, related to nuxt/nuxt#34997
findExportsincorrectly picks up object property keys as named exports when scanning multi-line TypeScript files. TheextraNamescapture group inEXPORT_DECAL_REused\s*and[\s\w:[\]{}]*, which allowed the regex to span across newlines into multi-line object literals passed as call arguments.Reproduction:
Changes
src/analyze.ts: InEXPORT_DECAL_RE, change theextraNamesgroup:\s*→[^\S\n]*(horizontal whitespace only — no newlines after comma)[\s\w:[\]{}]*→[\w:[\]{}]*(drop\sto prevent crossing lines)test/exports.test.ts: Add regression test for the above caseTest plan
🤖 Generated with Claude Code
Summary by CodeRabbit
Bug Fixes
Tests