mirror of
https://github.com/slint-ui/slint.git
synced 2025-10-22 08:12:48 +00:00
Keep all nodes for a given element (even if it is optimized out)
This commit is contained in:
parent
ffaf19812c
commit
09dc25f107
10 changed files with 40 additions and 36 deletions
|
@ -650,8 +650,10 @@ 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 node, if available
|
/// The AST nodes, if available.
|
||||||
pub node: Option<syntax_nodes::Element>,
|
/// 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.
|
||||||
|
pub node: Vec<syntax_nodes::Element>,
|
||||||
|
|
||||||
/// This element was a layout that has been lowered to a Rectangle
|
/// This element was a layout that has been lowered to a Rectangle
|
||||||
pub layout: Option<crate::layout::Layout>,
|
pub layout: Option<crate::layout::Layout>,
|
||||||
|
@ -659,11 +661,11 @@ pub struct Element {
|
||||||
|
|
||||||
impl Spanned for Element {
|
impl Spanned for Element {
|
||||||
fn span(&self) -> crate::diagnostics::Span {
|
fn span(&self) -> crate::diagnostics::Span {
|
||||||
self.node.as_ref().map(|n| n.span()).unwrap_or_default()
|
self.node.first().map(|n| n.span()).unwrap_or_default()
|
||||||
}
|
}
|
||||||
|
|
||||||
fn source_file(&self) -> Option<&crate::diagnostics::SourceFile> {
|
fn source_file(&self) -> Option<&crate::diagnostics::SourceFile> {
|
||||||
self.node.as_ref().map(|n| &n.source_file)
|
self.node.first().map(|n| &n.source_file)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -897,7 +899,7 @@ impl Element {
|
||||||
let mut r = Element {
|
let mut r = Element {
|
||||||
id,
|
id,
|
||||||
base_type,
|
base_type,
|
||||||
node: Some(node.clone()),
|
node: vec![node.clone()],
|
||||||
is_legacy_syntax,
|
is_legacy_syntax,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
@ -1632,7 +1634,7 @@ 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.node
|
||||||
.as_ref()
|
.first()
|
||||||
.and_then(|n| n.child_token(parser::SyntaxKind::Identifier))
|
.and_then(|n| n.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())
|
||||||
|
@ -1777,7 +1779,7 @@ fn animation_element_from_node(
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
let mut anim_element =
|
let mut anim_element =
|
||||||
Element { id: "".into(), base_type: anim_type, node: None, ..Default::default() };
|
Element { id: "".into(), base_type: anim_type, ..Default::default() };
|
||||||
anim_element.parse_bindings(
|
anim_element.parse_bindings(
|
||||||
anim.Binding().filter_map(|b| {
|
anim.Binding().filter_map(|b| {
|
||||||
Some((b.child_token(SyntaxKind::Identifier)?, b.BindingExpression().into()))
|
Some((b.child_token(SyntaxKind::Identifier)?, b.BindingExpression().into()))
|
||||||
|
|
|
@ -130,6 +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);
|
||||||
|
|
||||||
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() {
|
||||||
|
|
|
@ -22,6 +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));
|
||||||
|
|
||||||
let enclosing = parent.enclosing_component.upgrade().unwrap();
|
let enclosing = parent.enclosing_component.upgrade().unwrap();
|
||||||
|
|
||||||
|
|
|
@ -136,7 +136,7 @@ fn find_element_at_offset(component: &Rc<Component>, path: PathBuf, offset: u32)
|
||||||
if elem.borrow().repeated.is_some() {
|
if elem.borrow().repeated.is_some() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if let Some(node) = elem.borrow().node.as_ref().and_then(|n| n.QualifiedName()) {
|
for node in elem.borrow().node.iter().filter_map(|n| n.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());
|
||||||
}
|
}
|
||||||
|
|
|
@ -525,7 +525,7 @@ pub async fn set_binding_command(
|
||||||
element
|
element
|
||||||
.borrow()
|
.borrow()
|
||||||
.node
|
.node
|
||||||
.as_ref()
|
.first()
|
||||||
.ok_or("The element was found, but had no range defined!")?,
|
.ok_or("The element was found, but had no range defined!")?,
|
||||||
)
|
)
|
||||||
.ok_or("Failed to map node")?;
|
.ok_or("Failed to map node")?;
|
||||||
|
@ -608,7 +608,7 @@ pub async fn remove_binding_command(
|
||||||
element
|
element
|
||||||
.borrow()
|
.borrow()
|
||||||
.node
|
.node
|
||||||
.as_ref()
|
.first()
|
||||||
.ok_or("The element was found, but had no range defined!")?,
|
.ok_or("The element was found, but had no range defined!")?,
|
||||||
)
|
)
|
||||||
.ok_or("Failed to map node")?;
|
.ok_or("Failed to map node")?;
|
||||||
|
@ -755,7 +755,7 @@ 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.borrow().node.as_ref().map_or(false, |n| n.text_range().contains(offset.into()))
|
element.borrow().node.first().map_or(false, |n| n.text_range().contains(offset.into()))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn element_at_position(
|
pub fn element_at_position(
|
||||||
|
@ -1110,7 +1110,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.as_ref()?;
|
let element_node = root_element.node.first()?;
|
||||||
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() {
|
||||||
|
@ -1161,8 +1161,8 @@ fn get_document_symbols(
|
||||||
.filter_map(|child| {
|
.filter_map(|child| {
|
||||||
let e = child.borrow();
|
let e = child.borrow();
|
||||||
Some(DocumentSymbol {
|
Some(DocumentSymbol {
|
||||||
range: map_node(e.node.as_ref()?)?,
|
range: map_node(e.node.first()?)?,
|
||||||
selection_range: map_node(e.node.as_ref()?.QualifiedName().as_ref()?)?,
|
selection_range: map_node(e.node.first()?.QualifiedName().as_ref()?)?,
|
||||||
name: e.base_type.to_string(),
|
name: e.base_type.to_string(),
|
||||||
detail: (!e.id.is_empty()).then(|| e.id.clone()),
|
detail: (!e.id.is_empty()).then(|| e.id.clone()),
|
||||||
kind: lsp_types::SymbolKind::VARIABLE,
|
kind: lsp_types::SymbolKind::VARIABLE,
|
||||||
|
@ -1194,7 +1194,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.as_ref()?)?,
|
range: map_node(c.root_element.borrow().node.first()?)?,
|
||||||
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,
|
||||||
})
|
})
|
||||||
|
|
|
@ -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.as_ref()?)
|
goto_node(c.root_element.borrow().node.first()?)
|
||||||
}
|
}
|
||||||
_ => 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.clone()?.into(),
|
} => e.upgrade()?.borrow().node.first()?.clone().into(),
|
||||||
LookupResult::Expression {
|
LookupResult::Expression {
|
||||||
expression:
|
expression:
|
||||||
Expression::CallbackReference(nr, _)
|
Expression::CallbackReference(nr, _)
|
||||||
|
@ -107,7 +107,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())?;
|
||||||
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.as_ref()?),
|
Ok(ElementType::Component(c)) => goto_node(c.root_element.borrow().node.first()?),
|
||||||
_ => None,
|
_ => None,
|
||||||
};
|
};
|
||||||
} else if let Some(n) = syntax_nodes::ImportSpecifier::new(node.clone()) {
|
} else if let Some(n) = syntax_nodes::ImportSpecifier::new(node.clone()) {
|
||||||
|
|
|
@ -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.as_ref()?.text_range();
|
let element_range = element.node.first()?.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.as_ref() {
|
if let Some(element_node) = element.node.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,14 +390,14 @@ 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.as_ref();
|
let node = element.node.first()?;
|
||||||
|
|
||||||
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)?;
|
||||||
|
|
||||||
Some(lsp_types::Range::new(
|
Some(lsp_types::Range::new(
|
||||||
map_position(node?.source_file()?, open_brace.text_range().start()),
|
map_position(node.source_file()?, open_brace.text_range().start()),
|
||||||
map_position(node?.source_file()?, close_brace.text_range().end()),
|
map_position(node.source_file()?, close_brace.text_range().end()),
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -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.as_ref().and_then(|n| map_node(n)),
|
range: e.node.first().and_then(|n| map_node(n)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -628,7 +628,7 @@ fn set_binding_on_known_property(
|
||||||
// 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().node.as_ref().and_then(|n| n.first_token()).and_then(|t| t.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());
|
||||||
|
@ -658,7 +658,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.as_ref() {
|
if let Some(node) = element.node.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| {
|
||||||
|
@ -740,10 +740,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.as_ref().and_then(|n| n.source_file());
|
let source_file = element.node.first().and_then(|n| n.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.as_ref()?.token_at_offset(offset.into()).right_biased())
|
.and_then(|offset| element.node.first()?.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)
|
||||||
|
|
|
@ -26,7 +26,7 @@ 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();
|
||||||
e.node
|
e.node
|
||||||
.as_ref()
|
.first()
|
||||||
.and_then(|n| {
|
.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)
|
||||||
|
@ -77,7 +77,7 @@ fn select_element(component_instance: &ComponentInstance, selected_element: &Ele
|
||||||
}
|
}
|
||||||
|
|
||||||
fn element_offset(element: &ElementRc) -> Option<(PathBuf, u32)> {
|
fn element_offset(element: &ElementRc) -> Option<(PathBuf, u32)> {
|
||||||
let Some(node) = &element.borrow().node else {
|
let Some(node) = element.borrow().node.first().cloned() else {
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
let path = node.source_file.path().to_path_buf();
|
let path = node.source_file.path().to_path_buf();
|
||||||
|
@ -86,7 +86,7 @@ fn element_offset(element: &ElementRc) -> Option<(PathBuf, u32)> {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn element_source_range(element: &ElementRc) -> Option<(SourceFile, TextRange)> {
|
fn element_source_range(element: &ElementRc) -> Option<(SourceFile, TextRange)> {
|
||||||
let Some(node) = &element.borrow().node else {
|
let Some(node) = element.borrow().node.first().cloned() else {
|
||||||
return None;
|
return None;
|
||||||
};
|
};
|
||||||
let source_file = node.source_file.clone();
|
let source_file = node.source_file.clone();
|
||||||
|
@ -140,7 +140,7 @@ impl SelectionCandidate {
|
||||||
|
|
||||||
fn is_builtin(&self) -> bool {
|
fn is_builtin(&self) -> bool {
|
||||||
let elem = self.element.borrow();
|
let elem = self.element.borrow();
|
||||||
let Some(node) = &elem.node else {
|
let Some(node) = elem.node.first() else {
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
let Some(sf) = node.source_file() else {
|
let Some(sf) = node.source_file() else {
|
||||||
|
|
|
@ -152,7 +152,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.as_ref().map_or(false, |n| n.text_range().contains(offset))
|
c.borrow().node.first().map_or(false, |n| n.text_range().contains(offset))
|
||||||
}) {
|
}) {
|
||||||
it = c.clone();
|
it = c.clone();
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -222,7 +222,7 @@ fn visit_node(
|
||||||
.borrow()
|
.borrow()
|
||||||
.children
|
.children
|
||||||
.iter()
|
.iter()
|
||||||
.find(|c| c.borrow().node.as_ref().map_or(false, |n| n.node == node.node))
|
.find(|c| c.borrow().node.first().map_or(false, |n| n.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) {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue