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
use crate;
/// Strip trailing whitespace from every line and ensure the file ends with a single newline.
pub
/// Generate C# file header with hash and nullable-enable pragma.
pub
/// Generate Directory.Build.props with Nullable=enable and LangVersion=latest.
/// This is auto-generated (overwritten on each build) so it doesn't require user maintenance.
pub
/// Visitor support files earlier alef releases wrote at the namespace root and that
/// `gen_visitor_files` no longer emits under any configuration — the modern configured-bridge
/// path folds both into `TraitBridges.cs`.
const VISITOR_SUPPORT_FILES: = ;
/// Filenames a `visitor_callbacks`-enabled run supersedes: the two support files
/// `TraitBridges.cs` now carries.
pub
/// Filenames a run without visitor callbacks does not emit: the two support files plus every
/// configured trait bridge's `context_type` / `result_type` class.
///
/// Note what the second group is: names taken straight out of the consumer's own
/// `[[trait_bridges]]` entries. `{ContextType}.cs` under the consumer's own namespace directory
/// is exactly as likely to be a file a human wrote as one alef did, which is why nothing here is
/// eligible for unlinking on a filename match. ~keep
pub
/// Report visitor support files present under `base_path` that this run did not emit.
/// **Reports only — never deletes.** Returns the reported paths so a test can assert on the
/// surface without reading the log.
///
/// ## What this replaces
///
/// Two `fs::remove_file` loops (`delete_superseded_visitor_files`, `delete_stale_visitor_files`)
/// called from `generate_bindings` — that is, from inside the stage
/// `bin_cli::helpers::collect_managed_surface` documents as "a pure in-memory render; nothing
/// here writes to disk". `alef verify` and `alef adopt` both compose that stage, and `alef diff`
/// calls `pipeline::generate` directly, so three read-only commands unlinked files in the
/// consumer's tree. `base_path` is also relative (`resolve_output_dir` returns the configured
/// `[crates.output]` string verbatim), so the unlink resolved against the process working
/// directory rather than the project root it was pointed at.
///
/// ## Why reporting, and not a narrower delete
///
/// `cli::pipeline::generate::orphans::report_disk_scan_candidates` already settled this trade in
/// this codebase. Its candidates cleared five gates — alef marker, git-tracked, under an owned
/// output root, absent from the run's keep set, non-degenerate manifest for that root — and it
/// still only reports, because a consumer's hand-written 408-line Java public API class cleared
/// all five. The deletes removed here cleared none of them: a filename match was the entire test.
///
/// The disabled branch's trigger was weaker again. `config.ffi` is an `Option`, and an absent
/// `[ffi]` section read as `visitor_callbacks == false`, so a consumer who had simply never
/// written an `[ffi]` section was treated identically to one who had explicitly disabled the
/// feature. Requiring an explicit `false` would fix only that third fault and leave the other two
/// standing; a marker/ownership gate would leave a read-only command deleting, and the precedent
/// above has already found that gate insufficient. The asymmetry decides it exactly as it did
/// there: a file left behind costs a CS8632 warning and a line in the log naming the path; a file
/// wrongly removed costs a consumer source file nobody reads by hand. ~keep
///
/// ~keep `emitted` is the set of paths this run is actually writing, and it is the difference
/// between a true statement and a false one. The check used to be `path.is_file()` alone, run
/// before the type and enum emitters had pushed anything: in the branch where `visitor_callbacks`
/// is off (which includes a consumer having no `[ffi]` section at all, since `unwrap_or(false)`
/// cannot tell that from an explicit `false`) the candidate list is `{context_type}.cs` and
/// `{result_type}.cs` from `[[trait_bridges]]` -- and those emitters, whose skip is gated on
/// `has_visitor_callbacks`, go on to write exactly those files. So the run emitted the files and
/// reported them as unemitted in the same breath, on every generate, adopt, verify and diff.
pub