Skip to content

Commit 0a0fcdb

Browse files
committed
librustc: offer suggestions for unresolved names.
1 parent a8f07dc commit 0a0fcdb

File tree

1 file changed

+82
-2
lines changed

1 file changed

+82
-2
lines changed

src/librustc/middle/resolve.rs

Lines changed: 82 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4816,6 +4816,75 @@ pub impl Resolver {
48164816
}
48174817
}
48184818
4819+
fn find_best_match_for_name(@mut self, name: &str) -> Option<~str> {
4820+
let mut maybes: ~[~str] = ~[];
4821+
let mut values: ~[uint] = ~[];
4822+
4823+
let mut j = self.value_ribs.len();
4824+
while j != 0 {
4825+
j -= 1;
4826+
let rib = self.value_ribs.get_elt(j);
4827+
for rib.bindings.each_entry |e| {
4828+
vec::push(&mut maybes, copy *self.session.str_of(e.key));
4829+
vec::push(&mut values, uint::max_value);
4830+
}
4831+
}
4832+
4833+
// Levenshtein Distance between two strings
4834+
fn distance(s: &str, t: &str) -> uint {
4835+
4836+
let slen = str::len(s);
4837+
let tlen = str::len(t);
4838+
4839+
if slen == 0 { return tlen; }
4840+
if tlen == 0 { return slen; }
4841+
4842+
let mut dcol = vec::from_fn(tlen + 1, |x| x);
4843+
4844+
for str::each_chari(s) |i, sc| {
4845+
4846+
let mut current = i;
4847+
dcol[0] = current + 1;
4848+
4849+
for str::each_chari(t) |j, tc| {
4850+
4851+
let mut next = dcol[j + 1];
4852+
4853+
if sc == tc {
4854+
dcol[j + 1] = current;
4855+
} else {
4856+
dcol[j + 1] = cmp::min(current, next);
4857+
dcol[j + 1] = cmp::min(dcol[j + 1], dcol[j]) + 1;
4858+
}
4859+
4860+
current = next;
4861+
}
4862+
}
4863+
4864+
return dcol[tlen];
4865+
}
4866+
4867+
let mut smallest = 0;
4868+
for vec::eachi(maybes) |i, &other| {
4869+
4870+
values[i] = distance(name, other);
4871+
4872+
if values[i] <= values[smallest] {
4873+
smallest = i;
4874+
}
4875+
}
4876+
4877+
if vec::len(values) > 0 &&
4878+
values[smallest] != uint::max_value &&
4879+
values[smallest] < str::len(name) + 2 {
4880+
4881+
Some(vec::swap_remove(&mut maybes, smallest))
4882+
4883+
} else {
4884+
None
4885+
}
4886+
}
4887+
48194888
fn name_exists_in_scope_struct(@mut self, name: &str) -> bool {
48204889
let mut i = self.type_ribs.len();
48214890
while i != 0 {
@@ -4882,9 +4951,20 @@ pub impl Resolver {
48824951
wrong_name));
48834952
}
48844953
else {
4885-
self.session.span_err(expr.span,
4886-
fmt!("unresolved name: %s",
4954+
match self.find_best_match_for_name(wrong_name) {
4955+
4956+
Some(m) => {
4957+
self.session.span_err(expr.span,
4958+
fmt!("unresolved name: `%s`. \
4959+
Did you mean: `%s`?",
4960+
wrong_name, m));
4961+
}
4962+
None => {
4963+
self.session.span_err(expr.span,
4964+
fmt!("unresolved name: `%s`.",
48874965
wrong_name));
4966+
}
4967+
}
48884968
}
48894969
}
48904970
}

0 commit comments

Comments
 (0)