swls_core/feature/
goto_definition.rs1use bevy_ecs::{
2 component::Component,
3 schedule::{IntoScheduleConfigs, Schedule, ScheduleLabel},
4 world::World,
5};
6
7use crate::prelude::get_current_cst_token;
8pub use crate::systems::{get_current_prefix, goto_prefix};
9pub use crate::util::triple::get_current_triple;
10
11#[derive(Component, Debug, Default)]
13pub struct GotoDefinitionRequest(pub Vec<crate::lsp_types::Location>);
14
15#[derive(ScheduleLabel, Clone, Eq, PartialEq, Debug, Hash)]
17pub struct Label;
18
19pub fn setup_schedule(world: &mut World) {
20 let mut references = Schedule::new(Label);
21 references.add_systems((
22 get_current_cst_token.before(get_current_triple),
23 get_current_triple,
24 get_current_prefix.after(get_current_triple),
28 goto_prefix.after(get_current_prefix),
29 system::goto_definition.after(get_current_prefix),
30 ));
31 world.add_schedule(references);
32}
33
34mod system {
35 use std::collections::HashSet;
36
37 use bevy_ecs::prelude::*;
38 use goto_definition::GotoDefinitionRequest;
39 use sophia_api::{quad::Quad as _, term::TermKind};
40
41 use crate::{prelude::*, util::token_to_location};
42
43 pub fn goto_definition(
44 mut query: Query<(
45 &TripleComponent,
46 &Triples,
47 &Label,
48 &RopeC,
49 &PositionComponent,
50 &mut GotoDefinitionRequest,
51 )>,
52 project: Query<(&Triples, &RopeC, &Label)>,
53 ) {
54 for (triple, triples, label, rope, pos, mut req) in &mut query {
55 let target = triple.kind();
56 let Some(term) = triple.term() else {
57 continue;
58 };
59 let _span = tracing::debug_span!("goto_definition", term = %term.value).entered();
60 let Some(idx) = position_to_offset(pos.0, rope) else {
61 continue;
62 };
63 if !term.span.contains(&idx) {
64 continue;
65 }
66
67 tracing::debug!("kind {:?}", target);
68 if target == TermKind::Iri {
69 for (triples, rope, label) in &project {
70 tracing::debug!("Looking into buffer {}", label.as_str());
71 let subs: HashSet<_> = triples
72 .iter()
73 .map(|x| x.s())
74 .filter(|x| &x.value == &term.value)
75 .collect();
76
77 req.0.extend(
78 subs.into_iter()
79 .flat_map(|t| token_to_location(&t.span, label, &rope)),
80 );
81 }
82 } else if target == TermKind::BlankNode {
83 let subs: HashSet<_> = triples
84 .iter()
85 .map(|x| x.s())
86 .filter(|x| &x.value == &term.value)
87 .collect();
88 req.0.extend(
89 subs.into_iter()
90 .flat_map(|t| token_to_location(&t.span, label, &rope)),
91 );
92 }
93 }
94 }
95}