feat: allow ExprLinter to work on sentences as well as chunks (#2165)

* feat: allow `ExprLinter` to work on sentences as well as chunks

* feat: senter linter using associated types

* fix: two linters missed conversion

* refactor(core): rename method + field

* fix(core): merge fallout

---------

Co-authored-by: Elijah Potter <me@elijahpotter.dev>
This commit is contained in:
Andrew Dunbar
2025-11-28 16:44:36 +00:00
committed by GitHub
parent 90efaf6430
commit 256cf92196
177 changed files with 631 additions and 33 deletions

View File

@@ -1,6 +1,7 @@
use crate::expr::Expr;
use crate::expr::FirstMatchOf;
use crate::expr::FixedPhrase;
use crate::linting::expr_linter::Chunk;
use crate::{
Token, TokenStringExt,
linting::{ExprLinter, Lint, LintKind, Suggestion},
@@ -26,6 +27,8 @@ impl Default for APart {
}
impl ExprLinter for APart {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -1,3 +1,4 @@
use crate::linting::expr_linter::Chunk;
use crate::{
Token,
expr::{All, AnchorEnd, Expr, FirstMatchOf, LongestMatchOf, ReflexivePronoun, SequenceExpr},
@@ -34,6 +35,8 @@ impl Default for Addicting {
}
impl ExprLinter for Addicting {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -1,3 +1,4 @@
use crate::linting::expr_linter::Chunk;
use crate::{
CharStringExt, Token, TokenStringExt,
expr::{Expr, SequenceExpr},
@@ -21,6 +22,8 @@ impl Default for AdjectiveDoubleDegree {
}
impl ExprLinter for AdjectiveDoubleDegree {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -1,5 +1,6 @@
use crate::Token;
use crate::expr::{DurationExpr, Expr, SequenceExpr};
use crate::linting::expr_linter::Chunk;
use crate::linting::{ExprLinter, Lint, LintKind, Suggestion};
use crate::token_string_ext::TokenStringExt;
@@ -41,6 +42,8 @@ impl Default for AfterLater {
}
impl ExprLinter for AfterLater {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -1,6 +1,7 @@
use crate::Token;
use crate::char_string::CharStringExt;
use crate::expr::{Expr, SequenceExpr};
use crate::linting::expr_linter::Chunk;
use crate::linting::{ExprLinter, Lint, LintKind, Suggestion};
use crate::token_string_ext::TokenStringExt;
@@ -41,6 +42,8 @@ impl Default for AllIntentsAndPurposes {
}
impl ExprLinter for AllIntentsAndPurposes {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -1,4 +1,5 @@
use crate::expr::{Expr, SequenceExpr};
use crate::linting::expr_linter::Chunk;
use crate::linting::{ExprLinter, Lint, LintKind};
use crate::token::Token;
use crate::token_string_ext::TokenStringExt;
@@ -24,6 +25,8 @@ impl Default for AllowTo {
}
impl ExprLinter for AllowTo {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.exp.as_ref()
}

View File

@@ -1,3 +1,4 @@
use crate::linting::expr_linter::Chunk;
use crate::{
Span, Token, TokenStringExt,
expr::{Expr, FixedPhrase, LongestMatchOf, SequenceExpr},
@@ -40,6 +41,8 @@ impl Default for AmInTheMorning {
}
impl ExprLinter for AmInTheMorning {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -5,6 +5,7 @@ use crate::expr::SequenceExpr;
use crate::{Token, TokenStringExt, patterns::WordSet};
use super::{ExprLinter, Lint, LintKind, Suggestion};
use crate::linting::expr_linter::Chunk;
pub struct AmountsFor {
expr: Box<dyn Expr>,
@@ -38,6 +39,8 @@ impl Default for AmountsFor {
}
impl ExprLinter for AmountsFor {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -1,5 +1,6 @@
use crate::Token;
use crate::expr::{Expr, SequenceExpr};
use crate::linting::expr_linter::Chunk;
use crate::linting::{ExprLinter, Lint, LintKind, Suggestion};
pub struct AndIn {
@@ -15,6 +16,8 @@ impl Default for AndIn {
}
impl ExprLinter for AndIn {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
&*self.expr
}

View File

@@ -1,4 +1,5 @@
use crate::expr::{All, Expr, FixedPhrase, SequenceExpr};
use crate::linting::expr_linter::Chunk;
use crate::linting::{ExprLinter, LintKind, Suggestion};
use crate::patterns::WordSet;
use crate::token_string_ext::TokenStringExt;
@@ -35,6 +36,8 @@ impl Default for AndTheLike {
}
impl ExprLinter for AndTheLike {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -1,3 +1,4 @@
use crate::linting::expr_linter::Chunk;
use crate::{
Token, TokenStringExt,
expr::{Expr, FixedPhrase, SequenceExpr},
@@ -23,6 +24,8 @@ impl Default for AnotherThingComing {
}
impl ExprLinter for AnotherThingComing {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -1,3 +1,4 @@
use crate::linting::expr_linter::Chunk;
use crate::{
Token, TokenStringExt,
expr::{Expr, FixedPhrase, SequenceExpr},
@@ -23,6 +24,8 @@ impl Default for AnotherThinkComing {
}
impl ExprLinter for AnotherThinkComing {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -1,5 +1,6 @@
use crate::expr::Expr;
use crate::expr::SequenceExpr;
use crate::linting::expr_linter::Chunk;
use crate::{
Span, Token,
linting::{ExprLinter, Lint, LintKind, Suggestion},
@@ -32,6 +33,8 @@ impl Default for AskNoPreposition {
}
impl ExprLinter for AskNoPreposition {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -3,6 +3,7 @@ use crate::expr::{Expr, SequenceExpr};
use crate::linting::{LintKind, Suggestion};
use super::{ExprLinter, Lint};
use crate::linting::expr_linter::Chunk;
pub struct AvoidCurses {
expr: Box<dyn Expr>,
@@ -17,6 +18,8 @@ impl Default for AvoidCurses {
}
impl ExprLinter for AvoidCurses {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -8,6 +8,7 @@ use crate::{
};
use super::{ExprLinter, Lint, LintKind, Suggestion};
use crate::linting::expr_linter::Chunk;
pub struct BackInTheDay {
expr: Box<dyn Expr>,
@@ -34,6 +35,8 @@ impl Default for BackInTheDay {
}
impl ExprLinter for BackInTheDay {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -1,5 +1,6 @@
use std::sync::Arc;
use crate::linting::expr_linter::Chunk;
use crate::{
Token,
expr::{Expr, ExprMap, SequenceExpr},
@@ -51,6 +52,8 @@ impl Default for BeAllowed {
}
impl ExprLinter for BeAllowed {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -3,6 +3,7 @@ use crate::expr::{Expr, SequenceExpr};
use crate::patterns::WhitespacePattern;
use super::{ExprLinter, Lint, LintKind, Suggestion};
use crate::linting::expr_linter::Chunk;
pub struct BestOfAllTime {
expr: Box<dyn Expr>,
@@ -37,6 +38,8 @@ impl Default for BestOfAllTime {
}
impl ExprLinter for BestOfAllTime {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -2,6 +2,7 @@ use crate::expr::{Expr, WordExprGroup};
use crate::{Token, TokenStringExt};
use super::{ExprLinter, Lint, LintKind};
use crate::linting::expr_linter::Chunk;
pub struct BoringWords {
expr: Box<dyn Expr>,
@@ -24,6 +25,8 @@ impl Default for BoringWords {
}
impl ExprLinter for BoringWords {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -2,6 +2,7 @@ use super::{ExprLinter, Lint, LintKind};
use crate::Token;
use crate::expr::{Expr, SequenceExpr};
use crate::linting::Suggestion;
use crate::linting::expr_linter::Chunk;
pub struct Bought {
expr: Box<dyn Expr>,
@@ -24,6 +25,8 @@ impl Default for Bought {
}
impl ExprLinter for Bought {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -5,6 +5,7 @@ use crate::patterns::{DerivedFrom, WordSet};
use crate::{Token, TokenStringExt};
use super::{ExprLinter, Lint, LintKind, Suggestion};
use crate::linting::expr_linter::Chunk;
pub struct CallThem {
expr: Box<dyn Expr>,
@@ -53,6 +54,8 @@ impl Default for CallThem {
}
impl ExprLinter for CallThem {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -2,6 +2,7 @@ use super::{ExprLinter, Suggestion};
use crate::Lint;
use crate::expr::{Expr, LongestMatchOf, SequenceExpr};
use crate::linting::LintKind;
use crate::linting::expr_linter::Chunk;
use crate::linting::expr_linter::find_the_only_token_matching;
use crate::{CharStringExt, Token};
@@ -31,6 +32,8 @@ impl Default for Cant {
}
impl ExprLinter for Cant {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -1,3 +1,4 @@
use crate::linting::expr_linter::Chunk;
use crate::{
Token,
expr::{Expr, SequenceExpr},
@@ -27,6 +28,8 @@ impl Default for CautionaryTale {
}
impl ExprLinter for CautionaryTale {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -1,5 +1,6 @@
use crate::Token;
use crate::expr::{Expr, SequenceExpr};
use crate::linting::expr_linter::Chunk;
use crate::linting::{ExprLinter, Lint, LintKind, Suggestion};
use crate::patterns::Word;
@@ -33,6 +34,8 @@ impl Default for ChangeTack {
}
impl ExprLinter for ChangeTack {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -4,6 +4,7 @@ use crate::expr::SpaceOrHyphen;
use crate::{Token, TokenStringExt, patterns::WordSet};
use super::{ExprLinter, Lint, LintKind, Suggestion};
use crate::linting::expr_linter::Chunk;
pub struct ChockFull {
expr: Box<dyn Expr>,
@@ -23,6 +24,8 @@ impl Default for ChockFull {
}
impl ExprLinter for ChockFull {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -5,6 +5,7 @@ use crate::expr::SequenceExpr;
use crate::{CharStringExt, TokenStringExt, linting::ExprLinter};
use super::{Lint, LintKind, Suggestion, is_content_word, predicate};
use crate::linting::expr_linter::Chunk;
use crate::{Lrc, Token};
@@ -53,6 +54,8 @@ impl Default for CompoundNounAfterDetAdj {
}
impl ExprLinter for CompoundNounAfterDetAdj {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -6,6 +6,7 @@ use crate::patterns::AnyPattern;
use crate::{CharStringExt, Lrc, TokenStringExt, linting::ExprLinter};
use super::{Lint, LintKind, Suggestion, is_content_word, predicate};
use crate::linting::expr_linter::Chunk;
use crate::Token;
@@ -52,6 +53,8 @@ impl Default for CompoundNounAfterPossessive {
}
impl ExprLinter for CompoundNounAfterPossessive {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -8,6 +8,7 @@ use crate::{CharStringExt, Lrc, TokenStringExt, linting::ExprLinter};
use super::{Lint, LintKind, Suggestion, is_content_word, predicate};
use crate::Token;
use crate::linting::expr_linter::Chunk;
/// Two adjacent words separated by whitespace that if joined would be a valid noun.
pub struct CompoundNounBeforeAuxVerb {
@@ -44,6 +45,8 @@ impl Default for CompoundNounBeforeAuxVerb {
}
impl ExprLinter for CompoundNounBeforeAuxVerb {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -1,3 +1,4 @@
use crate::linting::expr_linter::Chunk;
use crate::{
Token, TokenKind,
expr::{AnchorStart, Expr, SequenceExpr},
@@ -41,6 +42,8 @@ impl Default for CompoundSubjectI {
}
impl ExprLinter for CompoundSubjectI {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -1,6 +1,7 @@
use crate::expr::Expr;
use crate::expr::OwnedExprExt;
use crate::expr::SequenceExpr;
use crate::linting::expr_linter::Chunk;
use crate::{Token, patterns::Word};
use super::{ExprLinter, Lint, LintKind, Suggestion};
@@ -28,6 +29,8 @@ impl Default for Confident {
}
impl ExprLinter for Confident {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -3,6 +3,7 @@ use super::expr_linter::ExprLinter;
use crate::expr::Expr;
use crate::expr::SequenceExpr;
use crate::linting::LintKind;
use crate::linting::expr_linter::Chunk;
use crate::patterns::WordSet;
use crate::{Lint, Lrc, Token, TokenStringExt};
@@ -33,6 +34,8 @@ impl CriteriaPhenomena {
}
impl ExprLinter for CriteriaPhenomena {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -4,6 +4,7 @@ use crate::expr::SequenceExpr;
use crate::{Token, TokenStringExt};
use super::{ExprLinter, Lint, LintKind, Suggestion};
use crate::linting::expr_linter::Chunk;
const EN_DASH: char = '';
const EM_DASH: char = '—';
@@ -29,6 +30,8 @@ impl Default for Dashes {
}
impl ExprLinter for Dashes {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -3,6 +3,7 @@ use crate::expr::SequenceExpr;
use crate::{Token, TokenStringExt};
use super::{ExprLinter, Lint, LintKind, Suggestion};
use crate::linting::expr_linter::Chunk;
pub struct DespiteOf {
expr: Box<dyn Expr>,
@@ -21,6 +22,8 @@ impl Default for DespiteOf {
}
impl ExprLinter for DespiteOf {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -3,6 +3,7 @@ use crate::expr::SequenceExpr;
use crate::{Token, TokenStringExt};
use super::{ExprLinter, Lint, LintKind, Suggestion};
use crate::linting::expr_linter::Chunk;
pub struct DeterminerWithoutNoun {
expr: Box<dyn Expr>,
@@ -22,6 +23,8 @@ impl Default for DeterminerWithoutNoun {
}
impl ExprLinter for DeterminerWithoutNoun {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -1,5 +1,6 @@
use crate::Token;
use crate::expr::{Expr, SequenceExpr};
use crate::linting::expr_linter::Chunk;
use crate::linting::{ExprLinter, Lint, LintKind, Suggestion};
pub struct Didnt {
@@ -20,6 +21,8 @@ impl Default for Didnt {
}
impl ExprLinter for Didnt {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -4,6 +4,7 @@ use crate::expr::WordExprGroup;
use hashbrown::HashMap;
use super::{ExprLinter, Lint, LintKind, Suggestion};
use crate::linting::expr_linter::Chunk;
use crate::{Token, TokenStringExt};
pub struct DotInitialisms {
@@ -35,6 +36,8 @@ impl Default for DotInitialisms {
}
impl ExprLinter for DotInitialisms {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -1,5 +1,6 @@
use std::sync::Arc;
use crate::linting::expr_linter::Chunk;
use crate::{
Token, TokenKind, TokenStringExt,
expr::{Expr, ExprMap, SequenceExpr},
@@ -57,6 +58,8 @@ impl Default for DoubleClick {
}
impl ExprLinter for DoubleClick {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -5,6 +5,7 @@ use crate::{Token, TokenStringExt};
use super::Suggestion;
use super::{ExprLinter, Lint, LintKind};
use crate::linting::expr_linter::Chunk;
pub struct DoubleModal {
expr: Box<dyn Expr>,
@@ -24,6 +25,8 @@ impl Default for DoubleModal {
}
impl ExprLinter for DoubleModal {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -1,6 +1,7 @@
use crate::expr::Expr;
use crate::expr::OwnedExprExt;
use crate::expr::SequenceExpr;
use crate::linting::expr_linter::Chunk;
use crate::{
Token,
linting::{ExprLinter, Lint, LintKind, Suggestion},
@@ -36,6 +37,8 @@ impl Default for ElsePossessive {
}
impl ExprLinter for ElsePossessive {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -3,6 +3,7 @@ use crate::expr::All;
use crate::expr::Expr;
use crate::expr::LongestMatchOf;
use crate::expr::SequenceExpr;
use crate::linting::expr_linter::Chunk;
use crate::{Lrc, Punctuation, Token, TokenKind, TokenStringExt, patterns::Word};
pub struct Everyday {
@@ -147,6 +148,8 @@ impl Default for Everyday {
}
impl ExprLinter for Everyday {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -4,6 +4,7 @@ use super::{ExprLinter, Lint, LintKind};
use crate::Token;
use crate::expr::{Expr, SequenceExpr, SpaceOrHyphen};
use crate::linting::Suggestion;
use crate::linting::expr_linter::Chunk;
use crate::patterns::{ImpliesQuantity, WordSet};
pub struct ExpandMemoryShorthands {
@@ -74,6 +75,8 @@ impl Default for ExpandMemoryShorthands {
}
impl ExprLinter for ExpandMemoryShorthands {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -6,6 +6,7 @@ use std::sync::Arc;
use super::{ExprLinter, Lint, LintKind};
use crate::Token;
use crate::linting::Suggestion;
use crate::linting::expr_linter::Chunk;
use crate::patterns::{ImpliesQuantity, WordSet};
pub struct ExpandTimeShorthands {
@@ -57,6 +58,8 @@ impl Default for ExpandTimeShorthands {
}
impl ExprLinter for ExpandTimeShorthands {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -5,12 +5,41 @@ use crate::{Document, LSend, Token, TokenStringExt};
use super::{Lint, Linter};
pub trait DocumentIterator {
type Unit;
fn iter_units<'a>(document: &'a Document) -> Box<dyn Iterator<Item = &'a [Token]> + 'a>;
}
/// Process text in chunks (clauses between commas)
pub struct Chunk;
/// Process text in full sentences
pub struct Sentence;
impl DocumentIterator for Chunk {
type Unit = Chunk;
fn iter_units<'a>(document: &'a Document) -> Box<dyn Iterator<Item = &'a [Token]> + 'a> {
Box::new(document.iter_chunks())
}
}
impl DocumentIterator for Sentence {
type Unit = Sentence;
fn iter_units<'a>(document: &'a Document) -> Box<dyn Iterator<Item = &'a [Token]> + 'a> {
Box::new(document.iter_sentences())
}
}
/// A trait that searches for tokens that fulfil [`Expr`]s in a [`Document`].
///
/// Makes use of [`TokenStringExt::iter_chunks`] to avoid matching across sentence or clause
/// boundaries.
/// Makes use of [`TokenStringExt::iter_chunks`] by default, or [`TokenStringExt::iter_sentences`] to process either
/// a chunk (clause) or a sentence at a time.
#[blanket(derive(Box))]
pub trait ExprLinter: LSend {
type Unit: DocumentIterator;
/// A simple getter for the expression you want Harper to search for.
fn expr(&self) -> &dyn Expr;
/// If any portions of a [`Document`] match [`Self::expr`], they are passed through [`ExprLinter::match_to_lint`]
@@ -65,16 +94,17 @@ where
}
}
impl<L> Linter for L
impl<L, U> Linter for L
where
L: ExprLinter,
L: ExprLinter<Unit = U>,
U: DocumentIterator,
{
fn lint(&mut self, document: &Document) -> Vec<Lint> {
let mut lints = Vec::new();
let source = document.get_source();
for chunk in document.iter_chunks() {
lints.extend(run_on_chunk(self, chunk, source));
for unit in U::iter_units(document) {
lints.extend(run_on_chunk(self, unit, source));
}
lints
@@ -87,24 +117,25 @@ where
pub fn run_on_chunk<'a>(
linter: &'a impl ExprLinter,
chunk: &'a [Token],
unit: &'a [Token],
source: &'a [char],
) -> impl Iterator<Item = Lint> + 'a {
linter
.expr()
.iter_matches(chunk, source)
.iter_matches(unit, source)
.filter_map(|match_span| {
linter.match_to_lint_with_context(
&chunk[match_span.start..match_span.end],
&unit[match_span.start..match_span.end],
source,
Some((&chunk[..match_span.start], &chunk[match_span.end..])),
Some((&unit[..match_span.start], &unit[match_span.end..])),
)
})
}
#[cfg(test)]
mod tests {
mod tests_context {
use crate::expr::{Expr, FixedPhrase};
use crate::linting::expr_linter::{Chunk, Sentence};
use crate::linting::tests::assert_suggestion_result;
use crate::linting::{ExprLinter, Suggestion};
use crate::token_string_ext::TokenStringExt;
@@ -123,6 +154,8 @@ mod tests {
}
impl ExprLinter for TestSimpleLinter {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
&*self.expr
}
@@ -154,6 +187,8 @@ mod tests {
}
impl ExprLinter for TestContextLinter {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
&*self.expr
}
@@ -205,6 +240,39 @@ mod tests {
}
}
pub struct TestSentenceLinter {
expr: Box<dyn Expr>,
}
impl Default for TestSentenceLinter {
fn default() -> Self {
Self {
expr: Box::new(FixedPhrase::from_phrase("two, two")),
}
}
}
impl ExprLinter for TestSentenceLinter {
type Unit = Sentence;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}
fn match_to_lint(&self, toks: &[Token], _src: &[char]) -> Option<Lint> {
Some(Lint {
span: toks.span()?,
message: "sentence".to_string(),
suggestions: vec![Suggestion::ReplaceWith(vec!['2', '&', '2'])],
..Default::default()
})
}
fn description(&self) -> &str {
"sentence linter"
}
}
#[test]
fn simple_test_123() {
assert_suggestion_result("one two three", TestSimpleLinter::default(), "one 2 three");
@@ -219,4 +287,13 @@ mod tests {
fn context_test_321() {
assert_suggestion_result("three two one", TestContextLinter::default(), "three < one");
}
#[test]
fn sentence_test_123() {
assert_suggestion_result(
"one, two, two, three",
TestSentenceLinter::default(),
"one, 2&2, three",
);
}
}

View File

@@ -1,5 +1,6 @@
use crate::char_string::CharStringExt;
use crate::expr::{Expr, SequenceExpr};
use crate::linting::expr_linter::Chunk;
use crate::linting::{ExprLinter, Lint, LintKind, Suggestion};
use crate::token::Token;
@@ -25,6 +26,8 @@ impl Default for FarBeIt {
}
impl ExprLinter for FarBeIt {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -1,6 +1,7 @@
use crate::Token;
use crate::char_string::CharStringExt;
use crate::expr::{Expr, SequenceExpr};
use crate::linting::expr_linter::Chunk;
use crate::linting::expr_linter::find_the_only_token_matching;
use crate::linting::{ExprLinter, Lint, LintKind, Suggestion};
@@ -42,6 +43,8 @@ impl Default for FeelFell {
}
impl ExprLinter for FeelFell {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -1,6 +1,7 @@
use crate::expr::Expr;
use crate::expr::SequenceExpr;
use crate::expr::TimeUnitExpr;
use crate::linting::expr_linter::Chunk;
use crate::{
Lrc, Token,
linting::{ExprLinter, Lint, Suggestion},
@@ -33,6 +34,8 @@ impl Default for FewUnitsOfTimeAgo {
}
impl ExprLinter for FewUnitsOfTimeAgo {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -1,3 +1,4 @@
use crate::linting::expr_linter::Chunk;
use crate::{
Lrc, Token, TokenStringExt,
expr::{Expr, SequenceExpr},
@@ -30,6 +31,8 @@ impl Default for FillerWords {
}
impl ExprLinter for FillerWords {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -3,6 +3,7 @@ use crate::expr::Expr;
use crate::expr::SequenceExpr;
use crate::patterns::InflectionOfBe;
use super::expr_linter::Chunk;
use super::{ExprLinter, Lint, LintKind, Suggestion};
pub struct FindFine {
@@ -23,6 +24,8 @@ impl Default for FindFine {
}
impl ExprLinter for FindFine {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -1,5 +1,6 @@
use crate::expr::Expr;
use crate::expr::SequenceExpr;
use crate::linting::expr_linter::Chunk;
use crate::{
Token,
linting::{ExprLinter, Lint, LintKind, Suggestion},
@@ -24,6 +25,8 @@ impl Default for FirstAidKit {
}
impl ExprLinter for FirstAidKit {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -7,6 +7,7 @@ use crate::{
};
use super::{ExprLinter, Lint, LintKind, Suggestion};
use crate::linting::expr_linter::Chunk;
pub struct ForNoun {
expr: Box<dyn Expr>,
@@ -25,6 +26,8 @@ impl Default for ForNoun {
}
impl ExprLinter for ForNoun {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -7,6 +7,7 @@ use crate::expr::{Expr, ExprMap, SequenceExpr};
use crate::patterns::WhitespacePattern;
use super::{ExprLinter, Lint, LintKind, Suggestion};
use crate::linting::expr_linter::Chunk;
pub struct FreePredicate {
expr: Box<dyn Expr>,
@@ -47,6 +48,8 @@ impl Default for FreePredicate {
}
impl ExprLinter for FreePredicate {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -1,3 +1,4 @@
use crate::linting::expr_linter::Chunk;
use crate::{
Token,
expr::{Expr, SequenceExpr},
@@ -23,6 +24,8 @@ impl Default for FriendOfMe {
}
impl ExprLinter for FriendOfMe {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -2,6 +2,7 @@ use crate::Token;
use crate::TokenStringExt;
use crate::expr::{Expr, SequenceExpr};
use crate::linting::Suggestion;
use crate::linting::expr_linter::Chunk;
use crate::linting::{ExprLinter, Lint, LintKind};
pub struct GoSoFarAsTo {
@@ -22,6 +23,8 @@ impl Default for GoSoFarAsTo {
}
impl ExprLinter for GoSoFarAsTo {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.exp.as_ref()
}

View File

@@ -2,6 +2,7 @@ use crate::expr::{AnchorStart, Expr, SequenceExpr};
use crate::{Token, TokenKind};
use super::{ExprLinter, Lint, LintKind, Suggestion};
use crate::linting::expr_linter::Chunk;
pub struct HavePronoun {
expr: Box<dyn Expr>,
@@ -25,6 +26,8 @@ impl Default for HavePronoun {
}
impl ExprLinter for HavePronoun {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -1,3 +1,4 @@
use crate::linting::expr_linter::Chunk;
use crate::{
Dialect, Token,
expr::{Expr, FixedPhrase, SequenceExpr},
@@ -31,6 +32,8 @@ impl HaveTakeALook {
}
impl ExprLinter for HaveTakeALook {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -1,6 +1,7 @@
use crate::expr::Expr;
use crate::expr::FirstMatchOf;
use crate::expr::FixedPhrase;
use crate::linting::expr_linter::Chunk;
use crate::linting::{ExprLinter, Lint, LintKind};
use crate::{Token, TokenStringExt};
@@ -24,6 +25,8 @@ impl Default for Hedging {
}
impl ExprLinter for Hedging {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -1,3 +1,4 @@
use crate::linting::expr_linter::Chunk;
use crate::{
Token,
expr::{AnchorStart, Expr, SequenceExpr},
@@ -27,6 +28,8 @@ impl Default for HelloGreeting {
}
impl ExprLinter for HelloGreeting {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -3,6 +3,7 @@ use crate::expr::SequenceExpr;
use crate::{Token, TokenStringExt};
use super::{ExprLinter, Lint, LintKind, Suggestion};
use crate::linting::expr_linter::Chunk;
pub struct Hereby {
expr: Box<dyn Expr>,
@@ -23,6 +24,8 @@ impl Default for Hereby {
}
impl ExprLinter for Hereby {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -2,6 +2,7 @@ use super::super::{ExprLinter, Lint, LintKind};
use crate::expr::Expr;
use crate::expr::SequenceExpr;
use crate::linting::Suggestion;
use crate::linting::expr_linter::Chunk;
use crate::patterns::WordSet;
use crate::{CharString, CharStringExt};
use crate::{Token, char_string::char_string};
@@ -39,6 +40,8 @@ impl ToHop {
}
impl ExprLinter for ToHop {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -2,6 +2,7 @@ use super::super::{ExprLinter, Lint, LintKind};
use crate::expr::Expr;
use crate::expr::SequenceExpr;
use crate::linting::Suggestion;
use crate::linting::expr_linter::Chunk;
use crate::patterns::WordSet;
use crate::{Token, char_string::char_string};
@@ -25,6 +26,8 @@ impl Default for ToHope {
}
impl ExprLinter for ToHope {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -1,3 +1,4 @@
use crate::linting::expr_linter::Chunk;
use crate::{
Token,
expr::SequenceExpr,
@@ -31,6 +32,8 @@ impl Default for HopeYoure {
}
impl ExprLinter for HopeYoure {
type Unit = Chunk;
fn expr(&self) -> &dyn crate::expr::Expr {
self.expr.as_ref()
}

View File

@@ -1,5 +1,6 @@
use harper_brill::UPOS;
use crate::linting::expr_linter::Chunk;
use crate::{
Token, TokenKind, TokenStringExt,
expr::{All, Expr, OwnedExprExt, SequenceExpr},
@@ -49,6 +50,8 @@ impl Default for HowTo {
}
impl ExprLinter for HowTo {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -3,6 +3,7 @@ use crate::expr::SequenceExpr;
use crate::{Token, patterns::NominalPhrase};
use super::{ExprLinter, Lint, LintKind, Suggestion};
use crate::linting::expr_linter::Chunk;
pub struct HyphenateNumberDay {
expr: Box<dyn Expr>,
@@ -36,6 +37,8 @@ impl Default for HyphenateNumberDay {
}
impl ExprLinter for HyphenateNumberDay {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -1,8 +1,10 @@
use crate::linting::expr_linter::Chunk;
use crate::{
Lrc, Token, TokenStringExt,
expr::{AnchorStart, Expr, FirstMatchOf, FixedPhrase, SequenceExpr},
linting::{ExprLinter, Lint, LintKind, Suggestion},
};
pub struct IAmAgreement {
expr: Box<dyn Expr>,
}
@@ -34,6 +36,8 @@ impl Default for IAmAgreement {
}
impl ExprLinter for IAmAgreement {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -1,4 +1,5 @@
use crate::expr::{Expr, SequenceExpr};
use crate::linting::expr_linter::Chunk;
use crate::linting::{ExprLinter, LintKind, Suggestion};
use crate::patterns::{NominalPhrase, WordSet};
use crate::token_string_ext::TokenStringExt;
@@ -33,6 +34,8 @@ impl Default for IfWouldve {
}
impl ExprLinter for IfWouldve {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -6,6 +6,7 @@ use crate::{
};
use super::{ExprLinter, Lint};
use crate::linting::expr_linter::Chunk;
pub struct InOnTheCards {
expr: Box<dyn Expr>,
@@ -41,6 +42,8 @@ impl InOnTheCards {
}
impl ExprLinter for InOnTheCards {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -4,6 +4,7 @@ use itertools::Itertools;
use crate::{Token, patterns::Word};
use super::{ExprLinter, Lint, LintKind, Suggestion};
use crate::linting::expr_linter::Chunk;
/// A struct that can be composed to expand initialisms, respecting the capitalization of each
/// item.
@@ -29,6 +30,8 @@ impl InitialismLinter {
}
impl ExprLinter for InitialismLinter {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -8,7 +8,7 @@ pub fn lint_group() -> LintGroup {
macro_rules! add_initialism_mappings {
($group:expr, { $($name:expr => ($initialism:expr, $expanded:expr)),+ $(,)? }) => {
$(
$group.add_expr_linter(
$group.add_chunk_expr_linter(
$name,
Box::new(InitialismLinter::new($initialism, $expanded)),
);

View File

@@ -1,3 +1,4 @@
use crate::linting::expr_linter::Chunk;
use crate::{
CharStringExt, Token, TokenKind,
expr::{Expr, SequenceExpr},
@@ -25,6 +26,8 @@ impl Default for InterestedIn {
}
impl ExprLinter for InterestedIn {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -1,4 +1,5 @@
use crate::expr::{Expr, SequenceExpr};
use crate::linting::expr_linter::Chunk;
use crate::{
Token, TokenKind,
linting::{ExprLinter, Lint, LintKind, Suggestion},
@@ -51,6 +52,8 @@ impl Default for ItIs {
}
impl ExprLinter for ItIs {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -1,5 +1,6 @@
use crate::Token;
use crate::expr::{Expr, SequenceExpr};
use crate::linting::expr_linter::Chunk;
use crate::linting::{ExprLinter, Lint, LintKind, Suggestion};
use crate::token_string_ext::TokenStringExt;
@@ -43,6 +44,8 @@ impl Default for ItLooksLikeThat {
}
impl ExprLinter for ItLooksLikeThat {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -1,6 +1,7 @@
use crate::expr::Expr;
use crate::expr::OwnedExprExt;
use crate::expr::SequenceExpr;
use crate::linting::expr_linter::Chunk;
use crate::{
Token,
linting::{ExprLinter, Lint, LintKind, Suggestion},
@@ -64,6 +65,8 @@ impl Default for ItWouldBe {
}
impl ExprLinter for ItWouldBe {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -12,6 +12,7 @@ use crate::patterns::UPOSSet;
use crate::patterns::WordSet;
use super::{ExprLinter, Lint, LintKind, Suggestion};
use crate::linting::expr_linter::Chunk;
pub struct ItsPossessive {
expr: Box<dyn Expr>,
@@ -73,6 +74,8 @@ impl Default for ItsPossessive {
}
impl ExprLinter for ItsPossessive {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -3,6 +3,7 @@ use crate::expr::SequenceExpr;
use crate::{Token, patterns::WordSet};
use super::{ExprLinter, Lint, LintKind, Suggestion};
use crate::linting::expr_linter::Chunk;
pub struct LeftRightHand {
expr: Box<dyn Expr>,
@@ -24,6 +25,8 @@ impl Default for LeftRightHand {
}
impl ExprLinter for LeftRightHand {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -3,6 +3,7 @@ use crate::patterns::WordSet;
use crate::{CharStringExt, Token, TokenStringExt};
use super::{ExprLinter, Lint, LintKind, Suggestion};
use crate::linting::expr_linter::Chunk;
pub struct LessWorse {
expr: Box<dyn Expr>,
@@ -22,6 +23,8 @@ impl Default for LessWorse {
}
impl ExprLinter for LessWorse {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -4,6 +4,7 @@ use crate::linting::{LintKind, Suggestion};
use crate::token_string_ext::TokenStringExt;
use super::{ExprLinter, Lint};
use crate::linting::expr_linter::Chunk;
pub struct LetToDo {
expr: Box<dyn Expr>,
@@ -47,6 +48,8 @@ impl Default for LetToDo {
}
impl ExprLinter for LetToDo {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -2,6 +2,7 @@ use crate::expr::Expr;
use crate::expr::SequenceExpr;
use crate::{Token, TokenStringExt};
use crate::linting::expr_linter::Chunk;
use crate::linting::{ExprLinter, Lint, LintKind, Suggestion};
/// See also:
@@ -24,6 +25,8 @@ impl Default for LetUsRedundancy {
}
impl ExprLinter for LetUsRedundancy {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -9,6 +9,7 @@ use crate::{
};
use crate::linting::ExprLinter;
use crate::linting::expr_linter::Chunk;
/// See also:
/// harper-core/src/linting/compound_nouns/implied_ownership_compound_nouns.rs
@@ -57,6 +58,8 @@ impl Default for NoContractionWithVerb {
}
impl ExprLinter for NoContractionWithVerb {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -4,6 +4,7 @@ use crate::expr::SequenceExpr;
use crate::{Token, TokenStringExt};
use super::{ExprLinter, Lint, LintKind, Suggestion};
use crate::linting::expr_linter::Chunk;
pub struct Likewise {
expr: Box<dyn Expr>,
@@ -30,6 +31,8 @@ impl Default for Likewise {
}
}
impl ExprLinter for Likewise {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -182,6 +182,7 @@ use super::would_never_have::WouldNeverHave;
use super::{CurrencyPlacement, HtmlDescriptionLinter, Linter, NoOxfordComma, OxfordComma};
use super::{ExprLinter, Lint};
use crate::linting::dashes::Dashes;
use crate::linting::expr_linter::Chunk;
use crate::linting::open_compounds::OpenCompounds;
use crate::linting::{
MassPlurals, NounVerbConfusion, closed_compounds, initialisms, phrase_corrections,
@@ -308,7 +309,7 @@ pub struct LintGroup {
/// We use a binary map here so the ordering is stable.
linters: BTreeMap<String, Box<dyn Linter>>,
/// We use a binary map here so the ordering is stable.
expr_linters: BTreeMap<String, Box<dyn ExprLinter>>,
chunk_expr_linters: BTreeMap<String, Box<dyn ExprLinter<Unit = Chunk>>>,
/// Since [`ExprLinter`]s operate on a chunk-basis, we can store a
/// mapping of `Chunk -> Lint` and only re-run the expr linters
/// when a chunk changes.
@@ -324,7 +325,7 @@ impl LintGroup {
Self {
config: LintGroupConfig::default(),
linters: BTreeMap::new(),
expr_linters: BTreeMap::new(),
chunk_expr_linters: BTreeMap::new(),
chunk_expr_cache: LruCache::new(NonZero::new(1000).unwrap()),
hasher_builder: RandomState::default(),
}
@@ -332,7 +333,8 @@ impl LintGroup {
/// Check if the group already contains a linter with a given name.
pub fn contains_key(&self, name: impl AsRef<str>) -> bool {
self.linters.contains_key(name.as_ref()) || self.expr_linters.contains_key(name.as_ref())
self.linters.contains_key(name.as_ref())
|| self.chunk_expr_linters.contains_key(name.as_ref())
}
/// Add a [`Linter`] to the group, returning whether the operation was successful.
@@ -347,21 +349,22 @@ impl LintGroup {
}
}
/// Add a [`ExprLinter`] to the group, returning whether the operation was successful.
/// Add a chunk-based [`ExprLinter`] to the group, returning whether the operation was successful.
/// If it returns `false`, it is because a linter with that key already existed in the group.
///
/// This function is not significantly different from [`Self::add`], but allows us to take
/// advantage of some properties of [`ExprLinter`]s for cache optimization.
pub fn add_expr_linter(
/// advantage of some properties of chunk-based [`ExprLinter`]s for cache optimization.
pub fn add_chunk_expr_linter(
&mut self,
name: impl AsRef<str>,
linter: impl ExprLinter + 'static,
// linter: impl ExprLinter + 'static,
linter: impl ExprLinter<Unit = Chunk> + 'static,
) -> bool {
if self.contains_key(&name) {
false
} else {
self.expr_linters
.insert(name.as_ref().to_string(), Box::new(linter));
self.chunk_expr_linters
.insert(name.as_ref().to_string(), Box::new(linter) as _);
true
}
}
@@ -374,14 +377,14 @@ impl LintGroup {
let other_linters = std::mem::take(&mut other.linters);
self.linters.extend(other_linters);
let other_expr_linters = std::mem::take(&mut other.expr_linters);
self.expr_linters.extend(other_expr_linters);
let other_expr_linters = std::mem::take(&mut other.chunk_expr_linters);
self.chunk_expr_linters.extend(other_expr_linters);
}
pub fn iter_keys(&self) -> impl Iterator<Item = &str> {
self.linters
.keys()
.chain(self.expr_linters.keys())
.chain(self.chunk_expr_linters.keys())
.map(|v| v.as_str())
}
@@ -404,7 +407,7 @@ impl LintGroup {
.iter()
.map(|(key, value)| (key.as_str(), value.description()))
.chain(
self.expr_linters
self.chunk_expr_linters
.iter()
.map(|(key, value)| (key.as_str(), ExprLinter::description(value))),
)
@@ -417,7 +420,7 @@ impl LintGroup {
.iter()
.map(|(key, value)| (key.as_str(), value.description_html()))
.chain(
self.expr_linters
self.chunk_expr_linters
.iter()
.map(|(key, value)| (key.as_str(), value.description_html())),
)
@@ -442,12 +445,12 @@ impl LintGroup {
};
}
/// Add an `ExprLinter` to the group, setting it to be enabled by default.
/// Add a chunk-based `ExprLinter` to the group, setting it to be enabled by default.
/// While you _can_ pass an `ExprLinter` to `insert_struct_rule`, using this macro instead
/// will allow it to use more aggressive caching strategies.
macro_rules! insert_expr_rule {
($rule:ident, $default_config:expr) => {
out.add_expr_linter(stringify!($rule), $rule::default());
out.add_chunk_expr_linter(stringify!($rule), $rule::default());
out.config
.set_rule_enabled(stringify!($rule), $default_config);
};
@@ -699,7 +702,7 @@ impl LintGroup {
} else {
let mut pattern_lints = BTreeMap::new();
for (key, linter) in &mut self.expr_linters {
for (key, linter) in &mut self.chunk_expr_linters {
if self.config.is_rule_enabled(key) {
let lints =
run_on_chunk(linter, chunk, document.get_source()).map(|mut l| {

View File

@@ -1,5 +1,6 @@
use hashbrown::HashSet;
use crate::linting::expr_linter::Chunk;
use crate::{
Token,
expr::{Expr, FixedPhrase, SequenceExpr},
@@ -27,6 +28,8 @@ impl Default for LookingForwardTo {
}
impl ExprLinter for LookingForwardTo {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -4,6 +4,7 @@ use crate::expr::FixedPhrase;
use crate::expr::LongestMatchOf;
use crate::expr::SimilarToPhrase;
use crate::linting::Suggestion;
use crate::linting::expr_linter::Chunk;
use crate::{Token, TokenStringExt};
pub struct MapPhraseLinter {
@@ -105,6 +106,8 @@ impl MapPhraseLinter {
}
impl ExprLinter for MapPhraseLinter {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -4,6 +4,7 @@ use crate::expr::Expr;
use crate::expr::FixedPhrase;
use crate::expr::LongestMatchOf;
use crate::linting::Suggestion;
use crate::linting::expr_linter::Chunk;
use crate::{Token, TokenStringExt};
pub struct MapPhraseSetLinter<'a> {
@@ -68,6 +69,8 @@ impl<'a> MapPhraseSetLinter<'a> {
}
impl<'a> ExprLinter for MapPhraseSetLinter<'a> {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -1,5 +1,6 @@
use hashbrown::HashSet;
use crate::linting::expr_linter::Chunk;
use crate::{
CharStringExt, Token, TokenStringExt,
expr::{All, Expr, FirstMatchOf, FixedPhrase, SequenceExpr},
@@ -56,6 +57,8 @@ impl<D> ExprLinter for MassPlurals<D>
where
D: Dictionary,
{
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -9,6 +9,7 @@ use crate::patterns::UPOSSet;
use crate::{Token, TokenStringExt};
use super::{ExprLinter, Lint, LintKind};
use crate::linting::expr_linter::Chunk;
pub struct MissingPreposition {
expr: Box<dyn Expr>,
@@ -41,6 +42,8 @@ impl Default for MissingPreposition {
}
impl ExprLinter for MissingPreposition {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -2,6 +2,7 @@ use std::sync::Arc;
use harper_brill::UPOS;
use crate::linting::expr_linter::Chunk;
use crate::{
Token,
expr::{Expr, ExprMap, SequenceExpr},
@@ -216,6 +217,8 @@ impl Default for MissingTo {
}
impl ExprLinter for MissingTo {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -1,3 +1,4 @@
use crate::linting::expr_linter::Chunk;
use crate::{
Token, TokenStringExt,
expr::{Expr, SequenceExpr},
@@ -29,6 +30,8 @@ impl Default for Misspell {
}
impl ExprLinter for Misspell {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -1,4 +1,5 @@
use crate::CharStringExt;
use crate::linting::expr_linter::Chunk;
use crate::linting::expr_linter::find_the_only_token_matching;
use crate::linting::{ExprLinter, LintKind, Suggestion};
use crate::{
@@ -29,6 +30,8 @@ impl Default for MixedBag {
}
impl ExprLinter for MixedBag {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -5,6 +5,7 @@ use crate::patterns::ModalVerb;
use crate::{Lrc, Token, TokenStringExt};
use super::{ExprLinter, Lint, LintKind, Suggestion};
use crate::linting::expr_linter::Chunk;
pub struct ModalOf {
expr: Box<dyn Expr>,
@@ -71,6 +72,8 @@ impl Default for ModalOf {
}
impl ExprLinter for ModalOf {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -1,5 +1,6 @@
use std::sync::Arc;
use crate::linting::expr_linter::Chunk;
use crate::{
CharStringExt, Token,
expr::{Expr, ExprMap, SequenceExpr},
@@ -68,6 +69,8 @@ impl Default for ModalSeem {
}
impl ExprLinter for ModalSeem {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -1,3 +1,4 @@
use crate::linting::expr_linter::Chunk;
use crate::{
Lrc, Token, TokenKind,
expr::{Expr, FirstMatchOf, SequenceExpr},
@@ -87,6 +88,8 @@ impl Default for Months {
}
impl ExprLinter for Months {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -1,4 +1,5 @@
use crate::expr::{Expr, SequenceExpr};
use crate::linting::expr_linter::Chunk;
use crate::linting::{ExprLinter, Lint, LintKind, Suggestion};
use crate::token::Token;
use crate::token_string_ext::TokenStringExt;
@@ -29,6 +30,8 @@ impl Default for MoreBetter {
}
impl ExprLinter for MoreBetter {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -4,6 +4,7 @@ use crate::expr::SequenceExpr;
use crate::{Token, TokenStringExt, patterns::WordSet};
use super::{ExprLinter, Lint, LintKind, Suggestion};
use crate::linting::expr_linter::Chunk;
pub struct MostNumber {
expr: Box<dyn Expr>,
@@ -35,6 +36,8 @@ impl Default for MostNumber {
}
impl ExprLinter for MostNumber {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -1,4 +1,5 @@
use crate::expr::{Expr, FixedPhrase, SequenceExpr};
use crate::linting::expr_linter::Chunk;
use crate::linting::{ExprLinter, LintKind, Suggestion};
use crate::patterns::Word;
use crate::{Lint, Token};
@@ -23,6 +24,8 @@ impl Default for MostOfTheTimes {
}
impl ExprLinter for MostOfTheTimes {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -3,6 +3,7 @@ use super::expr_linter::ExprLinter;
use crate::expr::Expr;
use crate::expr::SequenceExpr;
use crate::linting::LintKind;
use crate::linting::expr_linter::Chunk;
use crate::patterns::WordSet;
use crate::{CharStringExt, Lint, Lrc, Token, TokenStringExt};
@@ -76,6 +77,8 @@ impl MultipleSequentialPronouns {
}
impl ExprLinter for MultipleSequentialPronouns {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -1,5 +1,6 @@
use crate::expr::Expr;
use crate::expr::SequenceExpr;
use crate::linting::expr_linter::Chunk;
use crate::{
Token,
linting::{ExprLinter, Lint, LintKind, Suggestion},
@@ -28,6 +29,8 @@ impl Default for NailOnTheHead {
}
impl ExprLinter for NailOnTheHead {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -9,6 +9,7 @@ use crate::patterns::DerivedFrom;
use crate::patterns::WordSet;
use super::{ExprLinter, Lint, LintKind, Suggestion};
use crate::linting::expr_linter::Chunk;
pub struct NeedToNoun {
expr: Box<dyn Expr>,
@@ -50,6 +51,8 @@ impl Default for NeedToNoun {
}
impl ExprLinter for NeedToNoun {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -1,3 +1,4 @@
use crate::linting::expr_linter::Chunk;
use crate::{
CharStringExt, Token, TokenStringExt,
expr::{Expr, FirstMatchOf, SequenceExpr},
@@ -35,6 +36,8 @@ impl Default for NoMatchFor {
}
impl ExprLinter for NoMatchFor {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -3,6 +3,7 @@ use crate::expr::SequenceExpr;
use crate::{Token, TokenStringExt};
use super::{ExprLinter, Lint, LintKind, Suggestion};
use crate::linting::expr_linter::Chunk;
pub struct Nobody {
expr: Box<dyn Expr>,
@@ -22,6 +23,8 @@ impl Default for Nobody {
}
impl ExprLinter for Nobody {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -3,6 +3,7 @@ use harper_brill::UPOS;
use crate::CharStringExt;
use crate::expr::Expr;
use crate::expr::SequenceExpr;
use crate::linting::expr_linter::Chunk;
use crate::{
Token,
dict_word_metadata::Person,
@@ -57,6 +58,8 @@ impl Default for NominalWants {
}
impl ExprLinter for NominalWants {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

View File

@@ -1,3 +1,4 @@
use crate::linting::expr_linter::Chunk;
use crate::{
Lrc, Span, Token, TokenStringExt,
expr::{Expr, FirstMatchOf, LongestMatchOf, SequenceExpr},
@@ -66,6 +67,8 @@ impl Default for NounCountability {
}
impl ExprLinter for NounCountability {
type Unit = Chunk;
fn expr(&self) -> &dyn Expr {
self.expr.as_ref()
}

Some files were not shown because too many files have changed in this diff Show More