i_slint_compiler/passes/resolving/
remove_noop.rs1use crate::{diagnostics::BuildDiagnostics, expression_tree::Expression, parser::SyntaxNode};
5
6pub fn remove_from_codeblock(
12 code_block: &mut Vec<(SyntaxNode, Expression)>,
13 diagnostics: &mut BuildDiagnostics,
14) {
15 if code_block.len() > 1 {
16 for index in (0..(code_block.len() - 1)).rev() {
26 let (node, expression) = &code_block[index];
27 if without_side_effects(expression) {
28 diagnostics.push_warning("Expression has no effect!".to_owned(), node);
29 code_block.remove(index);
30 }
31 }
32 }
33}
34
35fn without_side_effects(expression: &Expression) -> bool {
41 match expression {
42 Expression::Condition { condition, true_expr, false_expr } => {
43 without_side_effects(condition)
44 && without_side_effects(true_expr)
45 && without_side_effects(false_expr)
46 }
47 Expression::NumberLiteral(_, _) => true,
48 Expression::StringLiteral(_) => true,
49 Expression::BoolLiteral(_) => true,
50 Expression::Keys(_) => true,
51 Expression::CodeBlock(expressions) => expressions.iter().all(without_side_effects),
52 Expression::FunctionParameterReference { .. } => true,
53 Expression::Invalid => false,
56 Expression::Uncompiled(_) => false,
57 Expression::PropertyReference(_) => false,
60 Expression::ElementReference(_) => false,
61 Expression::RepeaterIndexReference { .. } => true,
62 Expression::RepeaterModelReference { .. } => true,
63 Expression::StoreLocalVariable { .. } => false,
64 Expression::ReadLocalVariable { .. } => true,
65 Expression::StructFieldAccess { base, name: _ } => without_side_effects(base),
66 Expression::ArrayIndex { array, index } => {
67 without_side_effects(array) && without_side_effects(index)
68 }
69 Expression::Cast { from, to: _ } => without_side_effects(from),
72 Expression::FunctionCall { .. } => false,
76 Expression::SelfAssignment { .. } => false,
77 Expression::BinaryExpression { lhs, rhs, .. } => {
78 without_side_effects(lhs) && without_side_effects(rhs)
79 }
80 Expression::UnaryOp { sub, op: _ } => without_side_effects(sub),
81 Expression::ImageReference { .. } => true,
82 Expression::Array { element_ty: _, values } => values.iter().all(without_side_effects),
83 Expression::Struct { ty: _, values } => values.values().all(without_side_effects),
84 Expression::PathData(_) => true,
85 Expression::EasingCurve(_) => true,
86 Expression::LinearGradient { angle, stops } => {
87 without_side_effects(angle)
88 && stops
89 .iter()
90 .all(|(start, end)| without_side_effects(start) && without_side_effects(end))
91 }
92 Expression::RadialGradient { center, radius, stops } => {
93 center
94 .as_ref()
95 .is_none_or(|(cx, cy)| without_side_effects(cx) && without_side_effects(cy))
96 && radius.as_ref().is_none_or(|r| without_side_effects(r))
97 && stops
98 .iter()
99 .all(|(start, end)| without_side_effects(start) && without_side_effects(end))
100 }
101 Expression::ConicGradient { from_angle, center, stops } => {
102 without_side_effects(from_angle)
103 && center
104 .as_ref()
105 .is_none_or(|(cx, cy)| without_side_effects(cx) && without_side_effects(cy))
106 && stops
107 .iter()
108 .all(|(start, end)| without_side_effects(start) && without_side_effects(end))
109 }
110 Expression::EnumerationValue(_) => true,
111 Expression::ReturnStatement(_) => false,
114 Expression::LayoutCacheAccess { .. } => false,
115 Expression::GridRepeaterCacheAccess { .. } => false,
116 Expression::ComputeBoxLayoutInfo { .. } => false,
117 Expression::ComputeGridLayoutInfo { .. } => false,
118 Expression::OrganizeGridLayout(_) => false,
119 Expression::SolveBoxLayout(_, _) => false,
120 Expression::SolveGridLayout { .. } => false,
121 Expression::SolveFlexboxLayout(..) => false,
122 Expression::ComputeFlexboxLayoutInfo { .. } => false,
123 Expression::MinMax { ty: _, op: _, lhs, rhs } => {
124 without_side_effects(lhs) && without_side_effects(rhs)
125 }
126 Expression::DebugHook { .. } => false,
127 Expression::EmptyComponentFactory => false,
128 Expression::EmptyDataTransfer => false,
129 }
130}