Skip to main content

luaur_analysis/functions/
block_diff_start.rs

1use luaur_ast::records::ast_array::AstArray;
2use luaur_ast::records::ast_node::AstNode;
3use luaur_ast::records::ast_stat::AstStat;
4use luaur_ast::records::ast_stat_block::AstStatBlock;
5use luaur_ast::records::position::Position;
6use luaur_ast::rtti::ast_node_is;
7use luaur_common::records::small_vector::SmallVector;
8
9pub fn block_diff_start(
10    block_old: *mut AstStatBlock,
11    block_new: *mut AstStatBlock,
12    nearest_statement_new_ast: *mut AstStat,
13) -> Option<Position> {
14    let block_old = unsafe { &*block_old };
15    let block_new = unsafe { &*block_new };
16
17    let _old = block_old.body;
18    let _new = block_new.body;
19    let old_size = _old.size;
20    let mut st_index: usize = 0;
21
22    // We couldn't find a nearest statement
23    if unsafe {
24        nearest_statement_new_ast as *mut AstNode
25            == &(*block_new).base.base as *const _ as *mut AstNode
26    } {
27        return None;
28    }
29
30    let mut found = false;
31    let mut i = 0;
32    while i < _new.size {
33        let st = unsafe { *_new.data.add(i) };
34        if st == nearest_statement_new_ast {
35            found = true;
36            st_index = i;
37            break;
38        }
39        i += 1;
40    }
41
42    if !found {
43        return None;
44    }
45
46    // Take care of some easy cases!
47    if old_size == 0 && _new.size >= 0 {
48        let first_stat = unsafe { *_new.data };
49        let location = unsafe { (*first_stat).base.location };
50        return Some(location.begin);
51    }
52
53    if _new.size < old_size {
54        return None;
55    }
56
57    let min_val = if old_size < st_index + 1 {
58        old_size
59    } else {
60        st_index + 1
61    };
62    let mut j = 0;
63    while j < min_val {
64        let old_stat = unsafe { *_old.data.add(j) };
65        let new_stat = unsafe { *_new.data.add(j) };
66
67        let is_same = unsafe {
68            (*old_stat).base.class_index == (*new_stat).base.class_index
69                && (*old_stat).base.location == (*new_stat).base.location
70        };
71        if !is_same {
72            let location = unsafe { (*old_stat).base.location };
73            return Some(location.begin);
74        }
75        j += 1;
76    }
77
78    if old_size <= st_index {
79        let stat_at_old_size = unsafe { *_new.data.add(old_size) };
80        let location = unsafe { (*stat_at_old_size).base.location };
81        return Some(location.begin);
82    }
83
84    None
85}