@@ -174,10 +174,10 @@ pub fn find_best_match_for_name(
174174fn  find_best_match_for_name_impl ( 
175175    use_substring_score :  bool , 
176176    candidates :  & [ Symbol ] , 
177-     lookup :  Symbol , 
177+     lookup_symbol :  Symbol , 
178178    dist :  Option < usize > , 
179179)  -> Option < Symbol >  { 
180-     let  lookup = lookup . as_str ( ) ; 
180+     let  lookup = lookup_symbol . as_str ( ) ; 
181181    let  lookup_uppercase = lookup. to_uppercase ( ) ; 
182182
183183    // Priority of matches: 
@@ -190,6 +190,8 @@ fn find_best_match_for_name_impl(
190190
191191    let  mut  dist = dist. unwrap_or_else ( || cmp:: max ( lookup. len ( ) ,  3 )  / 3 ) ; 
192192    let  mut  best = None ; 
193+     // store the candidates with the same distance, only for `use_substring_score` current. 
194+     let  mut  next_candidates = vec ! [ ] ; 
193195    for  c in  candidates { 
194196        match  if  use_substring_score { 
195197            edit_distance_with_substrings ( lookup,  c. as_str ( ) ,  dist) 
@@ -198,12 +200,36 @@ fn find_best_match_for_name_impl(
198200        }  { 
199201            Some ( 0 )  => return  Some ( * c) , 
200202            Some ( d)  => { 
201-                 dist = d - 1 ; 
203+                 if  use_substring_score { 
204+                     if  d < dist { 
205+                         dist = d; 
206+                         next_candidates. clear ( ) ; 
207+                     }  else  { 
208+                         // `d == dist` here, we need to store the candidates with the same distance 
209+                         // so we won't decrease the distance in the next loop. 
210+                     } 
211+                     next_candidates. push ( * c) ; 
212+                 }  else  { 
213+                     dist = d - 1 ; 
214+                 } 
202215                best = Some ( * c) ; 
203216            } 
204217            None  => { } 
205218        } 
206219    } 
220+ 
221+     // We have a tie among several candidates, try to select the best among them ignoring substrings. 
222+     // For example, the candidates list `force_capture`, `capture`, and user inputed `forced_capture`, 
223+     // we select `force_capture` with a extra round of edit distance calculation. 
224+     if  next_candidates. len ( )  > 1  { 
225+         debug_assert ! ( use_substring_score) ; 
226+         best = find_best_match_for_name_impl ( 
227+             false , 
228+             & next_candidates, 
229+             lookup_symbol, 
230+             Some ( lookup. len ( ) ) , 
231+         ) ; 
232+     } 
207233    if  best. is_some ( )  { 
208234        return  best; 
209235    } 
0 commit comments