mirror of
https://github.com/crate-ci/typos.git
synced 2024-12-22 23:52:12 -05:00
Merge pull request #217 from epage/refactor
Lay groundwork for new policy engine
This commit is contained in:
commit
60dbf0a254
13 changed files with 305 additions and 458 deletions
176
Cargo.lock
generated
176
Cargo.lock
generated
|
@ -11,15 +11,15 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "adler"
|
||||
version = "0.2.3"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ee2a4ec343196209d6594e19543ae87a39f96d5534d7174822a3ad825dd6ed7e"
|
||||
checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe"
|
||||
|
||||
[[package]]
|
||||
name = "ahash"
|
||||
version = "0.7.0"
|
||||
version = "0.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "efa60d2eadd8b12a996add391db32bd1153eac697ba4869660c0016353611426"
|
||||
checksum = "7f200cbb1e856866d9eade941cf3aa0c5d7dd36f74311c4273b494f4ef036957"
|
||||
dependencies = [
|
||||
"getrandom 0.2.2",
|
||||
"once_cell",
|
||||
|
@ -94,7 +94,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "9d117600f438b1707d4e4ae15d3595657288f8235a0eb593e80ecc98ab34e1bc"
|
||||
dependencies = [
|
||||
"addr2line",
|
||||
"cfg-if 1.0.0",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"miniz_oxide",
|
||||
"object",
|
||||
|
@ -121,9 +121,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "bstr"
|
||||
version = "0.2.14"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "473fc6b38233f9af7baa94fb5852dca389e3d95b8e21c8e3719301462c5d9faf"
|
||||
checksum = "a40b47ad93e1a5404e6c18dec46b628214fee441c70f4ab5d6942142cc268a3d"
|
||||
dependencies = [
|
||||
"lazy_static",
|
||||
"memchr",
|
||||
|
@ -133,9 +133,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "bumpalo"
|
||||
version = "3.6.0"
|
||||
version = "3.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "099e596ef14349721d9016f6b80dd3419ea1bf289ab9b44df8e4dfd3a005d5d9"
|
||||
checksum = "63396b8a4b9de3f4fdfb320ab6080762242f66a8ef174c49d8e19b674db4cdbe"
|
||||
|
||||
[[package]]
|
||||
name = "byteorder"
|
||||
|
@ -152,12 +152,6 @@ dependencies = [
|
|||
"rustc_version",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
|
@ -222,12 +216,6 @@ dependencies = [
|
|||
"unicase",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "const_fn"
|
||||
version = "0.4.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "28b9d6de7f49e22cf97ad17fc4036ece69300032f45f78f30b4a4482cdc3f4a6"
|
||||
|
||||
[[package]]
|
||||
name = "content_inspector"
|
||||
version = "0.2.4"
|
||||
|
@ -279,7 +267,7 @@ version = "0.5.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dca26ee1f8d361640700bde38b2c37d8c22b3ce2d360e1fc1c74ea4b0aa7d775"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"cfg-if",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
|
@ -289,19 +277,18 @@ version = "0.8.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "94af6efb46fef72616855b036a624cf27ba656ffc9be1b9a3c931cfc7749a9a9"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"cfg-if",
|
||||
"crossbeam-epoch",
|
||||
"crossbeam-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crossbeam-epoch"
|
||||
version = "0.9.1"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a1aaa739f95311c2c7887a76863f500026092fb1dce0161dab577e559ef3569d"
|
||||
checksum = "2584f639eb95fea8c798496315b297cf81b9b58b6d30ab066a75455333cf4b12"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"const_fn",
|
||||
"cfg-if",
|
||||
"crossbeam-utils",
|
||||
"lazy_static",
|
||||
"memoffset",
|
||||
|
@ -310,12 +297,12 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "crossbeam-utils"
|
||||
version = "0.8.1"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "02d96d1e189ef58269ebe5b97953da3274d83a93af647c2ddd6f9dab28cedb8d"
|
||||
checksum = "e7e9d99fa91428effe99c5c6d4634cdeba32b8cf784fc428a2a687f61a952c49"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"cfg-if 1.0.0",
|
||||
"cfg-if",
|
||||
"lazy_static",
|
||||
]
|
||||
|
||||
|
@ -360,7 +347,7 @@ dependencies = [
|
|||
"fnv",
|
||||
"ident_case",
|
||||
"proc-macro2 1.0.24",
|
||||
"quote 1.0.8",
|
||||
"quote 1.0.9",
|
||||
"strsim 0.9.3",
|
||||
"syn 1.0.60",
|
||||
]
|
||||
|
@ -372,7 +359,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "d9b5a2f4ac4969822c62224815d069952656cadc7084fdca9751e6d959189b72"
|
||||
dependencies = [
|
||||
"darling_core",
|
||||
"quote 1.0.8",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.60",
|
||||
]
|
||||
|
||||
|
@ -397,7 +384,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "41cb0e6161ad61ed084a36ba71fbba9e3ac5aee3606fb607fe08da6acbcf3d8c"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.24",
|
||||
"quote 1.0.8",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.60",
|
||||
]
|
||||
|
||||
|
@ -409,7 +396,7 @@ checksum = "f1cf41b4580a37cca5ef2ada2cc43cf5d6be3983f4522e83010d67ab6925e84b"
|
|||
dependencies = [
|
||||
"darling",
|
||||
"proc-macro2 1.0.24",
|
||||
"quote 1.0.8",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.60",
|
||||
]
|
||||
|
||||
|
@ -523,7 +510,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "946ee94e3dbf58fdd324f9ce245c7b238d46a66f00e86a020b71996349e46cce"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.24",
|
||||
"quote 1.0.8",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.60",
|
||||
]
|
||||
|
||||
|
@ -542,9 +529,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "env_logger"
|
||||
version = "0.8.2"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f26ecb66b4bdca6c1409b40fb255eefc2bd4f6d135dab3c3124f80ffa2a9661e"
|
||||
checksum = "17392a012ea30ef05a610aa97dfb49496e71c9f676b27879922ea5bdf60d9d3f"
|
||||
dependencies = [
|
||||
"atty",
|
||||
"humantime 2.1.0",
|
||||
|
@ -580,7 +567,7 @@ version = "0.1.16"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8fc3cb4d91f53b50155bdcfd23f6a4c39ae1969c2ae85982b135750cccaf5fce"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi 0.9.0+wasi-snapshot-preview1",
|
||||
]
|
||||
|
@ -591,7 +578,7 @@ version = "0.2.2"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c9495705279e7140bf035dde1f6e750c162df8b625267cd52cc44e0b156732c8"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi 0.10.2+wasi-snapshot-preview1",
|
||||
]
|
||||
|
@ -730,9 +717,9 @@ checksum = "dd25036021b0de88a0aff6b850051563c6516d0bf53f8638938edbb9de732736"
|
|||
|
||||
[[package]]
|
||||
name = "js-sys"
|
||||
version = "0.3.47"
|
||||
version = "0.3.48"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5cfb73131c35423a367daf8cbd24100af0d077668c8c2943f0e7dd775fef0f65"
|
||||
checksum = "dc9f84f9b115ce7843d60706df1422a916680bfdfcbdb0447c5614ff9d7e4d78"
|
||||
dependencies = [
|
||||
"wasm-bindgen",
|
||||
]
|
||||
|
@ -745,22 +732,22 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
|||
|
||||
[[package]]
|
||||
name = "lexical-core"
|
||||
version = "0.7.4"
|
||||
version = "0.7.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "db65c6da02e61f55dae90a0ae427b2a5f6b3e8db09f58d10efab23af92592616"
|
||||
checksum = "21f866863575d0e1d654fbeeabdc927292fdf862873dc3c96c6f753357e13374"
|
||||
dependencies = [
|
||||
"arrayvec",
|
||||
"bitflags",
|
||||
"cfg-if 0.1.10",
|
||||
"cfg-if",
|
||||
"ryu",
|
||||
"static_assertions",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.85"
|
||||
version = "0.2.86"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ccac4b00700875e6a07c6cde370d44d32fa01c5a65cdd2fca6858c479d28bb3"
|
||||
checksum = "b7282d924be3275cec7f6756ff4121987bc6481325397dde6ba3e7802b1a8b1c"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
|
@ -768,7 +755,7 @@ version = "0.4.14"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -788,9 +775,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "miniz_oxide"
|
||||
version = "0.4.3"
|
||||
version = "0.4.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0f2d26ec3309788e423cfbf68ad1800f061638098d76a83681af979dc4eda19d"
|
||||
checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b"
|
||||
dependencies = [
|
||||
"adler",
|
||||
"autocfg",
|
||||
|
@ -820,11 +807,12 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "nom"
|
||||
version = "6.1.0"
|
||||
version = "6.1.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab6f70b46d6325aa300f1c7bb3d470127dfc27806d8ea6bf294ee0ce643ce2b1"
|
||||
checksum = "e7413f999671bd4745a7b624bd370a569fb6bc574b23c83a3c5ed2e453f3d5e2"
|
||||
dependencies = [
|
||||
"bitvec",
|
||||
"funty",
|
||||
"lexical-core",
|
||||
"memchr",
|
||||
"version_check",
|
||||
|
@ -863,9 +851,9 @@ checksum = "a9a7ab5d64814df0fe4a4b5ead45ed6c5f181ee3ff04ba344313a6c80446c5d4"
|
|||
|
||||
[[package]]
|
||||
name = "once_cell"
|
||||
version = "1.5.2"
|
||||
version = "1.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "13bd41f508810a131401606d54ac32a467c97172d74ba7662562ebba5ad07fa0"
|
||||
checksum = "10acf907b94fc1b1a152d08ef97e7759650268cf986bf127f387e602b02c7e5a"
|
||||
|
||||
[[package]]
|
||||
name = "oorandom"
|
||||
|
@ -998,7 +986,7 @@ checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
|
|||
dependencies = [
|
||||
"proc-macro-error-attr",
|
||||
"proc-macro2 1.0.24",
|
||||
"quote 1.0.8",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.60",
|
||||
"version_check",
|
||||
]
|
||||
|
@ -1010,7 +998,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.24",
|
||||
"quote 1.0.8",
|
||||
"quote 1.0.9",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
|
@ -1049,9 +1037,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "quote"
|
||||
version = "1.0.8"
|
||||
version = "1.0.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "991431c3519a3f36861882da93630ce66b52918dcf1b8e2fd66b397fc96f28df"
|
||||
checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.24",
|
||||
]
|
||||
|
@ -1084,7 +1072,7 @@ checksum = "0ef9e7e66b4468674bfcb0c81af8b7fa0bb154fa9f28eb840da5c447baeb8d7e"
|
|||
dependencies = [
|
||||
"libc",
|
||||
"rand_chacha 0.3.0",
|
||||
"rand_core 0.6.1",
|
||||
"rand_core 0.6.2",
|
||||
"rand_hc 0.3.0",
|
||||
]
|
||||
|
||||
|
@ -1105,7 +1093,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "e12735cf05c9e10bf21534da50a147b924d555dc7a547c42e6bb2d5b6017ae0d"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core 0.6.1",
|
||||
"rand_core 0.6.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1119,9 +1107,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.6.1"
|
||||
version = "0.6.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c026d7df8b298d90ccbbc5190bd04d85e159eaf5576caeacf8741da93ccbd2e5"
|
||||
checksum = "34cf66eb183df1c5876e2dcf6b13d57340741e8dc255b48e40a26de954d06ae7"
|
||||
dependencies = [
|
||||
"getrandom 0.2.2",
|
||||
]
|
||||
|
@ -1141,7 +1129,7 @@ version = "0.3.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3190ef7066a446f2e7f42e239d161e905420ccab01eb967c9eb27d21b2322a73"
|
||||
dependencies = [
|
||||
"rand_core 0.6.1",
|
||||
"rand_core 0.6.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -1180,9 +1168,9 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.2.4"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "05ec8ca9416c5ea37062b502703cd7fcb207736bc294f6e0cf367ac6fc234570"
|
||||
checksum = "94341e4e44e24f6b591b59e47a8a027df12e008d73fd5672dbea9cc22f4507d9"
|
||||
dependencies = [
|
||||
"bitflags",
|
||||
]
|
||||
|
@ -1300,15 +1288,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "9391c295d64fc0abb2c556bad848f33cb8296276b1ad2677d1ae1ace4f258f31"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.24",
|
||||
"quote 1.0.8",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.60",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.61"
|
||||
version = "1.0.64"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4fceb2595057b6891a4ee808f70054bd2d12f0e97f1cbb78689b59f676df325a"
|
||||
checksum = "799e97dc9fdae36a5c8b8f2cae9ce2ee9fdce2058c57a93e6099d919fd982f79"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"ryu",
|
||||
|
@ -1359,7 +1347,7 @@ dependencies = [
|
|||
"heck",
|
||||
"proc-macro-error",
|
||||
"proc-macro2 1.0.24",
|
||||
"quote 1.0.8",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.60",
|
||||
]
|
||||
|
||||
|
@ -1381,15 +1369,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "c700597eca8a5a762beb35753ef6b94df201c81cca676604f547495a0d7f0081"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.24",
|
||||
"quote 1.0.8",
|
||||
"quote 1.0.9",
|
||||
"unicode-xid 0.2.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tap"
|
||||
version = "1.0.0"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "36474e732d1affd3a6ed582781b3683df3d0563714c59c39591e8ff707cf078e"
|
||||
checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
|
||||
|
||||
[[package]]
|
||||
name = "tempfile"
|
||||
|
@ -1397,7 +1385,7 @@ version = "3.2.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dac1c663cfc93810f88aed9b8941d48cabf856a1b111c29a40439018d870eb22"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"rand 0.8.3",
|
||||
"redox_syscall",
|
||||
|
@ -1425,21 +1413,21 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "thiserror"
|
||||
version = "1.0.23"
|
||||
version = "1.0.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "76cc616c6abf8c8928e2fdcc0dbfab37175edd8fb49a4641066ad1364fdab146"
|
||||
checksum = "e0f4a65597094d4483ddaed134f409b2cb7c1beccf25201a9f73c719254fa98e"
|
||||
dependencies = [
|
||||
"thiserror-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "thiserror-impl"
|
||||
version = "1.0.23"
|
||||
version = "1.0.24"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9be73a2caec27583d0046ef3796c3794f868a5bc813db689eed00c7631275cd1"
|
||||
checksum = "7765189610d8241a44529806d6fd1f2e0a08734313a35d5b3a556f92b381f3c0"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.24",
|
||||
"quote 1.0.8",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.60",
|
||||
]
|
||||
|
||||
|
@ -1507,7 +1495,7 @@ dependencies = [
|
|||
"derive_setters",
|
||||
"difflib",
|
||||
"encoding",
|
||||
"env_logger 0.8.2",
|
||||
"env_logger 0.8.3",
|
||||
"human-panic",
|
||||
"ignore",
|
||||
"itertools 0.10.0",
|
||||
|
@ -1692,47 +1680,47 @@ checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6"
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen"
|
||||
version = "0.2.70"
|
||||
version = "0.2.71"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "55c0f7123de74f0dab9b7d00fd614e7b19349cd1e2f5252bbe9b1754b59433be"
|
||||
checksum = "7ee1280240b7c461d6a0071313e08f34a60b0365f14260362e5a2b17d1d31aa7"
|
||||
dependencies = [
|
||||
"cfg-if 1.0.0",
|
||||
"cfg-if",
|
||||
"wasm-bindgen-macro",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-backend"
|
||||
version = "0.2.70"
|
||||
version = "0.2.71"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7bc45447f0d4573f3d65720f636bbcc3dd6ce920ed704670118650bcd47764c7"
|
||||
checksum = "5b7d8b6942b8bb3a9b0e73fc79b98095a27de6fa247615e59d096754a3bc2aa8"
|
||||
dependencies = [
|
||||
"bumpalo",
|
||||
"lazy_static",
|
||||
"log",
|
||||
"proc-macro2 1.0.24",
|
||||
"quote 1.0.8",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.60",
|
||||
"wasm-bindgen-shared",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro"
|
||||
version = "0.2.70"
|
||||
version = "0.2.71"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3b8853882eef39593ad4174dd26fc9865a64e84026d223f63bb2c42affcbba2c"
|
||||
checksum = "e5ac38da8ef716661f0f36c0d8320b89028efe10c7c0afde65baffb496ce0d3b"
|
||||
dependencies = [
|
||||
"quote 1.0.8",
|
||||
"quote 1.0.9",
|
||||
"wasm-bindgen-macro-support",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-macro-support"
|
||||
version = "0.2.70"
|
||||
version = "0.2.71"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4133b5e7f2a531fa413b3a1695e925038a05a71cf67e87dafa295cb645a01385"
|
||||
checksum = "cc053ec74d454df287b9374ee8abb36ffd5acb95ba87da3ba5b7d3fe20eb401e"
|
||||
dependencies = [
|
||||
"proc-macro2 1.0.24",
|
||||
"quote 1.0.8",
|
||||
"quote 1.0.9",
|
||||
"syn 1.0.60",
|
||||
"wasm-bindgen-backend",
|
||||
"wasm-bindgen-shared",
|
||||
|
@ -1740,15 +1728,15 @@ dependencies = [
|
|||
|
||||
[[package]]
|
||||
name = "wasm-bindgen-shared"
|
||||
version = "0.2.70"
|
||||
version = "0.2.71"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dd4945e4943ae02d15c13962b38a5b1e81eadd4b71214eee75af64a4d6a4fd64"
|
||||
checksum = "7d6f8ec44822dd71f5f221a5847fb34acd9060535c1211b70a05844c0f6383b1"
|
||||
|
||||
[[package]]
|
||||
name = "web-sys"
|
||||
version = "0.3.47"
|
||||
version = "0.3.48"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c40dc691fc48003eba817c38da7113c15698142da971298003cac3ef175680b3"
|
||||
checksum = "ec600b26223b2948cedfde2a0aa6756dcf1fef616f43d7b3097aaf53a6c4d92b"
|
||||
dependencies = [
|
||||
"js-sys",
|
||||
"wasm-bindgen",
|
||||
|
|
|
@ -2,7 +2,7 @@ mod data;
|
|||
|
||||
use assert_fs::prelude::*;
|
||||
use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion};
|
||||
use typos_cli::checks::FileChecker;
|
||||
use typos_cli::file::FileChecker;
|
||||
|
||||
fn bench_checks(c: &mut Criterion) {
|
||||
let mut group = c.benchmark_group("checks");
|
||||
|
@ -15,11 +15,12 @@ fn bench_checks(c: &mut Criterion) {
|
|||
|
||||
let corrections = typos_cli::dict::BuiltIn::new(Default::default());
|
||||
let parser = typos::tokens::Tokenizer::new();
|
||||
let checks = typos_cli::checks::TyposSettings::new().build_files();
|
||||
let settings = typos_cli::file::CheckSettings::new();
|
||||
b.iter(|| {
|
||||
checks.check_file(
|
||||
typos_cli::file::FoundFiles.check_file(
|
||||
sample_path.path(),
|
||||
true,
|
||||
&settings,
|
||||
&parser,
|
||||
&corrections,
|
||||
&typos_cli::report::PrintSilent,
|
||||
|
@ -35,11 +36,12 @@ fn bench_checks(c: &mut Criterion) {
|
|||
|
||||
let corrections = typos_cli::dict::BuiltIn::new(Default::default());
|
||||
let parser = typos::tokens::Tokenizer::new();
|
||||
let checks = typos_cli::checks::TyposSettings::new().build_identifier_parser();
|
||||
let settings = typos_cli::file::CheckSettings::new();
|
||||
b.iter(|| {
|
||||
checks.check_file(
|
||||
typos_cli::file::Identifiers.check_file(
|
||||
sample_path.path(),
|
||||
true,
|
||||
&settings,
|
||||
&parser,
|
||||
&corrections,
|
||||
&typos_cli::report::PrintSilent,
|
||||
|
@ -55,11 +57,12 @@ fn bench_checks(c: &mut Criterion) {
|
|||
|
||||
let corrections = typos_cli::dict::BuiltIn::new(Default::default());
|
||||
let parser = typos::tokens::Tokenizer::new();
|
||||
let checks = typos_cli::checks::TyposSettings::new().build_word_parser();
|
||||
let settings = typos_cli::file::CheckSettings::new();
|
||||
b.iter(|| {
|
||||
checks.check_file(
|
||||
typos_cli::file::Words.check_file(
|
||||
sample_path.path(),
|
||||
true,
|
||||
&settings,
|
||||
&parser,
|
||||
&corrections,
|
||||
&typos_cli::report::PrintSilent,
|
||||
|
@ -75,11 +78,12 @@ fn bench_checks(c: &mut Criterion) {
|
|||
|
||||
let corrections = typos_cli::dict::BuiltIn::new(Default::default());
|
||||
let parser = typos::tokens::Tokenizer::new();
|
||||
let checks = typos_cli::checks::TyposSettings::new().build_typos();
|
||||
let settings = typos_cli::file::CheckSettings::new();
|
||||
b.iter(|| {
|
||||
checks.check_file(
|
||||
typos_cli::file::Typos.check_file(
|
||||
sample_path.path(),
|
||||
true,
|
||||
&settings,
|
||||
&parser,
|
||||
&corrections,
|
||||
&typos_cli::report::PrintSilent,
|
||||
|
|
100
crates/typos/src/check.rs
Normal file
100
crates/typos/src/check.rs
Normal file
|
@ -0,0 +1,100 @@
|
|||
use crate::tokens;
|
||||
use crate::Dictionary;
|
||||
use std::borrow::Cow;
|
||||
|
||||
pub fn check_str<'b, 's: 'b>(
|
||||
buffer: &'b str,
|
||||
tokenizer: &'s tokens::Tokenizer,
|
||||
dictionary: &'s dyn Dictionary,
|
||||
) -> impl Iterator<Item = Typo<'b>> {
|
||||
tokenizer
|
||||
.parse_str(buffer)
|
||||
.flat_map(move |ident| process_ident(ident, dictionary))
|
||||
}
|
||||
|
||||
pub fn check_bytes<'b, 's: 'b>(
|
||||
buffer: &'b [u8],
|
||||
tokenizer: &'s tokens::Tokenizer,
|
||||
dictionary: &'s dyn Dictionary,
|
||||
) -> impl Iterator<Item = Typo<'b>> {
|
||||
tokenizer
|
||||
.parse_bytes(buffer)
|
||||
.flat_map(move |ident| process_ident(ident, dictionary))
|
||||
}
|
||||
|
||||
fn process_ident<'i, 's: 'i>(
|
||||
ident: tokens::Identifier<'i>,
|
||||
dictionary: &'s dyn Dictionary,
|
||||
) -> impl Iterator<Item = Typo<'i>> {
|
||||
match dictionary.correct_ident(ident) {
|
||||
Some(crate::Status::Valid) => itertools::Either::Left(None.into_iter()),
|
||||
Some(corrections) => {
|
||||
let typo = Typo {
|
||||
byte_offset: ident.offset(),
|
||||
typo: ident.token().into(),
|
||||
corrections,
|
||||
};
|
||||
itertools::Either::Left(Some(typo).into_iter())
|
||||
}
|
||||
None => itertools::Either::Right(
|
||||
ident
|
||||
.split()
|
||||
.filter_map(move |word| process_word(word, dictionary)),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
fn process_word<'w, 's: 'w>(
|
||||
word: tokens::Word<'w>,
|
||||
dictionary: &'s dyn Dictionary,
|
||||
) -> Option<Typo<'w>> {
|
||||
match dictionary.correct_word(word) {
|
||||
Some(crate::Status::Valid) => None,
|
||||
Some(corrections) => {
|
||||
let typo = Typo {
|
||||
byte_offset: word.offset(),
|
||||
typo: word.token().into(),
|
||||
corrections,
|
||||
};
|
||||
Some(typo)
|
||||
}
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
|
||||
/// An invalid term found in the buffer.
|
||||
#[derive(Clone, Debug)]
|
||||
#[non_exhaustive]
|
||||
pub struct Typo<'m> {
|
||||
pub byte_offset: usize,
|
||||
pub typo: Cow<'m, str>,
|
||||
pub corrections: crate::Status<'m>,
|
||||
}
|
||||
|
||||
impl<'m> Typo<'m> {
|
||||
pub fn into_owned(self) -> Typo<'static> {
|
||||
Typo {
|
||||
byte_offset: self.byte_offset,
|
||||
typo: Cow::Owned(self.typo.into_owned()),
|
||||
corrections: self.corrections.into_owned(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn borrow(&self) -> Typo<'_> {
|
||||
Typo {
|
||||
byte_offset: self.byte_offset,
|
||||
typo: Cow::Borrowed(self.typo.as_ref()),
|
||||
corrections: self.corrections.borrow(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'m> Default for Typo<'m> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
byte_offset: 0,
|
||||
typo: "".into(),
|
||||
corrections: crate::Status::Invalid,
|
||||
}
|
||||
}
|
||||
}
|
|
@ -13,21 +13,6 @@ pub trait Dictionary: Send + Sync {
|
|||
fn correct_word<'s, 'w>(&'s self, word: crate::tokens::Word<'w>) -> Option<Status<'s>>;
|
||||
}
|
||||
|
||||
pub(crate) struct NullDictionary;
|
||||
|
||||
impl Dictionary for NullDictionary {
|
||||
fn correct_ident<'s, 'w>(
|
||||
&'s self,
|
||||
_ident: crate::tokens::Identifier<'w>,
|
||||
) -> Option<Status<'s>> {
|
||||
None
|
||||
}
|
||||
|
||||
fn correct_word<'s, 'w>(&'s self, _word: crate::tokens::Word<'w>) -> Option<Status<'s>> {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Validity of a term in a Dictionary.
|
||||
#[derive(Clone, PartialEq, Eq, Debug, serde::Serialize)]
|
||||
#[serde(rename_all = "snake_case")]
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
mod check;
|
||||
mod dict;
|
||||
mod parser;
|
||||
|
||||
pub mod tokens;
|
||||
|
||||
pub use check::*;
|
||||
pub use dict::*;
|
||||
pub use parser::*;
|
||||
|
|
|
@ -1,147 +0,0 @@
|
|||
use crate::tokens;
|
||||
use crate::Dictionary;
|
||||
use std::borrow::Cow;
|
||||
|
||||
/// Extract typos from the buffer.
|
||||
#[derive(Clone)]
|
||||
pub struct ParserBuilder<'p, 'd> {
|
||||
tokenizer: Option<&'p tokens::Tokenizer>,
|
||||
dictionary: &'d dyn Dictionary,
|
||||
}
|
||||
|
||||
impl<'p> ParserBuilder<'p, 'static> {
|
||||
pub fn new() -> Self {
|
||||
Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'p, 'd> ParserBuilder<'p, 'd> {
|
||||
/// Set the Tokenizer used when parsing.
|
||||
pub fn tokenizer(mut self, tokenizer: &'p tokens::Tokenizer) -> Self {
|
||||
self.tokenizer = Some(tokenizer);
|
||||
self
|
||||
}
|
||||
|
||||
/// Set the dictionary used when parsing.
|
||||
pub fn dictionary<'d1>(self, dictionary: &'d1 dyn Dictionary) -> ParserBuilder<'p, 'd1> {
|
||||
ParserBuilder {
|
||||
tokenizer: self.tokenizer,
|
||||
dictionary,
|
||||
}
|
||||
}
|
||||
|
||||
/// Extract typos from the buffer.
|
||||
pub fn build(&self) -> TyposParser<'p, 'd> {
|
||||
TyposParser {
|
||||
tokenizer: self.tokenizer.unwrap_or(&DEFAULT_TOKENIZER),
|
||||
dictionary: self.dictionary,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'p> Default for ParserBuilder<'p, 'static> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
tokenizer: None,
|
||||
dictionary: &crate::NullDictionary,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static DEFAULT_TOKENIZER: once_cell::sync::Lazy<tokens::Tokenizer> =
|
||||
once_cell::sync::Lazy::new(tokens::Tokenizer::new);
|
||||
|
||||
/// Extract typos from the buffer.
|
||||
#[derive(Clone)]
|
||||
pub struct TyposParser<'p, 'd> {
|
||||
tokenizer: &'p tokens::Tokenizer,
|
||||
dictionary: &'d dyn Dictionary,
|
||||
}
|
||||
|
||||
impl<'p, 'd> TyposParser<'p, 'd> {
|
||||
pub fn parse_str<'b, 's: 'b>(&'s self, buffer: &'b str) -> impl Iterator<Item = Typo<'b>> {
|
||||
self.tokenizer
|
||||
.parse_str(buffer)
|
||||
.flat_map(move |ident| self.process_ident(ident))
|
||||
}
|
||||
|
||||
pub fn parse_bytes<'b, 's: 'b>(&'s self, buffer: &'b [u8]) -> impl Iterator<Item = Typo<'b>> {
|
||||
self.tokenizer
|
||||
.parse_bytes(buffer)
|
||||
.flat_map(move |ident| self.process_ident(ident))
|
||||
}
|
||||
|
||||
fn process_ident<'i, 's: 'i>(
|
||||
&'s self,
|
||||
ident: tokens::Identifier<'i>,
|
||||
) -> impl Iterator<Item = Typo<'i>> {
|
||||
match self.dictionary.correct_ident(ident) {
|
||||
Some(crate::Status::Valid) => itertools::Either::Left(None.into_iter()),
|
||||
Some(corrections) => {
|
||||
let typo = Typo {
|
||||
byte_offset: ident.offset(),
|
||||
typo: ident.token().into(),
|
||||
corrections,
|
||||
};
|
||||
itertools::Either::Left(Some(typo).into_iter())
|
||||
}
|
||||
None => itertools::Either::Right(
|
||||
ident
|
||||
.split()
|
||||
.filter_map(move |word| self.process_word(word)),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
fn process_word<'w, 's: 'w>(&'s self, word: tokens::Word<'w>) -> Option<Typo<'w>> {
|
||||
match self.dictionary.correct_word(word) {
|
||||
Some(crate::Status::Valid) => None,
|
||||
Some(corrections) => {
|
||||
let typo = Typo {
|
||||
byte_offset: word.offset(),
|
||||
typo: word.token().into(),
|
||||
corrections,
|
||||
};
|
||||
Some(typo)
|
||||
}
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// An invalid term found in the buffer.
|
||||
#[derive(Clone, Debug)]
|
||||
#[non_exhaustive]
|
||||
pub struct Typo<'m> {
|
||||
pub byte_offset: usize,
|
||||
pub typo: Cow<'m, str>,
|
||||
pub corrections: crate::Status<'m>,
|
||||
}
|
||||
|
||||
impl<'m> Typo<'m> {
|
||||
pub fn into_owned(self) -> Typo<'static> {
|
||||
Typo {
|
||||
byte_offset: self.byte_offset,
|
||||
typo: Cow::Owned(self.typo.into_owned()),
|
||||
corrections: self.corrections.into_owned(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn borrow(&self) -> Typo<'_> {
|
||||
Typo {
|
||||
byte_offset: self.byte_offset,
|
||||
typo: Cow::Borrowed(self.typo.as_ref()),
|
||||
corrections: self.corrections.borrow(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'m> Default for Typo<'m> {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
byte_offset: 0,
|
||||
typo: "".into(),
|
||||
corrections: crate::Status::Invalid,
|
||||
}
|
||||
}
|
||||
}
|
|
@ -181,7 +181,7 @@ impl<'t> Identifier<'t> {
|
|||
|
||||
/// Split into individual Words.
|
||||
pub fn split(&self) -> impl Iterator<Item = Word<'t>> {
|
||||
split_ident(self.token, self.offset)
|
||||
SplitIdent::new(self.token, self.offset)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -195,7 +195,7 @@ pub struct Word<'t> {
|
|||
|
||||
impl<'t> Word<'t> {
|
||||
pub fn new(token: &'t str, offset: usize) -> Result<Self, std::io::Error> {
|
||||
let mut itr = split_ident(token, 0);
|
||||
let mut itr = SplitIdent::new(token, 0);
|
||||
let mut item = itr.next().ok_or_else(|| {
|
||||
std::io::Error::new(
|
||||
std::io::ErrorKind::InvalidInput,
|
||||
|
@ -239,10 +239,6 @@ impl<'t> Word<'t> {
|
|||
}
|
||||
}
|
||||
|
||||
fn split_ident(ident: &str, offset: usize) -> impl Iterator<Item = Word<'_>> {
|
||||
SplitIdent::new(ident, offset)
|
||||
}
|
||||
|
||||
struct SplitIdent<'s> {
|
||||
ident: &'s str,
|
||||
offset: usize,
|
||||
|
|
|
@ -14,13 +14,13 @@ Configuration is read from the following (in precedence order)
|
|||
|
||||
| Field | Argument | Format | Description |
|
||||
|------------------------|-------------------|--------|-------------|
|
||||
| files.binary | --binary | bool | Check binary files as text |
|
||||
| files.ignore-hidden | --hidden | bool | Skip hidden files and directories. |
|
||||
| files.ignore-files | --ignore | bool | Respect ignore files. |
|
||||
| files.ignore-dot | --ignore-dot | bool | Respect .ignore files. |
|
||||
| files.ignore-vcs | --ignore-vcs | bool | Respect ignore files in vcs directories. |
|
||||
| files.ignore-global | --ignore-global | bool | Respect global ignore files. |
|
||||
| files.ignore-parent | --ignore-parent | bool | Respect ignore files in parent directories. |
|
||||
| default.binary | --binary | bool | Check binary files as text |
|
||||
| default.check-filename | \- | bool | Verifying spelling in file names. |
|
||||
| default.check-file | \- | bool | Verifying spelling in files. |
|
||||
| default.ignore-hex | \- | bool | Do not check identifiers that appear to be hexadecimal values. |
|
||||
|
|
30
src/args.rs
30
src/args.rs
|
@ -104,6 +104,12 @@ pub(crate) struct Args {
|
|||
#[derive(Debug, StructOpt)]
|
||||
#[structopt(rename_all = "kebab-case")]
|
||||
pub(crate) struct FileArgs {
|
||||
#[structopt(long, overrides_with("no-binary"))]
|
||||
/// Search binary files.
|
||||
binary: bool,
|
||||
#[structopt(long, overrides_with("binary"), hidden(true))]
|
||||
no_binary: bool,
|
||||
|
||||
#[structopt(long, overrides_with("check-filenames"))]
|
||||
/// Skip verifying spelling in file names.
|
||||
no_check_filenames: bool,
|
||||
|
@ -130,6 +136,15 @@ pub(crate) struct FileArgs {
|
|||
}
|
||||
|
||||
impl config::FileSource for FileArgs {
|
||||
fn binary(&self) -> Option<bool> {
|
||||
match (self.binary, self.no_binary) {
|
||||
(true, false) => Some(true),
|
||||
(false, true) => Some(false),
|
||||
(false, false) => None,
|
||||
(_, _) => unreachable!("StructOpt should make this impossible"),
|
||||
}
|
||||
}
|
||||
|
||||
fn check_filename(&self) -> Option<bool> {
|
||||
match (self.check_filenames, self.no_check_filenames) {
|
||||
(true, false) => Some(true),
|
||||
|
@ -178,12 +193,6 @@ impl config::ConfigSource for ConfigArgs {
|
|||
#[derive(Debug, StructOpt)]
|
||||
#[structopt(rename_all = "kebab-case")]
|
||||
pub(crate) struct WalkArgs {
|
||||
#[structopt(long, overrides_with("no-binary"))]
|
||||
/// Search binary files.
|
||||
binary: bool,
|
||||
#[structopt(long, overrides_with("binary"), hidden(true))]
|
||||
no_binary: bool,
|
||||
|
||||
#[structopt(long, overrides_with("no-hidden"))]
|
||||
/// Search hidden files and directories.
|
||||
hidden: bool,
|
||||
|
@ -222,15 +231,6 @@ pub(crate) struct WalkArgs {
|
|||
}
|
||||
|
||||
impl config::WalkSource for WalkArgs {
|
||||
fn binary(&self) -> Option<bool> {
|
||||
match (self.binary, self.no_binary) {
|
||||
(true, false) => Some(true),
|
||||
(false, true) => Some(false),
|
||||
(false, false) => None,
|
||||
(_, _) => unreachable!("StructOpt should make this impossible"),
|
||||
}
|
||||
}
|
||||
|
||||
fn ignore_hidden(&self) -> Option<bool> {
|
||||
match (self.hidden, self.no_hidden) {
|
||||
(true, false) => Some(false),
|
||||
|
|
|
@ -12,11 +12,6 @@ pub trait ConfigSource {
|
|||
}
|
||||
|
||||
pub trait WalkSource {
|
||||
/// Search binary files.
|
||||
fn binary(&self) -> Option<bool> {
|
||||
None
|
||||
}
|
||||
|
||||
/// Skip hidden files and directories.
|
||||
fn ignore_hidden(&self) -> Option<bool> {
|
||||
None
|
||||
|
@ -49,6 +44,11 @@ pub trait WalkSource {
|
|||
}
|
||||
|
||||
pub trait FileSource {
|
||||
/// Check binary files.
|
||||
fn binary(&self) -> Option<bool> {
|
||||
None
|
||||
}
|
||||
|
||||
/// Verifying spelling in file names.
|
||||
fn check_filename(&self) -> Option<bool> {
|
||||
None
|
||||
|
@ -157,7 +157,6 @@ impl ConfigSource for Config {
|
|||
#[serde(deny_unknown_fields, default)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
pub struct Walk {
|
||||
pub binary: Option<bool>,
|
||||
pub ignore_hidden: Option<bool>,
|
||||
pub ignore_files: Option<bool>,
|
||||
pub ignore_dot: Option<bool>,
|
||||
|
@ -170,7 +169,6 @@ impl Walk {
|
|||
pub fn from_defaults() -> Self {
|
||||
let empty = Self::default();
|
||||
Self {
|
||||
binary: Some(empty.binary()),
|
||||
ignore_hidden: Some(empty.ignore_hidden()),
|
||||
ignore_files: Some(true),
|
||||
ignore_dot: Some(empty.ignore_dot()),
|
||||
|
@ -181,9 +179,6 @@ impl Walk {
|
|||
}
|
||||
|
||||
pub fn update(&mut self, source: &dyn WalkSource) {
|
||||
if let Some(source) = source.binary() {
|
||||
self.binary = Some(source);
|
||||
}
|
||||
if let Some(source) = source.ignore_hidden() {
|
||||
self.ignore_hidden = Some(source);
|
||||
}
|
||||
|
@ -209,10 +204,6 @@ impl Walk {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn binary(&self) -> bool {
|
||||
self.binary.unwrap_or(false)
|
||||
}
|
||||
|
||||
pub fn ignore_hidden(&self) -> bool {
|
||||
self.ignore_hidden.unwrap_or(true)
|
||||
}
|
||||
|
@ -238,10 +229,6 @@ impl Walk {
|
|||
}
|
||||
|
||||
impl WalkSource for Walk {
|
||||
fn binary(&self) -> Option<bool> {
|
||||
self.binary
|
||||
}
|
||||
|
||||
fn ignore_hidden(&self) -> Option<bool> {
|
||||
self.ignore_hidden
|
||||
}
|
||||
|
@ -271,6 +258,7 @@ impl WalkSource for Walk {
|
|||
#[serde(deny_unknown_fields, default)]
|
||||
#[serde(rename_all = "kebab-case")]
|
||||
pub struct FileConfig {
|
||||
pub binary: Option<bool>,
|
||||
pub check_filename: Option<bool>,
|
||||
pub check_file: Option<bool>,
|
||||
pub ignore_hex: Option<bool>,
|
||||
|
@ -287,6 +275,7 @@ impl FileConfig {
|
|||
pub fn from_defaults() -> Self {
|
||||
let empty = Self::default();
|
||||
FileConfig {
|
||||
binary: Some(empty.binary()),
|
||||
check_filename: Some(empty.check_filename()),
|
||||
check_file: Some(empty.check_file()),
|
||||
ignore_hex: Some(empty.ignore_hex()),
|
||||
|
@ -301,6 +290,9 @@ impl FileConfig {
|
|||
}
|
||||
|
||||
pub fn update(&mut self, source: &dyn FileSource) {
|
||||
if let Some(source) = source.binary() {
|
||||
self.binary = Some(source);
|
||||
}
|
||||
if let Some(source) = source.check_filename() {
|
||||
self.check_filename = Some(source);
|
||||
}
|
||||
|
@ -337,6 +329,10 @@ impl FileConfig {
|
|||
);
|
||||
}
|
||||
|
||||
pub fn binary(&self) -> bool {
|
||||
self.binary.unwrap_or(false)
|
||||
}
|
||||
|
||||
pub fn check_filename(&self) -> bool {
|
||||
self.check_filename.unwrap_or(true)
|
||||
}
|
||||
|
@ -387,6 +383,10 @@ impl FileConfig {
|
|||
}
|
||||
|
||||
impl FileSource for FileConfig {
|
||||
fn binary(&self) -> Option<bool> {
|
||||
self.binary
|
||||
}
|
||||
|
||||
fn check_filename(&self) -> Option<bool> {
|
||||
self.check_filename
|
||||
}
|
||||
|
|
|
@ -12,20 +12,21 @@ pub trait FileChecker: Send + Sync {
|
|||
&self,
|
||||
path: &std::path::Path,
|
||||
explicit: bool,
|
||||
parser: &tokens::Tokenizer,
|
||||
settings: &CheckSettings,
|
||||
tokenizer: &tokens::Tokenizer,
|
||||
dictionary: &dyn Dictionary,
|
||||
reporter: &dyn report::Report,
|
||||
) -> Result<(), std::io::Error>;
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||
pub struct TyposSettings {
|
||||
pub struct CheckSettings {
|
||||
check_filenames: bool,
|
||||
check_files: bool,
|
||||
binary: bool,
|
||||
}
|
||||
|
||||
impl TyposSettings {
|
||||
impl CheckSettings {
|
||||
pub fn new() -> Self {
|
||||
Default::default()
|
||||
}
|
||||
|
@ -44,55 +45,9 @@ impl TyposSettings {
|
|||
self.binary = yes;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn build_typos(&self) -> Typos {
|
||||
Typos {
|
||||
check_filenames: self.check_filenames,
|
||||
check_files: self.check_files,
|
||||
binary: self.binary,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn build_fix_typos(&self) -> FixTypos {
|
||||
FixTypos {
|
||||
check_filenames: self.check_filenames,
|
||||
check_files: self.check_files,
|
||||
binary: self.binary,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn build_diff_typos(&self) -> DiffTypos {
|
||||
DiffTypos {
|
||||
check_filenames: self.check_filenames,
|
||||
check_files: self.check_files,
|
||||
binary: self.binary,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn build_identifier_parser(&self) -> Identifiers {
|
||||
Identifiers {
|
||||
check_filenames: self.check_filenames,
|
||||
check_files: self.check_files,
|
||||
binary: self.binary,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn build_word_parser(&self) -> Words {
|
||||
Words {
|
||||
check_filenames: self.check_filenames,
|
||||
check_files: self.check_files,
|
||||
binary: self.binary,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn build_files(&self) -> FoundFiles {
|
||||
FoundFiles {
|
||||
binary: self.binary,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for TyposSettings {
|
||||
impl Default for CheckSettings {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
check_filenames: true,
|
||||
|
@ -102,30 +57,22 @@ impl Default for TyposSettings {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Typos {
|
||||
check_filenames: bool,
|
||||
check_files: bool,
|
||||
binary: bool,
|
||||
}
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct Typos;
|
||||
|
||||
impl FileChecker for Typos {
|
||||
fn check_file(
|
||||
&self,
|
||||
path: &std::path::Path,
|
||||
explicit: bool,
|
||||
settings: &CheckSettings,
|
||||
tokenizer: &tokens::Tokenizer,
|
||||
dictionary: &dyn Dictionary,
|
||||
reporter: &dyn report::Report,
|
||||
) -> Result<(), std::io::Error> {
|
||||
let parser = typos::ParserBuilder::new()
|
||||
.tokenizer(tokenizer)
|
||||
.dictionary(dictionary)
|
||||
.build();
|
||||
|
||||
if self.check_filenames {
|
||||
if settings.check_filenames {
|
||||
if let Some(file_name) = path.file_name().and_then(|s| s.to_str()) {
|
||||
for typo in parser.parse_str(file_name) {
|
||||
for typo in typos::check_str(file_name, tokenizer, dictionary) {
|
||||
let msg = report::Typo {
|
||||
context: Some(report::PathContext { path }.into()),
|
||||
buffer: std::borrow::Cow::Borrowed(file_name.as_bytes()),
|
||||
|
@ -138,14 +85,14 @@ impl FileChecker for Typos {
|
|||
}
|
||||
}
|
||||
|
||||
if self.check_files {
|
||||
if settings.check_files {
|
||||
let (buffer, content_type) = read_file(path, reporter)?;
|
||||
if !explicit && !self.binary && content_type.is_binary() {
|
||||
if !explicit && !settings.binary && content_type.is_binary() {
|
||||
let msg = report::BinaryFile { path };
|
||||
reporter.report(msg.into())?;
|
||||
} else {
|
||||
let mut accum_line_num = AccumulateLineNum::new();
|
||||
for typo in parser.parse_bytes(&buffer) {
|
||||
for typo in typos::check_bytes(&buffer, tokenizer, dictionary) {
|
||||
let line_num = accum_line_num.line_num(&buffer, typo.byte_offset);
|
||||
let (line, line_offset) = extract_line(&buffer, typo.byte_offset);
|
||||
let msg = report::Typo {
|
||||
|
@ -164,36 +111,28 @@ impl FileChecker for Typos {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct FixTypos {
|
||||
check_filenames: bool,
|
||||
check_files: bool,
|
||||
binary: bool,
|
||||
}
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct FixTypos;
|
||||
|
||||
impl FileChecker for FixTypos {
|
||||
fn check_file(
|
||||
&self,
|
||||
path: &std::path::Path,
|
||||
explicit: bool,
|
||||
settings: &CheckSettings,
|
||||
tokenizer: &tokens::Tokenizer,
|
||||
dictionary: &dyn Dictionary,
|
||||
reporter: &dyn report::Report,
|
||||
) -> Result<(), std::io::Error> {
|
||||
let parser = typos::ParserBuilder::new()
|
||||
.tokenizer(tokenizer)
|
||||
.dictionary(dictionary)
|
||||
.build();
|
||||
|
||||
if self.check_files {
|
||||
if settings.check_files {
|
||||
let (buffer, content_type) = read_file(path, reporter)?;
|
||||
if !explicit && !self.binary && content_type.is_binary() {
|
||||
if !explicit && !settings.binary && content_type.is_binary() {
|
||||
let msg = report::BinaryFile { path };
|
||||
reporter.report(msg.into())?;
|
||||
} else {
|
||||
let mut fixes = Vec::new();
|
||||
let mut accum_line_num = AccumulateLineNum::new();
|
||||
for typo in parser.parse_bytes(&buffer) {
|
||||
for typo in typos::check_bytes(&buffer, tokenizer, dictionary) {
|
||||
if is_fixable(&typo) {
|
||||
fixes.push(typo.into_owned());
|
||||
} else {
|
||||
|
@ -217,10 +156,10 @@ impl FileChecker for FixTypos {
|
|||
}
|
||||
|
||||
// Ensure the above write can happen before renaming the file.
|
||||
if self.check_filenames {
|
||||
if settings.check_filenames {
|
||||
if let Some(file_name) = path.file_name().and_then(|s| s.to_str()) {
|
||||
let mut fixes = Vec::new();
|
||||
for typo in parser.parse_str(file_name) {
|
||||
for typo in typos::check_str(file_name, tokenizer, dictionary) {
|
||||
if is_fixable(&typo) {
|
||||
fixes.push(typo.into_owned());
|
||||
} else {
|
||||
|
@ -249,38 +188,30 @@ impl FileChecker for FixTypos {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct DiffTypos {
|
||||
check_filenames: bool,
|
||||
check_files: bool,
|
||||
binary: bool,
|
||||
}
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct DiffTypos;
|
||||
|
||||
impl FileChecker for DiffTypos {
|
||||
fn check_file(
|
||||
&self,
|
||||
path: &std::path::Path,
|
||||
explicit: bool,
|
||||
settings: &CheckSettings,
|
||||
tokenizer: &tokens::Tokenizer,
|
||||
dictionary: &dyn Dictionary,
|
||||
reporter: &dyn report::Report,
|
||||
) -> Result<(), std::io::Error> {
|
||||
let parser = typos::ParserBuilder::new()
|
||||
.tokenizer(tokenizer)
|
||||
.dictionary(dictionary)
|
||||
.build();
|
||||
|
||||
let mut content = Vec::new();
|
||||
let mut new_content = Vec::new();
|
||||
if self.check_files {
|
||||
if settings.check_files {
|
||||
let (buffer, content_type) = read_file(path, reporter)?;
|
||||
if !explicit && !self.binary && content_type.is_binary() {
|
||||
if !explicit && !settings.binary && content_type.is_binary() {
|
||||
let msg = report::BinaryFile { path };
|
||||
reporter.report(msg.into())?;
|
||||
} else {
|
||||
let mut fixes = Vec::new();
|
||||
let mut accum_line_num = AccumulateLineNum::new();
|
||||
for typo in parser.parse_bytes(&buffer) {
|
||||
for typo in typos::check_bytes(&buffer, tokenizer, dictionary) {
|
||||
if is_fixable(&typo) {
|
||||
fixes.push(typo.into_owned());
|
||||
} else {
|
||||
|
@ -305,10 +236,10 @@ impl FileChecker for DiffTypos {
|
|||
|
||||
// Match FixTypos ordering for easy diffing.
|
||||
let mut new_path = None;
|
||||
if self.check_filenames {
|
||||
if settings.check_filenames {
|
||||
if let Some(file_name) = path.file_name().and_then(|s| s.to_str()) {
|
||||
let mut fixes = Vec::new();
|
||||
for typo in parser.parse_str(file_name) {
|
||||
for typo in typos::check_str(file_name, tokenizer, dictionary) {
|
||||
if is_fixable(&typo) {
|
||||
fixes.push(typo.into_owned());
|
||||
} else {
|
||||
|
@ -361,23 +292,20 @@ impl FileChecker for DiffTypos {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Identifiers {
|
||||
check_filenames: bool,
|
||||
check_files: bool,
|
||||
binary: bool,
|
||||
}
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct Identifiers;
|
||||
|
||||
impl FileChecker for Identifiers {
|
||||
fn check_file(
|
||||
&self,
|
||||
path: &std::path::Path,
|
||||
explicit: bool,
|
||||
settings: &CheckSettings,
|
||||
tokenizer: &tokens::Tokenizer,
|
||||
_dictionary: &dyn Dictionary,
|
||||
reporter: &dyn report::Report,
|
||||
) -> Result<(), std::io::Error> {
|
||||
if self.check_filenames {
|
||||
if settings.check_filenames {
|
||||
if let Some(file_name) = path.file_name().and_then(|s| s.to_str()) {
|
||||
for word in tokenizer.parse_str(file_name) {
|
||||
let msg = report::Parse {
|
||||
|
@ -390,9 +318,9 @@ impl FileChecker for Identifiers {
|
|||
}
|
||||
}
|
||||
|
||||
if self.check_files {
|
||||
if settings.check_files {
|
||||
let (buffer, content_type) = read_file(path, reporter)?;
|
||||
if !explicit && !self.binary && content_type.is_binary() {
|
||||
if !explicit && !settings.binary && content_type.is_binary() {
|
||||
let msg = report::BinaryFile { path };
|
||||
reporter.report(msg.into())?;
|
||||
} else {
|
||||
|
@ -415,23 +343,20 @@ impl FileChecker for Identifiers {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Words {
|
||||
check_filenames: bool,
|
||||
check_files: bool,
|
||||
binary: bool,
|
||||
}
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct Words;
|
||||
|
||||
impl FileChecker for Words {
|
||||
fn check_file(
|
||||
&self,
|
||||
path: &std::path::Path,
|
||||
explicit: bool,
|
||||
settings: &CheckSettings,
|
||||
tokenizer: &tokens::Tokenizer,
|
||||
_dictionary: &dyn Dictionary,
|
||||
reporter: &dyn report::Report,
|
||||
) -> Result<(), std::io::Error> {
|
||||
if self.check_filenames {
|
||||
if settings.check_filenames {
|
||||
if let Some(file_name) = path.file_name().and_then(|s| s.to_str()) {
|
||||
for word in tokenizer.parse_str(file_name).flat_map(|i| i.split()) {
|
||||
let msg = report::Parse {
|
||||
|
@ -444,9 +369,9 @@ impl FileChecker for Words {
|
|||
}
|
||||
}
|
||||
|
||||
if self.check_files {
|
||||
if settings.check_files {
|
||||
let (buffer, content_type) = read_file(path, reporter)?;
|
||||
if !explicit && !self.binary && content_type.is_binary() {
|
||||
if !explicit && !settings.binary && content_type.is_binary() {
|
||||
let msg = report::BinaryFile { path };
|
||||
reporter.report(msg.into())?;
|
||||
} else {
|
||||
|
@ -469,22 +394,21 @@ impl FileChecker for Words {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct FoundFiles {
|
||||
binary: bool,
|
||||
}
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
pub struct FoundFiles;
|
||||
|
||||
impl FileChecker for FoundFiles {
|
||||
fn check_file(
|
||||
&self,
|
||||
path: &std::path::Path,
|
||||
explicit: bool,
|
||||
settings: &CheckSettings,
|
||||
_parser: &tokens::Tokenizer,
|
||||
_dictionary: &dyn Dictionary,
|
||||
reporter: &dyn report::Report,
|
||||
) -> Result<(), std::io::Error> {
|
||||
// Check `self.binary` first so we can easily check performance of walking vs reading
|
||||
if self.binary {
|
||||
// Check `settings.binary` first so we can easily check performance of walking vs reading
|
||||
if settings.binary {
|
||||
let msg = report::File::new(path);
|
||||
reporter.report(msg.into())?;
|
||||
} else {
|
||||
|
@ -674,12 +598,13 @@ fn fix_buffer(mut buffer: Vec<u8>, typos: impl Iterator<Item = typos::Typo<'stat
|
|||
pub fn walk_path(
|
||||
walk: ignore::Walk,
|
||||
checks: &dyn FileChecker,
|
||||
parser: &typos::tokens::Tokenizer,
|
||||
settings: &CheckSettings,
|
||||
tokenizer: &typos::tokens::Tokenizer,
|
||||
dictionary: &dyn typos::Dictionary,
|
||||
reporter: &dyn report::Report,
|
||||
) -> Result<(), ignore::Error> {
|
||||
for entry in walk {
|
||||
walk_entry(entry, checks, parser, dictionary, reporter)?;
|
||||
walk_entry(entry, checks, settings, tokenizer, dictionary, reporter)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
@ -687,14 +612,15 @@ pub fn walk_path(
|
|||
pub fn walk_path_parallel(
|
||||
walk: ignore::WalkParallel,
|
||||
checks: &dyn FileChecker,
|
||||
parser: &typos::tokens::Tokenizer,
|
||||
settings: &CheckSettings,
|
||||
tokenizer: &typos::tokens::Tokenizer,
|
||||
dictionary: &dyn typos::Dictionary,
|
||||
reporter: &dyn report::Report,
|
||||
) -> Result<(), ignore::Error> {
|
||||
let error: std::sync::Mutex<Result<(), ignore::Error>> = std::sync::Mutex::new(Ok(()));
|
||||
walk.run(|| {
|
||||
Box::new(|entry: Result<ignore::DirEntry, ignore::Error>| {
|
||||
match walk_entry(entry, checks, parser, dictionary, reporter) {
|
||||
match walk_entry(entry, checks, settings, tokenizer, dictionary, reporter) {
|
||||
Ok(()) => ignore::WalkState::Continue,
|
||||
Err(err) => {
|
||||
*error.lock().unwrap() = Err(err);
|
||||
|
@ -710,7 +636,8 @@ pub fn walk_path_parallel(
|
|||
fn walk_entry(
|
||||
entry: Result<ignore::DirEntry, ignore::Error>,
|
||||
checks: &dyn FileChecker,
|
||||
parser: &typos::tokens::Tokenizer,
|
||||
settings: &CheckSettings,
|
||||
tokenizer: &typos::tokens::Tokenizer,
|
||||
dictionary: &dyn typos::Dictionary,
|
||||
reporter: &dyn report::Report,
|
||||
) -> Result<(), ignore::Error> {
|
||||
|
@ -728,7 +655,7 @@ fn walk_entry(
|
|||
} else {
|
||||
entry.path()
|
||||
};
|
||||
checks.check_file(path, explicit, parser, dictionary, reporter)?;
|
||||
checks.check_file(path, explicit, settings, tokenizer, dictionary, reporter)?;
|
||||
}
|
||||
|
||||
Ok(())
|
|
@ -1,4 +1,4 @@
|
|||
pub mod checks;
|
||||
pub mod config;
|
||||
pub mod dict;
|
||||
pub mod file;
|
||||
pub mod report;
|
||||
|
|
38
src/main.rs
38
src/main.rs
|
@ -7,7 +7,6 @@ use std::io::Write;
|
|||
use structopt::StructOpt;
|
||||
|
||||
mod args;
|
||||
use typos_cli::checks;
|
||||
use typos_cli::config;
|
||||
use typos_cli::dict;
|
||||
use typos_cli::report;
|
||||
|
@ -92,7 +91,7 @@ fn run_checks(args: &args::Args) -> proc_exit::ExitResult {
|
|||
};
|
||||
let config = load_config(cwd, &args).with_code(proc_exit::Code::CONFIG_ERR)?;
|
||||
|
||||
let parser = typos::tokens::TokenizerBuilder::new()
|
||||
let tokenizer = typos::tokens::TokenizerBuilder::new()
|
||||
.ignore_hex(config.default.ignore_hex())
|
||||
.leading_digits(config.default.identifier_leading_digits())
|
||||
.leading_chars(config.default.identifier_leading_chars().to_owned())
|
||||
|
@ -105,11 +104,11 @@ fn run_checks(args: &args::Args) -> proc_exit::ExitResult {
|
|||
dictionary.identifiers(config.default.extend_identifiers());
|
||||
dictionary.words(config.default.extend_words());
|
||||
|
||||
let mut settings = checks::TyposSettings::new();
|
||||
let mut settings = typos_cli::file::CheckSettings::new();
|
||||
settings
|
||||
.check_filenames(config.default.check_filename())
|
||||
.check_files(config.default.check_file())
|
||||
.binary(config.files.binary());
|
||||
.binary(config.default.binary());
|
||||
|
||||
let threads = if path.is_file() { 1 } else { args.threads };
|
||||
let single_threaded = threads == 1;
|
||||
|
@ -132,40 +131,35 @@ fn run_checks(args: &args::Args) -> proc_exit::ExitResult {
|
|||
let status_reporter = report::MessageStatus::new(output_reporter);
|
||||
let reporter: &dyn report::Report = &status_reporter;
|
||||
|
||||
let (files, identifier_parser, word_parser, checks, fixer, differ);
|
||||
let selected_checks: &dyn checks::FileChecker = if args.files {
|
||||
files = settings.build_files();
|
||||
&files
|
||||
let selected_checks: &dyn typos_cli::file::FileChecker = if args.files {
|
||||
&typos_cli::file::FoundFiles
|
||||
} else if args.identifiers {
|
||||
identifier_parser = settings.build_identifier_parser();
|
||||
&identifier_parser
|
||||
&typos_cli::file::Identifiers
|
||||
} else if args.words {
|
||||
word_parser = settings.build_word_parser();
|
||||
&word_parser
|
||||
&typos_cli::file::Words
|
||||
} else if args.write_changes {
|
||||
fixer = settings.build_fix_typos();
|
||||
&fixer
|
||||
&typos_cli::file::FixTypos
|
||||
} else if args.diff {
|
||||
differ = settings.build_diff_typos();
|
||||
&differ
|
||||
&typos_cli::file::DiffTypos
|
||||
} else {
|
||||
checks = settings.build_typos();
|
||||
&checks
|
||||
&typos_cli::file::Typos
|
||||
};
|
||||
|
||||
if single_threaded {
|
||||
checks::walk_path(
|
||||
typos_cli::file::walk_path(
|
||||
walk.build(),
|
||||
selected_checks,
|
||||
&parser,
|
||||
&settings,
|
||||
&tokenizer,
|
||||
&dictionary,
|
||||
reporter,
|
||||
)
|
||||
} else {
|
||||
checks::walk_path_parallel(
|
||||
typos_cli::file::walk_path_parallel(
|
||||
walk.build_parallel(),
|
||||
selected_checks,
|
||||
&parser,
|
||||
&settings,
|
||||
&tokenizer,
|
||||
&dictionary,
|
||||
reporter,
|
||||
)
|
||||
|
|
Loading…
Reference in a new issue