rust-analyzer/crates/proc-macro-srv-cli/src/main_loop.rs
Chayim Refael Friedman 4bcf03e28b Use stable AST IDs
Instead of simple numbering, we hash important bits, like the name of the item.

This will allow for much better incrementality, e.g. when you add an item. Currently, this invalidates the IDs of all following items, which invalidates pretty much everything.
2025-06-12 08:47:22 +03:00

135 lines
5.6 KiB
Rust

//! The main loop of the proc-macro server.
use std::io;
use proc_macro_api::legacy_protocol::{
json::{read_json, write_json},
msg::{
self, CURRENT_API_VERSION, ExpandMacroData, ExpnGlobals, Message, SpanMode, TokenId,
deserialize_span_data_index_map, serialize_span_data_index_map,
},
};
use proc_macro_srv::EnvSnapshot;
pub(crate) fn run() -> io::Result<()> {
fn macro_kind_to_api(kind: proc_macro_srv::ProcMacroKind) -> proc_macro_api::ProcMacroKind {
match kind {
proc_macro_srv::ProcMacroKind::CustomDerive => {
proc_macro_api::ProcMacroKind::CustomDerive
}
proc_macro_srv::ProcMacroKind::Bang => proc_macro_api::ProcMacroKind::Bang,
proc_macro_srv::ProcMacroKind::Attr => proc_macro_api::ProcMacroKind::Attr,
}
}
let mut buf = String::new();
let mut read_request = || msg::Request::read(read_json, &mut io::stdin().lock(), &mut buf);
let write_response = |msg: msg::Response| msg.write(write_json, &mut io::stdout().lock());
let env = EnvSnapshot::default();
let mut srv = proc_macro_srv::ProcMacroSrv::new(&env);
let mut span_mode = SpanMode::Id;
while let Some(req) = read_request()? {
let res = match req {
msg::Request::ListMacros { dylib_path } => {
msg::Response::ListMacros(srv.list_macros(&dylib_path).map(|macros| {
macros.into_iter().map(|(name, kind)| (name, macro_kind_to_api(kind))).collect()
}))
}
msg::Request::ExpandMacro(task) => {
let msg::ExpandMacro {
lib,
env,
current_dir,
data:
ExpandMacroData {
macro_body,
macro_name,
attributes,
has_global_spans:
ExpnGlobals { serialize: _, def_site, call_site, mixed_site },
span_data_table,
},
} = *task;
match span_mode {
SpanMode::Id => msg::Response::ExpandMacro({
let def_site = TokenId(def_site as u32);
let call_site = TokenId(call_site as u32);
let mixed_site = TokenId(mixed_site as u32);
let macro_body = macro_body.to_subtree_unresolved(CURRENT_API_VERSION);
let attributes =
attributes.map(|it| it.to_subtree_unresolved(CURRENT_API_VERSION));
srv.expand(
lib,
env,
current_dir,
macro_name,
macro_body,
attributes,
def_site,
call_site,
mixed_site,
)
.map(|it| {
msg::FlatTree::new_raw(tt::SubtreeView::new(&it), CURRENT_API_VERSION)
})
.map_err(msg::PanicMessage)
}),
SpanMode::RustAnalyzer { .. } => msg::Response::ExpandMacroExtended({
let mut span_data_table = deserialize_span_data_index_map(&span_data_table);
let def_site = span_data_table[def_site];
let call_site = span_data_table[call_site];
let mixed_site = span_data_table[mixed_site];
let macro_body =
macro_body.to_subtree_resolved(CURRENT_API_VERSION, &span_data_table);
let attributes = attributes.map(|it| {
it.to_subtree_resolved(CURRENT_API_VERSION, &span_data_table)
});
srv.expand(
lib,
env,
current_dir,
macro_name,
macro_body,
attributes,
def_site,
call_site,
mixed_site,
)
.map(|it| {
(
msg::FlatTree::new(
tt::SubtreeView::new(&it),
CURRENT_API_VERSION,
&mut span_data_table,
),
serialize_span_data_index_map(&span_data_table),
)
})
.map(|(tree, span_data_table)| msg::ExpandMacroExtended {
tree,
span_data_table,
})
.map_err(msg::PanicMessage)
}),
}
}
msg::Request::ApiVersionCheck {} => msg::Response::ApiVersionCheck(CURRENT_API_VERSION),
msg::Request::SetConfig(config) => {
span_mode = config.span_mode;
if let SpanMode::RustAnalyzer { fixup_ast_id } = span_mode {
srv.set_fixup_ast_id(fixup_ast_id);
}
msg::Response::SetConfig(config)
}
};
write_response(res)?
}
Ok(())
}