Skip to content

Commit 7f93ba5

Browse files
authored
Merge pull request #21145 from Veykril/push-prwwrlwmoxzx
proc-macro-srv: Fix `<TokenStream as Display>::fmt` impl producing trailing whitespace
2 parents 41a2df5 + 2578d40 commit 7f93ba5

File tree

6 files changed

+251
-30
lines changed

6 files changed

+251
-30
lines changed

src/tools/rust-analyzer/crates/proc-macro-api/src/legacy_protocol/msg/flat.rs

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,7 @@ impl FlatTree {
303303
pub fn to_tokenstream_unresolved<T: SpanTransformer<Table = ()>>(
304304
self,
305305
version: u32,
306+
span_join: impl Fn(T::Span, T::Span) -> T::Span,
306307
) -> proc_macro_srv::TokenStream<T::Span> {
307308
Reader::<T> {
308309
subtree: if version >= ENCODE_CLOSE_SPAN_VERSION {
@@ -326,13 +327,14 @@ impl FlatTree {
326327
span_data_table: &(),
327328
version,
328329
}
329-
.read_tokenstream()
330+
.read_tokenstream(span_join)
330331
}
331332

332333
pub fn to_tokenstream_resolved(
333334
self,
334335
version: u32,
335336
span_data_table: &SpanDataIndexMap,
337+
span_join: impl Fn(Span, Span) -> Span,
336338
) -> proc_macro_srv::TokenStream<Span> {
337339
Reader::<Span> {
338340
subtree: if version >= ENCODE_CLOSE_SPAN_VERSION {
@@ -356,7 +358,7 @@ impl FlatTree {
356358
span_data_table,
357359
version,
358360
}
359-
.read_tokenstream()
361+
.read_tokenstream(span_join)
360362
}
361363
}
362364

@@ -842,7 +844,10 @@ impl<T: SpanTransformer> Reader<'_, T> {
842844

843845
#[cfg(feature = "sysroot-abi")]
844846
impl<T: SpanTransformer> Reader<'_, T> {
845-
pub(crate) fn read_tokenstream(self) -> proc_macro_srv::TokenStream<T::Span> {
847+
pub(crate) fn read_tokenstream(
848+
self,
849+
span_join: impl Fn(T::Span, T::Span) -> T::Span,
850+
) -> proc_macro_srv::TokenStream<T::Span> {
846851
let mut res: Vec<Option<proc_macro_srv::Group<T::Span>>> = vec![None; self.subtree.len()];
847852
let read_span = |id| T::span_for_token_id(self.span_data_table, id);
848853
for i in (0..self.subtree.len()).rev() {
@@ -935,6 +940,8 @@ impl<T: SpanTransformer> Reader<'_, T> {
935940
}
936941
})
937942
.collect::<Vec<_>>();
943+
let open = read_span(repr.open);
944+
let close = read_span(repr.close);
938945
let g = proc_macro_srv::Group {
939946
delimiter: match repr.kind {
940947
tt::DelimiterKind::Parenthesis => proc_macro_srv::Delimiter::Parenthesis,
@@ -944,10 +951,10 @@ impl<T: SpanTransformer> Reader<'_, T> {
944951
},
945952
stream: if stream.is_empty() { None } else { Some(TokenStream::new(stream)) },
946953
span: proc_macro_srv::DelimSpan {
947-
open: read_span(repr.open),
948-
close: read_span(repr.close),
949-
// FIXME
950-
entire: read_span(repr.close),
954+
open,
955+
close,
956+
// FIXME: The protocol does not yet encode entire spans ...
957+
entire: span_join(open, close),
951958
},
952959
};
953960
res[i] = Some(g);

src/tools/rust-analyzer/crates/proc-macro-srv-cli/src/main_loop.rs

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -90,10 +90,10 @@ fn run_<C: Codec>() -> io::Result<()> {
9090
let call_site = SpanId(call_site as u32);
9191
let mixed_site = SpanId(mixed_site as u32);
9292

93-
let macro_body =
94-
macro_body.to_tokenstream_unresolved::<SpanTrans>(CURRENT_API_VERSION);
93+
let macro_body = macro_body
94+
.to_tokenstream_unresolved::<SpanTrans>(CURRENT_API_VERSION, |_, b| b);
9595
let attributes = attributes.map(|it| {
96-
it.to_tokenstream_unresolved::<SpanTrans>(CURRENT_API_VERSION)
96+
it.to_tokenstream_unresolved::<SpanTrans>(CURRENT_API_VERSION, |_, b| b)
9797
});
9898

9999
srv.expand(
@@ -124,10 +124,17 @@ fn run_<C: Codec>() -> io::Result<()> {
124124
let call_site = span_data_table[call_site];
125125
let mixed_site = span_data_table[mixed_site];
126126

127-
let macro_body = macro_body
128-
.to_tokenstream_resolved(CURRENT_API_VERSION, &span_data_table);
127+
let macro_body = macro_body.to_tokenstream_resolved(
128+
CURRENT_API_VERSION,
129+
&span_data_table,
130+
|a, b| srv.join_spans(a, b).unwrap_or(b),
131+
);
129132
let attributes = attributes.map(|it| {
130-
it.to_tokenstream_resolved(CURRENT_API_VERSION, &span_data_table)
133+
it.to_tokenstream_resolved(
134+
CURRENT_API_VERSION,
135+
&span_data_table,
136+
|a, b| srv.join_spans(a, b).unwrap_or(b),
137+
)
131138
});
132139
srv.expand(
133140
lib,

src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/imp/src/lib.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,11 @@ pub fn attr_error(args: TokenStream, item: TokenStream) -> TokenStream {
9494
format!("compile_error!(\"#[attr_error({})] {}\");", args, item).parse().unwrap()
9595
}
9696

97+
#[proc_macro_derive(DeriveReemit, attributes(helper))]
98+
pub fn derive_reemit(item: TokenStream) -> TokenStream {
99+
item
100+
}
101+
97102
#[proc_macro_derive(DeriveEmpty)]
98103
pub fn derive_empty(_item: TokenStream) -> TokenStream {
99104
TokenStream::default()

src/tools/rust-analyzer/crates/proc-macro-srv/src/lib.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,35 @@ impl<'env> ProcMacroSrv<'env> {
8181
temp_dir: TempDir::with_prefix("proc-macro-srv").unwrap(),
8282
}
8383
}
84+
85+
pub fn join_spans(&self, first: Span, second: Span) -> Option<Span> {
86+
// We can't modify the span range for fixup spans, those are meaningful to fixup, so just
87+
// prefer the non-fixup span.
88+
if first.anchor.ast_id == span::FIXUP_ERASED_FILE_AST_ID_MARKER {
89+
return Some(second);
90+
}
91+
if second.anchor.ast_id == span::FIXUP_ERASED_FILE_AST_ID_MARKER {
92+
return Some(first);
93+
}
94+
// FIXME: Once we can talk back to the client, implement a "long join" request for anchors
95+
// that differ in [AstId]s as joining those spans requires resolving the AstIds.
96+
if first.anchor != second.anchor {
97+
return None;
98+
}
99+
// Differing context, we can't merge these so prefer the one that's root
100+
if first.ctx != second.ctx {
101+
if first.ctx.is_root() {
102+
return Some(second);
103+
} else if second.ctx.is_root() {
104+
return Some(first);
105+
}
106+
}
107+
Some(Span {
108+
range: first.range.cover(second.range),
109+
anchor: second.anchor,
110+
ctx: second.ctx,
111+
})
112+
}
84113
}
85114

86115
const EXPANDER_STACK_SIZE: usize = 8 * 1024 * 1024;

src/tools/rust-analyzer/crates/proc-macro-srv/src/tests/mod.rs

Lines changed: 168 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,165 @@ fn test_derive_empty() {
5252
);
5353
}
5454

55+
#[test]
56+
fn test_derive_reemit_helpers() {
57+
assert_expand(
58+
"DeriveReemit",
59+
r#"
60+
#[helper(build_fn(private, name = "partial_build"))]
61+
pub struct Foo {
62+
/// The domain where this federated instance is running
63+
#[helper(setter(into))]
64+
pub(crate) domain: String,
65+
}
66+
"#,
67+
expect![[r#"
68+
PUNCT 1 # [joint]
69+
GROUP [] 1 1 1
70+
IDENT 1 helper
71+
GROUP () 1 1 1
72+
IDENT 1 build_fn
73+
GROUP () 1 1 1
74+
IDENT 1 private
75+
PUNCT 1 , [alone]
76+
IDENT 1 name
77+
PUNCT 1 = [alone]
78+
LITER 1 Str partial_build
79+
IDENT 1 pub
80+
IDENT 1 struct
81+
IDENT 1 Foo
82+
GROUP {} 1 1 1
83+
PUNCT 1 # [alone]
84+
GROUP [] 1 1 1
85+
IDENT 1 doc
86+
PUNCT 1 = [alone]
87+
LITER 1 Str / The domain where this federated instance is running
88+
PUNCT 1 # [joint]
89+
GROUP [] 1 1 1
90+
IDENT 1 helper
91+
GROUP () 1 1 1
92+
IDENT 1 setter
93+
GROUP () 1 1 1
94+
IDENT 1 into
95+
IDENT 1 pub
96+
GROUP () 1 1 1
97+
IDENT 1 crate
98+
IDENT 1 domain
99+
PUNCT 1 : [alone]
100+
IDENT 1 String
101+
PUNCT 1 , [alone]
102+
103+
104+
PUNCT 1 # [joint]
105+
GROUP [] 1 1 1
106+
IDENT 1 helper
107+
GROUP () 1 1 1
108+
IDENT 1 build_fn
109+
GROUP () 1 1 1
110+
IDENT 1 private
111+
PUNCT 1 , [alone]
112+
IDENT 1 name
113+
PUNCT 1 = [alone]
114+
LITER 1 Str partial_build
115+
IDENT 1 pub
116+
IDENT 1 struct
117+
IDENT 1 Foo
118+
GROUP {} 1 1 1
119+
PUNCT 1 # [alone]
120+
GROUP [] 1 1 1
121+
IDENT 1 doc
122+
PUNCT 1 = [alone]
123+
LITER 1 Str / The domain where this federated instance is running
124+
PUNCT 1 # [joint]
125+
GROUP [] 1 1 1
126+
IDENT 1 helper
127+
GROUP () 1 1 1
128+
IDENT 1 setter
129+
GROUP () 1 1 1
130+
IDENT 1 into
131+
IDENT 1 pub
132+
GROUP () 1 1 1
133+
IDENT 1 crate
134+
IDENT 1 domain
135+
PUNCT 1 : [alone]
136+
IDENT 1 String
137+
PUNCT 1 , [alone]
138+
"#]],
139+
expect![[r#"
140+
PUNCT 42:Root[0000, 0]@1..2#ROOT2024 # [joint]
141+
GROUP [] 42:Root[0000, 0]@2..3#ROOT2024 42:Root[0000, 0]@52..53#ROOT2024 42:Root[0000, 0]@2..53#ROOT2024
142+
IDENT 42:Root[0000, 0]@3..9#ROOT2024 helper
143+
GROUP () 42:Root[0000, 0]@9..10#ROOT2024 42:Root[0000, 0]@51..52#ROOT2024 42:Root[0000, 0]@9..52#ROOT2024
144+
IDENT 42:Root[0000, 0]@10..18#ROOT2024 build_fn
145+
GROUP () 42:Root[0000, 0]@18..19#ROOT2024 42:Root[0000, 0]@50..51#ROOT2024 42:Root[0000, 0]@18..51#ROOT2024
146+
IDENT 42:Root[0000, 0]@19..26#ROOT2024 private
147+
PUNCT 42:Root[0000, 0]@26..27#ROOT2024 , [alone]
148+
IDENT 42:Root[0000, 0]@28..32#ROOT2024 name
149+
PUNCT 42:Root[0000, 0]@33..34#ROOT2024 = [alone]
150+
LITER 42:Root[0000, 0]@35..50#ROOT2024 Str partial_build
151+
IDENT 42:Root[0000, 0]@54..57#ROOT2024 pub
152+
IDENT 42:Root[0000, 0]@58..64#ROOT2024 struct
153+
IDENT 42:Root[0000, 0]@65..68#ROOT2024 Foo
154+
GROUP {} 42:Root[0000, 0]@69..70#ROOT2024 42:Root[0000, 0]@190..191#ROOT2024 42:Root[0000, 0]@69..191#ROOT2024
155+
PUNCT 42:Root[0000, 0]@0..0#ROOT2024 # [alone]
156+
GROUP [] 42:Root[0000, 0]@0..0#ROOT2024 42:Root[0000, 0]@0..0#ROOT2024 42:Root[0000, 0]@0..0#ROOT2024
157+
IDENT 42:Root[0000, 0]@0..0#ROOT2024 doc
158+
PUNCT 42:Root[0000, 0]@0..0#ROOT2024 = [alone]
159+
LITER 42:Root[0000, 0]@75..130#ROOT2024 Str / The domain where this federated instance is running
160+
PUNCT 42:Root[0000, 0]@135..136#ROOT2024 # [joint]
161+
GROUP [] 42:Root[0000, 0]@136..137#ROOT2024 42:Root[0000, 0]@157..158#ROOT2024 42:Root[0000, 0]@136..158#ROOT2024
162+
IDENT 42:Root[0000, 0]@137..143#ROOT2024 helper
163+
GROUP () 42:Root[0000, 0]@143..144#ROOT2024 42:Root[0000, 0]@156..157#ROOT2024 42:Root[0000, 0]@143..157#ROOT2024
164+
IDENT 42:Root[0000, 0]@144..150#ROOT2024 setter
165+
GROUP () 42:Root[0000, 0]@150..151#ROOT2024 42:Root[0000, 0]@155..156#ROOT2024 42:Root[0000, 0]@150..156#ROOT2024
166+
IDENT 42:Root[0000, 0]@151..155#ROOT2024 into
167+
IDENT 42:Root[0000, 0]@163..166#ROOT2024 pub
168+
GROUP () 42:Root[0000, 0]@166..167#ROOT2024 42:Root[0000, 0]@172..173#ROOT2024 42:Root[0000, 0]@166..173#ROOT2024
169+
IDENT 42:Root[0000, 0]@167..172#ROOT2024 crate
170+
IDENT 42:Root[0000, 0]@174..180#ROOT2024 domain
171+
PUNCT 42:Root[0000, 0]@180..181#ROOT2024 : [alone]
172+
IDENT 42:Root[0000, 0]@182..188#ROOT2024 String
173+
PUNCT 42:Root[0000, 0]@188..189#ROOT2024 , [alone]
174+
175+
176+
PUNCT 42:Root[0000, 0]@1..2#ROOT2024 # [joint]
177+
GROUP [] 42:Root[0000, 0]@2..3#ROOT2024 42:Root[0000, 0]@52..53#ROOT2024 42:Root[0000, 0]@2..53#ROOT2024
178+
IDENT 42:Root[0000, 0]@3..9#ROOT2024 helper
179+
GROUP () 42:Root[0000, 0]@9..10#ROOT2024 42:Root[0000, 0]@51..52#ROOT2024 42:Root[0000, 0]@9..52#ROOT2024
180+
IDENT 42:Root[0000, 0]@10..18#ROOT2024 build_fn
181+
GROUP () 42:Root[0000, 0]@18..19#ROOT2024 42:Root[0000, 0]@50..51#ROOT2024 42:Root[0000, 0]@18..51#ROOT2024
182+
IDENT 42:Root[0000, 0]@19..26#ROOT2024 private
183+
PUNCT 42:Root[0000, 0]@26..27#ROOT2024 , [alone]
184+
IDENT 42:Root[0000, 0]@28..32#ROOT2024 name
185+
PUNCT 42:Root[0000, 0]@33..34#ROOT2024 = [alone]
186+
LITER 42:Root[0000, 0]@35..50#ROOT2024 Str partial_build
187+
IDENT 42:Root[0000, 0]@54..57#ROOT2024 pub
188+
IDENT 42:Root[0000, 0]@58..64#ROOT2024 struct
189+
IDENT 42:Root[0000, 0]@65..68#ROOT2024 Foo
190+
GROUP {} 42:Root[0000, 0]@69..70#ROOT2024 42:Root[0000, 0]@190..191#ROOT2024 42:Root[0000, 0]@69..191#ROOT2024
191+
PUNCT 42:Root[0000, 0]@0..0#ROOT2024 # [alone]
192+
GROUP [] 42:Root[0000, 0]@0..0#ROOT2024 42:Root[0000, 0]@0..0#ROOT2024 42:Root[0000, 0]@0..0#ROOT2024
193+
IDENT 42:Root[0000, 0]@0..0#ROOT2024 doc
194+
PUNCT 42:Root[0000, 0]@0..0#ROOT2024 = [alone]
195+
LITER 42:Root[0000, 0]@75..130#ROOT2024 Str / The domain where this federated instance is running
196+
PUNCT 42:Root[0000, 0]@135..136#ROOT2024 # [joint]
197+
GROUP [] 42:Root[0000, 0]@136..137#ROOT2024 42:Root[0000, 0]@157..158#ROOT2024 42:Root[0000, 0]@136..158#ROOT2024
198+
IDENT 42:Root[0000, 0]@137..143#ROOT2024 helper
199+
GROUP () 42:Root[0000, 0]@143..144#ROOT2024 42:Root[0000, 0]@156..157#ROOT2024 42:Root[0000, 0]@143..157#ROOT2024
200+
IDENT 42:Root[0000, 0]@144..150#ROOT2024 setter
201+
GROUP () 42:Root[0000, 0]@150..151#ROOT2024 42:Root[0000, 0]@155..156#ROOT2024 42:Root[0000, 0]@150..156#ROOT2024
202+
IDENT 42:Root[0000, 0]@151..155#ROOT2024 into
203+
IDENT 42:Root[0000, 0]@163..166#ROOT2024 pub
204+
GROUP () 42:Root[0000, 0]@166..167#ROOT2024 42:Root[0000, 0]@172..173#ROOT2024 42:Root[0000, 0]@166..173#ROOT2024
205+
IDENT 42:Root[0000, 0]@167..172#ROOT2024 crate
206+
IDENT 42:Root[0000, 0]@174..180#ROOT2024 domain
207+
PUNCT 42:Root[0000, 0]@180..181#ROOT2024 : [alone]
208+
IDENT 42:Root[0000, 0]@182..188#ROOT2024 String
209+
PUNCT 42:Root[0000, 0]@188..189#ROOT2024 , [alone]
210+
"#]],
211+
);
212+
}
213+
55214
#[test]
56215
fn test_derive_error() {
57216
assert_expand(
@@ -69,7 +228,7 @@ fn test_derive_error() {
69228
IDENT 1 compile_error
70229
PUNCT 1 ! [joint]
71230
GROUP () 1 1 1
72-
LITER 1 Str #[derive(DeriveError)] struct S {field 58 u32 }
231+
LITER 1 Str #[derive(DeriveError)] struct S {field 58 u32}
73232
PUNCT 1 ; [alone]
74233
"#]],
75234
expect![[r#"
@@ -83,9 +242,9 @@ fn test_derive_error() {
83242
84243
IDENT 42:Root[0000, 0]@0..13#ROOT2024 compile_error
85244
PUNCT 42:Root[0000, 0]@13..14#ROOT2024 ! [joint]
86-
GROUP () 42:Root[0000, 0]@14..15#ROOT2024 42:Root[0000, 0]@64..65#ROOT2024 42:Root[0000, 0]@14..65#ROOT2024
87-
LITER 42:Root[0000, 0]@15..64#ROOT2024 Str #[derive(DeriveError)] struct S {field 58 u32 }
88-
PUNCT 42:Root[0000, 0]@65..66#ROOT2024 ; [alone]
245+
GROUP () 42:Root[0000, 0]@14..15#ROOT2024 42:Root[0000, 0]@63..64#ROOT2024 42:Root[0000, 0]@14..64#ROOT2024
246+
LITER 42:Root[0000, 0]@15..63#ROOT2024 Str #[derive(DeriveError)] struct S {field 58 u32}
247+
PUNCT 42:Root[0000, 0]@64..65#ROOT2024 ; [alone]
89248
"#]],
90249
);
91250
}
@@ -472,7 +631,7 @@ fn test_attr_macro() {
472631
IDENT 1 compile_error
473632
PUNCT 1 ! [joint]
474633
GROUP () 1 1 1
475-
LITER 1 Str #[attr_error(some arguments )] mod m {}
634+
LITER 1 Str #[attr_error(some arguments)] mod m {}
476635
PUNCT 1 ; [alone]
477636
"#]],
478637
expect![[r#"
@@ -487,9 +646,9 @@ fn test_attr_macro() {
487646
488647
IDENT 42:Root[0000, 0]@0..13#ROOT2024 compile_error
489648
PUNCT 42:Root[0000, 0]@13..14#ROOT2024 ! [joint]
490-
GROUP () 42:Root[0000, 0]@14..15#ROOT2024 42:Root[0000, 0]@56..57#ROOT2024 42:Root[0000, 0]@14..57#ROOT2024
491-
LITER 42:Root[0000, 0]@15..56#ROOT2024 Str #[attr_error(some arguments )] mod m {}
492-
PUNCT 42:Root[0000, 0]@57..58#ROOT2024 ; [alone]
649+
GROUP () 42:Root[0000, 0]@14..15#ROOT2024 42:Root[0000, 0]@55..56#ROOT2024 42:Root[0000, 0]@14..56#ROOT2024
650+
LITER 42:Root[0000, 0]@15..55#ROOT2024 Str #[attr_error(some arguments)] mod m {}
651+
PUNCT 42:Root[0000, 0]@56..57#ROOT2024 ; [alone]
493652
"#]],
494653
);
495654
}
@@ -535,6 +694,7 @@ fn list_test_macros() {
535694
attr_noop [Attr]
536695
attr_panic [Attr]
537696
attr_error [Attr]
697+
DeriveReemit [CustomDerive]
538698
DeriveEmpty [CustomDerive]
539699
DerivePanic [CustomDerive]
540700
DeriveError [CustomDerive]"#]]

0 commit comments

Comments
 (0)