Skip to content

fix: support on whitespace inside macro for descend_node_at_offset - #22971

Open
A4-Tacks wants to merge 2 commits into
rust-lang:masterfrom
A4-Tacks:ancestors-on-ws-in-macro
Open

fix: support on whitespace inside macro for descend_node_at_offset#22971
A4-Tacks wants to merge 2 commits into
rust-lang:masterfrom
A4-Tacks:ancestors-on-ws-in-macro

Conversation

@A4-Tacks

@A4-Tacks A4-Tacks commented Jul 31, 2026

Copy link
Copy Markdown
Member

Fixes #21729

Example

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

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
    });
}

A4-Tacks added 2 commits July 31, 2026 21:45
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
    });
}
```
@rustbot rustbot added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jul 31, 2026
Comment on lines +1537 to +1550
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

@ChayimFriedman2 ChayimFriedman2 Jul 31, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

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()))
};

View changes since the review

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

and it also doesn't account for comments.

I think triggering on comments is too surprising

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

This is similar to the behavior of trimmed_range

Comment on lines +1562 to +1570
.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)
})
})

@ChayimFriedman2 ChayimFriedman2 Jul 31, 2026

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

This should come before the kmerge_by(). Also I think it's better to not check on_whitespace.

View changes since the review

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

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?)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

S-waiting-on-review Status: Awaiting review from the assignee but also interested parties.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Work on whitespace for find_node_at_offset_with_descend

3 participants