1use crate::types::{CodeAction, CompletionItem, Diagnostic, DocumentHighlight, FoldingRange, Hover, InitializeParams, InlayHint, LocationRange, SelectionRange, 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 {
13 type Lang: Language;
14 type Vfs: WritableVfs;
15
16 fn vfs(&self) -> &Self::Vfs;
18
19 fn workspace(&self) -> &crate::workspace::WorkspaceManager;
21
22 fn get_source(&self, uri: &str) -> Option<<Self::Vfs as Vfs>::Source> {
24 self.vfs().get_source(uri)
25 }
26
27 fn get_root(&self, _uri: &str) -> impl Future<Output = Option<RedNode<'_, Self::Lang>>> + Send + '_ {
30 async { None }
31 }
32
33 fn with_root<'a, R, F>(&'a self, uri: &'a str, f: F) -> impl Future<Output = Option<R>> + Send + 'a
35 where
36 R: Send,
37 F: FnOnce(RedNode<'a, Self::Lang>) -> R + Send + 'a,
38 {
39 async move {
40 let root = self.get_root(uri).await?;
41 Some(f(root))
42 }
43 }
44
45 fn with_roots<'a, R, F>(&'a self, uris: Vec<String>, f: F) -> impl Future<Output = Vec<R>> + Send + 'a
47 where
48 R: Send + 'static,
49 F: Fn(RedNode<'a, Self::Lang>) -> R + Send + Sync + 'a,
50 {
51 let mut futures = Vec::new();
52 let f = std::sync::Arc::new(f);
53
54 for uri in uris {
55 let f = f.clone();
56 futures.push(async move { if let Some(root) = self.get_root(&uri).await { Some(f(root)) } else { None } });
57 }
58
59 async move { futures::future::join_all(futures).await.into_iter().flatten().collect() }
60 }
61
62 fn hover(&self, _uri: &str, _range: Range<usize>) -> impl Future<Output = Option<Hover>> + Send + '_ {
64 async { None }
65 }
66
67 fn folding_ranges(&self, _uri: &str) -> impl Future<Output = Vec<FoldingRange>> + Send + '_ {
69 async { vec![] }
70 }
71
72 fn document_symbols<'a>(&'a self, uri: &'a str) -> impl Future<Output = Vec<StructureItem>> + Send + 'a {
74 let uri = uri.to_string();
75 async move {
76 let _source = match self.get_source(&uri) {
77 Some(s) => s,
78 None => return vec![],
79 };
80 let _root = match self.get_root(&uri).await {
81 Some(r) => r,
82 None => return vec![],
83 };
84 let symbols = self.workspace().symbols.query_file(&uri);
85 if !symbols.is_empty() {
86 return symbols.into_iter().map(StructureItem::from).collect();
87 }
88 vec![]
89 }
90 }
91
92 fn workspace_symbols<'a>(&'a self, query: String) -> impl Future<Output = Vec<WorkspaceSymbol>> + Send + 'a {
94 async move { self.workspace().symbols.query(&query).into_iter().map(|s| WorkspaceSymbol::from(s)).collect() }
95 }
96
97 fn list_all_files(&self, root_uri: &str) -> impl Future<Output = Vec<String>> + Send + '_ {
99 let root_uri = root_uri.to_string();
100 async move {
101 let mut files = Vec::new();
102 let mut stack = vec![root_uri];
103
104 while let Some(uri) = stack.pop() {
105 if self.vfs().is_file(&uri) {
106 files.push(uri);
107 }
108 else if self.vfs().is_dir(&uri) {
109 if let Some(entries) = self.vfs().read_dir(&uri) {
110 for entry in entries {
111 stack.push(entry.to_string());
112 }
113 }
114 }
115 }
116 files
117 }
118 }
119
120 fn definition<'a>(&'a self, uri: &'a str, range: Range<usize>) -> impl Future<Output = Vec<LocationRange>> + Send + 'a {
122 let uri = uri.to_string();
123 async move {
124 let root = match self.get_root(&uri).await {
125 Some(r) => r,
126 None => return vec![],
127 };
128 let source = match self.get_source(&uri) {
129 Some(s) => s,
130 None => return vec![],
131 };
132
133 use oak_core::tree::RedTree;
135 let node = match root.child_at_offset(range.start) {
136 Some(RedTree::Node(n)) => n,
137 Some(RedTree::Leaf(l)) => return vec![LocationRange { uri: uri.clone().into(), range: l.span }],
138 None => root,
139 };
140
141 let role = node.green.kind.role();
143 if role.universal() == oak_core::language::UniversalElementRole::Reference {
144 let name = &source.get_text_in(node.span());
145
146 if let Some(sym) = self.workspace().symbols.lookup(name) {
150 return vec![LocationRange { uri: sym.uri, range: sym.range }];
151 }
152
153 if let Some(resolved_uri) = self.workspace().resolver.resolve(&uri, name) {
155 return vec![LocationRange { uri: resolved_uri.into(), range: (0..0).into() }];
156 }
157 }
158
159 vec![]
160 }
161 }
162
163 fn references<'a>(&'a self, _uri: &'a str, _range: Range<usize>) -> impl Future<Output = Vec<LocationRange>> + Send + 'a {
165 async { vec![] }
166 }
167
168 fn type_definition<'a>(&'a self, _uri: &'a str, _range: Range<usize>) -> impl Future<Output = Vec<LocationRange>> + Send + 'a {
170 async { vec![] }
171 }
172
173 fn implementation<'a>(&'a self, _uri: &'a str, _range: Range<usize>) -> impl Future<Output = Vec<LocationRange>> + Send + 'a {
175 async { vec![] }
176 }
177
178 fn document_highlights<'a>(&'a self, _uri: &'a str, _range: Range<usize>) -> impl Future<Output = Vec<DocumentHighlight>> + Send + 'a {
180 async { vec![] }
181 }
182
183 fn rename<'a>(&'a self, _uri: &'a str, _range: Range<usize>, _new_name: String) -> impl Future<Output = Option<WorkspaceEdit>> + Send + 'a {
185 async { None }
186 }
187
188 fn completion<'a>(&'a self, _uri: &'a str, _position: usize) -> impl Future<Output = Vec<CompletionItem>> + Send + 'a {
190 async { vec![] }
191 }
192
193 fn diagnostics<'a>(&'a self, _uri: &'a str) -> impl Future<Output = Vec<Diagnostic>> + Send + 'a {
195 async { vec![] }
196 }
197
198 fn semantic_tokens<'a>(&'a self, _uri: &'a str) -> impl Future<Output = Option<SemanticTokens>> + Send + 'a {
200 async { None }
201 }
202
203 fn semantic_tokens_range<'a>(&'a self, _uri: &'a str, _range: Range<usize>) -> impl Future<Output = Option<SemanticTokens>> + Send + 'a {
205 async { None }
206 }
207
208 fn selection_ranges<'a>(&'a self, _uri: &'a str, _ranges: Vec<usize>) -> impl Future<Output = Vec<SelectionRange>> + Send + 'a {
210 async { vec![] }
211 }
212
213 fn signature_help<'a>(&'a self, _uri: &'a str, _position: usize) -> impl Future<Output = Option<SignatureHelp>> + Send + 'a {
215 async { None }
216 }
217
218 fn inlay_hints<'a>(&'a self, _uri: &'a str) -> impl Future<Output = Vec<InlayHint>> + Send + 'a {
220 async { vec![] }
221 }
222
223 fn formatting<'a>(&'a self, _uri: &'a str) -> impl Future<Output = Vec<TextEdit>> + Send + 'a {
225 async { vec![] }
226 }
227
228 fn code_actions<'a>(&'a self, _uri: &'a str, _range: Range<usize>) -> impl Future<Output = Vec<CodeAction>> + Send + 'a {
230 async { vec![] }
231 }
232
233 fn initialize<'a>(&'a self, _params: InitializeParams) -> impl Future<Output = ()> + Send + 'a {
235 async {}
236 }
237
238 fn initialized<'a>(&'a self) -> impl Future<Output = ()> + Send + 'a {
240 async {}
241 }
242
243 fn shutdown<'a>(&'a self) -> impl Future<Output = ()> + Send + 'a {
245 async {}
246 }
247
248 fn did_save<'a>(&'a self, _uri: &'a str) -> impl Future<Output = ()> + Send + 'a {
250 async {}
251 }
252
253 fn did_close<'a>(&'a self, _uri: &'a str) -> impl Future<Output = ()> + Send + 'a {
255 async {}
256 }
257}