Introduce postfix item types

This commit is contained in:
Aleksei Trifonov 2022-04-01 20:50:27 +03:00
parent 41d8369d1c
commit eda4046a05
5 changed files with 50 additions and 33 deletions

View file

@ -12,9 +12,11 @@ use syntax::{
use text_edit::TextEdit; use text_edit::TextEdit;
use crate::{ use crate::{
completions::postfix::format_like::add_format_like_completions, context::CompletionContext, completions::postfix::format_like::add_format_like_completions,
item::Builder, patterns::ImmediateLocation, CompletionItem, CompletionItemKind, context::CompletionContext,
CompletionRelevance, Completions, SnippetScope, item::{Builder, CompletionRelevancePostfixMatch},
patterns::ImmediateLocation,
CompletionItem, CompletionItemKind, CompletionRelevance, Completions, SnippetScope,
}; };
pub(crate) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) { pub(crate) fn complete_postfix(acc: &mut Completions, ctx: &CompletionContext) {
@ -240,11 +242,12 @@ fn build_postfix_snippet_builder<'ctx>(
let mut item = let mut item =
CompletionItem::new(CompletionItemKind::Snippet, ctx.source_range(), label); CompletionItem::new(CompletionItemKind::Snippet, ctx.source_range(), label);
item.detail(detail).snippet_edit(cap, edit); item.detail(detail).snippet_edit(cap, edit);
let relevance = if ctx.original_token.text() == label { let postfix_match = if ctx.original_token.text() == label {
CompletionRelevance { exact_postfix_snippet_match: true, ..Default::default() } Some(CompletionRelevancePostfixMatch::Exact)
} else { } else {
CompletionRelevance { is_postfix: true, ..Default::default() } Some(CompletionRelevancePostfixMatch::NonExact)
}; };
let relevance = CompletionRelevance { postfix_match, ..Default::default() };
item.set_relevance(relevance); item.set_relevance(relevance);
item item
} }

View file

