Skip to main content

swls_core/feature/
references.rs

1use bevy_ecs::{
2    component::Component,
3    schedule::{IntoScheduleConfigs, Schedule, ScheduleLabel},
4    world::World,
5};
6
7use crate::lsp_types::Location;
8pub use crate::util::triple::get_current_triple;
9
10/// [`Component`] indicating that the current document is handling a References request.
11#[derive(Component, Debug, Default)]
12pub struct ReferencesRequest(pub Vec<Location>);
13
14/// [`ScheduleLabel`] related to the References schedule
15#[derive(ScheduleLabel, Clone, Eq, PartialEq, Debug, Hash)]
16pub struct Label;
17
18pub fn setup_schedule(world: &mut World) {
19    let mut references = Schedule::new(Label);
20    references.add_systems((
21        get_current_triple,
22        system::add_references.after(get_current_triple),
23    ));
24    world.add_schedule(references);
25}
26
27mod system {
28    use bevy_ecs::prelude::*;
29    use references::ReferencesRequest;
30    use sophia_api::{quad::Quad as _, term::TermKind};
31
32    use crate::{prelude::*, util::token_to_location};
33
34    pub fn add_references(
35        mut query: Query<(
36            &TripleComponent,
37            &Triples,
38            &Label,
39            &RopeC,
40            &mut ReferencesRequest,
41        )>,
42        project: Query<(&Triples, &RopeC, &Label)>,
43    ) {
44        for (triple, triples, label, rope, mut req) in &mut query {
45            let target = triple.kind();
46            let Some(term) = triple.term() else { continue };
47            tracing::debug!("Found term '{}' with kind {:?}", term.value, target);
48
49            if target == TermKind::Iri {
50                for (proj_triples, proj_rope, proj_label) in &project {
51                    req.0.extend(
52                        proj_triples
53                            .0
54                            .iter()
55                            .flat_map(|q| [q.s(), q.p(), q.o()])
56                            .filter(|t| t == &term)
57                            .flat_map(|t| token_to_location(&t.span, proj_label, proj_rope)),
58                    );
59                }
60            } else if target == TermKind::BlankNode || target == TermKind::Variable {
61                // Blank nodes and variables are document-local
62                req.0.extend(
63                    triples
64                        .0
65                        .iter()
66                        .flat_map(|q| [q.s(), q.p(), q.o()])
67                        .filter(|t| t == &term)
68                        .flat_map(|t| token_to_location(&t.span, label, rope)),
69                );
70            }
71        }
72    }
73}