prebindgen_registry/registry/model.rs
1//! Questions about the model, answered through the registry that projects it.
2
3use std::collections::HashMap;
4
5use super::{
6 view::{default_module_of, origin_module_of},
7 *,
8};
9
10impl<M> Registry<M> {
11 /// The parameter-side fold for each `(function, parameter)` position.
12 ///
13 /// Inherent rather than on [`Conversions`]: a fold is read when a wrapper's
14 /// parameters are emitted, never while a conversion is being built, so no
15 /// generic caller needs it.
16 pub fn expansion_plans(&self) -> &HashMap<(syn::Ident, syn::Ident), crate::expand::FoldPlan> {
17 &self.expansion_plans
18 }
19
20 /// What the binding declared — read by the emitter's gate.
21 pub(crate) fn declared(&self) -> &Declared {
22 &self.declared
23 }
24
25 /// The parsed model this registry projects.
26 pub fn flat(&self) -> &prebindgen_flat::flat::Flat {
27 &self.flat
28 }
29
30 /// Every **named** item the model holds — functions, structs, either enum
31 /// shape, consts — regardless of whether the stream carried an origin stamp.
32 ///
33 /// Lives here so an adapter that needs "anything the source crate defines"
34 /// does not enumerate element kinds itself: a new kind is taught here once
35 /// instead of drifting in each adapter. An **alias is deliberately absent**
36 /// — see the arm below — and callers are expected to pair this with
37 /// `origin_module(..).unwrap_or_else(default_module)`.
38 pub fn named_item_idents(&self) -> impl Iterator<Item = &syn::Ident> {
39 use prebindgen_flat::flat::{Element, Type};
40 self.flat.elements().filter_map(|e| match e {
41 // An `Extern` names a type without declaring a body, and is
42 // deliberately absent: its caller decides which names to qualify in
43 // generated Rust, and qualifying an alias would move that output.
44 Element::Type(Type::Extern(_)) => None,
45 Element::Function(_) | Element::Type(_) | Element::Constant(_) => e.name(),
46 Element::Guard(_) | Element::Unsupported(_) => None,
47 })
48 }
49
50 /// Whether the source declares a type under this name — **including an
51 /// alias**.
52 ///
53 /// An alias counts because `#[prebindgen] pub type Handle = ..` *is* a
54 /// declaration of that name: it can be declared bare by an adapter (landing
55 /// in the no-indexed-body branch below, which is what
56 /// `ptr_class(ZKeyExpr<'static>)` relies on), so a diagnostic that says
57 /// "no such captured item" would be false.
58 pub(super) fn declares_type(&self, ident: &syn::Ident) -> bool {
59 self.flat.declared_type(ident).is_some()
60 }
61
62 /// The origin crate's **module path** for an item, read off the element's
63 /// own [`SourceLocation`] stamp, or `None` when unknown — callers then fall
64 /// back to [`Self::default_module`].
65 pub fn origin_module(&self, ident: &syn::Ident) -> Option<syn::Path> {
66 // Off the element's own location, which covers both populations: a
67 // captured item stamped at capture time, and a binding-local fn stamped
68 // by `add_local_function`.
69 origin_module_of(&self.flat, ident)
70 }
71
72 /// The default module for references with no recorded origin: the
73 /// first-seen item origin. `None` for an origin-less item-level
74 /// registry (adapters then fall back to `crate`). To change a module
75 /// name, override it at the source — a stream's origin stamps
76 /// (`Source::builder(dir).crate_name("myflat")`) — never here: a
77 /// registry-level override could only fix ONE module, which is
78 /// incomplete with chained multi-source streams.
79 pub fn default_module(&self) -> Option<syn::Path> {
80 default_module_of(&self.flat)
81 }
82
83 /// Module paths of every ingested source, ingestion order — e.g. for a
84 /// glob import that must see all sources' items.
85 pub fn all_source_modules(&self) -> Vec<syn::Path> {
86 self.flat
87 .source_modules()
88 .iter()
89 .filter_map(|m| syn::parse_str(m).ok())
90 .collect()
91 }
92}