@@ -4,71 +4,79 @@ use itertools::Itertools;
44
55use hir:: { Adt , ModuleDef , PathResolution , Semantics , Struct } ;
66use ra_ide_db:: RootDatabase ;
7- use ra_syntax:: ast:: { Name , Pat } ;
87use ra_syntax:: {
9- ast,
10- ast:: { Path , RecordField , RecordLit , RecordPat } ,
11- AstNode ,
8+ algo , ast,
9+ ast:: { Name , Path , RecordLit , RecordPat } ,
10+ AstNode , SyntaxKind , SyntaxNode ,
1211} ;
1312
1413use crate :: {
1514 assist_ctx:: { Assist , AssistCtx } ,
1615 AssistId ,
1716} ;
17+ use ra_syntax:: ast:: { Expr , NameRef } ;
1818
1919pub ( crate ) fn reorder_fields ( ctx : AssistCtx ) -> Option < Assist > {
20- reorder_struct ( ctx. clone ( ) ) . or_else ( || reorder_struct_pat ( ctx) )
20+ reorder :: < RecordLit > ( ctx. clone ( ) ) . or_else ( || reorder :: < RecordPat > ( ctx) )
2121}
2222
23- fn reorder_struct ( ctx : AssistCtx ) -> Option < Assist > {
24- let record: RecordLit = ctx. find_node_at_offset ( ) ?;
25- reorder ( ctx, & record, & record. path ( ) ?, field_name)
26- }
27-
28- fn field_name ( r : & RecordField ) -> String {
29- r. name_ref ( )
30- . map ( |name| name. syntax ( ) . text ( ) . to_string ( ) )
31- . or_else ( || r. expr ( ) . map ( |e| e. syntax ( ) . text ( ) . to_string ( ) ) )
32- . unwrap_or_default ( )
33- }
34-
35- fn reorder_struct_pat ( ctx : AssistCtx ) -> Option < Assist > {
36- let record: RecordPat = ctx. find_node_at_offset ( ) ?;
37- reorder ( ctx, & record, & record. path ( ) ?, field_pat_name)
38- }
23+ fn reorder < R : AstNode > ( ctx : AssistCtx ) -> Option < Assist > {
24+ let record = ctx. find_node_at_offset :: < R > ( ) ?;
25+ let path = record. syntax ( ) . children ( ) . find_map ( Path :: cast) ?;
3926
40- fn field_pat_name ( field : & Pat ) -> String {
41- field. syntax ( ) . children ( ) . find_map ( Name :: cast) . map ( |n| n. to_string ( ) ) . unwrap_or_default ( )
42- }
27+ let ranks = compute_fields_ranks ( & path, & ctx) ?;
4328
44- fn reorder < R : AstNode , F : AstNode + Eq + Clone > (
45- ctx : AssistCtx ,
46- record : & R ,
47- path : & Path ,
48- field_name : fn ( & F ) -> String ,
49- ) -> Option < Assist > {
50- let ranks = compute_fields_ranks ( path, & ctx) ?;
51- let fields: Vec < F > = get_fields ( record) ;
52- let sorted_fields: Vec < F > =
53- sort_by_rank ( & fields, |f| * ranks. get ( & field_name ( f) ) . unwrap_or ( & usize:: max_value ( ) ) ) ;
29+ let fields = get_fields ( & record. syntax ( ) ) ;
30+ let sorted_fields = sorted_by_rank ( & fields, |node| {
31+ * ranks. get ( & get_field_name ( node) ) . unwrap_or ( & usize:: max_value ( ) )
32+ } ) ;
5433
5534 if sorted_fields == fields {
5635 return None ;
5736 }
5837
5938 ctx. add_assist ( AssistId ( "reorder_fields" ) , "Reorder record fields" , |edit| {
60- for ( old, new) in fields. into_iter ( ) . zip ( sorted_fields) {
61- edit . replace_ast ( old, new) ;
39+ for ( old, new) in fields. iter ( ) . zip ( & sorted_fields) {
40+ algo :: diff ( old, new) . into_text_edit ( edit . text_edit_builder ( ) ) ;
6241 }
6342 edit. target ( record. syntax ( ) . text_range ( ) )
6443 } )
6544}
6645
67- fn get_fields < R : AstNode , F : AstNode > ( record : & R ) -> Vec < F > {
68- record. syntax ( ) . children ( ) . flat_map ( |n1| n1. children ( ) ) . filter_map ( |n3| F :: cast ( n3) ) . collect ( )
46+ fn get_fields_kind ( node : & SyntaxNode ) -> Vec < SyntaxKind > {
47+ use SyntaxKind :: * ;
48+ match node. kind ( ) {
49+ RECORD_LIT => vec ! [ RECORD_FIELD ] ,
50+ RECORD_PAT => vec ! [ RECORD_FIELD_PAT , BIND_PAT ] ,
51+ _ => vec ! [ ] ,
52+ }
53+ }
54+
55+ fn get_field_name ( node : & SyntaxNode ) -> String {
56+ use SyntaxKind :: * ;
57+ match node. kind ( ) {
58+ RECORD_FIELD => {
59+ if let Some ( name) = node. children ( ) . find_map ( NameRef :: cast) {
60+ return name. to_string ( ) ;
61+ }
62+ node. children ( ) . find_map ( Expr :: cast) . map ( |expr| expr. to_string ( ) ) . unwrap_or_default ( )
63+ }
64+ BIND_PAT | RECORD_FIELD_PAT => {
65+ node. children ( ) . find_map ( Name :: cast) . map ( |n| n. to_string ( ) ) . unwrap_or_default ( )
66+ }
67+ _ => String :: new ( ) ,
68+ }
69+ }
70+
71+ fn get_fields ( record : & SyntaxNode ) -> Vec < SyntaxNode > {
72+ let kinds = get_fields_kind ( record) ;
73+ record. children ( ) . flat_map ( |n| n. children ( ) ) . filter ( |n| kinds. contains ( & n. kind ( ) ) ) . collect ( )
6974}
7075
71- fn sort_by_rank < F : AstNode + Clone > ( fields : & [ F ] , get_rank : impl FnMut ( & F ) -> usize ) -> Vec < F > {
76+ fn sorted_by_rank (
77+ fields : & [ SyntaxNode ] ,
78+ get_rank : impl Fn ( & SyntaxNode ) -> usize ,
79+ ) -> Vec < SyntaxNode > {
7280 fields. iter ( ) . cloned ( ) . sorted_by_key ( get_rank) . collect ( )
7381}
7482
0 commit comments