Skip to content

Commit 35d4ed4

Browse files
committed
v2: add wasm
1 parent 7a5679e commit 35d4ed4

5 files changed

Lines changed: 243 additions & 0 deletions

File tree

Cargo.lock

Lines changed: 67 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ squawk-linter = { version = "0.0.0", path = "./crates/linter" }
4141
squawk-github = { version = "0.0.0", path = "./crates/github" }
4242
squawk_lexer = { version = "0.0.0", path = "./crates/squawk_lexer" }
4343
squawk_parser = { version = "0.0.0", path = "./crates/squawk_parser" }
44+
squawk_linter = { version = "0.0.0", path = "./crates/squawk_linter" }
4445

4546
[workspace.lints.clippy]
4647
collapsible_else_if = "allow"

crates/squawk_wasm/Cargo.toml

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
[package]
2+
name = "squawk_wasm"
3+
version = "0.1.0"
4+
edition.workspace = true
5+
rust-version.workspace = true
6+
authors.workspace = true
7+
license.workspace = true
8+
9+
[lib]
10+
crate-type = ["cdylib", "rlib"]
11+
12+
[features]
13+
default = ["console_error_panic_hook"]
14+
15+
[dependencies]
16+
17+
squawk_syntax.workspace = true
18+
squawk_linter.workspace = true
19+
squawk_lexer.workspace = true
20+
21+
wasm-bindgen.workspace = true
22+
serde-wasm-bindgen.workspace = true
23+
serde.workspace = true
24+
console_error_panic_hook = { workspace = true, optional = true }
25+
web-sys = { workspace = true, features = ["Window"] }
26+
console_log.workspace = true
27+
log.workspace = true
28+
line-index.workspace = true
29+
30+
[dev-dependencies]
31+
wasm-bindgen-test.workspace = true
32+
33+
[lints]
34+
workspace = true

crates/squawk_wasm/README.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
# squak_wasm
2+
3+
```shell
4+
wasm-pack build --target web crates/squawk_wasm
5+
```

crates/squawk_wasm/src/lib.rs

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
use line_index::LineIndex;
2+
use log::info;
3+
use serde::Serialize;
4+
use wasm_bindgen::prelude::*;
5+
use web_sys::js_sys::Error;
6+
7+
#[wasm_bindgen(start)]
8+
pub fn run() {
9+
use log::Level;
10+
11+
// When the `console_error_panic_hook` feature is enabled, we can call the
12+
// `set_panic_hook` function at least once during initialization, and then
13+
// we will get better error messages if our code ever panics.
14+
//
15+
// For more details see
16+
// https://github.com/rustwasm/console_error_panic_hook#readme
17+
#[cfg(feature = "console_error_panic_hook")]
18+
console_error_panic_hook::set_once();
19+
console_log::init_with_level(Level::Debug).expect("Initializing logger went wrong.");
20+
info!("init!");
21+
}
22+
23+
#[wasm_bindgen]
24+
pub fn dump_cst(text: String) -> String {
25+
let parse = squawk_syntax::SourceFile::parse(&text);
26+
format!("{:#?}", parse.syntax_node())
27+
}
28+
29+
#[wasm_bindgen]
30+
pub fn dump_tokens(text: String) -> String {
31+
let tokens = squawk_lexer::tokenize(&text);
32+
let mut start = 0;
33+
let mut out = String::new();
34+
for token in tokens {
35+
let end = start + token.len;
36+
let content = &text[start as usize..(end) as usize];
37+
out += &format!("{:?}@{start}..{end} {:?}\n", token.kind, content);
38+
start += token.len;
39+
}
40+
out
41+
}
42+
43+
#[allow(dead_code)]
44+
#[derive(Serialize)]
45+
enum Severity {
46+
Hint,
47+
Info,
48+
Warning,
49+
Error,
50+
}
51+
52+
#[derive(Serialize)]
53+
struct LintError {
54+
severity: Severity,
55+
code: String,
56+
message: String,
57+
start_line_number: u32,
58+
start_column: u32,
59+
end_line_number: u32,
60+
end_column: u32,
61+
// used for the linter tab
62+
range_start: usize,
63+
// used for the linter tab
64+
range_end: usize,
65+
// used for the linter tab
66+
messages: Vec<String>,
67+
}
68+
69+
#[wasm_bindgen]
70+
pub fn lint(text: String) -> Result<JsValue, Error> {
71+
let mut linter = squawk_linter::Linter::with_all_rules();
72+
let parse = squawk_syntax::SourceFile::parse(&text);
73+
let parse_errors = parse.errors();
74+
75+
let line_index = LineIndex::new(&text);
76+
77+
// TODO: chain these with other stuff
78+
let parse_errors = parse_errors.iter().map(|x| {
79+
let range_start = x.range().start();
80+
let range_end = x.range().end();
81+
let start = line_index.line_col(range_start);
82+
let end = line_index.line_col(range_end);
83+
let start = line_index
84+
.to_wide(line_index::WideEncoding::Utf16, start)
85+
.unwrap();
86+
let end = line_index
87+
.to_wide(line_index::WideEncoding::Utf16, end)
88+
.unwrap();
89+
LintError {
90+
severity: Severity::Error,
91+
code: "syntax-error".to_string(),
92+
message: x.message().to_string(),
93+
start_line_number: start.line,
94+
start_column: start.col,
95+
end_line_number: end.line,
96+
end_column: end.col,
97+
range_start: range_start.into(),
98+
range_end: range_end.into(),
99+
messages: vec![],
100+
}
101+
});
102+
103+
let lint_errors = linter.lint(parse, &text);
104+
let errors = lint_errors.into_iter().map(|x| {
105+
let start = line_index.line_col(x.text_range.start());
106+
let end = line_index.line_col(x.text_range.end());
107+
let start = line_index
108+
.to_wide(line_index::WideEncoding::Utf16, start)
109+
.unwrap();
110+
let end = line_index
111+
.to_wide(line_index::WideEncoding::Utf16, end)
112+
.unwrap();
113+
LintError {
114+
code: x.code.to_string(),
115+
range_start: x.text_range.start().into(),
116+
range_end: x.text_range.end().into(),
117+
message: x.message.clone(),
118+
messages: x.messages.clone(),
119+
// parser errors should be error
120+
severity: Severity::Warning,
121+
start_line_number: start.line,
122+
start_column: start.col,
123+
end_line_number: end.line,
124+
end_column: end.col,
125+
}
126+
});
127+
128+
let mut errors_to_dump = errors.chain(parse_errors).collect::<Vec<_>>();
129+
errors_to_dump.sort_by_key(|k| (k.start_line_number, k.start_column));
130+
131+
serde_wasm_bindgen::to_value(&errors_to_dump).map_err(into_error)
132+
}
133+
134+
fn into_error<E: std::fmt::Display>(err: E) -> Error {
135+
Error::new(&err.to_string())
136+
}

0 commit comments

Comments
 (0)