Skip to main content

vexil_codegen_rust/
annotations.rs

1use crate::emit::CodeWriter;
2use vexil_lang::ir::{ResolvedAnnotations, TombstoneDef};
3
4/// Emit `@doc` as `///` doc comments.
5pub fn emit_doc(w: &mut CodeWriter, annotations: &ResolvedAnnotations) {
6    for doc in &annotations.doc {
7        w.line(&format!("/// {doc}"));
8    }
9}
10
11/// Emit `@since` as a doc comment.
12pub fn emit_since(w: &mut CodeWriter, annotations: &ResolvedAnnotations) {
13    if let Some(ref since) = annotations.since {
14        w.line(&format!("/// @since {since}"));
15    }
16}
17
18/// Emit `@deprecated` as `#[deprecated(...)]`.
19pub fn emit_deprecated(w: &mut CodeWriter, annotations: &ResolvedAnnotations) {
20    if let Some(ref dep) = annotations.deprecated {
21        match &dep.since {
22            Some(since) => w.line(&format!(
23                "#[deprecated(since = \"{since}\", note = \"{}\")]",
24                dep.reason
25            )),
26            None => w.line(&format!("#[deprecated(note = \"{}\")]", dep.reason)),
27        }
28    }
29}
30
31/// Emit `@non_exhaustive` as `#[non_exhaustive]`.
32pub fn emit_non_exhaustive(w: &mut CodeWriter, annotations: &ResolvedAnnotations) {
33    if annotations.non_exhaustive {
34        w.line("#[non_exhaustive]");
35    }
36}
37
38/// Emit all type-level annotations in standard order.
39pub fn emit_type_annotations(w: &mut CodeWriter, annotations: &ResolvedAnnotations) {
40    emit_doc(w, annotations);
41    emit_since(w, annotations);
42    emit_deprecated(w, annotations);
43    emit_non_exhaustive(w, annotations);
44}
45
46/// Emit field-level annotations.
47pub fn emit_field_annotations(w: &mut CodeWriter, annotations: &ResolvedAnnotations) {
48    emit_doc(w, annotations);
49    emit_since(w, annotations);
50    emit_deprecated(w, annotations);
51}
52
53/// Emit protocol-level annotations (@revision).
54pub fn emit_protocol_annotations(w: &mut CodeWriter, annotations: &ResolvedAnnotations) {
55    if let Some(rev) = annotations.revision {
56        w.line(&format!("/// @revision({rev})"));
57    }
58}
59
60pub fn emit_tombstones(w: &mut CodeWriter, type_name: &str, tombstones: &[TombstoneDef]) {
61    if tombstones.is_empty() {
62        return;
63    }
64    for t in tombstones {
65        let since_str = t.since.as_deref().unwrap_or("unknown");
66        w.line(&format!(
67            "// REMOVED @{} (since {}): {}",
68            t.ordinal, since_str, t.reason
69        ));
70    }
71    w.write(&format!(
72        "pub const {}_REMOVED_ORDINALS: &[(u16, &str, &str)] = &[",
73        type_name.to_uppercase()
74    ));
75    w.append("\n");
76    w.indent();
77    for t in tombstones {
78        let since_str = t.since.as_deref().unwrap_or("unknown");
79        w.line(&format!(
80            "({}, \"{}\", \"{}\"),",
81            t.ordinal, since_str, t.reason
82        ));
83    }
84    w.dedent();
85    w.line("];");
86}