aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/lib.rs118
-rw-r--r--src/utils.rs10
2 files changed, 128 insertions, 0 deletions
diff --git a/src/lib.rs b/src/lib.rs
new file mode 100644
index 0000000..f9a6a26
--- /dev/null
+++ b/src/lib.rs
@@ -0,0 +1,118 @@
1mod utils;
2
3use js_sys::Array;
4
5use syntax::{
6 ast::{self, AstNode},
7 NodeOrToken, SourceFile, SyntaxElement, SyntaxError, SyntaxNode,
8};
9use wasm_bindgen::prelude::*;
10
11use std::{convert::From, str::FromStr};
12
13// When the `wee_alloc` feature is enabled, use `wee_alloc` as the global
14// allocator.
15#[cfg(feature = "wee_alloc")]
16#[global_allocator]
17static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT;
18
19#[wasm_bindgen]
20pub fn put_cst(source: &str) -> String {
21 let source_file = SourceFile::parse(source);
22 source_file.debug_dump()
23}
24
25// wrapper type to pass syntax elements to JS
26#[wasm_bindgen]
27#[derive(Debug, Clone)]
28pub struct SynNode {
29 node: SyntaxElement,
30}
31
32impl SynNode {
33 pub fn new(node: SyntaxElement) -> Self {
34 Self { node }
35 }
36}
37
38#[wasm_bindgen]
39impl SynNode {
40 pub fn children(&self) -> Vec<JsValue> {
41 match &self.node {
42 NodeOrToken::Node(n) => n
43 .children_with_tokens()
44 .map(SynNode::new)
45 .map(JsValue::from)
46 .collect(),
47 NodeOrToken::Token(_) => vec![],
48 }
49 }
50
51 pub fn is_token(&self) -> bool {
52 self.node.as_token().is_some()
53 }
54
55 pub fn to_string(&self) -> String {
56 format!("{:?}@{:?}", self.node.kind(), self.node.text_range(),)
57 }
58
59 pub fn from_str(s: &str) -> Result<JsValue, JsValue> {
60 FromStr::from_str(s)
61 .map(|p: SynNode| JsValue::from(p))
62 .map_err(JsValue::from)
63 }
64}
65
66impl FromStr for SynNode {
67 type Err = Array;
68 fn from_str(s: &str) -> Result<Self, Array> {
69 let source_file = SourceFile::parse(s);
70 if source_file.errors().is_empty() {
71 Ok(Self {
72 node: NodeOrToken::Node(source_file.ok().unwrap().syntax().clone()),
73 })
74 } else {
75 Err(source_file
76 .errors()
77 .into_iter()
78 .map(SynErr::new)
79 .map(JsValue::from)
80 .collect())
81 }
82 }
83}
84
85#[wasm_bindgen]
86#[derive(Debug, Clone)]
87struct SynErr {
88 err: SyntaxError,
89}
90
91impl SynErr {
92 pub fn new(err: &SyntaxError) -> Self {
93 Self { err: err.clone() }
94 }
95}
96
97#[wasm_bindgen]
98struct TextRange {
99 start: u32,
100 end: u32,
101}
102
103impl From<(u32, u32)> for TextRange {
104 fn from((start, end): (u32, u32)) -> Self {
105 TextRange { start, end }
106 }
107}
108
109#[wasm_bindgen]
110impl SynErr {
111 pub fn range(&self) -> TextRange {
112 let r = self.err.range();
113 (r.start().into(), r.end().into()).into()
114 }
115 pub fn to_string(&self) -> String {
116 self.err.to_string()
117 }
118}
diff --git a/src/utils.rs b/src/utils.rs
new file mode 100644
index 0000000..b1d7929
--- /dev/null
+++ b/src/utils.rs
@@ -0,0 +1,10 @@
1pub fn set_panic_hook() {
2 // When the `console_error_panic_hook` feature is enabled, we can call the
3 // `set_panic_hook` function at least once during initialization, and then
4 // we will get better error messages if our code ever panics.
5 //
6 // For more details see
7 // https://github.com/rustwasm/console_error_panic_hook#readme
8 #[cfg(feature = "console_error_panic_hook")]
9 console_error_panic_hook::set_once();
10}