@@ -138,19 +138,21 @@ impl SnippetEdit {
138138 . into_iter ( )
139139 . zip ( 1 ..)
140140 . with_position ( )
141- . map ( |pos| {
141+ . flat_map ( |pos| {
142142 let ( snippet, index) = match pos {
143143 ( itertools:: Position :: First , it) | ( itertools:: Position :: Middle , it) => it,
144144 // last/only snippet gets index 0
145145 ( itertools:: Position :: Last , ( snippet, _) )
146146 | ( itertools:: Position :: Only , ( snippet, _) ) => ( snippet, 0 ) ,
147147 } ;
148148
149- let range = match snippet {
150- Snippet :: Tabstop ( pos) => TextRange :: empty ( pos) ,
151- Snippet :: Placeholder ( range) => range,
152- } ;
153- ( index, range)
149+ match snippet {
150+ Snippet :: Tabstop ( pos) => vec ! [ ( index, TextRange :: empty( pos) ) ] ,
151+ Snippet :: Placeholder ( range) => vec ! [ ( index, range) ] ,
152+ Snippet :: PlaceholderGroup ( ranges) => {
153+ ranges. into_iter ( ) . map ( |range| ( index, range) ) . collect ( )
154+ }
155+ }
154156 } )
155157 . collect_vec ( ) ;
156158
@@ -248,7 +250,7 @@ impl SourceChangeBuilder {
248250 fn commit ( & mut self ) {
249251 let snippet_edit = self . snippet_builder . take ( ) . map ( |builder| {
250252 SnippetEdit :: new (
251- builder. places . into_iter ( ) . map ( PlaceSnippet :: finalize_position) . collect_vec ( ) ,
253+ builder. places . into_iter ( ) . flat_map ( PlaceSnippet :: finalize_position) . collect ( ) ,
252254 )
253255 } ) ;
254256
@@ -356,6 +358,17 @@ impl SourceChangeBuilder {
356358 self . add_snippet ( PlaceSnippet :: Over ( node. syntax ( ) . clone ( ) . into ( ) ) )
357359 }
358360
361+ /// Adds a snippet to move the cursor selected over `nodes`
362+ ///
363+ /// This allows for renaming newly generated items without having to go
364+ /// through a separate rename step.
365+ pub fn add_placeholder_snippet_group ( & mut self , _cap : SnippetCap , nodes : Vec < SyntaxNode > ) {
366+ assert ! ( nodes. iter( ) . all( |node| node. parent( ) . is_some( ) ) ) ;
367+ self . add_snippet ( PlaceSnippet :: OverGroup (
368+ nodes. into_iter ( ) . map ( |node| node. into ( ) ) . collect ( ) ,
369+ ) )
370+ }
371+
359372 fn add_snippet ( & mut self , snippet : PlaceSnippet ) {
360373 let snippet_builder = self . snippet_builder . get_or_insert ( SnippetBuilder { places : vec ! [ ] } ) ;
361374 snippet_builder. places . push ( snippet) ;
@@ -400,6 +413,13 @@ pub enum Snippet {
400413 Tabstop ( TextSize ) ,
401414 /// A placeholder snippet (e.g. `${0:placeholder}`).
402415 Placeholder ( TextRange ) ,
416+ /// A group of placeholder snippets, e.g.
417+ ///
418+ /// ```no_run
419+ /// let ${0:new_var} = 4;
420+ /// fun(1, 2, 3, ${0:new_var});
421+ /// ```
422+ PlaceholderGroup ( Vec < TextRange > ) ,
403423}
404424
405425enum PlaceSnippet {
@@ -409,14 +429,20 @@ enum PlaceSnippet {
409429 After ( SyntaxElement ) ,
410430 /// Place a placeholder snippet in place of the element
411431 Over ( SyntaxElement ) ,
432+ /// Place a group of placeholder snippets which are linked together
433+ /// in place of the elements
434+ OverGroup ( Vec < SyntaxElement > ) ,
412435}
413436
414437impl PlaceSnippet {
415- fn finalize_position ( self ) -> Snippet {
438+ fn finalize_position ( self ) -> Vec < Snippet > {
416439 match self {
417- PlaceSnippet :: Before ( it) => Snippet :: Tabstop ( it. text_range ( ) . start ( ) ) ,
418- PlaceSnippet :: After ( it) => Snippet :: Tabstop ( it. text_range ( ) . end ( ) ) ,
419- PlaceSnippet :: Over ( it) => Snippet :: Placeholder ( it. text_range ( ) ) ,
440+ PlaceSnippet :: Before ( it) => vec ! [ Snippet :: Tabstop ( it. text_range( ) . start( ) ) ] ,
441+ PlaceSnippet :: After ( it) => vec ! [ Snippet :: Tabstop ( it. text_range( ) . end( ) ) ] ,
442+ PlaceSnippet :: Over ( it) => vec ! [ Snippet :: Placeholder ( it. text_range( ) ) ] ,
443+ PlaceSnippet :: OverGroup ( it) => {
444+ vec ! [ Snippet :: PlaceholderGroup ( it. into_iter( ) . map( |it| it. text_range( ) ) . collect( ) ) ]
445+ }
420446 }
421447 }
422448}
0 commit comments