Skip to main content

cynic_codegen/suggestions/
mod.rs

1use strsim::jaro_winkler;
2
3/// Using Hamming algorithm to guess possible similar fields.
4pub fn guess_field<'a>(
5    candidates: impl Iterator<Item = &'a str>,
6    provided_name: &str,
7) -> Option<&'a str> {
8    let (chosen_candidate, _) = candidates
9        .map(|candidate| (candidate, jaro_winkler(candidate, provided_name)))
10        .filter(|(_, distance)| *distance > 0.6)
11        .reduce(|lhs @ (_, distance_lhs), rhs @ (_, distance_rhs)| {
12            if distance_lhs > distance_rhs {
13                lhs
14            } else {
15                rhs
16            }
17        })?;
18
19    Some(chosen_candidate)
20}
21
22pub fn format_guess(guess_field: Option<&str>) -> String {
23    match guess_field {
24        Some(v) => format!(" Did you mean `{v}`?"),
25        None => "".to_owned(),
26    }
27}
28
29pub struct FieldSuggestionError<'a> {
30    pub expected_field: &'a str,
31    pub graphql_type_name: &'a str,
32    pub suggested_field: Option<&'a str>,
33}
34
35impl std::fmt::Display for FieldSuggestionError<'_> {
36    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
37        write!(
38            f,
39            "no field `{}` on the GraphQL type `{}`. {}",
40            self.expected_field,
41            self.graphql_type_name,
42            format_guess(self.suggested_field)
43        )
44    }
45}