Skip to content

Commit a892237

Browse files
committed
Add rust-analyzer-span server feature equivalent to the ID server
1 parent 3ce3593 commit a892237

File tree

17 files changed

+1158
-557
lines changed

17 files changed

+1158
-557
lines changed

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/proc-macro-api/src/lib.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,10 @@ use triomphe::Arc;
2020
use serde::{Deserialize, Serialize};
2121

2222
use crate::{
23-
msg::{ExpandMacro, ExpnGlobals, FlatTree, PanicMessage, HAS_GLOBAL_SPANS},
23+
msg::{
24+
flat::serialize_span_data_index_map, ExpandMacro, ExpnGlobals, FlatTree, PanicMessage,
25+
HAS_GLOBAL_SPANS, RUST_ANALYZER_SPAN_SUPPORT,
26+
},
2427
process::ProcMacroProcessSrv,
2528
};
2629

@@ -166,6 +169,11 @@ impl ProcMacro {
166169
call_site,
167170
mixed_site,
168171
},
172+
span_data_table: if version >= RUST_ANALYZER_SPAN_SUPPORT {
173+
serialize_span_data_index_map(&span_data_table)
174+
} else {
175+
Vec::new()
176+
},
169177
};
170178

171179
let response = self
@@ -178,9 +186,7 @@ impl ProcMacro {
178186
msg::Response::ExpandMacro(it) => {
179187
Ok(it.map(|tree| FlatTree::to_subtree_resolved(tree, version, &span_data_table)))
180188
}
181-
msg::Response::ListMacros(..) | msg::Response::ApiVersionCheck(..) => {
182-
Err(ServerError { message: "unexpected response".to_string(), io: None })
183-
}
189+
_ => Err(ServerError { message: "unexpected response".to_string(), io: None }),
184190
}
185191
}
186192
}

crates/proc-macro-api/src/msg.rs

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,28 +10,42 @@ use serde::{de::DeserializeOwned, Deserialize, Serialize};
1010

1111
use crate::ProcMacroKind;
1212

13-
pub use crate::msg::flat::{FlatTree, TokenId};
13+
pub use crate::msg::flat::{
14+
deserialize_span_data_index_map, serialize_span_data_index_map, FlatTree, SpanDataIndexMap,
15+
TokenId,
16+
};
1417

1518
// The versions of the server protocol
1619
pub const NO_VERSION_CHECK_VERSION: u32 = 0;
1720
pub const VERSION_CHECK_VERSION: u32 = 1;
1821
pub const ENCODE_CLOSE_SPAN_VERSION: u32 = 2;
1922
pub const HAS_GLOBAL_SPANS: u32 = 3;
23+
pub const RUST_ANALYZER_SPAN_SUPPORT: u32 = 4;
2024

21-
pub const CURRENT_API_VERSION: u32 = HAS_GLOBAL_SPANS;
25+
pub const CURRENT_API_VERSION: u32 = RUST_ANALYZER_SPAN_SUPPORT;
2226

2327
#[derive(Debug, Serialize, Deserialize)]
2428
pub enum Request {
2529
ListMacros { dylib_path: PathBuf },
2630
ExpandMacro(ExpandMacro),
31+
SetSpanMode(SpanMode),
2732
ApiVersionCheck {},
2833
}
2934

35+
#[derive(Copy, Clone, Default, Debug, Serialize, Deserialize)]
36+
pub enum SpanMode {
37+
#[default]
38+
Id,
39+
RustAnalyzer,
40+
}
41+
3042
#[derive(Debug, Serialize, Deserialize)]
3143
pub enum Response {
3244
ListMacros(Result<Vec<(String, ProcMacroKind)>, String>),
3345
ExpandMacro(Result<FlatTree, PanicMessage>),
46+
ExpandMacroSpans(Result<(FlatTree, Vec<u32>), PanicMessage>),
3447
ApiVersionCheck(u32),
48+
SetSpanMode(SpanMode),
3549
}
3650

3751
#[derive(Debug, Serialize, Deserialize)]
@@ -64,9 +78,12 @@ pub struct ExpandMacro {
6478
#[serde(skip_serializing_if = "ExpnGlobals::skip_serializing_if")]
6579
#[serde(default)]
6680
pub has_global_spans: ExpnGlobals,
81+
#[serde(skip_serializing_if = "Vec::is_empty")]
82+
#[serde(default)]
83+
pub span_data_table: Vec<u32>,
6784
}
6885

