Skip to content
12 changes: 2 additions & 10 deletions harper-core/src/linting/confident.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{
Token,
patterns::{OwnedPatternExt, Pattern, SequencePattern, Word},
patterns::{Pattern, new_syntax_experiment::prelude::*},
};

use super::{Lint, LintKind, PatternLinter, Suggestion};
Expand All @@ -11,16 +11,8 @@ pub struct Confident {

impl Default for Confident {
fn default() -> Self {
let pattern = SequencePattern::default()
.then(
(|tok: &Token, _source: &[char]| tok.kind.is_verb() || tok.kind.is_determiner())
.or(Box::new(Word::new("very"))),
)
.then_whitespace()
.t_aco("confidant");

Self {
pattern: Box::new(pattern),
pattern: Box::new(seq![Verb | Det | "very", WS, "confidant"]),
}
}
}
Expand Down
8 changes: 2 additions & 6 deletions harper-core/src/linting/despite_of.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{
Token, TokenStringExt,
patterns::{Pattern, SequencePattern},
patterns::{Pattern, new_syntax_experiment::prelude::*},
};

use super::{Lint, LintKind, PatternLinter, Suggestion};
Expand All @@ -11,12 +11,8 @@ pub struct DespiteOf {

impl Default for DespiteOf {
fn default() -> Self {
let pattern = SequencePattern::aco("despite")
.then_whitespace()
.then_exact_word("of");

Self {
pattern: Box::new(pattern),
pattern: Box::new(seq!["despite", WS, exact("of")]),
}
}
}
Expand Down
62 changes: 8 additions & 54 deletions harper-core/src/linting/modal_of.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use crate::{
Lrc, Token, TokenStringExt,
patterns::{EitherPattern, Pattern, SequencePattern, WordSet},
Token, TokenStringExt,
patterns::{Pattern, new_syntax_experiment::prelude::*},
};

use super::{Lint, LintKind, PatternLinter, Suggestion};
Expand All @@ -21,43 +21,11 @@ impl Default for ModalOf {
words.add(&format!("{}n't", word));
});

let modal_of = Lrc::new(
SequencePattern::default()
.then(words)
.then_whitespace()
.t_aco("of"),
);

let ws_course = Lrc::new(SequencePattern::default().then_whitespace().t_aco("course"));

let modal_of_course = Lrc::new(
SequencePattern::default()
.then(modal_of.clone())
.then(ws_course.clone()),
);

let anyword_might_of = Lrc::new(
SequencePattern::default()
.then_any_word()
.then_whitespace()
.t_aco("might")
.then_whitespace()
.t_aco("of"),
);

let anyword_might_of_course = Lrc::new(
SequencePattern::default()
.then(anyword_might_of.clone())
.then(ws_course.clone()),
);

Self {
pattern: Box::new(EitherPattern::new(vec![
Box::new(anyword_might_of_course),
Box::new(modal_of_course),
Box::new(anyword_might_of),
Box::new(modal_of),
])),
pattern: Box::new(choice![
seq![AnyWord, WS, "might", WS, "of", not_next![WS, "course"]],
seq![words, WS, "of", not_next![WS, "course"]],
]),
}
}
}
Expand All @@ -69,20 +37,7 @@ impl PatternLinter for ModalOf {

fn match_to_lint(&self, matched_toks: &[Token], source_chars: &[char]) -> Option<Lint> {
let modal_index = match matched_toks.len() {
// Without context, always an error from the start
3 => 0,
5 => {
// False positives: modal _ of _ course / adj. _ might _ of / art. _ might _ of
let w3_text = matched_toks
.last()
.unwrap()
.span
.get_content(source_chars)
.iter()
.collect::<String>();
if w3_text.as_str() != "of" {
return None;
}
let w1_kind = &matched_toks.first().unwrap().kind;
// the might of something, great might of something
if w1_kind.is_adjective() || w1_kind.is_determiner() {
Expand All @@ -91,9 +46,8 @@ impl PatternLinter for ModalOf {
// not a false positive, skip context before
2
}
// False positive: <word> _ might _ of _ course
7 => return None,
_ => unreachable!(),
// Without context, always an error from the start
_ => 0,
};

let span_modal_of = matched_toks[modal_index..modal_index + 3].span().unwrap();
Expand Down
1 change: 1 addition & 0 deletions harper-core/src/patterns/any_pattern.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use crate::Token;
use super::Pattern;

/// A [`Pattern`] that will match any single token.
#[derive(Clone, Copy)]
pub struct AnyPattern;

impl Pattern for AnyPattern {
Expand Down
40 changes: 27 additions & 13 deletions harper-core/src/patterns/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ mod indefinite_article;
mod inflection_of_be;
mod invert;
mod naive_pattern_group;
pub mod new_syntax_experiment;
mod nominal_phrase;
mod pattern_map;
mod repeating_pattern;
Expand Down Expand Up @@ -144,31 +145,44 @@ where
}

#[cfg(feature = "concurrent")]
impl<F> Pattern for F
where
F: Fn(&Token, &[char]) -> bool,
F: Send + Sync,
{
pub trait SinlgeTokenPattern: Send + Sync + 'static {
fn matches_token(&self, token: &Token, source: &[char]) -> bool;
}
#[cfg(not(feature = "concurrent"))]
pub trait SinlgeTokenPattern: 'static {
fn matches_token(&self, token: &Token, source: &[char]) -> bool;
}

impl<P: SinlgeTokenPattern> Pattern for P {
fn matches(&self, tokens: &[Token], source: &[char]) -> Option<usize> {
if self(tokens.first()?, source) {
let t = tokens.first()?;
if self.matches_token(t, source) {
Some(1)
} else {
None
}
}
}

#[cfg(feature = "concurrent")]
impl<F> SinlgeTokenPattern for F
where
F: Fn(&Token, &[char]) -> bool,
F: Send + Sync + 'static,
{
fn matches_token(&self, token: &Token, source: &[char]) -> bool {
self(token, source)
}
}

#[cfg(not(feature = "concurrent"))]
impl<F> Pattern for F
impl<F> SinlgeTokenPattern for F
where
F: Fn(&Token, &[char]) -> bool,
F: 'static,
{
fn matches(&self, tokens: &[Token], source: &[char]) -> Option<NonZeroUsize> {
if self(tokens.first()?, source) {
Some(1)
} else {
None
}
fn matches_token(&self, token: &Token, source: &[char]) -> bool {
self(token, source)
}
}

Expand Down
Loading
Loading