I'm refactoring a package that imports many other packages' full namespaces. I believe that many of these dependencies are used for single function call uses that would be better handled using importFrom, or are orphaned dependencies that are no longer used.
There's enough code in the package that it would be tedious to manually examine every line looking for unfamiliar function calls.
How can I determine where and how many times objects from imported namespaces are being used in the package? Please note that this package does not include unit tests.
Here is a reproducible example:
DESCRIPTION
file:
Package: my_package
Title: title
Version: 0.0.1
Authors@R: person(
given = "A",
family = "Person",
role = c("aut", "cre"),
email = "[email protected]"
)
Description: Something
License: Some license
Encoding: UTF-8
LazyData: true
RoxygenNote: 7.1.1
Imports:
dplyr,
purrr,
stringr
NAMESPACE
file:
import(dplyr)
import(purrr)
import(stringr)
my_package.R
file:
#' my_package
#' @docType package
#' @name my_package
NULL
#' @import dplyr
#' @import purrr
#' @import stringr
NULL
functions.R
file
#' add 1 to "banana" column and call it "apple"
#' @description demonstrate a variety of dplyr functions
#' @param x a data.frame object
#' @return a data.frame object with columns "apple" and "banana"
#' @examples
#' my_fruit <- data.frame(banana = c(1,2,3), pear = c(4,5,6))
#' my_function(my_fruit)
#' @export
my_function <- function(x) {
x %>%
mutate(apple = banana + 1) %>%
select(apple, banana)
}
I am looking for a solution that would identifies that %>%
, mutate
and select
are exports from dplyr
, %>%
is an export from purrr
, and there are no used exports from the attached namespace stringr
. In the case of functions like %>%
exported from multiple namespaces it's not that important to me to distinguish which namespace the export is coming from (in the example both %>%
are rexports from the magrittr
dependency) since where actual masking occurs a warning is generated when the package gets loaded.
Here's a base solution
final output :
It is not 100% robust as for instance a function
function(x) {select<-identity; select(x)}
will show select as being taken from {dplyr}.It will also miss functions that are not used in
fun()
form, as inlapply(my_list, fun)
.We can't really detect those robustly, a way around, that might get us there or at least closer if we have 100% test coverage, is to curry those imported functions so they tell us when they're called, then run the tests.
You probably don't need this though.