@@ -452,43 +452,77 @@ pub fn code_action(cx: &mut Context) {
452
452
cx. callback (
453
453
future,
454
454
move |editor, compositor, response : Option < lsp:: CodeActionResponse > | {
455
- let actions = match response {
455
+ let mut actions = match response {
456
456
Some ( a) => a,
457
457
None => return ,
458
458
} ;
459
+
459
460
if actions. is_empty ( ) {
460
461
editor. set_status ( "No code actions available" ) ;
461
462
return ;
462
463
}
463
464
464
- let mut picker = ui:: Menu :: new ( actions, ( ) , move |editor, code_action, event| {
465
- if event != PromptEvent :: Validate {
466
- return ;
467
- }
465
+ // sort by CodeActionKind
466
+ // this ensures that the most relevant codeactions (quickfix) show up first
467
+ // while more situational commands (like refactors) show up later
468
+ // this behaviour is modeled after the behaviour of vscode (editor/contrib/codeAction/browser/codeActionWidget.ts)
469
+
470
+ let mut categories = vec ! [ Vec :: new( ) ; 8 ] ;
471
+ for action in actions. drain ( ..) {
472
+ let category = match & action {
473
+ lsp:: CodeActionOrCommand :: CodeAction ( lsp:: CodeAction {
474
+ kind : Some ( kind) ,
475
+ ..
476
+ } ) => match kind. as_str ( ) {
477
+ "quickfix" => 0 ,
478
+ "refactor.extract" => 1 ,
479
+ "refactor.inline" => 2 ,
480
+ "refactor.rewrite" => 3 ,
481
+ "refactor.move" => 4 ,
482
+ "refactor.surround" => 5 ,
483
+ "source" => 6 ,
484
+ _ => 7 ,
485
+ } ,
486
+ _ => 7 ,
487
+ } ;
488
+ log:: error!( "{category}" ) ;
468
489
469
- // always present here
470
- let code_action = code_action. unwrap ( ) ;
490
+ categories[ category] . push ( action) ;
491
+ }
492
+
493
+ for category in categories {
494
+ actions. extend ( category. into_iter ( ) )
495
+ }
471
496
472
- match code_action {
473
- lsp :: CodeActionOrCommand :: Command ( command ) => {
474
- log :: debug! ( "code action command: {:?}" , command ) ;
475
- execute_lsp_command ( editor , command . clone ( ) ) ;
497
+ let mut picker =
498
+ ui :: Menu :: new ( actions , false , ( ) , move |editor , code_action , event| {
499
+ if event != PromptEvent :: Validate {
500
+ return ;
476
501
}
477
- lsp:: CodeActionOrCommand :: CodeAction ( code_action) => {
478
- log:: debug!( "code action: {:?}" , code_action) ;
479
- if let Some ( ref workspace_edit) = code_action. edit {
480
- log:: debug!( "edit: {:?}" , workspace_edit) ;
481
- apply_workspace_edit ( editor, offset_encoding, workspace_edit) ;
482
- }
483
502
484
- // if code action provides both edit and command first the edit
485
- // should be applied and then the command
486
- if let Some ( command) = & code_action. command {
503
+ // always present here
504
+ let code_action = code_action. unwrap ( ) ;
505
+
506
+ match code_action {
507
+ lsp:: CodeActionOrCommand :: Command ( command) => {
508
+ log:: debug!( "code action command: {:?}" , command) ;
487
509
execute_lsp_command ( editor, command. clone ( ) ) ;
488
510
}
511
+ lsp:: CodeActionOrCommand :: CodeAction ( code_action) => {
512
+ log:: debug!( "code action: {:?}" , code_action) ;
513
+ if let Some ( ref workspace_edit) = code_action. edit {
514
+ log:: debug!( "edit: {:?}" , workspace_edit) ;
515
+ apply_workspace_edit ( editor, offset_encoding, workspace_edit) ;
516
+ }
517
+
518
+ // if code action provides both edit and command first the edit
519
+ // should be applied and then the command
520
+ if let Some ( command) = & code_action. command {
521
+ execute_lsp_command ( editor, command. clone ( ) ) ;
522
+ }
523
+ }
489
524
}
490
- }
491
- } ) ;
525
+ } ) ;
492
526
picker. move_down ( ) ; // pre-select the first item
493
527
494
528
let popup = Popup :: new ( "code-action" , picker) ;
0 commit comments