use std::sync::Arc;
use reedline::{Completer, Span, Suggestion};
use super::completion::{CompletionEngine, MongoCandidateProvider};
use super::shared_state::SharedState;
use crate::executor::ExecutionContext;
pub struct MongoCompleter {
completion_engine: CompletionEngine,
}
impl MongoCompleter {
pub fn new(
shared_state: SharedState,
execution_context: Option<Arc<ExecutionContext>>,
) -> Self {
let provider = Arc::new(MongoCandidateProvider::new(
shared_state.clone(),
execution_context,
));
let completion_engine = CompletionEngine::new(provider);
Self { completion_engine }
}
}
impl Completer for MongoCompleter {
fn complete(&mut self, line: &str, pos: usize) -> Vec<Suggestion> {
let (start, candidates) = self.completion_engine.complete(line, pos);
candidates
.into_iter()
.map(|pair| Suggestion {
value: pair.replacement,
description: pair.description,
style: None,
extra: None,
span: Span::new(start, pos),
append_whitespace: false,
match_indices: None,
})
.collect()
}
}
#[cfg(test)]
mod tests {
use super::*;
fn create_test_completer() -> MongoCompleter {
let shared_state = SharedState::new("test".to_string());
MongoCompleter::new(shared_state, None)
}
#[test]
fn test_complete_collection_dot() {
let mut completer = create_test_completer();
let suggestions = completer.complete("db.users.", 9);
assert!(!suggestions.is_empty());
assert!(suggestions.iter().any(|s| s.value == "find"));
assert!(suggestions.iter().any(|s| s.value == "insertOne"));
}
#[test]
fn test_complete_with_prefix() {
let mut completer = create_test_completer();
let suggestions = completer.complete("db.users.fi", 11);
assert!(suggestions.iter().any(|s| s.value == "find"));
assert!(suggestions.iter().any(|s| s.value == "findOne"));
assert!(!suggestions.iter().any(|s| s.value == "insertOne"));
}
#[test]
fn test_span_position() {
let mut completer = create_test_completer();
let suggestions = completer.complete("db.users.find", 13);
for suggestion in suggestions {
assert_eq!(suggestion.span.start, 9); assert_eq!(suggestion.span.end, 13); }
}
}