use super::{ParentSyntax, parse_face, replace_face_macro, source_references};
#[test]
fn parses_multiline_registration_tokens_and_locations() {
let source = r#"
crate::control_object! {
kind: Button,
name: { zh: "按钮", en: "Button" },
requires: [
"layout.viewport" => "ControlRegistry",
"draw.basic" => "BasicDrawing",
],
parent: crate::NodeId::from_path("control/control.rs", "ControlRegistry"),
getting_from_other_registry: Some("engine"),
}
"#;
let face = parse_face(source).unwrap().unwrap();
assert_eq!(face.path("kind").as_deref(), Some("Button"));
assert_eq!(face.localized("name", "zh").as_deref(), Some("按钮"));
assert_eq!(face.field_location("requires").unwrap().line, 5);
assert_eq!(
face.requirements("requires").unwrap(),
[
("layout.viewport".to_owned(), "ControlRegistry".to_owned()),
("draw.basic".to_owned(), "BasicDrawing".to_owned())
]
);
assert_eq!(
face.parent(),
Some(ParentSyntax::FromPath {
source: "control/control.rs".to_owned(),
kind: "ControlRegistry".to_owned(),
})
);
assert_eq!(
face.option_string("getting_from_other_registry"),
Some(Some("engine".to_owned()))
);
}
#[test]
fn parses_namespaced_package_root_parent() {
let source = r#"
crate::control_object! {
kind: Workspace,
parent: crate::root_node_id(env!("CARGO_PKG_NAME")),
}
"#;
let face = parse_face(source).unwrap().unwrap();
assert_eq!(face.parent(), Some(ParentSyntax::Root));
}
#[test]
fn rejects_duplicate_fields() {
let source = "crate::control_object! { kind: First, kind: Second }";
let error = parse_face(source).unwrap_err();
assert!(error.message.contains("duplicate field `kind`"));
}
#[test]
fn replacing_a_face_preserves_its_rust_implementation() {
let source = r#"pub struct Button;
impl Button { pub fn paint(&self) -> u32 { 7 } }
crate::control_object! {
kind: Button,
stable_name: "button",
}
#[test] fn paints() { assert_eq!(Button.paint(), 7); }
"#;
let replacement = r#"crate::control_object! {
kind: Button,
stable_name: "button_graft",
}"#;
let copied = replace_face_macro(source, replacement).unwrap();
assert!(copied.contains("pub fn paint(&self) -> u32 { 7 }"));
assert!(copied.contains("stable_name: \"button_graft\""));
assert!(!copied.contains("stable_name: \"button\","));
assert!(copied.contains("#[test] fn paints()"));
}
#[test]
fn source_references_ignore_imports_strings_comments_and_registration_data() {
let source = r#"
use crate::unused::Thing;
fn run() {
crate::control::object::button::dispatch_action("unused::fake()", true);
// crate::comment::fake();
crate::control_object! { kind: Fake, parent: crate::hidden::NODE_ID }
}
"#;
let references = source_references(source).unwrap();
assert!(
references
.paths
.contains("crate::control::object::button::dispatch_action")
);
assert!(!references.paths.iter().any(|path| path.contains("unused")));
assert!(!references.paths.iter().any(|path| path.contains("hidden")));
assert!(!references.conservative);
}
#[test]
fn a_macro_invocation_is_read_for_the_paths_it_spells() {
let referenced = "pub fn build() { let _ = vec![crate::control::object::dial::NODE_ID]; }";
let references = source_references(referenced).unwrap();
assert!(
references
.paths
.contains("crate::control::object::dial::NODE_ID"),
"a path inside a macro is a reference like any other: {:?}",
references.paths
);
let narrow = "pub fn build() -> u8 { crate::control::dial::NODE_ID }";
assert!(!source_references(narrow).unwrap().conservative);
for transparent in [
"nichlink_run_method::host!();",
"static_graft_plan!(crate::FRAMEWORK, cut \"root/a\");",
"fn f() { crate::control_object! { kind: Fake } }",
"const NAME: &str = env!(\"CARGO_PKG_NAME\");",
"const TWO: &str = concat!(\"a\", \"b\");",
] {
assert!(
!source_references(transparent).unwrap().conservative,
"`{transparent}` must not widen the scope"
);
}
}
#[test]
fn a_declaration_keeps_its_cfg_gate() {
let face = parse_face(
"// generated-by=NichLink\n#[cfg(feature = \"optional-face\")]\n\
crate::root_object! {\n kind: Widget,\n}\n",
)
.expect("parse")
.expect("face");
assert_eq!(face.cfg(), Some("feature = \"optional-face\""));
}