From 86c85bdd9ed22ef05a1868a2eb78677fa155aaec Mon Sep 17 00:00:00 2001 From: NikVolf Date: Thu, 30 Jun 2016 14:34:49 +0300 Subject: [PATCH 1/7] post expansion pass --- ipc/codegen/src/lib.rs | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/ipc/codegen/src/lib.rs b/ipc/codegen/src/lib.rs index 126aa3a85..fc737b060 100644 --- a/ipc/codegen/src/lib.rs +++ b/ipc/codegen/src/lib.rs @@ -50,11 +50,37 @@ include!("lib.rs.in"); #[cfg(feature = "with-syntex")] pub fn register(reg: &mut syntex::Registry) { + /// Strip the serde attributes from the crate. + #[cfg(feature = "with-syntex")] + fn strip_attributes(krate: ast::Crate) -> ast::Crate { + /// Helper folder that strips the serde attributes after the extensions have been expanded. + struct StripAttributeFolder; + + impl fold::Folder for StripAttributeFolder { + fn fold_attribute(&mut self, attr: ast::Attribute) -> Option { + match attr.node.value.node { + ast::MetaItemKind::List(ref n, _) if n == &"ipc" => { return None; } + _ => {} + } + + Some(attr) + } + + fn fold_mac(&mut self, mac: ast::Mac) -> ast::Mac { + fold::noop_fold_mac(mac, self) + } + } + + fold::Folder::fold_crate(&mut StripAttributeFolder, krate) + } + reg.add_attr("feature(custom_derive)"); reg.add_attr("feature(custom_attribute)"); reg.add_decorator("derive_Ipc", codegen::expand_ipc_implementation); reg.add_decorator("derive_Binary", serialization::expand_serialization_implementation); + + reg.add_post_expansion_pass(strip_attributes); } #[cfg(not(feature = "with-syntex"))] @@ -67,4 +93,6 @@ pub fn register(reg: &mut rustc_plugin::Registry) { syntax::parse::token::intern("derive_Binary"), syntax::ext::base::MultiDecorator( Box::new(serialization::expand_serialization_implementation))); + + reg.register_attribute("ipc".to_owned(), AttributeType::Normal); } From 427d54f3415a302c1b55d7954443ceb85f1c8285 Mon Sep 17 00:00:00 2001 From: NikVolf Date: Thu, 30 Jun 2016 14:41:56 +0300 Subject: [PATCH 2/7] versions sorting --- ipc/tests/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ipc/tests/Cargo.toml b/ipc/tests/Cargo.toml index f7a5ee9bd..d9c80145d 100644 --- a/ipc/tests/Cargo.toml +++ b/ipc/tests/Cargo.toml @@ -16,5 +16,5 @@ ethcore-ipc-nano = { path = "../nano" } ethcore-util = { path = "../../util" } [build-dependencies] -syntex = "*" +syntex = "0.33" ethcore-ipc-codegen = { path = "../codegen" } From 6259a5a7373292cebf4cbbbc04d6ecf59ccb8283 Mon Sep 17 00:00:00 2001 From: NikVolf Date: Thu, 30 Jun 2016 14:42:11 +0300 Subject: [PATCH 3/7] versions sorting --- ipc/codegen/Cargo.toml | 4 ++-- ipc/codegen/src/lib.rs | 5 ++--- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/ipc/codegen/Cargo.toml b/ipc/codegen/Cargo.toml index 4d83b65e1..649882c51 100644 --- a/ipc/codegen/Cargo.toml +++ b/ipc/codegen/Cargo.toml @@ -22,5 +22,5 @@ aster = { version = "0.17", default-features = false } clippy = { version = "^0.*", optional = true } quasi = { version = "0.11", default-features = false } quasi_macros = { version = "0.11", optional = true } -syntex = { version = "*", optional = true } -syntex_syntax = { version = "*", optional = true } +syntex = { version = "0.33", optional = true } +syntex_syntax = { version = "0.33", optional = true } diff --git a/ipc/codegen/src/lib.rs b/ipc/codegen/src/lib.rs index fc737b060..afa7979d0 100644 --- a/ipc/codegen/src/lib.rs +++ b/ipc/codegen/src/lib.rs @@ -50,12 +50,11 @@ include!("lib.rs.in"); #[cfg(feature = "with-syntex")] pub fn register(reg: &mut syntex::Registry) { - /// Strip the serde attributes from the crate. + use syntax::{ast, fold}; + #[cfg(feature = "with-syntex")] fn strip_attributes(krate: ast::Crate) -> ast::Crate { - /// Helper folder that strips the serde attributes after the extensions have been expanded. struct StripAttributeFolder; - impl fold::Folder for StripAttributeFolder { fn fold_attribute(&mut self, attr: ast::Attribute) -> Option { match attr.node.value.node { From 6e8df6a6cec64dbbeb85b63f3b84bfc51c8c0bd8 Mon Sep 17 00:00:00 2001 From: NikVolf Date: Thu, 30 Jun 2016 15:33:34 +0300 Subject: [PATCH 4/7] attribute parsing --- ipc/codegen/src/codegen.rs | 67 +++++++++++++++++++++++++++++++++----- 1 file changed, 59 insertions(+), 8 deletions(-) diff --git a/ipc/codegen/src/codegen.rs b/ipc/codegen/src/codegen.rs index 9dd6a7b32..672132c9f 100644 --- a/ipc/codegen/src/codegen.rs +++ b/ipc/codegen/src/codegen.rs @@ -497,9 +497,9 @@ fn client_generics(builder: &aster::AstBuilder, interface_map: &InterfaceMap) -> .build() } -fn client_qualified_ident(builder: &aster::AstBuilder, interface_map: &InterfaceMap) -> P { +fn client_qualified_ident(cx: &ExtCtxt, builder: &aster::AstBuilder, interface_map: &InterfaceMap) -> P { let generics = client_generics(builder, interface_map); - aster::ty::TyBuilder::new().path().segment(interface_map.ident_map.client_ident(builder)) + aster::ty::TyBuilder::new().path().segment(interface_map.ident_map.client_ident(cx, builder, &interface_map.original_item)) .with_generics(generics).build() .build() } @@ -515,7 +515,7 @@ fn client_phantom_ident(builder: &aster::AstBuilder, interface_map: &InterfaceMa /// for say `Service` it generates `ServiceClient` fn push_client_struct(cx: &ExtCtxt, builder: &aster::AstBuilder, interface_map: &InterfaceMap, push: &mut FnMut(Annotatable)) { let generics = client_generics(builder, interface_map); - let client_short_ident = interface_map.ident_map.client_ident(builder); + let client_short_ident = interface_map.ident_map.client_ident(cx, builder, &interface_map.original_item); let phantom = client_phantom_ident(builder, interface_map); let client_struct_item = quote_item!(cx, @@ -547,9 +547,9 @@ fn push_with_socket_client_implementation( push: &mut FnMut(Annotatable)) { let generics = client_generics(builder, interface_map); - let client_ident = client_qualified_ident(builder, interface_map); + let client_ident = client_qualified_ident(cx, builder, interface_map); let where_clause = &generics.where_clause; - let client_short_ident = interface_map.ident_map.client_ident(builder); + let client_short_ident = interface_map.ident_map.client_ident(cx, builder, &interface_map.original_item); let implement = quote_item!(cx, impl $generics ::ipc::WithSocket for $client_ident $where_clause { @@ -578,7 +578,7 @@ fn push_client_implementation( .collect::>>(); let generics = client_generics(builder, interface_map); - let client_ident = client_qualified_ident(builder, interface_map); + let client_ident = client_qualified_ident(cx, builder, interface_map); let where_clause = &generics.where_clause; let handshake_item = quote_impl_item!(cx, @@ -682,6 +682,52 @@ fn implement_handshake_arm( } +fn get_str_from_lit(cx: &ExtCtxt, name: &str, lit: &ast::Lit) -> Result { + match lit.node { + ast::LitKind::Str(ref s, _) => Ok(format!("{}", s)), + _ => { + cx.span_err( + lit.span, + &format!("ipc client_ident annotation `{}` must be a string, not `{}`", + name, + ::syntax::print::pprust::lit_to_string(lit))); + + return Err(()); + } + } +} + +pub fn get_ipc_meta_items(attr: &ast::Attribute) -> Option<&[P]> { + match attr.node.value.node { + ast::MetaItemKind::List(ref name, ref items) if name == &"ipc" => { + Some(items) + } + _ => None + } +} + +fn client_ident_renamed(cx: &ExtCtxt, item: &ast::Item) -> Option { + for meta_items in item.attrs().iter().filter_map(get_ipc_meta_items) { + for meta_item in meta_items { + let span = meta_item.span; + match meta_item.node { + ast::MetaItemKind::NameValue(ref name, ref lit) if name == &"client_ident" => { + if let Ok(s) = get_str_from_lit(cx, name, lit) { + return Some(s); + } + } + _ => { + cx.span_err( + meta_item.span, + &format!("unknown client_ident container attribute `{}`", + ::syntax::print::pprust::meta_item_to_string(meta_item))); + } + } + } + } + None +} + struct InterfaceMap { pub original_item: Item, pub item: P, @@ -700,8 +746,13 @@ impl IdentMap { builder.id(format!("{}", ::syntax::print::pprust::path_to_string(&self.original_path))) } - fn client_ident(&self, builder: &aster::AstBuilder) -> Ident { - builder.id(format!("{}Client", self.original_path.segments[0].identifier)) + fn client_ident(&self, cx: &ExtCtxt, builder: &aster::AstBuilder, item: &ast::Item) -> Ident { + if let Some(new_name) = client_ident_renamed(cx, item) { + builder.id(new_name) + } + else { + builder.id(format!("{}Client", self.original_path.segments[0].identifier)) + } } fn qualified_ident(&self, builder: &aster::AstBuilder) -> Ident { From 5c5f52c01792b6b7ae31750c4dae83aaadee143e Mon Sep 17 00:00:00 2001 From: NikVolf Date: Thu, 30 Jun 2016 16:23:10 +0300 Subject: [PATCH 5/7] tests for client_ident --- ipc/tests/build.rs | 17 +++++++++++++++++ ipc/tests/examples.rs | 6 +++--- ipc/tests/over_nano.rs | 7 +++++++ ipc/tests/run.rs | 1 + ipc/tests/with_attrs.rs | 18 ++++++++++++++++++ ipc/tests/with_attrs.rs.in | 39 ++++++++++++++++++++++++++++++++++++++ 6 files changed, 85 insertions(+), 3 deletions(-) create mode 100644 ipc/tests/with_attrs.rs create mode 100644 ipc/tests/with_attrs.rs.in diff --git a/ipc/tests/build.rs b/ipc/tests/build.rs index e498e3405..6538f56e1 100644 --- a/ipc/tests/build.rs +++ b/ipc/tests/build.rs @@ -58,6 +58,23 @@ pub fn main() { registry.expand("", &src, &dst).unwrap(); } + // rpc pass + if { + let src = Path::new("with_attrs.rs.in"); + let dst = Path::new(&out_dir).join("with_attrs_ipc.rs"); + let mut registry = syntex::Registry::new(); + codegen::register(&mut registry); + registry.expand("", &src, &dst).is_ok() + } + // serialization pass + { + let src = Path::new(&out_dir).join("with_attrs_ipc.rs"); + let dst = Path::new(&out_dir).join("with_attrs_cg.rs"); + let mut registry = syntex::Registry::new(); + codegen::register(&mut registry); + registry.expand("", &src, &dst).unwrap(); + } + // rpc pass { let src = Path::new("binary.rs.in"); diff --git a/ipc/tests/examples.rs b/ipc/tests/examples.rs index 99cf385fa..b4159f196 100644 --- a/ipc/tests/examples.rs +++ b/ipc/tests/examples.rs @@ -86,7 +86,7 @@ mod tests { 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 5, 0, 0, 0], - service_client.socket().borrow().write_buffer.clone()); + service_client.socket().write().unwrap().write_buffer.clone()); assert_eq!(10, result); } @@ -103,7 +103,7 @@ mod tests { 1, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0, - 5, 0, 0, 0, 10, 0, 0, 0], service_client.socket().borrow().write_buffer.clone()); + 5, 0, 0, 0, 10, 0, 0, 0], service_client.socket().write().unwrap().write_buffer.clone()); assert_eq!(10, result); } @@ -145,7 +145,7 @@ mod tests { // items 3, 0, 0, 0, 0, 0, 0, 0, 11, 0, 0, 0, 0, 0, 0, 0], - service_client.socket().borrow().write_buffer.clone()); + service_client.socket().write().unwrap().write_buffer.clone()); assert_eq!(true, result); } diff --git a/ipc/tests/over_nano.rs b/ipc/tests/over_nano.rs index 36ad17f2a..bdeaec3d5 100644 --- a/ipc/tests/over_nano.rs +++ b/ipc/tests/over_nano.rs @@ -18,6 +18,7 @@ mod tests { use super::super::service::*; + use super::super::with_attrs::PrettyNamedClient; use nanoipc; use std::sync::Arc; use std::io::Write; @@ -43,6 +44,12 @@ mod tests { assert!(client.is_ok()); } + #[test] + fn can_create_renamed_client() { + let client = nanoipc::init_duplex_client::>("ipc:///tmp/parity-nano-test10.ipc"); + assert!(client.is_ok()); + } + #[test] fn can_call_handshake() { let url = "ipc:///tmp/parity-test-nano-20.ipc"; diff --git a/ipc/tests/run.rs b/ipc/tests/run.rs index cdda5275b..ab0041899 100644 --- a/ipc/tests/run.rs +++ b/ipc/tests/run.rs @@ -28,3 +28,4 @@ mod examples; mod over_nano; mod nested; mod binary; +mod with_attrs; diff --git a/ipc/tests/with_attrs.rs b/ipc/tests/with_attrs.rs new file mode 100644 index 000000000..e9b3e0d76 --- /dev/null +++ b/ipc/tests/with_attrs.rs @@ -0,0 +1,18 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +#![allow(dead_code, unused_assignments, unused_variables)] // codegen issues +include!(concat!(env!("OUT_DIR"), "/with_attrs_cg.rs")); diff --git a/ipc/tests/with_attrs.rs.in b/ipc/tests/with_attrs.rs.in new file mode 100644 index 000000000..bca1b0bfe --- /dev/null +++ b/ipc/tests/with_attrs.rs.in @@ -0,0 +1,39 @@ +// Copyright 2015, 2016 Ethcore (UK) Ltd. +// This file is part of Parity. + +// Parity is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Parity is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Parity. If not, see . + +use std::sync::RwLock; +use std::ops::*; +use ipc::IpcConfig; +use std::mem; +use ipc::binary::BinaryConvertError; +use std::collections::VecDeque; + +pub struct BadlyNamedService; + +#[derive(Ipc)] +#[ipc(client_ident="PrettyNamedClient")] +impl BadlyNamedService { + fn is_zero(&self, x: u64) -> bool { + x == 0 + } +} + +impl ::ipc::IpcConfig for BadlyNamedService {} + +#[test] +fn invoke() { + +} From eb56e743409ffe22b079207b531e1708f76a7aaa Mon Sep 17 00:00:00 2001 From: NikVolf Date: Thu, 30 Jun 2016 16:24:46 +0300 Subject: [PATCH 6/7] unused test --- ipc/tests/with_attrs.rs.in | 5 ----- 1 file changed, 5 deletions(-) diff --git a/ipc/tests/with_attrs.rs.in b/ipc/tests/with_attrs.rs.in index bca1b0bfe..c49ce9c72 100644 --- a/ipc/tests/with_attrs.rs.in +++ b/ipc/tests/with_attrs.rs.in @@ -32,8 +32,3 @@ impl BadlyNamedService { } impl ::ipc::IpcConfig for BadlyNamedService {} - -#[test] -fn invoke() { - -} From 08048a7377123cf79fe37ed21046892f15961fa9 Mon Sep 17 00:00:00 2001 From: NikVolf Date: Thu, 30 Jun 2016 16:26:37 +0300 Subject: [PATCH 7/7] redundant space --- ipc/tests/with_attrs.rs.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ipc/tests/with_attrs.rs.in b/ipc/tests/with_attrs.rs.in index c49ce9c72..0168f3a72 100644 --- a/ipc/tests/with_attrs.rs.in +++ b/ipc/tests/with_attrs.rs.in @@ -25,7 +25,7 @@ pub struct BadlyNamedService; #[derive(Ipc)] #[ipc(client_ident="PrettyNamedClient")] -impl BadlyNamedService { +impl BadlyNamedService { fn is_zero(&self, x: u64) -> bool { x == 0 }