1use std::sync::Arc;
4
5use increparse::Engine;
6use lsp_types::{CompletionResponse, Diagnostic, DocumentSymbol, Hover, Location, SymbolKind};
7
8use crate::document::Document;
9use crate::encoding::PositionEncoding;
10use crate::server::Language;
11use crate::FailedNode;
12
13pub type DiagnosticFn<C> =
15 dyn Fn(&Document<C>, &FailedNode<'_, C>) -> Option<Diagnostic> + Send + Sync;
16
17pub type ExtraDiagnosticsFn<C> = dyn Fn(&Document<C>) -> Vec<Diagnostic> + Send + Sync;
19
20pub type SymbolsFn<C> = dyn Fn(&Document<C>) -> Vec<DocumentSymbol> + Send + Sync;
22
23pub type LabelFn<C> = dyn Fn(&C) -> Option<NodeLabel> + Send + Sync;
25
26pub struct SimpleLanguage<C> {
50 engine: Engine<C>,
51 root_ctx: C,
52 encoding: PositionEncoding,
53 diagnostic_fn: Option<Arc<DiagnosticFn<C>>>,
54 extra_diagnostics_fn: Option<Arc<ExtraDiagnosticsFn<C>>>,
55 symbols_fn: Option<Arc<SymbolsFn<C>>>,
56 label_fn: Option<Arc<LabelFn<C>>>,
57 describe_fn: Option<Arc<DescribeFn<C>>>,
58 hover_fn: Option<Arc<HoverFn<C>>>,
59 definition_fn: Option<Arc<DefinitionFn<C>>>,
60 completion_fn: Option<Arc<CompletionFn<C>>>,
61 code_action_fn: Option<Arc<CodeActionFn<C>>>,
62}
63
64pub type DescribeFn<C> = dyn Fn(&C) -> Option<String> + Send + Sync;
67
68pub type HoverFn<C> = dyn Fn(&Document<C>, usize) -> Option<Hover> + Send + Sync;
70
71pub type DefinitionFn<C> = dyn Fn(&Document<C>, usize) -> Option<Vec<Location>> + Send + Sync;
73
74pub type CompletionFn<C> = dyn Fn(&Document<C>, usize) -> Option<CompletionResponse> + Send + Sync;
76
77pub type CodeActionFn<C> =
80 dyn Fn(&Document<C>, lsp_types::Range) -> Vec<lsp_types::CodeAction> + Send + Sync;
81
82#[derive(Debug, Clone, PartialEq, Eq)]
85pub struct NodeLabel {
86 pub name: String,
88 pub detail: Option<String>,
90 pub kind: SymbolKind,
94}
95
96impl NodeLabel {
97 pub fn new(name: impl Into<String>) -> Self {
99 Self {
100 name: name.into(),
101 detail: None,
102 kind: SymbolKind::FUNCTION,
103 }
104 }
105
106 pub fn detail(mut self, detail: impl Into<String>) -> Self {
108 self.detail = Some(detail.into());
109 self
110 }
111
112 pub fn kind(mut self, kind: SymbolKind) -> Self {
115 self.kind = kind;
116 self
117 }
118}
119
120impl<C: Clone + PartialEq + Send + 'static> SimpleLanguage<C> {
121 pub fn new(engine: Engine<C>, root_ctx: C) -> Self {
123 Self {
124 engine,
125 root_ctx,
126 encoding: PositionEncoding::Utf16,
127 diagnostic_fn: None,
128 extra_diagnostics_fn: None,
129 symbols_fn: None,
130 label_fn: None,
131 describe_fn: None,
132 hover_fn: None,
133 definition_fn: None,
134 completion_fn: None,
135 code_action_fn: None,
136 }
137 }
138
139 pub fn encoding(mut self, encoding: PositionEncoding) -> Self {
141 self.encoding = encoding;
142 self
143 }
144
145 pub fn diagnostic_fn(
149 mut self,
150 f: impl Fn(&Document<C>, &FailedNode<'_, C>) -> Option<Diagnostic> + Send + Sync + 'static,
151 ) -> Self {
152 self.diagnostic_fn = Some(Arc::new(f));
153 self
154 }
155
156 pub fn extra_diagnostics(
161 mut self,
162 f: impl Fn(&Document<C>) -> Vec<Diagnostic> + Send + Sync + 'static,
163 ) -> Self {
164 self.extra_diagnostics_fn = Some(Arc::new(f));
165 self
166 }
167
168 pub fn symbols_fn(
171 mut self,
172 f: impl Fn(&Document<C>) -> Vec<DocumentSymbol> + Send + Sync + 'static,
173 ) -> Self {
174 self.symbols_fn = Some(Arc::new(f));
175 self
176 }
177
178 pub fn label_fn(mut self, f: impl Fn(&C) -> Option<NodeLabel> + Send + Sync + 'static) -> Self {
181 self.label_fn = Some(Arc::new(f));
182 self
183 }
184
185 pub fn describe_fn(mut self, f: impl Fn(&C) -> Option<String> + Send + Sync + 'static) -> Self {
190 self.describe_fn = Some(Arc::new(f));
191 self
192 }
193
194 pub fn hover_fn(
197 mut self,
198 f: impl Fn(&Document<C>, usize) -> Option<Hover> + Send + Sync + 'static,
199 ) -> Self {
200 self.hover_fn = Some(Arc::new(f));
201 self
202 }
203
204 pub fn definition_fn(
206 mut self,
207 f: impl Fn(&Document<C>, usize) -> Option<Vec<Location>> + Send + Sync + 'static,
208 ) -> Self {
209 self.definition_fn = Some(Arc::new(f));
210 self
211 }
212
213 pub fn completion_fn(
215 mut self,
216 f: impl Fn(&Document<C>, usize) -> Option<CompletionResponse> + Send + Sync + 'static,
217 ) -> Self {
218 self.completion_fn = Some(Arc::new(f));
219 self
220 }
221
222 pub fn code_action_fn(
225 mut self,
226 f: impl Fn(&Document<C>, lsp_types::Range) -> Vec<lsp_types::CodeAction>
227 + Send
228 + Sync
229 + 'static,
230 ) -> Self {
231 self.code_action_fn = Some(Arc::new(f));
232 self
233 }
234}
235
236impl<C: Clone + PartialEq + Send + Sync + 'static> Language<C> for SimpleLanguage<C> {
239 fn supports_symbols(&self) -> bool {
240 self.symbols_fn.is_some() || self.label_fn.is_some()
241 }
242
243 fn supports_hover(&self) -> bool {
244 self.hover_fn.is_some() || self.describe_fn.is_some()
245 }
246
247 fn supports_definition(&self) -> bool {
248 self.definition_fn.is_some()
249 }
250
251 fn supports_completion(&self) -> bool {
252 self.completion_fn.is_some()
253 }
254
255 fn supports_code_actions(&self) -> bool {
256 self.code_action_fn.is_some()
257 }
258
259 fn code_action(
260 &self,
261 doc: &Document<C>,
262 range: lsp_types::Range,
263 ) -> Vec<lsp_types::CodeAction> {
264 match &self.code_action_fn {
265 Some(f) => f(doc, range),
266 None => Vec::new(),
267 }
268 }
269
270 fn hover(&self, doc: &Document<C>, offset: usize) -> Option<Hover> {
271 if let Some(f) = &self.hover_fn {
272 return f(doc, offset);
273 }
274 let describe = self.describe_fn.as_ref()?;
275 let tree = doc.session().tree();
276 let id = tree.node_at(offset)?;
277 let text = describe(tree.ctx(id))?;
278 Some(Hover {
279 contents: lsp_types::HoverContents::Scalar(lsp_types::MarkedString::String(text)),
280 range: Some(doc.range(tree.span(id))),
281 })
282 }
283
284 fn definition(&self, doc: &Document<C>, offset: usize) -> Option<Vec<Location>> {
285 let f = self.definition_fn.as_ref()?;
286 f(doc, offset)
287 }
288
289 fn completion(&self, doc: &Document<C>, offset: usize) -> Option<CompletionResponse> {
290 let f = self.completion_fn.as_ref()?;
291 f(doc, offset)
292 }
293
294 fn engine(&self) -> &Engine<C> {
295 &self.engine
296 }
297
298 fn root_ctx(&self) -> C {
299 self.root_ctx.clone()
300 }
301
302 fn encoding(&self) -> PositionEncoding {
303 self.encoding
304 }
305
306 fn diagnostic(&self, doc: &Document<C>, node: FailedNode<'_, C>) -> Option<Diagnostic> {
307 let f = self.diagnostic_fn.as_ref()?;
308 f(doc, &node)
309 }
310
311 fn extra_diagnostics(&self, doc: &Document<C>) -> Vec<Diagnostic> {
312 match &self.extra_diagnostics_fn {
313 Some(f) => f(doc),
314 None => Vec::new(),
315 }
316 }
317
318 fn symbols(&self, doc: &Document<C>) -> Vec<DocumentSymbol> {
319 if let Some(f) = &self.symbols_fn {
320 return f(doc);
321 }
322 if let Some(label) = &self.label_fn {
323 let tree = doc.session().tree();
324 return tree
325 .nodes()
326 .filter_map(|id| {
327 let label = label(tree.ctx(id))?;
328 let range = doc.range(tree.span(id));
329 Some(DocumentSymbol {
330 name: label.name,
331 detail: label.detail,
332 kind: label.kind,
333 range,
334 selection_range: range,
335 children: None,
336 tags: None,
337 #[allow(deprecated)]
338 deprecated: None,
339 })
340 })
341 .collect();
342 }
343 Vec::new()
344 }
345}