Skip to content

[issues/541] Fix Go to RangeLink falsely reporting "Multiple files match" when root-level file matches#585

Merged
couimet merged 2 commits into
mainfrom
issues/541
May 17, 2026
Merged

[issues/541] Fix Go to RangeLink falsely reporting "Multiple files match" when root-level file matches#585
couimet merged 2 commits into
mainfrom
issues/541

Conversation

@couimet
Copy link
Copy Markdown
Owner

@couimet couimet commented May 17, 2026

Summary

The bare filename resolution path in resolveWorkspacePath() always delegated to findFiles('**/filename', undefined, 2), returning FILENAME_AMBIGUOUS as soon as 2 matches existed anywhere in the workspace. In monorepos, common root-level files like package.json appear in multiple subdirectories, so typing a bare filename always triggered the ambiguity warning. This fix checks workspace root(s) via fs.stat before falling back to findFiles, matching the most likely user intent. node_modules is now excluded from the findFiles fallback to avoid dependency-directory noise.

Changes

  • Reordered bare-filename resolution in resolveWorkspacePath.ts: check workspace root(s) via fs.stat before findFiles. Single root match returns workspace-relative; multiple root matches across workspace folders returns FILENAME_AMBIGUOUS
  • Added {**/node_modules/**} exclude pattern to findFiles fallback
  • Updated 5 test assertions to reflect new resolution order and node_modules exclusion
  • Added multi-root ambiguity test for bare filename existing at multiple workspace roots
  • Documentation: CHANGELOG added; README not needed (no new feature or setting)

Test Plan

  • All existing tests pass (1923)
  • New tests added for: root-first resolution, multi-root ambiguity, findFiles node_modules exclusion
  • Manual testing: test package.json bare filename navigation in monorepo workspace

Related

Closes #541

Summary by CodeRabbit

  • Bug Fixes

    • Improved workspace file path resolution to prioritize direct root directory checks before falling back to broader searches, enabling more efficient and accurate file disambiguation.
  • Tests

    • Enhanced test coverage for workspace path resolution edge cases, including ambiguous filenames across multiple workspace roots and various fallback scenarios.

Review Change Stack

…tch" when root-level file matches

## Summary

The bare filename resolution path in `resolveWorkspacePath()` always delegated to `findFiles('**/filename', undefined, 2)`, returning `FILENAME_AMBIGUOUS` as soon as 2 matches existed anywhere in the workspace. In monorepos, common root-level files like `package.json` appear in multiple subdirectories, so typing a bare filename always triggered the ambiguity warning. This fix checks workspace root(s) via `fs.stat` before falling back to `findFiles`, matching the most likely user intent. `node_modules` is now excluded from the findFiles fallback to avoid dependency-directory noise.

## Changes

- Reordered bare-filename resolution in `resolveWorkspacePath.ts`: check workspace root(s) via `fs.stat` before `findFiles`. Single root match returns `workspace-relative`; multiple root matches across workspace folders returns `FILENAME_AMBIGUOUS`
- Added `{**/node_modules/**}` exclude pattern to `findFiles` fallback
- Updated 5 test assertions to reflect new resolution order and node_modules exclusion
- Added multi-root ambiguity test for bare filename existing at multiple workspace roots
- Documentation: CHANGELOG added; README not needed (no new feature or setting)

## Test Plan

- [x] All existing tests pass (1923)
- [x] New tests added for: root-first resolution, multi-root ambiguity, findFiles node_modules exclusion
- [ ] Manual testing: test `package.json` bare filename navigation in monorepo workspace

## Related

Closes #541
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 17, 2026

Warning

Rate limit exceeded

@couimet has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 46 minutes and 13 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: ee8ed915-f201-44e2-b5a3-2ba135e99276

📥 Commits

Reviewing files that changed from the base of the PR and between 9826d0a and 5bf27de.

📒 Files selected for processing (1)
  • packages/rangelink-vscode-extension/src/__tests__/utils/resolveWorkspacePath.test.ts

Walkthrough

Updates resolveWorkspacePath to prioritize direct workspace-root matching via fs.stat before falling back to workspace.findFiles. Test cases are aligned to verify the new root-first strategy, explicit node_modules exclusion in glob patterns, and edge-case handling for ambiguity and resolution failures.

Changes

Bare-filename resolution refactor

Layer / File(s) Summary
Core resolution strategy and documentation
src/utils/resolveWorkspacePath.ts
Documentation updated to describe root-fs.stat-first approach. Implementation rewritten to iterate workspace roots, count matches via workspace.fs.stat, return single matches or FILENAME_AMBIGUOUS at threshold, then fall back to workspace.findFiles with {**/node_modules/**} exclusion.
Test alignment and edge-case coverage
src/__tests__/utils/resolveWorkspacePath.test.ts
Existing bare-filename tests updated to expect {**/node_modules/**} exclude glob. New tests added for findFiles rejection scenarios and multi-root filename ambiguity. Prior root-vs-subdirectory tests replaced with scenarios verifying fs.stat vs findFiles invocation and result precedence.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • couimet/rangeLink#497: Introduces the initial bare-filename fallback behavior in resolveWorkspacePath, which this PR refines with a root-stat-first strategy and explicit node_modules exclusion.

Poem

🐰 A rabbit hops through workspace roots with glee,
Checking local files before the glob decree—
No node_modules clutter in the path ahead,
Just clean matches found, ambiguity well-read! ✨

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: fixing false 'Multiple files match' errors for root-level files in Go to RangeLink functionality.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch issues/541

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@github-actions
Copy link
Copy Markdown

github-actions Bot commented May 17, 2026

⚠️ QA Coverage Gap Detected

The PR modifies the behavior of the resolveWorkspacePath function, specifically in how it handles file path detection patterns by excluding node_modules. This change affects the output when resolving file paths, which is user-visible.

Suggested test cases:

  • File Path Resolution: Verify that resolveWorkspacePath excludes node_modules when resolving paths (automatable)
  • File Path Resolution: Check that FILENAME_AMBIGUOUS is returned when multiple files match in different workspace roots (automatable)
  • File Path Resolution: Ensure that undefined is returned when findFiles rejects (automatable)

Generated by QA Gap Check (GPT-4o-mini via GitHub Models)

@couimet
Copy link
Copy Markdown
Owner Author

couimet commented May 17, 2026

@coderabbitai review I was rate-limited in #585 (comment)

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented May 17, 2026

@couimet Sure! I'll kick off a new review of PR #585 for you right away.

(。•̀ᴗ-)✧

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
packages/rangelink-vscode-extension/src/__tests__/utils/resolveWorkspacePath.test.ts (1)

307-329: 💤 Low value

Duplicate tests: lines 307-317 and 319-329 are functionally identical.

Both tests:

  • Override mockStat to resolve successfully
  • Call resolveWorkspacePath('auth.ts', mockVscode)
  • Assert identical expectations (workspace-relative, same fsPath, stat called once, findFiles not called)

The second test's title ("even if findFiles would fail") suggests a distinct scenario, but since findFiles is never invoked when the root match succeeds, the test doesn't actually verify failure handling—it's the same test with a different name.

Consider removing one or making test 319-329 genuinely distinct (e.g., by verifying a scenario where root resolution doesn't short-circuit).

🤖 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
`@packages/rangelink-vscode-extension/src/__tests__/utils/resolveWorkspacePath.test.ts`
around lines 307 - 329, The two tests calling resolveWorkspacePath('auth.ts',
mockVscode) are duplicates; remove one or change the second ("should return root
match when bare filename exists at workspace root even if findFiles would fail")
to exercise the intended failure path by making mockStat reject (so
workspace-relative doesn't short-circuit) and then set mockFindFiles to reject
or return no results, then assert the behavior you expect when findFiles fails;
reference the resolveWorkspacePath function and the mocks mockStat and
mockFindFiles to locate and adjust the tests accordingly.
🤖 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.

Nitpick comments:
In
`@packages/rangelink-vscode-extension/src/__tests__/utils/resolveWorkspacePath.test.ts`:
- Around line 307-329: The two tests calling resolveWorkspacePath('auth.ts',
mockVscode) are duplicates; remove one or change the second ("should return root
match when bare filename exists at workspace root even if findFiles would fail")
to exercise the intended failure path by making mockStat reject (so
workspace-relative doesn't short-circuit) and then set mockFindFiles to reject
or return no results, then assert the behavior you expect when findFiles fails;
reference the resolveWorkspacePath function and the mocks mockStat and
mockFindFiles to locate and adjust the tests accordingly.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 0e6ee404-6835-4ab8-912d-f0b85d7a7a02

📥 Commits

Reviewing files that changed from the base of the PR and between 57c009d and 9826d0a.

📒 Files selected for processing (2)
  • packages/rangelink-vscode-extension/src/__tests__/utils/resolveWorkspacePath.test.ts
  • packages/rangelink-vscode-extension/src/utils/resolveWorkspacePath.ts

The two tests at lines 307-317 and 319-329 were functionally identical: both set mockStat to resolve, called resolveWorkspacePath with the same input, and asserted the same expectations. The removed test's stated scenario ("even if findFiles would fail") is impossible: when mockStat resolves, the root-match branch short-circuits before findFiles is ever invoked. The remaining test at line 307 already covers the root-match-only case, and findFiles rejection is independently tested at line 221.

Ref: #585 (review)
@github-actions
Copy link
Copy Markdown

CI / Integration Tests (with extensions) — run summary

Duration 7m 1s
Integration tests passing 181
QA TC IDs exercised custom-ai-assistant-003, claude-code-006, claude-code-007, gemini-code-assist-001, gemini-code-assist-005, gemini-code-assist-006
Report View run & artifacts

@github-actions
Copy link
Copy Markdown

CI / Test & Validate — run summary

Duration 8m 5s
Unit tests passed 1922 / 1922
Integration tests passing 177
QA TC IDs exercised status-bar-menu-002, status-bar-menu-003, status-bar-menu-005, status-bar-menu-006, bind-to-destination-010, bind-to-destination-013, terminal-picker-001, terminal-picker-002, terminal-picker-003, terminal-picker-004, terminal-picker-005, terminal-picker-006, terminal-picker-007, terminal-picker-008, terminal-picker-011, terminal-picker-012, terminal-picker-013, file-picker-001, file-picker-002, file-picker-003, file-picker-004, file-picker-005, file-picker-009, file-picker-011, file-picker-012, clipboard-preservation-002, clipboard-preservation-003, clipboard-preservation-006, clipboard-preservation-007, clipboard-preservation-008, clipboard-preservation-009, send-file-path-001, send-file-path-006, send-file-path-007, send-file-path-008, dirty-buffer-warning-004, dirty-buffer-warning-006, dirty-buffer-warning-007, dirty-buffer-warning-019, send-terminal-selection-003, send-terminal-selection-006, send-terminal-selection-007, go-to-link-001, unbind-001, unbind-003, unbind-004, editor-binding-validation-004, full-line-navigation-001, full-line-navigation-002, char-navigation-001, char-navigation-002, full-line-link-generation-001, wrapped-link-navigation-001, wrapped-link-navigation-002, wrapped-link-navigation-003, wrapped-link-navigation-004, markdown-link-navigation-001, url-exclusion-001, stale-viewcolumn-001, full-line-selection-validation-001, core-send-commands-r-l-001, core-send-commands-r-c-001, core-send-commands-r-l-005, core-send-commands-r-p-001, core-send-commands-r-v-001, clickable-file-paths-001, clickable-file-paths-002, clickable-file-paths-003, clickable-file-paths-004, clickable-file-paths-005, clickable-file-paths-006, clickable-file-paths-007, clickable-file-paths-008, clickable-file-paths-009, clickable-file-paths-010, clickable-file-paths-011, clickable-file-paths-012, smart-padding-001, smart-padding-002, smart-padding-003, smart-padding-004, smart-padding-005, smart-padding-006, duplicate-tab-group-001, duplicate-tab-group-002, duplicate-tab-group-003, duplicate-tab-group-004, langswitch-binding-001, langswitch-binding-002, navigation-clamping-001, navigation-clamping-002, navigation-clamping-003, navigation-clamping-004, untitled-navigation-001, untitled-navigation-002, untitled-navigation-003, untitled-navigation-004, untitled-navigation-005, untitled-navigation-006, navigation-toast-settings-001, navigation-toast-settings-002, navigation-toast-settings-003, filename-fallback-navigation-001, filename-fallback-navigation-002, filename-fallback-navigation-003, filename-fallback-navigation-004, custom-ai-assistant-001, custom-ai-assistant-002, custom-ai-assistant-004, custom-ai-assistant-005, custom-ai-assistant-006, custom-ai-assistant-007, custom-ai-assistant-008, custom-ai-assistant-009, custom-ai-assistant-015, custom-ai-assistant-016, claude-code-001, github-copilot-chat-001, release-notifier-001, release-notifier-002
Report View run & artifacts

Repository owner deleted a comment from github-actions Bot May 17, 2026
Repository owner deleted a comment from github-actions Bot May 17, 2026
@couimet couimet merged commit 26fdd38 into main May 17, 2026
5 checks passed
@couimet couimet deleted the issues/541 branch May 17, 2026 14:15
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

R-G mistakenly returns "Multiple files match" when a root-level file matches

1 participant