Skip to content

Commit c09504b

Browse files
bors[bot]Côme ALLART
andauthored
Merge #11194
11194: fix(gen-doc-assist): remove lifetimes in description of `new` r=Veykril a=numero-744 From wrong behavior: ```rust /// Creates a new [`MyGenericStruct<'a, T>`]. ``` to correct behavior: ```rust /// Creates a new [`MyGenericStruct<T>`]. ``` But I feel like there is a better way to implement it. Do you know if there is an existing function that could do the work of `lifetimes_removed()` below? Co-authored-by: Côme ALLART <[email protected]>
2 parents 2fb6f5e + 1b5c60f commit c09504b

File tree

1 file changed

+146
-10
lines changed

1 file changed

+146
-10
lines changed

crates/ide_assists/src/handlers/generate_documentation_template.rs

Lines changed: 146 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,9 @@ fn introduction_builder(ast_func: &ast::Fn, ctx: &AssistContext) -> String {
8888

8989
let is_new = ast_func.name()?.to_string() == "new";
9090
match is_new && ret_ty == self_ty {
91-
true => Some(format!("Creates a new [`{}`].", self_type(ast_func)?)),
91+
true => {
92+
Some(format!("Creates a new [`{}`].", self_type_without_lifetimes(ast_func)?))
93+
}
9294
false => None,
9395
}
9496
} else {
@@ -221,18 +223,34 @@ fn self_name(ast_func: &ast::Fn) -> Option<String> {
221223
}
222224

223225
/// Heper function to get the name of the type of `self`
224-
fn self_type(ast_func: &ast::Fn) -> Option<String> {
225-
ast_func
226-
.syntax()
227-
.ancestors()
228-
.find_map(ast::Impl::cast)
229-
.and_then(|i| i.self_ty())
230-
.map(|t| (t.to_string()))
226+
fn self_type(ast_func: &ast::Fn) -> Option<ast::Type> {
227+
ast_func.syntax().ancestors().find_map(ast::Impl::cast).and_then(|i| i.self_ty())
228+
}
229+
230+
/// Output the real name of `Self` like `MyType<T>`, without the lifetimes.
231+
fn self_type_without_lifetimes(ast_func: &ast::Fn) -> Option<String> {
232+
let path_segment = match self_type(ast_func)? {
233+
ast::Type::PathType(path_type) => path_type.path()?.segment()?,
234+
_ => return None,
235+
};
236+
let mut name = path_segment.name_ref()?.to_string();
237+
let generics = path_segment
238+
.generic_arg_list()?
239+
.generic_args()
240+
.filter(|generic| matches!(generic, ast::GenericArg::TypeArg(_)))
241+
.map(|generic| generic.to_string());
242+
let generics: String = generics.format(", ").to_string();
243+
if !generics.is_empty() {
244+
name.push('<');
245+
name.push_str(&generics);
246+
name.push('>');
247+
}
248+
Some(name)
231249
}
232250

233251
/// Heper function to get the name of the type of `self` without generic arguments
234252
fn self_partial_type(ast_func: &ast::Fn) -> Option<String> {
235-
let mut self_type = self_type(ast_func)?;
253+
let mut self_type = self_type(ast_func)?.to_string();
236254
if let Some(idx) = self_type.find(|c| ['<', ' '].contains(&c)) {
237255
self_type.truncate(idx);
238256
}
@@ -309,7 +327,7 @@ fn arguments_from_params(param_list: &ast::ParamList) -> String {
309327
},
310328
_ => "_".to_string(),
311329
});
312-
Itertools::intersperse(args_iter, ", ".to_string()).collect()
330+
args_iter.format(", ").to_string()
313331
}
314332

315333
/// Helper function to build a function call. `None` if expected `self_name` was not provided
@@ -991,6 +1009,124 @@ impl<T> MyGenericStruct<T> {
9911009
);
9921010
}
9931011