@ -4,7 +4,7 @@ use syntax::{ast::Expr, T};
use crate::{ use crate::{
patterns::ImmediateLocation, CompletionContext, CompletionItem, CompletionItemKind, patterns::ImmediateLocation, CompletionContext, CompletionItem, CompletionItemKind,
CompletionRelevance, Completions, CompletionRelevance, CompletionRelevancePostfixMatch, Completions,
}; };
pub(crate) fn complete_record(acc: &mut Completions, ctx: &CompletionContext) -> Option<()> { 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 = let completion_text =
completion_text.strip_prefix(ctx.token.text()).unwrap_or(completion_text); completion_text.strip_prefix(ctx.token.text()).unwrap_or(completion_text);
item.insert_text(completion_text).set_relevance(CompletionRelevance { item.insert_text(completion_text).set_relevance(CompletionRelevance {
exact_postfix_snippet_match: true, postfix_match: Some(CompletionRelevancePostfixMatch::Exact),
..Default::default() ..Default::default()
}); });
item.add_to(acc); item.add_to(acc);

View file

@ -143,17 +143,8 @@ pub struct CompletionRelevance {
pub is_op_method: bool, pub is_op_method: bool,
/// Set for item completions that are private but in the workspace. /// Set for item completions that are private but in the workspace.
pub is_private_editable: bool, pub is_private_editable: bool,
/// This is set in cases like these: /// Set for postfix snippet item completions
/// pub postfix_match: Option<CompletionRelevancePostfixMatch>,
/// ```
/// (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 in cases when item is postfix, but not exact
pub is_postfix: bool,
} }
#[derive(Debug, Clone, Copy, Eq, PartialEq)] #[derive(Debug, Clone, Copy, Eq, PartialEq)]
@ -180,6 +171,21 @@ pub enum CompletionRelevanceTypeMatch {
Exact, 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 { impl CompletionRelevance {
const BASE_LINE: u32 = 3; const BASE_LINE: u32 = 3;
/// Provides a relevance score. Higher values are more relevant. /// Provides a relevance score. Higher values are more relevant.
@ -201,7 +207,7 @@ impl CompletionRelevance {
if self.is_private_editable { if self.is_private_editable {
score -= 1; score -= 1;
} }
if self.is_postfix { if self.postfix_match.is_some() {
score -= 3; score -= 3;
} }
@ -217,7 +223,7 @@ impl CompletionRelevance {
if self.is_local { if self.is_local {
score += 1; score += 1;
} }
if self.exact_postfix_snippet_match { if self.postfix_match == Some(CompletionRelevancePostfixMatch::Exact) {
score += 100; score += 100;
} }
@ -536,7 +542,9 @@ mod tests {
use itertools::Itertools; use itertools::Itertools;
use test_utils::assert_eq_text; 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 /// Check that these are CompletionRelevance are sorted in ascending order
/// by their relevance score. /// by their relevance score.
@ -579,7 +587,10 @@ mod tests {
// This test asserts that the relevance score for these items is ascending, and // This test asserts that the relevance score for these items is ascending, and
// that any items in the same vec have the same score. // that any items in the same vec have the same score.
let expected_relevance_order = vec![ let expected_relevance_order = vec![
vec![CompletionRelevance { is_postfix: true, ..CompletionRelevance::default() }], vec![CompletionRelevance {
postfix_match: Some(CompletionRelevancePostfixMatch::NonExact),
..CompletionRelevance::default()
}],
vec![CompletionRelevance { vec![CompletionRelevance {
is_op_method: true, is_op_method: true,
is_private_editable: true, is_private_editable: true,
@ -619,7 +630,7 @@ mod tests {
..CompletionRelevance::default() ..CompletionRelevance::default()
}], }],
vec![CompletionRelevance { vec![CompletionRelevance {
exact_postfix_snippet_match: true, postfix_match: Some(CompletionRelevancePostfixMatch::Exact),
..CompletionRelevance::default() ..CompletionRelevance::default()
}], }],
]; ];

View file

@ -28,7 +28,10 @@ use crate::{completions::Completions, context::CompletionContext};
pub use crate::{ pub use crate::{
config::CompletionConfig, config::CompletionConfig,
item::{CompletionItem, CompletionItemKind, CompletionRelevance, ImportEdit}, item::{
CompletionItem, CompletionItemKind, CompletionRelevance, CompletionRelevancePostfixMatch,
ImportEdit,
},
snippet::{Snippet, SnippetScope}, snippet::{Snippet, SnippetScope},
}; };

View file

@ -365,7 +365,7 @@ mod tests {
use crate::{ use crate::{
item::CompletionRelevanceTypeMatch, item::CompletionRelevanceTypeMatch,
tests::{check_edit, do_completion, get_all_items, TEST_CONFIG}, tests::{check_edit, do_completion, get_all_items, TEST_CONFIG},
CompletionItem, CompletionItemKind, CompletionRelevance, CompletionItem, CompletionItemKind, CompletionRelevance, CompletionRelevancePostfixMatch,
}; };
#[track_caller] #[track_caller]
@ -432,7 +432,10 @@ mod tests {
), ),
(relevance.exact_name_match, "name"), (relevance.exact_name_match, "name"),
(relevance.is_local, "local"), (relevance.is_local, "local"),
(relevance.exact_postfix_snippet_match, "snippet"), (
relevance.postfix_match == Some(CompletionRelevancePostfixMatch::Exact),
"snippet",
),
(relevance.is_op_method, "op_method"), (relevance.is_op_method, "op_method"),
] ]
.into_iter() .into_iter()
@ -614,8 +617,7 @@ fn main() { let _: m::Spam = S$0 }
is_local: false, is_local: false,
is_op_method: false, is_op_method: false,
is_private_editable: false, is_private_editable: false,
exact_postfix_snippet_match: false, postfix_match: None,
is_postfix: false,
}, },
}, },
CompletionItem { CompletionItem {
@ -636,8 +638,7 @@ fn main() { let _: m::Spam = S$0 }
is_local: false, is_local: false,
is_op_method: false, is_op_method: false,
is_private_editable: false, is_private_editable: false,
exact_postfix_snippet_match: false, postfix_match: None,
is_postfix: false,
}, },
}, },
] ]
@ -724,8 +725,7 @@ fn foo() { A { the$0 } }
is_local: false, is_local: false,
is_op_method: false, is_op_method: false,
is_private_editable: false, is_private_editable: false,
exact_postfix_snippet_match: false, postfix_match: None,
is_postfix: false,
}, },
}, },
] ]