1
- use hir:: db:: AstDatabase ;
2
- use ide_db:: source_change:: SourceChange ;
3
- use syntax:: { ast, AstNode } ;
1
+ use ide_db:: {
2
+ base_db:: { FileLoader , FileRange } ,
3
+ source_change:: SourceChange ,
4
+ } ;
5
+ use syntax:: { TextRange , TextSize } ;
4
6
use text_edit:: TextEdit ;
5
7
6
8
use crate :: { fix, Assist , Diagnostic , DiagnosticsContext } ;
@@ -15,29 +17,42 @@ pub(crate) fn remove_this_semicolon(
15
17
Diagnostic :: new (
16
18
"remove-this-semicolon" ,
17
19
"remove this semicolon" ,
18
- ctx . sema . diagnostics_display_range ( d . expr . clone ( ) . map ( |it| it. into ( ) ) ) . range ,
20
+ semicolon_range ( ctx , d ) . unwrap_or_else ( |it| it) . range ,
19
21
)
20
22
. with_fixes ( fixes ( ctx, d) )
21
23
}
22
24
25
+ fn semicolon_range (
26
+ ctx : & DiagnosticsContext < ' _ > ,
27
+ d : & hir:: RemoveThisSemicolon ,
28
+ ) -> Result < FileRange , FileRange > {
29
+ let expr_range = ctx. sema . diagnostics_display_range ( d. expr . clone ( ) . map ( |it| it. into ( ) ) ) ;
30
+ let file_text = ctx. sema . db . file_text ( expr_range. file_id ) ;
31
+ let range_end: usize = expr_range. range . end ( ) . into ( ) ;
32
+ // FIXME: This doesn't handle whitespace and comments, but handling those in
33
+ // the presence of macros might prove tricky...
34
+ if file_text[ range_end..] . starts_with ( ';' ) {
35
+ Ok ( FileRange {
36
+ file_id : expr_range. file_id ,
37
+ range : TextRange :: at ( expr_range. range . end ( ) , TextSize :: of ( ';' ) ) ,
38
+ } )
39
+ } else {
40
+ Err ( expr_range)
41
+ }
42
+ }
43
+
23
44
fn fixes ( ctx : & DiagnosticsContext < ' _ > , d : & hir:: RemoveThisSemicolon ) -> Option < Vec < Assist > > {
24
- let root = ctx. sema . db . parse_or_expand ( d. expr . file_id ) ?;
25
-
26
- let semicolon = d
27
- . expr
28
- . value
29
- . to_node ( & root)
30
- . syntax ( )
31
- . parent ( )
32
- . and_then ( ast:: ExprStmt :: cast)
33
- . and_then ( |expr| expr. semicolon_token ( ) ) ?
34
- . text_range ( ) ;
35
-
36
- let edit = TextEdit :: delete ( semicolon) ;
37
- let source_change =
38
- SourceChange :: from_text_edit ( d. expr . file_id . original_file ( ctx. sema . db ) , edit) ;
39
-
40
- Some ( vec ! [ fix( "remove_semicolon" , "Remove this semicolon" , source_change, semicolon) ] )
45
+ let semicolon_range = semicolon_range ( ctx, d) . ok ( ) ?;
46
+
47
+ let edit = TextEdit :: delete ( semicolon_range. range ) ;
48
+ let source_change = SourceChange :: from_text_edit ( semicolon_range. file_id , edit) ;
49
+
50
+ Some ( vec ! [ fix(
51
+ "remove_semicolon" ,
52
+ "Remove this semicolon" ,
53
+ source_change,
54
+ semicolon_range. range,
55
+ ) ] )
41
56
}
42
57
43
58
#[ cfg( test) ]
@@ -49,7 +64,7 @@ mod tests {
49
64
check_diagnostics (
50
65
r#"
51
66
fn test() -> i32 { 123; }
52
- //^^ ^ 💡 error: remove this semicolon
67
+ // ^ 💡 error: remove this semicolon
53
68
"# ,
54
69
) ;
55
70
}
0 commit comments