写点什么

2022-11-12:以下 rust 语言代码中,结构体 S 实现了 crate::T1::T2 的方法,如何获取方法列表?以下代码应该返回 [“m1“,“m2“,“m5“],顺序不限。m3 是 S 的方法,但并不属于 c

  • 2022-11-12
    北京
  • 本文字数:2724 字

    阅读完需:约 9 分钟

2022-11-12:以下rust语言代码中,结构体S实现了crate::T1::T2的方法,如何获取方法列表?以下代码应该返回[“m1“,“m2“,“m5“],顺序不限。m3是S的方法,但并不属于c

2022-11-12:以下 rust 语言代码中,结构体 S 实现了 crate::T1::T2 的方法,如何获取方法列表?以下代码应该返回["m1","m2","m5"],顺序不限。m3 是 S 的方法,但并不属于 crate::T1::T2 的。m4 也是 S 的方法,但这是实现 T3 的,也不属于 crate::T1::T2 的。


pub struct S;
impl crate::T1::T2 for S { fn m1(&mut self){} fn m2(&mut self){}}
impl S { fn m3(&mut self){}}
impl T3 for S { fn m4(&mut self){}}
impl crate::T1::T2 for S { fn m5(&mut self){}}
复制代码


答案 2022-11-12:


要解析 rust 的代码,syn,quote,proc-macro2 合理利用这三个库。使用场景是写框架。


代码如下:


// main.rs文件内容如下:use quote::quote;use std::collections::HashSet;use std::error::Error;use syn::spanned::Spanned;use syn::visit::Visit;
#[tokio::main]async fn main() -> Result<(), Box<dyn Error>> { let content = include_str!("test.rs.txt"); let ast: syn::File = syn::parse_file(content)?; let mut a = ImplVisitor::new("crate::T1::T2", "S"); a.visit_file(&ast); println!("out_method_name_set = {:#?}", a.out_method_name_set); Ok(())}
// 遍历服务的方法pub struct ImplMethodVisitor { // 收集方法 pub out_method_name_set: HashSet<String>,}
impl ImplMethodVisitor { pub fn new() -> Self { Self { out_method_name_set: HashSet::new(), } }}
impl<'ast> Visit<'ast> for ImplMethodVisitor { fn visit_impl_item_method(&mut self, node: &'ast syn::ImplItemMethod) { // 获取方法名 let method_a = &node.sig.ident; let method = format!("{}", quote! {#method_a}); // 将方法保存起来 self.out_method_name_set.insert(method);
// Delegate to the default impl to visit any nested functions. //visit::visit_impl_item_method(self, node); }}
// 遍历服务的实现pub struct ImplVisitor { // 接口名 pub interface_name: String, // 服务名 pub service_name: String, // 收集方法 pub out_method_name_set: HashSet<String>, // 结束行 pub out_end_line: usize, // 结束列 pub out_end_column: usize,}
impl ImplVisitor { pub fn new(interface_name: &str, service_name: &str) -> Self { Self { interface_name: String::from(interface_name), service_name: String::from(service_name), out_method_name_set: HashSet::new(), out_end_line: 0, out_end_column: 0, } }}
impl<'ast> Visit<'ast> for ImplVisitor { fn visit_item_impl(&mut self, node: &'ast syn::ItemImpl) { // 获取服务名称 let service_a = node.self_ty.as_ref(); let mut service = String::new(); match service_a { syn::Type::Path(service_b) => { let mut ans = String::new(); for service_c in service_b.path.segments.iter() { let service_d = service_c.ident.clone(); ans.push_str("::"); let aaa = format!("{}", quote! {#service_d}); ans.push_str(&aaa); } //println!("找到Service----{}",&ans[2..]); service = String::from(&ans[2..]); } _ => { //println!("没找到Service"); } }
// 获取接口名称 let interface_a = &node.trait_; let mut interface = String::new(); match interface_a { Some(interface_b) => { let interface_c = &interface_b.1; let mut ans = String::new(); for interface_d in interface_c.segments.iter() { let interface_e = &interface_d.ident; ans.push_str("::"); let interface_f = format!("{}", quote! {#interface_e}); ans.push_str(&interface_f); } //println!("找到接口----{}",&ans[2..]); interface = String::from(&ans[2..]); } _ => { //println!("没找到接口"); } }
if self.interface_name != interface { //println!("接口不匹配"); return; } if self.service_name != service { //println!("服务名称不匹配"); return; } // println!("接口名和服务名都匹配----{}----{}",interface,service); // 修改结束索引 self.out_end_line = node.span().end().line - 1; self.out_end_column = node.span().end().column - 1;
// 遍历方法 let mut mv = ImplMethodVisitor::new(); mv.visit_item_impl(node); // 将方法保存起来 for m in mv.out_method_name_set.iter() { self.out_method_name_set.insert(String::from(m)); }
// Delegate to the default impl to visit any nested functions. //visit::visit_item_impl(self, node); }}
复制代码


// test.rs.txt内容如下:pub struct S;
impl crate::T1::T2 for S { fn m1(&mut self){} fn m2(&mut self){}}
impl S { fn m3(&mut self){}}
impl T3 for S { fn m4(&mut self){}}
impl crate::T1::T2 for S { fn m5(&mut self){}}
复制代码


# Cargo.toml内容如下:
[package]name = "rust-ast"version = "0.1.0"edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]tokio = { version = "1.0", features = ["full"] }anyhow = "1.0.66"proc-macro2={ version = "1.0.47", features = ["span-locations"] }syn = {version = "1.0",features=["full","extra-traits","visit"]}quote = "1"
复制代码


执行结果如下:



发布于: 刚刚阅读数: 5
用户头像

还未添加个人签名 2021-02-15 加入

还未添加个人简介

评论

发布
暂无评论
2022-11-12:以下rust语言代码中,结构体S实现了crate::T1::T2的方法,如何获取方法列表?以下代码应该返回[“m1“,“m2“,“m5“],顺序不限。m3是S的方法,但并不属于c_rust_福大大架构师每日一题_InfoQ写作社区