From 270bcfdfc226bcdfffd7b8aa903073929fcef5f2 Mon Sep 17 00:00:00 2001 From: Geoffrey Copin Date: Sat, 11 Apr 2020 17:04:25 +0200 Subject: Avoid adding a RecordFieldPat variant to the Pat enum --- crates/ra_assists/src/handlers/reorder_fields.rs | 86 +++++++++++++----------- 1 file changed, 47 insertions(+), 39 deletions(-) (limited to 'crates/ra_assists/src/handlers') 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; use hir::{Adt, ModuleDef, PathResolution, Semantics, Struct}; use ra_ide_db::RootDatabase; -use ra_syntax::ast::{Name, Pat}; use ra_syntax::{ - ast, - ast::{Path, RecordField, RecordLit, RecordPat}, - AstNode, + algo, ast, + ast::{Name, Path, RecordLit, RecordPat}, + AstNode, SyntaxKind, SyntaxNode, }; use crate::{ assist_ctx::{Assist, AssistCtx}, AssistId, }; +use ra_syntax::ast::{Expr, NameRef}; pub(crate) fn reorder_fields(ctx: AssistCtx) -> Option { - reorder_struct(ctx.clone()).or_else(|| reorder_struct_pat(ctx)) + reorder::(ctx.clone()).or_else(|| reorder::(ctx)) } -fn reorder_struct(ctx: AssistCtx) -> Option { - let record: RecordLit = ctx.find_node_at_offset()?; - reorder(ctx, &record, &record.path()?, field_name) -} - -fn field_name(r: &RecordField) -> String { - r.name_ref() - .map(|name| name.syntax().text().to_string()) - .or_else(|| r.expr().map(|e| e.syntax().text().to_string())) - .unwrap_or_default() -} - -fn reorder_struct_pat(ctx: AssistCtx) -> Option { - let record: RecordPat = ctx.find_node_at_offset()?; - reorder(ctx, &record, &record.path()?, field_pat_name) -} +fn reorder(ctx: AssistCtx) -> Option { + let record = ctx.find_node_at_offset::()?; + let path = record.syntax().children().find_map(Path::cast)?; -fn field_pat_name(field: &Pat) -> String { - field.syntax().children().find_map(Name::cast).map(|n| n.to_string()).unwrap_or_default() -} + let ranks = compute_fields_ranks(&path, &ctx)?; -fn reorder( - ctx: AssistCtx, - record: &R, - path: &Path, - field_name: fn(&F) -> String, -) -> Option { - let ranks = compute_fields_ranks(path, &ctx)?; - let fields: Vec = get_fields(record); - let sorted_fields: Vec = - sort_by_rank(&fields, |f| *ranks.get(&field_name(f)).unwrap_or(&usize::max_value())); + let fields = get_fields(&record.syntax()); + let sorted_fields = sorted_by_rank(&fields, |node| { + *ranks.get(&get_field_name(node)).unwrap_or(&usize::max_value()) + }); if sorted_fields == fields { return None; } ctx.add_assist(AssistId("reorder_fields"), "Reorder record fields", |edit| { - for (old, new) in fields.into_iter().zip(sorted_fields) { - edit.replace_ast(old, new); + for (old, new) in fields.iter().zip(&sorted_fields) { + algo::diff(old, new).into_text_edit(edit.text_edit_builder()); } edit.target(record.syntax().text_range()) }) } -fn get_fields(record: &R) -> Vec { - record.syntax().children().flat_map(|n1| n1.children()).filter_map(|n3| F::cast(n3)).collect() +fn get_fields_kind(node: &SyntaxNode) -> Vec { + use SyntaxKind::*; + match node.kind() { + RECORD_LIT => vec![RECORD_FIELD], + RECORD_PAT => vec![RECORD_FIELD_PAT, BIND_PAT], + _ => vec![], + } +} + +fn get_field_name(node: &SyntaxNode) -> String { + use SyntaxKind::*; + match node.kind() { + RECORD_FIELD => { + if let Some(name) = node.children().find_map(NameRef::cast) { + return name.to_string(); + } + node.children().find_map(Expr::cast).map(|expr| expr.to_string()).unwrap_or_default() + } + BIND_PAT | RECORD_FIELD_PAT => { + node.children().find_map(Name::cast).map(|n| n.to_string()).unwrap_or_default() + } + _ => String::new(), + } +} + +fn get_fields(record: &SyntaxNode) -> Vec { + let kinds = get_fields_kind(record); + record.children().flat_map(|n| n.children()).filter(|n| kinds.contains(&n.kind())).collect() } -fn sort_by_rank(fields: &[F], get_rank: impl FnMut(&F) -> usize) -> Vec { +fn sorted_by_rank( + fields: &[SyntaxNode], + get_rank: impl Fn(&SyntaxNode) -> usize, +) -> Vec { fields.iter().cloned().sorted_by_key(get_rank).collect() } -- cgit v1.2.3