@@ -89,7 +89,7 @@ fn introduction_builder(ast_func: &ast::Fn, ctx: &AssistContext) -> String {
89
89
let is_new = ast_func. name ( ) ?. to_string ( ) == "new" ;
90
90
match is_new && ret_ty == self_ty {
91
91
true => {
92
- Some ( format ! ( "Creates a new [`{}`]." , lifetimes_removed ( & self_type ( ast_func) ?) ) )
92
+ Some ( format ! ( "Creates a new [`{}`]." , self_type_without_lifetimes ( ast_func) ?) )
93
93
}
94
94
false => None ,
95
95
}
@@ -223,61 +223,32 @@ fn self_name(ast_func: &ast::Fn) -> Option<String> {
223
223
}
224
224
225
225
/// Heper function to get the name of the type of `self`
226
- fn self_type ( ast_func : & ast:: Fn ) -> Option < String > {
227
- ast_func
228
- . syntax ( )
229
- . ancestors ( )
230
- . find_map ( ast:: Impl :: cast)
231
- . and_then ( |i| i. self_ty ( ) )
232
- . 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 ( ) )
233
228
}
234
229
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
- }
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 =
233
+ ast:: PathType :: cast ( self_type ( ast_func) ?. syntax ( ) . clone ( ) ) ?. path ( ) ?. segment ( ) ?;
234
+ let mut name = path_segment. name_ref ( ) ?. to_string ( ) ;
235
+ let generics = path_segment
236
+ . generic_arg_list ( ) ?
237
+ . generic_args ( )
238
+ . filter ( |generic| matches ! ( generic, ast:: GenericArg :: TypeArg ( _) ) )
239
+ . map ( |generic| generic. to_string ( ) ) ;
240
+ let generics: String = Itertools :: intersperse ( generics, ", " . to_string ( ) ) . collect ( ) ;
241
+ if !generics. is_empty ( ) {
242
+ name. push ( '<' ) ;
243
+ name. push_str ( & generics) ;
244
+ name. push ( '>' ) ;
274
245
}
275
- without_lifetimes
246
+ Some ( name )
276
247
}
277
248
278
249
/// Heper function to get the name of the type of `self` without generic arguments
279
250
fn self_partial_type ( ast_func : & ast:: Fn ) -> Option < String > {
280
- let mut self_type = self_type ( ast_func) ?;
251
+ let mut self_type = self_type ( ast_func) ?. to_string ( ) ;
281
252
if let Some ( idx) = self_type. find ( |c| [ '<' , ' ' ] . contains ( & c) ) {
282
253
self_type. truncate ( idx) ;
283
254
}
@@ -1114,6 +1085,46 @@ impl<'a, 'b, T> MyGenericStruct<'a, 'b, T> {
1114
1085
) ;
1115
1086
}
1116
1087
1088
+ #[ test]
1089
+ fn removes_all_lifetimes_and_brackets_from_description ( ) {
1090
+ check_assist (
1091
+ generate_documentation_template,
1092
+ r#"
1093
+ #[derive(Debug, PartialEq)]
1094
+ pub struct MyGenericStruct<'a, 'b> {
1095
+ pub x: &'a usize,
1096
+ pub y: &'b usize,
1097
+ }
1098
+ impl<'a, 'b> MyGenericStruct<'a, 'b> {
1099
+ pub fn new$0(x: &'a usize, y: &'b usize) -> Self {
1100
+ MyGenericStruct { x, y }
1101
+ }
1102
+ }
1103
+ "# ,
1104
+ r#"
1105
+ #[derive(Debug, PartialEq)]
1106
+ pub struct MyGenericStruct<'a, 'b> {
1107
+ pub x: &'a usize,
1108
+ pub y: &'b usize,
1109
+ }
1110
+ impl<'a, 'b> MyGenericStruct<'a, 'b> {
1111
+ /// Creates a new [`MyGenericStruct`].
1112
+ ///
1113
+ /// # Examples
1114
+ ///
1115
+ /// ```
1116
+ /// use test::MyGenericStruct;
1117
+ ///
1118
+ /// assert_eq!(MyGenericStruct::new(x, y), );
1119
+ /// ```
1120
+ pub fn new(x: &'a usize, y: &'b usize) -> Self {
1121
+ MyGenericStruct { x, y }
1122
+ }
1123
+ }
1124
+ "# ,
1125
+ ) ;
1126
+ }
1127
+
1117
1128
#[ test]
1118
1129
fn detects_new_with_self ( ) {
1119
1130
check_assist (
0 commit comments