From e6d22187a67e762bb950de244a6ca15f3a0b0731 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 9 Apr 2020 18:25:36 +0200 Subject: Add _token suffix to token accessors I think this makes is more clear which things are : AstNode and which are : AstToken --- crates/ra_assists/src/handlers/add_explicit_type.rs | 4 ++-- crates/ra_assists/src/handlers/add_impl.rs | 2 +- crates/ra_assists/src/handlers/add_new.rs | 2 +- crates/ra_assists/src/handlers/merge_imports.rs | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) (limited to 'crates/ra_assists/src') diff --git a/crates/ra_assists/src/handlers/add_explicit_type.rs b/crates/ra_assists/src/handlers/add_explicit_type.rs index d86d804b2..e7dcfb44e 100644 --- a/crates/ra_assists/src/handlers/add_explicit_type.rs +++ b/crates/ra_assists/src/handlers/add_explicit_type.rs @@ -1,6 +1,6 @@ use hir::HirDisplay; use ra_syntax::{ - ast::{self, AstNode, LetStmt, NameOwner, TypeAscriptionOwner}, + ast::{self, AstNode, AstToken, LetStmt, NameOwner, TypeAscriptionOwner}, TextRange, }; @@ -35,7 +35,7 @@ pub(crate) fn add_explicit_type(ctx: AssistCtx) -> Option { let name = pat.name()?; let name_range = name.syntax().text_range(); let stmt_range = stmt.syntax().text_range(); - let eq_range = stmt.eq_token()?.text_range(); + let eq_range = stmt.eq_token()?.syntax().text_range(); // Assist should only be applicable if cursor is between 'let' and '=' let let_range = TextRange::from_to(stmt_range.start(), eq_range.start()); let cursor_in_range = ctx.frange.range.is_subrange(&let_range); diff --git a/crates/ra_assists/src/handlers/add_impl.rs b/crates/ra_assists/src/handlers/add_impl.rs index 72a201b6d..26dfed237 100644 --- a/crates/ra_assists/src/handlers/add_impl.rs +++ b/crates/ra_assists/src/handlers/add_impl.rs @@ -42,7 +42,7 @@ pub(crate) fn add_impl(ctx: AssistCtx) -> Option { if let Some(type_params) = type_params { let lifetime_params = type_params .lifetime_params() - .filter_map(|it| it.lifetime()) + .filter_map(|it| it.lifetime_token()) .map(|it| it.text().clone()); let type_params = type_params.type_params().filter_map(|it| it.name()).map(|it| it.text().clone()); diff --git a/crates/ra_assists/src/handlers/add_new.rs b/crates/ra_assists/src/handlers/add_new.rs index c10397249..30360af94 100644 --- a/crates/ra_assists/src/handlers/add_new.rs +++ b/crates/ra_assists/src/handlers/add_new.rs @@ -106,7 +106,7 @@ fn generate_impl_text(strukt: &ast::StructDef, code: &str) -> String { if let Some(type_params) = type_params { let lifetime_params = type_params .lifetime_params() - .filter_map(|it| it.lifetime()) + .filter_map(|it| it.lifetime_token()) .map(|it| it.text().clone()); let type_params = type_params.type_params().filter_map(|it| it.name()).map(|it| it.text().clone()); diff --git a/crates/ra_assists/src/handlers/merge_imports.rs b/crates/ra_assists/src/handlers/merge_imports.rs index f8b3ddb4e..936d50ab4 100644 --- a/crates/ra_assists/src/handlers/merge_imports.rs +++ b/crates/ra_assists/src/handlers/merge_imports.rs @@ -82,7 +82,7 @@ fn try_merge_trees(old: &ast::UseTree, new: &ast::UseTree) -> Option Date: Thu, 9 Apr 2020 18:40:43 +0200 Subject: Be consistent about token accesors --- crates/ra_assists/src/handlers/inline_local_variable.rs | 2 +- crates/ra_assists/src/handlers/introduce_variable.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'crates/ra_assists/src') diff --git a/crates/ra_assists/src/handlers/inline_local_variable.rs b/crates/ra_assists/src/handlers/inline_local_variable.rs index 3bfcba8ff..b9eb09676 100644 --- a/crates/ra_assists/src/handlers/inline_local_variable.rs +++ b/crates/ra_assists/src/handlers/inline_local_variable.rs @@ -29,7 +29,7 @@ pub(crate) fn inline_local_variable(ctx: AssistCtx) -> Option { ast::Pat::BindPat(pat) => pat, _ => return None, }; - if bind_pat.is_mutable() { + if bind_pat.mut_kw_token().is_some() { tested_by!(test_not_inline_mut_variable); return None; } diff --git a/crates/ra_assists/src/handlers/introduce_variable.rs b/crates/ra_assists/src/handlers/introduce_variable.rs index 8a02f1a32..ab6bdf6bb 100644 --- a/crates/ra_assists/src/handlers/introduce_variable.rs +++ b/crates/ra_assists/src/handlers/introduce_variable.rs @@ -61,7 +61,7 @@ pub(crate) fn introduce_variable(ctx: AssistCtx) -> Option { }; if is_full_stmt { tested_by!(test_introduce_var_expr_stmt); - if !full_stmt.unwrap().has_semi() { + if full_stmt.unwrap().semi_token().is_none() { buf.push_str(";"); } edit.replace(expr.syntax().text_range(), buf); -- cgit v1.2.3 From 30084a56a5731343bd4cec727646a6c55900234f Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Thu, 9 Apr 2020 23:35:05 +0200 Subject: Simpler acessors for keywords --- crates/ra_assists/src/handlers/inline_local_variable.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'crates/ra_assists/src') diff --git a/crates/ra_assists/src/handlers/inline_local_variable.rs b/crates/ra_assists/src/handlers/inline_local_variable.rs index b9eb09676..c4fb425b0 100644 --- a/crates/ra_assists/src/handlers/inline_local_variable.rs +++ b/crates/ra_assists/src/handlers/inline_local_variable.rs @@ -29,7 +29,7 @@ pub(crate) fn inline_local_variable(ctx: AssistCtx) -> Option { ast::Pat::BindPat(pat) => pat, _ => return None, }; - if bind_pat.mut_kw_token().is_some() { + if bind_pat.mut_token().is_some() { tested_by!(test_not_inline_mut_variable); return None; } -- cgit v1.2.3 From 730a927c5e6b382690e88f482a03701636242a2c Mon Sep 17 00:00:00 2001 From: Geoffrey Copin Date: Fri, 10 Apr 2020 00:35:43 +0200 Subject: Implement assist "Reorder field names" --- crates/ra_assists/src/handlers/reorder_fields.rs | 207 +++++++++++++++++++++++ crates/ra_assists/src/lib.rs | 2 + 2 files changed, 209 insertions(+) create mode 100644 crates/ra_assists/src/handlers/reorder_fields.rs (limited to 'crates/ra_assists/src') diff --git a/crates/ra_assists/src/handlers/reorder_fields.rs b/crates/ra_assists/src/handlers/reorder_fields.rs new file mode 100644 index 000000000..c17c1288c --- /dev/null +++ b/crates/ra_assists/src/handlers/reorder_fields.rs @@ -0,0 +1,207 @@ +use std::collections::HashMap; + +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, +}; + +use crate::{ + assist_ctx::{Assist, AssistCtx}, + AssistId, +}; + +pub(crate) fn reorder_fields(ctx: AssistCtx) -> Option { + reorder_struct(ctx.clone()).or_else(|| reorder_struct_pat(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()) + .unwrap_or_else(|| r.expr().unwrap().syntax().text()) + .to_string() +} + +fn reorder_struct_pat(ctx: AssistCtx) -> Option { + let record: RecordPat = ctx.find_node_at_offset()?; + reorder(ctx, &record, &record.path()?, field_pat_name) +} + +fn field_pat_name(field: &Pat) -> String { + field.syntax().children().find_map(Name::cast).map(|n| n.to_string()).unwrap_or_default() +} + +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())); + + 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); + } + 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 sort_by_rank(fields: &[F], get_rank: impl FnMut(&F) -> usize) -> Vec { + fields.iter().cloned().sorted_by_key(get_rank).collect() +} + +fn struct_definition(path: &ast::Path, sema: &Semantics) -> Option { + match sema.resolve_path(path) { + Some(PathResolution::Def(ModuleDef::Adt(Adt::Struct(s)))) => Some(s), + _ => None, + } +} + +fn compute_fields_ranks(path: &Path, ctx: &AssistCtx) -> Option> { + Some( + struct_definition(path, ctx.sema)? + .fields(ctx.db) + .iter() + .enumerate() + .map(|(idx, field)| (field.name(ctx.db).to_string(), idx)) + .collect(), + ) +} + +#[cfg(test)] +mod tests { + use crate::helpers::{check_assist, check_assist_not_applicable}; + + use super::*; + + #[test] + fn not_applicable_if_sorted() { + check_assist_not_applicable( + reorder_fields, + r#" + struct Foo { + foo: i32, + bar: i32, + } + + const test: Foo = <|>Foo { foo: 0, bar: 0 }; + "#, + ) + } + + #[test] + fn trivial_empty_fields() { + check_assist_not_applicable( + reorder_fields, + r#" + struct Foo {}; + const test: Foo = <|>Foo {} + "#, + ) + } + + #[test] + fn reorder_struct_fields() { + check_assist( + reorder_fields, + r#" + struct Foo {foo: i32, bar: i32}; + const test: Foo = <|>Foo {bar: 0, foo: 1} + "#, + r#" + struct Foo {foo: i32, bar: i32}; + const test: Foo = <|>Foo {foo: 1, bar: 0} + "#, + ) + } + + #[test] + fn reorder_struct_pattern() { + check_assist( + reorder_fields, + r#" + struct Foo { foo: i64, bar: i64, baz: i64 } + + fn f(f: Foo) -> { + match f { + <|>Foo { baz: 0, ref mut bar, .. } => (), + _ => () + } + } + "#, + r#" + struct Foo { foo: i64, bar: i64, baz: i64 } + + fn f(f: Foo) -> { + match f { + <|>Foo { ref mut bar, baz: 0, .. } => (), + _ => () + } + } + "#, + ) + } + + #[test] + fn reorder_with_extra_field() { + check_assist( + reorder_fields, + r#" + struct Foo { + foo: String, + bar: String, + } + + impl Foo { + fn new() -> Foo { + let foo = String::new(); + <|>Foo { + bar: foo.clone(), + extra: "Extra field", + foo, + } + } + } + "#, + r#" + struct Foo { + foo: String, + bar: String, + } + + impl Foo { + fn new() -> Foo { + let foo = String::new(); + <|>Foo { + foo, + bar: foo.clone(), + extra: "Extra field", + } + } + } + "#, + ) + } +} diff --git a/crates/ra_assists/src/lib.rs b/crates/ra_assists/src/lib.rs index 5ba5254fd..a00136da1 100644 --- a/crates/ra_assists/src/lib.rs +++ b/crates/ra_assists/src/lib.rs @@ -129,6 +129,7 @@ mod handlers { mod replace_unwrap_with_match; mod split_import; mod add_from_impl_for_enum; + mod reorder_fields; pub(crate) fn all() -> &'static [AssistHandler] { &[ @@ -170,6 +171,7 @@ mod handlers { // These are manually sorted for better priorities add_missing_impl_members::add_missing_impl_members, add_missing_impl_members::add_missing_default_members, + reorder_fields::reorder_fields, ] } } -- cgit v1.2.3 From c8b4c36f8161d34c8145a49965efee4514275989 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 10 Apr 2020 10:11:05 +0200 Subject: Semicolon token --- crates/ra_assists/src/handlers/introduce_variable.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'crates/ra_assists/src') diff --git a/crates/ra_assists/src/handlers/introduce_variable.rs b/crates/ra_assists/src/handlers/introduce_variable.rs index ab6bdf6bb..8d0f7e922 100644 --- a/crates/ra_assists/src/handlers/introduce_variable.rs +++ b/crates/ra_assists/src/handlers/introduce_variable.rs @@ -61,7 +61,7 @@ pub(crate) fn introduce_variable(ctx: AssistCtx) -> Option { }; if is_full_stmt { tested_by!(test_introduce_var_expr_stmt); - if full_stmt.unwrap().semi_token().is_none() { + if full_stmt.unwrap().semicolon_token().is_none() { buf.push_str(";"); } edit.replace(expr.syntax().text_range(), buf); -- cgit v1.2.3 From 460c8bbdec8561a581d035f9767b7dd1ba36cfd7 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 10 Apr 2020 10:27:23 +0200 Subject: Curley tokens --- crates/ra_assists/src/handlers/merge_imports.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'crates/ra_assists/src') diff --git a/crates/ra_assists/src/handlers/merge_imports.rs b/crates/ra_assists/src/handlers/merge_imports.rs index 936d50ab4..0958f52f1 100644 --- a/crates/ra_assists/src/handlers/merge_imports.rs +++ b/crates/ra_assists/src/handlers/merge_imports.rs @@ -3,7 +3,7 @@ use std::iter::successors; use ra_syntax::{ algo::{neighbor, SyntaxRewriter}, ast::{self, edit::AstNodeEdit, make}, - AstNode, AstToken, Direction, InsertPosition, SyntaxElement, T, + AstNode, Direction, InsertPosition, SyntaxElement, T, }; use crate::{Assist, AssistCtx, AssistId}; @@ -82,7 +82,7 @@ fn try_merge_trees(old: &ast::UseTree, new: &ast::UseTree) -> Option Date: Fri, 10 Apr 2020 10:35:39 +0200 Subject: Convert more tokens --- crates/ra_assists/src/handlers/add_explicit_type.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'crates/ra_assists/src') diff --git a/crates/ra_assists/src/handlers/add_explicit_type.rs b/crates/ra_assists/src/handlers/add_explicit_type.rs index e7dcfb44e..d86d804b2 100644 --- a/crates/ra_assists/src/handlers/add_explicit_type.rs +++ b/crates/ra_assists/src/handlers/add_explicit_type.rs @@ -1,6 +1,6 @@ use hir::HirDisplay; use ra_syntax::{ - ast::{self, AstNode, AstToken, LetStmt, NameOwner, TypeAscriptionOwner}, + ast::{self, AstNode, LetStmt, NameOwner, TypeAscriptionOwner}, TextRange, }; @@ -35,7 +35,7 @@ pub(crate) fn add_explicit_type(ctx: AssistCtx) -> Option { let name = pat.name()?; let name_range = name.syntax().text_range(); let stmt_range = stmt.syntax().text_range(); - let eq_range = stmt.eq_token()?.syntax().text_range(); + let eq_range = stmt.eq_token()?.text_range(); // Assist should only be applicable if cursor is between 'let' and '=' let let_range = TextRange::from_to(stmt_range.start(), eq_range.start()); let cursor_in_range = ctx.frange.range.is_subrange(&let_range); -- cgit v1.2.3 From 8d71a6bf0ca51ae099a5b470afdb957bca321441 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 10 Apr 2020 11:49:13 +0200 Subject: Scale token generation back --- crates/ra_assists/src/handlers/add_impl.rs | 2 +- crates/ra_assists/src/handlers/add_new.rs | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) (limited to 'crates/ra_assists/src') diff --git a/crates/ra_assists/src/handlers/add_impl.rs b/crates/ra_assists/src/handlers/add_impl.rs index 26dfed237..6622eadb2 100644 --- a/crates/ra_assists/src/handlers/add_impl.rs +++ b/crates/ra_assists/src/handlers/add_impl.rs @@ -1,5 +1,5 @@ use ra_syntax::{ - ast::{self, AstNode, AstToken, NameOwner, TypeParamsOwner}, + ast::{self, AstNode, NameOwner, TypeParamsOwner}, TextUnit, }; use stdx::{format_to, SepBy}; diff --git a/crates/ra_assists/src/handlers/add_new.rs b/crates/ra_assists/src/handlers/add_new.rs index 30360af94..240b19fa3 100644 --- a/crates/ra_assists/src/handlers/add_new.rs +++ b/crates/ra_assists/src/handlers/add_new.rs @@ -1,8 +1,7 @@ use hir::Adt; use ra_syntax::{ ast::{ - self, AstNode, AstToken, NameOwner, StructKind, TypeAscriptionOwner, TypeParamsOwner, - VisibilityOwner, + self, AstNode, NameOwner, StructKind, TypeAscriptionOwner, TypeParamsOwner, VisibilityOwner, }, TextUnit, T, }; -- cgit v1.2.3 From 5c5bde47fb759440d007c90fd83021de538120b8 Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Fri, 10 Apr 2020 17:06:57 +0200 Subject: Rename some tokens --- crates/ra_assists/src/handlers/move_bounds.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'crates/ra_assists/src') diff --git a/crates/ra_assists/src/handlers/move_bounds.rs b/crates/ra_assists/src/handlers/move_bounds.rs index 93f26f51a..0f26884dc 100644 --- a/crates/ra_assists/src/handlers/move_bounds.rs +++ b/crates/ra_assists/src/handlers/move_bounds.rs @@ -2,6 +2,7 @@ use ra_syntax::{ ast::{self, edit::AstNodeEdit, make, AstNode, NameOwner, TypeBoundsOwner}, match_ast, SyntaxKind::*, + T, }; use crate::{Assist, AssistCtx, AssistId}; @@ -42,7 +43,7 @@ pub(crate) fn move_bounds_to_where_clause(ctx: AssistCtx) -> Option { ast::EnumDef(it) => it.variant_list()?.syntax().clone().into(), ast::StructDef(it) => { it.syntax().children_with_tokens() - .find(|it| it.kind() == RECORD_FIELD_DEF_LIST || it.kind() == SEMI)? + .find(|it| it.kind() == RECORD_FIELD_DEF_LIST || it.kind() == T![;])? }, _ => return None } -- cgit v1.2.3 From af04d45d32b5d9bdf949beb17152ef78dd4a0523 Mon Sep 17 00:00:00 2001 From: Chris Hopman Date: Fri, 10 Apr 2020 13:41:11 -0700 Subject: Change missing impl assist to use todo!() instead of unimplemented() todo!() "Indicates unfinished code" (https://doc.rust-lang.org/std/macro.todo.html) Rust documentation provides further clarification: > The difference between unimplemented! and todo! is that while todo! > conveys an intent of implementing the functionality later and the > message is "not yet implemented", unimplemented! makes no such claims. todo!() seems more appropriate for assists that insert missing impls. --- crates/ra_assists/src/doc_tests/generated.rs | 2 +- .../src/handlers/add_missing_impl_members.rs | 34 +++++++++++----------- 2 files changed, 18 insertions(+), 18 deletions(-) (limited to 'crates/ra_assists/src') diff --git a/crates/ra_assists/src/doc_tests/generated.rs b/crates/ra_assists/src/doc_tests/generated.rs index 64444ee3a..24392836c 100644 --- a/crates/ra_assists/src/doc_tests/generated.rs +++ b/crates/ra_assists/src/doc_tests/generated.rs @@ -180,7 +180,7 @@ trait Trait { } impl Trait for () { - fn foo(&self) -> u32 { unimplemented!() } + fn foo(&self) -> u32 { todo!() } } "#####, diff --git a/crates/ra_assists/src/handlers/add_missing_impl_members.rs b/crates/ra_assists/src/handlers/add_missing_impl_members.rs index 722f207e2..2d6d44980 100644 --- a/crates/ra_assists/src/handlers/add_missing_impl_members.rs +++ b/crates/ra_assists/src/handlers/add_missing_impl_members.rs @@ -40,7 +40,7 @@ enum AddMissingImplMembersMode { // } // // impl Trait for () { -// fn foo(&self) -> u32 { unimplemented!() } +// fn foo(&self) -> u32 { todo!() } // // } // ``` @@ -165,7 +165,7 @@ fn add_missing_impl_members_inner( fn add_body(fn_def: ast::FnDef) -> ast::FnDef { if fn_def.body().is_none() { - fn_def.with_body(make::block_from_expr(make::expr_unimplemented())) + fn_def.with_body(make::block_from_expr(make::expr_todo())) } else { fn_def } @@ -215,8 +215,8 @@ impl Foo for S { fn bar(&self) {} <|>type Output; const CONST: usize = 42; - fn foo(&self) { unimplemented!() } - fn baz(&self) { unimplemented!() } + fn foo(&self) { todo!() } + fn baz(&self) { todo!() } }", ); @@ -250,7 +250,7 @@ struct S; impl Foo for S { fn bar(&self) {} - <|>fn foo(&self) { unimplemented!() } + <|>fn foo(&self) { todo!() } }", ); @@ -268,7 +268,7 @@ impl Foo for S { <|> }", trait Foo { fn foo(&self); } struct S; impl Foo for S { - <|>fn foo(&self) { unimplemented!() } + <|>fn foo(&self) { todo!() } }", ); } @@ -285,7 +285,7 @@ impl Foo for S { <|> }", trait Foo { fn foo(&self, t: T) -> &T; } struct S; impl Foo for S { - <|>fn foo(&self, t: u32) -> &u32 { unimplemented!() } + <|>fn foo(&self, t: u32) -> &u32 { todo!() } }", ); } @@ -302,7 +302,7 @@ impl Foo for S { <|> }", trait Foo { fn foo(&self, t: T) -> &T; } struct S; impl Foo for S { - <|>fn foo(&self, t: U) -> &U { unimplemented!() } + <|>fn foo(&self, t: U) -> &U { todo!() } }", ); } @@ -319,7 +319,7 @@ impl Foo for S {}<|>", trait Foo { fn foo(&self); } struct S; impl Foo for S { - <|>fn foo(&self) { unimplemented!() } + <|>fn foo(&self) { todo!() } }", ) } @@ -342,7 +342,7 @@ mod foo { } struct S; impl foo::Foo for S { - <|>fn foo(&self, bar: foo::Bar) { unimplemented!() } + <|>fn foo(&self, bar: foo::Bar) { todo!() } }", ); } @@ -365,7 +365,7 @@ mod foo { } struct S; impl foo::Foo for S { - <|>fn foo(&self, bar: foo::Bar) { unimplemented!() } + <|>fn foo(&self, bar: foo::Bar) { todo!() } }", ); } @@ -388,7 +388,7 @@ mod foo { } struct S; impl foo::Foo for S { - <|>fn foo(&self, bar: foo::Bar) { unimplemented!() } + <|>fn foo(&self, bar: foo::Bar) { todo!() } }", ); } @@ -414,7 +414,7 @@ mod foo { struct Param; struct S; impl foo::Foo for S { - <|>fn foo(&self, bar: Param) { unimplemented!() } + <|>fn foo(&self, bar: Param) { todo!() } }", ); } @@ -439,7 +439,7 @@ mod foo { } struct S; impl foo::Foo for S { - <|>fn foo(&self, bar: foo::Bar::Assoc) { unimplemented!() } + <|>fn foo(&self, bar: foo::Bar::Assoc) { todo!() } }", ); } @@ -464,7 +464,7 @@ mod foo { } struct S; impl foo::Foo for S { - <|>fn foo(&self, bar: foo::Bar) { unimplemented!() } + <|>fn foo(&self, bar: foo::Bar) { todo!() } }", ); } @@ -487,7 +487,7 @@ mod foo { } struct S; impl foo::Foo for S { - <|>fn foo(&self, bar: dyn Fn(u32) -> i32) { unimplemented!() } + <|>fn foo(&self, bar: dyn Fn(u32) -> i32) { todo!() } }", ); } @@ -544,7 +544,7 @@ trait Foo { struct S; impl Foo for S { <|>type Output; - fn foo(&self) { unimplemented!() } + fn foo(&self) { todo!() } }"#, ) } -- cgit v1.2.3 From 21443f1b4839872841d8f32e87209f2106d43ad8 Mon Sep 17 00:00:00 2001 From: Geoffrey Copin Date: Sat, 11 Apr 2020 12:58:20 +0200 Subject: Remove Option unwraping --- crates/ra_assists/src/handlers/reorder_fields.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'crates/ra_assists/src') diff --git a/crates/ra_assists/src/handlers/reorder_fields.rs b/crates/ra_assists/src/handlers/reorder_fields.rs index c17c1288c..1da85fcec 100644 --- a/crates/ra_assists/src/handlers/reorder_fields.rs +++ b/crates/ra_assists/src/handlers/reorder_fields.rs @@ -27,9 +27,9 @@ fn reorder_struct(ctx: AssistCtx) -> Option { fn field_name(r: &RecordField) -> String { r.name_ref() - .map(|name| name.syntax().text()) - .unwrap_or_else(|| r.expr().unwrap().syntax().text()) - .to_string() + .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 { -- cgit v1.2.3 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') 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 From 25a0ce2e9e59ca09665055c053d0008b7bbb9cb7 Mon Sep 17 00:00:00 2001 From: Geoffrey Copin Date: Sat, 11 Apr 2020 19:39:10 +0200 Subject: Add documentation comment --- crates/ra_assists/src/handlers/reorder_fields.rs | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'crates/ra_assists/src') diff --git a/crates/ra_assists/src/handlers/reorder_fields.rs b/crates/ra_assists/src/handlers/reorder_fields.rs index 100e1feb1..661c1bf54 100644 --- a/crates/ra_assists/src/handlers/reorder_fields.rs +++ b/crates/ra_assists/src/handlers/reorder_fields.rs @@ -16,6 +16,22 @@ use crate::{ }; use ra_syntax::ast::{Expr, NameRef}; + +// Assist: reorder_fields +// +// Reorder the fields of record literals and record patterns in the same order as in +// the definition. +// +// ``` +// struct Foo {foo: i32, bar: i32}; +// const test: Foo = <|>Foo {bar: 0, foo: 1} +// ``` +// -> +// ``` +// struct Foo {foo: i32, bar: i32}; +// const test: Foo = <|>Foo {foo: 1, bar: 0} +// ``` +// pub(crate) fn reorder_fields(ctx: AssistCtx) -> Option { reorder::(ctx.clone()).or_else(|| reorder::(ctx)) } -- cgit v1.2.3 From d362fcfc1c52f40a64a329e90b3f213afea0e6f5 Mon Sep 17 00:00:00 2001 From: Geoffrey Copin Date: Sat, 11 Apr 2020 20:32:48 +0200 Subject: Fix doc tests --- crates/ra_assists/src/handlers/reorder_fields.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'crates/ra_assists/src') diff --git a/crates/ra_assists/src/handlers/reorder_fields.rs b/crates/ra_assists/src/handlers/reorder_fields.rs index 661c1bf54..692dd1315 100644 --- a/crates/ra_assists/src/handlers/reorder_fields.rs +++ b/crates/ra_assists/src/handlers/reorder_fields.rs @@ -16,7 +16,6 @@ use crate::{ }; use ra_syntax::ast::{Expr, NameRef}; - // Assist: reorder_fields // // Reorder the fields of record literals and record patterns in the same order as in @@ -29,7 +28,7 @@ use ra_syntax::ast::{Expr, NameRef}; // -> // ``` // struct Foo {foo: i32, bar: i32}; -// const test: Foo = <|>Foo {foo: 1, bar: 0} +// const test: Foo = Foo {foo: 1, bar: 0} // ``` // pub(crate) fn reorder_fields(ctx: AssistCtx) -> Option { -- cgit v1.2.3 From d9089245fefdc4179c1d61839e78131c5e5a5a45 Mon Sep 17 00:00:00 2001 From: Geoffrey Copin Date: Sat, 11 Apr 2020 20:32:58 +0200 Subject: Generate doc --- crates/ra_assists/src/doc_tests/generated.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) (limited to 'crates/ra_assists/src') diff --git a/crates/ra_assists/src/doc_tests/generated.rs b/crates/ra_assists/src/doc_tests/generated.rs index 64444ee3a..6dc049715 100644 --- a/crates/ra_assists/src/doc_tests/generated.rs +++ b/crates/ra_assists/src/doc_tests/generated.rs @@ -606,6 +606,21 @@ impl Walrus { ) } +#[test] +fn doctest_reorder_fields() { + check( + "reorder_fields", + r#####" +struct Foo {foo: i32, bar: i32}; +const test: Foo = <|>Foo {bar: 0, foo: 1} +"#####, + r#####" +struct Foo {foo: i32, bar: i32}; +const test: Foo = Foo {foo: 1, bar: 0} +"#####, + ) +} + #[test] fn doctest_replace_if_let_with_match() { check( -- cgit v1.2.3