#[cfg(not(all(feature = "metadata", feature = "doc-gen")))]
compile_error!(
"\n\n\
❌ This example requires both 'metadata' and 'doc-gen' features!\n\
\n\
Run with:\n\
cargo run --example component_location_standalone --features metadata,doc-gen\n\
"
);
#[cfg(all(feature = "metadata", feature = "doc-gen"))]
#[allow(dead_code)]
use std::fs;
#[cfg(all(feature = "metadata", feature = "doc-gen"))]
use waddling_errors_macros::{component_location, diag, setup};
#[cfg(all(feature = "metadata", feature = "doc-gen"))]
pub mod components {
use waddling_errors_macros::component;
component! {
pub enum Component {
Auth {
docs: "Authentication and authorization",
},
Api {
docs: "External API integrations",
},
Crypto {
docs: "Cryptographic operations",
},
}
}
pub use Component::*;
}
#[cfg(all(feature = "metadata", feature = "doc-gen"))]
pub mod primaries {
use waddling_errors_macros::primary;
primary! {
pub enum Primary {
Token {
docs: "Token-related errors",
},
Connection {
docs: "Connection errors",
},
Key {
docs: "Key errors",
},
}
}
}
#[cfg(all(feature = "metadata", feature = "doc-gen"))]
pub mod sequences {
use waddling_errors_macros::sequence;
sequence! {
EXPIRED(1) {
description: "Resource has expired",
},
INVALID(2) {
description: "Resource is invalid",
},
MISSING(3) {
description: "Resource is missing",
},
}
}
#[cfg(all(feature = "metadata", feature = "doc-gen"))]
setup! {
components = crate::components,
primaries = crate::primaries,
sequences = crate::sequences,
}
#[cfg(not(all(feature = "metadata", feature = "doc-gen")))]
pub mod components {}
#[cfg(not(all(feature = "metadata", feature = "doc-gen")))]
pub mod primaries {}
#[cfg(not(all(feature = "metadata", feature = "doc-gen")))]
pub mod sequences {}
#[cfg(all(feature = "metadata", feature = "doc-gen"))]
component_location!(Auth, role = public);
#[cfg(all(feature = "metadata", feature = "doc-gen"))]
component_location!(Crypto, role = developer);
#[cfg(all(feature = "metadata", feature = "doc-gen"))]
component_location!(Api, role = internal);
#[cfg(all(feature = "metadata", feature = "doc-gen"))]
diag! {
strict(component, primary, sequence, naming, duplicates, sequence_values, string_values),
E.Auth.Token.EXPIRED: {
message: "JWT token has expired",
hints: ["Request a new token"],
},
E.Auth.Token.INVALID: {
message: "JWT token is invalid",
hints: ["Check token format"],
},
}
#[cfg(all(feature = "metadata", feature = "doc-gen"))]
diag! {
strict(component, primary, sequence, naming, duplicates, sequence_values, string_values),
E.Crypto.Key.MISSING: {
message: "Encryption key not found",
hints: ["Check key configuration"],
},
}
#[cfg(all(feature = "metadata", feature = "doc-gen"))]
diag! {
strict(component, primary, sequence, naming, duplicates, sequence_values, string_values),
E.Api.Connection.INVALID: {
message: "API endpoint configuration invalid",
hints: ["Verify API URL"],
},
}
#[cfg(all(feature = "metadata", feature = "doc-gen"))]
mod auth_internal {
use waddling_errors_macros::in_component;
#[in_component(Auth, role = internal)]
pub mod jwt_impl {
#[allow(dead_code)]
pub fn verify_signature() {
println!("Verifying JWT signature...");
}
waddling_errors_macros::diag! {
strict(component, primary, sequence, naming, duplicates, sequence_values, string_values),
E.Auth.Token.MISSING: {
message: "JWT token not provided",
hints: ["Include Authorization header"],
},
}
}
pub use jwt_impl::*;
}
#[cfg(all(feature = "metadata", feature = "doc-gen"))]
fn main() {
use waddling_errors::doc_generator::{DocRegistry, JsonRenderer};
println!("🦆 component_location! Macro Test");
println!("==================================\n");
println!("📋 This example demonstrates:");
println!(" - Multiple component locations in ONE file");
println!(" - No need to wrap code in modules");
println!(" - Role-based visibility for each location");
println!();
let mut registry = DocRegistry::new("component_location_test", "1.0.0");
println!("📝 Registering diagnostics...");
registry.register_diagnostic_runtime(&E_AUTH_TOKEN_EXPIRED);
registry.register_diagnostic_runtime(&E_AUTH_TOKEN_INVALID);
registry.register_diagnostic_runtime(&E_CRYPTO_KEY_MISSING);
registry.register_diagnostic_runtime(&E_API_CONNECTION_INVALID);
registry.register_diagnostic_runtime(&auth_internal::E_AUTH_TOKEN_MISSING);
println!(" ✓ Registered 5 diagnostics");
println!("\n📍 Registering component locations...\n");
__component_loc_auth::register(&mut registry);
__component_loc_crypto::register(&mut registry);
__component_loc_api::register(&mut registry);
auth_internal::jwt_impl::__register_component_location(&mut registry);
println!(" ✓ Registered locations:");
println!(" - AUTH (from component_location! - public)");
println!(" - CRYPTO (from component_location! - developer)");
println!(" - API (from component_location! - internal)");
println!(" - AUTH (from #[in_component] - internal)");
println!("\n🔍 Verifying generated constants...");
assert_eq!(__component_loc_auth::COMPONENT, "Auth");
assert_eq!(__component_loc_crypto::COMPONENT, "Crypto");
assert_eq!(__component_loc_api::COMPONENT, "Api");
println!(" ✓ Component names match component! registration");
assert!(__component_loc_auth::FILE.contains("component_location_standalone.rs"));
println!(" ✓ File paths are correct");
let output_dir = "target/doc/component_location_test";
println!("\n📚 Generating documentation to {}/...", output_dir);
match registry.render_all_roles(vec![Box::new(JsonRenderer)], output_dir) {
Ok(_) => println!(" ✓ Documentation generated successfully"),
Err(e) => {
eprintln!(" ❌ Failed: {}", e);
std::process::exit(1);
}
}
println!("\n🔬 Verifying JSON output...\n");
let int_json = fs::read_to_string(format!("{}/component_location_test-int.json", output_dir))
.expect("Failed to read internal JSON");
assert!(int_json.contains("\"AUTH\""), "AUTH component missing");
assert!(int_json.contains("\"CRYPTO\""), "CRYPTO component missing");
assert!(int_json.contains("\"API\""), "API component missing");
let auth_section = int_json.find("\"AUTH\"").unwrap();
let auth_end = int_json[auth_section..].find('}').unwrap() + auth_section;
let auth_content = &int_json[auth_section..auth_end];
let auth_locations = auth_content.matches("\"path\":").count();
println!(" Component locations in internal JSON:");
println!(" - AUTH: {} locations", auth_locations);
println!(" - CRYPTO: has Public/Developer visible locations");
println!(" - API: has Internal only locations");
println!("\n✅ All tests passed!");
println!("\n📋 Summary:");
println!(" - component_location! allows multiple components per file");
println!(" - Each call generates its own marker module");
println!(" - Constants are accessible via __component_loc_<name>::*");
println!(" - Works alongside #[in_component] on modules");
println!();
println!("🎉 The component_location! macro is working correctly!");
}
#[cfg(not(all(feature = "metadata", feature = "doc-gen")))]
fn main() {}