Skip to content

Commit 927cbe2

Browse files
committed
add find_best_match_for_names for multiple lookups
1 parent c335dd4 commit 927cbe2

File tree

2 files changed

+33
-8
lines changed

2 files changed

+33
-8
lines changed

compiler/rustc_lint/src/context.rs

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ use rustc_middle::ty::{self, print::Printer, GenericArg, RegisteredTools, Ty, Ty
3333
use rustc_session::lint::{BuiltinLintDiagnostics, LintExpectationId};
3434
use rustc_session::lint::{FutureIncompatibleInfo, Level, Lint, LintBuffer, LintId};
3535
use rustc_session::{LintStoreMarker, Session};
36-
use rustc_span::edit_distance::find_best_match_for_name;
36+
use rustc_span::edit_distance::find_best_match_for_names;
3737
use rustc_span::symbol::{sym, Ident, Symbol};
3838
use rustc_span::Span;
3939
use rustc_target::abi;
@@ -442,14 +442,11 @@ impl LintStore {
442442
let groups = groups.iter().map(|k| Symbol::intern(k));
443443
let lints = self.lints.iter().map(|l| Symbol::intern(&l.name_lower()));
444444
let names: Vec<Symbol> = groups.chain(lints).collect();
445-
let mut res = find_best_match_for_name(&names, Symbol::intern(&name_lower), Some(2));
446-
if res.is_none() && name_lower.contains("::") {
447-
let stripped = name_lower.split("::").last().unwrap();
448-
res = find_best_match_for_name(&names, Symbol::intern(stripped), Some(2));
449-
}
450-
if res.is_none() {
451-
res = find_best_match_for_name(&names, Symbol::intern(&name_lower), None);
445+
let mut lookups = vec![Symbol::intern(&name_lower)];
446+
if let Some(stripped) = name_lower.split("::").last() {
447+
lookups.push(Symbol::intern(stripped));
452448
}
449+
let res = find_best_match_for_names(&names, &lookups, None);
453450
let is_rustc = res.map_or_else(
454451
|| false,
455452
|s| name_lower.contains("::") && !s.as_str().starts_with(tool_name),

compiler/rustc_span/src/edit_distance.rs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,34 @@ pub fn find_best_match_for_name(
170170
find_best_match_for_name_impl(false, candidates, lookup, dist)
171171
}
172172

173+
/// Find the best match for a give word list
174+
///
175+
/// This function is helpfull when we have multiple patterns for candidates, for example:
176+
///
177+
/// For give keyword `clippy::missing_docs`, we may have multiple candidates:
178+
/// - `clippy::missing_docs_in_private_items`
179+
/// - `clippy::erasing_op`
180+
/// - `missing_docs`
181+
///
182+
/// We want to find the best match for the given keyword, strip a prefix to get `missing_docs`,
183+
/// then call this function with `lookups` as `["clippy::missing_docs", "missing_docs"]`
184+
pub fn find_best_match_for_names(
185+
candidates: &[Symbol],
186+
lookups: &[Symbol],
187+
dist: Option<usize>,
188+
) -> Option<Symbol> {
189+
lookups
190+
.iter()
191+
.map(|s| (s, find_best_match_for_name_impl(false, candidates, *s, dist)))
192+
.filter_map(|(s, r)| r.map(|r| (s, r)))
193+
.min_by(|(s1, r1), (s2, r2)| {
194+
let d1 = edit_distance(s1.as_str(), r1.as_str(), usize::MAX).unwrap();
195+
let d2 = edit_distance(s2.as_str(), r2.as_str(), usize::MAX).unwrap();
196+
d1.cmp(&d2)
197+
})
198+
.map(|(_, r)| r)
199+
}
200+
173201
#[cold]
174202
fn find_best_match_for_name_impl(
175203
use_substring_score: bool,

0 commit comments

Comments
 (0)