diff options
| author | cjkenn <cam.j.kennedy@gmail.com> | 2020-01-03 15:53:03 -0800 |
|---|---|---|
| committer | cjkenn <cam.j.kennedy@gmail.com> | 2020-01-03 15:53:03 -0800 |
| commit | 91334e0a799c35d6adf0a226a2f0aee0d70896e3 (patch) | |
| tree | a13789d8c1e7cbe885a83b4851ab1b65aaafa2fa | |
| parent | 0ec370670220b712b042ee09aab067ec7e5878d5 (diff) | |
| download | rust-91334e0a799c35d6adf0a226a2f0aee0d70896e3.tar.gz rust-91334e0a799c35d6adf0a226a2f0aee0d70896e3.zip | |
add a check for variable names that might match by word
| -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 f55b58d7d13..8ddda1720b8 100644 --- a/src/libsyntax/util/lev_distance.rs +++ b/src/libsyntax/util/lev_distance.rs @@ -52,14 +52,15 @@ 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() { @@ -73,10 +74,32 @@ 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")) + ); }) } |
