Skip to content

Commit 67200c8

Browse files
committed
live-preview: Compile-test element moves in can_move function
Compile test the result of an element move in the `can_move` function to catch all cases where the move would be problematic. Shuffle some test code around to allow for testing this new functionality.
1 parent f55ef8f commit 67200c8

File tree

9 files changed

+317
-73
lines changed

9 files changed

+317
-73
lines changed

tools/lsp/common.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,11 @@ impl DocumentCache {
6262
Self(type_loader)
6363
}
6464

65+
pub fn snapshot(&self) -> Option<Self> {
66+
let type_loader = i_slint_compiler::typeloader::snapshot(&self.0)?;
67+
Some(Self::new_from_type_loader(type_loader))
68+
}
69+
6570
pub fn resolve_import_path(
6671
&self,
6772
import_token: Option<&i_slint_compiler::parser::NodeOrToken>,
@@ -82,7 +87,7 @@ impl DocumentCache {
8287
}
8388

8489
pub fn get_document_by_path(&self, path: &Path) -> Option<&Document> {
85-
self.0.get_document(&path)
90+
self.0.get_document(path)
8691
}
8792

8893
pub fn get_document_for_source_file(&self, source_file: &SourceFile) -> Option<&Document> {
@@ -408,7 +413,6 @@ pub fn create_workspace_edit_from_source_files(
408413
.entry((url, sf.version()))
409414
.and_modify(|v| v.push(edit.clone()))
410415
.or_insert_with(|| vec![edit]);
411-
} else {
412416
}
413417
});
414418

tools/lsp/common/rename_component.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -252,7 +252,7 @@ fn fix_exports(
252252

253253
if update_imports {
254254
let my_path = document_node.source_file.path();
255-
fix_imports(document_cache, &my_path, old_type, new_type, edits);
255+
fix_imports(document_cache, my_path, old_type, new_type, edits);
256256
}
257257
}
258258
}
@@ -310,7 +310,7 @@ pub fn rename_component_from_definition(
310310
if export_names.contains(&component_type) {
311311
let my_path = source_file.path();
312312

313-
fix_imports(document_cache, &my_path, &component_type, &new_name, &mut edits);
313+
fix_imports(document_cache, my_path, &component_type, &new_name, &mut edits);
314314
}
315315

316316
common::create_workspace_edit_from_source_files(edits)

tools/lsp/language.rs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -454,7 +454,7 @@ pub fn query_properties_command(
454454
.expect("Failed to serialize none-element property query result!"));
455455
};
456456

