autoimport
is a package designed to easily add
@importFrom
roxygen tags to all your functions.
When importing functions to use them in a package, you have the
choice between @import pkg
to import a whole package and
@importFrom pkg fun1 fun2
to import only a few
functions.
The @importFrom
syntax is preferable, as it has been
stressed out that importing whole packages “makes your code harder to
read (you can’t tell where a function is coming from), and if you
@import
many packages, it increases the chances of function
name conflicts.”
The R Packages (2e) guidelines say that here are two reasonable locations for @importFrom :
As close as possible to the usage of the external function. With this mindset, you would place @importFrom in the roxygen comment above the function in your package where you use the external function.
In a central location. This approach keeps all @importFrom tags together, in a dedicated section of the package-level documentation file (which can be created with
usethis::use_package_doc()
).
I find the first option much clearer, but, as they warn, it tends to get very tedious to keep track of all the function calls.
Therefore, autoimport
will parse your code, detect all
the functions you import, and then add the right @importFrom tags in the right place. Just
like that!
For now, only the development version is available:
# Install development version on Github
::pak("DanChaltiel/autoimport") pak
Simply load the package and run the function!
::load_all(".")
devtools::autoimport() autoimport
The first run will take some time, but a cache system is implemented so that next runs are faster.
Then, you can see the diff and accept the changes using the shiny widget:
::import_review() autoimport
autoimport
will guess the potential source of your
functions based on (1) the packages currently loaded in your environment
(e.g. via library()
), and (2) the packages listed as
dependencies in DESCRIPTION.
load_all(".")
is required for autoimport to have
access to the package’s private functions, for example so that
dplyr::filter()
cannot mask
yourpackage:::filter()
.
Some package guesses are bound to be wrong, in which case you
should use usethis::use_import_from()
. See “Limitations”
below for more details.
Autoimport is based on utils::getSrcref()
and share the
same limits. Therefore, some function syntaxes are not recognized and
autoimport
will try to remove their
@importFrom
from individual functions:
@importFrom dplyr %>%
,
@importFrom rlang :=
, …)sapply(x, my_fun))
glue("my_fun={my_fun(x)}")
)To keep them imported, you should either use a prefix
(pkg::my_fun
) or import them in your package-level
documentation, as this file is ignored by default (due to
ignore_package=TRUE
).
For that, usethis::use_import_from()
and
usethis::use_pipe()
are your friends!
Also, note that R6 methods calls trigger a “not found” warning (WIP, see #21).
As running autoimport()
on a large package can take some
time, a cache system is implemented, by default in file
inst/autoimport_cache.rds
.
Any function not modified since last run should be taken from the cache, resulting on a much faster run.
In some seldom cases, this can cause issues with modifications in
DESCRIPTION or IMPORTLIST not being taken into account. Run
clean_cache()
to remove this file, or use
use_cache="write"
.
When trying to figure out which package to import a function from,
autoimport()
follows this algorithm:
Note that this algorithm is still a bit experimental and that I could only test it on my few own packages. Any feedback is more than welcome!
As I couldn’t find any standardized guideline about the right order
of roxygen2
tags, autoimport
puts them:
@importFrom
tag if there is
one