@@ -60,7 +60,7 @@ pub(crate) fn generate_documentation_template(
60
60
text_range,
61
61
|builder| {
62
62
// Introduction / short function description before the sections
63
- let mut doc_lines = vec ! [ introduction_builder( & ast_func, ctx) ] ;
63
+ let mut doc_lines = vec ! [ introduction_builder( & ast_func, ctx) . unwrap_or ( "." . into ( ) ) ] ;
64
64
// Then come the sections
65
65
if let Some ( mut lines) = examples_builder ( & ast_func, ctx) {
66
66
doc_lines. push ( "" . into ( ) ) ;
@@ -78,26 +78,64 @@ pub(crate) fn generate_documentation_template(
78
78
}
79
79
80
80
/// Builds an introduction, trying to be smart if the function is `::new()`
81
- fn introduction_builder ( ast_func : & ast:: Fn , ctx : & AssistContext ) -> String {
82
- || -> Option < String > {
83
- let hir_func = ctx. sema . to_def ( ast_func) ?;
84
- let container = hir_func. as_assoc_item ( ctx. db ( ) ) ?. container ( ctx. db ( ) ) ;
85
- if let hir:: AssocItemContainer :: Impl ( implementation) = container {
86
- let ret_ty = hir_func. ret_type ( ctx. db ( ) ) ;
87
- let self_ty = implementation. self_ty ( ctx. db ( ) ) ;
88
-
89
- let is_new = ast_func. name ( ) ?. to_string ( ) == "new" ;
90
- match is_new && ret_ty == self_ty {
91
- true => {
92
- Some ( format ! ( "Creates a new [`{}`]." , self_type_without_lifetimes( ast_func) ?) )
81
+ fn introduction_builder ( ast_func : & ast:: Fn , ctx : & AssistContext ) -> Option < String > {
82
+ let hir_func = ctx. sema . to_def ( ast_func) ?;
83
+ let container = hir_func. as_assoc_item ( ctx. db ( ) ) ?. container ( ctx. db ( ) ) ;
84
+ if let hir:: AssocItemContainer :: Impl ( imp) = container {
85
+ let ret_ty = hir_func. ret_type ( ctx. db ( ) ) ;
86
+ let self_ty = imp. self_ty ( ctx. db ( ) ) ;
87
+ let name = ast_func. name ( ) ?. to_string ( ) ;
88
+
89
+ let intro_for_new = || {
90
+ let is_new = name == "new" ;
91
+ if is_new && ret_ty == self_ty {
92
+ Some ( format ! ( "Creates a new [`{}`]." , self_type_without_lifetimes( ast_func) ?) )
93
+ } else {
94
+ None
95
+ }
96
+ } ;
97
+
98
+ let intro_for_getter = || match (
99
+ hir_func. self_param ( ctx. sema . db ) ,
100
+ & * hir_func. params_without_self ( ctx. sema . db ) ,
101
+ ) {
102
+ ( Some ( self_param) , [ ] ) if self_param. access ( ctx. sema . db ) != hir:: Access :: Owned => {
103
+ if name. starts_with ( "as_" ) || name. starts_with ( "to_" ) || name == "get" {
104
+ return None ;
93
105
}
94
- false => None ,
106
+ let what = name. trim_end_matches ( "_mut" ) . replace ( '_' , " " ) ;
107
+ let reference = if ret_ty. is_mutable_reference ( ) {
108
+ " a mutable reference to"
109
+ } else if ret_ty. is_reference ( ) {
110
+ " a reference to"
111
+ } else {
112
+ ""
113
+ } ;
114
+ Some ( format ! ( "Returns{reference} the {what}." ) )
95
115
}
96
- } else {
97
- None
116
+ _ => None ,
117
+ } ;
118
+
119
+ let intro_for_setter = || {
120
+ if !name. starts_with ( "set_" ) {
121
+ return None ;
122
+ }
123
+
124
+ let what = name. trim_start_matches ( "set_" ) . replace ( '_' , " " ) ;
125
+ Some ( format ! ( "Sets the {what}." ) )
126
+ } ;
127
+
128
+ if let Some ( intro) = intro_for_new ( ) {
129
+ return Some ( intro) ;
130
+ }
131
+ if let Some ( intro) = intro_for_getter ( ) {
132
+ return Some ( intro) ;
98
133
}
99
- } ( )
100
- . unwrap_or_else ( || "." . into ( ) )
134
+ if let Some ( intro) = intro_for_setter ( ) {
135
+ return Some ( intro) ;
136
+ }
137
+ }
138
+ None
101
139
}
102
140
103
141
/// Builds an `# Examples` section. An option is returned to be able to manage an error in the AST.
@@ -1220,6 +1258,197 @@ impl<T> MyGenericStruct<T> {
1220
1258
self.x = new_value;
1221
1259
}
1222
1260
}
1261
+ "# ,
1262
+ ) ;
1263
+ }
1264
+
1265
+ #[ test]
1266
+ fn generates_intro_for_getters ( ) {
1267
+ check_assist (
1268
+ generate_documentation_template,
1269
+ r#"
1270
+ pub struct S;
1271
+ impl S {
1272
+ pub fn speed$0(&self) -> f32 { 0.0 }
1273
+ }
1274
+ "# ,
1275
+ r#"
1276
+ pub struct S;
1277
+ impl S {
1278
+ /// Returns the speed.
1279
+ ///
1280
+ /// # Examples
1281
+ ///
1282
+ /// ```
1283
+ /// use test::S;
1284
+ ///
1285
+ /// let s = ;
1286
+ /// assert_eq!(s.speed(), );
1287
+ /// ```
1288
+ pub fn speed(&self) -> f32 { 0.0 }
1289
+ }
1290
+ "# ,
1291
+ ) ;
1292
+ check_assist (
1293
+ generate_documentation_template,
1294
+ r#"
1295
+ pub struct S;
1296
+ impl S {
1297
+ pub fn data$0(&self) -> &[u8] { &[] }
1298
+ }
1299
+ "# ,
1300
+ r#"
1301
+ pub struct S;
1302
+ impl S {
1303
+ /// Returns a reference to the data.
1304
+ ///
1305
+ /// # Examples
1306
+ ///
1307
+ /// ```
1308
+ /// use test::S;
1309
+ ///
1310
+ /// let s = ;
1311
+ /// assert_eq!(s.data(), );
1312
+ /// ```
1313
+ pub fn data(&self) -> &[u8] { &[] }
1314
+ }
1315
+ "# ,
1316
+ ) ;
1317
+ check_assist (
1318
+ generate_documentation_template,
1319
+ r#"
1320
+ pub struct S;
1321
+ impl S {
1322
+ pub fn data$0(&mut self) -> &mut [u8] { &mut [] }
1323
+ }
1324
+ "# ,
1325
+ r#"
1326
+ pub struct S;
1327
+ impl S {
1328
+ /// Returns a mutable reference to the data.
1329
+ ///
1330
+ /// # Examples
1331
+ ///
1332
+ /// ```
1333
+ /// use test::S;
1334
+ ///
1335
+ /// let mut s = ;
1336
+ /// assert_eq!(s.data(), );
1337
+ /// assert_eq!(s, );
1338
+ /// ```
1339
+ pub fn data(&mut self) -> &mut [u8] { &mut [] }
1340
+ }
1341
+ "# ,
1342
+ ) ;
1343
+ check_assist (
1344
+ generate_documentation_template,
1345
+ r#"
1346
+ pub struct S;
1347
+ impl S {
1348
+ pub fn data_mut$0(&mut self) -> &mut [u8] { &mut [] }
1349
+ }
1350
+ "# ,
1351
+ r#"
1352
+ pub struct S;
1353
+ impl S {
1354
+ /// Returns a mutable reference to the data.
1355
+ ///
1356
+ /// # Examples
1357
+ ///
1358
+ /// ```
1359
+ /// use test::S;
1360
+ ///
1361
+ /// let mut s = ;
1362
+ /// assert_eq!(s.data_mut(), );
1363
+ /// assert_eq!(s, );
1364
+ /// ```
1365
+ pub fn data_mut(&mut self) -> &mut [u8] { &mut [] }
1366
+ }
1367
+ "# ,
1368
+ ) ;
1369
+ }
1370
+
1371
+ #[ test]
1372
+ fn no_getter_intro_for_prefixed_methods ( ) {
1373
+ check_assist (
1374
+ generate_documentation_template,
1375
+ r#"
1376
+ pub struct S;
1377
+ impl S {
1378
+ pub fn as_bytes$0(&self) -> &[u8] { &[] }
1379
+ }
1380
+ "# ,
1381
+ r#"
1382
+ pub struct S;
1383
+ impl S {
1384
+ /// .
1385
+ ///
1386
+ /// # Examples
1387
+ ///
1388
+ /// ```
1389
+ /// use test::S;
1390
+ ///
1391
+ /// let s = ;
1392
+ /// assert_eq!(s.as_bytes(), );
1393
+ /// ```
1394
+ pub fn as_bytes(&self) -> &[u8] { &[] }
1395
+ }
1396
+ "# ,
1397
+ ) ;
1398
+ }
1399
+
1400
+ #[ test]
1401
+ fn generates_intro_for_setters ( ) {
1402
+ check_assist (
1403
+ generate_documentation_template,
1404
+ r#"
1405
+ pub struct S;
1406
+ impl S {
1407
+ pub fn set_data$0(&mut self, data: Vec<u8>) {}
1408
+ }
1409
+ "# ,
1410
+ r#"
1411
+ pub struct S;
1412
+ impl S {
1413
+ /// Sets the data.
1414
+ ///
1415
+ /// # Examples
1416
+ ///
1417
+ /// ```
1418
+ /// use test::S;
1419
+ ///
1420
+ /// let mut s = ;
1421
+ /// s.set_data(data);
1422
+ /// assert_eq!(s, );
1423
+ /// ```
1424
+ pub fn set_data(&mut self, data: Vec<u8>) {}
1425
+ }
1426
+ "# ,
1427
+ ) ;
1428
+ check_assist (
1429
+ generate_documentation_template,
1430
+ r#"
1431
+ pub struct S;
1432
+ impl S {
1433
+ pub fn set_domain_name$0(&mut self, name: String) {}
1434
+ }
1435
+ "# ,
1436
+ r#"
1437
+ pub struct S;
1438
+ impl S {
1439
+ /// Sets the domain name.
1440
+ ///
1441
+ /// # Examples
1442
+ ///
1443
+ /// ```
1444
+ /// use test::S;
1445
+ ///
1446
+ /// let mut s = ;
1447
+ /// s.set_domain_name(name);
1448
+ /// assert_eq!(s, );
1449
+ /// ```
1450
+ pub fn set_domain_name(&mut self, name: String) {}
1451
+ }
1223
1452
"# ,
1224
1453
) ;
1225
1454
}
0 commit comments