]> git.lizzy.rs Git - rust.git/commitdiff
feat: improve dot completions with scoring
authorBenjamin Coenen <5719034+bnjjj@users.noreply.github.com>
Fri, 17 Apr 2020 08:29:32 +0000 (10:29 +0200)
committerBenjamin Coenen <5719034+bnjjj@users.noreply.github.com>
Fri, 17 Apr 2020 08:29:32 +0000 (10:29 +0200)
Signed-off-by: Benjamin Coenen <5719034+bnjjj@users.noreply.github.com>
crates/ra_ide/src/completion.rs
crates/ra_ide/src/completion/complete_dot.rs
crates/ra_ide/src/completion/completion_item.rs
crates/ra_ide/src/completion/presentation.rs

index 38c8aed8d549a6b66a573577fc1e4bf0a12877f9..19bc4321c1875ccc7d2a9439834a9ad2fd2e65cf 100644 (file)
@@ -94,8 +94,5 @@ 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);
 
-    // Compute score for completion items
-    acc.compute_score(&ctx);
-
     Some(acc)
 }
index 174b39964cd28e8b0fb0679cb3bafe177fd6e969..c16357a7e047821a1033a51ebbc63673a3b61a90 100644 (file)
@@ -1,16 +1,11 @@
 //! FIXME: write short doc here
 
