Skip to content

Commit

Permalink
Add DefinedMacros handler
Browse files Browse the repository at this point in the history
commit-id:7587de32
  • Loading branch information
Draggu committed Nov 8, 2024
1 parent c5291c0 commit c66080d
Show file tree
Hide file tree
Showing 6 changed files with 145 additions and 9 deletions.
20 changes: 19 additions & 1 deletion scarb/src/compiler/plugin/proc_macro/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,7 +107,7 @@ impl ProcMacroInstance {
self.package_id
}

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

pub fn declared_attributes(&self) -> Vec<String> {
self.get_expansions()
.iter()
.filter(|e| e.kind == ExpansionKind::Attr)
.map(|e| e.name.clone())
.map(Into::into)
.collect()
}

pub fn declared_derives(&self) -> Vec<String> {
self.get_expansions()
.iter()
Expand All @@ -134,6 +143,15 @@ impl ProcMacroInstance {
.collect()
}

pub fn inline_macros(&self) -> Vec<String> {
self.get_expansions()
.iter()
.filter(|e| e.kind == ExpansionKind::Inline)
.map(|e| e.name.clone())
.map(Into::into)
.collect()
}

/// Apply expansion to token stream.
///
/// This function implements the actual calls to functions from the dynamic library.
Expand Down
6 changes: 5 additions & 1 deletion scarb/src/compiler/plugin/proc_macro/host.rs
Original file line number Diff line number Diff line change
Expand Up @@ -946,7 +946,7 @@ impl MacroPlugin for ProcMacroHostPlugin {
fn declared_attributes(&self) -> Vec<String> {
self.macros
.iter()
.flat_map(|m| m.declared_attributes())
.flat_map(|m| m.declared_attributes_and_executables())
.chain(vec![FULL_PATH_MARKER_KEY.to_string()])
.collect()
}
Expand Down Expand Up @@ -1101,4 +1101,8 @@ impl ProcMacroHost {
pub fn into_plugin(self) -> Result<ProcMacroHostPlugin> {
ProcMacroHostPlugin::try_new(self.macros)
}

pub fn macros(&self) -> &[Arc<ProcMacroInstance>] {
&self.macros
}
}
49 changes: 49 additions & 0 deletions scarb/src/ops/proc_macro_server/methods/defined_macros.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
use std::sync::Arc;

use anyhow::Result;
use scarb_proc_macro_server_types::methods::defined_macros::{
DefinedMacros, DefinedMacrosResponse,
};

use super::Handler;
use crate::compiler::plugin::proc_macro::ProcMacroHost;

impl Handler for DefinedMacros {
fn handle(
proc_macro_host: Arc<ProcMacroHost>,
_params: Self::Params,
) -> Result<Self::Response> {
let mut response = proc_macro_host
.macros()
.iter()
.map(|e| DefinedMacrosResponse {
attributes: e.declared_attributes(),
inline_macros: e.inline_macros(),
derives: e.declared_derives(),
executables: e.executable_attributes(),
})
.reduce(|mut acc, defined_macros| {
acc.attributes.extend(defined_macros.attributes);
acc.inline_macros.extend(defined_macros.inline_macros);
acc.derives.extend(defined_macros.derives);
acc.executables.extend(defined_macros.executables);

acc
})
.unwrap_or_default();

response.attributes.sort();
response.attributes.dedup();

response.inline_macros.sort();
response.inline_macros.dedup();

response.derives.sort();
response.derives.dedup();

response.executables.sort();
response.executables.dedup();

Ok(response)
}
}
12 changes: 12 additions & 0 deletions scarb/src/ops/proc_macro_server/methods/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
use std::sync::Arc;

use anyhow::Result;
use scarb_proc_macro_server_types::methods::Method;

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

pub mod defined_macros;

pub trait Handler: Method {
fn handle(proc_macro_host: Arc<ProcMacroHost>, params: Self::Params) -> Result<Self::Response>;
}
29 changes: 22 additions & 7 deletions scarb/src/ops/proc_macro_server/mod.rs
Original file line number Diff line number Diff line change
@@ -1,28 +1,35 @@
use std::num::NonZero;
use std::sync::Arc;
use std::thread::available_parallelism;

use anyhow::{anyhow, Result};
use connection::Connection;
use crossbeam_channel::{Receiver, Sender};
use methods::Handler;
use scarb_proc_macro_server_types::jsonrpc::{ResponseError, RpcRequest, RpcResponse};
use scarb_proc_macro_server_types::methods::defined_macros::DefinedMacros;
use scarb_proc_macro_server_types::methods::Method;
use serde_json::Value;

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

mod connection;
mod methods;

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

for i in 0..available_parallelism {
let receiver = connection.receiver.clone();
let sender = connection.sender.clone();
let proc_macros = proc_macros.clone();

std::thread::Builder::new()
.name(format!("proc-macro-server-worker-thread-{i}"))
.spawn(move || {
handle_requests(receiver, sender);
handle_requests(proc_macros, receiver, sender);
})
.expect("failed to spawn thread");
}
Expand All @@ -32,10 +39,14 @@ pub fn start_proc_macro_server(_proc_macros: ProcMacroHost) -> Result<()> {
Ok(())
}

fn handle_requests(receiver: Receiver<RpcRequest>, sender: Sender<RpcResponse>) {
fn handle_requests(
proc_macros: Arc<ProcMacroHost>,
receiver: Receiver<RpcRequest>,
sender: Sender<RpcResponse>,
) {
for request in receiver {
let id = request.id;
let response = route_request(request);
let response = route_request(proc_macros.clone(), request);

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

fn route_request(request: RpcRequest) -> Result<Value> {
#[allow(clippy::match_single_binding)]
fn route_request(proc_macros: Arc<ProcMacroHost>, request: RpcRequest) -> Result<Value> {
match request.method.as_str() {
//TODO add method handlers
DefinedMacros::METHOD => run_handler::<DefinedMacros>(proc_macros.clone(), request.value),
_ => Err(anyhow!("method not found")),
}
}

fn run_handler<M: Handler>(proc_macros: Arc<ProcMacroHost>, value: Value) -> Result<Value> {
M::handle(proc_macros, serde_json::from_value(value).unwrap())
.map(|res| serde_json::to_value(res).unwrap())
}
38 changes: 38 additions & 0 deletions scarb/tests/proc_macro_server.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
use assert_fs::prelude::PathChild;
use assert_fs::TempDir;
use scarb_proc_macro_server_types::methods::defined_macros::DefinedMacros;
use scarb_proc_macro_server_types::methods::defined_macros::DefinedMacrosParams;
use scarb_test_support::cairo_plugin_project_builder::CairoPluginProjectBuilder;
use scarb_test_support::proc_macro_server::ProcMacroClient;
use scarb_test_support::proc_macro_server::SIMPLE_MACROS;
use scarb_test_support::project_builder::ProjectBuilder;

#[test]
fn defined_macros() {
let t = TempDir::new().unwrap();
let plugin_package = t.child("some");

CairoPluginProjectBuilder::default()
.lib_rs(SIMPLE_MACROS)
.build(&plugin_package);

let project = t.child("test_package");

ProjectBuilder::start()
.name("test_package")
.version("1.0.0")
.lib_cairo("")
.dep("some", plugin_package)
.build(&project);

let mut proc_macro_server = ProcMacroClient::new(&project);

let response = proc_macro_server
.request_and_wait::<DefinedMacros>(DefinedMacrosParams {})
.unwrap();

assert_eq!(response.attributes, vec!["some".to_string()]);
assert_eq!(response.derives, vec!["some_derive".to_string()]);
assert_eq!(response.inline_macros, vec!["inline_some".to_string()]);
assert_eq!(response.executables, vec!["some_executable".to_string()]);
}

0 comments on commit c66080d

Please sign in to comment.