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 displayable: bool,
32 },
33 ValueEnum {
34 variants: Vec<ValueEnumVariant>,
35 underlying_ty: Option<Type>,
36 methods: MethodSignatures,
37 },
38 Struct {
39 generics: Vec<Generic>,
40 fields: Vec<StructFieldDefinition>,
41 kind: StructKind,
42 methods: MethodSignatures,
43 constructor: Option<Type>,
44 displayable: bool,
45 },
46 Interface {
47 definition: Interface,
48 },
49 Value {
50 allowed_lints: Vec<String>,
51 go_hints: Vec<String>,
52 go_name: Option<String>,
53 },
54}
55
56impl Definition {
57 pub fn ty(&self) -> &Type {
58 &self.ty
59 }
60
61 pub fn visibility(&self) -> &Visibility {
62 &self.visibility
63 }
64
65 pub fn name_span(&self) -> Option<Span> {
66 self.name_span
67 }
68
69 pub fn doc(&self) -> Option<&String> {
70 self.doc.as_ref()
71 }
72
73 pub fn is_newtype(&self) -> bool {
78 matches!(
79 &self.body,
80 DefinitionBody::Struct {
81 kind: StructKind::Tuple,
82 fields,
83 generics,
84 ..
85 } if fields.len() == 1 && generics.is_empty()
86 )
87 }
88
89 pub fn is_pointer_backed_newtype<F>(&self, is_alias: F) -> bool
90 where
91 F: Fn(&str) -> bool,
92 {
93 self.is_newtype()
94 && matches!(
95 &self.body,
96 DefinitionBody::Struct { fields, .. }
97 if crate::types::peel_alias(&fields[0].ty, is_alias).is_ref()
98 )
99 }
100
101 pub fn allowed_lints(&self) -> &[String] {
102 match &self.body {
103 DefinitionBody::Value { allowed_lints, .. } => allowed_lints,
104 _ => &[],
105 }
106 }
107
108 pub fn go_hints(&self) -> &[String] {
109 match &self.body {
110 DefinitionBody::Value { go_hints, .. } => go_hints,
111 _ => &[],
112 }
113 }
114
115 pub fn go_name(&self) -> Option<&str> {
116 match &self.body {
117 DefinitionBody::Value { go_name, .. } => go_name.as_deref(),
118 _ => None,
119 }
120 }
121
122 pub fn methods_mut(&mut self) -> Option<&mut MethodSignatures> {
123 match &mut self.body {
124 DefinitionBody::Struct { methods, .. } => Some(methods),
125 DefinitionBody::TypeAlias { methods, .. } => Some(methods),
126 DefinitionBody::Enum { methods, .. } => Some(methods),
127 DefinitionBody::ValueEnum { methods, .. } => Some(methods),
128 _ => None,
129 }
130 }
131
132 pub fn is_displayable(&self) -> bool {
133 matches!(
134 &self.body,
135 DefinitionBody::Struct {
136 displayable: true,
137 ..
138 } | DefinitionBody::Enum {
139 displayable: true,
140 ..
141 }
142 )
143 }
144
145 pub fn is_type_definition(&self) -> bool {
146 matches!(
147 self.body,
148 DefinitionBody::Struct { .. }
149 | DefinitionBody::Enum { .. }
150 | DefinitionBody::ValueEnum { .. }
151 | DefinitionBody::TypeAlias { .. }
152 )
153 }
154
155 pub fn is_type_alias(&self) -> bool {
156 matches!(self.body, DefinitionBody::TypeAlias { .. })
157 }
158}
159
160pub type MethodSignatures = HashMap<EcoString, Type>;
161
162#[derive(Debug, Clone, PartialEq)]
163pub enum Visibility {
164 Public,
165 Private,
166 Local,
167}
168
169impl Visibility {
170 pub fn is_public(&self) -> bool {
171 matches!(self, Visibility::Public)
172 }
173}
174
175#[derive(Debug, Clone, PartialEq)]
176pub struct Interface {
177 pub name: EcoString,
178 pub generics: Vec<Generic>,
179 pub parents: Vec<Type>,
180 pub methods: HashMap<EcoString, Type>,
181}