1use crate::types::{CodeAction, CompletionItem, Diagnostic, DocumentHighlight, FoldingRange, Hover, InitializeParams, InlayHint, LocationRange, SemanticTokens, SignatureHelp, StructureItem, TextEdit, WorkspaceEdit, WorkspaceSymbol};
2use core::range::Range;
3use oak_core::{
4 language::{ElementRole, ElementType, Language},
5 source::Source,
6 tree::RedNode,
7};
8use oak_resolver::ModuleResolver;
9use oak_vfs::{Vfs, WritableVfs};
10use std::future::Future;
11
12pub trait LanguageService: Send + Sync {
23 type Lang: Language;
25 type Vfs: WritableVfs;
27
28 fn vfs(&self) -> &Self::Vfs;
30
31 fn workspace(&self) -> &crate::workspace::WorkspaceManager;
33
34 fn get_source(&self, uri: &str) -> Option<<Self::Vfs as Vfs>::Source> {
36 self.vfs().get_source(uri)
37 }
38
39 fn get_root(&self, _uri: &str) -> impl Future<Output = Option<RedNode<'_, Self::Lang>>> + Send + '_ {
45 async { None }
46 }
47
48 fn with_root<'a, R, F>(&'a self, uri: &'a str, f: F) -> impl Future<Output = Option<R>> + Send + 'a
52 where
53 R: Send,
54 F: FnOnce(RedNode<'a, Self::Lang>) -> R + Send + 'a,
55 {
56 async move {
57 let root = self.get_root(uri).await?;
58 Some(f(root))
59 }
60 }
61
62 fn with_roots<'a, R, F>(&'a self, uris: Vec<String>, f: F) -> impl Future<Output = Vec<R>> + Send + 'a
66 where
67 R: Send + 'static,
68 F: Fn(RedNode<'a, Self::Lang>) -> R + Send + Sync + 'a,
69 {
70 let mut futures = Vec::new();
71 let f = std::sync::Arc::new(f);
72
73 for uri in uris {
74 let f = f.clone();
75 futures.push(async move { if let Some(root) = self.get_root(&uri).await { Some(f(root)) } else { None } })
76 }
77
78 async move { futures::future::join_all(futures).await.into_iter().flatten().collect() }
79 }
80
81 fn hover(&self, _uri: &str, _range: Range<usize>) -> impl Future<Output = Option<Hover>> + Send + '_ {
87 async { None }
88 }
89
90 fn folding_ranges(&self, _uri: &str) -> impl Future<Output = Vec<FoldingRange>> + Send + '_ {
92 async { vec![] }
93 }
94
95 fn document_symbols<'a>(&'a self, uri: &'a str) -> impl Future<Output = Vec<StructureItem>> + Send + 'a {
101 let uri = uri.to_string();
102 async move {
103 let _source = match self.get_source(&uri) {
104 Some(s) => s,
105 None => return vec![],
106 };
107 let _root = match self.get_root(&uri).await {
108 Some(r) => r,
109 None => return vec![],
110 };
111 let symbols = self.workspace().symbols.query_file(&uri);
112 if !symbols.is_empty() {
113 return symbols.into_iter().map(StructureItem::from).collect();
114 }
115 vec![]
116 }
117 }
118
119 fn workspace_symbols<'a>(&'a self, query: String) -> impl Future<Output = Vec<WorkspaceSymbol>> + Send + 'a {
124 async move { self.workspace().symbols.query(&query).into_iter().map(|s| WorkspaceSymbol::from(s)).collect() }
125 }
126
127 fn list_all_files(&self, root_uri: &str) -> impl Future<Output = Vec<String>> + Send + '_ {
131 let root_uri: oak_core::Arc<str> = root_uri.into();
132 async move {
133 let mut files = Vec::new();
134 let mut stack = vec![root_uri];
135
136 while let Some(uri) = stack.pop() {
137 if self.vfs().is_file(&uri) {
138 files.push(uri.to_string());
139 }
140 else if self.vfs().is_dir(&uri) {
141 if let Some(entries) = self.vfs().read_dir(&uri) {
142 stack.extend(entries);
143 }
144 }
145 }
146 files
147 }
148 }
149
150 fn definition<'a>(&'a self, uri: &'a str, range: Range<usize>) -> impl Future<Output = Vec<LocationRange>> + Send + 'a {
158 let uri = uri.to_string();
159 async move {
160 let root = match self.get_root(&uri).await {
161 Some(r) => r,
162 None => return vec![],
163 };
164 let source = match self.get_source(&uri) {
165 Some(s) => s,
166 None => return vec![],
167 };
168
169 use oak_core::tree::RedTree;
171 let node = match root.child_at_offset(range.start) {
172 Some(RedTree::Node(n)) => n,
173 Some(RedTree::Leaf(l)) => return vec![LocationRange { uri: uri.clone().into(), range: l.span }],
174 None => root,
175 };
176
177 let role = node.green.kind.role();
179 if role.universal() == oak_core::language::UniversalElementRole::Reference {
180 let name = &source.get_text_in(node.span());
181
182 if let Some(sym) = self.workspace().symbols.lookup(name) {
186 return vec![LocationRange { uri: sym.uri, range: sym.range }];
187 }
188
189 if let Some(resolved_uri) = self.workspace().resolver.resolve(&uri, name) {
191 return vec![LocationRange { uri: resolved_uri.into(), range: (0..0).into() }];
192 }
193
194 }
196
197 vec![]
198 }
199 }
200
201 fn document_highlight<'a>(&'a self, _uri: &'a str, _range: Range<usize>) -> impl Future<Output = Vec<DocumentHighlight>> + Send + 'a {
203 async { vec![] }
204 }
205
206 fn code_action<'a>(&'a self, _uri: &'a str, _range: Range<usize>) -> impl Future<Output = Vec<CodeAction>> + Send + 'a {
208 async { vec![] }
209 }
210
211 fn formatting<'a>(&'a self, _uri: &'a str) -> impl Future<Output = Vec<TextEdit>> + Send + 'a {
213 async { vec![] }
214 }
215
216 fn range_formatting<'a>(&'a self, _uri: &'a str, _range: Range<usize>) -> impl Future<Output = Vec<TextEdit>> + Send + 'a {
218 async { vec![] }
219 }
220
221 fn rename<'a>(&'a self, _uri: &'a str, _range: Range<usize>, _new_name: String) -> impl Future<Output = Option<WorkspaceEdit>> + Send + 'a {
223 async { None }
224 }
225
226 fn semantic_tokens<'a>(&'a self, _uri: &'a str) -> impl Future<Output = Option<SemanticTokens>> + Send + 'a {
228 async { None }
229 }
230
231 fn completion<'a>(&'a self, _uri: &'a str, _offset: usize) -> impl Future<Output = Vec<CompletionItem>> + Send + 'a {
236 async { vec![] }
237 }
238
239 fn signature_help<'a>(&'a self, _uri: &'a str, _range: Range<usize>) -> impl Future<Output = Option<SignatureHelp>> + Send + 'a {
244 async { None }
245 }
246
247 fn inlay_hint<'a>(&'a self, _uri: &'a str, _range: Range<usize>) -> impl Future<Output = Vec<InlayHint>> + Send + 'a {
252 async { vec![] }
253 }
254
255 fn references<'a>(&'a self, _uri: &'a str, _range: Range<usize>) -> impl Future<Output = Vec<LocationRange>> + Send + 'a {
257 async { vec![] }
258 }
259
260 fn type_definition<'a>(&'a self, _uri: &'a str, _range: Range<usize>) -> impl Future<Output = Vec<LocationRange>> + Send + 'a {
262 async { vec![] }
263 }
264
265 fn implementation<'a>(&'a self, _uri: &'a str, _range: Range<usize>) -> impl Future<Output = Vec<LocationRange>> + Send + 'a {
267 async { vec![] }
268 }
269
270 fn initialize<'a>(&'a self, _params: InitializeParams) -> impl Future<Output = ()> + Send + 'a {
272 async {}
273 }
274
275 fn initialized<'a>(&'a self) -> impl Future<Output = ()> + Send + 'a {
277 async {}
278 }
279
280 fn shutdown<'a>(&'a self) -> impl Future<Output = ()> + Send + 'a {
282 async {}
283 }
284
285 fn did_save<'a>(&'a self, _uri: &'a str) -> impl Future<Output = ()> + Send + 'a {
287 async {}
288 }
289
290 fn did_close<'a>(&'a self, _uri: &'a str) -> impl Future<Output = ()> + Send + 'a {
292 async {}
293 }
294
295 fn diagnostics<'a>(&'a self, _uri: &'a str) -> impl Future<Output = Vec<Diagnostic>> + Send + 'a {
297 async { vec![] }
298 }
299}