interpreter: Return the ElementRc + index, not just the ElementRc

This way we do not have to check the ElementRc once more to find the node in
its debug data.
This commit is contained in:
Tobias Hunger 2024-03-20 12:50:43 +01:00 committed by Tobias Hunger
parent b4a20b2c47
commit 15fb452017
5 changed files with 56 additions and 43 deletions

View file

@ -1221,12 +1221,12 @@ impl ComponentInstance {
///
/// WARNING: this is not part of the public API
#[cfg(feature = "highlight")]
pub fn element_at_source_code_position(
pub fn element_node_at_source_code_position(
&self,
path: &Path,
offset: u32,
) -> Vec<i_slint_compiler::object_tree::ElementRc> {
crate::highlight::element_at_source_code_position(&self.inner, path, offset)
) -> Vec<(i_slint_compiler::object_tree::ElementRc, usize)> {
crate::highlight::element_node_at_source_code_position(&self.inner, path, offset)
}
}

View file

@ -37,10 +37,11 @@ pub(crate) fn component_positions(
generativity::make_guard!(guard);
let c = component_instance.unerase(guard);
let elements = find_element_at_offset(&c.description().original, path, offset);
let elements =
find_element_node_at_source_code_position(&c.description().original, path, offset);
collect_highlight_data(
component_instance,
&elements.into_iter().map(|e| Rc::downgrade(&e)).collect::<Vec<_>>(),
&elements.into_iter().map(|(e, _)| Rc::downgrade(&e)).collect::<Vec<_>>(),
)
}
@ -58,15 +59,15 @@ pub(crate) fn element_positions(
values
}
pub(crate) fn element_at_source_code_position(
pub(crate) fn element_node_at_source_code_position(
component_instance: &DynamicComponentVRc,
path: &Path,
offset: u32,
) -> Vec<ElementRc> {
) -> Vec<(ElementRc, usize)> {
generativity::make_guard!(guard);
let c = component_instance.unerase(guard);
find_element_at_offset(&c.description().original, path, offset)
find_element_node_at_source_code_position(&c.description().original, path, offset)
}
fn fill_highlight_data(
@ -113,8 +114,12 @@ fn fill_highlight_data(
}
// Go over all elements in original to find the one that is highlighted
fn find_element_at_offset(component: &Rc<Component>, path: &Path, offset: u32) -> Vec<ElementRc> {
let mut result = Vec::<ElementRc>::new();
fn find_element_node_at_source_code_position(
component: &Rc<Component>,
path: &Path,
offset: u32,
) -> Vec<(ElementRc, usize)> {
let mut result = Vec::new();
i_slint_compiler::object_tree::recurse_elem_including_sub_components(
component,
&(),
@ -122,9 +127,15 @@ fn find_element_at_offset(component: &Rc<Component>, path: &Path, offset: u32) -
if elem.borrow().repeated.is_some() {
return;
}
for node in elem.borrow().debug.iter().filter_map(|n| n.0.QualifiedName()) {
for (index, node) in elem
.borrow()
.debug
.iter()
.enumerate()
.filter_map(|(i, n)| n.0.QualifiedName().map(|n| (i, n)))
{
if node.source_file.path() == path && node.text_range().contains(offset.into()) {
result.push(elem.clone());
result.push((elem.clone(), index));
}
}
},

View file

@ -30,6 +30,12 @@ impl std::fmt::Debug for ElementRcNode {
}
impl ElementRcNode {
pub fn new(element: ElementRc, debug_index: usize) -> Option<Self> {
let _ = element.borrow().debug.get(debug_index)?;
Some(Self { element, debug_index })
}
pub fn find_in(element: ElementRc, path: &std::path::Path, offset: u32) -> Option<Self> {
let debug_index = element.borrow().debug.iter().position(|(n, _)| {
u32::from(n.text_range().start()) == offset && n.source_file.path() == path

View file

@ -1,7 +1,7 @@
// Copyright © SixtyFPS GmbH <info@slint.dev>
// SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-Slint-Royalty-free-1.1 OR LicenseRef-Slint-commercial
use crate::common::{self, ComponentInformation, PreviewComponent, PreviewConfig};
use crate::common::{self, ComponentInformation, ElementRcNode, PreviewComponent, PreviewConfig};
use crate::lsp_ext::Health;
use crate::preview::element_selection::ElementSelection;
use crate::util;
@ -423,24 +423,26 @@ pub fn load_preview(preview_component: PreviewComponent) {
if notify_editor {
if let Some(component_instance) = component_instance() {
if let Some(element) = component_instance
.element_at_source_code_position(&se.path, se.offset)
if let Some((element, debug_index)) = component_instance
.element_node_at_source_code_position(&se.path, se.offset)
.first()
{
if let Some((node, _)) =
element.borrow().debug.iter().find(|n| !is_element_node_ignored(&n.0))
{
let Some(element_node) = ElementRcNode::new(element.clone(), *debug_index)
else {
return;
};
let (path, pos) = element_node.with_element_node(|node| {
let sf = &node.source_file;
let pos = util::map_position(sf, se.offset.into());
(sf.path().to_owned(), util::map_position(sf, se.offset.into()))
});
ask_editor_to_show_document(
&se.path.to_string_lossy(),
&path.to_string_lossy(),
lsp_types::Range::new(pos, pos),
);
}
}
}
}
}
});
}
@ -534,29 +536,22 @@ pub fn highlight(url: Option<Url>, offset: u32) {
}
cache.highlight = highlight;
let selected = selected_element();
if cache.highlight.as_ref().map_or(true, |(url, _)| cache.dependency.contains(url)) {
run_in_ui_thread(move || async move {
let Some(component_instance) = component_instance() else {
return;
};
let Some(path) = url.and_then(|u| Url::to_file_path(&u).ok()) else {
return;
};
let elements = component_instance.element_at_source_code_position(&path, offset);
if let Some(e) = elements.first() {
let Some(debug_index) = e.borrow().debug.iter().position(|(n, _)| {
n.text_range().contains(offset.into()) && n.source_file.path() == path
}) else {
if Some((path.clone(), offset)) == selected.map(|s| (s.path, s.offset)) {
// Already selected!
return;
};
let is_layout =
e.borrow().debug.get(debug_index).map_or(false, |(_, l)| l.is_some());
element_selection::select_element_at_source_code_position(
path, offset, is_layout, None, false,
);
} else {
element_selection::unselect_element();
}
// TODO: false is wrong for is_layout here, but we will replace that soon anyway!
element_selection::select_element_at_source_code_position(
path, offset, false, None, false,
);
})
}
}

View file

@ -23,8 +23,9 @@ impl ElementSelection {
pub fn as_element(&self) -> Option<ElementRc> {
let component_instance = super::component_instance()?;
let elements = component_instance.element_at_source_code_position(&self.path, self.offset);
elements.get(self.instance_index).or_else(|| elements.first()).cloned()
let elements =
component_instance.element_node_at_source_code_position(&self.path, self.offset);
elements.get(self.instance_index).or_else(|| elements.first()).map(|(e, _)| e.clone())
}
pub fn as_element_node(&self) -> Option<ElementRcNode> {