ITADN

New rule: explicit package names

#474Openchristopherkenny 创建于 2026-05-08
futurenew-rule
When shifting from an analysis script to package code, it is often helpful to turn: ```r library(dplyr) library(ggplot2) iris |> mutate(something = seq_len(nrow(iris)) |> ggplot() + geom_point(...) ``` into: ```r library(dplyr) library(ggplot2) iris |> dplyr::mutate(something = seq_len(nrow(iris)) |> ggplot2::ggplot() + ggplot2::geom_point(...) ``` to allow easy copy-pasting into the package. It would be great to have a rule to make package names explicit in this way. I've given it a go, since prototypes are very cheap now. It implements this with a few specific choices to make it consistent: 1. If a function has multiple *package* sources, don't try to resolve it. 2. If a function has one package source, but is re-exported (e.g., `tibble()`), then resolve to the original (`tibble()` -> `tibble`, not to `dplyr` if both are loaded. Goes to `dplyr` if `tibble` is not loaded.) 3. If a function has a local source, treat that as the truth. [Proof of concept](https://github.com/christopherkenny/jarl/commit/0c0dfc9d73a7f124f47d1ec3ea9a28236be7f2e2) Input: ``` library(dplyr) library(tibble) library(rlang) # Clear dplyr calls should be flagged and fixed. x <- tibble(a = 1:5, g = c("a", "a", "b", "b", "b")) y <- mutate(x, b = a + 1) z <- summarise(group_by(y, g), total = sum(b)) # Re-exported calls should resolve to the provider package, not the re-exporter. nested <- tibble( id = 1:3, label = as_label(expr(id)) ) # Already explicit calls should be left alone. explicit <- dplyr::mutate(x, c = a * 2) # Default R packages should be left alone. base_calls <- list(mean(x$a), median(x$a), sum(x$a)) # This is ambiguous between stats and dplyr, so the rule should report without a fix. maybe_ambiguous <- filter(x, a > 2) # Local definitions should be left alone even if a package exports the same name. tibble <- function(value) { value } local_shadow <- tibble("not a package call") # Calls with internal comments should preserve comments when fixed. with_comment <- mutate( x, # keep this comment in place d = a + 10 ) ``` Output, with fixing: ``` library(dplyr) library(tibble) library(rlang) # Clear dplyr calls should be flagged and fixed. x <- tibble::tibble(a = 1:5, g = c("a", "a", "b", "b", "b")) y <- dplyr::mutate(x, b = a + 1) z <- dplyr::summarise(dplyr::group_by(y, g), total = sum(b)) # Re-exported calls should resolve to the provider package, not the re-exporter. nested <- tibble::tibble( id = 1:3, label = rlang::as_label(rlang::expr(id)) ) # Already explicit calls should be left alone. explicit <- dplyr::mutate(x, c = a * 2) # Default R packages should be left alone. base_calls <- list(mean(x$a), median(x$a), sum(x$a)) # This is ambiguous between stats and dplyr, so the rule should report without a fix. maybe_ambiguous <- filter(x, a > 2) # Local definitions should be left alone even if a package exports the same name. tibble <- function(value) { value } local_shadow <- tibble("not a package call") # Calls with internal comments should preserve comments when fixed. with_comment <- dplyr::mutate( x, # keep this comment in place d = a + 10 ) ``` Console notes: ``` warning: explicit_packages --> explicit_packages_stretch.R:23:20 | 23 | maybe_ambiguous <- filter(x, a > 2) | ------ Cannot choose an explicit package qualifier for `filter()`. | = help: `filter()` is exported by multiple loaded packages: stats, dplyr. ```
1 条评论