457-
if let Some(element) = element_at_position(&document_cache, &text_document_uri, &position) {
457+
if let Some(element) = element_at_position(document_cache, &text_document_uri, &position) {
458458
properties::query_properties(&text_document_uri, source_version, &element)
459459
.map(|r| serde_json::to_value(r).expect("Failed to serialize property query result!"))
460460
} else {
@@ -507,7 +507,7 @@ pub async fn set_binding_command(
507507
}
508508

509509
let element =
510-
element_at_position(&document_cache, &uri, &element_range.start).ok_or_else(|| {
510+
element_at_position(document_cache, &uri, &element_range.start).ok_or_else(|| {
511511
format!("No element found at the given start position {:?}", &element_range.start)
512512
})?;
513513

@@ -592,7 +592,7 @@ pub async fn remove_binding_command(
592592
}
593593

594594
let element =
595-
element_at_position(&document_cache, &uri, &element_range.start).ok_or_else(|| {
595+
element_at_position(document_cache, &uri, &element_range.start).ok_or_else(|| {
596596
format!("No element found at the given start position {:?}", &element_range.start)
597597
})?;
598598

@@ -707,7 +707,7 @@ fn get_document_and_offset<'a>(
707707
text_document_uri: &'_ Url,
708708
pos: &'_ Position,
709709
) -> Option<(&'a i_slint_compiler::object_tree::Document, u32)> {
710-
let doc = document_cache.get_document(&text_document_uri)?;
710+
let doc = document_cache.get_document(text_document_uri)?;
711711
let o = doc.node.as_ref()?.source_file.offset(pos.line as usize + 1, pos.character as usize + 1)
712712
as u32;
713713
doc.node.as_ref()?.text_range().contains_inclusive(o.into()).then_some((doc, o))
@@ -769,7 +769,7 @@ fn token_descr(
769769
text_document_uri: &Url,
770770
pos: &Position,
771771
) -> Option<(SyntaxToken, u32)> {
772-
let (doc, o) = get_document_and_offset(&document_cache, text_document_uri, pos)?;
772+
let (doc, o) = get_document_and_offset(document_cache, text_document_uri, pos)?;
773773
let node = doc.node.as_ref()?;
774774

775775
let token = token_at_offset(node, o)?;
@@ -874,7 +874,7 @@ fn get_code_actions(
874874
let text = token.text();
875875
completion::build_import_statements_edits(
876876
&token,
877-
&document_cache,
877+
document_cache,
878878
&mut |ci| !ci.is_global && ci.is_exported && ci.name == text,
879879
&mut |_name, file, edit| {
880880
result.push(CodeActionOrCommand::CodeAction(lsp_types::CodeAction {

tools/lsp/language/completion.rs

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -129,16 +129,16 @@ pub(crate) fn completion_at(
129129
}
130130

131131
if !is_global && snippet_support {
132-
add_components_to_import(&token, &document_cache, available_types, &mut r);
132+
add_components_to_import(&token, document_cache, available_types, &mut r);
133133
}
134134

135135
r
136136
});
137137
} else if let Some(n) = syntax_nodes::Binding::new(node.clone()) {
138138
if let Some(colon) = n.child_token(SyntaxKind::Colon) {
139139
if offset >= colon.text_range().end().into() {
140-
return with_lookup_ctx(&document_cache, node, |ctx| {
141-
resolve_expression_scope(ctx, &document_cache, snippet_support).map(Into::into)
140+
return with_lookup_ctx(document_cache, node, |ctx| {
141+
resolve_expression_scope(ctx, document_cache, snippet_support).map(Into::into)
142142
})?;
143143
}
144144
}
@@ -157,8 +157,8 @@ pub(crate) fn completion_at(
157157
if offset < double_arrow_range.end().into() {
158158
return None;
159159
}
160-
return with_lookup_ctx(&document_cache, node, |ctx| {
161-
resolve_expression_scope(ctx, &document_cache, snippet_support)
160+
return with_lookup_ctx(document_cache, node, |ctx| {
161+
resolve_expression_scope(ctx, document_cache, snippet_support)
162162
})?;
163163
} else if let Some(n) = syntax_nodes::CallbackConnection::new(node.clone()) {
164164
if token.kind() != SyntaxKind::Identifier {
@@ -230,8 +230,8 @@ pub(crate) fn completion_at(
230230
);
231231
}
232232

233-
return with_lookup_ctx(&document_cache, node, |ctx| {
234-
resolve_expression_scope(ctx, &document_cache, snippet_support).map(Into::into)
233+
return with_lookup_ctx(document_cache, node, |ctx| {
234+
resolve_expression_scope(ctx, document_cache, snippet_support).map(Into::into)
235235
})?;
236236
} else if let Some(q) = syntax_nodes::QualifiedName::new(node.clone()) {
237237
match q.parent()?.kind() {
@@ -263,7 +263,7 @@ pub(crate) fn completion_at(
263263

264264
if snippet_support {
265265
let available_types = result.iter().map(|c| c.label.clone()).collect();
266-
add_components_to_import(&token, &document_cache, available_types, &mut result);
266+
add_components_to_import(&token, document_cache, available_types, &mut result);
267267
}
268268

269269
return Some(result);
@@ -272,14 +272,14 @@ pub(crate) fn completion_at(
272272
return resolve_type_scope(token, document_cache).map(Into::into);
273273
}
274274
SyntaxKind::Expression => {
275-
return with_lookup_ctx(&document_cache, node, |ctx| {
275+
return with_lookup_ctx(document_cache, node, |ctx| {
276276
let it = q.children_with_tokens().filter_map(|t| t.into_token());
277277
let mut it = it.skip_while(|t| {
278278
t.kind() != SyntaxKind::Identifier && t.token != token.token
279279
});
280280
let first = it.next();
281281
if first.as_ref().map_or(true, |f| f.token == token.token) {
282-
return resolve_expression_scope(ctx, &document_cache, snippet_support)
282+
return resolve_expression_scope(ctx, document_cache, snippet_support)
283283
.map(Into::into);
284284
}
285285
let first = i_slint_compiler::parser::normalize_identifier(first?.text());
@@ -537,9 +537,7 @@ fn resolve_expression_scope(
537537
&token,
538538
document_cache,
539539
&mut |ci: &common::ComponentInformation| {
540-
if !ci.is_global || !ci.is_exported {
541-
false
542-
} else if available_types.contains(&ci.name) {
540+
if !ci.is_global || !ci.is_exported || available_types.contains(&ci.name) {
543541
false
544542
} else {
545543
available_types.insert(ci.name.clone());
@@ -676,9 +674,7 @@ fn add_components_to_import(
676674
token,
677675
document_cache,
678676
&mut |ci: &common::ComponentInformation| {
679-
if ci.is_global || !ci.is_exported {
680-
false
681-
} else if available_types.contains(&ci.name) {
677+
if ci.is_global || !ci.is_exported || available_types.contains(&ci.name) {
682678
false
683679
} else {
684680
available_types.insert(ci.name.clone());

tools/lsp/language/goto.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ pub fn goto_definition(
4646
if token.kind() != SyntaxKind::Identifier {
4747
return None;
4848
}
49-
let lr = with_lookup_ctx(&document_cache, node, |ctx| {
49+
let lr = with_lookup_ctx(document_cache, node, |ctx| {
5050
let mut it = n
5151
.children_with_tokens()
5252
.filter_map(|t| t.into_token())
@@ -188,7 +188,7 @@ fn find_property_declaration_in_base(
188188
let global_tr = document_cache.global_type_registry();
189189
let tr = element
190190
.source_file()
191-
.and_then(|sf| document_cache.get_document_for_source_file(&sf))
191+
.and_then(|sf| document_cache.get_document_for_source_file(sf))
192192
.map(|doc| &doc.local_registry)
193193
.unwrap_or(&global_tr);
194194

tools/lsp/language/properties.rs

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -628,7 +628,7 @@ pub fn set_binding(
628628
let expr_context_info = element.with_element_node(|node| {
629629
util::ExpressionContextInfo::new(node.clone(), property_name.to_string(), false)
630630
});
631-
util::with_property_lookup_ctx(&document_cache, &expr_context_info, |ctx| {
631+
util::with_property_lookup_ctx(document_cache, &expr_context_info, |ctx| {
632632
let expression =
633633
i_slint_compiler::expression_tree::Expression::from_binding_expression_node(
634634
expression_node,
@@ -721,14 +721,16 @@ pub fn set_bindings(
721721

722722
#[cfg(any(feature = "preview-external", feature = "preview-engine"))]
723723
fn element_at_source_code_position(
724-
dc: &mut language::DocumentCache,
724+
document_cache: &mut language::DocumentCache,
725725
position: &common::VersionedPosition,
726726
) -> Result<common::ElementRcNode> {
727-
if &dc.document_version(position.url()) != position.version() {
727+
if &document_cache.document_version(position.url()) != position.version() {
728728
return Err("Document version mismatch.".into());
729729
}
730730

731-
let doc = dc.get_document(position.url()).ok_or_else(|| "Document not found".to_string())?;
731+
let doc = document_cache
732+
.get_document(position.url())
733+
.ok_or_else(|| "Document not found".to_string())?;
732734

733735
let source_file = doc
734736
.node
@@ -737,9 +739,10 @@ fn element_at_source_code_position(
737739
.ok_or_else(|| "Document had no node".to_string())?;
738740
let element_position = util::map_position(&source_file, position.offset().into());
739741

740-
Ok(language::element_at_position(&dc, position.url(), &element_position).ok_or_else(|| {
741-
format!("No element found at the given start position {:?}", &element_position)
742-
})?)
742+
Ok(language::element_at_position(document_cache, position.url(), &element_position)
743+
.ok_or_else(|| {
744+
format!("No element found at the given start position {:?}", &element_position)
745+
})?)
743746
}
744747

745748
#[cfg(any(feature = "preview-external", feature = "preview-engine"))]

tools/lsp/preview.rs

Lines changed: 34 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -74,24 +74,23 @@ struct PreviewState {
7474
}
7575
thread_local! {static PREVIEW_STATE: std::cell::RefCell<PreviewState> = Default::default();}
7676

77-
// I will be needing this again soon...
78-
// struct DummyWaker();
77+
struct DummyWaker();
7978

80-
// impl std::task::Wake for DummyWaker {
81-
// fn wake(self: std::sync::Arc<Self>) {}
82-
// }
79+
impl std::task::Wake for DummyWaker {
80+
fn wake(self: std::sync::Arc<Self>) {}
81+
}
8382

84-
// pub fn poll_once<F: std::future::Future>(future: F) -> Option<F::Output> {
85-
// let waker = std::sync::Arc::new(DummyWaker()).into();
86-
// let mut ctx = std::task::Context::from_waker(&waker);
83+
pub fn poll_once<F: std::future::Future>(future: F) -> Option<F::Output> {
84+
let waker = std::sync::Arc::new(DummyWaker()).into();
85+
let mut ctx = std::task::Context::from_waker(&waker);
8786

88-
// let future = std::pin::pin!(future);
87+
let future = std::pin::pin!(future);
8988

90-
// match future.poll(&mut ctx) {
91-
// std::task::Poll::Ready(result) => Some(result),
92-
// std::task::Poll::Pending => None,
93-
// }
94-
// }
89+
match future.poll(&mut ctx) {
90+
std::task::Poll::Ready(result) => Some(result),
91+
std::task::Poll::Pending => None,
92+
}
93+
}
9594

9695
pub fn set_contents(url: &common::VersionedUrl, content: String) {
9796
let mut cache = CONTENT_CACHE.get_or_init(Default::default).lock().unwrap();
@@ -321,17 +320,20 @@ fn resize_selected_element_impl(rect: LogicalRect) {
321320
}
322321

323322
// triggered from the UI, running in UI thread
324-
fn can_move_selected_element(_x: f32, _y: f32, mouse_x: f32, mouse_y: f32) -> bool {
325-
// let position = LogicalPoint::new(x, y);
323+
fn can_move_selected_element(x: f32, y: f32, mouse_x: f32, mouse_y: f32) -> bool {
324+
let position = LogicalPoint::new(x, y);
326325
let mouse_position = LogicalPoint::new(mouse_x, mouse_y);
327326
let Some(selected) = selected_element() else {
328327
return false;
329328
};
330329
let Some(selected_element_node) = selected.as_element_node() else {
331330
return false;
332331
};
332+
let Some(document_cache) = document_cache() else {
333+
return false;
334+
};
333335

334-
drop_location::can_move_to(mouse_position, selected_element_node)
336+
drop_location::can_move_to(&document_cache, position, mouse_position, selected_element_node)
335337
}
336338

337339
// triggered from the UI, running in UI thread
@@ -344,10 +346,16 @@ fn move_selected_element(x: f32, y: f32, mouse_x: f32, mouse_y: f32) {
344346
let Some(selected_element_node) = selected.as_element_node() else {
345347
return;
346348
};
349+
let Some(document_cache) = document_cache() else {
350+
return;
351+
};
347352

348-
if let Some((edit, drop_data)) =
349-
drop_location::move_element_to(selected_element_node, position, mouse_position)
350-
{
353+
if let Some((edit, drop_data)) = drop_location::move_element_to(
354+
&document_cache,
355+
selected_element_node,
356+
position,
357+
mouse_position,
358+
) {
351359
element_selection::select_element_at_source_code_position(
352360
drop_data.path,
353361
drop_data.selection_offset,
@@ -817,6 +825,12 @@ fn document_cache() -> Option<common::DocumentCache> {
817825
))
818826
}
819827

828+
fn document_cache_from(component_instance: &ComponentInstance) -> Option<common::DocumentCache> {
829+
Some(common::DocumentCache::new_from_type_loader(
830+
component_instance.definition().raw_type_loader()?,
831+
))
832+
}
833+
820834
fn set_show_preview_ui(show_preview_ui: bool) {
821835
run_in_ui_thread(move || async move {
822836
PREVIEW_STATE.with(|preview_state| {

0 commit comments

Comments
 (0)