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