mirror of
https://github.com/slint-ui/slint.git
synced 2025-08-04 10:50:00 +00:00
lsp: Pass invalidation of files on to live-preview
This commit is contained in:
parent
e62d9e0695
commit
3d3bf9f01b
7 changed files with 65 additions and 14 deletions
|
@ -847,6 +847,18 @@ impl TypeLoader {
|
|||
myself
|
||||
}
|
||||
|
||||
pub fn drop_document(&mut self, path: &Path) -> Result<(), std::io::Error> {
|
||||
self.all_documents.docs.remove(path);
|
||||
if self.all_documents.currently_loading.contains_key(path) {
|
||||
Err(std::io::Error::new(
|
||||
std::io::ErrorKind::InvalidInput,
|
||||
format!("{path:?} is still loading"),
|
||||
))
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// Imports of files that don't have the .slint extension are returned.
|
||||
pub async fn load_dependencies_recursively<'a>(
|
||||
&'a mut self,
|
||||
|
@ -1016,6 +1028,17 @@ impl TypeLoader {
|
|||
}
|
||||
}
|
||||
|
||||
/// Read a file, taking the `CompilerConfiguration`s `open_import_fallback`
|
||||
/// into account when necessary.
|
||||
async fn read_file(&self, path: &Path) -> Result<String, std::io::Error> {
|
||||
if let Some(fallback) = self.compiler_config.open_import_fallback.clone() {
|
||||
let result = fallback(path.to_string_lossy().into()).await;
|
||||
result.unwrap_or_else(|| std::fs::read_to_string(path))
|
||||
} else {
|
||||
std::fs::read_to_string(path)
|
||||
}
|
||||
}
|
||||
|
||||
async fn ensure_document_loaded<'a: 'b, 'b>(
|
||||
state: &'a RefCell<BorrowedTypeLoader<'a>>,
|
||||
file_to_import: &'b str,
|
||||
|
@ -1097,14 +1120,8 @@ impl TypeLoader {
|
|||
core::str::from_utf8(builtin)
|
||||
.expect("internal error: embedded file is not UTF-8 source code"),
|
||||
))
|
||||
} else if let Some(fallback) = {
|
||||
let fallback = state.borrow().tl.compiler_config.open_import_fallback.clone();
|
||||
fallback
|
||||
} {
|
||||
let result = fallback(path_canon.to_string_lossy().into()).await;
|
||||
result.unwrap_or_else(|| std::fs::read_to_string(&path_canon))
|
||||
} else {
|
||||
std::fs::read_to_string(&path_canon)
|
||||
state.borrow().tl.read_file(&path_canon).await
|
||||
};
|
||||
|
||||
let ok = match source_code_result {
|
||||
|
|
|
@ -481,6 +481,7 @@ pub struct PreviewComponent {
|
|||
#[allow(unused)]
|
||||
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
|
||||
pub enum LspToPreviewMessage {
|
||||
InvalidateContents { url: lsp_types::Url },
|
||||
SetContents { url: VersionedUrl, contents: String },
|
||||
SetConfiguration { config: PreviewConfig },
|
||||
ShowPreview(PreviewComponent),
|
||||
|
|
|
@ -281,6 +281,11 @@ impl DocumentCache {
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn drop_document(&mut self, url: &Url) -> Result<()> {
|
||||
let path = uri_to_file(url).ok_or("Failed to convert path")?;
|
||||
Ok(self.type_loader.drop_document(&path)?)
|
||||
}
|
||||
|
||||
pub fn compiler_configuration(&self) -> CompilerConfiguration {
|
||||
CompilerConfiguration {
|
||||
include_paths: self.type_loader.compiler_config.include_paths.clone(),
|
||||
|
|
|
@ -614,7 +614,7 @@ pub async fn open_document(
|
|||
|
||||
pub async fn close_document(ctx: &Rc<Context>, url: lsp_types::Url) -> common::Result<()> {
|
||||
ctx.open_urls.borrow_mut().remove(&url);
|
||||
Ok(())
|
||||
invalidate_document(ctx, url).await
|
||||
}
|
||||
|
||||
pub async fn reload_document(
|
||||
|
@ -638,9 +638,18 @@ pub async fn reload_document(
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn trigger_file_watcher(ctx: &Context, url: &lsp_types::Url) -> common::Result<()> {
|
||||
if !ctx.open_urls.borrow().contains(url) {
|
||||
// do nothing for now...
|
||||
pub async fn invalidate_document(ctx: &Rc<Context>, url: lsp_types::Url) -> common::Result<()> {
|
||||
// The preview cares about resources and slint files, so forward everything
|
||||
ctx.server_notifier.send_message_to_preview(common::LspToPreviewMessage::InvalidateContents {
|
||||
url: url.clone(),
|
||||
});
|
||||
|
||||
ctx.document_cache.borrow_mut().drop_document(&url)
|
||||
}
|
||||
|
||||
pub async fn trigger_file_watcher(ctx: &Rc<Context>, url: lsp_types::Url) -> common::Result<()> {
|
||||
if !ctx.open_urls.borrow().contains(&url) {
|
||||
invalidate_document(ctx, url).await?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -460,7 +460,7 @@ async fn handle_notification(req: lsp_server::Notification, ctx: &Rc<Context>) -
|
|||
DidChangeWatchedFiles::METHOD => {
|
||||
let params: DidChangeWatchedFilesParams = serde_json::from_value(req.params)?;
|
||||
for fe in params.changes {
|
||||
trigger_file_watcher(ctx, &fe.uri).await?;
|
||||
trigger_file_watcher(ctx, fe.uri).await?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -17,6 +17,7 @@ use i_slint_core::model::VecModel;
|
|||
use lsp_types::Url;
|
||||
use slint::PlatformError;
|
||||
use slint_interpreter::{ComponentDefinition, ComponentHandle, ComponentInstance};
|
||||
use std::borrow::BorrowMut;
|
||||
use std::cell::RefCell;
|
||||
use std::collections::{HashMap, HashSet};
|
||||
use std::path::{Path, PathBuf};
|
||||
|
@ -124,6 +125,23 @@ pub fn poll_once<F: std::future::Future>(future: F) -> Option<F::Output> {
|
|||
}
|
||||
}
|
||||
|
||||
fn invalidate_contents(url: &lsp_types::Url) {
|
||||
let component = {
|
||||
let mut cache = CONTENT_CACHE.get_or_init(Default::default).lock().unwrap();
|
||||
|
||||
cache.source_code.remove(url);
|
||||
|
||||
(cache.dependency.contains(url) && cache.ui_is_visible)
|
||||
.then_some(cache.current_component())
|
||||
.flatten()
|
||||
};
|
||||
|
||||
// No need to bother with the document_cache: It follows the preview state at all times!
|
||||
if let Some(component) = component {
|
||||
load_preview(component, LoadBehavior::Reload);
|
||||
}
|
||||
}
|
||||
|
||||
fn set_contents(url: &common::VersionedUrl, content: String) {
|
||||
let mut cache = CONTENT_CACHE.get_or_init(Default::default).lock().unwrap();
|
||||
let old = cache.source_code.insert(url.url().clone(), (*url.version(), content.clone()));
|
||||
|
@ -960,7 +978,7 @@ fn finish_parsing(preview_url: &Url, ok: bool) {
|
|||
let mut preview_state = preview_state.borrow_mut();
|
||||
preview_state.known_components = components;
|
||||
|
||||
preview_state.document_cache.borrow_mut().replace(Rc::new(document_cache));
|
||||
preview_state.document_cache.borrow_mut().replace(Some(Rc::new(document_cache)));
|
||||
|
||||
if let Some(ui) = &preview_state.ui {
|
||||
ui::ui_set_uses_widgets(ui, uses_widgets);
|
||||
|
@ -1667,6 +1685,7 @@ fn update_preview_area(
|
|||
pub fn lsp_to_preview_message(message: crate::common::LspToPreviewMessage) {
|
||||
use crate::common::LspToPreviewMessage as M;
|
||||
match message {
|
||||
M::InvalidateContents { url } => invalidate_contents(&url),
|
||||
M::SetContents { url, contents } => {
|
||||
set_contents(&url, contents);
|
||||
}
|
||||
|
|
|
@ -338,7 +338,7 @@ impl SlintServer {
|
|||
wasm_bindgen_futures::future_to_promise(async move {
|
||||
let _lock = ReentryGuard::lock(guard).await;
|
||||
let url: lsp_types::Url = serde_wasm_bindgen::from_value(url)?;
|
||||
language::trigger_file_watcher(&ctx, &url)
|
||||
language::trigger_file_watcher(&ctx, url)
|
||||
.await
|
||||
.map_err(|e| JsError::new(&e.to_string()))?;
|
||||
Ok(JsValue::UNDEFINED)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue