feat: handle corner case of IDE selecting an item#2300
feat: handle corner case of IDE selecting an item#2300Myriad-Dreamin wants to merge 5 commits intomainfrom
Conversation
Summary of ChangesHello @Myriad-Dreamin, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request introduces significant improvements to the IDE's understanding and manipulation of language items, particularly labels and content references. It refines how these items are identified, resolved, and renamed, addressing corner cases and enhancing the overall developer experience. The changes include more precise span handling, enabling renaming for previously unsupported declaration types, and providing clearer feedback to the user through LSP change annotations for refactoring operations. Highlights
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request introduces label renaming and improves reference handling for labels and content references. The changes are a good step forward for IDE support. However, I've identified a couple of critical issues in the implementation that need to be addressed. Specifically, the logic for determining the rename range for references is incorrect, and the span calculation for content references will lead to incorrect highlighting. I've provided detailed suggestions to fix these issues. Additionally, there's a minor wording improvement for a user-facing message.
| let mut node = syntax.node().clone(); | ||
| if matches!(node.kind(), SyntaxKind::Ref) { | ||
| let marker = node | ||
| .children() | ||
| .find(|child| child.kind() == SyntaxKind::RefMarker)?; | ||
| node = marker; | ||
| } | ||
| let mut range = node.range(); | ||
| if matches!(node.kind(), SyntaxKind::RefMarker) { | ||
| range.start += 1; | ||
| } |
There was a problem hiding this comment.
The logic for determining the range for a rename operation on a Ref seems incorrect. It currently finds the RefMarker (@) and adjusts its range, which will not cover the identifier that needs to be renamed.
To fix this, you should find the identifier node within the Ref and use its range directly. This will ensure that the rename UI is anchored to the correct part of the code.
let range = if syntax.node().kind() == SyntaxKind::Ref {
syntax
.node()
.children()
.find(|child| matches!(child.kind(), SyntaxKind::Ident | SyntaxKind::Label))
.map(|ident_node| ident_node.range())
.unwrap_or_else(|| syntax.node().range())
} else {
syntax.node().range()
};| at: { | ||
| let marker_span = ident | ||
| .to_untyped() | ||
| .children() | ||
| .find(|child| child.kind() == SyntaxKind::RefMarker) | ||
| .map(|child| child.span()); | ||
|
|
||
| marker_span.unwrap_or(ident.span()) | ||
| }, |
There was a problem hiding this comment.
The logic to determine the span for a ContentRef seems to be targeting the RefMarker (@), which is likely incorrect. The span should probably cover the identifier part of the reference to ensure correct behavior for features like 'find references' and 'rename'.
By storing the span of the identifier itself, you'll get more accurate ranges for highlighting and editing. With this change, you'll also need to update references.rs to remove the adjustment for ContentRef (i.e., change Some((1, 0)) to None), as the span will now be correct.
| at: { | |
| let marker_span = ident | |
| .to_untyped() | |
| .children() | |
| .find(|child| child.kind() == SyntaxKind::RefMarker) | |
| .map(|child| child.span()); | |
| marker_span.unwrap_or(ident.span()) | |
| }, | |
| at: { | |
| let ident_span = ident | |
| .to_untyped() | |
| .children() | |
| .find(|child| matches!(child.kind(), SyntaxKind::Ident | SyntaxKind::Label)) | |
| .map(|child| child.span()); | |
| ident_span.unwrap_or(ident.span()) | |
| }, |
| let change_annotations = Some(create_change_annotation( | ||
| change_id, | ||
| true, | ||
| Some("The language server fuzzy searched the labels".to_string()), |
There was a problem hiding this comment.
The description for the rename annotation is a bit misleading. It's not a fuzzy search, but a precise search for all references to the label. A more accurate description would be clearer for the user.
| Some("The language server fuzzy searched the labels".to_string()), | |
| Some("Renaming this label will affect all its references.".to_string()), |
If the item before and after the cursor are both valid language items. We prefer to select the previous one. e.g.
@a:1|@b:1, we select the@a:1.