LinkedIn link GitHub link Twitter link

#R - Deprecate functions with roxygen2

We show how to use roxygen2 tags and templates for deprecating existing documented functions.

Introduction

Package roxygen2 provides a powerful way of documenting packages and objects inside them. In particular, great flexibility is available for organizing the documentation content in source files and templates, and render it as desired in the corresponding help pages.

We can leverage on this flexibility to adapt an existing package documentation upon making a function deprecated (and similarly defunct). As stated in the base-R ‘Marking Objects as 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 by re-arranging the roxygen2 documentation content.

## 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 as a replacement for the old myFun, which becomes 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 can be obtained by

  • creating generic content for help("ourPkg-deprecated"");
  • adjusting the existing myFun documentation content.
Package-level documentation

Generic content for help("ourPkg-deprecated") is defined 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
#'   functionality are also mentioned. Help pages for deprecated functions are
#'   available at \code{help("<function>-deprecated")}.
#' @name ourPkg-deprecated
#' @keywords internal
NULL
Function-specific documentation

Function-specific content is added to the ourPkg-deprecated help page from the corresponding source file, where we also want to make the original help page available via help("myFun-deprecated").

The source file of myFun is then 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"
}

Two blocks of roxygen2 tags have been added to the existing documentation content.

  • 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 ourPkg-deprecated.
  • The second block adds myFun-specific content to the ourPkg-deprecated help page. The standard ‘Usage’ section is added automatically, and we create a function-specific section where using myNewFun is suggested. Such content will be collected and shown in help("ourPkg-deprecated") for all deprecated functions with similar tags structure.

Note also that help(myFun) will point to the ourPkg-deprecated help page, and that @keywords internal prevents the corresponding topics 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 additional block.

## 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).

Update – When using roxygen2 ≥ 7.x, the following should be used instead.

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

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"
}

Example package manual and sources

A complete example of ourPkg is available for download. The package contains functions myFun, yourFun, herFun, hisFun, where all but yourFun are deprecated in favor of *NewFun, using roxygen2 templates for herFun and hisFun. The resulting documentation content can be assessed in the corresponding PDF reference manual.1

  1. Update – The source package and documentation are based on R version 3.6.2 (2019-12-12) and the latest set of R packages as of 2020-02-04.