1
- use ast:: { Comment , CommentShape } ;
2
1
use itertools:: Itertools ;
3
2
use std:: convert:: identity;
4
3
use syntax:: {
5
- ast:: { self , edit:: IndentLevel , CommentKind , Whitespace } ,
4
+ ast:: {
5
+ self ,
6
+ edit:: IndentLevel ,
7
+ Comment , CommentKind ,
8
+ CommentPlacement :: { Inner , Outer } ,
9
+ CommentShape :: { self , Block , Line } ,
10
+ Whitespace ,
11
+ } ,
6
12
AstToken , Direction , SyntaxElement , TextRange ,
7
13
} ;
8
14
@@ -42,34 +48,37 @@ pub(crate) fn convert_comment_block(acc: &mut Assists, ctx: &AssistContext) -> O
42
48
}
43
49
44
50
fn block_to_line ( acc : & mut Assists , comment : ast:: Comment ) -> Option < ( ) > {
45
- let indentation = IndentLevel :: from_token ( comment. syntax ( ) ) ;
46
- let line_prefix =
47
- comment_kind_prefix ( CommentKind { shape : CommentShape :: Line , ..comment. kind ( ) } ) ;
48
-
49
- let text = comment. text ( ) ;
50
- let text = & text[ comment. prefix ( ) . len ( ) ..( text. len ( ) - "*/" . len ( ) ) ] . trim ( ) ;
51
-
52
- let lines = text. lines ( ) . peekable ( ) ;
53
-
54
- let indent_spaces = indentation. to_string ( ) ;
55
- let output = lines
56
- . map ( |l| l. trim_start_matches ( & indent_spaces) )
57
- . map ( |l| {
58
- // Don't introduce trailing whitespace
59
- if l. is_empty ( ) {
60
- line_prefix. to_string ( )
61
- } else {
62
- format ! ( "{} {}" , line_prefix, l. trim_start_matches( & indent_spaces) )
63
- }
64
- } )
65
- . join ( & format ! ( "\n {}" , indent_spaces) ) ;
66
-
67
51
let target = comment. syntax ( ) . text_range ( ) ;
52
+
68
53
acc. add (
69
54
AssistId ( "block_to_line" , AssistKind :: RefactorRewrite ) ,
70
55
"Replace block comment with line comments" ,
71
56
target,
72
- |edit| edit. replace ( target, output) ,
57
+ |edit| {
58
+ let indentation = IndentLevel :: from_token ( comment. syntax ( ) ) ;
59
+ let line_prefix =
60
+ comment_kind_prefix ( CommentKind { shape : CommentShape :: Line , ..comment. kind ( ) } ) ;
61
+
62
+ let text = comment. text ( ) ;
63
+ let text = & text[ comment. prefix ( ) . len ( ) ..( text. len ( ) - "*/" . len ( ) ) ] . trim ( ) ;
64
+
65
+ let lines = text. lines ( ) . peekable ( ) ;
66
+
67
+ let indent_spaces = indentation. to_string ( ) ;
68
+ let output = lines
69
+ . map ( |l| l. trim_start_matches ( & indent_spaces) )
70
+ . map ( |l| {
71
+ // Don't introduce trailing whitespace
72
+ if l. is_empty ( ) {
73
+ line_prefix. to_string ( )
74
+ } else {
75
+ format ! ( "{} {}" , line_prefix, l. trim_start_matches( & indent_spaces) )
76
+ }
77
+ } )
78
+ . join ( & format ! ( "\n {}" , indent_spaces) ) ;
79
+
80
+ edit. replace ( target, output)
81
+ } ,
73
82
)
74
83
}
75
84
@@ -83,24 +92,27 @@ fn line_to_block(acc: &mut Assists, comment: ast::Comment) -> Option<()> {
83
92
comments. last ( ) . unwrap ( ) . syntax ( ) . text_range ( ) . end ( ) ,
84
93
) ;
85
94
86
- // We pick a single indentation level for the whole block comment based on the
87
- // comment where the assist was invoked. This will be prepended to the
88
- // contents of each line comment when they're put into the block comment.
89
- let indentation = IndentLevel :: from_token ( & comment. syntax ( ) ) ;
90
-
91
- let block_comment_body =
92
- comments. into_iter ( ) . map ( |c| line_comment_text ( indentation, c) ) . join ( "\n " ) ;
93
-
94
- let block_prefix =
95
- comment_kind_prefix ( CommentKind { shape : CommentShape :: Block , ..comment. kind ( ) } ) ;
96
-
97
- let output = format ! ( "{}\n {}\n {}*/" , block_prefix, block_comment_body, indentation. to_string( ) ) ;
98
-
99
95
acc. add (
100
96
AssistId ( "line_to_block" , AssistKind :: RefactorRewrite ) ,
101
97
"Replace line comments with a single block comment" ,
102
98
target,
103
- |edit| edit. replace ( target, output) ,
99
+ |edit| {
100
+ // We pick a single indentation level for the whole block comment based on the
101
+ // comment where the assist was invoked. This will be prepended to the
102
+ // contents of each line comment when they're put into the block comment.
103
+ let indentation = IndentLevel :: from_token ( & comment. syntax ( ) ) ;
104
+
105
+ let block_comment_body =
106
+ comments. into_iter ( ) . map ( |c| line_comment_text ( indentation, c) ) . join ( "\n " ) ;
107
+
108
+ let block_prefix =
109
+ comment_kind_prefix ( CommentKind { shape : CommentShape :: Block , ..comment. kind ( ) } ) ;
110
+
111
+ let output =
112
+ format ! ( "{}\n {}\n {}*/" , block_prefix, block_comment_body, indentation. to_string( ) ) ;
113
+
114
+ edit. replace ( target, output)
115
+ } ,
104
116
)
105
117
}
106
118
@@ -160,27 +172,18 @@ fn relevant_line_comments(comment: &ast::Comment) -> Vec<Comment> {
160
172
//
161
173
// But since such comments aren't idiomatic we're okay with this.
162
174
fn line_comment_text ( indentation : IndentLevel , comm : ast:: Comment ) -> String {
163
- let contents = trim_one ( comm. text ( ) . strip_prefix ( comm. prefix ( ) ) . unwrap ( ) ) . to_owned ( ) ;
175
+ let contents_without_prefix = comm. text ( ) . strip_prefix ( comm. prefix ( ) ) . unwrap ( ) ;
176
+ let contents = contents_without_prefix. strip_prefix ( ' ' ) . unwrap_or ( contents_without_prefix) ;
164
177
165
178
// Don't add the indentation if the line is empty
166
179
if contents. is_empty ( ) {
167
- contents
180
+ contents. to_owned ( )
168
181
} else {
169
182
indentation. to_string ( ) + & contents
170
183
}
171
184
}
172
185
173
- fn trim_one ( text : & str ) -> & str {
174
- if text. starts_with ( ' ' ) {
175
- & text[ 1 ..]
176
- } else {
177
- text
178
- }
179
- }
180
-
181
186
fn comment_kind_prefix ( ck : ast:: CommentKind ) -> & ' static str {
182
- use ast:: CommentPlacement :: { Inner , Outer } ;
183
- use ast:: CommentShape :: { Block , Line } ;
184
187
match ( ck. shape , ck. doc ) {
185
188
( Line , Some ( Inner ) ) => "//!" ,
186
189
( Line , Some ( Outer ) ) => "///" ,
0 commit comments