From 064095742980d4c825391f643e437520599f51d8 Mon Sep 17 00:00:00 2001 From: Benjamin Coenen <5719034+bnjjj@users.noreply.github.com> Date: Sun, 12 Apr 2020 17:45:07 +0200 Subject: Improve autocompletion by looking on the type and name, change implementation, include sort in Completions struct Signed-off-by: Benjamin Coenen <5719034+bnjjj@users.noreply.github.com> --- crates/ra_ide/src/completion.rs | 3 ++ crates/ra_ide/src/completion/complete_dot.rs | 69 ++++++++++++++++--------- crates/ra_ide/src/completion/completion_item.rs | 50 +++++++++++++++++- 3 files changed, 96 insertions(+), 26 deletions(-) (limited to 'crates') diff --git a/crates/ra_ide/src/completion.rs b/crates/ra_ide/src/completion.rs index 4a1a2a04a..3be8b1903 100644 --- a/crates/ra_ide/src/completion.rs +++ b/crates/ra_ide/src/completion.rs @@ -94,5 +94,8 @@ pub(crate) fn completions( complete_macro_in_item_position::complete_macro_in_item_position(&mut acc, &ctx); complete_trait_impl::complete_trait_impl(&mut acc, &ctx); + // Reorder completion items if there is a sort_option + acc.sort(); + Some(acc) } diff --git a/crates/ra_ide/src/completion/complete_dot.rs b/crates/ra_ide/src/completion/complete_dot.rs index b5448af5c..cb899d8ff 100644 --- a/crates/ra_ide/src/completion/complete_dot.rs +++ b/crates/ra_ide/src/completion/complete_dot.rs @@ -1,14 +1,23 @@ //! FIXME: write short doc here -use hir::{HasVisibility, HirDisplay, Type}; +use hir::{ + HasVisibility, + // HirDisplay, + Type, +}; use crate::completion::completion_item::CompletionKind; use crate::{ - completion::{completion_context::CompletionContext, completion_item::Completions}, + call_info::call_info, + completion::{ + completion_context::CompletionContext, + completion_item::{Completions, SortOption}, + }, + // CallInfo, CompletionItem, }; use rustc_hash::FxHashSet; -use std::cmp::Ordering; +// use std::cmp::Ordering; /// Complete dot accesses, i.e. fields or methods (and .await syntax). pub(super) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) { @@ -38,30 +47,40 @@ pub(super) fn complete_dot(acc: &mut Completions, ctx: &CompletionContext) { fn complete_fields(acc: &mut Completions, ctx: &CompletionContext, receiver: &Type) { for receiver in receiver.autoderef(ctx.db) { - let mut fields = receiver.fields(ctx.db); - if let Some(call_info) = &ctx.call_info { - if let Some(active_parameter_type) = call_info.active_parameter_type() { - let active_parameter_name = call_info.active_parameter_name().unwrap(); - fields.sort_by(|a, b| { - // For the same type - if active_parameter_type == a.1.display(ctx.db).to_string() { - // If same type + same name then go top position - if active_parameter_name == a.0.name(ctx.db).to_string() { - Ordering::Less - } else { - if active_parameter_type == b.1.display(ctx.db).to_string() { - Ordering::Equal - } else { - Ordering::Less - } - } - } else { - Ordering::Greater - } - }); - } + let fields = receiver.fields(ctx.db); + + // If we use this implementation we can delete call_info in the CompletionContext + if let Some(call_info) = call_info(ctx.db, ctx.file_position) { + acc.with_sort_option(SortOption::CallFn(call_info)); } + // // For Call Fn + // if let Some(call_info) = &ctx.call_info { + // if let Some(active_parameter_type) = call_info.active_parameter_type() { + // let active_parameter_name = call_info.active_parameter_name().unwrap(); + // fields.sort_by(|a, b| { + // // For the same type + // if active_parameter_type == a.1.display(ctx.db).to_string() { + // // If same type + same name then go top position + // if active_parameter_name == a.0.name(ctx.db).to_string() { + // Ordering::Less + // } else { + // if active_parameter_type == b.1.display(ctx.db).to_string() { + // Ordering::Equal + // } else { + // Ordering::Less + // } + // } + // } else { + // Ordering::Greater + // } + // }); + // } + // } + + // For Lit struct fields + // --- + for (field, ty) in fields { if ctx.scope().module().map_or(false, |m| !field.is_visible_from(ctx.db, m)) { // Skip private field. FIXME: If the definition location of the diff --git a/crates/ra_ide/src/completion/completion_item.rs b/crates/ra_ide/src/completion/completion_item.rs index bc0f1aff5..f8e6e53f1 100644 --- a/crates/ra_ide/src/completion/completion_item.rs +++ b/crates/ra_ide/src/completion/completion_item.rs @@ -1,7 +1,8 @@ //! FIXME: write short doc here -use std::fmt; +use std::{cmp::Ordering, fmt}; +use crate::CallInfo; use hir::Documentation; use ra_syntax::TextRange; use ra_text_edit::TextEdit; @@ -297,10 +298,17 @@ impl<'a> Into for Builder { } } +#[derive(Debug)] +pub(crate) enum SortOption { + CallFn(CallInfo), + // LitStruct, +} + /// Represents an in-progress set of completions being built. #[derive(Debug, Default)] pub(crate) struct Completions { buf: Vec, + sort_option: Option, } impl Completions { @@ -314,6 +322,46 @@ impl Completions { { items.into_iter().for_each(|item| self.add(item.into())) } + + pub(crate) fn with_sort_option(&mut self, sort_option: SortOption) { + self.sort_option = Some(sort_option); + } + + pub(crate) fn sort(&mut self) { + if self.sort_option.is_none() { + return; + } + let sort_option = self.sort_option.as_ref().unwrap(); + + match sort_option { + SortOption::CallFn(call_info) => { + if let Some(active_parameter_type) = call_info.active_parameter_type() { + let active_parameter_name = call_info.active_parameter_name().unwrap(); + + self.buf.sort_by(|a, b| { + // For the same type + if let Some(a_parameter_type) = &a.detail { + if &active_parameter_type == a_parameter_type { + // If same type + same name then go top position + if active_parameter_name != a.label { + if let Some(b_parameter_type) = &b.detail { + if &active_parameter_type == b_parameter_type { + return Ordering::Equal; + } + } + } + Ordering::Less + } else { + Ordering::Greater + } + } else { + Ordering::Greater + } + }); + } + } // _ => unimplemented!("sort options not already implemented"), + } + } } impl Into> for Completions { -- cgit v1.2.3