sort codeaction by their kind instead of alphabetically

pull/4299/head
Pascal Kuthe 2 years ago committed by Blaž Hrastnik
parent ce399471f0
commit 8673c1ec0c

@ -452,16 +452,56 @@ pub fn code_action(cx: &mut Context) {
cx.callback( cx.callback(
future, future,
move |editor, compositor, response: Option<lsp::CodeActionResponse>| { move |editor, compositor, response: Option<lsp::CodeActionResponse>| {
let actions = match response { let mut actions = match response {
Some(a) => a, Some(a) => a,
None => return, None => return,
}; };
if actions.is_empty() { if actions.is_empty() {
editor.set_status("No code actions available"); editor.set_status("No code actions available");
return; return;
} }
let mut picker = ui::Menu::new(actions, (), move |editor, code_action, event| { // sort by CodeActionKind
// this ensures that the most relevant codeactions (quickfix) show up first
// while more situational commands (like refactors) show up later
// this behaviour is modeled after the behaviour of vscode (editor/contrib/codeAction/browser/codeActionWidget.ts)
let mut categories = vec![Vec::new(); 8];
for action in actions.drain(..) {
let category = match &action {
lsp::CodeActionOrCommand::CodeAction(lsp::CodeAction {
kind: Some(kind),
..
}) => {
let mut components = kind.as_str().split('.');
match components.next() {
Some("quickfix") => 0,
Some("refactor") => match components.next() {
Some("extract") => 1,
Some("inline") => 2,
Some("rewrite") => 3,
Some("move") => 4,
Some("surround") => 5,
_ => 7,
},
Some("source") => 6,
_ => 7,
}
}
_ => 7,
};
categories[category].push(action);
}
for category in categories {
actions.extend(category.into_iter())
}
let mut picker =
ui::Menu::new(actions, false, (), move |editor, code_action, event| {
if event != PromptEvent::Validate { if event != PromptEvent::Validate {
return; return;
} }

@ -97,7 +97,7 @@ impl Completion {
start_offset: usize, start_offset: usize,
trigger_offset: usize, trigger_offset: usize,
) -> Self { ) -> Self {
let menu = Menu::new(items, (), move |editor: &mut Editor, item, event| { let menu = Menu::new(items, true, (), move |editor: &mut Editor, item, event| {
fn item_to_transaction( fn item_to_transaction(
doc: &Document, doc: &Document,
item: &CompletionItem, item: &CompletionItem,

@ -74,6 +74,7 @@ impl<T: Item> Menu<T> {
// rendering) // rendering)
pub fn new( pub fn new(
options: Vec<T>, options: Vec<T>,
sort: bool,
editor_data: <T as Item>::Data, editor_data: <T as Item>::Data,
callback_fn: impl Fn(&mut Editor, Option<&T>, MenuEvent) + 'static, callback_fn: impl Fn(&mut Editor, Option<&T>, MenuEvent) + 'static,
) -> Self { ) -> Self {
@ -91,8 +92,12 @@ impl<T: Item> Menu<T> {
recalculate: true, recalculate: true,
}; };
if sort {
// TODO: scoring on empty input should just use a fastpath // TODO: scoring on empty input should just use a fastpath
menu.score(""); menu.score("");
} else {
menu.matches = (0..menu.options.len()).map(|i| (i, 0)).collect();
}
menu menu
} }

Loading…
Cancel
Save