mirror of
https://github.com/slint-ui/slint.git
synced 2025-10-02 06:41:14 +00:00
LSP: add a setting to change the style
... and the include paths
This commit is contained in:
parent
8f29f22c6c
commit
cbe2d6d631
9 changed files with 260 additions and 37 deletions
|
@ -78,6 +78,17 @@
|
|||
"type": "string"
|
||||
},
|
||||
"description": "The command line arguments passed to the Slint LSP server"
|
||||
},
|
||||
"slint.preview.style": {
|
||||
"type": "string",
|
||||
"description": "The style to be used for the preview (eg: 'fluent', 'material', or 'native')"
|
||||
},
|
||||
"slint.includePaths": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
},
|
||||
"description": "List of paths in which the `import` statement and `@image-url` are looked up"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -26,8 +26,13 @@ slint_init(slint_wasm_data).then((_) => {
|
|||
return new TextDecoder().decode(contents);
|
||||
}
|
||||
|
||||
async function send_request(method: string, params: any): Promise<any> {
|
||||
return await connection.sendRequest(method, params);
|
||||
}
|
||||
|
||||
|
||||
connection.onInitialize((params: InitializeParams): InitializeResult => {
|
||||
the_lsp = slint_lsp.create(params, send_notification, load_file);
|
||||
the_lsp = slint_lsp.create(params, send_notification, send_request, load_file);
|
||||
return the_lsp.server_initialize_result();
|
||||
});
|
||||
|
||||
|
@ -39,6 +44,10 @@ slint_init(slint_wasm_data).then((_) => {
|
|||
return await the_lsp.handle_request(token, method, params);
|
||||
});
|
||||
|
||||
connection.onDidChangeConfiguration(async (_) => {
|
||||
the_lsp.reload_config();
|
||||
});
|
||||
|
||||
connection.onDidChangeTextDocument(async (param) => {
|
||||
await the_lsp.reload_document(param.contentChanges[param.contentChanges.length - 1].text, param.textDocument.uri, param.textDocument.version);
|
||||
});
|
||||
|
|
|
@ -46,6 +46,15 @@ function startClient(context: vscode.ExtensionContext) {
|
|||
return;
|
||||
});
|
||||
//client.onNotification(serverStatus, (params) => setServerStatus(params, statusBar));
|
||||
|
||||
vscode.workspace.onDidChangeConfiguration(async (ev) => {
|
||||
if (ev.affectsConfiguration("slint")) {
|
||||
await client.sendNotification("workspace/didChangeConfiguration", { settings: "" });
|
||||
if (previewUrl) {
|
||||
reload_preview(previewUrl, await getDocumentSource(previewUrl), previewComponent);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
};
|
||||
|
@ -66,12 +75,14 @@ function reload_preview(url: string, content: string, component: string) {
|
|||
previewAccessedFiles.clear();
|
||||
let webview_uri = previewPanel.webview.asWebviewUri(Uri.parse(url)).toString();
|
||||
previewAccessedFiles.add(webview_uri);
|
||||
const style = vscode.workspace.getConfiguration('slint').get<[string]>('preview.style');
|
||||
const msg = {
|
||||
command: "preview",
|
||||
base_url: url,
|
||||
webview_uri: webview_uri,
|
||||
component: component,
|
||||
content: content
|
||||
content: content,
|
||||
style: style,
|
||||
};
|
||||
if (previewBusy) {
|
||||
queuedPreviewMsg = msg;
|
||||
|
@ -179,8 +190,10 @@ function getPreviewHtml(slint_wasm_interpreter_url: Uri): string {
|
|||
return from_editor || await (await fetch(url)).text();
|
||||
}
|
||||
|
||||
async function render(source, base_url) {
|
||||
let { component, error_string } = await slint.compile_from_string(source, base_url, async(url) => await load_file(url));
|
||||
async function render(source, base_url, style) {
|
||||
let { component, error_string } =
|
||||
style ? await slint.compile_from_string_with_style(source, base_url, style, async(url) => await load_file(url))
|
||||
: await slint.compile_from_string(source, base_url, async(url) => await load_file(url));
|
||||
if (error_string != "") {
|
||||
var text = document.createTextNode(error_string);
|
||||
var p = document.createElement('pre');
|
||||
|
@ -203,7 +216,7 @@ function getPreviewHtml(slint_wasm_interpreter_url: Uri): string {
|
|||
window.addEventListener('message', async event => {
|
||||
if (event.data.command === "preview") {
|
||||
vscode.setState({base_url: event.data.base_url, component: event.data.component});
|
||||
await render(event.data.content, event.data.webview_uri);
|
||||
await render(event.data.content, event.data.webview_uri, event.data.style);
|
||||
} else if (event.data.command === "file_loaded") {
|
||||
let resolve = promises[event.data.url];
|
||||
if (resolve) {
|
||||
|
|
|
@ -165,6 +165,12 @@ export function activate(context: vscode.ExtensionContext) {
|
|||
const properties_provider = new PropertiesViewProvider(context.extensionUri);
|
||||
context.subscriptions.push(
|
||||
vscode.window.registerWebviewViewProvider(PropertiesViewProvider.viewType, properties_provider));
|
||||
|
||||
vscode.workspace.onDidChangeConfiguration(async (ev) => {
|
||||
if (ev.affectsConfiguration("slint")) {
|
||||
await client?.sendNotification("workspace/didChangeConfiguration", { settings: "" });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function deactivate(): Thenable<void> | undefined {
|
||||
|
|
|
@ -16,12 +16,16 @@ mod test;
|
|||
mod util;
|
||||
|
||||
use i_slint_compiler::CompilerConfiguration;
|
||||
use lsp_types::notification::{DidChangeTextDocument, DidOpenTextDocument, Notification};
|
||||
use lsp_types::notification::{
|
||||
DidChangeConfiguration, DidChangeTextDocument, DidOpenTextDocument, Notification,
|
||||
};
|
||||
use lsp_types::{DidChangeTextDocumentParams, DidOpenTextDocumentParams, InitializeParams};
|
||||
use server_loop::*;
|
||||
|
||||
use clap::Parser;
|
||||
use lsp_server::{Connection, Message, Request, Response};
|
||||
use lsp_server::{Connection, Message, RequestId, Response};
|
||||
use std::collections::HashMap;
|
||||
use std::sync::{atomic, Arc, Mutex};
|
||||
|
||||
#[derive(Clone, clap::Parser)]
|
||||
#[command(author, version, about, long_about = None)]
|
||||
|
@ -43,8 +47,15 @@ struct Cli {
|
|||
backend: String,
|
||||
}
|
||||
|
||||
type OutgoingRequestQueue = Arc<
|
||||
Mutex<HashMap<RequestId, Box<dyn FnOnce(lsp_server::Response, &mut DocumentCache) + Send>>>,
|
||||
>;
|
||||
|
||||
/// A handle that can be used to communicate with the client
|
||||
///
|
||||
/// This type is duplicated, with the same interface, in wasm_main.rs
|
||||
#[derive(Clone)]
|
||||
pub struct ServerNotifier(crossbeam_channel::Sender<Message>);
|
||||
pub struct ServerNotifier(crossbeam_channel::Sender<Message>, OutgoingRequestQueue);
|
||||
impl ServerNotifier {
|
||||
pub fn send_notification(
|
||||
&self,
|
||||
|
@ -54,9 +65,35 @@ impl ServerNotifier {
|
|||
self.0.send(Message::Notification(lsp_server::Notification::new(method, params)))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn send_request<T: lsp_types::request::Request>(
|
||||
&self,
|
||||
request: T::Params,
|
||||
f: impl FnOnce(Result<T::Result, String>, &mut DocumentCache) + Send + 'static,
|
||||
) -> Result<(), Error> {
|
||||
static REQ_ID: atomic::AtomicI32 = atomic::AtomicI32::new(0);
|
||||
let id = RequestId::from(REQ_ID.fetch_add(1, atomic::Ordering::Relaxed));
|
||||
let msg =
|
||||
Message::Request(lsp_server::Request::new(id.clone(), T::METHOD.to_string(), request));
|
||||
self.0.send(msg)?;
|
||||
self.1.lock().unwrap().insert(
|
||||
id,
|
||||
Box::new(move |r, c| {
|
||||
if let Some(r) = r.result {
|
||||
f(serde_json::from_value(r).map_err(|e| e.to_string()), c)
|
||||
} else if let Some(r) = r.error {
|
||||
f(Err(r.message), c)
|
||||
}
|
||||
}),
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub struct RequestHolder(Request, crossbeam_channel::Sender<Message>);
|
||||
/// The interface for a request received from the client
|
||||
///
|
||||
/// This type is duplicated, with the same interface, in wasm_main.rs
|
||||
pub struct RequestHolder(lsp_server::Request, ServerNotifier);
|
||||
impl RequestHolder {
|
||||
pub fn handle_request<
|
||||
Kind: lsp_types::request::Request,
|
||||
|
@ -76,9 +113,9 @@ impl RequestHolder {
|
|||
};
|
||||
|
||||
match f(param) {
|
||||
Ok(r) => self.1.send(Message::Response(Response::new_ok(id, r)))?,
|
||||
Ok(r) => self.1 .0.send(Message::Response(Response::new_ok(id, r)))?,
|
||||
Err(e) => {
|
||||
self.1.send(Message::Response(Response::new_err(id, 23, format!("{}", e))))?
|
||||
self.1 .0.send(Message::Response(Response::new_err(id, 23, format!("{}", e))))?
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -86,7 +123,7 @@ impl RequestHolder {
|
|||
}
|
||||
|
||||
pub fn server_notifier(&self) -> ServerNotifier {
|
||||
ServerNotifier(self.1.clone())
|
||||
self.1.clone()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -151,6 +188,12 @@ fn main_loop(connection: &Connection, params: serde_json::Value) -> Result<(), E
|
|||
compiler_config.include_paths = cli_args.include_paths;
|
||||
|
||||
let mut document_cache = DocumentCache::new(compiler_config);
|
||||
let request_queue = OutgoingRequestQueue::default();
|
||||
|
||||
let server_notifier = ServerNotifier(connection.sender.clone(), request_queue.clone());
|
||||
|
||||
load_configuration(&server_notifier)?;
|
||||
|
||||
for msg in &connection.receiver {
|
||||
match msg {
|
||||
Message::Request(req) => {
|
||||
|
@ -158,14 +201,21 @@ fn main_loop(connection: &Connection, params: serde_json::Value) -> Result<(), E
|
|||
return Ok(());
|
||||
}
|
||||
handle_request(
|
||||
RequestHolder(req, connection.sender.clone()),
|
||||
RequestHolder(req, server_notifier.clone()),
|
||||
¶ms,
|
||||
&mut document_cache,
|
||||
)?;
|
||||
}
|
||||
Message::Response(_resp) => {}
|
||||
Message::Response(resp) => {
|
||||
let f = request_queue
|
||||
.lock()
|
||||
.unwrap()
|
||||
.remove(&resp.id)
|
||||
.ok_or("Response to unknown request")?;
|
||||
f(resp, &mut document_cache);
|
||||
}
|
||||
Message::Notification(notification) => {
|
||||
handle_notification(connection, notification, &mut document_cache)?
|
||||
handle_notification(&server_notifier, notification, &mut document_cache)?
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -173,7 +223,7 @@ fn main_loop(connection: &Connection, params: serde_json::Value) -> Result<(), E
|
|||
}
|
||||
|
||||
pub fn handle_notification(
|
||||
connection: &Connection,
|
||||
connection: &ServerNotifier,
|
||||
req: lsp_server::Notification,
|
||||
document_cache: &mut DocumentCache,
|
||||
) -> Result<(), Error> {
|
||||
|
@ -181,7 +231,7 @@ pub fn handle_notification(
|
|||
DidOpenTextDocument::METHOD => {
|
||||
let params: DidOpenTextDocumentParams = serde_json::from_value(req.params)?;
|
||||
spin_on::spin_on(reload_document(
|
||||
&ServerNotifier(connection.sender.clone()),
|
||||
connection,
|
||||
params.text_document.text,
|
||||
params.text_document.uri,
|
||||
params.text_document.version,
|
||||
|
@ -191,19 +241,23 @@ pub fn handle_notification(
|
|||
DidChangeTextDocument::METHOD => {
|
||||
let mut params: DidChangeTextDocumentParams = serde_json::from_value(req.params)?;
|
||||
spin_on::spin_on(reload_document(
|
||||
&ServerNotifier(connection.sender.clone()),
|
||||
connection,
|
||||
params.content_changes.pop().unwrap().text,
|
||||
params.text_document.uri,
|
||||
params.text_document.version,
|
||||
document_cache,
|
||||
))?;
|
||||
}
|
||||
DidChangeConfiguration::METHOD => {
|
||||
load_configuration(connection)?;
|
||||
}
|
||||
|
||||
#[cfg(feature = "preview")]
|
||||
"slint/showPreview" => {
|
||||
show_preview_command(
|
||||
req.params.as_array().map_or(&[], |x| x.as_slice()),
|
||||
&ServerNotifier(connection.sender.clone()),
|
||||
connection,
|
||||
&document_cache.documents.compiler_config,
|
||||
)?;
|
||||
}
|
||||
_ => (),
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-commercial
|
||||
|
||||
use crate::lsp_ext::{Health, ServerStatusNotification, ServerStatusParams};
|
||||
use i_slint_compiler::CompilerConfiguration;
|
||||
use lsp_types::notification::Notification;
|
||||
use once_cell::sync::Lazy;
|
||||
use slint_interpreter::ComponentHandle;
|
||||
|
@ -152,6 +153,12 @@ pub struct PreviewComponent {
|
|||
/// The name of the component within that file.
|
||||
/// If None, then the last component is going to be shown.
|
||||
pub component: Option<String>,
|
||||
|
||||
/// The list of include paths
|
||||
pub include_paths: Vec<std::path::PathBuf>,
|
||||
|
||||
/// The style name for the preview
|
||||
pub style: String,
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
|
@ -178,6 +185,23 @@ pub fn set_contents(path: &Path, content: String) {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn config_changed(config: &CompilerConfiguration) {
|
||||
if let Some(cache) = CONTENT_CACHE.get() {
|
||||
let mut cache = cache.lock().unwrap();
|
||||
let style = config.style.clone().unwrap_or_default();
|
||||
if cache.current.style != style || cache.current.include_paths != config.include_paths {
|
||||
cache.current.style = style;
|
||||
cache.current.include_paths = config.include_paths.clone();
|
||||
let current = cache.current.clone();
|
||||
let sender = cache.sender.clone();
|
||||
drop(cache);
|
||||
if let Some(sender) = sender {
|
||||
load_preview(sender, current, PostLoadBehavior::DoNothing);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// If the file is in the cache, returns it.
|
||||
/// In any was, register it as a dependency
|
||||
fn get_file_from_cache(path: PathBuf) -> Option<String> {
|
||||
|
@ -201,15 +225,11 @@ async fn reload_preview(
|
|||
}
|
||||
|
||||
let mut builder = slint_interpreter::ComponentCompiler::default();
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
{
|
||||
use clap::Parser;
|
||||
let cli_args = super::Cli::parse();
|
||||
if !cli_args.style.is_empty() {
|
||||
builder.set_style(cli_args.style)
|
||||
};
|
||||
builder.set_include_paths(cli_args.include_paths);
|
||||
|
||||
if !preview_component.style.is_empty() {
|
||||
builder.set_style(preview_component.style);
|
||||
}
|
||||
builder.set_include_paths(preview_component.include_paths);
|
||||
|
||||
builder.set_file_loader(|path| {
|
||||
let path = path.to_owned();
|
||||
|
|
|
@ -178,7 +178,12 @@ pub fn handle_request(
|
|||
.and_then(|token| {
|
||||
#[cfg(feature = "preview")]
|
||||
if token.0.kind() == SyntaxKind::Comment {
|
||||
maybe_goto_preview(token.0, token.1, req.server_notifier());
|
||||
maybe_goto_preview(
|
||||
token.0,
|
||||
token.1,
|
||||
req.server_notifier(),
|
||||
&document_cache.documents.compiler_config,
|
||||
);
|
||||
return None;
|
||||
}
|
||||
goto::goto_definition(document_cache, token.0)
|
||||
|
@ -223,7 +228,11 @@ pub fn handle_request(
|
|||
#[cfg(any(feature = "preview", feature = "preview-lense"))]
|
||||
if params.command.as_str() == SHOW_PREVIEW_COMMAND {
|
||||
#[cfg(feature = "preview")]
|
||||
show_preview_command(¶ms.arguments, &req.server_notifier())?;
|
||||
show_preview_command(
|
||||
¶ms.arguments,
|
||||
&req.server_notifier(),
|
||||
&document_cache.documents.compiler_config,
|
||||
)?;
|
||||
return Ok(None::<serde_json::Value>);
|
||||
}
|
||||
if params.command.as_str() == QUERY_PROPERTIES_COMMAND {
|
||||
|
@ -279,6 +288,7 @@ pub fn handle_request(
|
|||
pub fn show_preview_command(
|
||||
params: &[serde_json::Value],
|
||||
connection: &crate::ServerNotifier,
|
||||
config: &CompilerConfiguration,
|
||||
) -> Result<(), Error> {
|
||||
use crate::preview;
|
||||
let e = || -> Error { "InvalidParameter".into() };
|
||||
|
@ -291,7 +301,12 @@ pub fn show_preview_command(
|
|||
let component = params.get(1).and_then(|v| v.as_str()).map(|v| v.to_string());
|
||||
preview::load_preview(
|
||||
connection.clone(),
|
||||
preview::PreviewComponent { path: path_canon, component },
|
||||
preview::PreviewComponent {
|
||||
path: path_canon,
|
||||
component,
|
||||
include_paths: config.include_paths.clone(),
|
||||
style: config.style.clone().unwrap_or_default(),
|
||||
},
|
||||
preview::PostLoadBehavior::ShowAfterLoad,
|
||||
);
|
||||
Ok(())
|
||||
|
@ -337,6 +352,7 @@ fn maybe_goto_preview(
|
|||
token: SyntaxToken,
|
||||
offset: u32,
|
||||
sender: crate::ServerNotifier,
|
||||
compiler_config: &CompilerConfiguration,
|
||||
) -> Option<()> {
|
||||
use crate::preview;
|
||||
let text = token.text();
|
||||
|
@ -362,6 +378,8 @@ fn maybe_goto_preview(
|
|||
preview::PreviewComponent {
|
||||
path: token.source_file.path().into(),
|
||||
component: Some(component_name),
|
||||
include_paths: compiler_config.include_paths.clone(),
|
||||
style: compiler_config.style.clone().unwrap_or_default(),
|
||||
},
|
||||
preview::PostLoadBehavior::ShowAfterLoad,
|
||||
);
|
||||
|
@ -687,6 +705,43 @@ fn get_code_lenses(
|
|||
}
|
||||
}
|
||||
|
||||
pub fn load_configuration(server_notifier: &crate::ServerNotifier) -> Result<(), Error> {
|
||||
server_notifier.send_request::<lsp_types::request::WorkspaceConfiguration>(
|
||||
lsp_types::ConfigurationParams {
|
||||
items: vec![lsp_types::ConfigurationItem {
|
||||
scope_uri: None,
|
||||
section: Some("slint".into()),
|
||||
}],
|
||||
},
|
||||
|result, document_cache| {
|
||||
if let Ok(r) = result {
|
||||
for v in r {
|
||||
if let Some(o) = v.as_object() {
|
||||
if let Some(ip) = o.get("includePath").and_then(|v| v.as_array()) {
|
||||
if !ip.is_empty() {
|
||||
document_cache.documents.compiler_config.include_paths = ip
|
||||
.iter()
|
||||
.filter_map(|x| x.as_str())
|
||||
.map(std::path::PathBuf::from)
|
||||
.collect();
|
||||
}
|
||||
}
|
||||
if let Some(style) =
|
||||
o.get("preview").and_then(|v| v.as_object()?.get("style")?.as_str())
|
||||
{
|
||||
if !style.is_empty() {
|
||||
document_cache.documents.compiler_config.style = Some(style.into());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "preview")]
|
||||
crate::preview::config_changed(&document_cache.documents.compiler_config);
|
||||
}
|
||||
},
|
||||
)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
|
|
@ -40,14 +40,42 @@ pub mod wasm_prelude {
|
|||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ServerNotifier(Function);
|
||||
pub struct ServerNotifier {
|
||||
send_notification: Function,
|
||||
send_request: Function,
|
||||
document_cache: Rc<RefCell<DocumentCache>>,
|
||||
reentry_guard: Rc<RefCell<ReentryGuard>>,
|
||||
}
|
||||
impl ServerNotifier {
|
||||
pub fn send_notification(&self, method: String, params: impl Serialize) -> Result<(), Error> {
|
||||
self.0
|
||||
self.send_notification
|
||||
.call2(&JsValue::UNDEFINED, &method.into(), &to_value(¶ms)?)
|
||||
.map_err(|x| format!("Error calling send_notification: {x:?}"))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn send_request<T: lsp_types::request::Request>(
|
||||
&self,
|
||||
request: T::Params,
|
||||
f: impl FnOnce(Result<T::Result, String>, &mut DocumentCache) + Send + 'static,
|
||||
) -> Result<(), Error> {
|
||||
let promise = self
|
||||
.send_request
|
||||
.call2(&JsValue::UNDEFINED, &T::METHOD.into(), &to_value(&request)?)
|
||||
.map_err(|x| format!("Error calling send_request: {x:?}"))?;
|
||||
let future = wasm_bindgen_futures::JsFuture::from(js_sys::Promise::from(promise));
|
||||
let document_cache = self.document_cache.clone();
|
||||
let guard = self.reentry_guard.clone();
|
||||
wasm_bindgen_futures::spawn_local(async move {
|
||||
let r = future
|
||||
.await
|
||||
.map_err(|e| format!("{e:?}"))
|
||||
.and_then(|v| serde_wasm_bindgen::from_value(v).map_err(|e| format!("{e:?}")));
|
||||
let _lock = ReentryGuard::lock(guard).await;
|
||||
f(r, &mut document_cache.borrow_mut());
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
|
@ -130,12 +158,16 @@ impl Drop for ReentryGuardLock {
|
|||
#[wasm_bindgen(typescript_custom_section)]
|
||||
const IMPORT_CALLBACK_FUNCTION_SECTION: &'static str = r#"
|
||||
type ImportCallbackFunction = (url: string) => Promise<string>;
|
||||
type SendRequestFunction = (method: string, r: any) => Promise<any>;
|
||||
"#;
|
||||
|
||||
#[wasm_bindgen]
|
||||
extern "C" {
|
||||
#[wasm_bindgen(typescript_type = "ImportCallbackFunction")]
|
||||
pub type ImportCallbackFunction;
|
||||
|
||||
#[wasm_bindgen(typescript_type = "SendRequestFunction")]
|
||||
pub type SendRequestFunction;
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
|
@ -150,6 +182,7 @@ pub struct SlintServer {
|
|||
pub fn create(
|
||||
init_param: JsValue,
|
||||
send_notification: Function,
|
||||
send_request: SendRequestFunction,
|
||||
load_file: ImportCallbackFunction,
|
||||
) -> Result<SlintServer, JsError> {
|
||||
console_error_panic_hook::set_once();
|
||||
|
@ -163,13 +196,20 @@ pub fn create(
|
|||
Box::pin(async move { Some(self::load_file(path, &load_file).await) })
|
||||
}));
|
||||
|
||||
let document_cache = DocumentCache::new(compiler_config);
|
||||
let document_cache = Rc::new(RefCell::new(DocumentCache::new(compiler_config)));
|
||||
let send_request = Function::from(send_request.clone());
|
||||
let reentry_guard = Rc::new(RefCell::new(ReentryGuard::default()));
|
||||
|
||||
Ok(SlintServer {
|
||||
document_cache: Rc::new(RefCell::new(document_cache)),
|
||||
document_cache: document_cache.clone(),
|
||||
init_param,
|
||||
notifier: ServerNotifier(send_notification),
|
||||
reentry_guard: Default::default(),
|
||||
notifier: ServerNotifier {
|
||||
send_notification,
|
||||
send_request,
|
||||
document_cache: document_cache.clone(),
|
||||
reentry_guard: reentry_guard.clone(),
|
||||
},
|
||||
reentry_guard,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -236,6 +276,17 @@ impl SlintServer {
|
|||
Ok(result.ok_or(JsError::new("Empty reply".into()))?)
|
||||
})
|
||||
}
|
||||
|
||||
#[wasm_bindgen]
|
||||
pub fn reload_config(&self) -> Result<(), JsError> {
|
||||
let guard = self.reentry_guard.clone();
|
||||
let notifier = self.notifier.clone();
|
||||
wasm_bindgen_futures::spawn_local(async move {
|
||||
let _lock = ReentryGuard::lock(guard).await;
|
||||
let _ = server_loop::load_configuration(¬ifier);
|
||||
});
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
async fn load_file(path: String, load_file: &Function) -> std::io::Result<String> {
|
||||
|
|
|
@ -23,12 +23,16 @@ slint_init().then((_) => {
|
|||
return true;
|
||||
}
|
||||
|
||||
async function send_request(method: string, params: any): Promise<any> {
|
||||
return await connection.sendRequest(method, params);
|
||||
}
|
||||
|
||||
async function load_file(path: string): Promise<string> {
|
||||
return await connection.sendRequest("slint/load_file", path);
|
||||
}
|
||||
|
||||
connection.onInitialize((params: InitializeParams): InitializeResult => {
|
||||
the_lsp = slint_lsp.create(params, send_notification, load_file);
|
||||
the_lsp = slint_lsp.create(params, send_notification, send_request, load_file);
|
||||
const response = the_lsp.server_initialize_result();
|
||||
response.capabilities.codeLensProvider = null; // CodeLenses are not relevant for the online editor
|
||||
return response;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue