Skip to main content

swls_lang_sparql/
lib.rs

1#[macro_use]
2extern crate tracing;
3
4use bevy_ecs::prelude::*;
5use swls_core::{lsp_types::SemanticTokenType, prelude::*};
6use swls_lang_rdf_base::register_rdf_lang;
7use swls_lang_turtle::lang::parser::TurtleParseError;
8
9pub mod ecs;
10use crate::ecs::{setup_completion, setup_parse};
11pub mod lang;
12
13pub fn setup_world(world: &mut World) {
14    // .rq (query) and .ru (update) are the W3C-registered extensions; .sparql is
15    // also widely used. .sq is kept for backwards compatibility.
16    register_rdf_lang::<Sparql, SparqlHelper>(
17        world,
18        &["sparql"],
19        &[".sq", ".rq", ".ru", ".sparql"],
20    );
21    setup_parse(world);
22    setup_completion(world);
23}
24
25#[derive(Debug, Component, Default)]
26pub struct Sparql;
27
28impl Lang for Sparql {
29    type ElementError = TurtleParseError;
30
31    const PATTERN: Option<&'static str> = None;
32    const LANG: &'static str = "sparql";
33    const CODE_ACTION: bool = false;
34    const HOVER: bool = true;
35    const TRIGGERS: &'static [&'static str] = &[];
36    const LEGEND_TYPES: &'static [SemanticTokenType] = &[
37        semantic_token::BOOLEAN,
38        semantic_token::LANG_TAG,
39        SemanticTokenType::COMMENT,
40        SemanticTokenType::ENUM_MEMBER,
41        SemanticTokenType::KEYWORD,
42        SemanticTokenType::NAMESPACE,
43        SemanticTokenType::NUMBER,
44        SemanticTokenType::PROPERTY,
45        SemanticTokenType::STRING,
46        SemanticTokenType::VARIABLE,
47    ];
48
49    fn semantic_token_type(kind: rowan::SyntaxKind) -> Option<SemanticTokenType> {
50        use rdf_parsers::sparql::parser::SyntaxKind as SK;
51        match SK::from(kind) {
52            SK::Var1 | SK::Var2 => Some(SemanticTokenType::VARIABLE),
53            SK::MyString
54            | SK::StringLiteral1
55            | SK::StringLiteral2
56            | SK::StringLiteralLong1
57            | SK::StringLiteralLong2 => Some(SemanticTokenType::STRING),
58            SK::Integer
59            | SK::Decimal
60            | SK::Double
61            | SK::IntegerPositive
62            | SK::IntegerNegative
63            | SK::DecimalPositive
64            | SK::DecimalNegative
65            | SK::DoublePositive
66            | SK::DoubleNegative => Some(SemanticTokenType::NUMBER),
67            SK::Comment => Some(SemanticTokenType::COMMENT),
68            SK::Langtag => Some(semantic_token::LANG_TAG),
69            SK::TrueLit | SK::FalseLit => Some(semantic_token::BOOLEAN),
70            SK::Iriref => Some(SemanticTokenType::PROPERTY),
71            SK::Alit
72            | SK::SparqlBaseToken
73            | SK::SparqlPrefixToken
74            | SK::AbsLit
75            | SK::AddLit
76            | SK::AllLit
77            | SK::AsLit
78            | SK::AscLit
79            | SK::AskLit
80            | SK::AvgLit
81            | SK::BindLit
82            | SK::BnodeLit
83            | SK::BoundLit
84            | SK::ByLit
85            | SK::CeilLit
86            | SK::ClearLit
87            | SK::CoalesceLit
88            | SK::ConcatLit
89            | SK::ConstructLit
90            | SK::ContainsLit
91            | SK::CopyLit
92            | SK::CountLit
93            | SK::CreateLit
94            | SK::DatatypeLit
95            | SK::DayLit
96            | SK::DefaultLit
97            | SK::DeleteLit
98            | SK::DeleteDataLit
99            | SK::DeleteWhereLit
100            | SK::DescLit
101            | SK::DescribeLit
102            | SK::DistinctLit
103            | SK::DropLit
104            | SK::EncodeForUriLit
105            | SK::ExistsLit
106            | SK::FilterLit
107            | SK::FloorLit
108            | SK::FromLit
109            | SK::GraphLit
110            | SK::GroupLit
111            | SK::GroupConcatLit
112            | SK::HavingLit
113            | SK::HoursLit
114            | SK::IfLit
115            | SK::InLit
116            | SK::InsertLit
117            | SK::InsertDataLit
118            | SK::IntoLit
119            | SK::IriLit
120            | SK::IsBlankLit
121            | SK::IsIriLit
122            | SK::IsLiteralLit
123            | SK::IsNumericLit
124            | SK::IsUriLit
125            | SK::LangLit
126            | SK::LangmatchesLit
127            | SK::LcaseLit
128            | SK::LimitLit
129            | SK::LoadLit
130            | SK::MaxLit
131            | SK::Md5Lit
132            | SK::MinLit
133            | SK::MinusLit
134            | SK::MinutesLit
135            | SK::MonthLit
136            | SK::MoveLit
137            | SK::NamedLit
138            | SK::NotLit
139            | SK::NowLit
140            | SK::OffsetLit
141            | SK::OptionalLit
142            | SK::OrderLit
143            | SK::RandLit
144            | SK::ReducedLit
145            | SK::RegexLit
146            | SK::ReplaceLit
147            | SK::RoundLit
148            | SK::SameTermLit
149            | SK::SampleLit
150            | SK::SecondsLit
151            | SK::SelectLit
152            | SK::SeparatorLit
153            | SK::ServiceLit
154            | SK::Sha1Lit
155            | SK::Sha256Lit
156            | SK::Sha384Lit
157            | SK::Sha512Lit
158            | SK::SilentLit
159            | SK::StrLit
160            | SK::StrafterLit
161            | SK::StrbeforeLit
162            | SK::StrdtLit
163            | SK::StrendsLit
164            | SK::StrlangLit
165            | SK::StrlenLit
166            | SK::StrstartsLit
167            | SK::StruuidLit
168            | SK::SubstrLit
169            | SK::SumLit
170            | SK::TimezoneLit
171            | SK::ToLit
172            | SK::TzLit
173            | SK::UcaseLit
174            | SK::UndefLit
175            | SK::UnionLit
176            | SK::UriLit
177            | SK::UsingLit
178            | SK::UuidLit
179            | SK::ValuesLit
180            | SK::WhereLit
181            | SK::WithLit
182            | SK::YearLit => Some(SemanticTokenType::KEYWORD),
183            _ => None,
184        }
185    }
186
187    fn semantic_token_spans(
188        kind: rowan::SyntaxKind,
189        span: std::ops::Range<usize>,
190        text: &str,
191    ) -> Vec<(SemanticTokenType, std::ops::Range<usize>)> {
192        use rdf_parsers::sparql::parser::SyntaxKind as SK;
193        match SK::from(kind) {
194            SK::PnameLn => {
195                let token_text = text.get(span.clone()).unwrap_or("");
196                if let Some((a, _)) = token_text.split_once(':') {
197                    let (start, end) = (span.start, span.end);
198                    vec![
199                        (SemanticTokenType::NAMESPACE, start..start + a.len() + 1),
200                        (SemanticTokenType::PROPERTY, start + a.len() + 1..end),
201                    ]
202                } else {
203                    vec![(SemanticTokenType::PROPERTY, span)]
204                }
205            }
206            SK::PnameNs => vec![(SemanticTokenType::NAMESPACE, span)],
207            SK::BlankNodeLabel => {
208                if span.len() > 2 {
209                    vec![
210                        (SemanticTokenType::NAMESPACE, span.start..span.start + 2),
211                        (SemanticTokenType::PROPERTY, span.start + 2..span.end),
212                    ]
213                } else {
214                    vec![(SemanticTokenType::NAMESPACE, span)]
215                }
216            }
217            _ => Self::semantic_token_type(kind)
218                .map(|t| vec![(t, span)])
219                .unwrap_or_default(),
220        }
221    }
222}
223
224/// All SPARQL keywords for completion.
225pub static SPARQL_KEYWORDS: &[&str] = &[
226    "REGEX",
227    "SUBSTR",
228    "REPLACE",
229    "EXISTS",
230    "SELECT",
231    "DISTINCT",
232    "REDUCED",
233    "OPTIONAL",
234    "UNION",
235    "AS",
236    "CONSTRUCT",
237    "WHERE",
238    "DESCRIBE",
239    "ASK",
240    "FROM",
241    "NAMED",
242    "GROUP",
243    "BY",
244    "HAVING",
245    "ORDER",
246    "ASC",
247    "DESC",
248    "LIMIT",
249    "OFFSET",
250    "VALUES",
251    "LOAD",
252    "SILENT",
253    "CLEAR",
254    "DROP",
255    "CREATE",
256    "ADD",
257    "MOVE",
258    "COPY",
259    "INSERT",
260    "DATA",
261    "DELETE",
262    "WITH",
263    "USING",
264    "DEFAULT",
265    "ALL",
266    "GRAPH",
267    "SERVICE",
268    "BIND",
269    "UNDEF",
270    "MINUS",
271    "FILTER",
272    // Aggregates
273    "COUNT",
274    "SUM",
275    "MIN",
276    "MAX",
277    "AVG",
278    "SAMPLE",
279    "GROUP_CONCAT",
280];
281
282#[derive(Debug, Default)]
283pub struct SparqlHelper;
284
285impl LangHelper for SparqlHelper {
286    fn keyword(&self) -> &[&'static str] {
287        SPARQL_KEYWORDS
288    }
289    fn supports_shape_validation(&self) -> bool {
290        false
291    }
292    fn model_based_rename(&self) -> bool {
293        true
294    }
295    fn blank_node_code_actions(&self) -> bool {
296        true
297    }
298    fn prefix_keyword(&self) -> &str {
299        "PREFIX"
300    }
301    fn format_prefix_declaration(
302        &self,
303        name: &str,
304        url: &str,
305        _format: swls_core::components::PrefixFormat,
306    ) -> String {
307        format!("PREFIX {}: <{}>\n", name, url)
308    }
309}