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
//! Per-fixture, per-language exclusion checks the snippet driver's `expected` gate consults
//! before a coverage cell is ever pushed.
//!
//! Split out of `mod.rs` to keep that file under the repo's per-file line cap: these three
//! predicates share no state with the rest of the driver beyond [`super::SnippetRenderContext`]
//! and [`super::DocumentationLanguage`], which they take as ordinary parameters.
use ;
use crate;
use crateFixture;
/// Whether the function a fixture's call resolves to for `language` is excluded for that
/// language, and therefore can never be rendered into a snippet.
///
/// Reuses [`crate::docs::language_pages::excludes::language_excludes`] -- the accessor the
/// docs generator already consults for the same question -- rather than re-deriving the
/// per-language `exclude_functions` union here. A second copy of that rule is exactly how a
/// ledger and its emitter drift apart: one path evolves (a language gains an override, a new
/// per-language config field is added) and the other silently keeps checking the old shape.
/// [`CallConfig::core_lookup_name`] gives the Rust-spelled identity `exclude_functions`
/// entries are keyed by, matching every built-in snippet recipe's own resolution (see
/// `e2e/codegen/go/snippet.rs`, `kotlin/snippet.rs`, `php/snippet.rs`, `ruby/snippet.rs`, and
/// the WASM-specific `rust_identity_for_wasm_symbol`, which resolves the same identity for the
/// one target that also accepts the JS spelling of an override). ~keep
pub
/// Whether `fixture` exercises the fixture engine's generic visitor/trait-bridge entry point
/// ([`Fixture::visitor`]) and this language excludes it via the
/// [`crate::e2e::fixture::VISITOR_EXCLUDE_FUNCTION_NAME`] convention.
///
/// `exclude_functions` normally names a real Rust function, so
/// [`function_excluded_for_language`] cannot catch this case: a visitor fixture's *call*
/// resolves to some ordinary function (e.g. `convert`), while the visitor itself attaches
/// through a trait-bridge parameter or options-struct field that never has its own IR function
/// name. `e2e::codegen::kotlin_android::project` already applies this exact rule when deciding
/// whether to emit a fixture's Kotlin-Android e2e test or fall back to
/// `ExcludedBindingsTest.kt`; without the matching check here, snippet generation rendered real
/// code against a visitor API the binding never exposed for that language. ~keep
pub
/// Whether the function or method a fixture's call resolves to for `language` is
/// `binding_excluded` in the IR -- i.e. marked `#[alef::skip]`/`#[doc(hidden)]` at
/// extraction time, which excludes it from every generated binding regardless of what
/// `alef.toml` configures.
///
/// This is deliberately separate from [`function_excluded_for_language`]: that helper
/// only ever consults `alef.toml`-configured `exclude_functions` lists via
/// [`crate::docs::language_pages::excludes::language_excludes`], which never reads
/// `FunctionDef::binding_excluded` / `MethodDef::binding_excluded` at all -- see
/// `src/snippets/gaps.rs`'s `LedgerExpectations` doc comment, which documented this exact
/// gap before this function closed it. Without this check a function a Rust author
/// explicitly opted out of every binding still entered `coverage.expected` for every
/// non-Rust language, and the snippet coverage ledger reported the resulting absence as a
/// gap the consumer has no `alef.toml` knob to silence -- it was never a gap.
///
/// Mirrors the `lang == Language::Rust || !binding_excluded` rule
/// `docs::language_pages::mod::generate_lang_doc` already applies for the same flag: the
/// Rust documentation page still lists a `binding_excluded` item (it exists in Rust
/// source, it is just not exposed to other-language bindings), so `"rust"` is carved out
/// here too and never treated as excluded.
///
/// Resolution mirrors [`crate::e2e::codegen::call_ir::CallIr::signature`]'s
/// free-function-first, then agreeing-methods fallback, but answers the `binding_excluded`
/// question instead of a signature: a free function of the resolved name wins
/// unambiguously (a crate has at most one `pub fn` of a given path), and when only methods
/// match, every same-named method across every type must agree on the flag or this
/// answers `false` (not excluded) rather than guessing. This mirrors `CallIr::signature`'s
/// conservatism on disagreement -- "learned nothing" -- deliberately: treating
/// disagreement as excluded would drop a cell that is still fully bindable through at
/// least one of the disagreeing types, which is worse than occasionally letting a
/// genuinely-excluded cell surface as a coverage gap a human can then triage with a
/// `docs.coverage_exceptions` entry. ~keep
///
/// A method can land at `binding_excluded == true` for two structurally different reasons
/// that this IR flag does not otherwise distinguish -- see [`adapter_binds_method_for_language`]
/// for why an adapter-handled method must not be treated as excluded here. ~keep
pub
/// Whether `[[crates.adapters]]` gives `type_name.method_name` a real binding surface in
/// `lang`, even though `MethodDef::binding_excluded` is `true` for it.
///
/// `mark_adapter_handled_methods` (`src/cli/pipeline/extract/services.rs`) sets
/// `binding_excluded = true` on every method matched by an adapter's `owner_type` +
/// `core_path`, with no per-language distinction at all -- it exists only to stop the
/// *generic* method codegen path from double-emitting a method a backend's adapter
/// machinery (async-method, streaming, callback-bridge) already handles through its own
/// specialised template. It says nothing about whether that language actually binds the
/// method: every backend that consumes `[[crates.adapters]]` (pyo3, napi, magnus, dart,
/// swift, kotlin, java, php, wasm -- see the `skip_languages` call sites in each backend's
/// `gen_bindings/mod.rs`) still emits the method for every language *except* the ones the
/// adapter's own `skip_languages` names; languages outside that pattern's backend set fall
/// through to the ordinary per-method codegen loop, which does not filter on
/// `binding_excluded` at the method level either (only `TypeDef::binding_excluded` gates a
/// whole type). So an adapter-handled method has a binding surface in `lang` unless this
/// specific adapter entry explicitly names `lang` in `skip_languages` -- re-deriving that
/// per-language answer from the same config `mark_adapter_handled_methods` read, rather
/// than trusting the language-blind flag it wrote, is what keeps this in sync with what
/// every backend's `skip_languages` filter already decides for real codegen. ~keep