diff options
author | Aleksey Kladov <[email protected]> | 2019-09-26 20:08:44 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2019-09-26 20:22:08 +0100 |
commit | d847d53e36571c8f7925b72cedf66bb203976148 (patch) | |
tree | 3fd5903b67b498a39660b2dafdc929f33d41900e /crates/ra_syntax/src/ast/edit.rs | |
parent | 1a4b42400544a652a053a34263967689d47f554b (diff) |
Start simplifying editing API
Diffstat (limited to 'crates/ra_syntax/src/ast/edit.rs')
-rw-r--r-- | crates/ra_syntax/src/ast/edit.rs | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/crates/ra_syntax/src/ast/edit.rs b/crates/ra_syntax/src/ast/edit.rs new file mode 100644 index 000000000..c65899812 --- /dev/null +++ b/crates/ra_syntax/src/ast/edit.rs | |||
@@ -0,0 +1,52 @@ | |||
1 | //! This module contains functions for editing syntax trees. As the trees are | ||
2 | //! immutable, all function here return a fresh copy of the tree, instead of | ||
3 | //! doing an in-place modification. | ||
4 | |||
5 | use arrayvec::ArrayVec; | ||
6 | use std::ops::RangeInclusive; | ||
7 | |||
8 | use crate::{ | ||
9 | algo, | ||
10 | ast::{self, make, AstNode}, | ||
11 | InsertPosition, SyntaxElement, | ||
12 | }; | ||
13 | |||
14 | impl ast::FnDef { | ||
15 | #[must_use] | ||
16 | pub fn with_body(&self, body: ast::Block) -> ast::FnDef { | ||
17 | let mut to_insert: ArrayVec<[SyntaxElement; 2]> = ArrayVec::new(); | ||
18 | let old_body_or_semi: SyntaxElement = if let Some(old_body) = self.body() { | ||
19 | old_body.syntax().clone().into() | ||
20 | } else if let Some(semi) = self.semicolon_token() { | ||
21 | to_insert.push(make::tokens::single_space().into()); | ||
22 | semi.into() | ||
23 | } else { | ||
24 | to_insert.push(make::tokens::single_space().into()); | ||
25 | to_insert.push(body.syntax().clone().into()); | ||
26 | return insert_children(self, InsertPosition::Last, to_insert.into_iter()); | ||
27 | }; | ||
28 | to_insert.push(body.syntax().clone().into()); | ||
29 | let replace_range = RangeInclusive::new(old_body_or_semi.clone(), old_body_or_semi); | ||
30 | replace_children(self, replace_range, to_insert.into_iter()) | ||
31 | } | ||
32 | } | ||
33 | |||
34 | #[must_use] | ||
35 | fn insert_children<N: AstNode>( | ||
36 | parent: &N, | ||
37 | position: InsertPosition<SyntaxElement>, | ||
38 | mut to_insert: impl Iterator<Item = SyntaxElement>, | ||
39 | ) -> N { | ||
40 | let new_syntax = algo::insert_children(parent.syntax(), position, &mut to_insert); | ||
41 | N::cast(new_syntax).unwrap() | ||
42 | } | ||
43 | |||
44 | #[must_use] | ||
45 | fn replace_children<N: AstNode>( | ||
46 | parent: &N, | ||
47 | to_replace: RangeInclusive<SyntaxElement>, | ||
48 | mut to_insert: impl Iterator<Item = SyntaxElement>, | ||
49 | ) -> N { | ||
50 | let new_syntax = algo::replace_children(parent.syntax(), to_replace, &mut to_insert); | ||
51 | N::cast(new_syntax).unwrap() | ||
52 | } | ||