Skip to main content

lisette_syntax/program/
definition.rs

1use rustc_hash::FxHashMap as HashMap;
2
3use ecow::EcoString;
4
5use crate::ast::{
6    Annotation, EnumVariant, Generic, Span, StructFieldDefinition, StructKind, ValueEnumVariant,
7};
8use crate::types::Type;
9
10#[derive(Debug, Clone)]
11pub struct Definition {
12    pub visibility: Visibility,
13    pub ty: Type,
14    pub name: Option<EcoString>,
15    pub name_span: Option<Span>,
16    pub doc: Option<String>,
17    pub body: DefinitionBody,
18}
19
20#[derive(Debug, Clone)]
21pub enum DefinitionBody {
22    TypeAlias {
23        generics: Vec<Generic>,
24        annotation: Annotation,
25        methods: MethodSignatures,
26    },
27    Enum {
28        generics: Vec<Generic>,
29        variants: Vec<EnumVariant>,
30        methods: MethodSignatures,
31    },
32    ValueEnum {
33        variants: Vec<ValueEnumVariant>,
34        underlying_ty: Option<Type>,
35        methods: MethodSignatures,
36    },
37    Struct {
38        generics: Vec<Generic>,
39        fields: Vec<StructFieldDefinition>,
40        kind: StructKind,
41        methods: MethodSignatures,
42        constructor: Option<Type>,
43    },
44    Interface {
45        definition: Interface,
46    },
47    Value {
48        allowed_lints: Vec<String>,
49        go_hints: Vec<String>,
50        go_name: Option<String>,
51    },
52}
53
54impl Definition {
55    pub fn ty(&self) -> &Type {
56        &self.ty
57    }
58
59    pub fn visibility(&self) -> &Visibility {
60        &self.visibility
61    }
62
63    pub fn name_span(&self) -> Option<Span> {
64        self.name_span
65    }
66
67    pub fn doc(&self) -> Option<&String> {
68        self.doc.as_ref()
69    }
70
71    /// A newtype is a single-field, non-generic tuple struct. Relevant
72    /// because Go compiles newtypes to named scalar types, so `.0` is a cast
73    /// rather than a field access — it cannot be assigned to, and taking
74    /// its address is invalid.
75    pub fn is_newtype(&self) -> bool {
76        matches!(
77            &self.body,
78            DefinitionBody::Struct {
79                kind: StructKind::Tuple,
80                fields,
81                generics,
82                ..
83            } if fields.len() == 1 && generics.is_empty()
84        )
85    }
86
87    pub fn allowed_lints(&self) -> &[String] {
88        match &self.body {
89            DefinitionBody::Value { allowed_lints, .. } => allowed_lints,
90            _ => &[],
91        }
92    }
93
94    pub fn go_hints(&self) -> &[String] {
95        match &self.body {
96            DefinitionBody::Value { go_hints, .. } => go_hints,
97            _ => &[],
98        }
99    }
100
101    pub fn go_name(&self) -> Option<&str> {
102        match &self.body {
103            DefinitionBody::Value { go_name, .. } => go_name.as_deref(),
104            _ => None,
105        }
106    }
107
108    pub fn methods_mut(&mut self) -> Option<&mut MethodSignatures> {
109        match &mut self.body {
110            DefinitionBody::Struct { methods, .. } => Some(methods),
111            DefinitionBody::TypeAlias { methods, .. } => Some(methods),
112            DefinitionBody::Enum { methods, .. } => Some(methods),
113            DefinitionBody::ValueEnum { methods, .. } => Some(methods),
114            _ => None,
115        }
116    }
117
118    pub fn is_type_definition(&self) -> bool {
119        matches!(
120            self.body,
121            DefinitionBody::Struct { .. }
122                | DefinitionBody::Enum { .. }
123                | DefinitionBody::ValueEnum { .. }
124                | DefinitionBody::TypeAlias { .. }
125        )
126    }
127
128    pub fn is_type_alias(&self) -> bool {
129        matches!(self.body, DefinitionBody::TypeAlias { .. })
130    }
131}
132
133pub type MethodSignatures = HashMap<EcoString, Type>;
134
135#[derive(Debug, Clone, PartialEq)]
136pub enum Visibility {
137    Public,
138    Private,
139    Local,
140}
141
142impl Visibility {
143    pub fn is_public(&self) -> bool {
144        matches!(self, Visibility::Public)
145    }
146}
147
148#[derive(Debug, Clone, PartialEq)]
149pub struct Interface {
150    pub name: EcoString,
151    pub generics: Vec<Generic>,
152    pub parents: Vec<Type>,
153    pub methods: HashMap<EcoString, Type>,
154}