@@ -166,23 +166,61 @@ fn on_eq_typed(file: &SourceFile, offset: TextSize) -> Option<TextEdit> {
166
166
if !stdx:: always!( file. syntax( ) . text( ) . char_at( offset) == Some ( '=' ) ) {
167
167
return None ;
168
168
}
169
- let let_stmt: ast:: LetStmt = find_node_at_offset ( file. syntax ( ) , offset) ?;
170
- if let_stmt. semicolon_token ( ) . is_some ( ) {
171
- return None ;
169
+
170
+ if let Some ( edit) = let_stmt ( file, offset) {
171
+ return Some ( edit) ;
172
+ }
173
+ if let Some ( edit) = assign_expr ( file, offset) {
174
+ return Some ( edit) ;
172
175
}
173
- if let Some ( expr) = let_stmt. initializer ( ) {
176
+
177
+ return None ;
178
+
179
+ fn assign_expr ( file : & SourceFile , offset : TextSize ) -> Option < TextEdit > {
180
+ let binop: ast:: BinExpr = find_node_at_offset ( file. syntax ( ) , offset) ?;
181
+ if !matches ! ( binop. op_kind( ) , Some ( ast:: BinaryOp :: Assignment { op: None } ) ) {
182
+ return None ;
183
+ }
184
+
185
+ if let Some ( expr_stmt) = ast:: ExprStmt :: cast ( binop. syntax ( ) . parent ( ) ?) {
186
+ if expr_stmt. semicolon_token ( ) . is_some ( ) {
187
+ return None ;
188
+ }
189
+ } else {
190
+ if !ast:: StmtList :: can_cast ( binop. syntax ( ) . parent ( ) ?. kind ( ) ) {
191
+ // Parent must be `ExprStmt` or `StmtList` for `;` to be valid.
192
+ return None ;
193
+ }
194
+ }
195
+
196
+ let expr = binop. rhs ( ) ?;
174
197
let expr_range = expr. syntax ( ) . text_range ( ) ;
175
198
if expr_range. contains ( offset) && offset != expr_range. start ( ) {
176
199
return None ;
177
200
}
178
201
if file. syntax ( ) . text ( ) . slice ( offset..expr_range. start ( ) ) . contains_char ( '\n' ) {
179
202
return None ;
180
203
}
181
- } else {
182
- return None ;
204
+ let offset = expr. syntax ( ) . text_range ( ) . end ( ) ;
205
+ Some ( TextEdit :: insert ( offset, ";" . to_string ( ) ) )
206
+ }
207
+
208
+ fn let_stmt ( file : & SourceFile , offset : TextSize ) -> Option < TextEdit > {
209
+ let let_stmt: ast:: LetStmt = find_node_at_offset ( file. syntax ( ) , offset) ?;
210
+ if let_stmt. semicolon_token ( ) . is_some ( ) {
211
+ return None ;
212
+ }
213
+ let expr = let_stmt. initializer ( ) ?;
214
+ let expr_range = expr. syntax ( ) . text_range ( ) ;
215
+ if expr_range. contains ( offset) && offset != expr_range. start ( ) {
216
+ return None ;
217
+ }
218
+ if file. syntax ( ) . text ( ) . slice ( offset..expr_range. start ( ) ) . contains_char ( '\n' ) {
219
+ return None ;
220
+ }
221
+ let offset = let_stmt. syntax ( ) . text_range ( ) . end ( ) ;
222
+ Some ( TextEdit :: insert ( offset, ";" . to_string ( ) ) )
183
223
}
184
- let offset = let_stmt. syntax ( ) . text_range ( ) . end ( ) ;
185
- Some ( TextEdit :: insert ( offset, ";" . to_string ( ) ) )
186
224
}
187
225
188
226
/// Returns an edit which should be applied when a dot ('.') is typed on a blank line, indenting the line appropriately.
@@ -286,7 +324,7 @@ mod tests {
286
324
}
287
325
288
326
#[ test]
289
- fn test_on_eq_typed ( ) {
327
+ fn test_semi_after_let ( ) {
290
328
// do_check(r"
291
329
// fn foo() {
292
330
// let foo =$0
@@ -322,6 +360,54 @@ fn foo() {
322
360
// ");
323
361
}
324
362
363
+ #[ test]
364
+ fn test_semi_after_assign ( ) {
365
+ type_char (
366
+ '=' ,
367
+ r#"
368
+ fn f() {
369
+ i $0 0
370
+ }
371
+ "# ,
372
+ r#"
373
+ fn f() {
374
+ i = 0;
375
+ }
376
+ "# ,
377
+ ) ;
378
+ type_char (
379
+ '=' ,
380
+ r#"
381
+ fn f() {
382
+ i $0 0
383
+ i
384
+ }
385
+ "# ,
386
+ r#"
387
+ fn f() {
388
+ i = 0;
389
+ i
390
+ }
391
+ "# ,
392
+ ) ;
393
+ type_char_noop (
394
+ '=' ,
395
+ r#"
396
+ fn f(x: u8) {
397
+ if x $0
398
+ }
399
+ "# ,
400
+ ) ;
401
+ type_char_noop (
402
+ '=' ,
403
+ r#"
404
+ fn f() {
405
+ g(i $0 0);
406
+ }
407
+ "# ,
408
+ ) ;
409
+ }
410
+
325
411
#[ test]
326
412
fn indents_new_chain_call ( ) {
327
413
type_char (
0 commit comments