Skip to content

Commit 91334e0

Browse files
committed
add a check for variable names that might match by word
1 parent 0ec3706 commit 91334e0

File tree

2 files changed

+34
-5
lines changed

2 files changed

+34
-5
lines changed

src/libsyntax/util/lev_distance.rs

Lines changed: 28 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,14 +52,15 @@ where
5252
T: Iterator<Item = &'a Symbol>,
5353
{
5454
let max_dist = dist.map_or_else(|| cmp::max(lookup.len(), 3) / 3, |d| d);
55+
let name_vec: Vec<&Symbol> = iter_names.collect();
5556

56-
let (case_insensitive_match, levenstein_match) = iter_names
57+
let (case_insensitive_match, levenshtein_match) = name_vec.iter()
5758
.filter_map(|&name| {
5859
let dist = lev_distance(lookup, &name.as_str());
5960
if dist <= max_dist { Some((name, dist)) } else { None }
6061
})
6162
// Here we are collecting the next structure:
62-
// (case_insensitive_match, (levenstein_match, levenstein_distance))
63+
// (case_insensitive_match, (levenshtein_match, levenshtein_distance))
6364
.fold((None, None), |result, (candidate, dist)| {
6465
(
6566
if candidate.as_str().to_uppercase() == lookup.to_uppercase() {
@@ -73,10 +74,32 @@ where
7374
},
7475
)
7576
});
76-
77+
78+
// Priority of matches:
79+
// 1. Exact case insensitive match
80+
// 2. Levenshtein distance match
81+
// 3. Sorted word match
7782
if let Some(candidate) = case_insensitive_match {
78-
Some(candidate) // exact case insensitive match has a higher priority
83+
Some(*candidate)
84+
} else if levenshtein_match.is_some() {
85+
levenshtein_match.map(|(candidate, _)| *candidate)
7986
} else {
80-
levenstein_match.map(|(candidate, _)| candidate)
87+
find_match_by_sorted_words(name_vec, lookup)
8188
}
8289
}
90+
91+
fn find_match_by_sorted_words<'a>(iter_names: Vec<&'a Symbol>, lookup: &str) -> Option<Symbol> {
92+
iter_names.iter().fold(None, |result, candidate| {
93+
if sort_by_words(&candidate.as_str()) == sort_by_words(lookup) {
94+
Some(**candidate)
95+
} else {
96+
result
97+
}
98+
})
99+
}
100+
101+
fn sort_by_words(name: &str) -> String {
102+
let mut split_words: Vec<&str> = name.split('_').collect();
103+
split_words.sort();
104+
split_words.join("_")
105+
}

src/libsyntax/util/lev_distance/tests.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,5 +46,11 @@ fn test_find_best_match_for_name() {
4646
find_best_match_for_name(input.iter(), "aaaa", Some(4)),
4747
Some(Symbol::intern("AAAA"))
4848
);
49+
50+
let input = vec![Symbol::intern("a_longer_variable_name")];
51+
assert_eq!(
52+
find_best_match_for_name(input.iter(), "a_variable_longer_name", None),
53+
Some(Symbol::intern("a_longer_variable_name"))
54+
);
4955
})
5056
}

0 commit comments

Comments
 (0)