use super::*;
pub(super) fn generated_paths(
registry: &Registry,
id: NodeId,
) -> Result<(String, PathBuf), String> {
let face = registry
.find(id)
.ok_or_else(|| format!("node `{id}` is not registered"))?;
let declared = Path::new(&face.source.file);
let root = source_root();
let source = if declared.is_absolute() {
let canonical_root = fs::canonicalize(&root)
.map_err(|error| format!("cannot resolve package source root: {error}"))?;
let canonical_source = fs::canonicalize(declared)
.map_err(|error| format!("cannot resolve registration source: {error}"))?;
if !canonical_source.starts_with(&canonical_root) {
return Err("only package-local generated modules can be edited".to_owned());
}
canonical_source
} else {
if declared.components().any(is_parent_component) {
return Err("only package-local generated modules can be edited".to_owned());
}
root.join(declared)
};
let relative = source.strip_prefix(&root).unwrap_or(declared);
let text = fs::read_to_string(&source)
.map_err(|_| "this module was not generated by NichLink".to_owned())?;
if !is_nichlink_owned_source(relative, &text) {
return Err("this module was not generated by NichLink".to_owned());
}
Ok((face.registry_name.to_owned(), source))
}
fn is_nichlink_owned_source(relative: &Path, text: &str) -> bool {
text.lines().any(|line| line == GENERATED_MARKER)
|| (relative == Path::new("control/control.rs")
&& text.contains("pub struct ControlRegistry;")
&& text.contains("registry_rule_path:")
&& text.contains("registry_rule:"))
}