forked from rust-lang/rust-analyzer
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Attempt rust-lang#1 Alphabetically Sorting Methods
- Loading branch information
1 parent
41321d9
commit 7787554
Showing
2 changed files
with
244 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,242 @@ | ||
use ast::{AssocItemList, Fn}; | ||
use itertools::Itertools; | ||
use rustc_hash::FxHashMap; | ||
|
||
use hir::{Adt, ModuleDef, PathResolution, Semantics, Struct}; | ||
use ide_db::RootDatabase; | ||
use syntax::{ | ||
algo, | ||
ast::{self, AssocItem, NameOwner}, | ||
match_ast, AstNode, SyntaxKind, | ||
SyntaxKind::*, | ||
SyntaxNode, | ||
}; | ||
|
||
use crate::{AssistContext, AssistId, AssistKind, Assists}; | ||
|
||
// Assist: reorder_methods_sort | ||
// | ||
// 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_methods_sort(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | ||
reorder(acc, ctx) //.or_else(|| reorder::<ast::RecordPat>(acc, ctx)) | ||
} | ||
|
||
fn reorder(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { | ||
let impl_ast = ctx.find_node_at_offset::<ast::Impl>()?; | ||
|
||
let items = impl_ast.assoc_item_list()?; | ||
|
||
let methods = get_methods(&items); | ||
let sorted: Vec<_> = | ||
methods.iter().cloned().sorted_by_key(|f| f.name().unwrap().text().to_string()).collect(); | ||
|
||
let target = items.syntax().text_range(); | ||
acc.add( | ||
AssistId("reorder_methods_sort", AssistKind::RefactorRewrite), | ||
"Sort impl methods", | ||
target, | ||
|edit| { | ||
let mut rewriter = algo::SyntaxRewriter::default(); | ||
for (old, new) in methods.iter().zip(&sorted) { | ||
rewriter.replace(old.syntax(), new.syntax()); | ||
} | ||
edit.rewrite(rewriter); | ||
}, | ||
) | ||
|
||
// println!("Fns: {:?}", fns); | ||
// items.syntax().text_range(); | ||
|
||
// let path = record.syntax().children().find_map(ast::Path::cast)?; | ||
|
||
// println!("Path: {}", path); | ||
|
||
// let ranks = compute_fields_ranks(&path, &ctx)?; | ||
|
||
// 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; | ||
// } | ||
|
||
// let target = record.syntax().text_range(); | ||
// acc.add( | ||
// AssistId("reorder_methods_sort", AssistKind::RefactorRewrite), | ||
// "Reorder record fields", | ||
// target, | ||
// |edit| { | ||
// let mut rewriter = algo::SyntaxRewriter::default(); | ||
// for (old, new) in fields.iter().zip(&sorted_fields) { | ||
// rewriter.replace(old, new); | ||
// } | ||
// edit.rewrite(rewriter); | ||
// }, | ||
// ) | ||
} | ||
|
||
fn get_methods(items: &AssocItemList) -> Vec<Fn> { | ||
items | ||
.assoc_items() | ||
.flat_map(|i| match i { | ||
AssocItem::Fn(f) => Some(f), | ||
_ => None, | ||
}) | ||
.filter(|f| f.name().is_some()) | ||
.collect() | ||
} | ||
|
||
struct Foo { | ||
c: usize, | ||
} | ||
impl Foo { | ||
fn ten() -> usize { | ||
10 | ||
} | ||
fn add(&mut self, b: usize) { | ||
self.c += b | ||
} | ||
fn sub(&mut self, b: usize) { | ||
self.c -= b | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use crate::tests::{check_assist, check_assist_not_applicable}; | ||
|
||
use super::*; | ||
|
||
#[test] | ||
fn not_applicable_if_sorted() { | ||
check_assist_not_applicable( | ||
reorder_methods_sort, | ||
r#" | ||
struct Foo { | ||
foo: i32, | ||
bar: i32, | ||
} | ||
const test: Foo = <|>Foo { foo: 0, bar: 0 }; | ||
"#, | ||
) | ||
} | ||
|
||
#[test] | ||
fn trivial_empty_impl() { | ||
check_assist_not_applicable( | ||
reorder_methods_sort, | ||
r#" | ||
struct Foo {}; | ||
<|>impl Foo {} | ||
"#, | ||
) | ||
} | ||
|
||
#[test] | ||
fn reorder_impl_methods() { | ||
check_assist( | ||
reorder_methods_sort, | ||
r#" | ||
struct Foo {c: usize} | ||
<|>impl Foo { | ||
fn sub(&mut self, b: usize) { self.c -= b } | ||
fn ten() -> usize { 10 } | ||
fn add(&mut self, b: usize) { self.c += b } | ||
} | ||
"#, | ||
r#" | ||
struct Foo {c: usize} | ||
impl Foo { | ||
fn add(&mut self, b: usize) { self.c += b } | ||
fn sub(&mut self, b: usize) { self.c -= b } | ||
fn ten() -> usize { 10 } | ||
} | ||
"#, | ||
) | ||
} | ||
|
||
#[test] | ||
fn reorder_struct_pattern() { | ||
check_assist( | ||
reorder_methods_sort, | ||
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_methods_sort, | ||
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", | ||
} | ||
} | ||
} | ||
"#, | ||
) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters