Skip to main content

annotate_build/
lib.rs

1use std::path::PathBuf;
2
3pub use config::{BuildConfig, ModuleDeriveBuilder};
4
5pub const SCHEMA_VERSION: u32 = 1;
6
7pub(crate) use function::*;
8pub(crate) use module::*;
9pub(crate) use path::*;
10pub(crate) use render::*;
11
12mod builder;
13mod config;
14mod environment;
15mod function;
16mod module;
17mod parser;
18mod path;
19mod render;
20mod visitor;
21
22/// Scan the current crate for `#[pragma(...)]` annotations and export the generated environment.
23pub fn build() {
24    build_with(|_| {});
25}
26
27/// Scan the current crate and export the generated environment from multiple JSON configuration
28/// specs.
29///
30/// Each spec must be a JSON string with the following shape:
31///
32/// ```json
33/// {
34///   "schema_version": 1,
35///   "functions": [
36///     { "pragma": "command" }
37///   ],
38///   "modules": [
39///     {
40///       "pragma": "plugin",
41///       "derives": [
42///         {
43///           "name": "logging",
44///           "functions": [
45///             "info",
46///             "warn",
47///             "error"
48///           ],
49///           "modules": [
50///             {
51///               "name": "http",
52///               "functions": [
53///                 "request_started",
54///                 "request_finished"
55///               ],
56///               "modules": []
57///             }
58///           ]
59///         }
60///       ]
61///     }
62///   ]
63/// }
64/// ```
65///
66/// Fields:
67/// - `schema_version`: Must match [`SCHEMA_VERSION`]. This makes format changes explicit and lets
68///   builds fail early on incompatible config.
69/// - `functions`: Additional attribute names that should be treated like `#[pragma(...)]` on
70///   functions.
71/// - `modules`: Additional attribute names that should be treated like `#[pragma(...)]` on
72///   modules, together with optional nested derive configuration.
73/// - `derives[*].name`: Optional derive/module name.
74/// - `derives[*].functions`: Function names to expose under that derive node.
75/// - `derives[*].modules`: Nested derive modules with the same structure.
76pub fn build_with_specs(specs: impl IntoIterator<Item: AsRef<str>>) {
77    let mut config = BuildConfig::default();
78
79    for spec in specs {
80        let spec_config = config::build_config_from_json_spec(spec.as_ref())
81            .expect("config spec string must be valid JSON with a supported schema version");
82        config.merge(spec_config);
83    }
84
85    build_from_config(config);
86}
87
88/// Scan the current crate and export the generated environment using a small configuration DSL.
89pub fn build_with(configure: impl FnOnce(&mut BuildConfig)) {
90    let mut config = BuildConfig::default();
91    configure(&mut config);
92
93    build_from_config(config);
94}
95
96fn build_from_config(config: BuildConfig) {
97    let manifest_dir = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap());
98
99    builder::build_manifest(
100        config.pragmas,
101        &config.derives,
102        config.module_derives,
103        manifest_dir.join("Cargo.toml"),
104        manifest_dir.file_name().unwrap(),
105    )
106}