1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
#[cfg(not(target_arch = "wasm32"))]
mod native {
    use crate::{input_edit::InputEdit, language::Language, node::Node, range::Range, tree_cursor::TreeCursor};

    #[derive(Clone)]
    pub struct Tree {
        pub(crate) inner: tree_sitter::Tree,
    }

    impl Tree {
        pub fn edit(&mut self, edit: &InputEdit) {
            self.inner.edit(&edit.inner);
        }

        pub fn changed_ranges(&self, other: &Tree) -> impl ExactSizeIterator<Item = Range> {
            self.inner.changed_ranges(&other.inner).map(|inner| Range { inner })
        }

        pub fn language(&self) -> Language {
            self.inner.language().into()
        }

        pub fn root_node(&self) -> Node<'_> {
            self.inner.root_node().into()
        }

        pub fn walk(&self) -> TreeCursor<'_> {
            self.inner.walk().into()
        }
    }

    impl std::fmt::Debug for Tree {
        fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
            std::fmt::Debug::fmt(&self.inner, fmt)
        }
    }

    impl From<tree_sitter::Tree> for Tree {
        #[inline]
        fn from(inner: tree_sitter::Tree) -> Self {
            Self { inner }
        }
    }

    impl std::panic::RefUnwindSafe for Tree {
    }

    unsafe impl Send for Tree {
    }

    unsafe impl Sync for Tree {
    }

    impl Unpin for Tree {
    }

    impl std::panic::UnwindSafe for Tree {
    }
}

#[cfg(not(target_arch = "wasm32"))]
pub use native::*;

#[cfg(target_arch = "wasm32")]
mod wasm {
    use crate::{input_edit::InputEdit, language::Language, node::Node, range::Range, tree_cursor::TreeCursor};
    use wasm_bindgen::JsCast;

    pub struct Tree {
        pub(crate) inner: web_tree_sitter::Tree,
    }

    impl Tree {
        pub fn edit(&mut self, edit: &InputEdit) {
            let edit = {
                let start_index = edit.start_byte();
                let old_end_index = edit.old_end_byte();
                let new_end_index = edit.new_end_byte();
                let start_position = edit.start_position().inner;
                let old_end_position = edit.old_end_position().inner;
                let new_end_position = edit.new_end_position().inner;
                web_tree_sitter::Edit::new(
                    start_index,
                    old_end_index,
                    new_end_index,
                    &start_position,
                    &old_end_position,
                    &new_end_position,
                )
            };
            self.inner.edit(&edit);
        }

        // FIXME: implement bindings upstream first
        pub fn changed_ranges(&self, other: &Tree) -> impl ExactSizeIterator<Item = Range> {
            self.inner
                .get_changed_ranges(&other.inner)
                .into_vec()
                .into_iter()
                .map(|value| value.unchecked_into::<web_tree_sitter::Range>().into())
        }

        pub fn language(&self) -> Language {
            self.inner.get_language().into()
        }

        pub fn root_node(&self) -> Node<'_> {
            self.inner.root_node().into()
        }

        pub fn walk(&self) -> TreeCursor<'_> {
            self.inner.walk().into()
        }
    }

    impl Clone for Tree {
        fn clone(&self) -> Tree {
            self.inner.copy().into()
        }
    }

    impl std::fmt::Debug for Tree {
        fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
            std::fmt::Debug::fmt(&self.inner, fmt)
        }
    }

    impl Drop for Tree {
        fn drop(&mut self) {
            self.inner.delete();
        }
    }

    impl From<web_tree_sitter::Tree> for Tree {
        #[inline]
        fn from(inner: web_tree_sitter::Tree) -> Self {
            Self { inner }
        }
    }

    impl std::panic::RefUnwindSafe for Tree {
    }

    unsafe impl Send for Tree {
    }

    unsafe impl Sync for Tree {
    }

    impl Unpin for Tree {
    }

    impl std::panic::UnwindSafe for Tree {
    }
}

#[cfg(target_arch = "wasm32")]
pub use wasm::*;