tools/documentation/updateReexports.R

# source("tools/documentation/updateReexports.R")
# Will add all functions aliased in `./tools/documentation/reexports.json`
# Will save all reexports to `./R/reexports.R` and document to enforce all re-exports
# This script needs information from `./tools/documentation/reexports.json` to allow pkgdown to be on the same page
# Information from `./tools/documentation/reexports.json` will be used in `shiny-dev-center`


local({

  # make sure packages are installed
  for (pkg in c("gh", "rprojroot", "devtools", "memoise", "magrittr", "jsonlite")) {
    if (!requireNamespace(pkg, quietly = TRUE)) {
      install.packages(pkg)
    }
  }

  `%>%` <- magrittr::`%>%`

  # pre document
  devtools::document()

  pre_namespace_lines <- readLines(rprojroot::find_package_root_file("NAMESPACE"))

  local_reexports_r_file <- rprojroot::find_package_root_file("R/reexports.R")
  unlink(local_reexports_r_file)

  alias_info <- jsonlite::fromJSON(rprojroot::find_package_root_file("tools/documentation/reexports.json"), simplifyDataFrame = FALSE)
  local_man_folder <- rprojroot::find_package_root_file("man")

  latest_tag <- memoise::memoise(function(repo) {
    # requires a GITHUB_PAT token
    gh::gh(paste0("GET /repos/", repo, "/tags"))[[1]]$name
  })

  vapply(
    FUN.VALUE = character(1), USE.NAMES = FALSE,
    alias_info,
    function(alias_pkg_info) {
      message("Starting: ", alias_pkg_info$repo)

      # tags are returned from newest to oldest. (Newest being first)
      latest_tag_name <- latest_tag(alias_pkg_info$repo)
      github_man_location <- paste0("https://raw.githubusercontent.com/", alias_pkg_info$repo, "/", latest_tag_name, "/man/")

      vapply(
        FUN.VALUE = character(1), USE.NAMES = FALSE,
        alias_pkg_info$exports,
        function(alias_item) {

          message("Gathering: ", alias_pkg_info$name, " ", alias_item$file)

          lines <- paste0(github_man_location, alias_item$file) %>%
            readLines() %>%
            { .[-(1:2)] } # remove first two roxygen2 comments

          funcs <-
            lines[grepl("\\alias{", lines, fixed = TRUE)] %>%
            sub("\\alias{", "", ., fixed = TRUE) %>%
            sub("}$", "", .) %>%
            setdiff(alias_item$ignore)

          beginning <- paste0("# ", alias_pkg_info$name, " ")
          paste0(
            "\n",
            beginning, alias_item$file, " ", paste0(rep("-", 80 - nchar(beginning) - nchar(alias_item$file) - 1), collapse = ""), "\n",
            ### https://github.com/tidyverse/dplyr/blob/713849e31b1f7b217154586d30aa169749075481/R/reexport-tibble.r
            # #' @importFrom tibble data_frame
            # #' @export
            # tibble::data_frame
            ###
            paste0(collapse = "\n",
              "\n",
              "#' @importFrom ", alias_pkg_info$name, " ", funcs, "\n",
              "#' @export\n",
              alias_pkg_info$name, "::", funcs
            )
          )
        }
      ) %>%
        # combine package items
        paste0(collapse = "\n\n")
    }

  ) %>%
    # combine packages
    paste0(collapse = "\n\n\n") %>%
    paste0(
      "####\n",
      "# Generated by `./tools/documentation/updateReexports.R`: do not edit by hand\n",
      "# Please call `source('tools/documentation/updateReexports.R')` from the root folder to update`\n",
      "####\n",
      "\n",
      .
    ) %>%
    writeLines(local_reexports_r_file)
  message("Updated: ", local_reexports_r_file)

  # document new functions
  devtools::document()
  post_namespace_lines <- readLines(rprojroot::find_package_root_file("NAMESPACE"))

  pkg_names <-
    vapply(alias_info, `[[`, character(1), "name") %>%
    paste0("`", ., "`", collapse = ", ")
  imports_txt <-
    vapply(alias_info, FUN.VALUE = character(1), function(alias_pkg_info) {
      conn <- paste0(
        "https://raw.githubusercontent.com/", alias_pkg_info$repo, "/", latest_tag(alias_pkg_info$repo), "/DESCRIPTION"
      ) %>%
        url()
      on.exit({close(conn)})

      conn %>%
        read.dcf() %>%
        as.data.frame() %>%
        {.$Version[1]} %>%
        as.character() %>%
        paste0("    ", alias_pkg_info$name, " (>= ", ., ")")
    }) %>%
    paste0(collapse = "\n")

  docs_are_same <- identical(pre_namespace_lines, post_namespace_lines)
  msg_fn <- if (docs_are_same) message else stop
  msg_fn(
    "\n",
    "The NAMESPACE exports ", if (docs_are_same) { "did NOT change"} else { "CHANGED"},
    " by copying in the ", pkg_names, " files\n",
    "\n",
    if (docs_are_same) "Possible ", pkg_names, " version requirement to add to DESCRIPTION file:\n",
    "Imports:\n",
    imports_txt
  )


  # validate that all man files are autogenerated
  first_man_file_line <-
    dir("man", full.names = TRUE) %>%
    Filter(function(x) {!dir.exists(x)}, .) %>% # be sure to remove folders (which may be interpreted as files)
    setNames(., .) %>%
    lapply(readLines) %>%
    lapply(head, 1)
  is_all_roxygen <-
    first_man_file_line %>%
    unique() %>%
    length() %>%
    magrittr::equals(1)

  if (!is_all_roxygen) {
    str(first_man_file_line[vapply(first_man_file_line, function(txt) !grepl("Generated by roxygen2:", txt, fixed = TRUE), logical(1))])
    stop("Not every file is auto generated by roxygen.  Fix this!")
  }

})
rstudio/shiny documentation built on June 14, 2024, 4:25 p.m.