diff --git a/crates/ide_completion/src/completions/postfix.rs b/crates/ide_completion/src/completions/postfix.rs index ead957a3f1..302694ea7c 100644 --- a/crates/ide_completion/src/completions/postfix.rs +++ b/crates/ide_completion/src/completions/postfix.rs @@ -12,9 +12,11 @@ use syntax::{ use text_edit::TextEdit; use crate::{ - completions::postfix::format_like::add_format_like_completions, context::CompletionContext, - item::Builder, patterns::ImmediateLocation, CompletionItem, CompletionItemKind, - CompletionRelevance, Completions, SnippetScope, + completions::postfix::format_like::add_format_like_completions, + context::CompletionContext, + item::{Builder, CompletionRelevancePostfixMatch}, + patterns::ImmediateLocation, + CompletionItem, CompletionItemKind, CompletionRelevance, Completions, SnippetScope, }; pub(crate) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) { @@ -240,12 +242,13 @@ fn build_postfix_snippet_builder<'ctx>( let mut item = CompletionItem::new(CompletionItemKind::Snippet, ctx.source_range(), label); item.detail(detail).snippet_edit(cap, edit); - if ctx.original_token.text() == label { - let relevance = - CompletionRelevance { exact_postfix_snippet_match: true, ..Default::default() }; - item.set_relevance(relevance); - } - + let postfix_match = if ctx.original_token.text() == label { + Some(CompletionRelevancePostfixMatch::Exact) + } else { + Some(CompletionRelevancePostfixMatch::NonExact) + }; + let relevance = CompletionRelevance { postfix_match, ..Default::default() }; + item.set_relevance(relevance); item } } diff --git a/crates/ide_completion/src/completions/record.rs b/crates/ide_completion/src/completions/record.rs index b65cf60a01..6057c0e004 100644 --- a/crates/ide_completion/src/completions/record.rs +++ b/crates/ide_completion/src/completions/record.rs @@ -4,7 +4,7 @@ use syntax::{ast::Expr, T}; use crate::{ patterns::ImmediateLocation, CompletionContext, CompletionItem, CompletionItemKind, - CompletionRelevance, Completions, + CompletionRelevance, CompletionRelevancePostfixMatch, Completions, }; pub(crate) fn complete_record(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> { @@ -45,7 +45,7 @@ pub(crate) fn complete_record(acc: &mut Completions, ctx: &CompletionContext) -> let completion_text = completion_text.strip_prefix(ctx.token.text()).unwrap_or(completion_text); item.insert_text(completion_text).set_relevance(CompletionRelevance { - exact_postfix_snippet_match: true, + postfix_match: Some(CompletionRelevancePostfixMatch::Exact), ..Default::default() }); item.add_to(acc); diff --git a/crates/ide_completion/src/item.rs b/crates/ide_completion/src/item.rs index 4b9f7d17c3..89cbddbad3 100644 --- a/crates/ide_completion/src/item.rs +++ b/crates/ide_completion/src/item.rs @@ -143,15 +143,8 @@ pub struct CompletionRelevance { pub is_op_method: bool, /// Set for item completions that are private but in the workspace. pub is_private_editable: bool, - /// This is set in cases like these: - /// - /// ``` - /// (a > b).not$0 - /// ``` - /// - /// Basically, we want to guarantee that postfix snippets always takes - /// precedence over everything else. - pub exact_postfix_snippet_match: bool, + /// Set for postfix snippet item completions + pub postfix_match: Option, } #[derive(Debug, Clone, Copy, Eq, PartialEq)] @@ -178,8 +171,23 @@ pub enum CompletionRelevanceTypeMatch { Exact, } +#[derive(Debug, Clone, Copy, Eq, PartialEq)] +pub enum CompletionRelevancePostfixMatch { + /// Set in cases when item is postfix, but not exact + NonExact, + /// This is set in cases like these: + /// + /// ``` + /// (a > b).not$0 + /// ``` + /// + /// Basically, we want to guarantee that postfix snippets always takes + /// precedence over everything else. + Exact, +} + impl CompletionRelevance { - const BASE_LINE: u32 = 2; + const BASE_LINE: u32 = 3; /// Provides a relevance score. Higher values are more relevant. /// /// The absolute value of the relevance score is not meaningful, for @@ -199,6 +207,9 @@ impl CompletionRelevance { if self.is_private_editable { score -= 1; } + if self.postfix_match.is_some() { + score -= 3; + } // score increases if self.exact_name_match { @@ -212,9 +223,10 @@ impl CompletionRelevance { if self.is_local { score += 1; } - if self.exact_postfix_snippet_match { + if self.postfix_match == Some(CompletionRelevancePostfixMatch::Exact) { score += 100; } + score } @@ -530,7 +542,9 @@ mod tests { use itertools::Itertools; use test_utils::assert_eq_text; - use super::{CompletionRelevance, CompletionRelevanceTypeMatch}; + use super::{ + CompletionRelevance, CompletionRelevancePostfixMatch, CompletionRelevanceTypeMatch, + }; /// Check that these are CompletionRelevance are sorted in ascending order /// by their relevance score. @@ -573,6 +587,10 @@ mod tests { // This test asserts that the relevance score for these items is ascending, and // that any items in the same vec have the same score. let expected_relevance_order = vec![ + vec![CompletionRelevance { + postfix_match: Some(CompletionRelevancePostfixMatch::NonExact), + ..CompletionRelevance::default() + }], vec![CompletionRelevance { is_op_method: true, is_private_editable: true, @@ -612,7 +630,7 @@ mod tests { ..CompletionRelevance::default() }], vec![CompletionRelevance { - exact_postfix_snippet_match: true, + postfix_match: Some(CompletionRelevancePostfixMatch::Exact), ..CompletionRelevance::default() }], ]; diff --git a/crates/ide_completion/src/lib.rs b/crates/ide_completion/src/lib.rs index 56c41a88e4..0cbe82abba 100644 --- a/crates/ide_completion/src/lib.rs +++ b/crates/ide_completion/src/lib.rs @@ -28,7 +28,10 @@ use crate::{completions::Completions, context::CompletionContext}; pub use crate::{ config::CompletionConfig, - item::{CompletionItem, CompletionItemKind, CompletionRelevance, ImportEdit}, + item::{ + CompletionItem, CompletionItemKind, CompletionRelevance, CompletionRelevancePostfixMatch, + ImportEdit, + }, snippet::{Snippet, SnippetScope}, }; diff --git a/crates/ide_completion/src/render.rs b/crates/ide_completion/src/render.rs index 604f217447..a18c064960 100644 --- a/crates/ide_completion/src/render.rs +++ b/crates/ide_completion/src/render.rs @@ -365,7 +365,7 @@ mod tests { use crate::{ item::CompletionRelevanceTypeMatch, tests::{check_edit, do_completion, get_all_items, TEST_CONFIG}, - CompletionItem, CompletionItemKind, CompletionRelevance, + CompletionItem, CompletionItemKind, CompletionRelevance, CompletionRelevancePostfixMatch, }; #[track_caller] @@ -432,7 +432,10 @@ mod tests { ), (relevance.exact_name_match, "name"), (relevance.is_local, "local"), - (relevance.exact_postfix_snippet_match, "snippet"), + ( + relevance.postfix_match == Some(CompletionRelevancePostfixMatch::Exact), + "snippet", + ), (relevance.is_op_method, "op_method"), ] .into_iter() @@ -614,7 +617,7 @@ fn main() { let _: m::Spam = S$0 } is_local: false, is_op_method: false, is_private_editable: false, - exact_postfix_snippet_match: false, + postfix_match: None, }, }, CompletionItem { @@ -635,7 +638,7 @@ fn main() { let _: m::Spam = S$0 } is_local: false, is_op_method: false, is_private_editable: false, - exact_postfix_snippet_match: false, + postfix_match: None, }, }, ] @@ -722,7 +725,7 @@ fn foo() { A { the$0 } } is_local: false, is_op_method: false, is_private_editable: false, - exact_postfix_snippet_match: false, + postfix_match: None, }, }, ]