diff --git a/src/cargo/core/package_id_spec.rs b/src/cargo/core/package_id_spec.rs index 29043b96326..267ea3ffde2 100644 --- a/src/cargo/core/package_id_spec.rs +++ b/src/cargo/core/package_id_spec.rs @@ -7,9 +7,9 @@ use serde::{de, ser}; use url::Url; use crate::core::PackageId; +use crate::util::edit_distance; use crate::util::errors::CargoResult; use crate::util::interning::InternedString; -use crate::util::lev_distance; use crate::util::{validate_package_name, IntoUrl, ToSemver}; /// Some or all of the data required to identify a package: @@ -88,7 +88,7 @@ impl PackageIdSpec { { let i: Vec<_> = i.into_iter().collect(); let spec = PackageIdSpec::parse(spec).with_context(|| { - let suggestion = lev_distance::closest_msg(spec, i.iter(), |id| id.name().as_str()); + let suggestion = edit_distance::closest_msg(spec, i.iter(), |id| id.name().as_str()); format!("invalid package ID specification: `{}`{}", spec, suggestion) })?; spec.query(i) @@ -229,7 +229,7 @@ impl PackageIdSpec { ); } if suggestion.is_empty() { - suggestion.push_str(&lev_distance::closest_msg( + suggestion.push_str(&edit_distance::closest_msg( &self.name, all_ids.iter(), |id| id.name().as_str(), diff --git a/src/cargo/core/resolver/errors.rs b/src/cargo/core/resolver/errors.rs index 1db5aefe7fa..ca5c833f4bc 100644 --- a/src/cargo/core/resolver/errors.rs +++ b/src/cargo/core/resolver/errors.rs @@ -2,7 +2,7 @@ use std::fmt; use std::task::Poll; use crate::core::{Dependency, PackageId, QueryKind, Registry, Summary}; -use crate::util::lev_distance::lev_distance; +use crate::util::edit_distance::edit_distance; use crate::util::{Config, VersionExt}; use anyhow::Error; @@ -308,7 +308,7 @@ pub(super) fn activation_error( candidates.dedup_by(|a, b| a.name() == b.name()); let mut candidates: Vec<_> = candidates .iter() - .filter_map(|n| Some((lev_distance(&*new_dep.package_name(), &*n.name(), 3)?, n))) + .filter_map(|n| Some((edit_distance(&*new_dep.package_name(), &*n.name(), 3)?, n))) .collect(); candidates.sort_by_key(|o| o.0); let mut msg: String; diff --git a/src/cargo/core/workspace.rs b/src/cargo/core/workspace.rs index 01f3cb7c261..9922d6d331d 100644 --- a/src/cargo/core/workspace.rs +++ b/src/cargo/core/workspace.rs @@ -19,9 +19,9 @@ use crate::core::{Dependency, FeatureValue, PackageId, PackageIdSpec}; use crate::core::{EitherManifest, Package, SourceId, VirtualManifest}; use crate::ops; use crate::sources::{PathSource, CRATES_IO_INDEX, CRATES_IO_REGISTRY}; +use crate::util::edit_distance; use crate::util::errors::{CargoResult, ManifestError}; use crate::util::interning::InternedString; -use crate::util::lev_distance; use crate::util::toml::{read_manifest, InheritableFields, TomlDependency, TomlProfiles}; use crate::util::{config::ConfigRelativePath, Config, Filesystem, IntoUrl}; use cargo_util::paths; @@ -1245,8 +1245,8 @@ impl<'cfg> Workspace<'cfg> { optional_dependency_names_per_member.insert(member, optional_dependency_names_raw); } - let levenshtein_test = |a: InternedString, b: InternedString| { - lev_distance(a.as_str(), b.as_str(), 3).is_some() + let edit_distance_test = |a: InternedString, b: InternedString| { + edit_distance(a.as_str(), b.as_str(), 3).is_some() }; let suggestions: Vec<_> = cli_features @@ -1258,12 +1258,12 @@ impl<'cfg> Workspace<'cfg> { // Finds member features which are similar to the requested feature. let summary_features = summary_features .iter() - .filter(move |feature| levenshtein_test(**feature, *typo)); + .filter(move |feature| edit_distance_test(**feature, *typo)); // Finds optional dependencies which name is similar to the feature let optional_dependency_features = optional_dependency_names .iter() - .filter(move |feature| levenshtein_test(**feature, *typo)); + .filter(move |feature| edit_distance_test(**feature, *typo)); summary_features .chain(optional_dependency_features) @@ -1279,13 +1279,13 @@ impl<'cfg> Workspace<'cfg> { // Finds set of `pkg/feat` that are very similar to current `pkg/feat`. let pkg_feat_similar = dependencies_features .iter() - .filter(|(name, _)| levenshtein_test(**name, *dep_name)) + .filter(|(name, _)| edit_distance_test(**name, *dep_name)) .map(|(name, features)| { ( name, features .iter() - .filter(|feature| levenshtein_test(**feature, *dep_feature)) + .filter(|feature| edit_distance_test(**feature, *dep_feature)) .collect::>(), ) }) @@ -1299,12 +1299,12 @@ impl<'cfg> Workspace<'cfg> { // Finds set of `member/optional_dep` features which name is similar to current `pkg/feat`. let optional_dependency_features = optional_dependency_names_per_member .iter() - .filter(|(package, _)| levenshtein_test(package.name(), *dep_name)) + .filter(|(package, _)| edit_distance_test(package.name(), *dep_name)) .map(|(package, optional_dependencies)| { optional_dependencies .into_iter() .filter(|optional_dependency| { - levenshtein_test(**optional_dependency, *dep_name) + edit_distance_test(**optional_dependency, *dep_name) }) .map(move |optional_dependency| { format!("{}/{}", package.name(), optional_dependency) @@ -1315,12 +1315,12 @@ impl<'cfg> Workspace<'cfg> { // Finds set of `member/feat` features which name is similar to current `pkg/feat`. let summary_features = summary_features_per_member .iter() - .filter(|(package, _)| levenshtein_test(package.name(), *dep_name)) + .filter(|(package, _)| edit_distance_test(package.name(), *dep_name)) .map(|(package, summary_features)| { summary_features .into_iter() .filter(|summary_feature| { - levenshtein_test(**summary_feature, *dep_feature) + edit_distance_test(**summary_feature, *dep_feature) }) .map(move |summary_feature| { format!("{}/{}", package.name(), summary_feature) diff --git a/src/cargo/ops/cargo_clean.rs b/src/cargo/ops/cargo_clean.rs index b3e1bf48302..de3139c9947 100644 --- a/src/cargo/ops/cargo_clean.rs +++ b/src/cargo/ops/cargo_clean.rs @@ -2,9 +2,9 @@ use crate::core::compiler::{CompileKind, CompileMode, Layout, RustcTargetData}; use crate::core::profiles::Profiles; use crate::core::{PackageIdSpec, TargetKind, Workspace}; use crate::ops; +use crate::util::edit_distance; use crate::util::errors::CargoResult; use crate::util::interning::InternedString; -use crate::util::lev_distance; use crate::util::{Config, Progress, ProgressStyle}; use anyhow::Context as _; @@ -118,7 +118,7 @@ pub fn clean(ws: &Workspace<'_>, opts: &CleanOptions<'_>) -> CargoResult<()> { let matches: Vec<_> = resolve.iter().filter(|id| spec.matches(*id)).collect(); if matches.is_empty() { let mut suggestion = String::new(); - suggestion.push_str(&lev_distance::closest_msg( + suggestion.push_str(&edit_distance::closest_msg( &spec.name(), resolve.iter(), |id| id.name().as_str(), diff --git a/src/cargo/util/lev_distance.rs b/src/cargo/util/edit_distance.rs similarity index 86% rename from src/cargo/util/lev_distance.rs rename to src/cargo/util/edit_distance.rs index 10131f217d3..f77e48b4401 100644 --- a/src/cargo/util/lev_distance.rs +++ b/src/cargo/util/edit_distance.rs @@ -5,7 +5,7 @@ use std::{cmp, mem}; /// Returns `None` if the distance exceeds the limit. /// /// [edit distance]: https://en.wikipedia.org/wiki/Edit_distance -pub fn lev_distance(a: &str, b: &str, limit: usize) -> Option { +pub fn edit_distance(a: &str, b: &str, limit: usize) -> Option { // Comparing the strings lowercased will result in a difference in capitalization being less distance away // than being a completely different letter. Otherwise `CHECK` is as far away from `check` as it // is from `build` (both with a distance of 5). For a single letter shortcut (e.g. `b` or `c`), they will @@ -100,9 +100,9 @@ pub fn closest<'a, T>( iter: impl Iterator, key: impl Fn(&T) -> &'a str, ) -> Option { - // Only consider candidates with a lev_distance of 3 or less so we don't + // Only consider candidates with an edit distance of 3 or less so we don't // suggest out-of-the-blue options. - iter.filter_map(|e| Some((lev_distance(choice, key(&e), 3)?, e))) + iter.filter_map(|e| Some((edit_distance(choice, key(&e), 3)?, e))) .min_by_key(|t| t.0) .map(|t| t.1) } @@ -121,23 +121,23 @@ pub fn closest_msg<'a, T>( } #[test] -fn test_lev_distance() { +fn test_edit_distance() { use std::char::{from_u32, MAX}; // Test bytelength agnosticity for c in (0u32..MAX as u32) .filter_map(from_u32) .map(|i| i.to_string()) { - assert_eq!(lev_distance(&c, &c, usize::MAX), Some(0)); + assert_eq!(edit_distance(&c, &c, usize::MAX), Some(0)); } let a = "\nMäry häd ä little lämb\n\nLittle lämb\n"; let b = "\nMary häd ä little lämb\n\nLittle lämb\n"; let c = "Mary häd ä little lämb\n\nLittle lämb\n"; - assert_eq!(lev_distance(a, b, usize::MAX), Some(1)); - assert_eq!(lev_distance(b, a, usize::MAX), Some(1)); - assert_eq!(lev_distance(a, c, usize::MAX), Some(2)); - assert_eq!(lev_distance(c, a, usize::MAX), Some(2)); - assert_eq!(lev_distance(b, c, usize::MAX), Some(1)); - assert_eq!(lev_distance(c, b, usize::MAX), Some(1)); + assert_eq!(edit_distance(a, b, usize::MAX), Some(1)); + assert_eq!(edit_distance(b, a, usize::MAX), Some(1)); + assert_eq!(edit_distance(a, c, usize::MAX), Some(2)); + assert_eq!(edit_distance(c, a, usize::MAX), Some(2)); + assert_eq!(edit_distance(b, c, usize::MAX), Some(1)); + assert_eq!(edit_distance(c, b, usize::MAX), Some(1)); } diff --git a/src/cargo/util/mod.rs b/src/cargo/util/mod.rs index 12b1520181f..e72f8183b5f 100644 --- a/src/cargo/util/mod.rs +++ b/src/cargo/util/mod.rs @@ -7,6 +7,7 @@ pub use self::config::{homedir, Config, ConfigValue}; pub(crate) use self::counter::MetricsCounter; pub use self::dependency_queue::DependencyQueue; pub use self::diagnostic_server::RustfixDiagnosticServer; +pub use self::edit_distance::{closest, closest_msg, edit_distance}; pub use self::errors::CliError; pub use self::errors::{internal, CargoResult, CliResult}; pub use self::flock::{FileLock, Filesystem}; @@ -16,7 +17,6 @@ pub use self::hex::{hash_u64, short_hash, to_hex}; pub use self::into_url::IntoUrl; pub use self::into_url_with_base::IntoUrlWithBase; pub(crate) use self::io::LimitErrorReader; -pub use self::lev_distance::{closest, closest_msg, lev_distance}; pub use self::lockserver::{LockServer, LockServerClient, LockServerStarted}; pub use self::progress::{Progress, ProgressStyle}; pub use self::queue::Queue; @@ -38,6 +38,7 @@ mod counter; pub mod cpu; mod dependency_queue; pub mod diagnostic_server; +pub mod edit_distance; pub mod errors; mod flock; pub mod graph; @@ -49,7 +50,6 @@ pub mod into_url; mod into_url_with_base; mod io; pub mod job; -pub mod lev_distance; mod lockserver; pub mod machine_message; pub mod network;