(pronounced “fleer” as in “beer”)
flir is an R package to detect and rewrite code patterns. It was
originally created to be an R linter and an alternative to
lintr. However, it may be better to view
it as a tool to refactor any type of code by detecting and rewriting
custom patterns (see Adding new
rules). flir
comes with a list of built-in rules and therefore can still be used as a
linter (see the “Usage” section below), but I now concentrate my efforts
on a new R linter entirely written in Rust:
Jarl. Therefore, I will not add new
rules in flir.
flir is powered by
astgrepr, which is
itself built on the Rust crate
ast-grep.
To get the CRAN version (stable):
install.packages("flir")To get the development version (unstable):
# install.packages("remotes")
remotes::install_github("etiennebacher/flir")Optional setup:
setup_flir(): creates the folderflirand 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 rule violations in R files;fix()looks for rule violations 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) > 0See the vignette Automatic
fixes to see
how to be more confident about changes introduced by flir.
I tested flir on several packages while developing it. I proposed some
pull requests for those packages. Here are a few:
ggplot2: #6050 and #6051marginaleffects: #1171 and #1177targets: #1325tinytable: #325usethis: #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>).
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 fast 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 3.44s 3.44s 0.291 313.5MB 12.2
#> 2 flir 153.77ms 172.76ms 5.89 1.8MB 1.96flir 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”.
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.
The website theme was heavily inspired by Matthew Kay’s ggblend
package: https://mjskay.github.io/ggblend/.