Skip to content

Commit 7f932b2

Browse files
authored
Add DefinedMacros handler (#1683)
**Stack**: - #1686 - #1685 - #1684 - #1683 ⬅ - #1718 ⚠️ *Part of a stack created by [spr](https://github.com/ejoffe/spr). Do not merge manually using the UI - doing so may have unexpected results.*
1 parent db646d0 commit 7f932b2

File tree

6 files changed

+145
-9
lines changed

6 files changed

+145
-9
lines changed

scarb/src/compiler/plugin/proc_macro/ffi.rs

+19-1
Original file line numberDiff line numberDiff line change
@@ -107,7 +107,7 @@ impl ProcMacroInstance {
107107
self.package_id
108108
}
109109

110-
pub fn declared_attributes(&self) -> Vec<String> {
110+
pub fn declared_attributes_and_executables(&self) -> Vec<String> {
111111
self.get_expansions()
112112
.iter()
113113
.filter(|e| e.kind == ExpansionKind::Attr || e.kind == ExpansionKind::Executable)
@@ -116,6 +116,15 @@ impl ProcMacroInstance {
116116
.collect()
117117
}
118118

119+
pub fn declared_attributes(&self) -> Vec<String> {
120+
self.get_expansions()
121+
.iter()
122+
.filter(|e| e.kind == ExpansionKind::Attr)
123+
.map(|e| e.name.clone())
124+
.map(Into::into)
125+
.collect()
126+
}
127+
119128
pub fn declared_derives(&self) -> Vec<String> {
120129
self.get_expansions()
121130
.iter()
@@ -134,6 +143,15 @@ impl ProcMacroInstance {
134143
.collect()
135144
}
136145

146+
pub fn inline_macros(&self) -> Vec<String> {
147+
self.get_expansions()
148+
.iter()
149+
.filter(|e| e.kind == ExpansionKind::Inline)
150+
.map(|e| e.name.clone())
151+
.map(Into::into)
152+
.collect()
153+
}
154+
137155
/// Apply expansion to token stream.
138156
///
139157
/// This function implements the actual calls to functions from the dynamic library.

scarb/src/compiler/plugin/proc_macro/host.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -946,7 +946,7 @@ impl MacroPlugin for ProcMacroHostPlugin {
946946
fn declared_attributes(&self) -> Vec<String> {
947947
self.macros
948948
.iter()
949-
.flat_map(|m| m.declared_attributes())
949+
.flat_map(|m| m.declared_attributes_and_executables())
950950
.chain(vec![FULL_PATH_MARKER_KEY.to_string()])
951951
.collect()
952952
}
@@ -1101,4 +1101,8 @@ impl ProcMacroHost {
11011101
pub fn into_plugin(self) -> Result<ProcMacroHostPlugin> {
11021102
ProcMacroHostPlugin::try_new(self.macros)
11031103
}
1104+
1105+
pub fn macros(&self) -> &[Arc<ProcMacroInstance>] {
1106+
&self.macros
1107+
}
11041108
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
use std::sync::Arc;
2+
3+
use anyhow::Result;
4+
use scarb_proc_macro_server_types::methods::defined_macros::{
5+
DefinedMacros, DefinedMacrosResponse,
6+
};
7+
8+
use super::Handler;
9+
use crate::compiler::plugin::proc_macro::ProcMacroHost;
10+
11+
impl Handler for DefinedMacros {
12+
fn handle(
13+
proc_macro_host: Arc<ProcMacroHost>,
14+
_params: Self::Params,
15+
) -> Result<Self::Response> {
16+
let mut response = proc_macro_host
17+
.macros()
18+
.iter()
19+
.map(|e| DefinedMacrosResponse {
20+
attributes: e.declared_attributes(),
21+
inline_macros: e.inline_macros(),
22+
derives: e.declared_derives(),
23+
executables: e.executable_attributes(),
24+
})
25+
.reduce(|mut acc, defined_macros| {
26+
acc.attributes.extend(defined_macros.attributes);
27+
acc.inline_macros.extend(defined_macros.inline_macros);
28+
acc.derives.extend(defined_macros.derives);
29+
acc.executables.extend(defined_macros.executables);
30+
31+
acc
32+
})
33+
.unwrap_or_default();
34+
35+
response.attributes.sort();
36+
response.attributes.dedup();
37+
38+
response.inline_macros.sort();
39+
response.inline_macros.dedup();
40+
41+
response.derives.sort();
42+
response.derives.dedup();
43+
44+
response.executables.sort();
45+
response.executables.dedup();
46+
47+
Ok(response)
48+
}
49+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
use std::sync::Arc;
2+
3+
use anyhow::Result;
4+
use scarb_proc_macro_server_types::methods::Method;
5+
6+
use crate::compiler::plugin::proc_macro::ProcMacroHost;
7+
8+
pub mod defined_macros;
9+
10+
pub trait Handler: Method {
11+
fn handle(proc_macro_host: Arc<ProcMacroHost>, params: Self::Params) -> Result<Self::Response>;
12+
}

scarb/src/ops/proc_macro_server/mod.rs

+22-7
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,35 @@
11
use std::num::NonZero;
2+
use std::sync::Arc;
23
use std::thread::available_parallelism;
34

45
use anyhow::{anyhow, Result};
56
use connection::Connection;
67
use crossbeam_channel::{Receiver, Sender};
8+
use methods::Handler;
79
use scarb_proc_macro_server_types::jsonrpc::{ResponseError, RpcRequest, RpcResponse};
10+
use scarb_proc_macro_server_types::methods::defined_macros::DefinedMacros;
11+
use scarb_proc_macro_server_types::methods::Method;
812
use serde_json::Value;
913

1014
use crate::compiler::plugin::proc_macro::ProcMacroHost;
1115

1216
mod connection;
17+
mod methods;
1318

14-
pub fn start_proc_macro_server(_proc_macros: ProcMacroHost) -> Result<()> {
19+
pub fn start_proc_macro_server(proc_macros: ProcMacroHost) -> Result<()> {
1520
let connection = Connection::new();
1621
let available_parallelism = available_parallelism().map(NonZero::get).unwrap_or(4);
22+
let proc_macros = Arc::new(proc_macros);
1723

1824
for i in 0..available_parallelism {
1925
let receiver = connection.receiver.clone();
2026
let sender = connection.sender.clone();
27+
let proc_macros = proc_macros.clone();
2128

2229
std::thread::Builder::new()
2330
.name(format!("proc-macro-server-worker-thread-{i}"))
2431
.spawn(move || {
25-
handle_requests(receiver, sender);
32+
handle_requests(proc_macros, receiver, sender);
2633
})
2734
.expect("failed to spawn thread");
2835
}
@@ -32,10 +39,14 @@ pub fn start_proc_macro_server(_proc_macros: ProcMacroHost) -> Result<()> {
3239
Ok(())
3340
}
3441

35-
fn handle_requests(receiver: Receiver<RpcRequest>, sender: Sender<RpcResponse>) {
42+
fn handle_requests(
43+
proc_macros: Arc<ProcMacroHost>,
44+
receiver: Receiver<RpcRequest>,
45+
sender: Sender<RpcResponse>,
46+
) {
3647
for request in receiver {
3748
let id = request.id;
38-
let response = route_request(request);
49+
let response = route_request(proc_macros.clone(), request);
3950

4051
let response = match response {
4152
Ok(result) => RpcResponse {
@@ -56,10 +67,14 @@ fn handle_requests(receiver: Receiver<RpcRequest>, sender: Sender<RpcResponse>)
5667
}
5768
}
5869

59-
fn route_request(request: RpcRequest) -> Result<Value> {
60-
#[allow(clippy::match_single_binding)]
70+
fn route_request(proc_macros: Arc<ProcMacroHost>, request: RpcRequest) -> Result<Value> {
6171
match request.method.as_str() {
62-
//TODO add method handlers
72+
DefinedMacros::METHOD => run_handler::<DefinedMacros>(proc_macros.clone(), request.value),
6373
_ => Err(anyhow!("method not found")),
6474
}
6575
}
76+
77+
fn run_handler<M: Handler>(proc_macros: Arc<ProcMacroHost>, value: Value) -> Result<Value> {
78+
M::handle(proc_macros, serde_json::from_value(value).unwrap())
79+
.map(|res| serde_json::to_value(res).unwrap())
80+
}

scarb/tests/proc_macro_server.rs

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
use assert_fs::prelude::PathChild;
2+
use assert_fs::TempDir;
3+
use scarb_proc_macro_server_types::methods::defined_macros::DefinedMacros;
4+
use scarb_proc_macro_server_types::methods::defined_macros::DefinedMacrosParams;
5+
use scarb_test_support::cairo_plugin_project_builder::CairoPluginProjectBuilder;
6+
use scarb_test_support::proc_macro_server::ProcMacroClient;
7+
use scarb_test_support::proc_macro_server::SIMPLE_MACROS;
8+
use scarb_test_support::project_builder::ProjectBuilder;
9+
10+
#[test]
11+
fn defined_macros() {
12+
let t = TempDir::new().unwrap();
13+
let plugin_package = t.child("some");
14+
15+
CairoPluginProjectBuilder::default()
16+
.lib_rs(SIMPLE_MACROS)
17+
.build(&plugin_package);
18+
19+
let project = t.child("test_package");
20+
21+
ProjectBuilder::start()
22+
.name("test_package")
23+
.version("1.0.0")
24+
.lib_cairo("")
25+
.dep("some", plugin_package)
26+
.build(&project);
27+
28+
let mut proc_macro_server = ProcMacroClient::new(&project);
29+
30+
let response = proc_macro_server
31+
.request_and_wait::<DefinedMacros>(DefinedMacrosParams {})
32+
.unwrap();
33+
34+
assert_eq!(response.attributes, vec!["some".to_string()]);
35+
assert_eq!(response.derives, vec!["some_derive".to_string()]);
36+
assert_eq!(response.inline_macros, vec!["inline_some".to_string()]);
37+
assert_eq!(response.executables, vec!["some_executable".to_string()]);
38+
}

0 commit comments

Comments
 (0)