Skip to content

Commit

Permalink
Unify suggestion-code, suggest different case words
Browse files Browse the repository at this point in the history
  • Loading branch information
sharkdp authored and David Peter committed Jul 27, 2023
1 parent a444ac4 commit d4297c0
Show file tree
Hide file tree
Showing 4 changed files with 35 additions and 21 deletions.
1 change: 1 addition & 0 deletions numbat/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ mod quantity;
mod registry;
pub mod resolver;
mod span;
mod suggestion;
mod tokenizer;
mod typechecker;
mod typed_ast;
Expand Down
19 changes: 8 additions & 11 deletions numbat/src/registry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use thiserror::Error;
use crate::{
arithmetic::{pretty_exponent, Exponent, Power, Rational},
product::{Canonicalize, Product},
suggestion,
};

#[derive(Clone, Error, Debug, PartialEq, Eq)]
Expand Down Expand Up @@ -126,17 +127,13 @@ impl<Metadata> Registry<Metadata> {
self.derived_entries
.get(name)
.ok_or_else(|| {
let suggestion = self
.base_entries
.iter()
.map(|(id, _)| id.to_string())
.chain(self.derived_entries.keys().map(|s| s.to_string()))
.min_by_key(|id| strsim::damerau_levenshtein(id, name))
.filter(|id| {
name.len() >= 3
&& id.len() >= 2
&& strsim::damerau_levenshtein(id, name) <= 3
});
let suggestion = suggestion::did_you_mean(
self.base_entries
.iter()
.map(|(id, _)| id.to_string())
.chain(self.derived_entries.keys().map(|s| s.to_string())),
name,
);
RegistryError::UnknownEntry(name.to_owned(), suggestion)
})
.cloned()
Expand Down
22 changes: 22 additions & 0 deletions numbat/src/suggestion.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
pub fn did_you_mean<S: AsRef<str>, T: AsRef<str>>(
entries: impl Iterator<Item = S>,
user_input: T,
) -> Option<String> {
if user_input.as_ref().len() < 3 {
return None;
}

entries
.map(|ref id| {
(
id.as_ref().to_string(),
strsim::damerau_levenshtein(
&id.as_ref().to_lowercase(),
&user_input.as_ref().to_lowercase(),
),
)
})
.min_by_key(|(_, dist)| *dist)
.filter(|(id, dist)| id.len() >= 2 && *dist <= 3)
.map(|(id, _)| id)
}
14 changes: 4 additions & 10 deletions numbat/src/typechecker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::name_resolution::LAST_RESULT_IDENTIFIERS;
use crate::registry::{BaseRepresentation, BaseRepresentationFactor, RegistryError};
use crate::span::Span;
use crate::typed_ast::{self, Type};
use crate::{ast, decorator, ffi};
use crate::{ast, decorator, ffi, suggestion};

use ast::DimensionExpression;
use num_traits::{CheckedAdd, CheckedDiv, CheckedMul, CheckedSub, FromPrimitive, Zero};
Expand Down Expand Up @@ -169,15 +169,9 @@ pub struct TypeChecker {
impl TypeChecker {
fn type_for_identifier(&self, span: Span, name: &str) -> Result<&Type> {
self.identifiers.get(name).ok_or_else(|| {
let suggestion = self
.identifiers
.iter()
.map(|(id, _)| id)
.min_by_key(|id| strsim::damerau_levenshtein(id, name))
.filter(|id| {
name.len() >= 3 && id.len() >= 2 && strsim::damerau_levenshtein(id, name) <= 3
});
TypeCheckError::UnknownIdentifier(span, name.into(), suggestion.cloned())
let suggestion =
suggestion::did_you_mean(self.identifiers.iter().map(|(id, _)| id), name);
TypeCheckError::UnknownIdentifier(span, name.into(), suggestion)
})
}

Expand Down

0 comments on commit d4297c0

Please sign in to comment.