69-
#[derive(Default, Debug, Serialize, Deserialize)]
86+
#[derive(Copy, Clone, Default, Debug, Serialize, Deserialize)]
7087
pub struct ExpnGlobals {
7188
#[serde(skip_serializing)]
7289
#[serde(default)]
@@ -241,6 +258,7 @@ mod tests {
241258
call_site: 0,
242259
mixed_site: 0,
243260
},
261+
span_data_table: Vec::new(),
244262
};
245263

246264
let json = serde_json::to_string(&task).unwrap();

crates/proc-macro-api/src/msg/flat.rs

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -38,12 +38,45 @@
3838
use std::collections::{HashMap, VecDeque};
3939

4040
use indexmap::IndexSet;
41+
use la_arena::RawIdx;
4142
use serde::{Deserialize, Serialize};
42-
use span::Span;
43+
use span::{ErasedFileAstId, FileId, Span, SpanAnchor, SyntaxContextId};
44+
use text_size::TextRange;
4345

4446
use crate::msg::ENCODE_CLOSE_SPAN_VERSION;
4547

46-
type SpanIndexMap = IndexSet<Span>;
48+
pub type SpanDataIndexMap = IndexSet<Span>;
49+
50+
pub fn serialize_span_data_index_map(map: &SpanDataIndexMap) -> Vec<u32> {
51+
map.iter()
52+
.flat_map(|span| {
53+
[
54+
span.anchor.file_id.index(),
55+
span.anchor.ast_id.into_raw().into_u32(),
56+
span.range.start().into(),
57+
span.range.end().into(),
58+
span.ctx.into_u32(),
59+
]
60+
})
61+
.collect()
62+
}
63+
64+
pub fn deserialize_span_data_index_map(map: &[u32]) -> SpanDataIndexMap {
65+
debug_assert!(map.len() % 5 == 0);
66+
map.chunks_exact(5)
67+
.map(|span| {
68+
let &[file_id, ast_id, start, end, e] = span else { unreachable!() };
69+
Span {
70+
anchor: SpanAnchor {
71+
file_id: FileId::from_raw(file_id),
72+
ast_id: ErasedFileAstId::from_raw(RawIdx::from_u32(ast_id)),
73+
},
74+
range: TextRange::new(start.into(), end.into()),
75+
ctx: SyntaxContextId::from_u32(e),
76+
}
77+
})
78+
.collect()
79+
}
4780