-use hir::{
-    HasVisibility,
-    // HirDisplay,
-    Type,
-};
+use hir::{HasVisibility, Type};
 
 use crate::{
-    call_info::call_info,
     completion::{
         completion_context::CompletionContext,
-        completion_item::{CompletionKind, Completions, ScoreOption},
+        completion_item::{CompletionKind, Completions},
     },
     // CallInfo,
     CompletionItem,
@@ -46,15 +41,7 @@ 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 fields = receiver.fields(ctx.db);
-
-        if let Some(record_field) = &ctx.record_field_syntax {
-            acc.with_score_option(ScoreOption::RecordField(record_field.clone()));
-        } else if let Some(call_info) = call_info(ctx.db, ctx.file_position) {
-            acc.with_score_option(ScoreOption::CallFn(call_info));
-        }
-
-        for (field, ty) in fields {
+        for (field, ty) in receiver.fields(ctx.db) {
             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
                 // field is editable, we should show the completion
index 84d51bafee97da9109c9cbc9556b635f776147e8..a3ae9c86b45cc5483b044c4ab72a96c06e61f47c 100644 (file)
@@ -1,11 +1,11 @@
 //! FIXME: write short doc here
 
-use std::{cmp::Ordering, fmt};
+use std::fmt;
 
 use super::completion_context::CompletionContext;
-use crate::CallInfo;
+use crate::call_info::call_info;
 use hir::{Documentation, HirDisplay};
-use ra_syntax::{ast::RecordField, TextRange};
+use ra_syntax::TextRange;
 use ra_text_edit::TextEdit;
 
 /// `CompletionItem` describes a single completion variant in the editor pop-up.
@@ -199,6 +199,10 @@ pub fn score(&self) -> Option<CompletionScore> {
         self.score.clone()
     }
 
+    pub fn set_score(&mut self, score: CompletionScore) {
+        self.score = Some(score);
+    }
+
     pub fn trigger_call_info(&self) -> bool {
         self.trigger_call_info
     }
@@ -300,6 +304,47 @@ pub(crate) fn set_deprecated(mut self, deprecated: bool) -> Builder {
         self.deprecated = Some(deprecated);
         self
     }
+    #[allow(unused)]
+    pub(crate) fn compute_score(mut self, ctx: &CompletionContext) -> Builder {
+        let (active_name, active_type) = if let Some(record_field) = &ctx.record_field_syntax {
+            if let Some((struct_field, _)) = ctx.sema.resolve_record_field(record_field) {
+                (
+                    struct_field.name(ctx.db).to_string(),
+                    struct_field.signature_ty(ctx.db).display(ctx.db).to_string(),
+                )
+            } else {
+                return self;
+            }
+        } else if let Some(call_info) = call_info(ctx.db, ctx.file_position) {
+            if call_info.active_parameter_type().is_some()
+                && call_info.active_parameter_name().is_some()
+            {
+                (
+                    call_info.active_parameter_name().unwrap(),
+                    call_info.active_parameter_type().unwrap(),
+                )
+            } else {
+                return self;
+            }
+        } else {
+            return self;
+        };
+
+        // Compute score
+        // For the same type
+        if let Some(a_parameter_type) = &self.detail {
+            if &active_type == a_parameter_type {
+                // If same type + same name then go top position
+                if active_name == self.label {
+                    return self.set_score(CompletionScore::TypeAndNameMatch);
+                } else {
+                    return self.set_score(CompletionScore::TypeMatch);
+                }
+            }
+        }
+
+        self
+    }
     pub(crate) fn set_score(mut self, score: CompletionScore) -> Builder {
         self.score = Some(score);
         self
@@ -316,12 +361,6 @@ fn into(self) -> CompletionItem {
     }
 }
 
-#[derive(Debug)]
-pub(crate) enum ScoreOption {
-    CallFn(CallInfo),
-    RecordField(RecordField),
-}
-
 #[derive(Debug, Clone)]
 pub enum CompletionScore {
     TypeMatch,
@@ -332,7 +371,6 @@ pub enum CompletionScore {
 #[derive(Debug, Default)]
 pub(crate) struct Completions {
     buf: Vec<CompletionItem>,
-    score_option: Option<ScoreOption>,
 }
 
 impl Completions {
@@ -346,54 +384,6 @@ pub(crate) fn add_all<I>(&mut self, items: I)
     {
         items.into_iter().for_each(|item| self.add(item.into()))
     }
-
-    pub(crate) fn with_score_option(&mut self, score_option: ScoreOption) {
-        self.score_option = Some(score_option);
-    }
-
-    pub(crate) fn compute_score(&mut self, ctx: &CompletionContext) {
-        if self.score_option.is_none() {
-            return;
-        }
-
-        let (active_name, active_type) = match self.score_option.as_ref().unwrap() {
-            ScoreOption::CallFn(call_info) => {
-                if call_info.active_parameter_type().is_none()
-                    || call_info.active_parameter_name().is_none()
-                {
-                    return;
-                }
-                (
-                    call_info.active_parameter_name().unwrap(),
-                    call_info.active_parameter_type().unwrap(),
-                )
-            }
-            ScoreOption::RecordField(record_field) => {
-                if let Some((struct_field, _)) = ctx.sema.resolve_record_field(record_field) {
-                    (
-                        struct_field.name(ctx.db).to_string(),
-                        struct_field.signature_ty(ctx.db).display(ctx.db).to_string(),
-                    )
-                } else {
-                    return;
-                }
-            }
-        };
-
-        for completion_item in &mut self.buf {
-            // For the same type
-            if let Some(a_parameter_type) = &completion_item.detail {
-                if &active_type == a_parameter_type {
-                    // If same type + same name then go top position
-                    if active_name == completion_item.label {
-                        completion_item.score = Some(CompletionScore::TypeAndNameMatch);
-                    } else {
-                        completion_item.score = Some(CompletionScore::TypeMatch);
-                    }
-                }
-            }
-        }
-    }
 }
 
 impl Into<Vec<CompletionItem>> for Completions {
index 55f75b15aa1f8dd38d85c60267804ca01384a9b4..5c3360ce42beaf52b55a4cbb92f804b9319884f1 100644 (file)
@@ -31,6 +31,7 @@ pub(crate) fn add_field(
         .detail(ty.display(ctx.db).to_string())
         .set_documentation(field.docs(ctx.db))
         .set_deprecated(is_deprecated)
+        .compute_score(ctx)
         .add_to(self);
     }