Skip to content

Commit 471c41a

Browse files
committed
Fix indent for trait_impl_redundant_assoc_item
Example --- ```rust trait Foo { } impl Foo for () { $0fn foo<T: Copy>(&self); } ``` **Before this PR**: ```rust trait Foo { fn foo<T>(&self) where T: Copy,; } impl Foo for () { fn foo<T: Copy>(&self); } ``` **After this PR**: ```rust trait Foo { fn foo<T>(&self) where T: Copy,; } impl Foo for () { fn foo<T: Copy>(&self); } ```
1 parent 8192c63 commit 471c41a

File tree

2 files changed

+114
-7
lines changed

2 files changed

+114
-7
lines changed

crates/ide-diagnostics/src/handlers/trait_impl_redundant_assoc_item.rs

Lines changed: 90 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ use ide_db::{
66
source_change::SourceChangeBuilder,
77
};
88
use syntax::ToSmolStr;
9+
use syntax::ast::edit::AstNodeEdit;
910

1011
use crate::{Diagnostic, DiagnosticCode, DiagnosticsContext};
1112

@@ -23,33 +24,32 @@ pub(crate) fn trait_impl_redundant_assoc_item(
2324

2425
let default_range = d.impl_.syntax_node_ptr().text_range();
2526
let trait_name = d.trait_.name(db).display_no_db(ctx.edition).to_smolstr();
27+
let indent_level = d.trait_.source(db).map_or(0, |it| it.value.indent_level().0) + 1;
2628

2729
let (redundant_item_name, diagnostic_range, redundant_item_def) = match assoc_item {
2830
hir::AssocItem::Function(id) => {
2931
let function = id;
3032
(
3133
format!("`fn {redundant_assoc_item_name}`"),
3234
function.source(db).map(|it| it.syntax().text_range()).unwrap_or(default_range),
33-
format!("\n {};", function.display(db, ctx.display_target)),
35+
format!("\n{};", function.display(db, ctx.display_target)),
3436
)
3537
}
3638
hir::AssocItem::Const(id) => {
3739
let constant = id;
3840
(
3941
format!("`const {redundant_assoc_item_name}`"),
4042
constant.source(db).map(|it| it.syntax().text_range()).unwrap_or(default_range),
41-
format!("\n {};", constant.display(db, ctx.display_target)),
43+
format!("\n{};", constant.display(db, ctx.display_target)),
4244
)
4345
}
4446
hir::AssocItem::TypeAlias(id) => {
4547
let type_alias = id;
4648
(
4749
format!("`type {redundant_assoc_item_name}`"),
4850
type_alias.source(db).map(|it| it.syntax().text_range()).unwrap_or(default_range),
49-
format!(
50-
"\n type {};",
51-
type_alias.name(ctx.sema.db).display_no_db(ctx.edition).to_smolstr()
52-
),
51+
// FIXME cannot generate generic parameter and bounds
52+
format!("\ntype {};", type_alias.name(ctx.sema.db).display_no_db(ctx.edition)),
5353
)
5454
}
5555
};
@@ -65,7 +65,7 @@ pub(crate) fn trait_impl_redundant_assoc_item(
6565
.with_fixes(quickfix_for_redundant_assoc_item(
6666
ctx,
6767
d,
68-
redundant_item_def,
68+
stdx::indent_string(redundant_item_def, indent_level).into(),
6969
diagnostic_range,
7070
))
7171
}
@@ -191,6 +191,89 @@ impl Marker for Foo {
191191
)
192192
}
193193

194+
#[test]
195+
fn quickfix_indentations() {
196+
check_fix(
197+
r#"
198+
mod indent {
199+
trait Marker {
200+
fn boo();
201+
}
202+
struct Foo;
203+
impl Marker for Foo {
204+
fn$0 bar<T: Copy>(_a: i32, _b: T) -> String {}
205+
fn boo() {}
206+
}
207+
}
208+
"#,
209+
r#"
210+
mod indent {
211+
trait Marker {
212+
fn bar<T>(_a: i32, _b: T) -> String
213+
where
214+
T: Copy,;
215+
fn boo();
216+
}
217+
struct Foo;
218+
impl Marker for Foo {
219+
fn bar<T: Copy>(_a: i32, _b: T) -> String {}
220+
fn boo() {}
221+
}
222+
}
223+
"#,
224+
);
225+
226+
check_fix(
227+
r#"
228+
mod indent {
229+
trait Marker {
230+
fn foo () {}
231+
}
232+
struct Foo;
233+
impl Marker for Foo {
234+
const FLAG: bool$0 = false;
235+
}
236+
}
237+
"#,
238+
r#"
239+
mod indent {
240+
trait Marker {
241+
const FLAG: bool;
242+
fn foo () {}
243+
}
244+
struct Foo;
245+
impl Marker for Foo {
246+
const FLAG: bool = false;
247+
}
248+
}
249+
"#,
250+
);
251+
252+
check_fix(
253+
r#"
254+
mod indent {
255+
trait Marker {
256+
}
257+
struct Foo;
258+
impl Marker for Foo {
259+
type T = i32;$0
260+
}
261+
}
262+
"#,
263+
r#"
264+
mod indent {
265+
trait Marker {
266+
type T;
267+
}
268+
struct Foo;
269+
impl Marker for Foo {
270+
type T = i32;
271+
}
272+
}
273+
"#,
274+
);
275+
}
276+
194277
#[test]
195278
fn quickfix_dont_work() {
196279
check_no_fix(

crates/stdx/src/lib.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
//! Missing batteries for standard libraries.
22
3+
use std::borrow::Cow;
34
use std::io as sio;
45
use std::process::Command;
56
use std::{cmp::Ordering, ops, time::Instant};
@@ -214,6 +215,29 @@ pub fn trim_indent(mut text: &str) -> String {
214215
.collect()
215216
}
216217

218+
/// Indent non empty lines, including the first line
219+
#[must_use]
220+
pub fn indent_string<'a, S>(s: S, indent_level: u8) -> Cow<'a, str>
221+
where
222+
Cow<'a, str>: From<S>,
223+
{
224+
let s = Cow::from(s);
225+
if indent_level == 0 || s.is_empty() {
226+
return s;
227+
}
228+
let indent_str = " ".repeat(indent_level as usize);
229+
s.split_inclusive("\n")
230+
.map(|line| {
231+
if line.trim_end().is_empty() {
232+
Cow::Borrowed(line)
233+
} else {
234+
format!("{indent_str}{line}").into()
235+
}
236+
})
237+
.collect::<String>()
238+
.into()
239+
}
240+
217241
pub fn equal_range_by<T, F>(slice: &[T], mut key: F) -> ops::Range<usize>
218242
where
219243
F: FnMut(&T) -> Ordering,

0 commit comments

Comments
 (0)