diff options
Diffstat (limited to 'src/libsyntax')
| -rw-r--r-- | src/libsyntax/util/lev_distance.rs | 33 | ||||
| -rw-r--r-- | src/libsyntax/util/lev_distance/tests.rs | 6 |
2 files changed, 34 insertions, 5 deletions
diff --git a/src/libsyntax/util/lev_distance.rs b/src/libsyntax/util/lev_distance.rs index fc697026fe4..cce86fed989 100644 --- a/src/libsyntax/util/lev_distance.rs +++ b/src/libsyntax/util/lev_distance.rs @@ -54,14 +54,16 @@ where T: Iterator<Item = &'a Symbol>, { let max_dist = dist.map_or_else(|| cmp::max(lookup.len(), 3) / 3, |d| d); + let name_vec: Vec<&Symbol> = iter_names.collect(); - let (case_insensitive_match, levenstein_match) = iter_names + let (case_insensitive_match, levenshtein_match) = name_vec + .iter() .filter_map(|&name| { let dist = lev_distance(lookup, &name.as_str()); if dist <= max_dist { Some((name, dist)) } else { None } }) // Here we are collecting the next structure: - // (case_insensitive_match, (levenstein_match, levenstein_distance)) + // (case_insensitive_match, (levenshtein_match, levenshtein_distance)) .fold((None, None), |result, (candidate, dist)| { ( if candidate.as_str().to_uppercase() == lookup.to_uppercase() { @@ -75,10 +77,31 @@ where }, ) }); - + // Priority of matches: + // 1. Exact case insensitive match + // 2. Levenshtein distance match + // 3. Sorted word match if let Some(candidate) = case_insensitive_match { - Some(candidate) // exact case insensitive match has a higher priority + Some(*candidate) + } else if levenshtein_match.is_some() { + levenshtein_match.map(|(candidate, _)| *candidate) } else { - levenstein_match.map(|(candidate, _)| candidate) + find_match_by_sorted_words(name_vec, lookup) } } + +fn find_match_by_sorted_words<'a>(iter_names: Vec<&'a Symbol>, lookup: &str) -> Option<Symbol> { + iter_names.iter().fold(None, |result, candidate| { + if sort_by_words(&candidate.as_str()) == sort_by_words(lookup) { + Some(**candidate) + } else { + result + } + }) +} + +fn sort_by_words(name: &str) -> String { + let mut split_words: Vec<&str> = name.split('_').collect(); + split_words.sort(); + split_words.join("_") +} diff --git a/src/libsyntax/util/lev_distance/tests.rs b/src/libsyntax/util/lev_distance/tests.rs index f65f9275d03..222661687c1 100644 --- a/src/libsyntax/util/lev_distance/tests.rs +++ b/src/libsyntax/util/lev_distance/tests.rs @@ -46,5 +46,11 @@ fn test_find_best_match_for_name() { find_best_match_for_name(input.iter(), "aaaa", Some(4)), Some(Symbol::intern("AAAA")) ); + + let input = vec![Symbol::intern("a_longer_variable_name")]; + assert_eq!( + find_best_match_for_name(input.iter(), "a_variable_longer_name", None), + Some(Symbol::intern("a_longer_variable_name")) + ); }) } |
