|
4 | 4 | //! `JsValue` arguments into pure Rust types, calls the corresponding |
5 | 5 | //! `mpl_language_server::*` function, and re-encodes the result. |
6 | 6 |
|
7 | | -use mpl_lang::{Query, compile, query::Source}; |
| 7 | +use mpl_lang::{CompileError, Query, compile2, query::Source}; |
8 | 8 | use mpl_language_server::SystemParamSpec; |
9 | 9 | use serde::Serialize; |
10 | 10 | use wasm_bindgen::prelude::*; |
11 | 11 |
|
12 | 12 | mod system_params; |
13 | 13 |
|
14 | 14 | /// Parse `query` (ignoring warnings) into a `Query` AST. Used by the |
15 | | -/// `parse_*` / `extract_dataset` shims below. Errors are stringified via |
16 | | -/// `Debug` to avoid pulling miette's fancy formatter into the wasm bundle. |
| 15 | +/// `parse_*` / `extract_dataset` shims below. |
17 | 16 | fn parse_with_system_param_specs( |
18 | 17 | query: &str, |
19 | 18 | system_params: &[SystemParamSpec], |
20 | 19 | ) -> Result<Query, String> { |
21 | 20 | let params = mpl_language_server::to_compile_params(system_params); |
22 | | - compile(query, params) |
| 21 | + compile2(query, params) |
23 | 22 | .map(|(q, _warnings)| q) |
24 | | - .map_err(|e| format!("{e:?}")) |
| 23 | + .map_err(|e| describe(&e)) |
| 24 | +} |
| 25 | + |
| 26 | +/// What went wrong, as a line the host can show. |
| 27 | +/// |
| 28 | +/// Each variant is rendered through the error it carries. Naming them one by one |
| 29 | +/// keeps miette's formatter and the grammar's rule names out of the wasm bundle, |
| 30 | +/// which is worth more here than the shorter spelling. |
| 31 | +fn describe(e: &CompileError) -> String { |
| 32 | + match e { |
| 33 | + CompileError::ParserV2(errors) => errors |
| 34 | + .iter() |
| 35 | + .map(ToString::to_string) |
| 36 | + .collect::<Vec<_>>() |
| 37 | + .join("; "), |
| 38 | + CompileError::Type(e) => e.to_string(), |
| 39 | + CompileError::Group(e) => e.to_string(), |
| 40 | + CompileError::Ifdef(e) => e.to_string(), |
| 41 | + CompileError::Parse(_) => "parse error".to_string(), |
| 42 | + } |
25 | 43 | } |
26 | 44 |
|
27 | 45 | /// Pure rust JSON parse helper. |
@@ -86,13 +104,59 @@ pub fn diagnostics(query: &str, system_params: JsValue) -> JsValue { |
86 | 104 | } |
87 | 105 |
|
88 | 106 | /// Tokenises `query` for syntax highlighting. |
| 107 | +/// |
| 108 | +/// Always returns an array: a query that does not parse yields the tokens it |
| 109 | +/// does have, so the editor keeps its colours while the user is still typing. |
89 | 110 | #[must_use] |
90 | 111 | #[wasm_bindgen] |
91 | 112 | pub fn tokenize(query: &str) -> JsValue { |
92 | 113 | let tokens = mpl_language_server::collect_tokens(query); |
93 | 114 | to_js_value(&tokens) |
94 | 115 | } |
95 | 116 |
|
| 117 | +/// Returns the token at byte `offset` as `{ from, to, type }`, or `null` where |
| 118 | +/// there is nothing to report (whitespace, punctuation, past the end). |
| 119 | +/// |
| 120 | +/// A `::`-qualified function name comes back whole, so hovering either segment |
| 121 | +/// of `prom::rate` yields the name the stdlib is keyed by. Callers read the text |
| 122 | +/// out of their own copy with the returned span. |
| 123 | +#[must_use] |
| 124 | +#[wasm_bindgen] |
| 125 | +pub fn token_at(query: &str, offset: usize) -> JsValue { |
| 126 | + to_js_value(&mpl_language_server::token_at(query, offset)) |
| 127 | +} |
| 128 | + |
| 129 | +/// Looks up an MPL keyword by name and returns its description and syntax, or |
| 130 | +/// `null` when the word names no keyword. |
| 131 | +#[must_use] |
| 132 | +#[wasm_bindgen] |
| 133 | +pub fn keyword_info(label: &str) -> JsValue { |
| 134 | + to_js_value(&mpl_language_server::keyword_info(label)) |
| 135 | +} |
| 136 | + |
| 137 | +/// Whether `name` has to be backtick-escaped to be read as an identifier. |
| 138 | +#[must_use] |
| 139 | +#[wasm_bindgen] |
| 140 | +pub fn needs_escape(name: &str) -> bool { |
| 141 | + mpl_language_server::needs_escape(name) |
| 142 | +} |
| 143 | + |
| 144 | +/// `name` written so it reads as an identifier, adding backticks only where |
| 145 | +/// they are required. |
| 146 | +#[must_use] |
| 147 | +#[wasm_bindgen] |
| 148 | +pub fn escape_ident(name: &str) -> String { |
| 149 | + mpl_language_server::escape_ident(name) |
| 150 | +} |
| 151 | + |
| 152 | +/// The text a completion inserts for `name`. Set `in_backtick` when the opening |
| 153 | +/// backtick is already in the document and the replacement starts after it. |
| 154 | +#[must_use] |
| 155 | +#[wasm_bindgen] |
| 156 | +pub fn apply_text_for_ident(name: &str, in_backtick: bool) -> String { |
| 157 | + mpl_language_server::apply_text_for_ident(name, in_backtick) |
| 158 | +} |
| 159 | + |
96 | 160 | /// Extracts the dataset name from an `MPL` query string. |
97 | 161 | /// |
98 | 162 | /// For `Simple` queries, returns the dataset from the source. |
|
0 commit comments