Deprecate functions with roxygen2

Hello roxygen2 deprecated world!

Introduction

package roxygen2 provides a flexible and powerful way of documenting packages and objects inside them. Great flexibility between how the documentation content is organized in source files tags and how it is rendered in the help pages.

We can leverage on this flexibility to adapt the documentation upon making a function deprecated or defunct. As stated in the base R deprecated documentation (help(Deprecated)):

The original help page for these functions is often available at help(“oldName-deprecated”) (note the quotes). Functions should be listed in help(“pkg-deprecated”) for an appropriate pkg, including base.

Deprecate existing functions

We show how an existing and documented function myFun in package ourPkg can be deprecated, and the documentation adjusted accordingly.

## myFun.r
#' @title My function.
#' @description My function.
#' @param arg1 My first argument.
#' @param arg2 My second argument.
#' @return My return value.
#' @export
myFun <- function(arg1, arg2) {
  "My return value"
}

Let us assume a new function myNewFunction exists, and the old myFun is now deprecated deprecated. We want to achieve the following

  • list myFun in help("ourPkg-deprecated), along with its replacement
  • make its original documentation available via help("myFun-deprecated")

This behavior is achieved by

  • creating generic content for content for help("ourPkg-deprecated"")
  • adjusting the existing myFun documentation content
Generic package-level documentation

Generic content for help("ourPkg-deprecated") can be specified in its own source file.

## ourPkg-deprecated.r
#' @title Deprecated functions in package \pkg{ourPkg}.
#' @description The functions listed below are deprecated and will be defunct in
#'   the near future. When possible, alternative functions with similar
#'   funcionality are also mentioned. Help pages for deprecated functions are
#'   available at \code{help("<function>-deprecated")}.
#' @name ourPkg-deprecated
#' @keywords internal
NULL

Function-specific content will be added to help("ourPkg-deprecated") from the corresponding function sources.

Function-specific documentation

The source file of myFun is modified as follows

## myFun.r
#' @title My function.
#' @description My function.
#' @param arg1 My first argument.
#' @param arg2 My second argument.
#' @return My return value.
#'
#' @name myFun-deprecated
#' @usage myFun(arg1, arg2)
#' @seealso \code{\link{ourPkg-deprecated}}
#' @keywords internal
NULL

#' @rdname ourPkg-deprecated
#' @section \code{myFun}:
#' For \code{myFun}, use \code{\link{myNewFun}}.
#'
#' @export
myFun <- function(arg1, arg2) {
  .Deprecated("myNewFun")
  "My return value"
}

In particular, two blocks of roxygen2 tags have been added to the original function tags.

  • The first block is used to create the myFun-deprecated help page, detached from the myFun object. For this reason we need to explicitly add the original function signature as ‘Usage’ section. We also add a ‘See Also’ link to the ourPkg-deprecated help page.
  • The second block adds myFun-specific content to the ourPkg-deprecated help page. This will include a the standard ‘Usage’ section content and function-specific section with the indication about using myNewFun instead. Such content will be collected for all deprecated function with similar tags structure.

Note also that help(myFun) will point to the ourPkg-deprecated help page, and that the @keywords internal prevents the corresponding topics from from appearing in the package documentation index.

Using roxygen2 templates

Deprecating functions as described above can be automated using templates. One can define a template for each of the two additional blocks:

## template-depr_pkg.r
#' @name ourPkg-deprecated
#' @section \code{<%= old %>}:
#' For \code{<%= old %>}, use \code{\link{<%= new %>}}.
## template-depr_fun.r
#' @name <%= fun %>-deprecated
#' @usage <%= gsub("\n", "\n#' ", roxygen2:::wrapString(roxygen2:::function_usage(fun, formals(fun)))) %>
#' @seealso \code{\link{ourPkg-deprecated}}
#' @keywords internal

Note the presence of template variables and of some roxygen2 internals for automating the construction of the ‘Usage’ section (handling multiple lines in case of many arguments).

Deprecating herFun in favor of herNewFun then results in the simple inclusion of the templates in the function source:

## herFun.r
#' @title Her function.
#' @description Her function.
#' @param arg1 Her first argument.
#' @param arg2 Her second argument.
#' @return Her return value.
#'
#' @templateVar fun herFun
#' @template template-depr_fun
NULL

#' @templateVar old herFun
#' @templateVar new herNewFun
#' @template template-depr_pkg
#'
#' @export
herFun <- function(arg1, arg2) {
  .Deprecated("herNewFun")
  "Her return value"
}
devtools::build(pkg) %>% install.packages(repos = NULL)
unlink(pkg, recursive = TRUE)