Skip to content
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

Edit: Support trimming active selections to a tree-sitter node #4031

Conversation

umpox
Copy link
Contributor

@umpox umpox commented May 3, 2024

Description

Fixes CODY-1363

This PR:

  • Attempts to match a users' provided selection to a tree-sitter node, so we can improve the reliability of Edit commands

Before:

We would prioritise the users selection (if non-empty) before anything else. This worked in most cases, but was not optimal as the user may have actually been attempting to match the tree-sitter node, but made a mistake and possibly:

  • Accidentally selected more than the node, e.g. extra whitespace chars
  • Accidentally didn't select the full node (e.g. made a partial line selection)

This would also be non-optimal as in some case we get more insight into the users' selection if we use tree-sitter. For example, for "Generate Documentation" in Python, using tree-sitter will help us determine the correct insertionPoint for the documentation. This relies on knowing the syntax of the node in Python. Even if the users' selection exactly matched the node we would not get that information.

AdjustedRangeBefore.mov

After:

We now attempt to match the users' selection to a tree-sitter node, in a safe manner that doesn't discard situations where their selection is likely preferred. This is by:

  1. Expanding their selection to the full lines of the start and end (helps if they don't select a full line)
  2. Trimming their selection to the first and last non-whitespace characters (helps if they select too many empty lines/spaces)
  3. Comparing this adjusted selection to the retrieved tree-sitter node. If it matches exactly then we can be confident that the user would prefer to user this, and we can benefit from the additional information we retrieve.
AdjustedRangeAfter.mov

Test plan

Document:

  1. Execute a "Document Code" command from just a cursor position, within an expected tree-sitter node (e.g. JS function). Expect it to expand correctly.
  2. Execute a "Document Code" command from a full selection that doesn't match an exact tree-sitter node (e.g. select just a function call like console.log()). Expect it to only document this line with the function call
  3. Execute a "Document Code" command from a full selection that does match an exact tree-sitter node, expect it to document this node correctly.
  4. Execute a "Document Code" command from an expanded selection that matches a tree-sitter node but with additional whitespace (including new lines) before and after. Expect it to document the tree-sitter node correctly. In Python, expect it to determine the correct insertion point.
  5. Execute a "Document Code" command from a partial selection that matches some part of the first line of a tree-sitter node. E.g. (select partially the first line, and partially the second line in a function foo() {\n console.log('hi') func). Expect it to document the tree-sitter node correctly.

@umpox umpox marked this pull request as ready for review May 3, 2024 11:21
@umpox umpox requested review from abeatrix and a team May 3, 2024 11:21
@toolmantim
Copy link
Contributor

Nice!

Copy link
Member

@valerybugakov valerybugakov left a comment

Choose a reason for hiding this comment

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

Great work! Left some comments inline.

P.S. It would be so cool to somehow animate the selection expansion to the nearest node (showing to a user how smart Cody is!). I really wanted to see visual feedback for it in the demo video. cc @toolmantim

vscode/src/commands/execute/doc.ts Outdated Show resolved Hide resolved
Comment on lines 30 to 31
// No usable selection, fallback to expanding the range to the nearest block.
return {}
Copy link
Member

Choose a reason for hiding this comment

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

Is the expansion to the nearest block done somewhere up the call chain?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah it's the default behavior for Edit commands. It's a little confusing when presented like this but it makes sense as an abstraction (command specific ranges falling back to generic edit block ranges if not found).

Added a comment

vscode/src/commands/execute/doc.ts Show resolved Hide resolved
// It is probable that the user would benefit from expanding to this node completely
const selectionMatchesNode =
adjustedSelection.start.isEqual(range.start) && range.contains(adjustedSelection.end)
if (!selectionMatchesNode && !editor.selection.isEmpty) {
Copy link
Member

Choose a reason for hiding this comment

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

Should we cover this branching in one of the unit tests?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Kinda tricky to isolate this with a specific test, but actually we have agent tests that cover this.

I noticed an issue with cursor position ranges (isEmpty) from these tests already

@umpox umpox merged commit 535a413 into main May 7, 2024
20 checks passed
@umpox umpox deleted the tom/cody-1363-python-docstrings-should-be-placed-inside-the-method-not branch May 7, 2024 12:00
umpox added a commit that referenced this pull request May 7, 2024
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.

None yet

3 participants