Skip to main content

gobject_ast/model/statement/
if_stmt.rs

1use serde::Serialize;
2
3use crate::model::{BinaryExpression, Expression, SourceLocation, Statement};
4
5#[derive(Debug, Clone, Serialize)]
6pub struct IfStatement {
7    pub condition: Expression,
8    #[serde(skip_serializing_if = "Vec::is_empty")]
9    pub then_body: Vec<Statement>,
10    #[serde(skip_serializing_if = "std::ops::Not::not")]
11    pub then_has_braces: bool,
12    #[serde(skip_serializing_if = "Option::is_none")]
13    pub else_body: Option<Vec<Statement>>,
14    pub location: SourceLocation,
15}
16
17impl IfStatement {
18    /// Extract variable from NULL check patterns: (ptr != NULL), (NULL != ptr),
19    /// (ptr)
20    pub fn extract_null_check_variable(&self) -> Option<&str> {
21        match &self.condition {
22            Expression::Binary(bin) if bin.is_null_check() => bin.extract_compared_variable(),
23            expr => expr.extract_variable_name(),
24        }
25    }
26
27    /// Extract variable from non-zero check patterns: (id > 0), (id != 0),
28    /// (id), (self->id)
29    pub fn extract_nonzero_check_variable(&self) -> Option<&str> {
30        match &self.condition {
31            Expression::Binary(bin) => {
32                if is_nonzero_comparison(bin) {
33                    bin.extract_compared_variable()
34                } else {
35                    None
36                }
37            }
38            expr => expr.extract_variable_name(),
39        }
40    }
41
42    /// Check if condition is a simple truthiness test (just a variable)
43    pub fn is_truthiness_check(&self) -> bool {
44        matches!(&self.condition, Expression::Identifier(_))
45    }
46
47    /// Check if then body has exactly one statement
48    pub fn has_single_statement(&self) -> bool {
49        self.then_body.len() == 1
50    }
51
52    /// Check if else branch exists
53    pub fn has_else(&self) -> bool {
54        self.else_body.is_some()
55    }
56}
57
58/// Helper to check if binary expression is a non-zero comparison
59fn is_nonzero_comparison(bin: &BinaryExpression) -> bool {
60    match bin.operator.as_str() {
61        "!=" | ">" | "<" => {
62            // Check if comparing to 0
63            bin.left.is_zero() || bin.right.is_zero()
64        }
65        _ => false,
66    }
67}