如何从Rust中的属性proc宏中获取extern模块中函数的行号(带INNERDATTRIE)
我是个编程新手。作为练习,我想编写一个类似于小lint的程序来检查函数的长度,如果长度大于默认的最大长度,则发出警告 所以我使用了attributeproc宏并将其用作InnerAttribute(只是不想为每个函数编写属性) 以下是名为lint_fn_len的属性proc宏库的cargo.toml文件:如何从Rust中的属性proc宏中获取extern模块中函数的行号(带INNERDATTRIE),rust,module,macros,attributes,proc,Rust,Module,Macros,Attributes,Proc,我是个编程新手。作为练习,我想编写一个类似于小lint的程序来检查函数的长度,如果长度大于默认的最大长度,则发出警告 所以我使用了attributeproc宏并将其用作InnerAttribute(只是不想为每个函数编写属性) 以下是名为lint_fn_len的属性proc宏库的cargo.toml文件: [package] name = "lint_fn_len" version = "0.0.0" authors = ["David"
[package]
name = "lint_fn_len"
version = "0.0.0"
authors = ["David"]
description = "exericse for attribute proc macro "
edition = "2018"
[lib]
proc-macro = true
[dependencies]
quote = "1"
proc-macro2 = "1.0"
syn = { version = "1.0.72", features = ["full"] }
#![feature(proc_macro_span)]
use proc_macro::TokenStream;
use quote::ToTokens;
use syn::{parse_macro_input, ItemFn, ItemMod, spanned::Spanned};
#[proc_macro_attribute]
pub fn my_attribute(_args: TokenStream, input: TokenStream) -> TokenStream {
let input1 = input.clone();
let mod1 = parse_macro_input!(input1 as ItemMod);
for item1 in mod1.content.unwrap().1 {
if let Ok(func1) = syn::parse::<ItemFn>(item1.to_token_stream().into()) {
let sp1 = func1.block.span().unwrap();
println!("end line number: {} , start line number: {}", sp1.end().line, sp1.start().line);
let numbers = sp1.end().line - sp1.start().line;
if numbers > 5 {
println!(
"Function {} is too long, count of line number is {} > 5 which is default max",
func1.sig.ident.to_string(),
numbers
);
};
}
}
input
}
以下是lint_fn_len的lib.rs文件:
[package]
name = "lint_fn_len"
version = "0.0.0"
authors = ["David"]
description = "exericse for attribute proc macro "
edition = "2018"
[lib]
proc-macro = true
[dependencies]
quote = "1"
proc-macro2 = "1.0"
syn = { version = "1.0.72", features = ["full"] }
#![feature(proc_macro_span)]
use proc_macro::TokenStream;
use quote::ToTokens;
use syn::{parse_macro_input, ItemFn, ItemMod, spanned::Spanned};
#[proc_macro_attribute]
pub fn my_attribute(_args: TokenStream, input: TokenStream) -> TokenStream {
let input1 = input.clone();
let mod1 = parse_macro_input!(input1 as ItemMod);
for item1 in mod1.content.unwrap().1 {
if let Ok(func1) = syn::parse::<ItemFn>(item1.to_token_stream().into()) {
let sp1 = func1.block.span().unwrap();
println!("end line number: {} , start line number: {}", sp1.end().line, sp1.start().line);
let numbers = sp1.end().line - sp1.start().line;
if numbers > 5 {
println!(
"Function {} is too long, count of line number is {} > 5 which is default max",
func1.sig.ident.to_string(),
numbers
);
};
}
}
input
}
以下是long_fn的主要.rs:
#![feature(custom_inner_attributes)]
#![feature(proc_macro_hygiene)]
use lint_fn_len::my_attribute;
mod mymod;
fn main() {
mymod::kk();
}
下面是模块(mymod.rs),它实际上在long_fn项目中使用属性proc宏:
#![my_attribute]
pub fn kk() {
println!("kk 1");
println!("kk 2");
}
编译器的输出如下:
cargo.exe build --color=always --message-format=json-diagnostic-rendered-ansi --package long_fn --bin long_fn
Compiling proc-macro2 v1.0.26
Compiling unicode-xid v0.2.2
Compiling syn v1.0.72
Compiling quote v1.0.9
Compiling lint_fn_len v0.0.0 (C:\Users\libin\IdeaProjects\lint_fn_len)
Compiling long_fn v0.1.0 (C:\Users\libin\IdeaProjects\long_fn)
end line number: 6 , start line number: 6
Finished dev [unoptimized + debuginfo] target(s) in 42.01s
Process finished with exit code 0
令人惊讶的是,mymod.rs文件的起始/结束行号(6/6)肯定是错误的。它们只是main.rs中“mod mymod;”行的开始/结束行号,这并不是我想要的。我想要mymod.rs中函数的开始/结束行号
作为另一种尝试,当我使用具有相同代码的内联模块时(当然没有额外的文件mymod.rs),生成的开始/结束行号是正确的,它们是main.rs中函数的开始/结束行号
为什么它不能与外部模块一起工作?这个案子有什么解决办法吗
在这种情况下,如何获取extern模块中函数的开始/结束行号
提前感谢您的帮助