1use std::ops::Range;
6use std::path::PathBuf;
7
8use serde::{Deserialize, Serialize};
9
10use crate::model::names::{Arity, FunctionName, Mfa, ModuleName, RecordName, TypeName};
11
12#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
18pub enum RefContext {
19 Body,
21 TypeAttribute,
24 OtherAttribute,
27 RecordAttribute,
31 AttributeString,
35}
36
37impl RefContext {
38 #[must_use]
42 pub fn is_attribute(self) -> bool {
43 !matches!(self, Self::Body)
44 }
45
46 #[must_use]
51 pub fn holds_calls(self) -> bool {
52 matches!(
53 self,
54 Self::Body | Self::OtherAttribute | Self::RecordAttribute
55 )
56 }
57}
58
59#[derive(Debug, Clone, PartialEq, Eq)]
63pub struct LineClass {
64 pub context: RefContext,
65 pub type_spans: Vec<Range<usize>>,
66}
67
68impl LineClass {
69 #[must_use]
70 pub fn new(context: RefContext) -> Self {
71 Self {
72 context,
73 type_spans: Vec::new(),
74 }
75 }
76}
77
78#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
79#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
80#[serde(tag = "kind", rename_all = "snake_case")]
81pub enum SymbolKind {
82 Behaviour {
83 module: ModuleName,
84 },
85 Callback {
86 module: ModuleName,
87 function: FunctionName,
88 arity: Arity,
89 },
90 Function {
91 mfa: Mfa,
92 },
93 FunctionAnyArity {
98 module: ModuleName,
99 function: FunctionName,
100 },
101 Macro {
102 name: String,
103 },
104 Record {
105 name: RecordName,
106 },
107 Type {
108 module: ModuleName,
109 name: TypeName,
110 arity: Arity,
111 },
112}
113
114#[derive(Debug, Clone, Copy)]
118pub enum ExportedSymbol<'a> {
119 Function(&'a Mfa),
120 FunctionAnyArity {
121 module: &'a ModuleName,
122 function: &'a FunctionName,
123 },
124 Type {
125 module: &'a ModuleName,
126 name: &'a TypeName,
127 arity: Arity,
128 },
129}
130
131impl SymbolKind {
132 #[must_use]
133 pub fn as_exported(&self) -> Option<ExportedSymbol<'_>> {
134 match self {
135 Self::Function { mfa } => Some(ExportedSymbol::Function(mfa)),
136 Self::FunctionAnyArity { module, function } => {
137 Some(ExportedSymbol::FunctionAnyArity { module, function })
138 }
139 Self::Type {
140 module,
141 name,
142 arity,
143 } => Some(ExportedSymbol::Type {
144 module,
145 name,
146 arity: *arity,
147 }),
148 Self::Behaviour { .. }
149 | Self::Callback { .. }
150 | Self::Macro { .. }
151 | Self::Record { .. } => None,
152 }
153 }
154}
155
156#[derive(
162 Debug, Clone, Copy, Default, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize,
163)]
164#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
165#[serde(rename_all = "snake_case")]
166pub enum RefOrigin {
167 #[default]
168 Added,
169 Context,
170}
171
172impl RefOrigin {
173 #[allow(clippy::trivially_copy_pass_by_ref)]
175 #[must_use]
176 pub fn is_added(&self) -> bool {
177 matches!(self, Self::Added)
178 }
179}
180
181#[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
182#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
183pub struct SymbolRef {
184 #[serde(flatten)]
185 pub kind: SymbolKind,
186 #[serde(default, skip_serializing_if = "RefOrigin::is_added")]
187 pub origin: RefOrigin,
188}
189
190impl SymbolRef {
191 pub fn function(mfa: Mfa) -> Self {
192 Self {
193 kind: SymbolKind::Function { mfa },
194 origin: RefOrigin::Added,
195 }
196 }
197
198 pub fn function_any_arity(module: ModuleName, function: FunctionName) -> Self {
199 Self {
200 kind: SymbolKind::FunctionAnyArity { module, function },
201 origin: RefOrigin::Added,
202 }
203 }
204
205 pub fn record(name: RecordName) -> Self {
206 Self {
207 kind: SymbolKind::Record { name },
208 origin: RefOrigin::Added,
209 }
210 }
211
212 pub fn macro_use(name: impl Into<String>) -> Self {
213 Self {
214 kind: SymbolKind::Macro { name: name.into() },
215 origin: RefOrigin::Added,
216 }
217 }
218
219 pub fn type_ref(module: ModuleName, name: TypeName, arity: Arity) -> Self {
220 Self {
221 kind: SymbolKind::Type {
222 module,
223 name,
224 arity,
225 },
226 origin: RefOrigin::Added,
227 }
228 }
229
230 #[must_use]
231 pub fn with_origin(mut self, origin: RefOrigin) -> Self {
232 self.origin = origin;
233 self
234 }
235}
236
237#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
238#[cfg_attr(feature = "schemars", derive(schemars::JsonSchema))]
239pub struct Reference {
240 pub symbol: SymbolRef,
241 pub from_path: PathBuf,
242 pub line: usize,
243}