lang_jsonld/ecs/
mod.rs

1use bevy_ecs::{schedule::IntoSystemConfigs as _, world::World};
2use lsp_core::prelude::*;
3mod highlight;
4pub use highlight::*;
5
6mod parse;
7use parse::derive_triples;
8pub use parse::{parse_jsonld_system, parse_source};
9
10pub fn setup_parse(world: &mut World) {
11    use lsp_core::prelude::parse::*;
12    world.schedule_scope(ParseLabel, |_, schedule| {
13        schedule.add_systems((
14            parse_source,
15            parse_jsonld_system.after(parse_source),
16            derive_triples
17                .after(parse_jsonld_system)
18                .before(triples)
19                .before(prefixes),
20        ));
21    });
22}
23
24#[cfg(test)]
25mod tests {
26    use completion::CompletionRequest;
27    use futures::executor::block_on;
28    use lsp_core::{components::*, prelude::*, util::lsp_range_to_range, Tasks};
29    use ropey::Rope;
30    use test_utils::{create_file, setup_world, TestClient};
31    use tracing::info;
32
33    use crate::JsonLd;
34
35    #[test]
36    fn parse_works() {
37        let (mut world, _) = setup_world(TestClient::new(), crate::setup_world);
38
39        let t1 = r#"
40{
41    "@context" : { "foaf": "http://xmlns.com/foaf/0.1/" },
42    "@id": "http://example.com/ns#me",
43    "foaf:friend": "http://example.com/ns#you"
44}"#;
45        let entity = create_file(&mut world, t1, "http://example.com/ns#", "jsonld", Open);
46
47        let tokens = world.entity(entity).get::<Tokens>().expect("tokens exists");
48        let jsonld = world
49            .entity(entity)
50            .get::<Element<JsonLd>>()
51            .expect("jsonld exists");
52
53        assert_eq!(tokens.0.len(), 17);
54
55        let triples = world
56            .entity(entity)
57            .get::<Triples>()
58            .expect("triples exists");
59
60        assert_eq!(triples.0.len(), 1);
61    }
62
63    #[test_log::test]
64    fn current_triple_works() {
65        let (mut world, _) = setup_world(TestClient::new(), crate::setup_world);
66
67        let t1 = r#"{
68    "@context" : { "foaf": "http://xmlns.com/foaf/0.1/" },
69    "@id": "http://example.com/ns#me",
70    "foaf:friend": "http://example.com/ns#you"
71}"#;
72        let entity = create_file(&mut world, t1, "http://example.com/ns#", "jsonld", Open);
73
74        // start call completion
75        world.entity_mut(entity).insert((
76            CompletionRequest(vec![]),
77            PositionComponent(lsp_types::Position {
78                line: 3,
79                character: 6,
80            }),
81        ));
82        world.run_schedule(CompletionLabel);
83
84        let _ = world
85            .entity_mut(entity)
86            .take::<TokenComponent>()
87            .expect("token component");
88        let triple = world
89            .entity_mut(entity)
90            .take::<TripleComponent>()
91            .expect("triple component");
92
93        assert_eq!(triple.target, TripleTarget::Predicate);
94
95        world.entity_mut(entity).insert((
96            CompletionRequest(vec![]),
97            PositionComponent(lsp_types::Position {
98                line: 3,
99                character: 22,
100            }),
101        ));
102        world.run_schedule(CompletionLabel);
103
104        let _ = world
105            .entity_mut(entity)
106            .take::<TokenComponent>()
107            .expect("token component");
108        let triple = world
109            .entity_mut(entity)
110            .take::<TripleComponent>()
111            .expect("triple component");
112
113        assert_eq!(triple.target, TripleTarget::Object);
114    }
115
116    #[test_log::test]
117    fn current_triple_works_2() {
118        let (mut world, _) = setup_world(TestClient::new(), crate::setup_world);
119
120        let t1 = r#"{
121  "@context": {
122    "foaf": "http://xmlns.com/foaf/0.1/"
123  },
124  "@id": "meee",
125  "@type": "foaf:Document",
126  "foa:": "foaf:Document"
127}
128"#;
129        let entity = create_file(&mut world, t1, "http://example.com/ns#", "jsonld", Open);
130
131        // start call completion
132        world.entity_mut(entity).insert((
133            CompletionRequest(vec![]),
134            PositionComponent(lsp_types::Position {
135                line: 6,
136                character: 6,
137            }),
138        ));
139        world.run_schedule(CompletionLabel);
140
141        let _ = world
142            .entity_mut(entity)
143            .take::<TokenComponent>()
144            .expect("token component");
145        let triple = world
146            .entity_mut(entity)
147            .take::<TripleComponent>()
148            .expect("triple component");
149
150        assert_eq!(triple.target, TripleTarget::Predicate);
151    }
152
153    #[test_log::test]
154    fn current_triple_works_corrupt() {
155        let (mut world, _) = setup_world(TestClient::new(), crate::setup_world);
156        lang_turtle::setup_world(&mut world);
157
158        let t1 = r#"{
159    "@context" : { "foaf": "http://xmlns.com/foaf/0.1/" },
160    "@id": "http://example.com/ns#me"
161}"#;
162
163        let t2 = r#"{
164    "@context" : { "foaf": "http://xmlns.com/foaf/0.1/" },
165    "@id": "http://example.com/ns#me",
166    "foa"
167}"#;
168        let entity = create_file(&mut world, t1, "http://example.com/ns#", "jsonld", Open);
169
170        let c = world.resource::<TestClient>().clone();
171        block_on(c.await_futures(|| world.run_schedule(Tasks)));
172
173        world
174            .entity_mut(entity)
175            .insert((Source(t2.to_string()), RopeC(Rope::from_str(t2)), Open));
176        world.run_schedule(ParseLabel);
177
178        // start call completion
179        world.entity_mut(entity).insert((
180            CompletionRequest(vec![]),
181            PositionComponent(lsp_types::Position {
182                line: 3,
183                character: 6,
184            }),
185        ));
186        world.run_schedule(Tasks);
187        world.run_schedule(Tasks);
188        world.run_schedule(CompletionLabel);
189
190        let _ = world
191            .entity_mut(entity)
192            .take::<TokenComponent>()
193            .expect("token component");
194        let triple = world
195            .entity_mut(entity)
196            .take::<TripleComponent>()
197            .expect("triple component");
198
199        assert_eq!(triple.target, TripleTarget::Predicate);
200
201        let comppletions = world
202            .entity_mut(entity)
203            .take::<CompletionRequest>()
204            .expect("completion request")
205            .0;
206
207        let rope_c = world.entity(entity).get::<RopeC>().expect("rope component");
208
209        for comp in &comppletions {
210            let range = lsp_range_to_range(&comp.edits[0].range, &rope_c).expect("valid range");
211            let txt = rope_c.slice(range).to_string();
212            info!("comp {} {} -> {}", comp.label, txt, comp.edits[0].new_text);
213        }
214
215        assert_eq!(comppletions.len(), 63);
216    }
217
218    #[test_log::test]
219    fn current_triple_works_corrupt_bn() {
220        let (mut world, _) = setup_world(TestClient::new(), crate::setup_world);
221        lang_turtle::setup_world(&mut world);
222
223        let t1 = r#"{
224    "@context" : { "foaf": "http://xmlns.com/foaf/0.1/" }
225}"#;
226
227        let t2 = r#"{
228    "@context" : { "foaf": "http://xmlns.com/foaf/0.1/" },
229    "foa"
230}"#;
231        let entity = create_file(&mut world, t1, "http://example.com/ns#", "jsonld", Open);
232
233        let c = world.resource::<TestClient>().clone();
234        block_on(c.await_futures(|| world.run_schedule(Tasks)));
235
236        world
237            .entity_mut(entity)
238            .insert((Source(t2.to_string()), RopeC(Rope::from_str(t2)), Open));
239        world.run_schedule(ParseLabel);
240
241        // start call completion
242        world.entity_mut(entity).insert((
243            CompletionRequest(vec![]),
244            PositionComponent(lsp_types::Position {
245                line: 2,
246                character: 6,
247            }),
248        ));
249        world.run_schedule(Tasks);
250        world.run_schedule(Tasks);
251        world.run_schedule(CompletionLabel);
252
253        let _ = world
254            .entity_mut(entity)
255            .take::<TokenComponent>()
256            .expect("token component");
257
258        let triple = world
259            .entity_mut(entity)
260            .take::<TripleComponent>()
261            .expect("triple component");
262
263        assert_eq!(triple.target, TripleTarget::Predicate);
264
265        let comppletions = world
266            .entity_mut(entity)
267            .take::<CompletionRequest>()
268            .expect("completion request")
269            .0;
270
271        let rope_c = world.entity(entity).get::<RopeC>().expect("rope component");
272
273        for comp in &comppletions {
274            let range = lsp_range_to_range(&comp.edits[0].range, &rope_c).expect("valid range");
275            let txt = rope_c.slice(range).to_string();
276            info!("comp {} {} -> {}", comp.label, txt, comp.edits[0].new_text);
277        }
278
279        assert_eq!(comppletions.len(), 63);
280    }
281}