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"
执行结果如下:

2022-11-12:以下rust语言代码中,结构体S实现了crate::T1::T2的方法,如何获取方法列表?以下代码应该返回[“m1“,“m2“,“m5“],顺序不限。m3是S的方法,但并不属于c的更多相关文章
- C语言中结构体对齐问题
C语言中结构体对齐问题 收藏 关于C语言中的结构体对齐问题 1,比如: struct{short a1;short a2;short a3;}A;struct{long a1;short a2;}B; ...
- Go语言中结构体的使用-第2部分OOP
1 概述 结构体的基本语法请参见:Go语言中结构体的使用-第1部分结构体.结构体除了是一个复合数据之外,还用来做面向对象编程.Go 语言使用结构体和结构体成员来描述真实世界的实体和实体对应的各种属性. ...
- 6. Go 语言中结构体的使用
1. 结构体的定义格式 在go语言中结果的定义格式如下: 123 type structName struct { filedList} 列子如下: 1234 type Person struct { ...
- C语言中结构体赋值问题的讨论
今天帮师姐调一个程序的BUG,师姐的程序中有个结构体直接赋值的语句,在我印象中结构体好像是不能直接赋值的,正如数组不能直接赋值那样,我怀疑这个地方有问题,但最后证明并不是这个问题.那么就总结一下C语言 ...
- C语言中结构体赋值问题的讨论(转载)
今天帮师姐调一个程序的BUG,师姐的程序中有个结构体直接赋值的语句,在我印象中结构体好像是不能直接赋值的,正如数组不能直接赋值那样,我怀疑这个地方有问题,但最后证明并不是这个问题.那么就总结一下C语言 ...
- Go语言中结构体的使用-第1部分结构体
1 概述 结构体是由成员构成的复合类型.Go 语言使用结构体和结构体成员来描述真实世界的实体和实体对应的各种属性.结构体成员,也可称之为成员变量,字段,属性.属性要满足唯一性.结构体的概念在软件工程上 ...
- Go语言基础之结构体
Go语言基础之结构体 Go语言中没有“类”的概念,也不支持“类”的继承等面向对象的概念.Go语言中通过结构体的内嵌再配合接口比面向对象具有更高的扩展性和灵活性. 类型别名和自定义类型 自定义类型 在G ...
- C语言第九讲,结构体
C语言第九讲,结构体 一丶结构体的定义 在C语言中,可以使用结构体(Struct)来存放一组不同类型的数据.结构体的定义形式为: struct 结构体名{ 结构体所包含的变量或数组 }; 结构体是一种 ...
- ndk学习之C语言基础复习----结构体、共用体与C++开端
自己实现sprintf功能: 关于C中的系统函数sprintf在上次[https://www.cnblogs.com/webor2006/p/7545627.html]学习中已经用到过了,这里再来回顾 ...
- GO学习-(13) Go语言基础之结构体
Go语言基础之结构体 Go语言中没有"类"的概念,也不支持"类"的继承等面向对象的概念.Go语言中通过结构体的内嵌再配合接口比面向对象具有更高的扩展性和灵活性. ...
随机推荐
- MySQL:查询语句 case when then 的用法
转载网址: https://blog.csdn.net/h123hlll/article/details/122366213
- python内置函数open()
open()函数 介绍 open()函数用于打开文件并创建文件对象. open()函数的语法格式: file = open(filename, mode='r', buffering=-1, enco ...
- 痞子衡嵌入式:内存读写正确性压力测试程序(memtester)
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是内存读写正确性压力测试程序memtester. 在嵌入式系统中,内存(RAM)的重要性不言而喻,系统性能及稳定性都与内存息息相关.关于内 ...
- 499div2-E Border :裴蜀定理
这个定理就像类似学扩展欧几里得判断是否有解的条件,当时是ax+by = c:仅当c = k*gcd(a,b)时有解,其实也就是只要是公约数的倍数就行. 而裴蜀定理是多个未知量x1*a1+x2*a2+. ...
- Maven 自动化构建
一.Maven:是一款服务于 Java平台的自动化构建工具 [1]Maven可以将一个项目按模块划分成不同的工程,利于分工协作;[2]Maven可以将 jar包保存在自己的中央"仓库&quo ...
- 【深入浅出 Yarn 架构与实现】5-2 Yarn 三种调度器
本篇文章将深入介绍 Yarn 三种调度器.Yarn 本身作为资源管理和调度服务,其中的资源调度模块更是重中之重.下面将介绍 Yarn 中实现的调度器功能,以及内部执行逻辑. 一.简介 Yarn 最主要 ...
- 机器学习算法(九): 基于线性判别模型的LDA手写数字分类识别
1.机器学习算法(九): 基于线性判别模型的LDA手写数字分类识别 1.1 LDA算法简介和应用 线性判别模型(LDA)在模式识别领域(比如人脸识别等图形图像识别领域)中有非常广泛的应用.LDA是一种 ...
- 必知必会的 WebSocket 协议
文章介绍 WebSocket 是一种在单个 TCP 连接上进行全双工通信的协议,它的出现使客户端和服务器之间的数据交换变得更加简单.WebSocket 通常被应用在实时性要求较高的场景,例如赛事数据. ...
- 快速使用ChatGpt Web Server
快速使用ChatGpt Web Server ChatGpt Web Server是使用Blazor Server模式部署的一个服务,所有的逻辑和代码执行都会在服务器执行,然后通过SignalR传输到 ...
- data.frame数据框操作——R语言
统计分析中最常见的原始数据形式是类似于数据库表或Excel数据表的形式. 这样形式的数据在R中叫做数据框(data.frame). 数据框类似于一个矩阵,但各列允许有不同类型:数值型向量.因子.字符型 ...