@@ -14,7 +14,10 @@ use std::{
1414use rowan:: TextRange ;
1515use rustc_hash:: FxHashMap ;
1616
17- use crate :: { AstNode , SyntaxElement , SyntaxNode , SyntaxToken } ;
17+ use crate :: {
18+ AstNode , SyntaxElement , SyntaxKind , SyntaxNode , SyntaxToken , T ,
19+ ast:: { self , edit:: IndentLevel , make} ,
20+ } ;
1821
1922mod edit_algo;
2023mod edits;
@@ -101,6 +104,28 @@ impl SyntaxEditor {
101104 self . changes . push ( Change :: InsertAll ( position, elements) )
102105 }
103106
107+ pub fn insert_with_whitespace ( & mut self , position : Position , element : impl Element ) {
108+ self . insert_all_with_whitespace ( position, vec ! [ element. syntax_element( ) ] )
109+ }
110+
111+ pub fn insert_all_with_whitespace (
112+ & mut self ,
113+ position : Position ,
114+ mut elements : Vec < SyntaxElement > ,
115+ ) {
116+ if let Some ( first) = elements. first ( )
117+ && let Some ( ws) = ws_before ( & position, first)
118+ {
119+ elements. insert ( 0 , ws. into ( ) ) ;
120+ }
121+ if let Some ( last) = elements. last ( )
122+ && let Some ( ws) = ws_after ( & position, last)
123+ {
124+ elements. push ( ws. into ( ) ) ;
125+ }
126+ self . insert_all ( position, elements)
127+ }
128+
104129 pub fn delete ( & mut self , element : impl Element ) {
105130 let element = element. syntax_element ( ) ;
106131 debug_assert ! ( is_ancestor_or_self_of_element( & element, & self . root) ) ;
@@ -412,6 +437,74 @@ impl Element for SyntaxToken {
412437 }
413438}
414439
440+ fn ws_before ( position : & Position , new : & SyntaxElement ) -> Option < SyntaxToken > {
441+ let prev = match & position. repr {
442+ PositionRepr :: FirstChild ( _) => return None ,
443+ PositionRepr :: After ( it) => it,
444+ } ;
445+
446+ if prev. kind ( ) == T ! [ '{' ]
447+ && new. kind ( ) == SyntaxKind :: USE
448+ && let Some ( item_list) = prev. parent ( ) . and_then ( ast:: ItemList :: cast)
449+ {
450+ let mut indent = IndentLevel :: from_element ( & item_list. syntax ( ) . clone ( ) . into ( ) ) ;
451+ indent. 0 += 1 ;
452+ return Some ( make:: tokens:: whitespace ( & format ! ( "\n {indent}" ) ) ) ;
453+ }
454+
455+ if prev. kind ( ) == T ! [ '{' ]
456+ && ast:: Stmt :: can_cast ( new. kind ( ) )
457+ && let Some ( stmt_list) = prev. parent ( ) . and_then ( ast:: StmtList :: cast)
458+ {
459+ let mut indent = IndentLevel :: from_element ( & stmt_list. syntax ( ) . clone ( ) . into ( ) ) ;
460+ indent. 0 += 1 ;
461+ return Some ( make:: tokens:: whitespace ( & format ! ( "\n {indent}" ) ) ) ;
462+ }
463+
464+ ws_between ( prev, new)
465+ }
466+
467+ fn ws_after ( position : & Position , new : & SyntaxElement ) -> Option < SyntaxToken > {
468+ let next = match & position. repr {
469+ PositionRepr :: FirstChild ( parent) => parent. first_child_or_token ( ) ?,
470+ PositionRepr :: After ( sibling) => sibling. next_sibling_or_token ( ) ?,
471+ } ;
472+ ws_between ( new, & next)
473+ }
474+
475+ fn ws_between ( left : & SyntaxElement , right : & SyntaxElement ) -> Option < SyntaxToken > {
476+ if left. kind ( ) == SyntaxKind :: WHITESPACE || right. kind ( ) == SyntaxKind :: WHITESPACE {
477+ return None ;
478+ }
479+ if right. kind ( ) == T ! [ ; ] || right. kind ( ) == T ! [ , ] {
480+ return None ;
481+ }
482+ if left. kind ( ) == T ! [ <] || right. kind ( ) == T ! [ >] {
483+ return None ;
484+ }
485+ if left. kind ( ) == T ! [ & ] && right. kind ( ) == SyntaxKind :: LIFETIME {
486+ return None ;
487+ }
488+ if right. kind ( ) == SyntaxKind :: GENERIC_ARG_LIST {
489+ return None ;
490+ }
491+ if right. kind ( ) == SyntaxKind :: USE {
492+ let mut indent = IndentLevel :: from_element ( left) ;
493+ if left. kind ( ) == SyntaxKind :: USE {
494+ indent. 0 = IndentLevel :: from_element ( right) . 0 . max ( indent. 0 ) ;
495+ }
496+ return Some ( make:: tokens:: whitespace ( & format ! ( "\n {indent}" ) ) ) ;
497+ }
498+ if left. kind ( ) == SyntaxKind :: ATTR {
499+ let mut indent = IndentLevel :: from_element ( right) ;
500+ if right. kind ( ) == SyntaxKind :: ATTR {
501+ indent. 0 = IndentLevel :: from_element ( left) . 0 . max ( indent. 0 ) ;
502+ }
503+ return Some ( make:: tokens:: whitespace ( & format ! ( "\n {indent}" ) ) ) ;
504+ }
505+ Some ( make:: tokens:: single_space ( ) )
506+ }
507+
415508fn is_ancestor_or_self ( node : & SyntaxNode , ancestor : & SyntaxNode ) -> bool {
416509 node == ancestor || node. ancestors ( ) . any ( |it| & it == ancestor)
417510}
0 commit comments