如何从Rust中的属性proc宏中获取extern模块中函数的行号(带INNERDATTRIE)

如何从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"

我是个编程新手。作为练习,我想编写一个类似于小lint的程序来检查函数的长度,如果长度大于默认的最大长度,则发出警告

所以我使用了attributeproc宏并将其用作InnerAttribute(只是不想为每个函数编写属性)

以下是名为lint_fn_len的属性proc宏库的cargo.toml文件:

[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模块中函数的开始/结束行号

提前感谢您的帮助