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