@@ -60,7 +60,7 @@ pub(crate) fn generate_documentation_template(
6060 text_range,
6161 |builder| {
6262 // 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 ( ) ) ] ;
6464 // Then come the sections
6565 if let Some ( mut lines) = examples_builder ( & ast_func, ctx) {
6666 doc_lines. push ( "" . into ( ) ) ;
@@ -78,26 +78,64 @@ pub(crate) fn generate_documentation_template(
7878}
7979
8080/// 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 ;
93105 }
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}." ) )
95115 }
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) ;
98133 }
99- } ( )
100- . unwrap_or_else ( || "." . into ( ) )
134+ if let Some ( intro) = intro_for_setter ( ) {
135+ return Some ( intro) ;
136+ }
137+ }
138+ None
101139}
102140
103141/// 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> {
12201258 self.x = new_value;
12211259 }
12221260}
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+ }
12231452"# ,
12241453 ) ;
12251454 }
0 commit comments