1use std::{
2 borrow::Cow,
3 collections::{HashMap, HashSet},
4 fmt::Debug,
5 path::PathBuf,
6};
7
8use bevy_ecs::{prelude::*, world::CommandQueue};
9use derive_more::{AsMut, AsRef, Deref, DerefMut};
10use futures::channel::mpsc::{UnboundedReceiver, UnboundedSender};
11use serde::Deserialize;
12
13use crate::{
14 lang::{Lang, LangHelper},
15 lsp_types::{Position, Url, WorkspaceFolder},
16 prelude::*,
17 systems::TypeId,
18};
19
20#[derive(Component, Default, Debug, Clone, Eq, Hash, PartialEq, PartialOrd, Ord)]
21pub struct CurrentType(pub Vec<TypeId>);
22
23#[derive(Component, AsRef, Deref, AsMut, DerefMut, Debug)]
25pub struct Element<L: Lang>(pub Spanned<L::Element>);
26
27#[derive(Component, AsRef, Deref, AsMut, DerefMut, Debug)]
29pub struct Wrapped<E>(pub E);
30
31#[derive(Component, AsRef, Deref, AsMut, DerefMut, Debug)]
33pub struct Errors<E>(pub Vec<E>);
34
35#[derive(Component, AsRef, Deref, AsMut, DerefMut, Debug)]
37pub struct Source(pub String);
38
39#[derive(Component, AsRef, Deref, AsMut, DerefMut, Debug)]
41pub struct RopeC(pub ropey::Rope);
42
43#[derive(Component, Debug, AsRef, Deref)]
46pub struct DynLang(pub Box<dyn LangHelper + 'static + Send + Sync>);
47
48#[derive(Component, Debug)]
52pub struct Open;
53
54#[derive(Component, Debug)]
60pub struct Dirty;
61
62#[derive(Component, AsRef, Deref, AsMut, DerefMut, Debug)]
64pub struct Label(pub crate::lsp_types::Url);
65
66#[derive(Resource, AsRef, Deref, AsMut, DerefMut, Debug)]
68pub struct CommandReceiver(pub UnboundedReceiver<CommandQueue>);
69
70#[derive(Resource, AsRef, Deref, AsMut, DerefMut, Debug, Clone)]
72pub struct CommandSender(pub UnboundedSender<CommandQueue>);
73
74#[derive(Component, AsRef, Deref, AsMut, DerefMut, Debug, Clone)]
79pub struct DocumentLinks(pub Vec<(crate::lsp_types::Url, &'static str)>);
80
81#[derive(Component, AsRef, Deref, AsMut, DerefMut, Debug)]
87pub struct PositionComponent(pub Position);
88
89#[derive(Component, AsRef, Deref, AsMut, DerefMut, Debug)]
91pub struct KeyWords(pub Vec<&'static str>);
92
93#[derive(Component, AsRef, Deref, AsMut, DerefMut, Debug)]
95pub struct Types(pub HashMap<Cow<'static, str>, Vec<TypeId>>);
96
97#[derive(Resource, Debug, Default)]
115pub struct TypeHierarchy<'a> {
116 numbers: HashMap<Cow<'a, str>, TypeId>,
117 nodes: Vec<Cow<'a, str>>,
118 subclass: Vec<HashSet<TypeId>>,
119 superclass: Vec<HashSet<TypeId>>,
120}
121
122impl<'a> TypeHierarchy<'a> {
123 pub fn get_id(&mut self, class: &str) -> TypeId {
124 if let Some(id) = self.numbers.get(class) {
125 *id
126 } else {
127 let new_id = TypeId(self.nodes.len());
128 let class_cow: Cow<'a, str> = Cow::Owned(class.to_string());
129 self.nodes.push(class_cow.clone());
130 self.numbers.insert(class_cow, new_id);
131 self.subclass.push(HashSet::new());
132 self.superclass.push(HashSet::new());
133 new_id
134 }
135 }
136
137 pub fn get_id_ref(&self, class: &str) -> Option<TypeId> {
138 self.numbers.get(class).copied()
139 }
140
141 pub fn set_subclass_of(&mut self, class: TypeId, to: TypeId) {
142 self.subclass[class.0].insert(to);
143 self.superclass[to.0].insert(class);
144 }
145
146 pub fn iter_subclass<'b>(&'b self, id: TypeId) -> impl Iterator<Item = Cow<'a, str>> + 'b {
147 let mut stack = std::collections::VecDeque::new();
148 stack.push_back(id);
149 let mut done = HashSet::new();
150 std::iter::from_fn(move || {
151 while let Some(id) = stack.pop_front() {
152 if done.contains(&id) {
153 continue;
154 }
155 done.insert(id);
156
157 self.subclass[id.0].iter().for_each(|i| stack.push_back(*i));
158 return Some(self.nodes[id.0].clone());
159 }
160
161 None
162 })
163 }
164
165 pub fn type_name(&self, id: TypeId) -> Cow<'a, str> {
166 self.nodes[id.0].clone()
167 }
168
169 pub fn iter_superclass<'b>(&'b self, id: TypeId) -> impl Iterator<Item = Cow<'a, str>> + 'b {
170 let mut stack = std::collections::VecDeque::new();
171 stack.push_back(id);
172 let mut done = HashSet::new();
173 std::iter::from_fn(move || {
174 while let Some(id) = stack.pop_front() {
175 if done.contains(&id) {
176 continue;
177 }
178 done.insert(id);
179
180 self.superclass[id.0]
181 .iter()
182 .for_each(|i| stack.push_back(*i));
183 return Some(self.nodes[id.0].clone());
184 }
185
186 None
187 })
188 }
189}
190
191#[derive(Debug, Deserialize, PartialEq, Eq, PartialOrd, Ord, Hash)]
192pub enum Disabled {
193 #[serde(alias = "SHAPES", alias = "shapes")]
194 Shapes,
195}
196
197#[derive(Resource, Debug, Default)]
198pub struct ServerConfig {
199 pub workspaces: Vec<WorkspaceFolder>,
200 pub config: Config,
201}
202
203#[derive(Debug, Deserialize)]
204pub struct Config {
205 #[serde(default = "debug")]
207 pub log: String,
208 pub turtle: Option<bool>,
210 pub jsonld: Option<bool>,
212 pub sparql: Option<bool>,
214 #[serde(flatten)]
216 pub local: LocalConfig,
217}
218
219#[derive(Debug, Deserialize, Default)]
220#[serde(default)]
221pub struct LocalConfig {
222 pub ontologies: HashSet<String>,
224 pub shapes: HashSet<String>,
226 pub disabled: HashSet<Disabled>,
228}
229
230impl LocalConfig {
231 pub fn combine(&mut self, other: LocalConfig) {
233 self.ontologies.extend(other.ontologies);
234 self.shapes.extend(other.shapes);
235 self.disabled.extend(other.disabled);
236 }
237 #[cfg(target_arch = "wasm32")]
238 pub async fn global(_: &Fs) -> Option<Self> {
239 None
240 }
241 #[cfg(not(target_arch = "wasm32"))]
242 pub async fn global(fs: &Fs) -> Option<Self> {
243 let global_path = dirs::config_dir()
244 .unwrap_or_else(|| PathBuf::from("."))
245 .join("swls/config.json");
246 let url = crate::lsp_types::Url::from_file_path(global_path).ok()?;
247
248 tracing::debug!("Found global config url {}", url.as_str());
249 let content = fs.0.read_file(&url).await?;
250 tracing::debug!("Read global config content");
251
252 match serde_json::from_str(&content) {
253 Ok(x) => Some(x),
254 Err(e) => {
255 tracing::error!("Deserialize failed\n{:?}", e);
256 None
257 }
258 }
259 }
260
261 pub async fn local(fs: &Fs, url: &Url) -> Option<Self> {
262 let url = Url::parse(&format!("{}/.swls/config.json", url.as_str())).ok()?;
263 tracing::debug!("Found local config url {}", url.as_str());
264 let content = fs.0.read_file(&url).await?;
265 tracing::debug!("Read local config content");
266 match serde_json::from_str(&content) {
267 Ok(x) => Some(x),
268 Err(e) => {
269 tracing::error!("Deserialize failed\n{:?}", e);
270 None
271 }
272 }
273 }
274}
275
276impl Default for Config {
277 fn default() -> Self {
278 Self {
279 log: "debug".to_string(),
280 turtle: None,
281 jsonld: None,
282 sparql: None,
283 local: LocalConfig::default(),
284 }
285 }
286}
287
288fn debug() -> String {
289 String::from("debug")
290}