use crate::{MethodCatalog, MethodEntry};
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct CompletionItem {
pub receiver: String,
pub name: String,
pub params: Vec<String>,
pub result: String,
pub doc: String,
}
#[must_use]
pub fn completion_data(catalog: &MethodCatalog) -> Vec<CompletionItem> {
catalog.entries().iter().map(entry_to_item).collect()
}
fn entry_to_item(e: &MethodEntry) -> CompletionItem {
CompletionItem {
receiver: e.receiver.to_string(),
name: e.name.to_string(),
params: e.params.iter().map(|p| p.to_string()).collect(),
result: e.result.to_string(),
doc: e.doc.to_string(),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn completion_data_covers_every_catalog_entry() {
let cat = crate::builtin_catalog();
let items = completion_data(&cat);
assert_eq!(
items.len(),
cat.len(),
"completion data must cover every catalog entry"
);
let has_vec_push = items
.iter()
.any(|i| i.receiver == "Vec[T]" && i.name == "push");
assert!(has_vec_push, "Vec[T].push must be in completion data");
let has_map_insert = items
.iter()
.any(|i| i.receiver == "Map[K, V]" && i.name == "insert");
assert!(
has_map_insert,
"Map[K, V].insert must be in completion data"
);
let has_grid_neighbors4 = items
.iter()
.any(|i| i.receiver == "Grid[T]" && i.name == "neighbors4");
assert!(
has_grid_neighbors4,
"Grid[T].neighbors4 must be in completion data"
);
}
#[test]
fn completion_data_round_trips_receiver_name_arity() {
let cat = crate::builtin_catalog();
let items = completion_data(&cat);
let triples: Vec<(String, String, usize)> = items
.iter()
.map(|i| (i.receiver.clone(), i.name.clone(), i.params.len()))
.collect();
let unique: std::collections::HashSet<_> = triples.iter().collect();
assert_eq!(
unique.len(),
items.len(),
"completion triples must be unique"
);
}
}