1012+
#[test]
1013+
fn removes_one_lifetime_from_description() {
1014+
check_assist(
1015+
generate_documentation_template,
1016+
r#"
1017+
#[derive(Debug, PartialEq)]
1018+
pub struct MyGenericStruct<'a, T> {
1019+
pub x: &'a T,
1020+
}
1021+
impl<'a, T> MyGenericStruct<'a, T> {
1022+
pub fn new$0(x: &'a T) -> Self {
1023+
MyGenericStruct { x }
1024+
}
1025+
}
1026+
"#,
1027+
r#"
1028+
#[derive(Debug, PartialEq)]
1029+
pub struct MyGenericStruct<'a, T> {
1030+
pub x: &'a T,
1031+
}
1032+
impl<'a, T> MyGenericStruct<'a, T> {
1033+
/// Creates a new [`MyGenericStruct<T>`].
1034+
///
1035+
/// # Examples
1036+
///
1037+
/// ```
1038+
/// use test::MyGenericStruct;
1039+
///
1040+
/// assert_eq!(MyGenericStruct::new(x), );
1041+
/// ```
1042+
pub fn new(x: &'a T) -> Self {
1043+
MyGenericStruct { x }
1044+
}
1045+
}
1046+
"#,
1047+
);
1048+
}
1049+
1050+
#[test]
1051+
fn removes_all_lifetimes_from_description() {
1052+
check_assist(
1053+
generate_documentation_template,
1054+
r#"
1055+
#[derive(Debug, PartialEq)]
1056+
pub struct MyGenericStruct<'a, 'b, T> {
1057+
pub x: &'a T,
1058+
pub y: &'b T,
1059+
}
1060+
impl<'a, 'b, T> MyGenericStruct<'a, 'b, T> {
1061+
pub fn new$0(x: &'a T, y: &'b T) -> Self {
1062+
MyGenericStruct { x, y }
1063+
}
1064+
}
1065+
"#,
1066+
r#"
1067+
#[derive(Debug, PartialEq)]
1068+
pub struct MyGenericStruct<'a, 'b, T> {
1069+
pub x: &'a T,
1070+
pub y: &'b T,
1071+
}
1072+
impl<'a, 'b, T> MyGenericStruct<'a, 'b, T> {
1073+
/// Creates a new [`MyGenericStruct<T>`].
1074+
///
1075+
/// # Examples
1076+
///
1077+
/// ```
1078+
/// use test::MyGenericStruct;
1079+
///
1080+
/// assert_eq!(MyGenericStruct::new(x, y), );
1081+
/// ```
1082+
pub fn new(x: &'a T, y: &'b T) -> Self {
1083+
MyGenericStruct { x, y }
1084+
}
1085+
}
1086+
"#,
1087+
);
1088+
}
1089+
1090+
#[test]
1091+
fn removes_all_lifetimes_and_brackets_from_description() {
1092+
check_assist(
1093+
generate_documentation_template,
1094+
r#"
1095+
#[derive(Debug, PartialEq)]
1096+
pub struct MyGenericStruct<'a, 'b> {
1097+
pub x: &'a usize,
1098+
pub y: &'b usize,
1099+
}
1100+
impl<'a, 'b> MyGenericStruct<'a, 'b> {
1101+
pub fn new$0(x: &'a usize, y: &'b usize) -> Self {
1102+
MyGenericStruct { x, y }
1103+
}
1104+
}
1105+
"#,
1106+
r#"
1107+
#[derive(Debug, PartialEq)]
1108+
pub struct MyGenericStruct<'a, 'b> {
1109+
pub x: &'a usize,
1110+
pub y: &'b usize,
1111+
}
1112+
impl<'a, 'b> MyGenericStruct<'a, 'b> {
1113+
/// Creates a new [`MyGenericStruct`].
1114+
///
1115+
/// # Examples
1116+
///
1117+
/// ```
1118+
/// use test::MyGenericStruct;
1119+
///
1120+
/// assert_eq!(MyGenericStruct::new(x, y), );
1121+
/// ```
1122+
pub fn new(x: &'a usize, y: &'b usize) -> Self {
1123+
MyGenericStruct { x, y }
1124+
}
1125+
}
1126+
"#,
1127+
);
1128+
}
1129+
9941130
#[test]
9951131
fn detects_new_with_self() {
9961132
check_assist(

0 commit comments

Comments
 (0)