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