Compiler: keep the layout debugging info next to its node

This commit is contained in:
Olivier Goffart 2024-02-21 10:53:20 +01:00
parent d65760e480
commit fac0921579
17 changed files with 97 additions and 83 deletions

View file

@ -538,7 +538,7 @@ impl Clone for PropertyAnimation {
property_analysis: e.property_analysis.clone(), property_analysis: e.property_analysis.clone(),
enclosing_component: e.enclosing_component.clone(), enclosing_component: e.enclosing_component.clone(),
repeated: None, repeated: None,
node: e.node.clone(), debug: e.debug.clone(),
..Default::default() ..Default::default()
})) }))
} }
@ -650,22 +650,23 @@ pub struct Element {
/// How many times the element was inlined /// How many times the element was inlined
pub inline_depth: i32, pub inline_depth: i32,
/// The AST nodes, if available. /// Debug information about this element.
///
/// Contains the AST node if available, as well as wether this element was a layout that had
/// been lowered into a rectangle in the lower_layouts pass.
/// There can be several in case of inlining or optimization (child merged into their parent). /// There can be several in case of inlining or optimization (child merged into their parent).
///
/// The order in the list is first the parent, and then the removed children. /// The order in the list is first the parent, and then the removed children.
pub node: Vec<syntax_nodes::Element>, pub debug: Vec<(syntax_nodes::Element, Option<crate::layout::Layout>)>,
/// This element was a layout that has been lowered to a Rectangle
pub layout: Option<crate::layout::Layout>,
} }
impl Spanned for Element { impl Spanned for Element {
fn span(&self) -> crate::diagnostics::Span { fn span(&self) -> crate::diagnostics::Span {
self.node.first().map(|n| n.span()).unwrap_or_default() self.debug.first().map(|n| n.0.span()).unwrap_or_default()
} }
fn source_file(&self) -> Option<&crate::diagnostics::SourceFile> { fn source_file(&self) -> Option<&crate::diagnostics::SourceFile> {
self.node.first().map(|n| &n.source_file) self.debug.first().map(|n| &n.0.source_file)
} }
} }
@ -899,7 +900,7 @@ impl Element {
let mut r = Element { let mut r = Element {
id, id,
base_type, base_type,
node: vec![node.clone()], debug: vec![(node.clone(), None)],
is_legacy_syntax, is_legacy_syntax,
..Default::default() ..Default::default()
}; };
@ -1633,9 +1634,9 @@ impl Element {
/// Returns the element's name as specified in the markup, not normalized. /// Returns the element's name as specified in the markup, not normalized.
pub fn original_name(&self) -> String { pub fn original_name(&self) -> String {
self.node self.debug
.first() .first()
.and_then(|n| n.child_token(parser::SyntaxKind::Identifier)) .and_then(|n| n.0.child_token(parser::SyntaxKind::Identifier))
.map(|n| n.to_string()) .map(|n| n.to_string())
.unwrap_or_else(|| self.id.clone()) .unwrap_or_else(|| self.id.clone())
} }
@ -2134,9 +2135,11 @@ pub fn visit_all_named_references_in_element(
let mut layout_info_prop = std::mem::take(&mut elem.borrow_mut().layout_info_prop); let mut layout_info_prop = std::mem::take(&mut elem.borrow_mut().layout_info_prop);
layout_info_prop.as_mut().map(|(h, b)| (vis(h), vis(b))); layout_info_prop.as_mut().map(|(h, b)| (vis(h), vis(b)));
elem.borrow_mut().layout_info_prop = layout_info_prop; elem.borrow_mut().layout_info_prop = layout_info_prop;
let mut layout = std::mem::take(&mut elem.borrow_mut().layout); let mut debug = std::mem::take(&mut elem.borrow_mut().debug);
layout.as_mut().map(|l| l.visit_named_references(&mut vis)); for d in debug.iter_mut() {
elem.borrow_mut().layout = layout; d.1.as_mut().map(|l| l.visit_named_references(&mut vis));
}
elem.borrow_mut().debug = debug;
let mut accessibility_props = std::mem::take(&mut elem.borrow_mut().accessibility_props); let mut accessibility_props = std::mem::take(&mut elem.borrow_mut().accessibility_props);
accessibility_props.0.iter_mut().for_each(|(_, x)| vis(x)); accessibility_props.0.iter_mut().for_each(|(_, x)| vis(x));

View file

@ -51,8 +51,8 @@ pub fn ensure_window(
is_flickable_viewport: false, is_flickable_viewport: false,
item_index: Default::default(), item_index: Default::default(),
item_index_of_first_children: Default::default(), item_index_of_first_children: Default::default(),
node: std::mem::take(&mut win_elem_mut.node), debug: std::mem::take(&mut win_elem_mut.debug),
layout: win_elem_mut.layout.clone(),
inline_depth: 0, inline_depth: 0,
is_legacy_syntax: false, is_legacy_syntax: false,
}; };

View file

@ -130,7 +130,7 @@ fn inline_element(
} }
elem_mut.children = new_children; elem_mut.children = new_children;
elem_mut.node.extend_from_slice(&inlined_component.root_element.borrow().node); elem_mut.debug.extend_from_slice(&inlined_component.root_element.borrow().debug);
if let ElementType::Component(c) = &mut elem_mut.base_type { if let ElementType::Component(c) = &mut elem_mut.base_type {
if c.parent_element.upgrade().is_some() { if c.parent_element.upgrade().is_some() {
@ -264,8 +264,7 @@ fn duplicate_element_with_mapping(
.collect(), .collect(),
repeated: elem.repeated.clone(), repeated: elem.repeated.clone(),
is_component_placeholder: elem.is_component_placeholder, is_component_placeholder: elem.is_component_placeholder,
node: elem.node.clone(), debug: elem.debug.clone(),
layout: elem.layout.clone(),
enclosing_component: Rc::downgrade(root_component), enclosing_component: Rc::downgrade(root_component),
states: elem.states.clone(), states: elem.states.clone(),
transitions: elem transitions: elem

View file

@ -36,7 +36,7 @@ fn process_component_container(element: &ElementRc, empty_type: &ElementType) {
let embedded_element = Element::make_rc(Element { let embedded_element = Element::make_rc(Element {
base_type: empty_type.clone(), base_type: empty_type.clone(),
id: elem.id.clone(), id: elem.id.clone(),
node: elem.node.clone(), debug: elem.debug.clone(),
enclosing_component: elem.enclosing_component.clone(), enclosing_component: elem.enclosing_component.clone(),
default_fill_parent: (true, true), default_fill_parent: (true, true),
is_legacy_syntax: elem.is_legacy_syntax, is_legacy_syntax: elem.is_legacy_syntax,

View file

@ -246,7 +246,9 @@ fn lower_grid_layout(
); );
grid_layout_element.borrow_mut().layout_info_prop = grid_layout_element.borrow_mut().layout_info_prop =
Some((layout_info_prop_h, layout_info_prop_v)); Some((layout_info_prop_h, layout_info_prop_v));
grid_layout_element.borrow_mut().layout = Some(Layout::GridLayout(grid)); if let Some(d) = grid_layout_element.borrow_mut().debug.last_mut() {
d.1 = Some(Layout::GridLayout(grid));
}
} }
impl GridLayout { impl GridLayout {
@ -434,7 +436,9 @@ fn lower_box_layout(
.into(), .into(),
); );
layout_element.borrow_mut().layout_info_prop = Some((layout_info_prop_h, layout_info_prop_v)); layout_element.borrow_mut().layout_info_prop = Some((layout_info_prop_h, layout_info_prop_v));
layout_element.borrow_mut().layout = Some(Layout::BoxLayout(layout)); if let Some(d) = layout_element.borrow_mut().debug.last_mut() {
d.1 = Some(Layout::BoxLayout(layout));
}
} }
fn lower_dialog_layout( fn lower_dialog_layout(
@ -645,7 +649,9 @@ fn lower_dialog_layout(
.into(), .into(),
); );
dialog_element.borrow_mut().layout_info_prop = Some((layout_info_prop_h, layout_info_prop_v)); dialog_element.borrow_mut().layout_info_prop = Some((layout_info_prop_h, layout_info_prop_v));
dialog_element.borrow_mut().layout = Some(Layout::GridLayout(grid)); if let Some(d) = dialog_element.borrow_mut().debug.last_mut() {
d.1 = Some(Layout::GridLayout(grid));
}
} }
struct CreateLayoutItemResult { struct CreateLayoutItemResult {

View file

@ -22,7 +22,7 @@ pub fn optimize_useless_rectangles(root_component: &Rc<Component>) {
} }
parent.children.extend(std::mem::take(&mut elem.borrow_mut().children)); parent.children.extend(std::mem::take(&mut elem.borrow_mut().children));
parent.node.extend(std::mem::take(&mut elem.borrow_mut().node)); parent.debug.extend(std::mem::take(&mut elem.borrow_mut().debug));
let enclosing = parent.enclosing_component.upgrade().unwrap(); let enclosing = parent.enclosing_component.upgrade().unwrap();

View file

@ -36,8 +36,7 @@ fn create_repeater_components(component: &Rc<Component>) {
named_references: Default::default(), named_references: Default::default(),
repeated: None, repeated: None,
is_component_placeholder: false, is_component_placeholder: false,
node: elem.node.clone(), debug: elem.debug.clone(),
layout: elem.layout.clone(),
enclosing_component: Default::default(), enclosing_component: Default::default(),
states: std::mem::take(&mut elem.states), states: std::mem::take(&mut elem.states),
transitions: std::mem::take(&mut elem.transitions), transitions: std::mem::take(&mut elem.transitions),

View file

@ -126,7 +126,11 @@ fn fill_highlight_data(
let size = geometry.size; let size = geometry.size;
if values.kind.is_none() { if values.kind.is_none() {
values.kind = if element.borrow().layout.is_some() { // FIXME: this visualization is misleading because it will highlight as a layout any
// optimized rectangle within a layout or parent of a layout.
// Example: `foo := Rectangle { lay := SomeLayout { ... } } ` lay will be optimized into foo
// and so both foo and lay will be considered as layout (assuming SomeLayout inherits from a layout)
values.kind = if element.borrow().debug.iter().any(|d| d.1.is_some()) {
Some(ComponentKind::Layout) Some(ComponentKind::Layout)
} else { } else {
Some(ComponentKind::Element) Some(ComponentKind::Element)
@ -147,7 +151,7 @@ fn find_element_at_offset(component: &Rc<Component>, path: &Path, offset: u32) -
if elem.borrow().repeated.is_some() { if elem.borrow().repeated.is_some() {
return; return;
} }
for node in elem.borrow().node.iter().filter_map(|n| n.QualifiedName()) { for node in elem.borrow().debug.iter().filter_map(|n| n.0.QualifiedName()) {
if node.source_file.path() == path && node.text_range().contains(offset.into()) { if node.source_file.path() == path && node.text_range().contains(offset.into()) {
result.push(elem.clone()); result.push(elem.clone());
} }

View file

@ -567,11 +567,12 @@ pub async fn set_binding_command(
})?; })?;
let node_range = map_node( let node_range = map_node(
element &element
.borrow() .borrow()
.node .debug
.first() .first()
.ok_or("The element was found, but had no range defined!")?, .ok_or("The element was found, but had no range defined!")?
.0,
) )
.ok_or("Failed to map node")?; .ok_or("Failed to map node")?;
@ -650,11 +651,12 @@ pub async fn remove_binding_command(
})?; })?;
let node_range = map_node( let node_range = map_node(
element &element
.borrow() .borrow()
.node .debug
.first() .first()
.ok_or("The element was found, but had no range defined!")?, .ok_or("The element was found, but had no range defined!")?
.0,
) )
.ok_or("Failed to map node")?; .ok_or("Failed to map node")?;
@ -802,10 +804,9 @@ fn get_document_and_offset<'a>(
fn element_contains(element: &i_slint_compiler::object_tree::ElementRc, offset: u32) -> bool { fn element_contains(element: &i_slint_compiler::object_tree::ElementRc, offset: u32) -> bool {
element element
.borrow() .borrow()
.node .debug
.first() .iter()
.and_then(|n| n.parent()) .any(|n| n.0.parent().map_or(false, |n| n.text_range().contains(offset.into())))
.map_or(false, |n| n.text_range().contains(offset.into()))
} }
pub fn element_at_position( pub fn element_at_position(
@ -1146,7 +1147,7 @@ fn get_document_symbols(
.iter() .iter()
.filter_map(|c| { .filter_map(|c| {
let root_element = c.root_element.borrow(); let root_element = c.root_element.borrow();
let element_node = root_element.node.first()?; let element_node = &root_element.debug.first()?.0;
let component_node = syntax_nodes::Component::new(element_node.parent()?)?; let component_node = syntax_nodes::Component::new(element_node.parent()?)?;
let selection_range = map_node(&component_node.DeclaredIdentifier())?; let selection_range = map_node(&component_node.DeclaredIdentifier())?;
if c.id.is_empty() { if c.id.is_empty() {
@ -1196,7 +1197,7 @@ fn get_document_symbols(
.iter() .iter()
.filter_map(|child| { .filter_map(|child| {
let e = child.borrow(); let e = child.borrow();
let element_node = e.node.first()?; let element_node = &e.debug.first()?.0;
let sub_element_node = element_node.parent()?; let sub_element_node = element_node.parent()?;
debug_assert_eq!(sub_element_node.kind(), SyntaxKind::SubElement); debug_assert_eq!(sub_element_node.kind(), SyntaxKind::SubElement);
Some(DocumentSymbol { Some(DocumentSymbol {
@ -1233,7 +1234,7 @@ fn get_code_lenses(
// Handle preview lens // Handle preview lens
r.extend(inner_components.iter().filter(|c| !c.is_global()).filter_map(|c| { r.extend(inner_components.iter().filter(|c| !c.is_global()).filter_map(|c| {
Some(CodeLens { Some(CodeLens {
range: map_node(c.root_element.borrow().node.first()?)?, range: map_node(&c.root_element.borrow().debug.first()?.0)?,
command: Some(create_show_preview_command(true, &text_document.uri, c.id.as_str())), command: Some(create_show_preview_command(true, &text_document.uri, c.id.as_str())),
data: None, data: None,
}) })

View file

@ -37,7 +37,7 @@ pub fn goto_definition(
let doc = document_cache.documents.get_document(node.source_file.path())?; let doc = document_cache.documents.get_document(node.source_file.path())?;
match doc.local_registry.lookup_element(&qual.to_string()) { match doc.local_registry.lookup_element(&qual.to_string()) {
Ok(ElementType::Component(c)) => { Ok(ElementType::Component(c)) => {
goto_node(c.root_element.borrow().node.first()?) goto_node(&c.root_element.borrow().debug.first()?.0)
} }
_ => None, _ => None,
} }
@ -68,7 +68,7 @@ pub fn goto_definition(
LookupResult::Expression { LookupResult::Expression {
expression: Expression::ElementReference(e), expression: Expression::ElementReference(e),
.. ..
} => e.upgrade()?.borrow().node.first()?.clone().into(), } => e.upgrade()?.borrow().debug.first()?.0.clone().into(),
LookupResult::Expression { LookupResult::Expression {
expression: expression:
Expression::CallbackReference(nr, _) Expression::CallbackReference(nr, _)
@ -107,7 +107,9 @@ pub fn goto_definition(
let doc = document_cache.documents.get_document(node.source_file.path())?; let doc = document_cache.documents.get_document(node.source_file.path())?;
let imp_name = i_slint_compiler::typeloader::ImportedName::from_node(n); let imp_name = i_slint_compiler::typeloader::ImportedName::from_node(n);
return match doc.local_registry.lookup_element(&imp_name.internal_name) { return match doc.local_registry.lookup_element(&imp_name.internal_name) {
Ok(ElementType::Component(c)) => goto_node(c.root_element.borrow().node.first()?), Ok(ElementType::Component(c)) => {
goto_node(&c.root_element.borrow().debug.first()?.0)
}
_ => None, _ => None,
}; };
} else if let Some(n) = syntax_nodes::ImportSpecifier::new(node.clone()) { } else if let Some(n) = syntax_nodes::ImportSpecifier::new(node.clone()) {

View file

@ -234,7 +234,7 @@ fn find_expression_range(
} }
fn find_property_binding_offset(element: &Element, property_name: &str) -> Option<u32> { fn find_property_binding_offset(element: &Element, property_name: &str) -> Option<u32> {
let element_range = element.node.first()?.text_range(); let element_range = element.debug.first()?.0.text_range();
if let Some(v) = element.bindings.get(property_name) { if let Some(v) = element.bindings.get(property_name) {
if let Some(span) = &v.borrow().span { if let Some(span) = &v.borrow().span {
@ -252,7 +252,7 @@ fn find_property_binding_offset(element: &Element, property_name: &str) -> Optio
} }
fn insert_property_definitions(element: &Element, properties: &mut Vec<PropertyInformation>) { fn insert_property_definitions(element: &Element, properties: &mut Vec<PropertyInformation>) {
if let Some(element_node) = element.node.first() { if let Some((element_node, _)) = element.debug.first() {
for prop_info in properties { for prop_info in properties {
if let Some(offset) = find_property_binding_offset(element, prop_info.name.as_str()) { if let Some(offset) = find_property_binding_offset(element, prop_info.name.as_str()) {
prop_info.defined_at = find_expression_range(element_node, offset); prop_info.defined_at = find_expression_range(element_node, offset);
@ -390,7 +390,7 @@ fn get_properties(element: &ElementRc) -> Vec<PropertyInformation> {
fn find_block_range(element: &ElementRc) -> Option<lsp_types::Range> { fn find_block_range(element: &ElementRc) -> Option<lsp_types::Range> {
let element = element.borrow(); let element = element.borrow();
let node = element.node.first()?; let node = &element.debug.first()?.0;
let open_brace = node.child_token(SyntaxKind::LBrace)?; let open_brace = node.child_token(SyntaxKind::LBrace)?;
let close_brace = node.child_token(SyntaxKind::RBrace)?; let close_brace = node.child_token(SyntaxKind::RBrace)?;
@ -407,7 +407,7 @@ fn get_element_information(element: &ElementRc) -> ElementInformation {
ElementInformation { ElementInformation {
id: e.id.clone(), id: e.id.clone(),
type_name: e.base_type.to_string(), type_name: e.base_type.to_string(),
range: e.node.first().and_then(|n| map_node(n)), range: e.debug.first().and_then(|n| map_node(&n.0)),
} }
} }
@ -622,7 +622,7 @@ pub(crate) fn set_binding(
let new_expression_type = { let new_expression_type = {
let element = element.borrow(); let element = element.borrow();
if let Some(node) = element.node.first() { if let Some((node, _)) = &element.debug.first() {
let expr_context_info = let expr_context_info =
ExpressionContextInfo::new(node.clone(), property_name.to_string(), false); ExpressionContextInfo::new(node.clone(), property_name.to_string(), false);
with_property_lookup_ctx(document_cache, &expr_context_info, |ctx| { with_property_lookup_ctx(document_cache, &expr_context_info, |ctx| {
@ -734,10 +734,10 @@ pub(crate) fn remove_binding(
property_name: &str, property_name: &str,
) -> Result<lsp_types::WorkspaceEdit> { ) -> Result<lsp_types::WorkspaceEdit> {
let element = element.borrow(); let element = element.borrow();
let source_file = element.node.first().and_then(|n| n.source_file()); let source_file = &element.debug.first().and_then(|n| n.0.source_file());
let range = find_property_binding_offset(&element, property_name) let range = find_property_binding_offset(&element, property_name)
.and_then(|offset| element.node.first()?.token_at_offset(offset.into()).right_biased()) .and_then(|offset| element.debug.first()?.0.token_at_offset(offset.into()).right_biased())
.and_then(|token| { .and_then(|token| {
for ancestor in token.parent_ancestors() { for ancestor in token.parent_ancestors() {
if (ancestor.kind() == SyntaxKind::Binding) if (ancestor.kind() == SyntaxKind::Binding)

View file

@ -422,12 +422,11 @@ pub fn load_preview(preview_component: PreviewComponent) {
.element_at_source_code_position(&se.path, se.offset) .element_at_source_code_position(&se.path, se.offset)
.first() .first()
{ {
if let Some(node) = element if let Some((node, _)) = element
.borrow() .borrow()
.node .debug
.iter() .iter()
.filter(|n| !crate::common::is_element_node_ignored(n)) .find(|n| !crate::common::is_element_node_ignored(&n.0))
.next()
{ {
let sf = &node.source_file; let sf = &node.source_file;
let pos = map_position(sf, se.offset.into()); let pos = map_position(sf, se.offset.into());
@ -544,7 +543,14 @@ pub fn highlight(url: Option<Url>, offset: u32) {
}; };
let elements = component_instance.element_at_source_code_position(&path, offset); let elements = component_instance.element_at_source_code_position(&path, offset);
if let Some(e) = elements.first() { if let Some(e) = elements.first() {
let is_layout = e.borrow().layout.is_some(); let is_layout = e
.borrow()
.debug
.iter()
.find(|(node, _)| {
node.text_range().contains(offset.into()) && node.source_file.path() == path
})
.map_or(false, |d| d.1.is_some());
element_selection::select_element_at_source_code_position( element_selection::select_element_at_source_code_position(
path, offset, is_layout, None, false, path, offset, is_layout, None, false,
); );

View file

@ -168,7 +168,7 @@ fn recurse_into_element(state: &mut State, element: &ElementRc) -> (usize, Vec<S
fn add_element_node(state: &mut State, element: &ElementRc, node_number: usize) { fn add_element_node(state: &mut State, element: &ElementRc, node_number: usize) {
let e = element.borrow(); let e = element.borrow();
let layout = if e.layout.is_some() { ",shape = box" } else { "" }; let layout = if e.debug.iter().any(|d| d.1.is_some()) { ",shape = box" } else { "" };
let repeated = if e.repeated.is_some() { ",color = blue" } else { "" }; let repeated = if e.repeated.is_some() { ",color = blue" } else { "" };
let component = if matches!(e.base_type, i_slint_compiler::langtype::ElementType::Component(_)) let component = if matches!(e.base_type, i_slint_compiler::langtype::ElementType::Component(_))
{ {

View file

@ -25,22 +25,21 @@ fn find_drop_location(
let (node_index, target_element) = elements.iter().find_map(|sc| { let (node_index, target_element) = elements.iter().find_map(|sc| {
sc.element sc.element
.borrow() .borrow()
.node .debug
.iter() .iter()
.enumerate() .position(|d| !crate::common::is_element_node_ignored(&d.0))
.filter(|(_, n)| !crate::common::is_element_node_ignored(n)) .map(|i| (i, sc.element.clone()))
.next()
.map(|(i, _)| (i, sc.element.clone()))
})?; })?;
let insertion_position = { let insertion_position = {
let elem = target_element.borrow(); let elem = target_element.borrow();
if elem.layout.is_some() { let (node, layout) = elem.debug.get(node_index)?;
if layout.is_some() {
return None; return None;
} }
let node = elem.node.get(node_index)?;
let last_token = crate::util::last_non_ws_token(node)?; let last_token = crate::util::last_non_ws_token(node)?;
let url = lsp_types::Url::from_file_path(node.source_file.path()).ok()?; let url = lsp_types::Url::from_file_path(node.source_file.path()).ok()?;

View file

@ -42,19 +42,16 @@ fn self_or_embedded_component_root(element: &ElementRc) -> ElementRc {
fn lsp_element_position(element: &ElementRc) -> Option<(String, lsp_types::Range)> { fn lsp_element_position(element: &ElementRc) -> Option<(String, lsp_types::Range)> {
let e = element.borrow(); let e = element.borrow();
let location = e let location = e.debug.iter().find(|e| !crate::common::is_element_node_ignored(&e.0)).and_then(
.node |(n, _)| {
.iter()
.filter(|e| !crate::common::is_element_node_ignored(*e))
.next()
.and_then(|n| {
n.parent() n.parent()
.filter(|p| p.kind() == i_slint_compiler::parser::SyntaxKind::SubElement) .filter(|p| p.kind() == i_slint_compiler::parser::SyntaxKind::SubElement)
.map_or_else( .map_or_else(
|| Some(n.source_file.text_size_to_file_line_column(n.text_range().start())), || Some(n.source_file.text_size_to_file_line_column(n.text_range().start())),
|p| Some(p.source_file.text_size_to_file_line_column(p.text_range().start())), |p| Some(p.source_file.text_size_to_file_line_column(p.text_range().start())),
) )
}); },
);
location.map(|(f, sl, sc, el, ec)| { location.map(|(f, sl, sc, el, ec)| {
use lsp_types::{Position, Range}; use lsp_types::{Position, Range};
let start = Position::new((sl as u32).saturating_sub(1), (sc as u32).saturating_sub(1)); let start = Position::new((sl as u32).saturating_sub(1), (sc as u32).saturating_sub(1));
@ -132,7 +129,8 @@ fn select_element(
component_instance, component_instance,
path, path,
offset, offset,
selected_element.borrow().layout.is_some(), // FIXME: need to check which one of the node this refer to to know if this is a layout
selected_element.borrow().debug.iter().any(|d| d.1.is_some()),
position, position,
false, // We update directly;-) false, // We update directly;-)
); );
@ -146,16 +144,14 @@ fn select_element(
} }
fn element_offset(element: &ElementRc) -> Option<(PathBuf, u32)> { fn element_offset(element: &ElementRc) -> Option<(PathBuf, u32)> {
let Some(node) = element.borrow().node.first().cloned() else { let node = element.borrow().debug.first()?.0.clone();
return None;
};
let path = node.source_file.path().to_path_buf(); let path = node.source_file.path().to_path_buf();
let offset = node.text_range().start().into(); let offset = node.text_range().start().into();
Some((path, offset)) Some((path, offset))
} }
fn element_source_range(element: &ElementRc) -> Option<(SourceFile, TextRange)> { fn element_source_range(element: &ElementRc) -> Option<(SourceFile, TextRange)> {
let node = element.borrow().node.first().cloned()?; let node = element.borrow().debug.first()?.0.clone();
let source_file = node.source_file.clone(); let source_file = node.source_file.clone();
let range = node.text_range(); let range = node.text_range();
Some((source_file, range)) Some((source_file, range))
@ -164,7 +160,7 @@ fn element_source_range(element: &ElementRc) -> Option<(SourceFile, TextRange)>
// Return the real root element, skipping any WindowElement that got added // Return the real root element, skipping any WindowElement that got added
pub fn root_element(component_instance: &ComponentInstance) -> ElementRc { pub fn root_element(component_instance: &ComponentInstance) -> ElementRc {
let root_element = component_instance.definition().root_component().root_element.clone(); let root_element = component_instance.definition().root_component().root_element.clone();
if !root_element.borrow().node.is_empty() { if !root_element.borrow().debug.is_empty() {
return root_element; return root_element;
} }
let child = root_element.borrow().children.first().cloned(); let child = root_element.borrow().children.first().cloned();
@ -192,10 +188,10 @@ impl SelectionCandidate {
pub fn is_builtin(&self) -> bool { pub fn is_builtin(&self) -> bool {
let elem = self.element.borrow(); let elem = self.element.borrow();
let Some(node) = elem.node.first() else { let Some(node) = elem.debug.first() else {
return true; return true;
}; };
let Some(sf) = node.source_file() else { let Some(sf) = node.0.source_file() else {
return true; return true;
}; };
sf.path().starts_with("builtin:/") sf.path().starts_with("builtin:/")

View file

@ -60,8 +60,7 @@ pub fn last_non_ws_token(node: &SyntaxNode) -> Option<SyntaxToken> {
// Find the indentation of the element itself as well as the indentation of properties inside the // Find the indentation of the element itself as well as the indentation of properties inside the
// element. Returns the element indent followed by the block indent // element. Returns the element indent followed by the block indent
pub fn find_element_indent(element: &ElementRc) -> Option<String> { pub fn find_element_indent(element: &ElementRc) -> Option<String> {
let mut token = let mut token = element.borrow().debug.first()?.0.first_token()?.prev_token();
element.borrow().node.first().and_then(|n| n.first_token()).and_then(|t| t.prev_token());
while let Some(t) = token { while let Some(t) = token {
if t.kind() == SyntaxKind::Whitespace && t.text().contains('\n') { if t.kind() == SyntaxKind::Whitespace && t.text().contains('\n') {
return t.text().split('\n').last().map(|s| s.to_owned()); return t.text().split('\n').last().map(|s| s.to_owned());
@ -180,7 +179,7 @@ pub fn with_property_lookup_ctx<R>(
loop { loop {
scope.push(it.clone()); scope.push(it.clone());
if let Some(c) = it.clone().borrow().children.iter().find(|c| { if let Some(c) = it.clone().borrow().children.iter().find(|c| {
c.borrow().node.first().map_or(false, |n| n.text_range().contains(offset)) c.borrow().debug.first().map_or(false, |n| n.0.text_range().contains(offset))
}) { }) {
it = c.clone(); it = c.clone();
} else { } else {

View file

@ -222,7 +222,7 @@ fn visit_node(
.borrow() .borrow()
.children .children
.iter() .iter()
.find(|c| c.borrow().node.first().map_or(false, |n| n.node == node.node)) .find(|c| c.borrow().debug.first().map_or(false, |n| n.0.node == node.node))
.cloned() .cloned()
} else if let Some(parent_co) = &state.current_component { } else if let Some(parent_co) = &state.current_component {
if node.parent().map_or(false, |n| n.kind() == SyntaxKind::Component) { if node.parent().map_or(false, |n| n.kind() == SyntaxKind::Component) {