aboutsummaryrefslogtreecommitdiff
path: root/crates/ide_assists/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ide_assists/src')
-rw-r--r--crates/ide_assists/src/handlers/add_missing_impl_members.rs6
-rw-r--r--crates/ide_assists/src/handlers/convert_comment_block.rs46
-rw-r--r--crates/ide_assists/src/handlers/reorder_fields.rs112
3 files changed, 60 insertions, 104 deletions
diff --git a/crates/ide_assists/src/handlers/add_missing_impl_members.rs b/crates/ide_assists/src/handlers/add_missing_impl_members.rs
index 63cea754d..0148635f9 100644
--- a/crates/ide_assists/src/handlers/add_missing_impl_members.rs
+++ b/crates/ide_assists/src/handlers/add_missing_impl_members.rs
@@ -3,9 +3,9 @@ use syntax::ast::{self, AstNode};
3 3
4use crate::{ 4use crate::{
5 assist_context::{AssistContext, Assists}, 5 assist_context::{AssistContext, Assists},
6 utils::add_trait_assoc_items_to_impl, 6 utils::{
7 utils::DefaultMethods, 7 add_trait_assoc_items_to_impl, filter_assoc_items, render_snippet, Cursor, DefaultMethods,
8 utils::{filter_assoc_items, render_snippet, Cursor}, 8 },
9 AssistId, AssistKind, 9 AssistId, AssistKind,
10}; 10};
11 11
diff --git a/crates/ide_assists/src/handlers/convert_comment_block.rs b/crates/ide_assists/src/handlers/convert_comment_block.rs
index 9dc3ee28f..d202a85f9 100644
--- a/crates/ide_assists/src/handlers/convert_comment_block.rs
+++ b/crates/ide_assists/src/handlers/convert_comment_block.rs
@@ -1,13 +1,6 @@
1use itertools::Itertools; 1use itertools::Itertools;
2use syntax::{ 2use syntax::{
3 ast::{ 3 ast::{self, edit::IndentLevel, Comment, CommentKind, CommentShape, Whitespace},
4 self,
5 edit::IndentLevel,
6 Comment, CommentKind,
7 CommentPlacement::{Inner, Outer},
8 CommentShape::{self, Block, Line},
9 Whitespace,
10 },
11 AstToken, Direction, SyntaxElement, TextRange, 4 AstToken, Direction, SyntaxElement, TextRange,
12}; 5};
13 6
@@ -29,21 +22,18 @@ use crate::{AssistContext, AssistId, AssistKind, Assists};
29/// */ 22/// */
30/// ``` 23/// ```
31pub(crate) fn convert_comment_block(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { 24pub(crate) fn convert_comment_block(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
32 if let Some(comment) = ctx.find_token_at_offset::<ast::Comment>() { 25 let comment = ctx.find_token_at_offset::<ast::Comment>()?;
33 // Only allow comments which are alone on their line 26 // Only allow comments which are alone on their line
34 if let Some(prev) = comment.syntax().prev_token() { 27 if let Some(prev) = comment.syntax().prev_token() {
35 if Whitespace::cast(prev).filter(|w| w.text().contains('\n')).is_none() { 28 if Whitespace::cast(prev).filter(|w| w.text().contains('\n')).is_none() {
36 return None; 29 return None;
37 }
38 } 30 }
39
40 return match comment.kind().shape {
41 ast::CommentShape::Block => block_to_line(acc, comment),
42 ast::CommentShape::Line => line_to_block(acc, comment),
43 };
44 } 31 }
45 32
46 return None; 33 match comment.kind().shape {
34 ast::CommentShape::Block => block_to_line(acc, comment),
35 ast::CommentShape::Line => line_to_block(acc, comment),
36 }
47} 37}
48 38
49fn block_to_line(acc: &mut Assists, comment: ast::Comment) -> Option<()> { 39fn block_to_line(acc: &mut Assists, comment: ast::Comment) -> Option<()> {
@@ -55,8 +45,7 @@ fn block_to_line(acc: &mut Assists, comment: ast::Comment) -> Option<()> {
55 target, 45 target,
56 |edit| { 46 |edit| {
57 let indentation = IndentLevel::from_token(comment.syntax()); 47 let indentation = IndentLevel::from_token(comment.syntax());
58 let line_prefix = 48 let line_prefix = CommentKind { shape: CommentShape::Line, ..comment.kind() }.prefix();
59 comment_kind_prefix(CommentKind { shape: CommentShape::Line, ..comment.kind() });
60 49
61 let text = comment.text(); 50 let text = comment.text();
62 let text = &text[comment.prefix().len()..(text.len() - "*/".len())].trim(); 51 let text = &text[comment.prefix().len()..(text.len() - "*/".len())].trim();
@@ -105,7 +94,7 @@ fn line_to_block(acc: &mut Assists, comment: ast::Comment) -> Option<()> {
105 comments.into_iter().map(|c| line_comment_text(indentation, c)).join("\n"); 94 comments.into_iter().map(|c| line_comment_text(indentation, c)).join("\n");
106 95
107 let block_prefix = 96 let block_prefix =
108 comment_kind_prefix(CommentKind { shape: CommentShape::Block, ..comment.kind() }); 97 CommentKind { shape: CommentShape::Block, ..comment.kind() }.prefix();
109 98
110 let output = 99 let output =
111 format!("{}\n{}\n{}*/", block_prefix, block_comment_body, indentation.to_string()); 100 format!("{}\n{}\n{}*/", block_prefix, block_comment_body, indentation.to_string());
@@ -182,17 +171,6 @@ fn line_comment_text(indentation: IndentLevel, comm: ast::Comment) -> String {
182 } 171 }
183} 172}
184 173
185fn comment_kind_prefix(ck: ast::CommentKind) -> &'static str {
186 match (ck.shape, ck.doc) {
187 (Line, Some(Inner)) => "//!",
188 (Line, Some(Outer)) => "///",
189 (Line, None) => "//",
190 (Block, Some(Inner)) => "/*!",
191 (Block, Some(Outer)) => "/**",
192 (Block, None) => "/*",
193 }
194}
195
196#[cfg(test)] 174#[cfg(test)]
197mod tests { 175mod tests {
198 use crate::tests::{check_assist, check_assist_not_applicable}; 176 use crate::tests::{check_assist, check_assist_not_applicable};
diff --git a/crates/ide_assists/src/handlers/reorder_fields.rs b/crates/ide_assists/src/handlers/reorder_fields.rs
index 794c89323..383ca6c47 100644
--- a/crates/ide_assists/src/handlers/reorder_fields.rs
+++ b/crates/ide_assists/src/handlers/reorder_fields.rs
@@ -1,9 +1,6 @@
1use itertools::Itertools;
2use rustc_hash::FxHashMap; 1use rustc_hash::FxHashMap;
3 2
4use hir::{Adt, ModuleDef, PathResolution, Semantics, Struct}; 3use syntax::{algo, ast, match_ast, AstNode, SyntaxKind::*, SyntaxNode};
5use ide_db::RootDatabase;
6use syntax::{algo, ast, match_ast, AstNode, SyntaxKind, SyntaxKind::*, SyntaxNode};
7 4
8use crate::{AssistContext, AssistId, AssistKind, Assists}; 5use crate::{AssistContext, AssistId, AssistKind, Assists};
9 6
@@ -23,26 +20,39 @@ use crate::{AssistContext, AssistId, AssistKind, Assists};
23// ``` 20// ```
24// 21//
25pub(crate) fn reorder_fields(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { 22pub(crate) fn reorder_fields(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
26 reorder::<ast::RecordExpr>(acc, ctx).or_else(|| reorder::<ast::RecordPat>(acc, ctx)) 23 let record = ctx
27} 24 .find_node_at_offset::<ast::RecordExpr>()
25 .map(|it| it.syntax().clone())
26 .or_else(|| ctx.find_node_at_offset::<ast::RecordPat>().map(|it| it.syntax().clone()))?;
28 27
29fn reorder<R: AstNode>(acc: &mut Assists, ctx: &AssistContext) -> Option<()> { 28 let path = record.children().find_map(ast::Path::cast)?;
30 let record = ctx.find_node_at_offset::<R>()?;
31 let path = record.syntax().children().find_map(ast::Path::cast)?;
32 29
33 let ranks = compute_fields_ranks(&path, &ctx)?; 30 let ranks = compute_fields_ranks(&path, &ctx)?;
34 31
35 let fields = get_fields(&record.syntax()); 32 let fields: Vec<SyntaxNode> = {
36 let sorted_fields = sorted_by_rank(&fields, |node| { 33 let field_kind = match record.kind() {
37 *ranks.get(&get_field_name(node)).unwrap_or(&usize::max_value()) 34 RECORD_EXPR => RECORD_EXPR_FIELD,
38 }); 35 RECORD_PAT => RECORD_PAT_FIELD,
36 _ => {
37 stdx::never!();
38 return None;
39 }
40 };
41 record.children().flat_map(|n| n.children()).filter(|n| n.kind() == field_kind).collect()
42 };
43
44 let sorted_fields = {
45 let mut fields = fields.clone();
46 fields.sort_by_key(|node| *ranks.get(&get_field_name(node)).unwrap_or(&usize::max_value()));
47 fields
48 };
39 49
40 if sorted_fields == fields { 50 if sorted_fields == fields {
41 cov_mark::hit!(reorder_sorted_fields); 51 cov_mark::hit!(reorder_sorted_fields);
42 return None; 52 return None;
43 } 53 }
44 54
45 let target = record.syntax().text_range(); 55 let target = record.text_range();
46 acc.add( 56 acc.add(
47 AssistId("reorder_fields", AssistKind::RefactorRewrite), 57 AssistId("reorder_fields", AssistKind::RefactorRewrite),
48 "Reorder record fields", 58 "Reorder record fields",
@@ -57,14 +67,6 @@ fn reorder<R: AstNode>(acc: &mut Assists, ctx: &AssistContext) -> Option<()> {
57 ) 67 )
58} 68}
59 69
60fn get_fields_kind(node: &SyntaxNode) -> Vec<SyntaxKind> {
61 match node.kind() {
62 RECORD_EXPR => vec![RECORD_EXPR_FIELD],
63 RECORD_PAT => vec![RECORD_PAT_FIELD, IDENT_PAT],
64 _ => vec![],
65 }
66}
67
68fn get_field_name(node: &SyntaxNode) -> String { 70fn get_field_name(node: &SyntaxNode) -> String {
69 let res = match_ast! { 71 let res = match_ast! {
70 match node { 72 match node {
@@ -76,34 +78,20 @@ fn get_field_name(node: &SyntaxNode) -> String {
76 res.unwrap_or_default() 78 res.unwrap_or_default()
77} 79}
78 80
79fn get_fields(record: &SyntaxNode) -> Vec<SyntaxNode> { 81fn compute_fields_ranks(path: &ast::Path, ctx: &AssistContext) -> Option<FxHashMap<String, usize>> {
80 let kinds = get_fields_kind(record); 82 let strukt = match ctx.sema.resolve_path(path) {
81 record.children().flat_map(|n| n.children()).filter(|n| kinds.contains(&n.kind())).collect() 83 Some(hir::PathResolution::Def(hir::ModuleDef::Adt(hir::Adt::Struct(it)))) => it,
82} 84 _ => return None,
83 85 };
84fn sorted_by_rank(
85 fields: &[SyntaxNode],
86 get_rank: impl Fn(&SyntaxNode) -> usize,
87) -> Vec<SyntaxNode> {
88 fields.iter().cloned().sorted_by_key(get_rank).collect()
89}
90 86
91fn struct_definition(path: &ast::Path, sema: &Semantics<RootDatabase>) -> Option<Struct> { 87 let res = strukt
92 match sema.resolve_path(path) { 88 .fields(ctx.db())
93 Some(PathResolution::Def(ModuleDef::Adt(Adt::Struct(s)))) => Some(s), 89 .iter()
94 _ => None, 90 .enumerate()
95 } 91 .map(|(idx, field)| (field.name(ctx.db()).to_string(), idx))
96} 92 .collect();
97 93
98fn compute_fields_ranks(path: &ast::Path, ctx: &AssistContext) -> Option<FxHashMap<String, usize>> { 94 Some(res)
99 Some(
100 struct_definition(path, &ctx.sema)?
101 .fields(ctx.db())
102 .iter()
103 .enumerate()
104 .map(|(idx, field)| (field.name(ctx.db()).to_string(), idx))
105 .collect(),
106 )
107} 95}
108 96
109#[cfg(test)] 97#[cfg(test)]
@@ -118,11 +106,7 @@ mod tests {
118 check_assist_not_applicable( 106 check_assist_not_applicable(
119 reorder_fields, 107 reorder_fields,
120 r#" 108 r#"
121struct Foo { 109struct Foo { foo: i32, bar: i32 }
122 foo: i32,
123 bar: i32,
124}
125
126const test: Foo = $0Foo { foo: 0, bar: 0 }; 110const test: Foo = $0Foo { foo: 0, bar: 0 };
127"#, 111"#,
128 ) 112 )
@@ -133,8 +117,8 @@ const test: Foo = $0Foo { foo: 0, bar: 0 };
133 check_assist_not_applicable( 117 check_assist_not_applicable(
134 reorder_fields, 118 reorder_fields,
135 r#" 119 r#"
136struct Foo {}; 120struct Foo {}
137const test: Foo = $0Foo {} 121const test: Foo = $0Foo {};
138"#, 122"#,
139 ) 123 )
140 } 124 }
@@ -144,12 +128,12 @@ const test: Foo = $0Foo {}
144 check_assist( 128 check_assist(
145 reorder_fields, 129 reorder_fields,
146 r#" 130 r#"
147struct Foo {foo: i32, bar: i32}; 131struct Foo { foo: i32, bar: i32 }
148const test: Foo = $0Foo {bar: 0, foo: 1} 132const test: Foo = $0Foo { bar: 0, foo: 1 };
149"#, 133"#,
150 r#" 134 r#"
151struct Foo {foo: i32, bar: i32}; 135struct Foo { foo: i32, bar: i32 }
152const test: Foo = Foo {foo: 1, bar: 0} 136const test: Foo = Foo { foo: 1, bar: 0 };
153"#, 137"#,
154 ) 138 )
155 } 139 }
@@ -186,10 +170,7 @@ fn f(f: Foo) -> {
186 check_assist( 170 check_assist(
187 reorder_fields, 171 reorder_fields,
188 r#" 172 r#"
189struct Foo { 173struct Foo { foo: String, bar: String }
190 foo: String,
191 bar: String,
192}
193 174
194impl Foo { 175impl Foo {
195 fn new() -> Foo { 176 fn new() -> Foo {
@@ -203,10 +184,7 @@ impl Foo {
203} 184}
204"#, 185"#,
205 r#" 186 r#"
206struct Foo { 187struct Foo { foo: String, bar: String }
207 foo: String,
208 bar: String,
209}
210 188
211impl Foo { 189impl Foo {
212 fn new() -> Foo { 190 fn new() -> Foo {