fix: support on whitespace inside macro for descend_node_at_offset - #22971
fix: support on whitespace inside macro for descend_node_at_offset#22971A4-Tacks wants to merge 2 commits into
Conversation
Example
---
```rust
macro_rules! m { ($expr:expr) => {$expr}}
enum Test { A, B, C }
fn foo(t: Test) {
m!(match t {
Test::A => (),
$0
});
}
```
**Before this PR**
Assist not applicable
**After this PR**
```rust
macro_rules! m { ($expr:expr) => {$expr}}
enum Test { A, B, C }
fn foo(t: Test) {
m!(match t {
Test::A => (),
Test::B => ${1:todo!()},
Test::C => ${2:todo!()},$0
});
}
```
| let (on_whitespace, tokens) = match node.token_at_offset(offset) { | ||
| syntax::TokenAtOffset::Single(token) if token.kind() == SyntaxKind::WHITESPACE => { | ||
| let prev = token | ||
| .prev_token() | ||
| .and_then(|token| skip_whitespace_token(token, Direction::Prev)); | ||
| let next = token | ||
| .next_token() | ||
| .and_then(|token| skip_whitespace_token(token, Direction::Next)); | ||
| (true, Either::Left(itertools::chain!([token], prev, next))) | ||
| } | ||
| tokens => (false, Either::Right(tokens)), | ||
| }; | ||
| let file_id = self.find_file(node).file_id; | ||
| tokens |
There was a problem hiding this comment.
Hmm, not a fan of this implementation, and it also doesn't account for comments.
How about:
let tokens = node.token_at_offset(offset);
let tokens = if tokens.all(|token| token.kind().is_trivia()) {
Either::Left(tokens.flat_map(|token| {
let prev = token
.prev_token()
.and_then(|token| skip_trivia_token(token, Direction::Prev));
let next = token
.next_token()
.and_then(|token| skip_trivia_token(token, Direction::Next));
std::iter::chain(prev, next)
}))
} else {
Either::Right(tokens.filter(|token| token.kind().is_trivia()))
};There was a problem hiding this comment.
and it also doesn't account for comments.
I think triggering on comments is too surprising
There was a problem hiding this comment.
This is similar to the behavior of trimmed_range
| .map(move |ancestors| { | ||
| ancestors.filter(move |node| { | ||
| if !on_whitespace { | ||
| return true; | ||
| } | ||
| let origin = self.original_range(node); | ||
| origin.file_id == file_id && origin.range.contains(offset) | ||
| }) | ||
| }) |
There was a problem hiding this comment.
This should come before the kmerge_by(). Also I think it's better to not check on_whitespace.
There was a problem hiding this comment.
If filtering is done before kmerge, it will result in excessive redundant calculations for kmerge
Checking the is_whitespace should prevent performance degradation most of the time and may also avoid some regressions (or fail-fast is better?)
Fixes #21729
Example
Before this PR
Assist not applicable
After this PR