1use crate::{
6 load::ModuleLoader,
7 model::{
8 annotations::{AnnotationBuilder, AnnotationOnlyBody, AnnotationProperty, HasAnnotations},
9 check::{find_definition, MaybeIncomplete, Validate},
10 definitions::Definition,
11 identifiers::{Identifier, IdentifierReference},
12 modules::Module,
13 values::Value,
14 HasName, HasOptionalBody, HasSourceSpan, References, Span,
15 },
16 store::ModuleStore,
17};
18use sdml_errors::diagnostics::functions::{
19 property_reference_not_property, type_definition_not_found, IdentifierCaseConvention,
20};
21use std::{collections::BTreeSet, fmt::Debug};
22use tracing::error;
23
24#[cfg(feature = "serde")]
25use serde::{Deserialize, Serialize};
26
27#[derive(Clone, Debug)]
33#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
34pub struct Member {
35 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
36 span: Option<Span>,
37 kind: MemberKind,
38}
39
40#[derive(Clone, Debug)]
41#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
42pub enum MemberKind {
43 Reference(IdentifierReference),
44 Definition(MemberDef),
45}
46
47#[derive(Clone, Debug)]
49#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
50pub struct MemberDef {
51 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
52 span: Option<Span>,
53 name: Identifier,
54 target_cardinality: Cardinality,
55 target_type: TypeReference,
56 #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
57 body: Option<AnnotationOnlyBody>,
58}
59
60impl<T> From<T> for Member
65where
66 T: Into<MemberKind>,
67{
68 fn from(kind: T) -> Self {
69 Self {
70 span: Default::default(),
71 kind: kind.into(),
72 }
73 }
74}
75
76impl HasSourceSpan for Member {
77 fn with_source_span(self, span: Span) -> Self {
78 let mut self_mut = self;
79 self_mut.span = Some(span);
80 self_mut
81 }
82
83 fn source_span(&self) -> Option<&Span> {
84 self.span.as_ref()
85 }
86
87 fn set_source_span(&mut self, span: Span) {
88 self.span = Some(span);
89 }
90
91 fn unset_source_span(&mut self) {
92 self.span = None;
93 }
94}
95
96impl MaybeIncomplete for Member {
97 fn is_incomplete(&self, top: &Module, cache: &impl ModuleStore) -> bool {
98 match &self.kind {
99 MemberKind::Reference(name) => {
100 if let Some(defn) = find_definition(name, top, cache) {
101 if matches!(defn, Definition::Property(_)) {
102 defn.is_incomplete(top, cache)
103 } else {
104 error!("Member property reference not a property");
105 false
106 }
107 } else {
108 error!("Member property reference not found");
109 false
110 }
111 }
112 MemberKind::Definition(v) => v.is_incomplete(top, cache),
113 }
114 }
115}
116
117impl Validate for Member {
118 fn validate(
119 &self,
120 top: &Module,
121 cache: &impl ModuleStore,
122 loader: &impl ModuleLoader,
123 check_constraints: bool,
124 ) {
125 match &self.kind {
126 MemberKind::Reference(name) => {
127 if let Some(defn) = find_definition(name, top, cache) {
128 if !matches!(defn, Definition::Property(_)) {
129 error!("Member property reference not a property");
130 loader
131 .report(&property_reference_not_property(
132 top.file_id().copied().unwrap_or_default(),
133 name.source_span().map(|span| span.byte_range()),
134 name,
135 ))
136 .unwrap()
137 }
138 } else {
139 error!("Member property reference not found");
140 loader
141 .report(&type_definition_not_found(
142 top.file_id().copied().unwrap_or_default(),
143 name.source_span().map(|span| span.byte_range()),
144 name,
145 ))
146 .unwrap()
147 }
148 }
149 MemberKind::Definition(v) => {
150 v.validate(top, cache, loader, check_constraints);
151 }
152 }
153 validate_is_incomplete_named(self, self.name(), top, cache, loader);
154 }
155}
156
157impl References for Member {
158 fn referenced_annotations<'a>(&'a self, names: &mut BTreeSet<&'a IdentifierReference>) {
159 match &self.kind {
160 MemberKind::Reference(v) => {
161 names.insert(v);
162 }
163 MemberKind::Definition(v) => v.referenced_annotations(names),
164 }
165 }
166
167 fn referenced_types<'a>(&'a self, names: &mut BTreeSet<&'a IdentifierReference>) {
168 match &self.kind {
169 MemberKind::Reference(v) => {
170 names.insert(v);
171 }
172 MemberKind::Definition(v) => v.referenced_types(names),
173 }
174 }
175}
176
177impl Member {
178 pub const fn new_reference(in_property: IdentifierReference) -> Self {
183 Self {
184 span: None,
185 kind: MemberKind::Reference(in_property),
186 }
187 }
188
189 pub const fn new_definition(definition: MemberDef) -> Self {
190 Self {
191 span: None,
192 kind: MemberKind::Definition(definition),
193 }
194 }
195
196 pub const fn kind(&self) -> &MemberKind {
201 &self.kind
202 }
203
204 #[inline(always)]
205 pub const fn is_definition(&self) -> bool {
206 self.kind.is_definition()
207 }
208
209 #[inline(always)]
210 pub const fn as_definition(&self) -> Option<&MemberDef> {
211 self.kind.as_definition()
212 }
213
214 #[inline(always)]
215 pub const fn is_property_reference(&self) -> bool {
216 self.kind.is_property_reference()
217 }
218
219 #[inline(always)]
220 pub const fn as_property_reference(&self) -> Option<&IdentifierReference> {
221 self.kind.as_property_reference()
222 }
223
224 pub fn name(&self) -> &Identifier {
229 match self.kind() {
230 MemberKind::Reference(v) => v.member(),
231 MemberKind::Definition(defn) => defn.name(),
232 }
233 }
234
235 pub fn resolve_target_type(
236 &self,
237 module: &Module,
238 cache: &impl ModuleStore,
239 ) -> Option<TypeReference> {
240 match self.kind() {
241 MemberKind::Reference(v) => {
242 if let Some(Definition::Property(property)) = cache.resolve_or_in(v, module.name())
243 {
244 Some(property.member_def().target_type().clone())
245 } else {
246 None
247 }
248 }
249 MemberKind::Definition(defn) => Some(defn.target_type().clone()),
250 }
251 }
252
253 pub fn resolve_target_cardinality(
254 &self,
255 module: &Module,
256 cache: &impl ModuleStore,
257 ) -> Option<Cardinality> {
258 match self.kind() {
259 MemberKind::Reference(v) => {
260 if let Some(Definition::Property(property)) = cache.resolve_or_in(v, module.name())
261 {
262 Some(property.member_def().target_cardinality().clone())
263 } else {
264 None
265 }
266 }
267 MemberKind::Definition(defn) => Some(defn.target_cardinality().clone()),
268 }
269 }
270}
271
272impl From<MemberDef> for MemberKind {
277 fn from(value: MemberDef) -> Self {
278 Self::Definition(value)
279 }
280}
281
282impl From<IdentifierReference> for MemberKind {
283 fn from(value: IdentifierReference) -> Self {
284 Self::Reference(value)
285 }
286}
287
288impl MemberKind {
289 pub const fn is_definition(&self) -> bool {
294 matches!(self, Self::Definition(_))
295 }
296
297 pub const fn as_definition(&self) -> Option<&MemberDef> {
298 match self {
299 Self::Definition(v) => Some(v),
300 _ => None,
301 }
302 }
303
304 pub const fn is_property_reference(&self) -> bool {
305 matches!(self, Self::Reference(_))
306 }
307
308 pub const fn as_property_reference(&self) -> Option<&IdentifierReference> {
309 match self {
310 Self::Reference(v) => Some(v),
311 _ => None,
312 }
313 }
314}
315
316impl HasName for MemberDef {
321 fn name(&self) -> &Identifier {
322 &self.name
323 }
324
325 fn set_name(&mut self, name: Identifier) {
326 self.name = name;
327 }
328}
329
330impl HasCardinality for MemberDef {
331 fn target_cardinality(&self) -> &Cardinality {
332 &self.target_cardinality
333 }
334
335 fn set_target_cardinality(&mut self, target_cardinality: Cardinality) {
336 self.target_cardinality = target_cardinality;
337 }
338}
339
340impl HasOptionalBody for MemberDef {
341 type Body = AnnotationOnlyBody;
342
343 fn body(&self) -> Option<&Self::Body> {
344 self.body.as_ref()
345 }
346
347 fn body_mut(&mut self) -> Option<&mut Self::Body> {
348 self.body.as_mut()
349 }
350
351 fn set_body(&mut self, body: Self::Body) {
352 self.body = Some(body);
353 }
354
355 fn unset_body(&mut self) {
356 self.body = None;
357 }
358}
359
360impl HasSourceSpan for MemberDef {
361 fn with_source_span(self, span: Span) -> Self {
362 let mut self_mut = self;
363 self_mut.span = Some(span);
364 self_mut
365 }
366
367 fn source_span(&self) -> Option<&Span> {
368 self.span.as_ref()
369 }
370
371 fn set_source_span(&mut self, span: Span) {
372 self.span = Some(span);
373 }
374
375 fn unset_source_span(&mut self) {
376 self.span = None;
377 }
378}
379
380impl HasType for MemberDef {
381 fn target_type(&self) -> &TypeReference {
382 &self.target_type
383 }
384
385 fn set_target_type(&mut self, target_type: TypeReference) {
386 self.target_type = target_type;
387 }
388}
389
390impl AnnotationBuilder for MemberDef {
391 fn with_predicate<I, V>(self, predicate: I, value: V) -> Self
392 where
393 Self: Sized,
394 I: Into<IdentifierReference>,
395 V: Into<Value>,
396 {
397 let mut self_mut = self;
398 if let Some(ref mut inner) = self_mut.body {
399 inner.add_to_annotations(AnnotationProperty::new(predicate.into(), value.into()));
400 }
401 self_mut
402 }
403}
404
405impl References for MemberDef {
406 fn referenced_annotations<'a>(&'a self, names: &mut BTreeSet<&'a IdentifierReference>) {
407 self.body
408 .as_ref()
409 .map(|b| b.referenced_annotations(names))
410 .unwrap_or_default()
411 }
412
413 fn referenced_types<'a>(&'a self, names: &mut BTreeSet<&'a IdentifierReference>) {
414 self.target_type.referenced_types(names);
415 }
416}
417
418impl MaybeIncomplete for MemberDef {
419 fn is_incomplete(&self, top: &Module, cache: &impl ModuleStore) -> bool {
420 self.target_type.is_incomplete(top, cache)
421 }
422}
423
424impl Validate for MemberDef {
425 fn validate(
426 &self,
427 top: &Module,
428 cache: &impl ModuleStore,
429 loader: &impl ModuleLoader,
430 check_constraints: bool,
431 ) {
432 self.name()
433 .validate(top, loader, Some(IdentifierCaseConvention::Member));
434 self.target_type()
435 .validate(top, cache, loader, check_constraints);
436 self.target_cardinality()
437 .validate(top, cache, loader, check_constraints);
438 }
439}
440
441impl MemberDef {
442 pub fn new<T>(name: Identifier, target_type: T) -> Self
447 where
448 T: Into<TypeReference>,
449 {
450 Self {
451 span: None,
452 name,
453 target_type: target_type.into(),
454 target_cardinality: Cardinality::one(),
455 body: None,
456 }
457 }
458
459 pub const fn new_unknown(name: Identifier) -> Self {
460 Self {
461 span: None,
462 name,
463 target_type: TypeReference::Unknown,
464 target_cardinality: Cardinality::one(),
465 body: None,
466 }
467 }
468
469 pub fn with_target_type(self, target_type: TypeReference) -> Self {
470 let mut self_mut = self;
471 self_mut.target_type = target_type;
472 self_mut
473 }
474
475 pub fn with_target_cardinality(self, target_cardinality: Cardinality) -> Self {
476 let mut self_mut = self;
477 self_mut.target_cardinality = target_cardinality;
478 self_mut
479 }
480
481 pub fn with_body(self, body: AnnotationOnlyBody) -> Self {
482 let mut self_mut = self;
483 self_mut.body = Some(body);
484 self_mut
485 }
486
487 pub const fn target_type(&self) -> &TypeReference {
492 &self.target_type
493 }
494
495 pub fn set_target_type(&mut self, target_type: TypeReference) {
496 self.target_type = target_type;
497 }
498
499 pub const fn target_cardinality(&self) -> &Cardinality {
500 &self.target_cardinality
501 }
502
503 pub fn set_target_cardinality(&mut self, target_cardinality: Cardinality) {
504 self.target_cardinality = target_cardinality;
505 }
506}
507
508mod cardinality;
513pub use cardinality::{
514 Cardinality, CardinalityRange, HasCardinality, Ordering, PseudoSequenceType, Uniqueness,
515 DEFAULT_CARDINALITY, DEFAULT_CARDINALITY_RANGE, TYPE_BAG_CARDINALITY, TYPE_LIST_CARDINALITY,
516 TYPE_MAYBE_CARDINALITY, TYPE_ORDERED_SET_CARDINALITY, TYPE_SET_CARDINALITY,
517};
518
519mod types;
520pub use types::{HasType, MappingType, TypeReference};
521
522use super::check::validate_is_incomplete_named;