From 6e8df6a6cec64dbbeb85b63f3b84bfc51c8c0bd8 Mon Sep 17 00:00:00 2001 From: NikVolf Date: Thu, 30 Jun 2016 15:33:34 +0300 Subject: [PATCH] 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 {