///|
/// Frozen project identity and selections. Paths remain selections with their
/// configuration origins; the host must resolve them against its own grants.
#derive(Eq, Debug)
pub(all) struct ProjectMetadataScope {
workspace_root : String
project_root : String
project_name : String
request : @configuration.MetadataProviderRequest
}
///|
pub extend ProjectMetadataScope with Eq::{equal, not_equal}
///|
pub extend ProjectMetadataScope with @debug.Debug::{to_repr}
///|
/// Bind a distinct capability closure to each planned MoonBit project. This
/// callback must be effect-free: restoration belongs in restore_library at
/// execution time. It must not allocate resources requiring plan disposal.
/// Static constructor capabilities and a project binder are separate authorities.
pub fn Engine::register_project_metadata_provider(
self : Engine,
bind : (ProjectMetadataScope) -> @linked_metadata.Capabilities raise,
) -> Unit raise {
if self.static_metadata_authority || self.project_metadata_provider is Some(_) {
raise @configuration.Invalid(
"metadata.ambiguous_authority: Use either static metadata capabilities or one project metadata provider",
)
}
self.project_metadata_provider = Some(bind)
}
///|
fn Engine::bind_project_metadata(
self : Engine,
name : String,
backend : GenerationBackend?,
scope : ProjectMetadataScope,
) -> GenerationBackend? raise {
guard name == "moonbit" &&
backend is Some(generator) &&
self.project_metadata_provider is Some(bind) else {
return backend
}
let capabilities = bind(scope)
Some({
..generator,
generate: fn(unit, options, cancelled) raise {
moonbit_generation(unit, options, cancelled, capabilities)
},
})
}