|
1 |
| -use crate::item::CompletionItem; |
| 1 | +use crate::{ |
| 2 | + CompletionItemKind, |
| 3 | + context::CompletionContext, |
| 4 | + item::CompletionItem, |
| 5 | + relevance::{filtering::CompletionFilter, scoring::CompletionScore}, |
| 6 | +}; |
2 | 7 |
|
3 |
| -pub(crate) struct CompletionBuilder { |
4 |
| - items: Vec<CompletionItem>, |
| 8 | +pub(crate) struct PossibleCompletionItem<'a> { |
| 9 | + pub label: String, |
| 10 | + pub description: String, |
| 11 | + pub kind: CompletionItemKind, |
| 12 | + pub score: CompletionScore<'a>, |
| 13 | + pub filter: CompletionFilter<'a>, |
5 | 14 | }
|
6 | 15 |
|
7 |
| -impl CompletionBuilder { |
8 |
| - pub fn new() -> Self { |
9 |
| - CompletionBuilder { items: vec![] } |
| 16 | +pub(crate) struct CompletionBuilder<'a> { |
| 17 | + items: Vec<PossibleCompletionItem<'a>>, |
| 18 | + ctx: &'a CompletionContext<'a>, |
| 19 | +} |
| 20 | + |
| 21 | +impl<'a> CompletionBuilder<'a> { |
| 22 | + pub fn new(ctx: &'a CompletionContext) -> Self { |
| 23 | + CompletionBuilder { items: vec![], ctx } |
10 | 24 | }
|
11 | 25 |
|
12 |
| - pub fn add_item(&mut self, item: CompletionItem) { |
| 26 | + pub fn add_item(&mut self, item: PossibleCompletionItem<'a>) { |
13 | 27 | self.items.push(item);
|
14 | 28 | }
|
15 | 29 |
|
16 |
| - pub fn finish(mut self) -> Vec<CompletionItem> { |
17 |
| - self.items |
18 |
| - .sort_by(|a, b| b.score.cmp(&a.score).then_with(|| a.label.cmp(&b.label))); |
| 30 | + pub fn finish(self) -> Vec<CompletionItem> { |
| 31 | + let mut items: Vec<PossibleCompletionItem> = self |
| 32 | + .items |
| 33 | + .into_iter() |
| 34 | + .filter(|i| i.filter.is_relevant(self.ctx).is_some()) |
| 35 | + .collect(); |
| 36 | + |
| 37 | + for item in items.iter_mut() { |
| 38 | + item.score.calc_score(self.ctx); |
| 39 | + } |
19 | 40 |
|
20 |
| - self.items.dedup_by(|a, b| a.label == b.label); |
21 |
| - self.items.truncate(crate::LIMIT); |
| 41 | + items.sort_by(|a, b| { |
| 42 | + b.score |
| 43 | + .get_score() |
| 44 | + .cmp(&a.score.get_score()) |
| 45 | + .then_with(|| a.label.cmp(&b.label)) |
| 46 | + }); |
22 | 47 |
|
23 |
| - let should_preselect_first_item = self.should_preselect_first_item(); |
| 48 | + items.dedup_by(|a, b| a.label == b.label); |
| 49 | + items.truncate(crate::LIMIT); |
24 | 50 |
|
25 |
| - self.items |
| 51 | + let should_preselect_first_item = should_preselect_first_item(&items); |
| 52 | + |
| 53 | + items |
26 | 54 | .into_iter()
|
27 | 55 | .enumerate()
|
28 |
| - .map(|(idx, mut item)| { |
29 |
| - if idx == 0 { |
30 |
| - item.preselected = should_preselect_first_item; |
| 56 | + .map(|(idx, item)| { |
| 57 | + let preselected = idx == 0 && should_preselect_first_item; |
| 58 | + |
| 59 | + CompletionItem { |
| 60 | + description: item.description, |
| 61 | + kind: item.kind, |
| 62 | + label: item.label, |
| 63 | + preselected, |
| 64 | + score: item.score.get_score(), |
31 | 65 | }
|
32 |
| - item |
33 | 66 | })
|
34 | 67 | .collect()
|
35 | 68 | }
|
| 69 | +} |
36 | 70 |
|
37 |
| - fn should_preselect_first_item(&mut self) -> bool { |
38 |
| - let mut items_iter = self.items.iter(); |
39 |
| - let first = items_iter.next(); |
40 |
| - let second = items_iter.next(); |
| 71 | +fn should_preselect_first_item(items: &Vec<PossibleCompletionItem>) -> bool { |
| 72 | + let mut items_iter = items.iter(); |
| 73 | + let first = items_iter.next(); |
| 74 | + let second = items_iter.next(); |
41 | 75 |
|
42 |
| - first.is_some_and(|f| match second { |
43 |
| - Some(s) => (f.score - s.score) > 10, |
44 |
| - None => true, |
45 |
| - }) |
46 |
| - } |
| 76 | + first.is_some_and(|f| match second { |
| 77 | + Some(s) => (f.score.get_score() - s.score.get_score()) > 10, |
| 78 | + None => true, |
| 79 | + }) |
47 | 80 | }
|
0 commit comments