【问题标题】:Find unused/"orphaned" non-exported objects during package development在包开发期间查找未使用/“孤立”的非导出对象
【发布时间】:2020-12-22 16:09:38
【问题描述】:

我正在重构一个包含许多非导出函数和其他非导出对象的包。除了手动对包中每个函数的名称进行全文搜索之外,有没有一种方法可以快速识别包中已定义但未导出或调用的所有“孤立”对象?

另外一个复杂的问题是在glue f 风格的字符串中调用了一些函数,因此在某些情况下调用的函数可能无法解析为表达式(这可能不是一个好的设计模式)。

但我会满足于只用于函数和其他对象的方法,这些对象在定义后永远不会作为普通表达式出现。

【问题讨论】:

    标签: r devtools


    【解决方案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 方法。

    【讨论】:

    • S3 的限制实在是太糟糕了,但考虑到语言的限制,我不清楚如何绕过它。
    • “语言限制”?我不确定你的意思是什么,我们在谈论 R ;-)。我将编辑我的答案以包含 S3 方法。
    • 由于 R 不是类型安全的,如何知道在解析时调用了哪个 S3 方法?
    • 我假设如果它被声明为 S3 方法,它会被导出,因为它会进入 S3 方法表。如果您在本地泛型上声明一个方法并且从不调用它,那么新代码将错误地假定它可以被调用。
    猜你喜欢
    • 1970-01-01
    • 2022-08-17
    • 2015-07-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-08-06
    相关资源
    最近更新 更多