Skip to content

Commit 3be33e4

Browse files
authored
Add ExpandAttribute handler (#1684)
**Stack**: - #1686 - #1685 - #1684⚠️ *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 7f932b2 commit 3be33e4

File tree

4 files changed

+86
-0
lines changed

4 files changed

+86
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
use std::sync::Arc;
2+
3+
use anyhow::Result;
4+
use scarb_proc_macro_server_types::methods::{expand::ExpandAttribute, ProcMacroResult};
5+
6+
use super::Handler;
7+
use crate::compiler::plugin::proc_macro::{ExpansionKind, ProcMacroHost};
8+
9+
impl Handler for ExpandAttribute {
10+
fn handle(proc_macro_host: Arc<ProcMacroHost>, params: Self::Params) -> Result<Self::Response> {
11+
let instance = proc_macro_host
12+
.macros()
13+
.iter()
14+
.find(|e| {
15+
e.get_expansions()
16+
.iter()
17+
.filter(|expansion| expansion.kind == ExpansionKind::Attr)
18+
.any(|expansion| expansion.name == params.attr)
19+
})
20+
.unwrap();
21+
22+
let result = instance.generate_code(params.attr.into(), params.args, params.item);
23+
24+
Ok(ProcMacroResult {
25+
token_stream: result.token_stream,
26+
diagnostics: result.diagnostics,
27+
})
28+
}
29+
}

scarb/src/ops/proc_macro_server/methods/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use scarb_proc_macro_server_types::methods::Method;
66
use crate::compiler::plugin::proc_macro::ProcMacroHost;
77

88
pub mod defined_macros;
9+
pub mod expand_attribute;
910

1011
pub trait Handler: Method {
1112
fn handle(proc_macro_host: Arc<ProcMacroHost>, params: Self::Params) -> Result<Self::Response>;

scarb/src/ops/proc_macro_server/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use crossbeam_channel::{Receiver, Sender};
88
use methods::Handler;
99
use scarb_proc_macro_server_types::jsonrpc::{ResponseError, RpcRequest, RpcResponse};
1010
use scarb_proc_macro_server_types::methods::defined_macros::DefinedMacros;
11+
use scarb_proc_macro_server_types::methods::expand::ExpandAttribute;
1112
use scarb_proc_macro_server_types::methods::Method;
1213
use serde_json::Value;
1314

@@ -70,6 +71,9 @@ fn handle_requests(
7071
fn route_request(proc_macros: Arc<ProcMacroHost>, request: RpcRequest) -> Result<Value> {
7172
match request.method.as_str() {
7273
DefinedMacros::METHOD => run_handler::<DefinedMacros>(proc_macros.clone(), request.value),
74+
ExpandAttribute::METHOD => {
75+
run_handler::<ExpandAttribute>(proc_macros.clone(), request.value)
76+
}
7377
_ => Err(anyhow!("method not found")),
7478
}
7579
}

scarb/tests/proc_macro_server.rs

+52
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
use assert_fs::prelude::PathChild;
22
use assert_fs::TempDir;
3+
use cairo_lang_macro::TokenStream;
34
use scarb_proc_macro_server_types::methods::defined_macros::DefinedMacros;
45
use scarb_proc_macro_server_types::methods::defined_macros::DefinedMacrosParams;
6+
use scarb_proc_macro_server_types::methods::expand::ExpandAttribute;
7+
use scarb_proc_macro_server_types::methods::expand::ExpandAttributeParams;
58
use scarb_test_support::cairo_plugin_project_builder::CairoPluginProjectBuilder;
69
use scarb_test_support::proc_macro_server::ProcMacroClient;
710
use scarb_test_support::proc_macro_server::SIMPLE_MACROS;
@@ -36,3 +39,52 @@ fn defined_macros() {
3639
assert_eq!(response.inline_macros, vec!["inline_some".to_string()]);
3740
assert_eq!(response.executables, vec!["some_executable".to_string()]);
3841
}
42+
43+
#[test]
44+
fn expand_attribute() {
45+
let t = TempDir::new().unwrap();
46+
let plugin_package = t.child("some");
47+
48+
let rename_to_very_new_name = r##"
49+
#[attribute_macro]
50+
pub fn rename_to_very_new_name(_attr: TokenStream, token_stream: TokenStream) -> ProcMacroResult {{
51+
let re = regex::Regex::new(r#"fn (\w+)\(.*\)\{.*\}"#).unwrap();
52+
let input = token_stream.to_string();
53+
let name = re.captures(&input).unwrap().get(1).unwrap().as_str();
54+
55+
let output = input.replace(name, "very_new_name");
56+
57+
ProcMacroResult::new(TokenStream::new(output))
58+
}}
59+
"##;
60+
61+
CairoPluginProjectBuilder::default()
62+
.lib_rs(format!("{SIMPLE_MACROS}\n{rename_to_very_new_name}"))
63+
.add_dep(r#"regex = "1.11.1""#)
64+
.build(&plugin_package);
65+
66+
let project = t.child("test_package");
67+
68+
ProjectBuilder::start()
69+
.name("test_package")
70+
.version("1.0.0")
71+
.lib_cairo("")
72+
.dep("some", plugin_package)
73+
.build(&project);
74+
75+
let mut proc_macro_server = ProcMacroClient::new(&project);
76+
77+
let response = proc_macro_server
78+
.request_and_wait::<ExpandAttribute>(ExpandAttributeParams {
79+
attr: "rename_to_very_new_name".to_string(),
80+
args: TokenStream::empty(),
81+
item: TokenStream::new("fn some_test_fn(){}".to_string()),
82+
})
83+
.unwrap();
84+
85+
assert_eq!(response.diagnostics, vec![]);
86+
assert_eq!(
87+
response.token_stream,
88+
TokenStream::new("fn very_new_name(){}".to_string())
89+
);
90+
}

0 commit comments

Comments
 (0)