I am trying to develop some procedural macros that are intended to help Rust code interface with a foreign language runtime, but have run into a rather tricky challenge.
I have a macro called "make_special_object" which uses the definition of a struct to generate the object for the foreign runtime as well as a Rust struct that implicitly talks to it. I have this working for properties, but I now want to deal with methods as well. Specifically I want to be able to do something like
#[make_special_object]
struct TestStruct {
...
}
impl TestStruct {
#[special_method]
pub fn test(name: &str) {
}
}
in order to define that there should be a method on the foreign object. The problem here is that make_special_object needs to know everything about the foreign object to be able to construct it, but the TokenStream passed in only provides information on the struct and not for any methods implemented on it. I could just have some fancy syntax to define the function directly inside the struct and my problems would be solved, but I want to maintain the idiomatic Rust look.
The "easiest" way I can think to do this is to have something inside build.rs that parses all the code and writes up the definitions of all methods in a JSON file that make_special_object can then read to get all the information it needs. This feels a bit hacky though, and I have no idea if there is something I can use to help me parse all the Rust code in a project for this purpose?
The other hacky idea I have is to set an env var, run the compiler in a mode where it does not emit anything so that the special_method macros can dump their metadata to JSON and then run the compiler again in normal mode with make_special_object now reading the JSON. Is this even possible?
Even if either of these options could be made to work, it would feel a bit wrong, so I am totally open to suggestions for entirely different approaches to this problem.