@@ -88,7 +88,9 @@ fn introduction_builder(ast_func: &ast::Fn, ctx: &AssistContext) -> String {
88
88
89
89
let is_new = ast_func. name ( ) ?. to_string ( ) == "new" ;
90
90
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 [`{}`]." , lifetimes_removed( & self_type( ast_func) ?) ) )
93
+ }
92
94
false => None ,
93
95
}
94
96
} else {
@@ -230,6 +232,49 @@ fn self_type(ast_func: &ast::Fn) -> Option<String> {
230
232
. map ( |t| ( t. to_string ( ) ) )
231
233
}
232
234
235
+ /// Output the same string as the input, removing lifetimes.
236
+ ///
237
+ /// Lifetimes are detected as starting with a `'` and ending with `,\s*` or before a `>`.
238
+ fn lifetimes_removed ( with_lifetimes : & str ) -> String {
239
+ #[ derive( Debug ) ]
240
+ enum State {
241
+ OutOfLifetime ,
242
+ AfterLifetime ,
243
+ InLifetime ,
244
+ }
245
+
246
+ let mut state = State :: OutOfLifetime ;
247
+ let mut without_lifetimes = String :: new ( ) ;
248
+ for c in with_lifetimes. chars ( ) {
249
+ match state {
250
+ State :: OutOfLifetime => {
251
+ if c == '\'' {
252
+ state = State :: InLifetime ;
253
+ } else {
254
+ without_lifetimes. push ( c) ;
255
+ }
256
+ }
257
+ State :: InLifetime => {
258
+ if c == ',' {
259
+ state = State :: AfterLifetime ;
260
+ } else if c == '>' {
261
+ without_lifetimes. push ( c) ;
262
+ state = State :: OutOfLifetime ;
263
+ }
264
+ }
265
+ State :: AfterLifetime => {
266
+ if c == '\'' {
267
+ state = State :: InLifetime ;
268
+ } else if !c. is_whitespace ( ) {
269
+ without_lifetimes. push ( c) ;
270
+ state = State :: OutOfLifetime ;
271
+ }
272
+ }
273
+ }
274
+ }
275
+ without_lifetimes
276
+ }
277
+
233
278
/// Heper function to get the name of the type of `self` without generic arguments
234
279
fn self_partial_type ( ast_func : & ast:: Fn ) -> Option < String > {
235
280
let mut self_type = self_type ( ast_func) ?;
@@ -991,6 +1036,84 @@ impl<T> MyGenericStruct<T> {
991
1036
) ;
992
1037
}
993
1038
1039
+ #[ test]
1040
+ fn removes_one_lifetime_from_description ( ) {
1041
+ check_assist (
1042
+ generate_documentation_template,
1043
+ r#"
1044
+ #[derive(Debug, PartialEq)]
1045
+ pub struct MyGenericStruct<'a, T> {
1046
+ pub x: &'a T,
1047
+ }
1048
+ impl<'a, T> MyGenericStruct<'a, T> {
1049
+ pub fn new$0(x: &'a T) -> Self {
1050
+ MyGenericStruct { x }
1051
+ }
1052
+ }
1053
+ "# ,
1054
+ r#"
1055
+ #[derive(Debug, PartialEq)]
1056
+ pub struct MyGenericStruct<'a, T> {
1057
+ pub x: &'a T,
1058
+ }
1059
+ impl<'a, T> MyGenericStruct<'a, T> {
1060
+ /// Creates a new [`MyGenericStruct<T>`].
1061
+ ///
1062
+ /// # Examples
1063
+ ///
1064
+ /// ```
1065
+ /// use test::MyGenericStruct;
1066
+ ///
1067
+ /// assert_eq!(MyGenericStruct::new(x), );
1068
+ /// ```
1069
+ pub fn new(x: &'a T) -> Self {
1070
+ MyGenericStruct { x }
1071
+ }
1072
+ }
1073
+ "# ,
1074
+ ) ;
1075
+ }
1076
+
1077
+ #[ test]
1078
+ fn removes_all_lifetimes_from_description ( ) {
1079
+ check_assist (
1080
+ generate_documentation_template,
1081
+ r#"
1082
+ #[derive(Debug, PartialEq)]
1083
+ pub struct MyGenericStruct<'a, 'b, T> {
1084
+ pub x: &'a T,
1085
+ pub y: &'b T,
1086
+ }
1087
+ impl<'a, 'b, T> MyGenericStruct<'a, 'b, T> {
1088
+ pub fn new$0(x: &'a T, y: &'b T) -> Self {
1089
+ MyGenericStruct { x, y }
1090
+ }
1091
+ }
1092
+ "# ,
1093
+ r#"
1094
+ #[derive(Debug, PartialEq)]
1095
+ pub struct MyGenericStruct<'a, 'b, T> {
1096
+ pub x: &'a T,
1097
+ pub y: &'b T,
1098
+ }
1099
+ impl<'a, 'b, T> MyGenericStruct<'a, 'b, T> {
1100
+ /// Creates a new [`MyGenericStruct<T>`].
1101
+ ///
1102
+ /// # Examples
1103
+ ///
1104
+ /// ```
1105
+ /// use test::MyGenericStruct;
1106
+ ///
1107
+ /// assert_eq!(MyGenericStruct::new(x, y), );
1108
+ /// ```
1109
+ pub fn new(x: &'a T, y: &'b T) -> Self {
1110
+ MyGenericStruct { x, y }
1111
+ }
1112
+ }
1113
+ "# ,
1114
+ ) ;
1115
+ }
1116
+
994
1117
#[ test]
995
1118
fn detects_new_with_self ( ) {
996
1119
check_assist (
0 commit comments