What is the criteria/threshold for Rust Analyzer to support procedural macro code?

I am generating a Rust module via a procedural macro attribute. When using this generated code, I get no auto-complete suggestions or hover info.

However, some procedurally-generated code does appear in autocomplete suggestions, e.g. the example code in json-typegen:

use json_typegen::json_typegen;

// `Point` and fields present in auto-complete
json_typegen!("pub Point", r#"{ "x": 1, "y": 2 }"#);

The two major differences I see here are that this is just a type, not a module; and it is using a function-like proc macro. Don't know if these are relevant though.

Are there any known guidelines I could follow with my procedural macro to make RA more likely to function with it?

We support derives and function-like proc macros, we don't support non-derive attribute proc macros yet.

Thanks! So if I converted my codegen to a function-like macro, is it likely that autocomplete etc. would work? Are there any other caveats with the current system?

They may work, but I won't necessary say "likely" :frowning: Our code-generation support (both for proc-macro and for include) is pretty thin at the moment. I'd advise to maybe try some minimal proof of concepts just to see if rust-analyzer can understand those.

Thanks for the advice. If it doesn't work, I'm probably going to look at generating to a file at a known location (xtask?), since support for #[path = "..."] mod x; seems to work perfectly.

Yeah, you might want to check the codegen.rs module from rust-analyzer's own code, we do use boring codegen instead of proc macros.

More philosophically, I think that codegeneration, if feasible, should be preferred to proc-macros. If there's actual code on the hard-drive, than it becomes easy to do things like:

  • read what's actually geneated
  • step with debugger through the generated code
  • use goto definition in an IDE to look at the generated code

To be clear, it totally is a bug that rust-analyze doesn't support proc macros fully, and, while I am willing to argue for codegen over proc-macros as a user of the language, I just need to fix rust-analyzer as the tool's contributor :slight_smile:

2 Likes

This is true, although I think derive/proc macros have benefits too:

  • No need to make a "generated" partitioning folder/gitignore rules
  • It means anything a user can physically edit is a legitimate code change (instead of having to instruct users that some files should be treated as "read only")
  • Code generation might be unsuitable to read directly, but the directive for the proc macro itself is meaningful (e.g. derive(Serialize) and serde attributes).

I can imagine the best-of-both would be the ability to preview generated code, without it existing in a file. I'm not sure if the LSP supports something like this, but it seems similar to the ability to view generated "header" files for dependencies in C# projects.

In fact, this would be better than something like cargo expand (or full code generation to file), if it meant you could view only the code generated from a proc macro directive, without any nested directives being expanded also. E.g. it might be more useful to see which derives have been added to a generated type, than to see the code for those derives in-line.