#r #devtools
#r #devtools
Вопрос:
Я занимаюсь рефакторингом пакета, содержащего множество неэкспортированных функций и других неэкспортированных объектов. Есть ли способ быстро идентифицировать все «потерянные» объекты, которые определены, но не экспортированы или не вызываются где-либо еще в пакете, кроме ручного полнотекстового поиска по имени каждой функции в пакете?
Дополнительная сложность заключается в том, что некоторые функции вызываются внутри glue
строк в стиле f, поэтому могут быть случаи, когда вызываются функции, которые не могут быть проанализированы как выражения (вероятно, это не очень хороший шаблон проектирования).
Но я был бы удовлетворен методом только для функций и других объектов, которые никогда не отображаются как обычные выражения после определения.
Ответ №1:
Это даст вам частичный ответ (отредактированный из оригинала):
pkg <- "testpkg"
library(pkg, character.only = TRUE)
ns <- getNamespace(pkg)
allnames <- ls(ns)
exports <- ls(paste0("package:", pkg))
nsInfo <- readRDS(system.file("Meta/nsInfo.rds", package = pkg))
if (!is.null(nsInfo$S3methods)) {
S3methods <- with(nsInfo, paste(S3methods[,1], S3methods[,2], sep = "."))
} else
S3methods <- NULL
locals <- setdiff(allnames, c(exports, S3methods))
used <- character()
newones <- c(exports, S3methods)
while (length(newones)) {
mentioned <- unique(unlist(lapply(newones, function(n) {
fun <- get(n, envir = ns)
if (is.function(fun))
codetools::findGlobals(fun)
})))
used <- c(used, newones)
newones <- setdiff(intersect(mentioned, locals), used)
}
unused <- setdiff(locals, used)
unused
Это все еще не совсем правильно, но это должно помочь вам начать. Некоторые проблемы:
- предполагается, что никакие функции не выполняют забавные вещи, такие как
assign()
, или возятся со средами и т. Д. - он не обнаруживает функции, которые полностью используются для создания других объектов в пакете.
- он не обнаруживает странные методы S3, объявленные с нестандартным именем.
Комментарии:
1. Ограничение S3 — это облом, но, учитывая ограничения языка, мне непонятно, как вы могли бы его обойти.
2. «Ограничения языка»? Я не уверен, что вы имеете в виду под этим, мы говорим о R ;-). Я отредактирую свой ответ, чтобы включить и методы S3.
3. Поскольку R не является безопасным для типов, как можно узнать, какой метод S3 вызывается во время синтаксического анализа?
4. Я предполагаю, что если он объявлен как метод S3, он экспортируется, потому что он попадает в таблицу методов S3. Если вы объявите метод в локальном универсальном и никогда не вызовете его, то новый код будет ошибочно предполагать, что он может быть вызван.