diff options
author | Aleksey Kladov <[email protected]> | 2019-09-25 15:57:12 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2019-09-25 15:57:12 +0100 |
commit | a525e830a62272d21fbb0fb1c20bfa865791512d (patch) | |
tree | 528212ba4d092c961b68e3591f53988c5b5e6a7d /crates/ra_syntax/src/algo.rs | |
parent | a452e50e0e89390b8a055f0c7c64100e9872edac (diff) |
add new editing API, suitable for modifying several nodes at once
Diffstat (limited to 'crates/ra_syntax/src/algo.rs')
-rw-r--r-- | crates/ra_syntax/src/algo.rs | 32 |
1 files changed, 32 insertions, 0 deletions
diff --git a/crates/ra_syntax/src/algo.rs b/crates/ra_syntax/src/algo.rs index 7ee5aa85b..f0ed96a17 100644 --- a/crates/ra_syntax/src/algo.rs +++ b/crates/ra_syntax/src/algo.rs | |||
@@ -3,6 +3,7 @@ pub mod visit; | |||
3 | use std::ops::RangeInclusive; | 3 | use std::ops::RangeInclusive; |
4 | 4 | ||
5 | use itertools::Itertools; | 5 | use itertools::Itertools; |
6 | use rustc_hash::FxHashMap; | ||
6 | 7 | ||
7 | use crate::{ | 8 | use crate::{ |
8 | AstNode, Direction, NodeOrToken, SyntaxElement, SyntaxNode, SyntaxNodePtr, TextRange, TextUnit, | 9 | AstNode, Direction, NodeOrToken, SyntaxElement, SyntaxNode, SyntaxNodePtr, TextRange, TextUnit, |
@@ -123,6 +124,37 @@ pub fn replace_children( | |||
123 | with_children(parent, new_children) | 124 | with_children(parent, new_children) |
124 | } | 125 | } |
125 | 126 | ||
127 | /// Replaces descendants in the node, according to the mapping. | ||
128 | /// | ||
129 | /// This is a type-unsafe low-level editing API, if you need to use it, prefer | ||
130 | /// to create a type-safe abstraction on top of it instead. | ||
131 | pub fn replace_descendants( | ||
132 | parent: &SyntaxNode, | ||
133 | map: &FxHashMap<SyntaxElement, SyntaxElement>, | ||
134 | ) -> SyntaxNode { | ||
135 | // FIXME: this could be made much faster. | ||
136 | let new_children = parent.children_with_tokens().map(|it| go(map, it)).collect::<Box<[_]>>(); | ||
137 | return with_children(parent, new_children); | ||
138 | |||
139 | fn go( | ||
140 | map: &FxHashMap<SyntaxElement, SyntaxElement>, | ||
141 | element: SyntaxElement, | ||
142 | ) -> NodeOrToken<rowan::GreenNode, rowan::GreenToken> { | ||
143 | if let Some(replacement) = map.get(&element) { | ||
144 | return match replacement { | ||
145 | NodeOrToken::Node(it) => NodeOrToken::Node(it.green().clone()), | ||
146 | NodeOrToken::Token(it) => NodeOrToken::Token(it.green().clone()), | ||
147 | }; | ||
148 | } | ||
149 | match element { | ||
150 | NodeOrToken::Token(it) => NodeOrToken::Token(it.green().clone()), | ||
151 | NodeOrToken::Node(it) => { | ||
152 | NodeOrToken::Node(replace_descendants(&it, map).green().clone()) | ||
153 | } | ||
154 | } | ||
155 | } | ||
156 | } | ||
157 | |||
126 | fn with_children( | 158 | fn with_children( |
127 | parent: &SyntaxNode, | 159 | parent: &SyntaxNode, |
128 | new_children: Box<[NodeOrToken<rowan::GreenNode, rowan::GreenToken>]>, | 160 | new_children: Box<[NodeOrToken<rowan::GreenNode, rowan::GreenToken>]>, |