thrift_analyzer/
wasm.rs

1//! WASM bindings for the analyzer.
2//!
3//! Build: `wasm-pack build --target nodejs`
4
5use std::io;
6
7use js_sys::Function;
8use serde_wasm_bindgen::to_value;
9use wasm_bindgen::prelude::*;
10
11use crate::analyzer;
12
13#[wasm_bindgen]
14pub struct Analyzer {
15    analyzer: analyzer::Analyzer,
16}
17
18#[wasm_bindgen]
19impl Analyzer {
20    pub fn new() -> Analyzer {
21        Analyzer {
22            analyzer: analyzer::Analyzer::new(),
23        }
24    }
25
26    pub fn sync_document(&mut self, path: &str, content: &str) {
27        self.analyzer.sync_document(path, content);
28    }
29
30    pub fn remove_document(&mut self, path: &str) {
31        self.analyzer.remove_document(path);
32    }
33
34    pub fn errors(&self) -> JsValue {
35        let errors = self.analyzer.errors();
36        to_value(errors).unwrap_or_default()
37    }
38
39    pub fn semantic_tokens(&self, path: &str) -> Option<Vec<u32>> {
40        self.analyzer.semantic_tokens(path).cloned()
41    }
42
43    pub fn semantic_token_types(&self) -> Vec<String> {
44        self.analyzer.semantic_token_types()
45    }
46
47    pub fn semantic_token_modifiers(&self) -> Vec<String> {
48        self.analyzer.semantic_token_modifiers()
49    }
50
51    pub fn definition(&self, path: &str, line: u32, column: u32) -> JsValue {
52        let pos = analyzer::base::Position { line, column };
53
54        match self.analyzer.definition(path, pos) {
55            Some(loc) => to_value(&loc).unwrap_or_default(),
56            None => JsValue::null(),
57        }
58    }
59
60    pub fn types_for_completion(&self, path: &str, line: u32, column: u32) -> JsValue {
61        let pos = analyzer::base::Position { line, column };
62        let completions = self.analyzer.types_for_completion(path, pos);
63        to_value(&completions).unwrap_or_default()
64    }
65
66    pub fn includes_for_completion(&self, path: &str, line: u32, column: u32) -> JsValue {
67        let pos = analyzer::base::Position { line, column };
68        let completions = self.analyzer.includes_for_completion(path, pos);
69        to_value(&completions).unwrap_or_default()
70    }
71
72    pub fn keywords_for_completion(&self) -> JsValue {
73        let completions = self.analyzer.keywords_for_completion();
74        to_value(&completions).unwrap_or_default()
75    }
76
77    pub fn set_wasm_read_file(&mut self, read_file: Function) {
78        self.analyzer.wasm_read_file = Some(Box::new(move |path: String| -> io::Result<String> {
79            let args = js_sys::Array::new();
80            args.push(&path.into());
81            let result = read_file.apply(&JsValue::null(), &args).unwrap_or_default();
82            let content =
83                js_sys::Reflect::get(&result, &JsValue::from_str("content")).unwrap_or_default();
84            let error = js_sys::Reflect::get(&result, &JsValue::from_str("error"))
85                .unwrap_or_default()
86                .as_string()
87                .unwrap_or_default();
88            if error.len() > 0 {
89                return Err(io::Error::new(io::ErrorKind::Other, error));
90            }
91
92            let result = content.as_string().unwrap_or_default();
93            Ok(result)
94        }));
95    }
96}