#macro-derive #path #properly #qualify

qualify-derive

Simple utility for wrapping derive macros that do not qualify paths properly

3 releases

0.1.2 Sep 22, 2020
0.1.1 Sep 22, 2020
0.1.0 Sep 22, 2020

#5 in #properly

Apache-2.0

8KB
92 lines

qualify-derive

GitHub actions crates.io crates.io docs.rs GitHub GitHub

Simple utility for wrapping derive macros that do not qualify paths properly.

When is this needed?

For example, specs v0.16.1 has a derive macro Component. If the #[storage] is not passed with the macro, it generates a line type Storage = DenseVecStorage;, which causes compile errors when DenseVecStorage is not already imported.

It is annoying to manually add an import for a derive macro all the time. qualify-derive assists with creating a wrapper macro that automatically imports them.

How to use

Create a new crate with this Cargo.toml (proc macros won't work in the current crate):

[package]
name = # the usual [package] stuff

[lib]
proc-macro = true

[dependencies]
qualify-derive = "0.1.1"

Then create src/lib.rs with the following cntents:


qualify_derive::declare! {
    your_attribute_name derives ::full_path_to::TargetDeriveMacro;
    use the_paths::you_want_to::import_automatically;
    use import_groups_are::not_supported;
		// use foo::{bar, qux}; // this does not work
    attr this_line_is_optional
}

This declares a proc-macro-attribute called your_attribute_name. In downstream crates, you can use #[your_attribute_name] in place of #[derive(::full_path_to::TargetDeriveMacro)].

attr this_line_is_optional will allow downstream crates to use #[your_attribute_name(some content here)], which is expanded into #[derive(::full_path_to::TargetDeriveMacro)] #[this_line_is_optional(some content here)].

Example

See test-macro and test-lib.

Limitations

  • Types that use attributes generated by this crate are known to have issues with cargo fix when they are unused. cargo fix removes the attribute if the type is unused.
  • The generated attributes would wrap the user type inside an anonymous module. super would refer to the module that the type itself is declared in. However, all symbols in the super scope are automatically imported down to the scope of the inner module, so it is not necessary to use super:: inside the type; but any use of super would be incorrect. Use super::super or absolute paths from crate:: instead.

Dependencies

~1.5MB
~35K SLoC