From c7b34e4873183d052f277ee7dda1f9927b66e154 Mon Sep 17 00:00:00 2001 From: Lukas Wirth Date: Mon, 31 Jul 2023 17:12:17 +0200 Subject: [PATCH] fix: Strip unused token ids from eager macro input token maps --- crates/hir-expand/src/eager.rs | 9 ++++++--- .../test_data/highlight_macros.html | 14 ++++++++++++-- crates/ide/src/syntax_highlighting/tests.rs | 15 ++++++++++++++- crates/mbe/src/token_map.rs | 4 ++++ crates/tt/src/lib.rs | 2 +- 5 files changed, 37 insertions(+), 7 deletions(-) diff --git a/crates/hir-expand/src/eager.rs b/crates/hir-expand/src/eager.rs index 91aa49d1e21..3ca2e295d7f 100644 --- a/crates/hir-expand/src/eager.rs +++ b/crates/hir-expand/src/eager.rs @@ -19,7 +19,7 @@ //! //! See the full discussion : use base_db::CrateId; -use rustc_hash::FxHashMap; +use rustc_hash::{FxHashMap, FxHashSet}; use syntax::{ted, Parse, SyntaxNode, TextRange, TextSize, WalkEvent}; use triomphe::Arc; @@ -83,10 +83,11 @@ pub fn expand_eager_macro_input( mbe::syntax_node_to_token_tree(&expanded_eager_input); let og_tmap = if let Some(tt) = macro_call.value.token_tree() { - let og_tmap = mbe::syntax_node_to_token_map(tt.syntax()); + let mut ids_used = FxHashSet::default(); + let mut og_tmap = mbe::syntax_node_to_token_map(tt.syntax()); // The tokenmap and ids of subtree point into the expanded syntax node, but that is inaccessible from the outside // so we need to remap them to the original input of the eager macro. - subtree.visit_ids(&|id| { + subtree.visit_ids(&mut |id| { // Note: we discard all token ids of braces and the like here, but that's not too bad and only a temporary fix if let Some(range) = expanded_eager_input_token_map @@ -97,6 +98,7 @@ pub fn expand_eager_macro_input( // remap from eager input expansion to original eager input if let Some(&og_range) = ws_mapping.get(og_range) { if let Some(og_token) = og_tmap.token_by_range(og_range) { + ids_used.insert(id); return og_token; } } @@ -104,6 +106,7 @@ pub fn expand_eager_macro_input( } tt::TokenId::UNSPECIFIED }); + og_tmap.filter(|id| ids_used.contains(&id)); og_tmap } else { Default::default() diff --git a/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html b/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html index c5fcec75680..06b66b302ae 100644 --- a/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html +++ b/crates/ide/src/syntax_highlighting/test_data/highlight_macros.html @@ -90,8 +90,18 @@ pre { color: #DCDCCC; background: #3F3F3F; font-size: 22px; padd } } +#[rustc_builtin_macro] +macro_rules! concat {} +#[rustc_builtin_macro] +macro_rules! include {} +#[rustc_builtin_macro] +macro_rules! format_args {} + +include!(concat!("foo/", "foo.rs")); + fn main() { - println!("Hello, {}!", 92); + format_args!("Hello, {}!", 92); dont_color_me_braces!(); noop!(noop!(1)); -} \ No newline at end of file +} + \ No newline at end of file diff --git a/crates/ide/src/syntax_highlighting/tests.rs b/crates/ide/src/syntax_highlighting/tests.rs index 696aa590025..87470718070 100644 --- a/crates/ide/src/syntax_highlighting/tests.rs +++ b/crates/ide/src/syntax_highlighting/tests.rs @@ -48,6 +48,7 @@ fn macros() { check_highlighting( r#" //- proc_macros: mirror +//- /lib.rs crate:lib proc_macros::mirror! { { ,i32 :x pub @@ -95,11 +96,23 @@ macro_rules! keyword_frag { } } +#[rustc_builtin_macro] +macro_rules! concat {} +#[rustc_builtin_macro] +macro_rules! include {} +#[rustc_builtin_macro] +macro_rules! format_args {} + +include!(concat!("foo/", "foo.rs")); + fn main() { - println!("Hello, {}!", 92); + format_args!("Hello, {}!", 92); dont_color_me_braces!(); noop!(noop!(1)); } +//- /foo/foo.rs crate:foo +mod foo {} +use self::foo as bar; "#, expect_file!["./test_data/highlight_macros.html"], false, diff --git a/crates/mbe/src/token_map.rs b/crates/mbe/src/token_map.rs index 9b2df89f9c7..73a27df5dbc 100644 --- a/crates/mbe/src/token_map.rs +++ b/crates/mbe/src/token_map.rs @@ -117,4 +117,8 @@ pub fn entries(&self) -> impl Iterator + '_ { TokenTextRange::Delimiter(_) => None, }) } + + pub fn filter(&mut self, id: impl Fn(tt::TokenId) -> bool) { + self.entries.retain(|&(tid, _)| id(tid)); + } } diff --git a/crates/tt/src/lib.rs b/crates/tt/src/lib.rs index 1b8d4ba42a5..ab398726b87 100644 --- a/crates/tt/src/lib.rs +++ b/crates/tt/src/lib.rs @@ -70,7 +70,7 @@ pub const fn empty() -> Self { } impl Subtree { - pub fn visit_ids(&mut self, f: &impl Fn(TokenId) -> TokenId) { + pub fn visit_ids(&mut self, f: &mut impl FnMut(TokenId) -> TokenId) { self.delimiter.open = f(self.delimiter.open); self.delimiter.close = f(self.delimiter.close); self.token_trees.iter_mut().for_each(|tt| match tt {