1#![allow(non_snake_case)]
2use std::{collections::HashSet, str::FromStr as _};
3
4use lang_turtle::lang::{
5 model::{Term, Triple, Turtle},
6 parse_source,
7 };
9
10fn check_turtle_defined_prefixes(turtle: Option<&Turtle>) -> bool {
11 let mut prefixes = HashSet::new();
13 if let Some(turtle) = turtle {
14 for pref in &turtle.prefixes {
15 prefixes.insert(pref.value().prefix.value().to_string());
16 }
17
18 turtle.triples.iter().all(|t| check_triple(&t, &prefixes))
19 } else {
20 true
21 }
22}
23
24pub fn test_syntax(location: &str, is_positive: bool) {
25 let url = lsp_types::Url::from_str(location).unwrap();
26 let path = url.to_file_path().expect("file path");
27 let turtle_source = std::fs::read_to_string(&path).expect("Failed to turtle");
28 let (turtle, errors) = parse_source(&url, &turtle_source);
29 let combinator = errors.is_empty() && turtle.is_some();
32 let defined_prefixes = check_turtle_defined_prefixes(turtle.as_ref());
35
36 if is_positive {
50 if !combinator || !defined_prefixes {
51 eprintln!(
52 "Failed to parse turtle\n{}\n\nErrors {:?}",
53 turtle_source, errors
54 );
55 assert!(false, "Parsing failed, and shouldn't have failed");
56 }
57 } else {
58 if errors.is_empty() && turtle.is_some() && defined_prefixes {
59 eprintln!(
60 "Failed to succeeded but shouldn't have: turtle\n{}",
61 turtle_source
62 );
63
64 assert!(false, "Parsing succeeded, and should have failed");
65 }
66 }
67}
68
69fn check_triple(triple: &Triple, defined: &HashSet<String>) -> bool {
70 if !check_term(&triple.subject, &defined) {
71 return false;
72 }
73
74 for po in &triple.po {
75 if !check_term(&po.predicate, defined) {
76 return false;
77 }
78
79 if !po.object.iter().all(|t| check_term(t, defined)) {
80 return false;
81 }
82 }
83
84 true
85}
86
87fn check_term(term: &Term, defined: &HashSet<String>) -> bool {
88 match term {
89 Term::BlankNode(lang_turtle::lang::model::BlankNode::Unnamed(pos, _, _)) => {
90 for po in pos {
91 if !check_term(&po.predicate, defined) {
92 return false;
93 }
94
95 if !po.object.iter().all(|t| check_term(t, defined)) {
96 return false;
97 }
98 }
99 true
100 }
101 Term::NamedNode(lang_turtle::lang::model::NamedNode::Prefixed { prefix, .. }) => {
102 defined.contains(prefix)
103 }
104 Term::Collection(spanneds) => spanneds.iter().all(|t| check_term(t, defined)),
105 _ => true,
106 }
107}
108
109include!(concat!(env!("OUT_DIR"), "/generated_tests.rs"));