swls_core/feature/
inlay.rs1use std::{borrow::Cow, collections::HashSet};
2
3use bevy_ecs::{
4 component::Component,
5 schedule::ScheduleLabel,
6 system::{Query, Res},
7 world::World,
8};
9use derive_more::{AsMut, AsRef, Deref, DerefMut};
10use sophia_api::{ns::rdf, prelude::Dataset};
11
12use crate::prelude::{DynLang, Prefixes, RopeC, Triples, TypeHierarchy, Types};
13
14#[derive(Component, AsRef, Deref, AsMut, DerefMut, Debug, Default)]
16pub struct InlayRequest(pub Vec<crate::lsp_types::InlayHint>);
17
18#[derive(ScheduleLabel, Clone, Eq, PartialEq, Debug, Hash)]
20pub struct Label;
21pub fn setup_schedule(world: &mut World) {
22 let mut inlay = bevy_ecs::schedule::Schedule::new(Label);
23 inlay.add_systems(inlay_types);
24 world.add_schedule(inlay);
25}
26
27#[tracing::instrument(skip(query, hierarchy))]
28fn inlay_types(
29 query: Query<(
30 &Triples,
31 &Types,
32 &RopeC,
33 &Prefixes,
34 &DynLang,
35 &mut InlayRequest,
36 )>,
37 hierarchy: Res<TypeHierarchy>,
38) {
39 for (triples, types, rope, prefixes, lang, mut request) in query {
40 let subjects: HashSet<_> = triples.subjects().flatten().collect();
41
42 let t = &mut request.0;
43
44 for s in subjects {
45 if let Some(types) = types.get(s.as_str()) {
46 let defined: HashSet<_> = triples.objects([s], [rdf::type_]).collect();
47 let defined_strings: HashSet<String> =
48 defined.iter().map(|x| x.value.to_string()).collect();
49
50 let types: Vec<_> = types
51 .iter()
52 .map(|e| hierarchy.type_name(*e))
53 .filter(|t| !defined_strings.contains(t.as_ref()))
54 .map(|t| prefixes.shorten(t.as_ref()).map(Cow::Owned).unwrap_or(t))
55 .collect();
56
57 if types.is_empty() {
58 continue;
59 }
60
61 if let Some(hint) = lang.inlay_types_hint(
62 &s.span,
63 rope,
64 defined.iter().max_by_key(|x| x.span.end).map(|x| &x.span),
65 types,
66 ) {
67 t.push(hint);
68 }
69 }
70 }
71 }
72}