(pronounced “fleer” as in “beer”)
ℹ️ Until v0.2.1 (included), this package was named flint
. In v0.3.0, it was renamed flir
.
flir
is a small R package to find and replace lints in R code.
- Lints detection with
lint()
- Automatic replacement of lints with
fix()
- Compatibility with (some) lintr rules
- Fast
flir
is powered by astgrepr
, which is itself built on the Rust crate ast-grep
.
Installation
install.packages('flir', repos = c('https://etiennebacher.r-universe.dev', 'https://cloud.r-project.org'))
Note: using remotes::install_github()
, devtools::install_github()
, or pak::pak()
without specifying the R-universe repo will require you to setup Rust to build the package.
Usage
Optional setup:
-
setup_flir()
: creates the folderflir
and populates it with built-in rules as well as a cache file. You can modify those rules or add new ones if you want more control.
You can use flir
as-is, without any setup. However, running setup_flir()
enables the use of caching, meaning that the subsequent runs will be faster. It is also gives you a place where you can store custom rules for your project/package.
The everyday usage consists of two functions:
-
lint()
looks for lints in R files; -
fix()
looks for lints in R files and automatically applies their replacement (if any).
One can also experiment with flir::lint_text()
and flir::fix_text()
:
flir::lint_text(
"
any(is.na(x))
any(duplicated(y))
"
)
#> Original code: any(is.na(x))
#> Suggestion: anyNA(x) is better than any(is.na(x)).
#> Rule ID: any_na-1
#>
#> Original code: any(duplicated(y))
#> Suggestion: anyDuplicated(x, ...) > 0 is better than any(duplicated(x), ...).
#> Rule ID: any_duplicated-1
flir::fix_text(
"
any(is.na(x))
any(duplicated(y))
"
)
#> Old code:
#> any(is.na(x))
#> any(duplicated(y))
#>
#> New code:
#> anyNA(x)
#> anyDuplicated(y) > 0
Real-life examples
I tested flir
on several packages while developing it. I proposed some pull requests for those packages. Here are a few:
-
ggplot2
: #6050 and #6051 -
marginaleffects
: #1171 and #1177 -
targets
: #1325 -
tinytable
: #325 -
usethis
: #2048
Except for some manual tweaks when the replacement was wrong (I was testing flir
after all), all changes were generated by flir::fix_package()
or flir::fix_dir(<dirname>)
.
Comparison with existing tools
The most used tool for lints detection in R is lintr
. However, lintr
’s performance is not optimal when it is applied on medium to large packages. Also, lintr
cannot perform automatic replacement of lints.
styler
is a package to clean code by fixing indentation and other things, but doesn’t perform code replacement based on lints.
flir
is quite performant. This is a small benchmark on 3.5k lines of code with a few linters:
file <- system.file("bench/test.R", package = "flir")
bench::mark(
lintr = lintr::lint(
file,
linters = list(
lintr::any_duplicated_linter(),
lintr::any_is_na_linter(),
lintr::matrix_apply_linter(),
lintr::function_return_linter(),
lintr::lengths_linter(),
lintr::T_and_F_symbol_linter(),
lintr::undesirable_function_linter(),
lintr::expect_length_linter()
)
),
flir = flir::lint(
file,
linters = list(
flir::any_duplicated_linter(),
flir::any_is_na_linter(),
flir::matrix_apply_linter(),
flir::function_return_linter(),
flir::lengths_linter(),
flir::T_and_F_symbol_linter(),
flir::undesirable_function_linter(),
flir::expect_length_linter()
),
verbose = FALSE,
open = FALSE
),
check = FALSE
)
#> Warning: Some expressions had a GC in every iteration; so filtering
#> is disabled.
#> # A tibble: 2 × 6
#> expression min median `itr/sec` mem_alloc `gc/sec`
#> <bch:expr> <bch:tm> <bch:tm> <dbl> <bch:byt> <dbl>
#> 1 lintr 2.97s 2.97s 0.337 315.05MB 2.36
#> 2 flir 180.79ms 181.69ms 5.43 1.85MB 0
Why the name “flir”?
flir
was originally named flint
but I had to rename it to avoid conflicts with a package named flint
on CRAN.
flir
stands for “Fix Lints In R”.
Contributing
Did you find some bugs or some errors in the documentation? Do you want flir
to support more rules?
Take a look at the contributing guide for instructions on bug report and pull requests.
Acknowledgements
The website theme was heavily inspired by Matthew Kay’s ggblend
package: https://mjskay.github.io/ggblend/.