Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(core): updates to SpelledNumbers #325

Merged
merged 2 commits into from
Dec 24, 2024
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 36 additions & 18 deletions harper-core/src/linting/spelled_numbers.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::linting::{LintKind, Linter, Suggestion};
use crate::{Document, Lint, TokenStringExt};

/// Linter that checks to make sure small integers (< one hundred) are spelled
/// Linter that checks to make sure small integers (< 10) are spelled
/// out.
#[derive(Default, Clone, Copy)]
pub struct SpelledNumbers;
Expand All @@ -14,14 +14,14 @@ impl Linter for SpelledNumbers {
let (number, _suffix) = number_tok.kind.number().unwrap();
let number: f64 = number.into();

if (number - number.floor()).abs() < f64::EPSILON && number <= 10. {
if (number - number.floor()).abs() < f64::EPSILON && number < 10. {
lints.push(Lint {
span: number_tok.span,
lint_kind: LintKind::Readability,
suggestions: vec![Suggestion::ReplaceWith(
spell_out_number(number as u64).unwrap().chars().collect(),
)],
message: "Try to spell out numbers less than a hundred.".to_string(),
message: "Try to spell out numbers less than ten.".to_string(),
Copy link
Collaborator Author

@grantlemons grantlemons Dec 22, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is kinda funny that this is spelled out when under my change it wouldn't be suggested.

I've always worked on the principle of:

  • Spelled out for < 10
  • Numerals for > 10
  • Whatever feels best for 10 in the moment

priority: 63,
})
}
Expand All @@ -33,12 +33,11 @@ impl Linter for SpelledNumbers {

/// Converts a number to it's spelled-out variant.
///
/// For example: 100 -> one-hundred.
/// For example: 100 -> one hundred.
///
/// Could easily be extended to support numbers greater than 110, but we don't
/// need that yet.
/// Works for numbers up to 999, but can be expanded to include more powers of 10.
fn spell_out_number(num: u64) -> Option<String> {
if num > 110 {
if num > 999 {
return None;
}

Expand All @@ -56,6 +55,13 @@ fn spell_out_number(num: u64) -> Option<String> {
10 => "ten".to_string(),
11 => "eleven".to_string(),
12 => "twelve".to_string(),
13 => "thirteen".to_string(),
14 => "fourteen".to_string(),
15 => "fifteen".to_string(),
16 => "sixteen".to_string(),
17 => "seventeen".to_string(),
18 => "eighteen".to_string(),
19 => "nineteen".to_string(),
20 => "twenty".to_string(),
30 => "thirty".to_string(),
40 => "forty".to_string(),
Expand All @@ -64,14 +70,18 @@ fn spell_out_number(num: u64) -> Option<String> {
70 => "seventy".to_string(),
80 => "eighty".to_string(),
90 => "ninety".to_string(),
100 => "one hundred".to_string(),
hundred if hundred % 100 == 0 => {
format!("{} hundred", spell_out_number(hundred / 100).unwrap())
}
Comment on lines +73 to +75
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This logic should probably be expanded to include more suffixes for powers of 10 up to 10^19 so it will work for large numbers at the beginning of sentences.

(10^19 is the largest power of 10 a u64 could represent)

_ => {
let parent = (num / 10) * 10;
let child = num % 10;
let n = 10u64.pow((num as f32).log10() as u32);
let parent = (num / n) * n; // truncate
let child = num % n;
Comment on lines +77 to +79
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This modification allows the truncation to extend to n digits, instead of just working for two digits as in the past.

This used to cause a stack overflow for n = 110. (and probably 101 to 109 as well)


format!(
"{} {}",
"{}{}{}",
spell_out_number(parent).unwrap(),
if num <= 99 { '-' } else { ' ' },
Comment on lines +82 to +84
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is because numbers between twenty-one and ninety-nine should be hyphenated.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Toss this info in a comment in the code.

spell_out_number(child).unwrap()
)
}
Expand All @@ -85,22 +95,30 @@ mod tests {
use super::{spell_out_number, SpelledNumbers};

#[test]
fn produces_fifty_three() {
assert_eq!(spell_out_number(53), Some("fifty three".to_string()))
fn produces_zero() {
assert_eq!(spell_out_number(0), Some("zero".to_string()))
}

#[test]
fn produces_eighty_two() {
assert_eq!(spell_out_number(82), Some("eighty two".to_string()))
assert_eq!(spell_out_number(82), Some("eighty-two".to_string()))
}

#[test]
fn produces_nine_hundred_ninety_nine() {
assert_eq!(
spell_out_number(999),
Some("nine hundred ninety-nine".to_string())
)
}

#[test]
fn corrects_ten() {
assert_suggestion_result("There are 10 pigs.", SpelledNumbers, "There are ten pigs.");
fn corrects_nine() {
assert_suggestion_result("There are 9 pigs.", SpelledNumbers, "There are nine pigs.");
}

#[test]
fn does_not_correct_eleven() {
assert_suggestion_result("There are 11 pigs.", SpelledNumbers, "There are 11 pigs.");
fn does_not_correct_ten() {
assert_suggestion_result("There are 10 pigs.", SpelledNumbers, "There are 10 pigs.");
}
}
Loading