1use super::{definitions::HasMultiMembers, identifiers::Identifier, HasSourceSpan};
7use crate::{
8 load::ModuleLoader,
9 model::{definitions::Definition, identifiers::IdentifierReference, modules::Module, HasName},
10 store::ModuleStore,
11};
12use sdml_errors::diagnostics::functions::{duplicate_member, member_is_incomplete};
13
14pub trait MaybeIncomplete {
19 fn is_incomplete(&self, top: &Module, cache: &impl ModuleStore) -> bool;
20}
21
22pub trait Validate {
23 fn validate(
24 &self,
25 top: &Module,
26 cache: &impl ModuleStore,
27 loader: &impl ModuleLoader,
28 check_constraints: bool,
29 );
30}
31
32pub fn find_definition<'a>(
37 name: &IdentifierReference,
38 current: &'a Module,
39 cache: &'a impl ModuleStore,
40) -> Option<&'a Definition> {
41 cache.resolve_or_in(name, current.name())
42}
43
44pub fn validate_is_incomplete<E>(
45 model_element: &E,
46 top: &Module,
47 cache: &impl ModuleStore,
48 loader: &impl ModuleLoader,
49) where
50 E: HasName + HasSourceSpan + MaybeIncomplete,
51{
52 validate_is_incomplete_named(model_element, model_element.name(), top, cache, loader)
53}
54
55pub fn validate_is_incomplete_named<E, S>(
56 model_element: &E,
57 name: S,
58 top: &Module,
59 cache: &impl ModuleStore,
60 loader: &impl ModuleLoader,
61) where
62 E: HasSourceSpan + MaybeIncomplete,
63 S: Into<String>,
64{
65 if model_element.is_incomplete(top, cache) {
66 loader
67 .report(&member_is_incomplete(
68 top.file_id().copied().unwrap_or_default(),
69 model_element.source_span().map(|span| span.byte_range()),
70 name.into(),
71 ))
72 .unwrap()
73 }
74}
75
76pub fn validate_multiple_method_duplicates<E>(
77 model_element: &E,
78 top: &Module,
79 _cache: &impl ModuleStore,
80 loader: &impl ModuleLoader,
81) where
82 E: HasSourceSpan + HasMultiMembers,
83{
84 let mut all_names: Vec<&Identifier> = model_element.all_member_names().collect();
85 all_names.sort();
86 for pair in all_names.windows(2) {
87 if pair[0] == pair[1] {
88 loader
89 .report(&duplicate_member(
90 top.file_id().copied().unwrap_or_default(),
91 pair[0]
92 .source_span()
93 .map(|span| span.byte_range())
94 .unwrap_or_default(),
95 pair[1]
96 .source_span()
97 .map(|span| span.byte_range())
98 .unwrap_or_default(),
99 ))
100 .unwrap()
101 }
102 }
103}
104
105#[cfg(feature = "terms")]
133pub mod terms {
134 use crate::{
135 load::ModuleLoader,
136 model::{
137 annotations::*, constraints::*, definitions::*, identifiers::*, members::*, modules::*,
138 values::*, *,
139 },
140 };
141 use sdml_errors::{diagnostics::functions::deprecated_term_used, Error};
142 use serde::{Deserialize, Serialize};
143 use std::collections::{HashMap, HashSet};
144
145 #[derive(Clone, Debug, Deserialize, Serialize)]
150 pub struct TermSet {
151 name: String,
152 #[serde(skip_serializing_if = "Option::is_none")]
153 version: Option<String>,
154 #[serde(skip_serializing_if = "Option::is_none")]
155 description: Option<String>,
156 terms: HashMap<String, Term>,
157 }
158
159 #[derive(Clone, Debug, Deserialize, Serialize)]
160 pub struct Term {
161 #[serde(skip_serializing_if = "Option::is_none", with = "serde_regex")]
162 regex: Option<regex::Regex>,
163 alternative_terms: Vec<String>,
164 #[serde(skip_serializing_if = "Option::is_none")]
165 reason: Option<String>,
166 }
167
168 const DEFAULT_RULES: &str = include_str!("default_terms.json");
173
174 pub fn default_term_set() -> Result<TermSet, Error> {
175 Ok(serde_json::from_str(DEFAULT_RULES).unwrap())
176 }
177
178 pub fn validate_module_terms(module: &Module, term_set: &TermSet, loader: &impl ModuleLoader) {
179 let mut validator = Validator::from(term_set);
180 module.name().validate_terms(&mut validator, module, loader);
181 for annotation in module.body().annotations() {
182 annotation.validate_terms(&mut validator, module, loader);
183 }
184 for definition in module.body().definitions() {
185 definition.validate_terms(&mut validator, module, loader);
186 }
187 }
188
189 #[derive(Clone, Debug)]
194 struct TermInfo<'a> {
195 regex: regex::Regex,
196 alternative_terms: &'a Vec<String>,
197 reason: &'a Option<String>,
198 }
199
200 #[derive(Clone, Debug)]
201 struct Validator<'a> {
202 term_map: HashMap<String, TermInfo<'a>>,
203 seen: HashSet<String>,
204 }
205
206 impl<'a> From<&'a TermSet> for Validator<'a> {
211 fn from(term_set: &'a TermSet) -> Self {
212 let mut term_map: HashMap<String, TermInfo<'a>> = Default::default();
213 for (term, info) in &term_set.terms {
214 let regex = if let Some(regex) = &info.regex {
215 regex.clone()
216 } else {
217 regex::Regex::new(&format!("(?i)\\b{}\\b", term)).unwrap()
218 };
219 let new_info = TermInfo {
220 regex,
221 alternative_terms: &info.alternative_terms,
222 reason: &info.reason,
223 };
224 term_map.insert(term.clone(), new_info);
225 }
226 Self {
227 term_map,
228 seen: Default::default(),
229 }
230 }
231 }
232
233 impl Validator<'_> {
234 fn check_for_matches<S>(
235 &mut self,
236 value: S,
237 span: Option<&Span>,
238 top: &Module,
239 loader: &impl ModuleLoader,
240 ) where
241 S: Into<String>,
242 {
243 let value = value.into();
244 if self.seen.insert(value.clone()) {
245 for (term, info) in &self.term_map {
246 if info.regex.is_match(value.as_ref()) {
247 loader
248 .report(&deprecated_term_used(
249 top.file_id().copied().unwrap_or_default(),
250 span.map(|span| span.byte_range()),
251 &value,
252 term,
253 info.alternative_terms,
254 info.reason.as_ref(),
255 ))
256 .unwrap()
257 }
258 }
259 }
260 }
261 }
262
263 trait ValidateTerms {
266 fn validate_terms(
267 &self,
268 validator: &mut Validator<'_>,
269 top: &Module,
270 loader: &impl ModuleLoader,
271 );
272 }
273
274 impl ValidateTerms for Identifier {
275 fn validate_terms(
276 &self,
277 validator: &mut Validator<'_>,
278 top: &Module,
279 loader: &impl ModuleLoader,
280 ) {
281 validator.check_for_matches(self, self.source_span(), top, loader);
282 }
283 }
284
285 impl ValidateTerms for QualifiedIdentifier {
286 fn validate_terms(
287 &self,
288 validator: &mut Validator<'_>,
289 top: &Module,
290 loader: &impl ModuleLoader,
291 ) {
292 self.module().validate_terms(validator, top, loader);
293 self.member().validate_terms(validator, top, loader);
294 }
295 }
296
297 impl ValidateTerms for IdentifierReference {
298 fn validate_terms(
299 &self,
300 validator: &mut Validator<'_>,
301 top: &Module,
302 loader: &impl ModuleLoader,
303 ) {
304 match self {
305 Self::Identifier(v) => v.validate_terms(validator, top, loader),
306 Self::QualifiedIdentifier(v) => v.validate_terms(validator, top, loader),
307 }
308 }
309 }
310
311 impl ValidateTerms for Annotation {
312 fn validate_terms(
313 &self,
314 validator: &mut Validator<'_>,
315 top: &Module,
316 loader: &impl ModuleLoader,
317 ) {
318 match self {
319 Self::Property(v) => v.validate_terms(validator, top, loader),
320 Self::Constraint(v) => v.validate_terms(validator, top, loader),
321 }
322 }
323 }
324
325 impl ValidateTerms for AnnotationProperty {
326 fn validate_terms(
327 &self,
328 validator: &mut Validator<'_>,
329 top: &Module,
330 loader: &impl ModuleLoader,
331 ) {
332 self.name_reference().validate_terms(validator, top, loader);
333 self.value().validate_terms(validator, top, loader);
334 }
335 }
336
337 impl ValidateTerms for Value {
338 fn validate_terms(
339 &self,
340 validator: &mut Validator<'_>,
341 top: &Module,
342 loader: &impl ModuleLoader,
343 ) {
344 match self {
345 Self::Simple(v) => v.validate_terms(validator, top, loader),
346 Self::ValueConstructor(v) => v.validate_terms(validator, top, loader),
347 Self::Mapping(v) => v.validate_terms(validator, top, loader),
348 Self::Reference(v) => v.validate_terms(validator, top, loader),
349 Self::Sequence(v) => v.validate_terms(validator, top, loader),
350 }
351 }
352 }
353
354 impl ValidateTerms for SimpleValue {
355 fn validate_terms(
356 &self,
357 validator: &mut Validator<'_>,
358 top: &Module,
359 loader: &impl ModuleLoader,
360 ) {
361 if let SimpleValue::String(value) = self {
362 validator.check_for_matches(value.value(), value.source_span(), top, loader);
363 }
364 }
365 }
366
367 impl ValidateTerms for ValueConstructor {
368 fn validate_terms(
369 &self,
370 validator: &mut Validator<'_>,
371 top: &Module,
372 loader: &impl ModuleLoader,
373 ) {
374 self.type_name().validate_terms(validator, top, loader);
375 self.value().validate_terms(validator, top, loader);
376 }
377 }
378
379 impl ValidateTerms for SequenceOfValues {
380 fn validate_terms(
381 &self,
382 validator: &mut Validator<'_>,
383 top: &Module,
384 loader: &impl ModuleLoader,
385 ) {
386 for value in self.iter() {
387 value.validate_terms(validator, top, loader);
388 }
389 }
390 }
391
392 impl ValidateTerms for SequenceMember {
393 fn validate_terms(
394 &self,
395 validator: &mut Validator<'_>,
396 top: &Module,
397 loader: &impl ModuleLoader,
398 ) {
399 match self {
400 Self::Simple(v) => v.validate_terms(validator, top, loader),
401 Self::ValueConstructor(v) => v.validate_terms(validator, top, loader),
402 Self::Reference(v) => v.validate_terms(validator, top, loader),
403 Self::Mapping(v) => v.validate_terms(validator, top, loader),
404 }
405 }
406 }
407
408 impl ValidateTerms for MappingValue {
409 fn validate_terms(
410 &self,
411 validator: &mut Validator<'_>,
412 top: &Module,
413 loader: &impl ModuleLoader,
414 ) {
415 self.domain().validate_terms(validator, top, loader);
416 self.range().validate_terms(validator, top, loader);
417 }
418 }
419
420 impl ValidateTerms for AnnotationOnlyBody {
421 fn validate_terms(
422 &self,
423 validator: &mut Validator<'_>,
424 top: &Module,
425 loader: &impl ModuleLoader,
426 ) {
427 for annotation in self.annotations() {
428 annotation.validate_terms(validator, top, loader);
429 }
430 }
431 }
432
433 impl ValidateTerms for Constraint {
434 fn validate_terms(
435 &self,
436 validator: &mut Validator<'_>,
437 top: &Module,
438 loader: &impl ModuleLoader,
439 ) {
440 self.name().validate_terms(validator, top, loader);
441 match self.body() {
442 ConstraintBody::Informal(v) => v.validate_terms(validator, top, loader),
443 ConstraintBody::Formal(v) => v.validate_terms(validator, top, loader),
444 }
445 }
446 }
447
448 impl ValidateTerms for ControlledLanguageString {
449 fn validate_terms(
450 &self,
451 validator: &mut Validator<'_>,
452 top: &Module,
453 loader: &impl ModuleLoader,
454 ) {
455 validator.check_for_matches(self.value(), self.source_span(), top, loader);
456 }
457 }
458
459 impl ValidateTerms for FormalConstraint {
460 fn validate_terms(
461 &self,
462 _validator: &mut Validator<'_>,
463 _top: &Module,
464 _loader: &impl ModuleLoader,
465 ) {
466 todo!()
467 }
468 }
469
470 impl ValidateTerms for Definition {
471 fn validate_terms(
472 &self,
473 validator: &mut Validator<'_>,
474 top: &Module,
475 loader: &impl ModuleLoader,
476 ) {
477 match self {
478 Self::Datatype(v) => v.validate_terms(validator, top, loader),
479 Self::Dimension(v) => v.validate_terms(validator, top, loader),
480 Self::Entity(v) => v.validate_terms(validator, top, loader),
481 Self::Enum(v) => v.validate_terms(validator, top, loader),
482 Self::Event(v) => v.validate_terms(validator, top, loader),
483 Self::Property(v) => v.validate_terms(validator, top, loader),
484 Self::Rdf(v) => v.validate_terms(validator, top, loader),
485 Self::Structure(v) => v.validate_terms(validator, top, loader),
486 Self::TypeClass(v) => v.validate_terms(validator, top, loader),
487 Self::Union(v) => v.validate_terms(validator, top, loader),
488 }
489 }
490 }
491
492 impl ValidateTerms for DatatypeDef {
493 fn validate_terms(
494 &self,
495 validator: &mut Validator<'_>,
496 top: &Module,
497 loader: &impl ModuleLoader,
498 ) {
499 self.name().validate_terms(validator, top, loader);
500 self.base_type().validate_terms(validator, top, loader);
501 if let Some(body) = self.body() {
502 body.validate_terms(validator, top, loader);
503 }
504 }
505 }
506
507 impl ValidateTerms for DimensionDef {
508 fn validate_terms(
509 &self,
510 validator: &mut Validator<'_>,
511 top: &Module,
512 loader: &impl ModuleLoader,
513 ) {
514 self.name().validate_terms(validator, top, loader);
515 if let Some(body) = self.body() {
516 for annotation in body.annotations() {
517 annotation.validate_terms(validator, top, loader);
518 }
519 match body.identity() {
520 DimensionIdentity::Source(source) => {
521 source.validate_terms(validator, top, loader)
522 }
523 DimensionIdentity::Identity(member) => {
524 member.validate_terms(validator, top, loader)
525 }
526 }
527 for parent in body.parents() {
528 parent.validate_terms(validator, top, loader);
529 }
530 for member in body.members() {
531 member.validate_terms(validator, top, loader);
532 }
533 }
534 }
535 }
536
537 impl ValidateTerms for SourceEntity {
538 fn validate_terms(
539 &self,
540 validator: &mut Validator<'_>,
541 top: &Module,
542 loader: &impl ModuleLoader,
543 ) {
544 self.target_entity().validate_terms(validator, top, loader);
545 for member in self.members() {
546 member.validate_terms(validator, top, loader);
547 }
548 }
549 }
550
551 impl ValidateTerms for DimensionParent {
552 fn validate_terms(
553 &self,
554 validator: &mut Validator<'_>,
555 top: &Module,
556 loader: &impl ModuleLoader,
557 ) {
558 self.name().validate_terms(validator, top, loader);
559 self.target_entity().validate_terms(validator, top, loader);
560 }
561 }
562
563 impl ValidateTerms for EntityDef {
564 fn validate_terms(
565 &self,
566 validator: &mut Validator<'_>,
567 top: &Module,
568 loader: &impl ModuleLoader,
569 ) {
570 self.name().validate_terms(validator, top, loader);
571 if let Some(body) = self.body() {
572 for annotation in body.annotations() {
573 annotation.validate_terms(validator, top, loader);
574 }
575 for member in body.members() {
576 member.validate_terms(validator, top, loader);
577 }
578 }
579 }
580 }
581
582 impl ValidateTerms for EnumDef {
583 fn validate_terms(
584 &self,
585 validator: &mut Validator<'_>,
586 top: &Module,
587 loader: &impl ModuleLoader,
588 ) {
589 self.name().validate_terms(validator, top, loader);
590 if let Some(body) = self.body() {
591 for annotation in body.annotations() {
592 annotation.validate_terms(validator, top, loader);
593 }
594 for variant in body.variants() {
595 variant.validate_terms(validator, top, loader);
596 }
597 }
598 }
599 }
600
601 impl ValidateTerms for ValueVariant {
602 fn validate_terms(
603 &self,
604 validator: &mut Validator<'_>,
605 top: &Module,
606 loader: &impl ModuleLoader,
607 ) {
608 self.name().validate_terms(validator, top, loader);
609 if let Some(body) = self.body() {
610 for annotation in body.annotations() {
611 annotation.validate_terms(validator, top, loader);
612 }
613 }
614 }
615 }
616
617 impl ValidateTerms for EventDef {
618 fn validate_terms(
619 &self,
620 validator: &mut Validator<'_>,
621 top: &Module,
622 loader: &impl ModuleLoader,
623 ) {
624 self.name().validate_terms(validator, top, loader);
625 if let Some(body) = self.body() {
626 for annotation in body.annotations() {
628 annotation.validate_terms(validator, top, loader);
629 for member in body.members() {
630 member.validate_terms(validator, top, loader);
631 }
632 }
633 }
634 }
635 }
636
637 impl ValidateTerms for PropertyDef {
638 fn validate_terms(
639 &self,
640 validator: &mut Validator<'_>,
641 top: &Module,
642 loader: &impl ModuleLoader,
643 ) {
644 self.member_def().validate_terms(validator, top, loader);
645 }
646 }
647
648 impl ValidateTerms for RdfDef {
649 fn validate_terms(
650 &self,
651 validator: &mut Validator<'_>,
652 top: &Module,
653 loader: &impl ModuleLoader,
654 ) {
655 self.name().validate_terms(validator, top, loader);
656 for annotation in self.body().annotations() {
657 annotation.validate_terms(validator, top, loader);
658 }
659 }
660 }
661
662 impl ValidateTerms for StructureDef {
663 fn validate_terms(
664 &self,
665 validator: &mut Validator<'_>,
666 top: &Module,
667 loader: &impl ModuleLoader,
668 ) {
669 self.name().validate_terms(validator, top, loader);
670 if let Some(body) = self.body() {
671 for annotation in body.annotations() {
672 annotation.validate_terms(validator, top, loader);
673 }
674 for member in body.members() {
675 member.validate_terms(validator, top, loader);
676 }
677 }
678 }
679 }
680
681 impl ValidateTerms for TypeClassDef {
682 fn validate_terms(
683 &self,
684 validator: &mut Validator<'_>,
685 top: &Module,
686 loader: &impl ModuleLoader,
687 ) {
688 self.name().validate_terms(validator, top, loader);
689 if let Some(body) = self.body() {
690 for annotation in body.annotations() {
691 annotation.validate_terms(validator, top, loader);
692 }
693 }
694 todo!("validate all")
695 }
696 }
697
698 impl ValidateTerms for UnionDef {
699 fn validate_terms(
700 &self,
701 validator: &mut Validator<'_>,
702 top: &Module,
703 loader: &impl ModuleLoader,
704 ) {
705 self.name().validate_terms(validator, top, loader);
706 if let Some(body) = self.body() {
707 for annotation in body.annotations() {
708 annotation.validate_terms(validator, top, loader);
709 }
710 for variant in body.variants() {
711 variant.validate_terms(validator, top, loader);
712 }
713 }
714 }
715 }
716
717 impl ValidateTerms for TypeVariant {
718 fn validate_terms(
719 &self,
720 validator: &mut Validator<'_>,
721 top: &Module,
722 loader: &impl ModuleLoader,
723 ) {
724 self.name_reference().validate_terms(validator, top, loader);
725 if let Some(rename) = self.rename() {
726 rename.validate_terms(validator, top, loader);
727 }
728 if let Some(body) = self.body() {
729 for annotation in body.annotations() {
730 annotation.validate_terms(validator, top, loader);
731 }
732 }
733 }
734 }
735
736 impl ValidateTerms for Member {
737 fn validate_terms(
738 &self,
739 validator: &mut Validator<'_>,
740 top: &Module,
741 loader: &impl ModuleLoader,
742 ) {
743 match self.kind() {
744 MemberKind::Reference(v) => v.validate_terms(validator, top, loader),
745 MemberKind::Definition(v) => v.validate_terms(validator, top, loader),
746 }
747 }
748 }
749
750 impl ValidateTerms for MemberDef {
751 fn validate_terms(
752 &self,
753 validator: &mut Validator<'_>,
754 top: &Module,
755 loader: &impl ModuleLoader,
756 ) {
757 self.name().validate_terms(validator, top, loader);
758 self.target_type().validate_terms(validator, top, loader);
759 if let Some(body) = self.body() {
760 body.validate_terms(validator, top, loader);
761 }
762 }
763 }
764
765 impl ValidateTerms for TypeReference {
766 fn validate_terms(
767 &self,
768 validator: &mut Validator<'_>,
769 top: &Module,
770 loader: &impl ModuleLoader,
771 ) {
772 match self {
773 Self::Unknown => {}
774 Self::Type(v) => v.validate_terms(validator, top, loader),
775 Self::MappingType(v) => {
776 v.domain().validate_terms(validator, top, loader);
777 v.range().validate_terms(validator, top, loader);
778 }
779 }
780 }
781 }
782}