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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
//! Answers "is this field optional?" and "does the result declare this field at all?" against
//! the *exact type the call returns*, instead of by bare field name across the whole crate IR.
//!
//! `FieldResolver::ir_field_sets` has to answer both questions from flat name sets, because it
//! is handed nothing that identifies which type the call under generation actually returns. That
//! forces two compromises it documents honestly and this module removes:
//!
//! * optionality is decided by unanimity — a name counts as optional only when EVERY declaration
//! of it in the crate is `Option<T>` — so one required twin on an unrelated struct silences the
//! guard for the declaration that matters;
//! * reachability is decided by existence-anywhere, so a name declared on any type at all reads
//! as a member of every result.
//!
//! Both are the safe default for a set that cannot tell types apart. Once the call's declared
//! return type is resolved (`codegen::call_ir::resolve_declared_result_type`), neither
//! compromise is needed: [`build_ir_result_field_map`] keys its answers by `(owner_type,
//! field_name)` and the two walkers below advance a type cursor from the root through the IR's
//! own struct graph before answering at the leaf — the same shape `ir_enum` and `ir_collection`
//! already use, and for the same reason.
//!
//! ~keep The optional set is *binding* optionality, not core-crate optionality. A NAPI binding
//! widens every field of a `Default`-implementing type to `Option<T>`, so a field declared
//! `metadata: PageMetadata` in Rust still reaches TypeScript as `readonly metadata?:
//! PageMetadata`; a snippet that renders `result.metadata.title` against it is a `TS18048`.
//! `OptionalityRule` carries which of those rules the target binding applies, and the NAPI arm
//! calls the binding backend's own predicate so the two can never drift.
use ;
use cratebinding_fields;
use crate;
use cratenamed_type;
use ;
use IrResultFieldMap;
/// Which "this field may be absent" rule the target language's binding applies.
///
/// A per-language choice rather than one shared answer because the bindings genuinely disagree,
/// and picking either one for everybody breaks the other half: guarding a wasm-bindgen getter
/// that always returns a value adds dead `?.` noise, while not guarding a NAPI `has_default`
/// field is a compile error in the generated snippet.
pub
/// Build the per-owner-type field facts [`IrResultFieldMap`] answers from.
///
/// `declared_fields` records only fields the binding actually attaches an accessor to
/// ([`binding_fields`], the same predicate every backend emits from), so a `#[serde(skip)]`
/// field is absent here exactly as it is absent from the generated class — a derived accessor
/// for it would not compile.
pub
/// Walk `path` from `map.root_type` through the IR struct graph and answer whether the leaf
/// segment is optional on the exact type that owns it.
///
/// `false` — never "unknown" — for an unresolved root, an unrecognized segment, or an unpopulated
/// map. Every one of those is the pre-anchoring answer for a field with no `fields_optional`
/// entry, so this is purely additive: it can only turn a `false` into a `true` when the IR
/// positively confirms the leaf is optional on the type the path reaches. Mirrors
/// `ir_collection::is_collection_path`.
pub
/// Whether `path`'s leaf segment is declared with a type this map cannot vouch for as
/// implementing `Display`: it resolves, after peeling `Option`/`Vec`, to a `Named` type from
/// the crate's own IR.
///
/// `extract` discards every `impl Display for X` before it reaches the IR (`Display` is one of
/// `STD_TRAITS`, dropped alongside `Debug`/`Clone`/etc. in
/// `extract::extractor::functions::impl_blocks`), so alef has no record of which IR types
/// genuinely implement it. `field_types` already carries exactly the fact needed to be
/// conservative about that gap: it is populated only for fields whose declared type unwraps to
/// a `Named` type ([`named_type`](crate::e2e::codegen::call_ir::named_type)), i.e. a struct or
/// enum this crate defines — the shape `println!("{}", ...)` fails to compile against unless
/// the type happens to derive/implement `Display` by hand. A scalar leaf (`String`, a numeric
/// primitive, `char`) never appears in `field_types`, so it reads as safe here, matching every
/// std type `display: true` was written for.
///
/// `false` — never "unsafe" — for an unresolved root, an unrecognized segment, or an unpopulated
/// map, mirroring [`is_optional_path`]'s fallback: caller must already default the flag to "no
/// warning" for a fixture with no IR in scope, so this cannot regress those.
pub
/// Whether the call's result type declares `path`'s FIRST segment as a binding-visible field.
///
/// `None` when nothing was anchored — no resolved root type, or a root type this map has no
/// fields for (an opaque handle, an enum, a type from outside the extracted surface). Callers
/// must treat `None` as "no answer" and fall back, exactly as `TargetParams::IrAbsent` does;
/// reading it as rejection would empty out every snippet whose result type is not a plain struct.
///
/// Only the first segment is judged. A deeper segment can legitimately walk into a type this map
/// does not carry (a map value, a `serde_json::Value`, a foreign type), and rejecting those would
/// discard real, compiling accessors to close a hole that only ever opened at the root. ~keep
pub
/// Whether the call's result type declares EVERY segment of `path`, walking the IR struct graph
/// from the root the same way [`walk_to_owner`] does.
///
/// [`root_declares_first_segment`] judges the root step only, which leaves a derived accessor free
/// to invent any deeper segment it likes: a snippet showed `result.document.document_structure`
/// against a `document` type declaring only `nodes`, because `document` itself was a real field
/// and nothing looked further. This walks on.
///
/// `None` — no answer, caller falls back — for every state where the IR genuinely cannot judge:
/// an unresolved root, a type this map carries no fields for, a `length`/`count` pseudo-segment,
/// and (the load-bearing one) a prefix segment whose declared type is not a struct in this map at
/// all. That last case is a map value, a `serde_json::Value`, a primitive, or a type from outside
/// the extracted surface — reachable, spellable, and unjudgeable — so it keeps the conservatism
/// [`root_declares_first_segment`] documents rather than discarding real accessors. Only a segment
/// the IR positively knows the owner of, and positively does not find, answers `Some(false)`. ~keep
pub
/// The `(owner_type, leaf_field_name)` a path resolves to, walking every prefix segment through
/// `field_types`. `None` when the root is unresolved or any segment names something the IR does
/// not recognize as a field on the type reached so far.