diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_assists/src/handlers/reorder_fields.rs | 86 | ||||
-rw-r--r-- | crates/ra_hir_def/src/body/lower.rs | 2 | ||||
-rw-r--r-- | crates/ra_syntax/src/ast/generated/nodes.rs | 8 |
3 files changed, 48 insertions, 48 deletions
diff --git a/crates/ra_assists/src/handlers/reorder_fields.rs b/crates/ra_assists/src/handlers/reorder_fields.rs index 1da85fcec..100e1feb1 100644 --- a/crates/ra_assists/src/handlers/reorder_fields.rs +++ b/crates/ra_assists/src/handlers/reorder_fields.rs | |||
@@ -4,71 +4,79 @@ use itertools::Itertools; | |||
4 | 4 | ||
5 | use hir::{Adt, ModuleDef, PathResolution, Semantics, Struct}; | 5 | use hir::{Adt, ModuleDef, PathResolution, Semantics, Struct}; |
6 | use ra_ide_db::RootDatabase; | 6 | use ra_ide_db::RootDatabase; |
7 | use ra_syntax::ast::{Name, Pat}; | ||
8 | use ra_syntax::{ | 7 | use ra_syntax::{ |
9 | ast, | 8 | algo, ast, |
10 | ast::{Path, RecordField, RecordLit, RecordPat}, | 9 | ast::{Name, Path, RecordLit, RecordPat}, |
11 | AstNode, | 10 | AstNode, SyntaxKind, SyntaxNode, |
12 | }; | 11 | }; |
13 | 12 | ||
14 | use crate::{ | 13 | use crate::{ |
15 | assist_ctx::{Assist, AssistCtx}, | 14 | assist_ctx::{Assist, AssistCtx}, |
16 | AssistId, | 15 | AssistId, |
17 | }; | 16 | }; |
17 | use ra_syntax::ast::{Expr, NameRef}; | ||
18 | 18 | ||
19 | pub(crate) fn reorder_fields(ctx: AssistCtx) -> Option<Assist> { | 19 | pub(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)) |
21 | } | 21 | } |
22 | 22 | ||
23 | fn reorder_struct(ctx: AssistCtx) -> Option<Assist> { | 23 | fn reorder<R: AstNode>(ctx: AssistCtx) -> Option<Assist> { |
24 | let record: RecordLit = ctx.find_node_at_offset()?; | 24 | let record = ctx.find_node_at_offset::<R>()?; |
25 | reorder(ctx, &record, &record.path()?, field_name) | 25 | let path = record.syntax().children().find_map(Path::cast)?; |
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 | } | ||
39 | 26 | ||
40 | fn field_pat_name(field: &Pat) -> String { | 27 | let ranks = compute_fields_ranks(&path, &ctx)?; |
41 | field.syntax().children().find_map(Name::cast).map(|n| n.to_string()).unwrap_or_default() | ||
42 | } | ||
43 | 28 | ||
44 | fn reorder<R: AstNode, F: AstNode + Eq + Clone>( | 29 | let fields = get_fields(&record.syntax()); |
45 | ctx: AssistCtx, | 30 | let sorted_fields = sorted_by_rank(&fields, |node| { |
46 | record: &R, | 31 | *ranks.get(&get_field_name(node)).unwrap_or(&usize::max_value()) |
47 | path: &Path, | 32 | }); |
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())); | ||
54 | 33 | ||
55 | if sorted_fields == fields { | 34 | if sorted_fields == fields { |
56 | return None; | 35 | return None; |
57 | } | 36 | } |
58 | 37 | ||
59 | ctx.add_assist(AssistId("reorder_fields"), "Reorder record fields", |edit| { | 38 | ctx.add_assist(AssistId("reorder_fields"), "Reorder record fields", |edit| { |
60 | for (old, new) in fields.into_iter().zip(sorted_fields) { | 39 | for (old, new) in fields.iter().zip(&sorted_fields) { |
61 | edit.replace_ast(old, new); | 40 | algo::diff(old, new).into_text_edit(edit.text_edit_builder()); |
62 | } | 41 | } |
63 | edit.target(record.syntax().text_range()) | 42 | edit.target(record.syntax().text_range()) |
64 | }) | 43 | }) |
65 | } | 44 | } |
66 | 45 | ||
67 | fn get_fields<R: AstNode, F: AstNode>(record: &R) -> Vec<F> { | 46 | fn get_fields_kind(node: &SyntaxNode) -> Vec<SyntaxKind> { |
68 | record.syntax().children().flat_map(|n1| n1.children()).filter_map(|n3| F::cast(n3)).collect() | 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() | ||
69 | } | 74 | } |
70 | 75 | ||
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> { | ||
72 | fields.iter().cloned().sorted_by_key(get_rank).collect() | 80 | fields.iter().cloned().sorted_by_key(get_rank).collect() |
73 | } | 81 | } |
74 | 82 | ||
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index 80492b733..e1b08d48f 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs | |||
@@ -691,8 +691,6 @@ impl ExprCollector<'_> { | |||
691 | } | 691 | } |
692 | // FIXME: implement | 692 | // FIXME: implement |
693 | ast::Pat::BoxPat(_) | ast::Pat::RangePat(_) | ast::Pat::MacroPat(_) => Pat::Missing, | 693 | ast::Pat::BoxPat(_) | ast::Pat::RangePat(_) | ast::Pat::MacroPat(_) => Pat::Missing, |
694 | // FIXME: implement | ||
695 | ast::Pat::RecordFieldPat(_) => Pat::Missing, | ||
696 | }; | 694 | }; |
697 | let ptr = AstPtr::new(&pat); | 695 | let ptr = AstPtr::new(&pat); |
698 | self.alloc_pat(pattern, Either::Left(ptr)) | 696 | self.alloc_pat(pattern, Either::Left(ptr)) |
diff --git a/crates/ra_syntax/src/ast/generated/nodes.rs b/crates/ra_syntax/src/ast/generated/nodes.rs index 79b225622..20f663046 100644 --- a/crates/ra_syntax/src/ast/generated/nodes.rs +++ b/crates/ra_syntax/src/ast/generated/nodes.rs | |||
@@ -3256,7 +3256,6 @@ pub enum Pat { | |||
3256 | RangePat(RangePat), | 3256 | RangePat(RangePat), |
3257 | LiteralPat(LiteralPat), | 3257 | LiteralPat(LiteralPat), |
3258 | MacroPat(MacroPat), | 3258 | MacroPat(MacroPat), |
3259 | RecordFieldPat(RecordFieldPat), | ||
3260 | } | 3259 | } |
3261 | impl From<OrPat> for Pat { | 3260 | impl From<OrPat> for Pat { |
3262 | fn from(node: OrPat) -> Pat { Pat::OrPat(node) } | 3261 | fn from(node: OrPat) -> Pat { Pat::OrPat(node) } |
@@ -3303,15 +3302,12 @@ impl From<LiteralPat> for Pat { | |||
3303 | impl From<MacroPat> for Pat { | 3302 | impl From<MacroPat> for Pat { |
3304 | fn from(node: MacroPat) -> Pat { Pat::MacroPat(node) } | 3303 | fn from(node: MacroPat) -> Pat { Pat::MacroPat(node) } |
3305 | } | 3304 | } |
3306 | impl From<RecordFieldPat> for Pat { | ||
3307 | fn from(node: RecordFieldPat) -> Pat { Pat::RecordFieldPat(node) } | ||
3308 | } | ||
3309 | impl AstNode for Pat { | 3305 | impl AstNode for Pat { |
3310 | fn can_cast(kind: SyntaxKind) -> bool { | 3306 | fn can_cast(kind: SyntaxKind) -> bool { |
3311 | match kind { | 3307 | match kind { |
3312 | OR_PAT | PAREN_PAT | REF_PAT | BOX_PAT | BIND_PAT | PLACEHOLDER_PAT | DOT_DOT_PAT | 3308 | OR_PAT | PAREN_PAT | REF_PAT | BOX_PAT | BIND_PAT | PLACEHOLDER_PAT | DOT_DOT_PAT |
3313 | | PATH_PAT | RECORD_PAT | TUPLE_STRUCT_PAT | TUPLE_PAT | SLICE_PAT | RANGE_PAT | 3309 | | PATH_PAT | RECORD_PAT | TUPLE_STRUCT_PAT | TUPLE_PAT | SLICE_PAT | RANGE_PAT |
3314 | | LITERAL_PAT | MACRO_PAT | RECORD_FIELD_PAT => true, | 3310 | | LITERAL_PAT | MACRO_PAT => true, |
3315 | _ => false, | 3311 | _ => false, |
3316 | } | 3312 | } |
3317 | } | 3313 | } |
@@ -3332,7 +3328,6 @@ impl AstNode for Pat { | |||
3332 | RANGE_PAT => Pat::RangePat(RangePat { syntax }), | 3328 | RANGE_PAT => Pat::RangePat(RangePat { syntax }), |
3333 | LITERAL_PAT => Pat::LiteralPat(LiteralPat { syntax }), | 3329 | LITERAL_PAT => Pat::LiteralPat(LiteralPat { syntax }), |
3334 | MACRO_PAT => Pat::MacroPat(MacroPat { syntax }), | 3330 | MACRO_PAT => Pat::MacroPat(MacroPat { syntax }), |
3335 | RECORD_FIELD_PAT => Pat::RecordFieldPat(RecordFieldPat { syntax }), | ||
3336 | _ => return None, | 3331 | _ => return None, |
3337 | }; | 3332 | }; |
3338 | Some(res) | 3333 | Some(res) |
@@ -3354,7 +3349,6 @@ impl AstNode for Pat { | |||
3354 | Pat::RangePat(it) => &it.syntax, | 3349 | Pat::RangePat(it) => &it.syntax, |
3355 | Pat::LiteralPat(it) => &it.syntax, | 3350 | Pat::LiteralPat(it) => &it.syntax, |
3356 | Pat::MacroPat(it) => &it.syntax, | 3351 | Pat::MacroPat(it) => &it.syntax, |
3357 | Pat::RecordFieldPat(it) => &it.syntax, | ||
3358 | } | 3352 | } |
3359 | } | 3353 | } |
3360 | } | 3354 | } |