@@ -11,12 +11,12 @@ use crate::{AssistContext, AssistId, AssistKind, Assists};
1111// Converts comments to documentation.
1212//
1313// ```
14- // // Wow what $0a nice function
14+ // // Wow what $0a nice module
1515// // I sure hope this shows up when I hover over it
1616// ```
1717// ->
1818// ```
19- // //! Wow what a nice function
19+ // //! Wow what a nice module
2020// //! I sure hope this shows up when I hover over it
2121// ```
2222pub ( crate ) fn convert_comment_from_or_to_doc (
@@ -43,7 +43,7 @@ fn doc_to_comment(acc: &mut Assists, comment: ast::Comment) -> Option<()> {
4343
4444 acc. add (
4545 AssistId ( "doc_to_comment" , AssistKind :: RefactorRewrite ) ,
46- "Replace a comment with doc comment" ,
46+ "Replace comment with doc comment" ,
4747 target,
4848 |edit| {
4949 // We need to either replace the first occurrence of /* with /***, or we need to replace
@@ -52,11 +52,12 @@ fn doc_to_comment(acc: &mut Assists, comment: ast::Comment) -> Option<()> {
5252 ast:: CommentShape :: Line => {
5353 let indentation = IndentLevel :: from_token ( comment. syntax ( ) ) ;
5454 let line_start = comment. prefix ( ) ;
55+ let prefix = format ! ( "{indentation}//" ) ;
5556 relevant_line_comments ( & comment)
5657 . iter ( )
5758 . map ( |comment| comment. text ( ) )
5859 . flat_map ( |text| text. lines ( ) )
59- . map ( |line| indentation . to_string ( ) + & line. replacen ( line_start, "//" , 1 ) )
60+ . map ( |line| line. replacen ( line_start, & prefix , 1 ) )
6061 . join ( "\n " )
6162 }
6263 ast:: CommentShape :: Block => {
@@ -89,23 +90,23 @@ fn comment_to_doc(acc: &mut Assists, comment: ast::Comment, style: CommentPlacem
8990
9091 acc. add (
9192 AssistId ( "comment_to_doc" , AssistKind :: RefactorRewrite ) ,
92- "Replace a doc comment with comment" ,
93+ "Replace doc comment with comment" ,
9394 target,
9495 |edit| {
9596 // We need to either replace the first occurrence of /* with /***, or we need to replace
9697 // the occurrences // at the start of each line with ///
9798 let output = match comment. kind ( ) . shape {
9899 ast:: CommentShape :: Line => {
100+ let indentation = IndentLevel :: from_token ( comment. syntax ( ) ) ;
99101 let line_start = match style {
100- CommentPlacement :: Inner => " //!",
101- CommentPlacement :: Outer => " ///",
102+ CommentPlacement :: Inner => format ! ( "{indentation} //!") ,
103+ CommentPlacement :: Outer => format ! ( "{indentation} ///") ,
102104 } ;
103- let indentation = IndentLevel :: from_token ( comment. syntax ( ) ) ;
104105 relevant_line_comments ( & comment)
105106 . iter ( )
106107 . map ( |comment| comment. text ( ) )
107108 . flat_map ( |text| text. lines ( ) )
108- . map ( |line| indentation . to_string ( ) + & line. replacen ( "//" , line_start, 1 ) )
109+ . map ( |line| line. replacen ( "//" , & line_start, 1 ) )
109110 . join ( "\n " )
110111 }
111112 ast:: CommentShape :: Block => {
@@ -139,29 +140,45 @@ fn comment_to_doc(acc: &mut Assists, comment: ast::Comment, style: CommentPlacem
139140/// Not all comments are valid candidates for conversion into doc comments. For example, the
140141/// comments in the code:
141142/// ```rust
142- /// // foos the bar
143- /// fn foo_bar(foo: Foo) -> Bar {
144- /// // Bar the foo
145- /// foo.into_bar()
146- /// }
143+ /// // Brilliant module right here
147144///
148- /// trait A {
149- /// // The A trait
145+ /// // Really good right
146+ /// fn good_function(foo: Foo) -> Bar {
147+ /// foo.into_bar()
150148/// }
149+ ///
150+ /// // So nice
151+ /// mod nice_module {}
151152/// ```
152153/// can be converted to doc comments. However, the comments in this example:
153154/// ```rust
154155/// fn foo_bar(foo: Foo /* not bar yet */) -> Bar {
155- /// foo.into_bar()
156- /// // Nicely done
156+ /// foo.into_bar()
157+ /// // Nicely done
157158/// }
158159/// // end of function
159160///
160161/// struct S {
161162/// // The S struct
162163/// }
163164/// ```
164- /// are not allowed to become doc comments.
165+ /// are not allowed to become doc comments. Moreover, some comments _are_ allowed, but aren't common
166+ /// style in Rust. For example, the following comments are allowed to be doc comments, but it is not
167+ /// common style for them to be:
168+ /// ```rust
169+ /// fn foo_bar(foo: Foo) -> Bar {
170+ /// // this could be an inner comment with //!
171+ /// foo.into_bar()
172+ /// }
173+ ///
174+ /// trait T {
175+ /// // The T struct could also be documented from within
176+ /// }
177+ ///
178+ /// mod mymod {
179+ /// // Modules only normally get inner documentation when they are defined as a separate file.
180+ /// }
181+ /// ```
165182fn can_be_doc_comment ( comment : & ast:: Comment ) -> Option < CommentPlacement > {
166183 use syntax:: SyntaxKind :: * ;
167184
@@ -175,38 +192,12 @@ fn can_be_doc_comment(comment: &ast::Comment) -> Option<CommentPlacement> {
175192 None => return Some ( CommentPlacement :: Inner ) ,
176193 }
177194
178- // check if comment is followed by: `struct`, `trait`, `mod`, `fn`, `type`, `extern crate`, `use`, `const`
195+ // check if comment is followed by: `struct`, `trait`, `mod`, `fn`, `type`, `extern crate`,
196+ // `use` or `const`.
179197 let parent = comment. syntax ( ) . parent ( ) ;
180198 let parent_kind = parent. as_ref ( ) . map ( |parent| parent. kind ( ) ) ;
181- if matches ! (
182- parent_kind,
183- Some ( STRUCT | TRAIT | MODULE | FN | TYPE_KW | EXTERN_CRATE | USE | CONST )
184- ) {
185- return Some ( CommentPlacement :: Outer ) ;
186- }
187-
188- // check if comment is preceded by: `fn f() {`, `trait T {`, `mod M {`:
189- let third_parent_kind = comment
190- . syntax ( )
191- . parent ( )
192- . and_then ( |p| p. parent ( ) )
193- . and_then ( |p| p. parent ( ) )
194- . map ( |parent| parent. kind ( ) ) ;
195- let is_first_item_in_parent = comment
196- . syntax ( )
197- . siblings_with_tokens ( Direction :: Prev )
198- . filter_map ( |not| not. into_node ( ) )
199- . next ( )
200- . is_none ( ) ;
201-
202- if matches ! ( parent_kind, Some ( STMT_LIST ) )
203- && is_first_item_in_parent
204- && matches ! ( third_parent_kind, Some ( FN | TRAIT | MODULE ) )
205- {
206- return Some ( CommentPlacement :: Inner ) ;
207- }
208-
209- None
199+ matches ! ( parent_kind, Some ( STRUCT | TRAIT | MODULE | FN | TYPE_KW | EXTERN_CRATE | USE | CONST ) )
200+ . then_some ( CommentPlacement :: Outer )
210201}
211202
212203/// The line -> block assist can be invoked from anywhere within a sequence of line comments.
@@ -467,39 +458,26 @@ mod tests {
467458
468459 #[ test]
469460 fn single_inner_line_comment_to_doc ( ) {
470- check_assist (
461+ check_assist_not_applicable (
471462 convert_comment_from_or_to_doc,
472463 r#"
473- fn main() {
464+ mod mymod {
474465 // unseen$0 docs
475466 foo();
476467 }
477468 "# ,
478- r#"
479- fn main() {
480- //! unseen docs
481- foo();
482- }
483- "# ,
484469 ) ;
485470 }
486471
487472 #[ test]
488473 fn multi_inner_line_comment_to_doc ( ) {
489- check_assist (
474+ check_assist_not_applicable (
490475 convert_comment_from_or_to_doc,
491476 r#"
492- fn main() {
477+ mod mymod {
493478 // unseen$0 docs
494479 // make me seen!
495- foo();
496- }
497- "# ,
498- r#"
499- fn main() {
500- //! unseen docs
501- //! make me seen!
502- foo();
480+ type Int = i32;
503481 }
504482 "# ,
505483 ) ;
@@ -510,13 +488,13 @@ mod tests {
510488 check_assist (
511489 convert_comment_from_or_to_doc,
512490 r#"
513- fn main() {
491+ mod mymod {
514492 //! visible$0 docs
515493 foo();
516494 }
517495 "# ,
518496 r#"
519- fn main() {
497+ mod mymod {
520498 // visible docs
521499 foo();
522500 }
@@ -529,58 +507,33 @@ mod tests {
529507 check_assist (
530508 convert_comment_from_or_to_doc,
531509 r#"
532- fn main() {
510+ mod mymod {
533511 //! visible$0 docs
534512 //! Hide me!
535513 foo();
536514 }
537515 "# ,
538516 r#"
539- fn main() {
517+ mod mymod {
540518 // visible docs
541519 // Hide me!
542520 foo();
543521 }
544522 "# ,
545523 ) ;
546- }
547-
548- #[ test]
549- fn single_inner_line_block_comment_to_doc ( ) {
550- check_assist (
551- convert_comment_from_or_to_doc,
552- r#"
553- fn main() {
554- /* unseen$0 docs */
555- foo();
556- }
557- "# ,
558- r#"
559- fn main() {
560- /*! unseen docs */
561- foo();
562- }
563- "# ,
564- ) ;
565- }
566-
567- #[ test]
568- fn multi_inner_line_block_comment_to_doc ( ) {
569524 check_assist (
570525 convert_comment_from_or_to_doc,
571526 r#"
572- fn main() {
573- /* unseen$0 docs
574- * make me seen!
575- */
527+ mod mymod {
528+ /// visible$0 docs
529+ /// Hide me!
576530 foo();
577531 }
578532 "# ,
579533 r#"
580- fn main() {
581- /*! unseen docs
582- * make me seen!
583- */
534+ mod mymod {
535+ // visible docs
536+ // Hide me!
584537 foo();
585538 }
586539 "# ,
@@ -592,15 +545,15 @@ mod tests {
592545 check_assist (
593546 convert_comment_from_or_to_doc,
594547 r#"
595- fn main() {
548+ mod mymod {
596549 /*! visible$0 docs */
597- foo() ;
550+ type Int = i32 ;
598551 }
599552 "# ,
600553 r#"
601- fn main() {
554+ mod mymod {
602555 /* visible docs */
603- foo() ;
556+ type Int = i32 ;
604557 }
605558 "# ,
606559 ) ;
@@ -611,21 +564,21 @@ mod tests {
611564 check_assist (
612565 convert_comment_from_or_to_doc,
613566 r#"
614- fn main() {
567+ mod mymod {
615568 /*! visible$0 docs
616569 * Hide me!
617570 */
618- foo() ;
571+ type Int = i32 ;
619572 }
620573 "# ,
621574 r#"
622- fn main() {
575+ mod mymod {
623576 /* visible docs
624577 * Hide me!
625578 */
626- foo() ;
579+ type Int = i32 ;
627580 }
628- "# ,
581+ "# ,
629582 ) ;
630583 }
631584
@@ -642,4 +595,16 @@ mod tests {
642595 "# ,
643596 ) ;
644597 }
598+
599+ #[ test]
600+ fn no_inner_comments ( ) {
601+ check_assist_not_applicable (
602+ convert_comment_from_or_to_doc,
603+ r#"
604+ mod mymod {
605+ // aaa$0aa
606+ }
607+ "# ,
608+ ) ;
609+ }
645610}
0 commit comments