dotrain_lsp/js_api/
mod.rs

1use wasm_bindgen::prelude::*;
2use lsp_types::{MarkupKind as MK, Position as Pos, TextDocumentItem as TDI, Url};
3use serde_wasm_bindgen::{to_value as to_js_value, from_value as from_js_value};
4use dotrain::{js_api::MetaStore, RainDocument, Rebind};
5use super::{RainLanguageServices, LanguageServiceParams};
6
7#[wasm_bindgen]
8extern "C" {
9    /// A wrapped JsValue representing typescript LSP Position interface in rust,
10    /// it can be deserialized to rust [mod@lsp_types::Position] using `serde-wasm-bindgen`
11    #[wasm_bindgen(typescript_type = "Position")]
12    pub type Position;
13    /// A wrapped JsValue representing typescript LSP TextDocumentItem interface in rust,
14    /// it can be deserialized to rust [mod@lsp_types::TextDocumentItem] using `serde-wasm-bindgen`
15    #[wasm_bindgen(typescript_type = "TextDocumentItem")]
16    pub type TextDocumentItem;
17    /// A wrapped JsValue representing typescript LSP MarkupKind interface in rust,
18    /// it can be deserialized to rust [mod@lsp_types::MarkupKind] using `serde-wasm-bindgen`
19    #[wasm_bindgen(typescript_type = "MarkupKind")]
20    pub type MarkupKind;
21    /// A wrapped JsValue representing typescript LSP Diagnostic interface in rust,
22    /// it can be deserialized to rust [mod@lsp_types::Diagnostic] using `serde-wasm-bindgen`
23    #[wasm_bindgen(typescript_type = "Diagnostic")]
24    pub type Diagnostic;
25    /// A wrapped JsValue representing typescript LSP Hover interface in rust,
26    /// it can be deserialized to rust [mod@lsp_types::Hover] using `serde-wasm-bindgen`
27    #[wasm_bindgen(typescript_type = "Hover")]
28    pub type Hover;
29    /// A wrapped JsValue representing typescript LSP CompletionItem interface in rust,
30    /// it can be deserialized to rust [mod@lsp_types::CompletionItem] using `serde-wasm-bindgen`
31    #[wasm_bindgen(typescript_type = "CompletionItem")]
32    pub type CompletionItem;
33    /// A wrapped JsValue representing typescript LSP SemanticTokensPartialResult interface in rust,
34    /// it can be deserialized to rust [mod@lsp_types::SemanticTokensPartialResult] using `serde-wasm-bindgen`
35    #[wasm_bindgen(typescript_type = "SemanticTokensPartialResult")]
36    pub type SemanticTokensPartialResult;
37}
38
39#[wasm_bindgen(typescript_custom_section)]
40const LSP_TS_IMPORTS: &'static str = r#"
41import { SemanticTokensPartialResult } from "vscode-languageserver-protocol";
42import { Hover, Position, MarkupKind, Diagnostic, CompletionItem, TextDocumentItem } from "vscode-languageserver-types";
43"#;
44
45#[wasm_bindgen]
46impl RainLanguageServices {
47    /// The meta Store associated with this RainLanguageServices instance
48    #[wasm_bindgen(getter, js_name = "metaStore")]
49    pub fn js_meta_store(&self) -> MetaStore {
50        self.meta_store.clone().into()
51    }
52
53    /// Instantiates with the given MetaStore
54    #[wasm_bindgen(constructor)]
55    pub fn js_new(meta_store: &MetaStore) -> RainLanguageServices {
56        RainLanguageServices::new(&LanguageServiceParams {
57            meta_store: Some(meta_store.into()),
58        })
59    }
60
61    /// Instantiates a RainDocument with remote meta search disabled when parsing from the given TextDocumentItem
62    #[wasm_bindgen(js_name = "newRainDocument")]
63    pub fn js_new_rain_document(
64        &self,
65        text_document: TextDocumentItem,
66        rebinds: Option<Vec<Rebind>>,
67    ) -> RainDocument {
68        let tdi = from_js_value::<TDI>(text_document.obj).unwrap_throw();
69        self.new_rain_document(&tdi, rebinds)
70    }
71
72    /// Instantiates a RainDocument with remote meta search enabled when parsing from the given TextDocumentItem
73    #[wasm_bindgen(js_name = "newRainDocumentAsync")]
74    pub async fn js_new_rain_document_async(
75        &self,
76        text_document: TextDocumentItem,
77        rebinds: Option<Vec<Rebind>>,
78    ) -> RainDocument {
79        let tdi = from_js_value::<TDI>(text_document.obj).unwrap_throw();
80        self.new_rain_document_async(&tdi, rebinds).await
81    }
82
83    /// Validates the document with remote meta search disabled when parsing and reports LSP diagnostics
84    #[wasm_bindgen(js_name = "doValidate")]
85    pub fn js_do_validate(
86        &self,
87        text_document: TextDocumentItem,
88        related_information: bool,
89        rebinds: Option<Vec<Rebind>>,
90    ) -> Vec<Diagnostic> {
91        let tdi = from_js_value::<TDI>(text_document.obj).unwrap_throw();
92        self.do_validate(&tdi, related_information, rebinds)
93            .iter()
94            .map(|v| Diagnostic {
95                obj: to_js_value(v).unwrap_or(JsValue::NULL),
96            })
97            .collect()
98    }
99
100    /// Reports LSP diagnostics from RainDocument's all problems
101    #[wasm_bindgen(js_name = "doValidateRainDocument")]
102    pub fn js_do_validate_rain_document(
103        &self,
104        rain_document: &RainDocument,
105        uri: &str,
106        related_information: bool,
107    ) -> Vec<Diagnostic> {
108        self.do_validate_rain_document(
109            rain_document,
110            &Url::parse(uri).unwrap_throw(),
111            related_information,
112        )
113        .iter()
114        .map(|v| Diagnostic {
115            obj: to_js_value(v).unwrap_or(JsValue::NULL),
116        })
117        .collect()
118    }
119
120    /// Validates the document with remote meta search enabled when parsing and reports LSP diagnostics
121    #[wasm_bindgen(js_name = "doValidateAsync")]
122    pub async fn js_do_validate_async(
123        &self,
124        text_document: TextDocumentItem,
125        related_information: bool,
126        rebinds: Option<Vec<Rebind>>,
127    ) -> JsValue {
128        let tdi = from_js_value::<TDI>(text_document.obj).unwrap_throw();
129        to_js_value(
130            &self
131                .do_validate_async(&tdi, related_information, rebinds)
132                .await,
133        )
134        .unwrap_or(JsValue::NULL)
135    }
136
137    /// Provides completion items at the given position
138    #[wasm_bindgen(js_name = "doComplete")]
139    pub fn js_do_complete(
140        &self,
141        text_document: TextDocumentItem,
142        position: Position,
143        documentation_format: Option<MarkupKind>,
144        rebinds: Option<Vec<Rebind>>,
145    ) -> Option<Vec<CompletionItem>> {
146        let pos = from_js_value::<Pos>(position.obj).unwrap_throw();
147        let tdi = from_js_value::<TDI>(text_document.obj).unwrap_throw();
148        self.do_complete(
149            &tdi,
150            pos,
151            documentation_format.and_then(|v| from_js_value::<MK>(v.obj).ok()),
152            rebinds,
153        )
154        .map(|c| {
155            c.iter()
156                .map(|v| CompletionItem {
157                    obj: to_js_value(v).unwrap_or(JsValue::NULL),
158                })
159                .collect()
160        })
161    }
162
163    /// Provides completion items at the given position
164    #[wasm_bindgen(js_name = "doCompleteRainDocument")]
165    pub fn js_do_complete_rain_document(
166        &self,
167        rain_document: &RainDocument,
168        uri: &str,
169        position: Position,
170        documentation_format: Option<MarkupKind>,
171    ) -> Option<Vec<CompletionItem>> {
172        let pos = from_js_value::<Pos>(position.obj).unwrap_throw();
173        self.do_complete_rain_document(
174            rain_document,
175            &Url::parse(uri).unwrap_throw(),
176            pos,
177            documentation_format.and_then(|v| from_js_value::<MK>(v.obj).ok()),
178        )
179        .map(|c| {
180            c.iter()
181                .map(|v| CompletionItem {
182                    obj: to_js_value(v).unwrap_or(JsValue::NULL),
183                })
184                .collect()
185        })
186    }
187
188    /// Provides hover for a fragment at the given position
189    #[wasm_bindgen(js_name = "doHover")]
190    pub fn js_do_hover(
191        &self,
192        text_document: TextDocumentItem,
193        position: Position,
194        content_format: Option<MarkupKind>,
195        rebinds: Option<Vec<Rebind>>,
196    ) -> Option<Hover> {
197        let pos = from_js_value::<Pos>(position.obj).unwrap_throw();
198        let tdi = from_js_value::<TDI>(text_document.obj).unwrap_throw();
199        self.do_hover(
200            &tdi,
201            pos,
202            content_format.and_then(|v| from_js_value::<MK>(v.obj).ok()),
203            rebinds,
204        )
205        .map(|v| Hover {
206            obj: to_js_value(&v).unwrap_or(JsValue::NULL),
207        })
208    }
209
210    /// Provides hover for a RainDocument fragment at the given position
211    #[wasm_bindgen(js_name = "doHoverRainDocument")]
212    pub fn js_do_hover_rain_document(
213        &self,
214        rain_document: &RainDocument,
215        position: Position,
216        content_format: Option<MarkupKind>,
217    ) -> Option<Hover> {
218        let pos = from_js_value::<Pos>(position.obj).unwrap_throw();
219        self.do_hover_rain_document(
220            rain_document,
221            pos,
222            content_format.and_then(|v| from_js_value::<MK>(v.obj).ok()),
223        )
224        .map(|v| Hover {
225            obj: to_js_value(&v).unwrap_or(JsValue::NULL),
226        })
227    }
228
229    /// Provides semantic tokens for elided fragments
230    #[wasm_bindgen(js_name = "semanticTokens")]
231    pub fn js_semantic_tokens(
232        &self,
233        text_document: TextDocumentItem,
234        semantic_token_types_index: u32,
235        semantic_token_modifiers_len: usize,
236        rebinds: Option<Vec<Rebind>>,
237    ) -> SemanticTokensPartialResult {
238        let tdi = from_js_value::<TDI>(text_document.obj).unwrap_throw();
239        SemanticTokensPartialResult {
240            obj: to_js_value(&self.semantic_tokens(
241                &tdi,
242                semantic_token_types_index,
243                semantic_token_modifiers_len,
244                rebinds,
245            ))
246            .unwrap_or(JsValue::NULL),
247        }
248    }
249
250    /// Provides semantic tokens for RainDocument's elided fragments
251    #[wasm_bindgen(js_name = "rainDocumentSemanticTokens")]
252    pub fn js_rain_document_semantic_tokens(
253        &self,
254        rain_document: &RainDocument,
255        semantic_token_types_index: u32,
256        semantic_token_modifiers_len: usize,
257    ) -> SemanticTokensPartialResult {
258        SemanticTokensPartialResult {
259            obj: to_js_value(&self.rain_document_semantic_tokens(
260                rain_document,
261                semantic_token_types_index,
262                semantic_token_modifiers_len,
263            ))
264            .unwrap_or(JsValue::NULL),
265        }
266    }
267}