Unnamed repository; edit this file 'description' to name the repository.
-rw-r--r--crates/proc-macro-srv/src/server/rust_analyzer_span.rs63
-rw-r--r--crates/proc-macro-srv/src/tests/mod.rs19
-rw-r--r--crates/proc-macro-test/imp/src/lib.rs14
3 files changed, 80 insertions, 16 deletions
diff --git a/crates/proc-macro-srv/src/server/rust_analyzer_span.rs b/crates/proc-macro-srv/src/server/rust_analyzer_span.rs
index d8648da604..adb7ff1bdf 100644
--- a/crates/proc-macro-srv/src/server/rust_analyzer_span.rs
+++ b/crates/proc-macro-srv/src/server/rust_analyzer_span.rs
@@ -4,6 +4,7 @@ use std::{
ops::{Bound, Range},
};
+use ::tt::{TextRange, TextSize};
use proc_macro::bridge::{self, server};
use span::Span;
@@ -241,11 +242,11 @@ impl server::Span for RaSpanServer {
SourceFile {}
}
fn save_span(&mut self, _span: Self::Span) -> usize {
- // FIXME stub
+ // FIXME stub, requires builtin quote! implementation
0
}
fn recover_proc_macro_span(&mut self, _id: usize) -> Self::Span {
- // FIXME stub
+ // FIXME stub, requires builtin quote! implementation
self.call_site
}
/// Recent feature, not yet in the proc_macro
@@ -289,32 +290,64 @@ impl server::Span for RaSpanServer {
fn subspan(
&mut self,
span: Self::Span,
- _start: Bound<usize>,
- _end: Bound<usize>,
+ start: Bound<usize>,
+ end: Bound<usize>,
) -> Option<Self::Span> {
- // Just return the span again, because some macros will unwrap the result.
- Some(span)
+ // FIXME requires db to resolve the ast id, THIS IS NOT INCREMENTAL as it works on absolute
+ // ranges
+ let length = span.range.len().into();
+
+ let start: u32 = match start {
+ Bound::Included(lo) => lo,
+ Bound::Excluded(lo) => lo.checked_add(1)?,
+ Bound::Unbounded => 0,
+ }
+ .try_into()
+ .ok()?;
+
+ let end: u32 = match end {
+ Bound::Included(hi) => hi.checked_add(1)?,
+ Bound::Excluded(hi) => hi,
+ Bound::Unbounded => span.range.len().into(),
+ }
+ .try_into()
+ .ok()?;
+
+ // Bounds check the values, preventing addition overflow and OOB spans.
+ let span_start = span.range.start().into();
+ if (u32::MAX - start) < span_start
+ || (u32::MAX - end) < span_start
+ || start >= end
+ || end > length
+ {
+ return None;
+ }
+
+ Some(Span {
+ range: TextRange::new(TextSize::from(start), TextSize::from(end)) + span.range.start(),
+ ..span
+ })
}
- fn resolved_at(&mut self, _span: Self::Span, _at: Self::Span) -> Self::Span {
- // FIXME handle span
- self.call_site
+
+ fn resolved_at(&mut self, span: Self::Span, at: Self::Span) -> Self::Span {
+ Span { ctx: at.ctx, ..span }
}
- fn end(&mut self, _self_: Self::Span) -> Self::Span {
- self.call_site
+ fn end(&mut self, span: Self::Span) -> Self::Span {
+ Span { range: TextRange::empty(span.range.end()), ..span }
}
- fn start(&mut self, _self_: Self::Span) -> Self::Span {
- self.call_site
+ fn start(&mut self, span: Self::Span) -> Self::Span {
+ Span { range: TextRange::empty(span.range.start()), ..span }
}
fn line(&mut self, _span: Self::Span) -> usize {
- // FIXME handle line
+ // FIXME requires db to resolve line index, THIS IS NOT INCREMENTAL
0
}
fn column(&mut self, _span: Self::Span) -> usize {
- // FIXME handle column
+ // FIXME requires db to resolve line index, THIS IS NOT INCREMENTAL
0
}
}
diff --git a/crates/proc-macro-srv/src/tests/mod.rs b/crates/proc-macro-srv/src/tests/mod.rs
index 2320a04cf1..87d832cc76 100644
--- a/crates/proc-macro-srv/src/tests/mod.rs
+++ b/crates/proc-macro-srv/src/tests/mod.rs
@@ -106,6 +106,24 @@ fn test_fn_like_fn_like_span_join() {
}
#[test]
+fn test_fn_like_fn_like_span_ops() {
+ assert_expand(
+ "fn_like_span_ops",
+ "set_def_site resolved_at_def_site start_span",
+ expect![[r#"
+ SUBTREE $$ 1 1
+ IDENT set_def_site 0
+ IDENT resolved_at_def_site 1
+ IDENT start_span 1"#]],
+ expect![[r#"
+ SUBTREE $$ SpanData { range: 0..100, anchor: SpanAnchor(FileId(42), 2), ctx: SyntaxContextId(0) } SpanData { range: 0..100, anchor: SpanAnchor(FileId(42), 2), ctx: SyntaxContextId(0) }
+ IDENT set_def_site SpanData { range: 0..150, anchor: SpanAnchor(FileId(41), 1), ctx: SyntaxContextId(0) }
+ IDENT resolved_at_def_site SpanData { range: 13..33, anchor: SpanAnchor(FileId(42), 2), ctx: SyntaxContextId(0) }
+ IDENT start_span SpanData { range: 34..34, anchor: SpanAnchor(FileId(42), 2), ctx: SyntaxContextId(0) }"#]],
+ );
+}
+
+#[test]
fn test_fn_like_mk_literals() {
assert_expand(
"fn_like_mk_literals",
@@ -218,6 +236,7 @@ fn list_test_macros() {
fn_like_mk_literals [FuncLike]
fn_like_mk_idents [FuncLike]
fn_like_span_join [FuncLike]
+ fn_like_span_ops [FuncLike]
attr_noop [Attr]
attr_panic [Attr]
attr_error [Attr]
diff --git a/crates/proc-macro-test/imp/src/lib.rs b/crates/proc-macro-test/imp/src/lib.rs
index d0f73dca32..d9018b1b87 100644
--- a/crates/proc-macro-test/imp/src/lib.rs
+++ b/crates/proc-macro-test/imp/src/lib.rs
@@ -1,7 +1,7 @@
//! Exports a few trivial procedural macros for testing.
#![warn(rust_2018_idioms, unused_lifetimes)]
-#![feature(proc_macro_span)]
+#![feature(proc_macro_span, proc_macro_def_site)]
use proc_macro::{Group, Ident, Literal, Punct, Span, TokenStream, TokenTree};
@@ -61,6 +61,18 @@ pub fn fn_like_span_join(args: TokenStream) -> TokenStream {
)))
}
+#[proc_macro]
+pub fn fn_like_span_ops(args: TokenStream) -> TokenStream {
+ let args = &mut args.into_iter();
+ let mut first = args.next().unwrap();
+ first.set_span(Span::def_site());
+ let mut second = args.next().unwrap();
+ second.set_span(second.span().resolved_at(Span::def_site()));
+ let mut third = args.next().unwrap();
+ third.set_span(third.span().start());
+ TokenStream::from_iter(vec![first, second, third])
+}
+
#[proc_macro_attribute]
pub fn attr_noop(_args: TokenStream, item: TokenStream) -> TokenStream {
item