From ad701b3f1959fa7c761668da5164518aa9d122cd Mon Sep 17 00:00:00 2001 From: Akshay Date: Sat, 12 Jun 2021 10:46:39 +0530 Subject: init --- src/lib.rs | 118 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/utils.rs | 10 +++++ 2 files changed, 128 insertions(+) create mode 100644 src/lib.rs create mode 100644 src/utils.rs (limited to 'src') 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 @@ +mod utils; + +use js_sys::Array; + +use syntax::{ + ast::{self, AstNode}, + NodeOrToken, SourceFile, SyntaxElement, SyntaxError, SyntaxNode, +}; +use wasm_bindgen::prelude::*; + +use std::{convert::From, str::FromStr}; + +// When the `wee_alloc` feature is enabled, use `wee_alloc` as the global +// allocator. +#[cfg(feature = "wee_alloc")] +#[global_allocator] +static ALLOC: wee_alloc::WeeAlloc = wee_alloc::WeeAlloc::INIT; + +#[wasm_bindgen] +pub fn put_cst(source: &str) -> String { + let source_file = SourceFile::parse(source); + source_file.debug_dump() +} + +// wrapper type to pass syntax elements to JS +#[wasm_bindgen] +#[derive(Debug, Clone)] +pub struct SynNode { + node: SyntaxElement, +} + +impl SynNode { + pub fn new(node: SyntaxElement) -> Self { + Self { node } + } +} + +#[wasm_bindgen] +impl SynNode { + pub fn children(&self) -> Vec { + match &self.node { + NodeOrToken::Node(n) => n + .children_with_tokens() + .map(SynNode::new) + .map(JsValue::from) + .collect(), + NodeOrToken::Token(_) => vec![], + } + } + + pub fn is_token(&self) -> bool { + self.node.as_token().is_some() + } + + pub fn to_string(&self) -> String { + format!("{:?}@{:?}", self.node.kind(), self.node.text_range(),) + } + + pub fn from_str(s: &str) -> Result { + FromStr::from_str(s) + .map(|p: SynNode| JsValue::from(p)) + .map_err(JsValue::from) + } +} + +impl FromStr for SynNode { + type Err = Array; + fn from_str(s: &str) -> Result { + let source_file = SourceFile::parse(s); + if source_file.errors().is_empty() { + Ok(Self { + node: NodeOrToken::Node(source_file.ok().unwrap().syntax().clone()), + }) + } else { + Err(source_file + .errors() + .into_iter() + .map(SynErr::new) + .map(JsValue::from) + .collect()) + } + } +} + +#[wasm_bindgen] +#[derive(Debug, Clone)] +struct SynErr { + err: SyntaxError, +} + +impl SynErr { + pub fn new(err: &SyntaxError) -> Self { + Self { err: err.clone() } + } +} + +#[wasm_bindgen] +struct TextRange { + start: u32, + end: u32, +} + +impl From<(u32, u32)> for TextRange { + fn from((start, end): (u32, u32)) -> Self { + TextRange { start, end } + } +} + +#[wasm_bindgen] +impl SynErr { + pub fn range(&self) -> TextRange { + let r = self.err.range(); + (r.start().into(), r.end().into()).into() + } + pub fn to_string(&self) -> String { + self.err.to_string() + } +} 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 @@ +pub fn set_panic_hook() { + // When the `console_error_panic_hook` feature is enabled, we can call the + // `set_panic_hook` function at least once during initialization, and then + // we will get better error messages if our code ever panics. + // + // For more details see + // https://github.com/rustwasm/console_error_panic_hook#readme + #[cfg(feature = "console_error_panic_hook")] + console_error_panic_hook::set_once(); +} -- cgit v1.2.3