mirror of
https://github.com/crate-ci/typos.git
synced 2024-11-21 16:41:01 -05:00
Merge pull request #67 from epage/custom
Refactor in prep for custom file types
This commit is contained in:
commit
0767e52f77
3 changed files with 138 additions and 121 deletions
|
@ -87,8 +87,15 @@ fn bench_parse_ident(data: &str, b: &mut test::Bencher) {
|
|||
sample_path.write_str(data).unwrap();
|
||||
|
||||
let parser = typos::tokens::Parser::new();
|
||||
let checks = typos::checks::TyposSettings::new().build_identifier_parser(&parser);
|
||||
b.iter(|| checks.check_file(sample_path.path(), true, typos::report::print_silent));
|
||||
let checks = typos::checks::TyposSettings::new().build_identifier_parser();
|
||||
b.iter(|| {
|
||||
checks.check_file(
|
||||
sample_path.path(),
|
||||
true,
|
||||
&parser,
|
||||
typos::report::print_silent,
|
||||
)
|
||||
});
|
||||
|
||||
temp.close().unwrap();
|
||||
}
|
||||
|
@ -129,8 +136,15 @@ fn bench_parse_word(data: &str, b: &mut test::Bencher) {
|
|||
sample_path.write_str(data).unwrap();
|
||||
|
||||
let parser = typos::tokens::Parser::new();
|
||||
let checks = typos::checks::TyposSettings::new().build_word_parser(&parser);
|
||||
b.iter(|| checks.check_file(sample_path.path(), true, typos::report::print_silent));
|
||||
let checks = typos::checks::TyposSettings::new().build_word_parser();
|
||||
b.iter(|| {
|
||||
checks.check_file(
|
||||
sample_path.path(),
|
||||
true,
|
||||
&parser,
|
||||
typos::report::print_silent,
|
||||
)
|
||||
});
|
||||
|
||||
temp.close().unwrap();
|
||||
}
|
||||
|
@ -172,8 +186,16 @@ fn bench_check_file(data: &str, b: &mut test::Bencher) {
|
|||
|
||||
let corrections = typos_cli::dict::BuiltIn::new();
|
||||
let parser = typos::tokens::Parser::new();
|
||||
let checks = typos::checks::TyposSettings::new().build_checks(&corrections, &parser);
|
||||
b.iter(|| checks.check_file(sample_path.path(), true, typos::report::print_silent));
|
||||
let checks = typos::checks::TyposSettings::new().build_checks();
|
||||
b.iter(|| {
|
||||
checks.check_file(
|
||||
sample_path.path(),
|
||||
true,
|
||||
&parser,
|
||||
&corrections,
|
||||
typos::report::print_silent,
|
||||
)
|
||||
});
|
||||
|
||||
temp.close().unwrap();
|
||||
}
|
||||
|
|
126
src/main.rs
126
src/main.rs
|
@ -265,6 +265,8 @@ trait Checks {
|
|||
fn check_filename(
|
||||
&self,
|
||||
path: &std::path::Path,
|
||||
parser: &typos::tokens::Parser,
|
||||
dictionary: &dyn typos::Dictionary,
|
||||
report: typos::report::Report,
|
||||
) -> Result<bool, typos::Error>;
|
||||
|
||||
|
@ -272,64 +274,78 @@ trait Checks {
|
|||
&self,
|
||||
path: &std::path::Path,
|
||||
explicit: bool,
|
||||
parser: &typos::tokens::Parser,
|
||||
dictionary: &dyn typos::Dictionary,
|
||||
report: typos::report::Report,
|
||||
) -> Result<bool, typos::Error>;
|
||||
}
|
||||
|
||||
impl<'p> Checks for typos::checks::ParseIdentifiers<'p> {
|
||||
impl<'p> Checks for typos::checks::ParseIdentifiers {
|
||||
fn check_filename(
|
||||
&self,
|
||||
path: &std::path::Path,
|
||||
parser: &typos::tokens::Parser,
|
||||
_dictionary: &dyn typos::Dictionary,
|
||||
report: typos::report::Report,
|
||||
) -> Result<bool, typos::Error> {
|
||||
self.check_filename(path, report)
|
||||
self.check_filename(path, parser, report)
|
||||
}
|
||||
|
||||
fn check_file(
|
||||
&self,
|
||||
path: &std::path::Path,
|
||||
explicit: bool,
|
||||
parser: &typos::tokens::Parser,
|
||||
_dictionary: &dyn typos::Dictionary,
|
||||
report: typos::report::Report,
|
||||
) -> Result<bool, typos::Error> {
|
||||
self.check_file(path, explicit, report)
|
||||
self.check_file(path, explicit, parser, report)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'p> Checks for typos::checks::ParseWords<'p> {
|
||||
impl<'p> Checks for typos::checks::ParseWords {
|
||||
fn check_filename(
|
||||
&self,
|
||||
path: &std::path::Path,
|
||||
parser: &typos::tokens::Parser,
|
||||
_dictionary: &dyn typos::Dictionary,
|
||||
report: typos::report::Report,
|
||||
) -> Result<bool, typos::Error> {
|
||||
self.check_filename(path, report)
|
||||
self.check_filename(path, parser, report)
|
||||
}
|
||||
|
||||
fn check_file(
|
||||
&self,
|
||||
path: &std::path::Path,
|
||||
explicit: bool,
|
||||
parser: &typos::tokens::Parser,
|
||||
_dictionary: &dyn typos::Dictionary,
|
||||
report: typos::report::Report,
|
||||
) -> Result<bool, typos::Error> {
|
||||
self.check_file(path, explicit, report)
|
||||
self.check_file(path, explicit, parser, report)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'d, 'p> Checks for typos::checks::Checks<'d, 'p> {
|
||||
impl<'d, 'p> Checks for typos::checks::Checks {
|
||||
fn check_filename(
|
||||
&self,
|
||||
path: &std::path::Path,
|
||||
parser: &typos::tokens::Parser,
|
||||
dictionary: &dyn typos::Dictionary,
|
||||
report: typos::report::Report,
|
||||
) -> Result<bool, typos::Error> {
|
||||
self.check_filename(path, report)
|
||||
self.check_filename(path, parser, dictionary, report)
|
||||
}
|
||||
|
||||
fn check_file(
|
||||
&self,
|
||||
path: &std::path::Path,
|
||||
explicit: bool,
|
||||
parser: &typos::tokens::Parser,
|
||||
dictionary: &dyn typos::Dictionary,
|
||||
report: typos::report::Report,
|
||||
) -> Result<bool, typos::Error> {
|
||||
self.check_file(path, explicit, report)
|
||||
self.check_file(path, explicit, parser, dictionary, report)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -356,20 +372,47 @@ fn init_logging(level: Option<log::Level>) {
|
|||
}
|
||||
}
|
||||
|
||||
fn check_path(
|
||||
mut walk: ignore::Walk,
|
||||
format: Format,
|
||||
checks: &dyn Checks,
|
||||
parser: &typos::tokens::Parser,
|
||||
dictionary: &dyn typos::Dictionary,
|
||||
) -> Result<(bool, bool), anyhow::Error> {
|
||||
let mut typos_found = false;
|
||||
let mut errors_found = false;
|
||||
|
||||
for entry in walk {
|
||||
match check_entry(entry, format, checks, parser, dictionary) {
|
||||
Ok(true) => typos_found = true,
|
||||
Err(err) => {
|
||||
let msg = typos::report::Error::new(err.to_string());
|
||||
format.report()(msg.into());
|
||||
errors_found = true
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
}
|
||||
|
||||
Ok((typos_found, errors_found))
|
||||
}
|
||||
|
||||
fn check_entry(
|
||||
entry: Result<ignore::DirEntry, ignore::Error>,
|
||||
format: Format,
|
||||
checks: &dyn Checks,
|
||||
parser: &typos::tokens::Parser,
|
||||
dictionary: &dyn typos::Dictionary,
|
||||
) -> Result<bool, anyhow::Error> {
|
||||
let mut typos_found = false;
|
||||
|
||||
let entry = entry?;
|
||||
if entry.file_type().map(|t| t.is_file()).unwrap_or(true) {
|
||||
let explicit = entry.depth() == 0;
|
||||
if checks.check_filename(entry.path(), format.report())? {
|
||||
if checks.check_filename(entry.path(), parser, dictionary, format.report())? {
|
||||
typos_found = true;
|
||||
}
|
||||
if checks.check_file(entry.path(), explicit, format.report())? {
|
||||
if checks.check_file(entry.path(), explicit, parser, dictionary, format.report())? {
|
||||
typos_found = true;
|
||||
}
|
||||
}
|
||||
|
@ -408,8 +451,6 @@ fn run() -> Result<i32, anyhow::Error> {
|
|||
config.default.update(&args.overrides);
|
||||
let config = config;
|
||||
|
||||
let dictionary = crate::dict::BuiltIn::new();
|
||||
|
||||
let parser = typos::tokens::ParserBuilder::new()
|
||||
.ignore_hex(config.default.ignore_hex())
|
||||
.leading_digits(config.default.identifier_leading_digits())
|
||||
|
@ -418,6 +459,8 @@ fn run() -> Result<i32, anyhow::Error> {
|
|||
.include_chars(config.default.identifier_include_chars().to_owned())
|
||||
.build();
|
||||
|
||||
let dictionary = crate::dict::BuiltIn::new();
|
||||
|
||||
let mut settings = typos::checks::TyposSettings::new();
|
||||
settings
|
||||
.check_filenames(config.default.check_filename())
|
||||
|
@ -446,43 +489,34 @@ fn run() -> Result<i32, anyhow::Error> {
|
|||
}
|
||||
}
|
||||
} else if args.identifiers {
|
||||
let checks = settings.build_identifier_parser(&parser);
|
||||
for entry in walk.build() {
|
||||
match check_entry(entry, args.format, &checks) {
|
||||
Ok(true) => typos_found = true,
|
||||
Err(err) => {
|
||||
let msg = typos::report::Error::new(err.to_string());
|
||||
args.format.report()(msg.into());
|
||||
errors_found = true
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
let checks = settings.build_identifier_parser();
|
||||
let (cur_typos, cur_errors) =
|
||||
check_path(walk.build(), args.format, &checks, &parser, &dictionary)?;
|
||||
if cur_typos {
|
||||
typos_found = true;
|
||||
}
|
||||
if cur_errors {
|
||||
errors_found = true;
|
||||
}
|
||||
} else if args.words {
|
||||
let checks = settings.build_word_parser(&parser);
|
||||
for entry in walk.build() {
|
||||
match check_entry(entry, args.format, &checks) {
|
||||
Ok(true) => typos_found = true,
|
||||
Err(err) => {
|
||||
let msg = typos::report::Error::new(err.to_string());
|
||||
args.format.report()(msg.into());
|
||||
errors_found = true
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
let checks = settings.build_word_parser();
|
||||
let (cur_typos, cur_errors) =
|
||||
check_path(walk.build(), args.format, &checks, &parser, &dictionary)?;
|
||||
if cur_typos {
|
||||
typos_found = true;
|
||||
}
|
||||
if cur_errors {
|
||||
errors_found = true;
|
||||
}
|
||||
} else {
|
||||
let checks = settings.build_checks(&dictionary, &parser);
|
||||
for entry in walk.build() {
|
||||
match check_entry(entry, args.format, &checks) {
|
||||
Ok(true) => typos_found = true,
|
||||
Err(err) => {
|
||||
let msg = typos::report::Error::new(err.to_string());
|
||||
args.format.report()(msg.into());
|
||||
errors_found = true
|
||||
}
|
||||
_ => (),
|
||||
}
|
||||
let checks = settings.build_checks();
|
||||
let (cur_typos, cur_errors) =
|
||||
check_path(walk.build(), args.format, &checks, &parser, &dictionary)?;
|
||||
if cur_typos {
|
||||
typos_found = true;
|
||||
}
|
||||
if cur_errors {
|
||||
errors_found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,32 +31,24 @@ impl TyposSettings {
|
|||
self
|
||||
}
|
||||
|
||||
pub fn build_checks<'d, 'p>(
|
||||
&self,
|
||||
dictionary: &'d dyn Dictionary,
|
||||
parser: &'p tokens::Parser,
|
||||
) -> Checks<'d, 'p> {
|
||||
pub fn build_checks(&self) -> Checks {
|
||||
Checks {
|
||||
dictionary,
|
||||
parser,
|
||||
check_filenames: self.check_filenames,
|
||||
check_files: self.check_files,
|
||||
binary: self.binary,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn build_identifier_parser<'p>(&self, parser: &'p tokens::Parser) -> ParseIdentifiers<'p> {
|
||||
pub fn build_identifier_parser(&self) -> ParseIdentifiers {
|
||||
ParseIdentifiers {
|
||||
parser,
|
||||
check_filenames: self.check_filenames,
|
||||
check_files: self.check_files,
|
||||
binary: self.binary,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn build_word_parser<'p>(&self, parser: &'p tokens::Parser) -> ParseWords<'p> {
|
||||
pub fn build_word_parser(&self) -> ParseWords {
|
||||
ParseWords {
|
||||
parser,
|
||||
check_filenames: self.check_filenames,
|
||||
check_files: self.check_files,
|
||||
binary: self.binary,
|
||||
|
@ -74,18 +66,18 @@ impl Default for TyposSettings {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ParseIdentifiers<'p> {
|
||||
parser: &'p tokens::Parser,
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ParseIdentifiers {
|
||||
check_filenames: bool,
|
||||
check_files: bool,
|
||||
binary: bool,
|
||||
}
|
||||
|
||||
impl<'p> ParseIdentifiers<'p> {
|
||||
impl ParseIdentifiers {
|
||||
pub fn check_filename(
|
||||
&self,
|
||||
path: &std::path::Path,
|
||||
parser: &tokens::Parser,
|
||||
report: report::Report,
|
||||
) -> Result<bool, crate::Error> {
|
||||
let typos_found = false;
|
||||
|
@ -98,7 +90,7 @@ impl<'p> ParseIdentifiers<'p> {
|
|||
let msg = report::Parse {
|
||||
path,
|
||||
kind: report::ParseKind::Identifier,
|
||||
data: self.parser.parse(part).map(|i| i.token()).collect(),
|
||||
data: parser.parse(part).map(|i| i.token()).collect(),
|
||||
non_exhaustive: (),
|
||||
};
|
||||
report(msg.into());
|
||||
|
@ -111,6 +103,7 @@ impl<'p> ParseIdentifiers<'p> {
|
|||
&self,
|
||||
path: &std::path::Path,
|
||||
explicit: bool,
|
||||
parser: &tokens::Parser,
|
||||
report: report::Report,
|
||||
) -> Result<bool, crate::Error> {
|
||||
let typos_found = false;
|
||||
|
@ -134,7 +127,7 @@ impl<'p> ParseIdentifiers<'p> {
|
|||
let msg = report::Parse {
|
||||
path,
|
||||
kind: report::ParseKind::Identifier,
|
||||
data: self.parser.parse_bytes(line).map(|i| i.token()).collect(),
|
||||
data: parser.parse_bytes(line).map(|i| i.token()).collect(),
|
||||
non_exhaustive: (),
|
||||
};
|
||||
report(msg.into());
|
||||
|
@ -144,29 +137,18 @@ impl<'p> ParseIdentifiers<'p> {
|
|||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for ParseIdentifiers<'_> {
|
||||
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
fmt.debug_struct("Checks")
|
||||
.field("parser", self.parser)
|
||||
.field("check_filenames", &self.check_filenames)
|
||||
.field("check_files", &self.check_files)
|
||||
.field("binary", &self.binary)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct ParseWords<'p> {
|
||||
parser: &'p tokens::Parser,
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct ParseWords {
|
||||
check_filenames: bool,
|
||||
check_files: bool,
|
||||
binary: bool,
|
||||
}
|
||||
|
||||
impl<'p> ParseWords<'p> {
|
||||
impl ParseWords {
|
||||
pub fn check_filename(
|
||||
&self,
|
||||
path: &std::path::Path,
|
||||
parser: &tokens::Parser,
|
||||
report: report::Report,
|
||||
) -> Result<bool, crate::Error> {
|
||||
let typos_found = false;
|
||||
|
@ -179,8 +161,7 @@ impl<'p> ParseWords<'p> {
|
|||
let msg = report::Parse {
|
||||
path,
|
||||
kind: report::ParseKind::Word,
|
||||
data: self
|
||||
.parser
|
||||
data: parser
|
||||
.parse(part)
|
||||
.flat_map(|ident| ident.split().map(|i| i.token()))
|
||||
.collect(),
|
||||
|
@ -196,6 +177,7 @@ impl<'p> ParseWords<'p> {
|
|||
&self,
|
||||
path: &std::path::Path,
|
||||
explicit: bool,
|
||||
parser: &tokens::Parser,
|
||||
report: report::Report,
|
||||
) -> Result<bool, crate::Error> {
|
||||
let typos_found = false;
|
||||
|
@ -219,8 +201,7 @@ impl<'p> ParseWords<'p> {
|
|||
let msg = report::Parse {
|
||||
path,
|
||||
kind: report::ParseKind::Word,
|
||||
data: self
|
||||
.parser
|
||||
data: parser
|
||||
.parse_bytes(line)
|
||||
.flat_map(|ident| ident.split().map(|i| i.token()))
|
||||
.collect(),
|
||||
|
@ -233,30 +214,19 @@ impl<'p> ParseWords<'p> {
|
|||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for ParseWords<'_> {
|
||||
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
fmt.debug_struct("Checks")
|
||||
.field("parser", self.parser)
|
||||
.field("check_filenames", &self.check_filenames)
|
||||
.field("check_files", &self.check_files)
|
||||
.field("binary", &self.binary)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct Checks<'d, 'p> {
|
||||
dictionary: &'d dyn Dictionary,
|
||||
parser: &'p tokens::Parser,
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Checks {
|
||||
check_filenames: bool,
|
||||
check_files: bool,
|
||||
binary: bool,
|
||||
}
|
||||
|
||||
impl<'d, 'p> Checks<'d, 'p> {
|
||||
impl Checks {
|
||||
pub fn check_filename(
|
||||
&self,
|
||||
path: &std::path::Path,
|
||||
parser: &tokens::Parser,
|
||||
dictionary: &dyn Dictionary,
|
||||
report: report::Report,
|
||||
) -> Result<bool, crate::Error> {
|
||||
let mut typos_found = false;
|
||||
|
@ -266,8 +236,8 @@ impl<'d, 'p> Checks<'d, 'p> {
|
|||
}
|
||||
|
||||
for part in path.components().filter_map(|c| c.as_os_str().to_str()) {
|
||||
for ident in self.parser.parse(part) {
|
||||
if let Some(correction) = self.dictionary.correct_ident(ident) {
|
||||
for ident in parser.parse(part) {
|
||||
if let Some(correction) = dictionary.correct_ident(ident) {
|
||||
let msg = report::FilenameCorrection {
|
||||
path,
|
||||
typo: ident.token(),
|
||||
|
@ -278,7 +248,7 @@ impl<'d, 'p> Checks<'d, 'p> {
|
|||
typos_found = true;
|
||||
} else {
|
||||
for word in ident.split() {
|
||||
if let Some(correction) = self.dictionary.correct_word(word) {
|
||||
if let Some(correction) = dictionary.correct_word(word) {
|
||||
let msg = report::FilenameCorrection {
|
||||
path,
|
||||
typo: word.token(),
|
||||
|
@ -300,6 +270,8 @@ impl<'d, 'p> Checks<'d, 'p> {
|
|||
&self,
|
||||
path: &std::path::Path,
|
||||
explicit: bool,
|
||||
parser: &tokens::Parser,
|
||||
dictionary: &dyn Dictionary,
|
||||
report: report::Report,
|
||||
) -> Result<bool, crate::Error> {
|
||||
let mut typos_found = false;
|
||||
|
@ -321,8 +293,8 @@ impl<'d, 'p> Checks<'d, 'p> {
|
|||
|
||||
for (line_idx, line) in buffer.lines().enumerate() {
|
||||
let line_num = line_idx + 1;
|
||||
for ident in self.parser.parse_bytes(line) {
|
||||
if let Some(correction) = self.dictionary.correct_ident(ident) {
|
||||
for ident in parser.parse_bytes(line) {
|
||||
if let Some(correction) = dictionary.correct_ident(ident) {
|
||||
let col_num = ident.offset();
|
||||
let msg = report::Correction {
|
||||
path,
|
||||
|
@ -337,7 +309,7 @@ impl<'d, 'p> Checks<'d, 'p> {
|
|||
report(msg.into());
|
||||
} else {
|
||||
for word in ident.split() {
|
||||
if let Some(correction) = self.dictionary.correct_word(word) {
|
||||
if let Some(correction) = dictionary.correct_word(word) {
|
||||
let col_num = word.offset();
|
||||
let msg = report::Correction {
|
||||
path,
|
||||
|
@ -360,17 +332,6 @@ impl<'d, 'p> Checks<'d, 'p> {
|
|||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Debug for Checks<'_, '_> {
|
||||
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
|
||||
fmt.debug_struct("Checks")
|
||||
.field("parser", self.parser)
|
||||
.field("check_filenames", &self.check_filenames)
|
||||
.field("check_files", &self.check_files)
|
||||
.field("binary", &self.binary)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
fn is_binary(buffer: &[u8]) -> bool {
|
||||
let null_max = std::cmp::min(buffer.len(), 1024);
|
||||
buffer[0..null_max].find_byte(b'\0').is_some()
|
||||
|
|
Loading…
Reference in a new issue