4881
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
4982
pub struct TokenId(pub u32);
@@ -93,7 +126,7 @@ impl FlatTree {
93126
pub fn new(
94127
subtree: &tt::Subtree<Span>,
95128
version: u32,
96-
span_data_table: &mut SpanIndexMap,
129+
span_data_table: &mut SpanDataIndexMap,
97130
) -> FlatTree {
98131
let mut w = Writer {
99132
string_table: HashMap::new(),
@@ -155,7 +188,7 @@ impl FlatTree {
155188
pub fn to_subtree_resolved(
156189
self,
157190
version: u32,
158-
span_data_table: &SpanIndexMap,
191+
span_data_table: &SpanDataIndexMap,
159192
) -> tt::Subtree<Span> {
160193
Reader {
161194
subtree: if version >= ENCODE_CLOSE_SPAN_VERSION {

crates/proc-macro-api/src/process.rs

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use paths::{AbsPath, AbsPathBuf};
99
use stdx::JodChild;
1010

1111
use crate::{
12-
msg::{Message, Request, Response, CURRENT_API_VERSION},
12+
msg::{Message, Request, Response, SpanMode, CURRENT_API_VERSION, RUST_ANALYZER_SPAN_SUPPORT},
1313
ProcMacroKind, ServerError,
1414
};
1515

@@ -19,6 +19,7 @@ pub(crate) struct ProcMacroProcessSrv {
1919
stdin: ChildStdin,
2020
stdout: BufReader<ChildStdout>,
2121
version: u32,
22+
mode: SpanMode,
2223
}
2324

2425
impl ProcMacroProcessSrv {
@@ -27,7 +28,13 @@ impl ProcMacroProcessSrv {
2728
let mut process = Process::run(process_path.clone(), null_stderr)?;
2829
let (stdin, stdout) = process.stdio().expect("couldn't access child stdio");
2930

30-
io::Result::Ok(ProcMacroProcessSrv { _process: process, stdin, stdout, version: 0 })
31+
io::Result::Ok(ProcMacroProcessSrv {
32+
_process: process,
33+
stdin,
34+
stdout,
35+
version: 0,
36+
mode: SpanMode::Id,
37+
})
3138
};
3239
let mut srv = create_srv(true)?;
3340
tracing::info!("sending version check");
@@ -43,6 +50,11 @@ impl ProcMacroProcessSrv {
4350
tracing::info!("got version {v}");
4451
srv = create_srv(false)?;
4552
srv.version = v;
53+
if srv.version > RUST_ANALYZER_SPAN_SUPPORT {
54+
if let Ok(mode) = srv.enable_rust_analyzer_spans() {
55+
srv.mode = mode;
56+
}
57+
}
4658
Ok(srv)
4759
}
4860
Err(e) => {
@@ -62,9 +74,17 @@ impl ProcMacroProcessSrv {
6274

6375
match response {
6476
Response::ApiVersionCheck(version) => Ok(version),
65-
Response::ExpandMacro { .. } | Response::ListMacros { .. } => {
66-
Err(ServerError { message: "unexpected response".to_string(), io: None })
67-
}
77+
_ => Err(ServerError { message: "unexpected response".to_string(), io: None }),
78+
}
79+
}
80+
81+
fn enable_rust_analyzer_spans(&mut self) -> Result<SpanMode, ServerError> {
82+
let request = Request::SetSpanMode(crate::msg::SpanMode::RustAnalyzer);
83+
let response = self.send_task(request)?;
84+
85+
match response {
86+
Response::SetSpanMode(span_mode) => Ok(span_mode),
87+
_ => Err(ServerError { message: "unexpected response".to_string(), io: None }),
6888
}
6989
}
7090

@@ -78,9 +98,7 @@ impl ProcMacroProcessSrv {
7898

7999
match response {
80100
Response::ListMacros(it) => Ok(it),
81-
Response::ExpandMacro { .. } | Response::ApiVersionCheck { .. } => {
82-
Err(ServerError { message: "unexpected response".to_string(), io: None })
83-
}
101+
_ => Err(ServerError { message: "unexpected response".to_string(), io: None }),
84102
}
85103
}
86104

crates/proc-macro-srv-cli/src/main.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,10 +39,17 @@ fn run() -> io::Result<()> {
3939
msg::Request::ListMacros { dylib_path } => {
4040
msg::Response::ListMacros(srv.list_macros(&dylib_path))
4141
}
42-
msg::Request::ExpandMacro(task) => msg::Response::ExpandMacro(srv.expand(task)),
42+
msg::Request::ExpandMacro(task) => match srv.span_mode() {
43+
msg::SpanMode::Id => msg::Response::ExpandMacro(srv.expand(task).map(|(it, _)| it)),
44+
msg::SpanMode::RustAnalyzer => msg::Response::ExpandMacroSpans(srv.expand(task)),
45+
},
4346
msg::Request::ApiVersionCheck {} => {
4447
msg::Response::ApiVersionCheck(proc_macro_api::msg::CURRENT_API_VERSION)
4548
}
49+
msg::Request::SetSpanMode(span_mode) => {
50+
srv.set_span_mode(span_mode);
51+
msg::Response::SetSpanMode(span_mode)
52+
}
4653
};
4754
write_response(res)?
4855
}

crates/proc-macro-srv/Cargo.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,8 @@ stdx.workspace = true
2626
tt.workspace = true
2727
mbe.workspace = true
2828
paths.workspace = true
29+
base-db.workspace = true
30+
span.workspace = true
2931
proc-macro-api.workspace = true
3032

3133
[dev-dependencies]

crates/proc-macro-srv/src/dylib.rs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,10 @@ use libloading::Library;
1111
use memmap2::Mmap;
1212
use object::Object;
1313
use paths::AbsPath;
14-
use proc_macro_api::{msg::TokenId, read_dylib_info, ProcMacroKind};
14+
use proc_macro::bridge;
15+
use proc_macro_api::{read_dylib_info, ProcMacroKind};
16+
17+
use crate::ProcMacroSrvSpan;
1518

1619
const NEW_REGISTRAR_SYMBOL: &str = "_rustc_proc_macro_decls_";
1720

@@ -147,15 +150,18 @@ impl Expander {
147150
Ok(Expander { inner: library })
148151
}
149152

150-
pub fn expand(
153+
pub fn expand<S: ProcMacroSrvSpan>(
151154
&self,
152155
macro_name: &str,
153-
macro_body: &crate::tt::Subtree,
154-
attributes: Option<&crate::tt::Subtree>,
155-
def_site: TokenId,
156-
call_site: TokenId,
157-
mixed_site: TokenId,
158-
) -> Result<crate::tt::Subtree, String> {
156+
macro_body: tt::Subtree<S>,
157+
attributes: Option<tt::Subtree<S>>,
158+
def_site: S,
159+
call_site: S,
160+
mixed_site: S,
161+
) -> Result<tt::Subtree<S>, String>
162+
where
163+
<S::Server as bridge::server::Types>::TokenStream: Default,
164+
{
159165
let result = self
160166
.inner
161167
.proc_macros

0 commit comments

Comments
 (0)