mirror of
https://github.com/slint-ui/slint.git
synced 2025-10-22 00:02:40 +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
|
||||
pub inline_depth: i32,
|
||||
|
||||
/// The AST node, if available
|
||||
pub node: Option<syntax_nodes::Element>,
|
||||
/// The AST nodes, if available.
|
||||
/// 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
|
||||
pub layout: Option<crate::layout::Layout>,
|
||||
|
@ -659,11 +661,11 @@ pub struct Element {
|
|||
|
||||
impl Spanned for Element {
|
||||
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> {
|
||||
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 {
|
||||
id,
|
||||
base_type,
|
||||
node: Some(node.clone()),
|
||||
node: vec![node.clone()],
|
||||
is_legacy_syntax,
|
||||
..Default::default()
|
||||
};
|
||||
|
@ -1632,7 +1634,7 @@ impl Element {
|
|||
/// Returns the element's name as specified in the markup, not normalized.
|
||||
pub fn original_name(&self) -> String {
|
||||
self.node
|
||||
.as_ref()
|
||||
.first()
|
||||
.and_then(|n| n.child_token(parser::SyntaxKind::Identifier))
|
||||
.map(|n| n.to_string())
|
||||
.unwrap_or_else(|| self.id.clone())
|
||||
|
@ -1777,7 +1779,7 @@ fn animation_element_from_node(
|
|||
None
|
||||
} else {
|
||||
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.Binding().filter_map(|b| {
|
||||
Some((b.child_token(SyntaxKind::Identifier)?, b.BindingExpression().into()))
|
||||
|
|
|
@ -130,6 +130,7 @@ fn inline_element(
|
|||
}
|
||||
|
||||
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 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.node.extend(std::mem::take(&mut elem.borrow_mut().node));
|
||||
|
||||
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() {
|
||||
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()) {
|
||||
result.push(elem.clone());
|
||||
}
|
||||
|
|
|
@ -525,7 +525,7 @@ pub async fn set_binding_command(
|
|||
element
|
||||
.borrow()
|
||||
.node
|
||||
.as_ref()
|
||||
.first()
|
||||
.ok_or("The element was found, but had no range defined!")?,
|
||||
)
|
||||
.ok_or("Failed to map node")?;
|
||||
|
@ -608,7 +608,7 @@ pub async fn remove_binding_command(
|
|||
element
|
||||
.borrow()
|
||||
.node
|
||||
.as_ref()
|
||||
.first()
|
||||
.ok_or("The element was found, but had no range defined!")?,
|
||||
)
|
||||
.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 {
|
||||
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(
|
||||
|
@ -1110,7 +1110,7 @@ fn get_document_symbols(
|
|||
.iter()
|
||||
.filter_map(|c| {
|
||||
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 selection_range = map_node(&component_node.DeclaredIdentifier())?;
|
||||
if c.id.is_empty() {
|
||||
|
@ -1161,8 +1161,8 @@ fn get_document_symbols(
|
|||
.filter_map(|child| {
|
||||
let e = child.borrow();
|
||||
Some(DocumentSymbol {
|
||||
range: map_node(e.node.as_ref()?)?,
|
||||
selection_range: map_node(e.node.as_ref()?.QualifiedName().as_ref()?)?,
|
||||
range: map_node(e.node.first()?)?,
|
||||
selection_range: map_node(e.node.first()?.QualifiedName().as_ref()?)?,
|
||||
name: e.base_type.to_string(),
|
||||
detail: (!e.id.is_empty()).then(|| e.id.clone()),
|
||||
kind: lsp_types::SymbolKind::VARIABLE,
|
||||
|
@ -1194,7 +1194,7 @@ fn get_code_lenses(
|
|||
// Handle preview lens
|
||||
r.extend(inner_components.iter().filter(|c| !c.is_global()).filter_map(|c| {
|
||||
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())),
|
||||
data: None,
|
||||
})
|
||||
|
|
|
@ -37,7 +37,7 @@ pub fn goto_definition(
|
|||
let doc = document_cache.documents.get_document(node.source_file.path())?;
|
||||
match doc.local_registry.lookup_element(&qual.to_string()) {
|
||||
Ok(ElementType::Component(c)) => {
|
||||
goto_node(c.root_element.borrow().node.as_ref()?)
|
||||
goto_node(c.root_element.borrow().node.first()?)
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ pub fn goto_definition(
|
|||
LookupResult::Expression {
|
||||
expression: Expression::ElementReference(e),
|
||||
..
|
||||
} => e.upgrade()?.borrow().node.clone()?.into(),
|
||||
} => e.upgrade()?.borrow().node.first()?.clone().into(),
|
||||
LookupResult::Expression {
|
||||
expression:
|
||||
Expression::CallbackReference(nr, _)
|
||||
|
@ -107,7 +107,7 @@ pub fn goto_definition(
|
|||
let doc = document_cache.documents.get_document(node.source_file.path())?;
|
||||
let imp_name = i_slint_compiler::typeloader::ImportedName::from_node(n);
|
||||
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,
|
||||
};
|
||||
} 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> {
|
||||
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(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>) {
|
||||
if let Some(element_node) = element.node.as_ref() {
|
||||
if let Some(element_node) = element.node.first() {
|
||||
for prop_info in properties {
|
||||
if let Some(offset) = find_property_binding_offset(element, prop_info.name.as_str()) {
|
||||
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> {
|
||||
let element = element.borrow();
|
||||
let node = element.node.as_ref();
|
||||
let node = element.node.first()?;
|
||||
|
||||
let open_brace = node?.child_token(SyntaxKind::LBrace)?;
|
||||
let close_brace = node?.child_token(SyntaxKind::RBrace)?;
|
||||
let open_brace = node.child_token(SyntaxKind::LBrace)?;
|
||||
let close_brace = node.child_token(SyntaxKind::RBrace)?;
|
||||
|
||||
Some(lsp_types::Range::new(
|
||||
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()?, open_brace.text_range().start()),
|
||||
map_position(node.source_file()?, close_brace.text_range().end()),
|
||||
))
|
||||
}
|
||||
|
||||
|
@ -407,7 +407,7 @@ fn get_element_information(element: &ElementRc) -> ElementInformation {
|
|||
ElementInformation {
|
||||
id: e.id.clone(),
|
||||
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
|
||||
pub fn find_element_indent(element: &ElementRc) -> Option<String> {
|
||||
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 {
|
||||
if t.kind() == SyntaxKind::Whitespace && t.text().contains('\n') {
|
||||
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 element = element.borrow();
|
||||
if let Some(node) = element.node.as_ref() {
|
||||
if let Some(node) = element.node.first() {
|
||||
let expr_context_info =
|
||||
ExpressionContextInfo::new(node.clone(), property_name.to_string(), false);
|
||||
with_property_lookup_ctx(document_cache, &expr_context_info, |ctx| {
|
||||
|
@ -740,10 +740,10 @@ pub(crate) fn remove_binding(
|
|||
property_name: &str,
|
||||
) -> Result<lsp_types::WorkspaceEdit> {
|
||||
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)
|
||||
.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| {
|
||||
for ancestor in token.parent_ancestors() {
|
||||
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)> {
|
||||
let e = &element.borrow();
|
||||
e.node
|
||||
.as_ref()
|
||||
.first()
|
||||
.and_then(|n| {
|
||||
n.parent()
|
||||
.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)> {
|
||||
let Some(node) = &element.borrow().node else {
|
||||
let Some(node) = element.borrow().node.first().cloned() else {
|
||||
return None;
|
||||
};
|
||||
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)> {
|
||||
let Some(node) = &element.borrow().node else {
|
||||
let Some(node) = element.borrow().node.first().cloned() else {
|
||||
return None;
|
||||
};
|
||||
let source_file = node.source_file.clone();
|
||||
|
@ -140,7 +140,7 @@ impl SelectionCandidate {
|
|||
|
||||
fn is_builtin(&self) -> bool {
|
||||
let elem = self.element.borrow();
|
||||
let Some(node) = &elem.node else {
|
||||
let Some(node) = elem.node.first() else {
|
||||
return true;
|
||||
};
|
||||
let Some(sf) = node.source_file() else {
|
||||
|
|
|
@ -152,7 +152,7 @@ pub fn with_property_lookup_ctx<R>(
|
|||
loop {
|
||||
scope.push(it.clone());
|
||||
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();
|
||||
} else {
|
||||
|
|
|
@ -222,7 +222,7 @@ fn visit_node(
|
|||
.borrow()
|
||||
.children
|
||||
.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()
|
||||
} else if let Some(parent_co) = &state.current_component {
|
||||
if node.parent().map_or(false, |n| n.kind() == SyntaxKind::Component) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue