Skip to content

Fix infinite looping in notebook addFindMatchToSelection (Cmd+D) #251157

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
Jun 13, 2025

Conversation

Copilot
Copy link
Contributor

@Copilot Copilot AI commented Jun 10, 2025

Problem

When using Cmd+D (Add Selection to Next Find Match) in notebooks, the operation keeps looping indefinitely instead of becoming a no-op once all find results are covered by selections. This differs from regular editors where pressing Cmd+D stops being effective when all matches are already selected.

Root Cause

The issue was in the findAndTrackNextSelection method in notebookMulticursor.ts. When in the Selecting state, the method calls notebookTextModel.findNextMatch() which cycles through matches infinitely, unlike regular editors where findNextMatch returns null when no more unique matches are available.

Solution

Added a check before calling findNextMatch that compares:

  • totalMatches: Count of all available matches in the notebook
  • totalSelections: Count of all current selections across tracked cells

When totalSelections >= totalMatches, the method returns early (no-op), preventing the infinite loop and matching the behavior of regular editors.

// Check if all matches are already covered by selections to avoid infinite looping
const allMatches = notebookTextModel.findMatches(this.word, false, true, USUAL_WORD_SEPARATORS);
const totalMatches = allMatches.reduce((sum, cellMatch) => sum + cellMatch.matches.length, 0);
const totalSelections = this.trackedCells.reduce((sum, trackedCell) => sum + trackedCell.matchSelections.length, 0);

if (totalSelections >= totalMatches) {
    // All matches are already selected, make this a no-op like in regular editors
    return;
}

Testing

The fix ensures that pressing Cmd+D in notebooks will stop being effective once all find results are covered by selections, exactly like in regular text editors. The operation becomes a no-op when all matches are already selected, preventing the infinite cycling behavior.

Fixes #235117.

Co-authored-by: Yoyokrazy <12552271+Yoyokrazy@users.noreply.github.com>
@Copilot Copilot AI changed the title [WIP] notebook.addFindMatchToSelection keeps looping Fix infinite looping in notebook addFindMatchToSelection (Cmd+D) Jun 10, 2025
@Copilot Copilot AI requested a review from Yoyokrazy June 10, 2025 22:02
Copilot finished work on behalf of Yoyokrazy June 10, 2025 22:02
Comment on lines 548 to 556
// Check if all matches are already covered by selections to avoid infinite looping
const allMatches = notebookTextModel.findMatches(this.word, false, true, USUAL_WORD_SEPARATORS);
const totalMatches = allMatches.reduce((sum, cellMatch) => sum + cellMatch.matches.length, 0);
const totalSelections = this.trackedCells.reduce((sum, trackedCell) => sum + trackedCell.matchSelections.length, 0);

if (totalSelections >= totalMatches) {
// All matches are already selected, make this a no-op like in regular editors
return;
}
Copy link
Contributor

Choose a reason for hiding this comment

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

this isn't optimal, since we don't want to do an entire extra findMatches call each time we check this and same with the iteration overTracked cells for totalSelections. Can we just record allMatches at the beginning of this whole process? ie when we're going from idle into selecting? the first case? Then each time we successfully add another match we can just incremement and then its a lot better, perf-wise

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good point! I've optimized the performance by recording allMatches count once during the idle→selecting transition and using a cached counter instead of recalculating on every Cmd+D press. This eliminates the expensive findMatches() call and tracked cells iteration. See commit 2dda55d.

…ulating

Co-authored-by: Yoyokrazy <12552271+Yoyokrazy@users.noreply.github.com>
Copilot finished work on behalf of Yoyokrazy June 11, 2025 18:27
@Yoyokrazy Yoyokrazy marked this pull request as ready for review June 13, 2025 17:04
@Yoyokrazy Yoyokrazy enabled auto-merge (squash) June 13, 2025 17:05
@vs-code-engineering vs-code-engineering bot added this to the June 2025 milestone Jun 13, 2025
Copy link
Contributor

@Yoyokrazy Yoyokrazy left a comment

Choose a reason for hiding this comment

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

built and verified fix

@Yoyokrazy Yoyokrazy merged commit aa3933c into main Jun 13, 2025
8 checks passed
@Yoyokrazy Yoyokrazy deleted the copilot/fix-235117 branch June 13, 2025 17:29
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.

notebook.addFindMatchToSelection keeps looping
3 participants