Skip to content

Commit d4b53f5

Browse files
committed
Decouple proc-macro server protocol from the server implementation
1 parent b570206 commit d4b53f5

File tree

17 files changed

+243
-218
lines changed

17 files changed

+243
-218
lines changed

src/tools/rust-analyzer/Cargo.lock

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1375,7 +1375,6 @@ dependencies = [
13751375
"memmap2",
13761376
"object 0.33.0",
13771377
"paths",
1378-
"proc-macro-api",
13791378
"proc-macro-test",
13801379
"ra-ap-rustc_lexer",
13811380
"span",

src/tools/rust-analyzer/crates/load-cargo/src/lib.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ use ide_db::{
1414
prime_caches, ChangeWithProcMacros, FxHashMap, RootDatabase,
1515
};
1616
use itertools::Itertools;
17-
use proc_macro_api::{MacroDylib, ProcMacroServer};
17+
use proc_macro_api::{MacroDylib, ProcMacroClient};
1818
use project_model::{CargoConfig, PackageRoot, ProjectManifest, ProjectWorkspace};
1919
use span::Span;
2020
use vfs::{
@@ -42,7 +42,7 @@ pub fn load_workspace_at(
4242
cargo_config: &CargoConfig,
4343
load_config: &LoadCargoConfig,
4444
progress: &dyn Fn(String),
45-
) -> anyhow::Result<(RootDatabase, vfs::Vfs, Option<ProcMacroServer>)> {
45+
) -> anyhow::Result<(RootDatabase, vfs::Vfs, Option<ProcMacroClient>)> {
4646
let root = AbsPathBuf::assert_utf8(std::env::current_dir()?.join(root));
4747
let root = ProjectManifest::discover_single(&root)?;
4848
let mut workspace = ProjectWorkspace::load(root, cargo_config, progress)?;
@@ -59,7 +59,7 @@ pub fn load_workspace(
5959
ws: ProjectWorkspace,
6060
extra_env: &FxHashMap<String, String>,
6161
load_config: &LoadCargoConfig,
62-
) -> anyhow::Result<(RootDatabase, vfs::Vfs, Option<ProcMacroServer>)> {
62+
) -> anyhow::Result<(RootDatabase, vfs::Vfs, Option<ProcMacroClient>)> {
6363
let (sender, receiver) = unbounded();
6464
let mut vfs = vfs::Vfs::default();
6565
let mut loader = {
@@ -71,10 +71,10 @@ pub fn load_workspace(
7171
let proc_macro_server = match &load_config.with_proc_macro_server {
7272
ProcMacroServerChoice::Sysroot => ws
7373
.find_sysroot_proc_macro_srv()
74-
.and_then(|it| ProcMacroServer::spawn(&it, extra_env).map_err(Into::into))
74+
.and_then(|it| ProcMacroClient::spawn(&it, extra_env).map_err(Into::into))
7575
.map_err(|e| (e, true)),
7676
ProcMacroServerChoice::Explicit(path) => {
77-
ProcMacroServer::spawn(path, extra_env).map_err(Into::into).map_err(|e| (e, true))
77+
ProcMacroClient::spawn(path, extra_env).map_err(Into::into).map_err(|e| (e, true))
7878
}
7979
ProcMacroServerChoice::None => {
8080
Err((anyhow::format_err!("proc macro server disabled"), false))
@@ -362,7 +362,7 @@ impl SourceRootConfig {
362362

363363
/// Load the proc-macros for the given lib path, disabling all expanders whose names are in `ignored_macros`.
364364
pub fn load_proc_macro(
365-
server: &ProcMacroServer,
365+
server: &ProcMacroClient,
366366
path: &AbsPath,
367367
ignored_macros: &[Box<str>],
368368
) -> ProcMacroLoadResult {

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

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,18 +13,16 @@ use paths::{AbsPath, AbsPathBuf};
1313
use span::Span;
1414
use std::{fmt, io, sync::Arc};
1515

16-
use serde::{Deserialize, Serialize};
17-
1816
use crate::{
1917
msg::{
2018
deserialize_span_data_index_map, flat::serialize_span_data_index_map, ExpandMacro,
2119
ExpnGlobals, FlatTree, PanicMessage, SpanDataIndexMap, HAS_GLOBAL_SPANS,
2220
RUST_ANALYZER_SPAN_SUPPORT,
2321
},
24-
process::ProcMacroProcessSrv,
22+
process::ProcMacroServerProcess,
2523
};
2624

27-
#[derive(Copy, Clone, Eq, PartialEq, Debug, Serialize, Deserialize)]
25+
#[derive(Copy, Clone, Eq, PartialEq, Debug, serde_derive::Serialize, serde_derive::Deserialize)]
2826
pub enum ProcMacroKind {
2927
CustomDerive,
3028
Attr,
@@ -37,12 +35,12 @@ pub enum ProcMacroKind {
3735
/// A handle to an external process which load dylibs with macros (.so or .dll)
3836
/// and runs actual macro expansion functions.
3937
#[derive(Debug)]
40-
pub struct ProcMacroServer {
38+
pub struct ProcMacroClient {
4139
/// Currently, the proc macro process expands all procedural macros sequentially.
4240
///
4341
/// That means that concurrent salsa requests may block each other when expanding proc macros,
4442
/// which is unfortunate, but simple and good enough for the time being.
45-
process: Arc<ProcMacroProcessSrv>,
43+
process: Arc<ProcMacroServerProcess>,
4644
path: AbsPathBuf,
4745
}
4846

@@ -62,7 +60,7 @@ impl MacroDylib {
6260
/// we share a single expander process for all macros.
6361
#[derive(Debug, Clone)]
6462
pub struct ProcMacro {
65-
process: Arc<ProcMacroProcessSrv>,
63+
process: Arc<ProcMacroServerProcess>,
6664
dylib_path: Arc<AbsPathBuf>,
6765
name: Box<str>,
6866
kind: ProcMacroKind,
@@ -95,15 +93,15 @@ impl fmt::Display for ServerError {
9593
}
9694
}
9795

98-
impl ProcMacroServer {
96+
impl ProcMacroClient {
9997
/// Spawns an external process as the proc macro server and returns a client connected to it.
10098
pub fn spawn(
10199
process_path: &AbsPath,
102100
env: impl IntoIterator<Item = (impl AsRef<std::ffi::OsStr>, impl AsRef<std::ffi::OsStr>)>
103101
+ Clone,
104-
) -> io::Result<ProcMacroServer> {
105-
let process = ProcMacroProcessSrv::run(process_path, env)?;
106-
Ok(ProcMacroServer { process: Arc::new(process), path: process_path.to_owned() })
102+
) -> io::Result<ProcMacroClient> {
103+
let process = ProcMacroServerProcess::run(process_path, env)?;
104+
Ok(ProcMacroClient { process: Arc::new(process), path: process_path.to_owned() })
107105
}
108106

109107
pub fn path(&self) -> &AbsPath {

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ use crate::ProcMacroKind;
1111

1212
pub use crate::msg::flat::{
1313
deserialize_span_data_index_map, serialize_span_data_index_map, FlatTree, SpanDataIndexMap,
14-
TokenId,
1514
};
15+
pub use span::TokenId;
1616

1717
// The versions of the server protocol
1818
pub const NO_VERSION_CHECK_VERSION: u32 = 0;

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

Lines changed: 3 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,9 @@ use std::collections::VecDeque;
4040
use intern::Symbol;
4141
use rustc_hash::FxHashMap;
4242
use serde_derive::{Deserialize, Serialize};
43-
use span::{EditionedFileId, ErasedFileAstId, Span, SpanAnchor, SyntaxContextId, TextRange};
43+
use span::{
44+
EditionedFileId, ErasedFileAstId, Span, SpanAnchor, SyntaxContextId, TextRange, TokenId,
45+
};
4446

4547
use crate::msg::{ENCODE_CLOSE_SPAN_VERSION, EXTENDED_LEAF_DATA};
4648

@@ -78,15 +80,6 @@ pub fn deserialize_span_data_index_map(map: &[u32]) -> SpanDataIndexMap {
7880
.collect()
7981
}
8082

81-
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
82-
pub struct TokenId(pub u32);
83-
84-
impl std::fmt::Debug for TokenId {
85-
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
86-
self.0.fmt(f)
87-
}
88-
}
89-
9083
#[derive(Serialize, Deserialize, Debug)]
9184
pub struct FlatTree {
9285
subtree: Vec<u32>,

src/tools/rust-analyzer/crates/proc-macro-api/src/process.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use crate::{
1717
};
1818

1919
#[derive(Debug)]
20-
pub(crate) struct ProcMacroProcessSrv {
20+
pub(crate) struct ProcMacroServerProcess {
2121
/// The state of the proc-macro server process, the protocol is currently strictly sequential
2222
/// hence the lock on the state.
2323
state: Mutex<ProcessSrvState>,
@@ -34,17 +34,17 @@ struct ProcessSrvState {
3434
stdout: BufReader<ChildStdout>,
3535
}
3636

37-
impl ProcMacroProcessSrv {
37+
impl ProcMacroServerProcess {
3838
pub(crate) fn run(
3939
process_path: &AbsPath,
4040
env: impl IntoIterator<Item = (impl AsRef<std::ffi::OsStr>, impl AsRef<std::ffi::OsStr>)>
4141
+ Clone,
42-
) -> io::Result<ProcMacroProcessSrv> {
42+
) -> io::Result<ProcMacroServerProcess> {
4343
let create_srv = |null_stderr| {
4444
let mut process = Process::run(process_path, env.clone(), null_stderr)?;
4545
let (stdin, stdout) = process.stdio().expect("couldn't access child stdio");
4646

47-
io::Result::Ok(ProcMacroProcessSrv {
47+
io::Result::Ok(ProcMacroServerProcess {
4848
state: Mutex::new(ProcessSrvState { process, stdin, stdout }),
4949
version: 0,
5050
mode: SpanMode::Id,

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

Lines changed: 7 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@
66
#[cfg(feature = "in-rust-tree")]
77
extern crate rustc_driver as _;
88

9-
use std::io;
9+
#[cfg(any(feature = "sysroot-abi", rust_analyzer))]
10+
mod main_loop;
11+
#[cfg(any(feature = "sysroot-abi", rust_analyzer))]
12+
use main_loop::run;
1013

1114
fn main() -> std::io::Result<()> {
1215
let v = std::env::var("RUST_ANALYZER_INTERNALS_DO_NOT_USE");
@@ -22,57 +25,10 @@ fn main() -> std::io::Result<()> {
2225
}
2326

2427
#[cfg(not(any(feature = "sysroot-abi", rust_analyzer)))]
25-
fn run() -> io::Result<()> {
26-
Err(io::Error::new(
27-
io::ErrorKind::Unsupported,
28+
fn run() -> std::io::Result<()> {
29+
Err(std::io::Error::new(
30+
std::io::ErrorKind::Unsupported,
2831
"proc-macro-srv-cli needs to be compiled with the `sysroot-abi` feature to function"
2932
.to_owned(),
3033
))
3134
}
32-
33-
#[cfg(any(feature = "sysroot-abi", rust_analyzer))]
34-
fn run() -> io::Result<()> {
35-
use proc_macro_api::{
36-
json::{read_json, write_json},
37-
msg::{self, Message},
38-
};
39-
use proc_macro_srv::EnvSnapshot;
40-
41-
let read_request =
42-
|buf: &mut String| msg::Request::read(read_json, &mut io::stdin().lock(), buf);
43-
44-
let write_response = |msg: msg::Response| msg.write(write_json, &mut io::stdout().lock());
45-
46-
let env = EnvSnapshot::default();
47-
let mut srv = proc_macro_srv::ProcMacroSrv::new(&env);
48-
let mut buf = String::new();
49-
50-
while let Some(req) = read_request(&mut buf)? {
51-
let res = match req {
52-
msg::Request::ListMacros { dylib_path } => {
53-
msg::Response::ListMacros(srv.list_macros(&dylib_path))
54-
}
55-
msg::Request::ExpandMacro(task) => match srv.span_mode() {
56-
msg::SpanMode::Id => {
57-
msg::Response::ExpandMacro(srv.expand(*task).map(|(it, _)| it))
58-
}
59-
msg::SpanMode::RustAnalyzer => msg::Response::ExpandMacroExtended(
60-
srv.expand(*task).map(|(tree, span_data_table)| msg::ExpandMacroExtended {
61-
tree,
62-
span_data_table,
63-
}),
64-
),
65-
},
66-
msg::Request::ApiVersionCheck {} => {
67-
msg::Response::ApiVersionCheck(proc_macro_api::msg::CURRENT_API_VERSION)
68-
}
69-
msg::Request::SetConfig(config) => {
70-
srv.set_span_mode(config.span_mode);
71-
msg::Response::SetConfig(config)
72-
}
73-
};
74-
write_response(res)?
75-
}
76-
77-
Ok(())
78-
}
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
//! The main loop of the proc-macro server.
2+
use std::io;
3+
4+
use proc_macro_api::{
5+
json::{read_json, write_json},
6+
msg::{
7+
self, deserialize_span_data_index_map, serialize_span_data_index_map, ExpandMacroData,
8+
ExpnGlobals, Message, SpanMode, TokenId, CURRENT_API_VERSION,
9+
},
10+
};
11+
use proc_macro_srv::EnvSnapshot;
12+
13+
pub(crate) fn run() -> io::Result<()> {
14+
fn macro_kind_to_api(kind: proc_macro_srv::ProcMacroKind) -> proc_macro_api::ProcMacroKind {
15+
match kind {
16+
proc_macro_srv::ProcMacroKind::CustomDerive => {
17+
proc_macro_api::ProcMacroKind::CustomDerive
18+
}
19+
proc_macro_srv::ProcMacroKind::Bang => proc_macro_api::ProcMacroKind::Bang,
20+
proc_macro_srv::ProcMacroKind::Attr => proc_macro_api::ProcMacroKind::Attr,
21+
}
22+
}
23+
24+
let read_request =
25+
|buf: &mut String| msg::Request::read(read_json, &mut io::stdin().lock(), buf);
26+
27+
let write_response = |msg: msg::Response| msg.write(write_json, &mut io::stdout().lock());
28+
29+
let env = EnvSnapshot::default();
30+
let mut srv = proc_macro_srv::ProcMacroSrv::new(&env);
31+
let mut buf = String::new();
32+
33+
let mut span_mode = SpanMode::Id;
34+
35+
while let Some(req) = read_request(&mut buf)? {
36+
let res = match req {
37+
msg::Request::ListMacros { dylib_path } => {
38+
msg::Response::ListMacros(srv.list_macros(&dylib_path).map(|macros| {
39+
macros.into_iter().map(|(name, kind)| (name, macro_kind_to_api(kind))).collect()
40+
}))
41+
}
42+
msg::Request::ExpandMacro(task) => {
43+
let msg::ExpandMacro {
44+
lib,
45+
env,
46+
current_dir,
47+
data:
48+
ExpandMacroData {
49+
macro_body,
50+
macro_name,
51+
attributes,
52+
has_global_spans:
53+
ExpnGlobals { serialize: _, def_site, call_site, mixed_site },
54+
span_data_table,
55+
},
56+
} = *task;
57+
match span_mode {
58+
SpanMode::Id => msg::Response::ExpandMacro({
59+
let def_site = TokenId(def_site as u32);
60+
let call_site = TokenId(call_site as u32);
61+
let mixed_site = TokenId(mixed_site as u32);
62+
63+
let macro_body = macro_body.to_subtree_unresolved(CURRENT_API_VERSION);
64+
let attributes =
65+
attributes.map(|it| it.to_subtree_unresolved(CURRENT_API_VERSION));
66+
67+
srv.expand(
68+
lib,
69+
env,
70+
current_dir,
71+
macro_name,
72+
macro_body,
73+
attributes,
74+
def_site,
75+
call_site,
76+
mixed_site,
77+
)
78+
.map(|it| msg::FlatTree::new_raw(&it, CURRENT_API_VERSION))
79+
.map_err(msg::PanicMessage)
80+
}),
81+
SpanMode::RustAnalyzer => msg::Response::ExpandMacroExtended({
82+
let mut span_data_table = deserialize_span_data_index_map(&span_data_table);
83+
84+
let def_site = span_data_table[def_site];
85+
let call_site = span_data_table[call_site];
86+
let mixed_site = span_data_table[mixed_site];
87+
88+
let macro_body =
89+
macro_body.to_subtree_resolved(CURRENT_API_VERSION, &span_data_table);
90+
let attributes = attributes.map(|it| {
91+
it.to_subtree_resolved(CURRENT_API_VERSION, &span_data_table)
92+
});
93+
srv.expand(
94+
lib,
95+
env,
96+
current_dir,
97+
macro_name,
98+
macro_body,
99+
attributes,
100+
def_site,
101+
call_site,
102+
mixed_site,
103+
)
104+
.map(|it| {
105+
(
106+
msg::FlatTree::new(&it, CURRENT_API_VERSION, &mut span_data_table),
107+
serialize_span_data_index_map(&span_data_table),
108+
)
109+
})
110+
.map(|(tree, span_data_table)| msg::ExpandMacroExtended {
111+
tree,
112+
span_data_table,
113+
})
114+
.map_err(msg::PanicMessage)
115+
}),
116+
}
117+
}
118+
msg::Request::ApiVersionCheck {} => msg::Response::ApiVersionCheck(CURRENT_API_VERSION),
119+
msg::Request::SetConfig(config) => {
120+
span_mode = config.span_mode;
121+
msg::Response::SetConfig(config)
122+
}
123+
};
124+
write_response(res)?
125+
}
126+
127+
Ok(())
128+
}

src/tools/rust-analyzer/crates/proc-macro-srv/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@ syntax-bridge.workspace = true
2323
paths.workspace = true
2424
# span = {workspace = true, default-features = false} does not work
2525
span = { path = "../span", version = "0.0.0", default-features = false}
26-
proc-macro-api.workspace = true
2726
intern.workspace = true
2827

2928
ra-ap-rustc_lexer.workspace = true

0 commit comments

Comments
 (0)