@@ -846,6 +846,53 @@ fn normalize_ws_between_braces(node: &SyntaxNode) -> Option<()> {
846
846
Some ( ( ) )
847
847
}
848
848
849
+ impl ast:: IdentPat {
850
+ pub fn set_pat ( & self , pat : Option < ast:: Pat > ) {
851
+ match pat {
852
+ None => {
853
+ if let Some ( at_token) = self . at_token ( ) {
854
+ // Remove `@ Pat`
855
+ let start = at_token. clone ( ) . into ( ) ;
856
+ let end = self
857
+ . pat ( )
858
+ . map ( |it| it. syntax ( ) . clone ( ) . into ( ) )
859
+ . unwrap_or_else ( || at_token. into ( ) ) ;
860
+
861
+ ted:: remove_all ( start..=end) ;
862
+
863
+ // Remove any trailing ws
864
+ if let Some ( last) =
865
+ self . syntax ( ) . last_token ( ) . filter ( |it| it. kind ( ) == WHITESPACE )
866
+ {
867
+ last. detach ( ) ;
868
+ }
869
+ }
870
+ }
871
+ Some ( pat) => {
872
+ if let Some ( old_pat) = self . pat ( ) {
873
+ // Replace existing pattern
874
+ ted:: replace ( old_pat. syntax ( ) , pat. syntax ( ) )
875
+ } else if let Some ( at_token) = self . at_token ( ) {
876
+ // Have an `@` token but not a pattern yet
877
+ ted:: insert ( ted:: Position :: after ( at_token) , pat. syntax ( ) ) ;
878
+ } else {
879
+ // Don't have an `@`, should have a name
880
+ let name = self . name ( ) . unwrap ( ) ;
881
+
882
+ ted:: insert_all (
883
+ ted:: Position :: after ( name. syntax ( ) ) ,
884
+ vec ! [
885
+ make:: token( T ![ @] ) . into( ) ,
886
+ make:: tokens:: single_space( ) . into( ) ,
887
+ pat. syntax( ) . clone( ) . into( ) ,
888
+ ] ,
889
+ )
890
+ }
891
+ }
892
+ }
893
+ }
894
+ }
895
+
849
896
pub trait HasVisibilityEdit : ast:: HasVisibility {
850
897
fn set_visibility ( & self , visbility : ast:: Visibility ) {
851
898
match self . visibility ( ) {
@@ -947,6 +994,34 @@ mod tests {
947
994
) ;
948
995
}
949
996
997
+ #[ test]
998
+ fn test_ident_pat_set_pat ( ) {
999
+ #[ track_caller]
1000
+ fn check ( before : & str , expected : & str , pat : Option < ast:: Pat > ) {
1001
+ let pat = pat. map ( |it| it. clone_for_update ( ) ) ;
1002
+
1003
+ let ident_pat = ast_mut_from_text :: < ast:: IdentPat > ( & format ! ( "fn f() {{ {before} }}" ) ) ;
1004
+ ident_pat. set_pat ( pat) ;
1005
+
1006
+ let after = ast_mut_from_text :: < ast:: IdentPat > ( & format ! ( "fn f() {{ {expected} }}" ) ) ;
1007
+ assert_eq ! ( ident_pat. to_string( ) , after. to_string( ) ) ;
1008
+ }
1009
+
1010
+ // replacing
1011
+ check ( "let a @ _;" , "let a @ ();" , Some ( make:: tuple_pat ( [ ] ) . into ( ) ) ) ;
1012
+
1013
+ // note: no trailing semicolon is added for the below tests since it
1014
+ // seems to be picked up by the ident pat during error recovery?
1015
+
1016
+ // adding
1017
+ check ( "let a " , "let a @ ()" , Some ( make:: tuple_pat ( [ ] ) . into ( ) ) ) ;
1018
+ check ( "let a @ " , "let a @ ()" , Some ( make:: tuple_pat ( [ ] ) . into ( ) ) ) ;
1019
+
1020
+ // removing
1021
+ check ( "let a @ ()" , "let a" , None ) ;
1022
+ check ( "let a @ " , "let a" , None ) ;
1023
+ }
1024
+
950
1025
#[ test]
951
1026
fn add_variant_to_empty_enum ( ) {
952
1027
let variant = make:: variant ( make:: name ( "Bar" ) , None ) . clone_for_update ( ) ;
0 commit comments