Skip to main content

swls_core/systems/properties/
systems.rs

1use std::{borrow::Cow, collections::HashSet};
2
3use bevy_ecs::prelude::*;
4use completion::{CompletionRequest, SimpleCompletion};
5use hover::HoverRequest;
6use tracing::{instrument, trace};
7
8use crate::{
9    lsp_types::{CompletionItemKind, TextEdit},
10    prelude::*,
11};
12
13#[instrument(skip(query, resource))]
14pub fn complete_class(
15    mut query: Query<(
16        &TokenComponent,
17        &TripleComponent,
18        &Prefixes,
19        &Types,
20        &mut CompletionRequest,
21    )>,
22    hierarchy: Res<TypeHierarchy<'static>>,
23    resource: Res<Ontologies>,
24) {
25    for (token, triple, prefixes, types, mut request) in &mut query {
26        if triple.triple.predicate.value == "http://www.w3.org/1999/02/22-rdf-syntax-ns#type"
27            && triple.target == TripleTarget::Object
28        {
29            let tts = types.get(&triple.triple.subject.value);
30
31            let superclasses: HashSet<_> = tts
32                .iter()
33                .flat_map(|x| x.iter())
34                .flat_map(|t| hierarchy.iter_superclass(*t))
35                .collect();
36
37            for class in resource.classes.values() {
38                let to_beat = prefixes
39                    .shorten(&class.term.value)
40                    .map(|x| Cow::Owned(x))
41                    .unwrap_or(class.term.value.clone());
42
43                if to_beat.starts_with(&token.text) {
44                    let mut completion = SimpleCompletion::new(
45                        CompletionItemKind::CLASS,
46                        format!("{}", to_beat),
47                        TextEdit {
48                            range: token.range.clone(),
49                            new_text: to_beat.to_string(),
50                        },
51                    )
52                    .label_description(class.full_title())
53                    .documentation(class.full_docs(&hierarchy, &prefixes));
54
55                    if superclasses.contains(class.term.as_str()) {
56                        completion.kind = CompletionItemKind::INTERFACE;
57                        request.push(completion.sort_text(format!("0{}", to_beat)));
58                    } else {
59                        request.push(completion.sort_text(format!("1{}", to_beat)));
60                    }
61                }
62            }
63        }
64    }
65}
66
67pub fn hover_class(
68    mut query: Query<(&TokenComponent, &Prefixes, &mut HoverRequest)>,
69    hierarchy: Res<TypeHierarchy<'static>>,
70    resource: Res<Ontologies>,
71) {
72    for (token, prefixes, mut request) in &mut query {
73        if let Some(target) = prefixes.expand(token.token.value()) {
74            for class in resource.classes.values() {
75                if class.term.value == target {
76                    request.0.push(format!(
77                        "## {}\n\n{}",
78                        class.full_title(),
79                        class.full_docs(&hierarchy, &prefixes)
80                    ));
81                }
82            }
83        }
84    }
85}
86
87#[instrument(skip(query, hierarchy, resource, config))]
88pub fn complete_properties(
89    mut query: Query<(
90        &TokenComponent,
91        &TripleComponent,
92        &Prefixes,
93        &Label,
94        &Types,
95        &mut CompletionRequest,
96    )>,
97    hierarchy: Res<TypeHierarchy<'static>>,
98    resource: Res<Ontologies>,
99    config: Res<ServerConfig>,
100) {
101    for (token, triple, prefixes, _this_label, types, mut request) in &mut query {
102        if triple.target == TripleTarget::Predicate {
103            let tts = types.get(&triple.triple.subject.value);
104
105            if let Some(tts) = tts.as_ref() {
106                trace!("Types for {}", triple.triple.subject.value);
107                for t in *tts {
108                    trace!(
109                        "{} {}",
110                        triple.triple.subject.value,
111                        hierarchy.type_name(*t)
112                    );
113                }
114            } else {
115                trace!("No types for {}", triple.triple.subject.value);
116            }
117
118            let subclasses: HashSet<_> = tts
119                .iter()
120                .flat_map(|x| x.iter())
121                .flat_map(|t| hierarchy.iter_subclass(*t))
122                .collect();
123
124            for property in resource.properties.values() {
125                let correct_domain = property
126                    .domains
127                    .iter()
128                    .any(|domain| subclasses.contains(domain.as_str()));
129
130                if !subclasses.is_empty()
131                    && config
132                        .config
133                        .local
134                        .completion
135                        .correct_domain_required(&property.term.value)
136                    && !correct_domain
137                {
138                    continue;
139                }
140
141                let to_beat = prefixes
142                    .shorten(&property.term.value)
143                    .map(|x| Cow::Owned(x))
144                    .unwrap_or(property.term.value.clone());
145
146                if to_beat.starts_with(&token.text) {
147                    let mut completion = SimpleCompletion::new(
148                        CompletionItemKind::ENUM_MEMBER,
149                        format!("{}", to_beat),
150                        TextEdit {
151                            range: token.range.clone(),
152                            new_text: to_beat.to_string(),
153                        },
154                    )
155                    .label_description(&property.full_title())
156                    .documentation(&property.full_docs(&prefixes));
157
158                    if correct_domain {
159                        completion.kind = CompletionItemKind::FIELD;
160                        request.push(completion.sort_text(format!("0{}", to_beat)));
161                    } else {
162                        request.push(completion.sort_text(format!("1{}", to_beat)));
163                    }
164                }
165            }
166        }
167    }
168}
169
170#[instrument(skip(query, resource))]
171pub fn hover_property(
172    mut query: Query<(
173        &TokenComponent,
174        &Prefixes,
175        &DocumentLinks,
176        &mut HoverRequest,
177    )>,
178    resource: Res<Ontologies>,
179) {
180    for (token, prefixes, _links, mut request) in &mut query {
181        if let Some(target) = prefixes.expand(token.token.value()) {
182            for c in resource
183                .properties
184                .values()
185                .filter(|c| c.term.value == target)
186            {
187                request
188                    .0
189                    .push(format!("## {}\n\n{}", c.full_title(), c.full_docs(&prefixes)));
190            }
191        }
192    }
193}