require("tools")

# -------------------------------------------------------------------
# find_wide_Rd_lines_in_Rd_object: render stage=render \Sexpr
# expressions within \examples if installed = TRUE.

rd <- sprintf("
\\name{foo}
\\title{Title}
\\description{Desc.}
\\examples{
  \\Sexpr[stage=render]{\"# foobar\"}
  \\Sexpr[stage=render]{strrep(\"long \", 30)}
  # %s
}", strrep("123456789 ", 10))

rd <- parse_Rd(con <- textConnection(rd)); close(con)

# does not error, but finds long lines, dynamic ones as well
bad <- tools:::find_wide_Rd_lines_in_Rd_object(rd, installed = TRUE)
stopifnot(
  "examples" %in% names(bad),
  "warn" %in% names(bad$examples),
  any(grepl("123456789 ", bad$examples$warn)),
  any(grepl("long ", bad$examples$warn))
)

# does error currently
err <- NULL
tryCatch(
  tools:::find_wide_Rd_lines_in_Rd_object(rd, installed = FALSE),
  error = function(e) err <<- e
)
stopifnot(!is.null(err))
\name{Rd-Sexpr-error}
\title{Trigger an Error when Evaluating Code from \verb{\\Sexpr}}
\description{
  \Sexpr[stage=render]{
    % this will give an error
    1 + "error"
  }
}
\name{SexprExample}
\title{title}
\description{description}
\details{
  Hello
  \Sexpr[stage=build,results=hide]{
    invisible(NULL)
    invisible(NULL)
    invisible(NULL)
    invisible(NULL)
    invisible(NULL)
    invisible(NULL)
    invisible(NULL)
    invisible(NULL)
    invisible(NULL)
    "" # workaround: remove results=hide and use the return value
  }
}
\name{Rd-Sexpr-warning}
\title{Trigger a \code{checkRd} Warning for \verb{\\Sexpr} Output}
\description{Regression test for c75410}
\section{Rd issue}{ % in line 5 (strong is invalid in code block)
  \Sexpr[results=rd,stage=build]{"\\\\code{\\\\strong{x}}"}
}
require("tools")

# -------------------------------------------------------------------
# prepare_Rd() is OK with a top level \Sexpr that is yet to be rendered

txt <- "
\\name{foo}
\\title{Title}
\\description{Desc.}
\\Sexpr[stage=render,results=rd]{\"\\\\\\details{This is dynamic.}\"}
"

rd <- parse_Rd(con <- textConnection(txt)); close(con)

warn <- NULL
withCallingHandlers(
  rd2 <- tools:::prepare_Rd(rd),
  warning = function(w) { warn <<- w; invokeRestart("muffleWarning") }
)
stopifnot(is.null(warn))
stopifnot("\\Sexpr" %in% tools:::RdTags(rd2))


## \Sexpr[stage=build, results=hide]{ <a dozen "empty" lines> }
tf <- textConnection("RdTeX", "w")
Rd2latex("Rd-Sexpr-hide-empty.Rd", tf, stages="build")
tex <- textConnectionValue(tf); close(tf); rm(tf)
(H2end <- tex[grep("^Hello", tex):length(tex)])
stopifnot((n <- length(H2end)) <= 4, # currently '3'; was 13 in R < 4.2.0
          H2end[-c(1L,n)] == "")     # also had \\AsIs{ .. }  " "  "   "


## checkRd() gives file name and correct line number of \Sexpr[results=rd] chunk
stopifnot(grepl("Rd-Sexpr-warning.Rd:5:",
                print(checkRd("Rd-Sexpr-warning.Rd", stages = "build")),
                fixed = TRUE))

## processRdChunk() gives file name and location of eval error
(msg <- tryCatch(checkRd(file_path_as_absolute("Rd-Sexpr-error.Rd")),
                 error = conditionMessage))
stopifnot(startsWith(msg, "Rd-Sexpr-error.Rd:4-7:"),
          length(checkRd("Rd-Sexpr-error.Rd", stages = NULL)) == 0)
## file name and line numbers were missing in R < 4.2.0


## \doi with hash symbol or Rd specials
rd <- parse_Rd("doi.Rd")
writeLines(out <- capture.output(Rd2txt(rd, stages = "build")))
stopifnot(grepl("10.1000/456#789", out[5], fixed = TRUE),
          grepl("doi.org/10.1000/456%23789", out[5], fixed = TRUE),
          grepl("10.1000/{}", out[7], fixed = TRUE),
          grepl("doi.org/10.1000/%7B%7D", out[7], fixed = TRUE))
## R < 4.2.0 failed to encode the hash and lost {}
require("tools")

x <- Rd_db("base")
system.time(y <- lapply(x, function(e)
    tryCatch(Rd2HTML(e, out = nullfile()), error = identity))) # 3-5 sec
stopifnot(!vapply(y, inherits, NA, "error"))
## Gave error when "running" \Sexpr{.} DateTimeClasses.Rd


## PR#18052: \dots must not be interpreted inside \preformatted
Rdsnippet <- tempfile()
writeLines(r"(\preformatted{
\item{\dots}{foo(arg = "\\\\dots", ...)}
})", Rdsnippet)
#file.show(Rdsnippet)
stopifnot(exprs = {
    identical(capture.output(Rd2HTML(Rdsnippet, fragment = TRUE))[2L],
              r"(\item{\dots}{foo(arg = "\\dots", ...)})")
    identical(capture.output(Rd2txt(Rdsnippet, fragment = TRUE))[2L],
              r"(\item{\dots}{foo(arg = "\\dots", ...)})")
    identical(capture.output(Rd2latex(Rdsnippet, fragment = TRUE))[2L],
              r"(\bsl{}item\{\bsl{}dots\}\{foo(arg = "\bsl{}\bsl{}dots", ...)\})")
}) # the last two failed in R < 4.1.0

## also do not translate \dots in R code lines in \examples
Rdsnippet <- tempfile()
writeLines(r"(\examples{
foo <- function(arg = "\\\\dots", ...) NULL # \dots
})", Rdsnippet)
#file.show(Rdsnippet)
stopifnot(exprs = {
    identical(capture.output(Rd2ex(parse_Rd(Rdsnippet), fragment = TRUE))[5L],
              r"(foo <- function(arg = "\\dots", ...) NULL # \dots)")
}) # failed in R < 4.1.0

## \usage: keep quoted "\\\\dots", but _do_ translate formal \dots arg
Rdsnippet <- tempfile()
writeLines(r"(\name{foo}\title{foo}\usage{
## keep this comment to ensure a newline at the end
foo(arg = "\\\\dots", \dots)
})", Rdsnippet)
Rdobj <- parse_Rd(Rdsnippet)
check_dots_usage <- function(FUN) {
    out <- trimws(grep("foo(", capture.output(FUN(Rdobj)),
                       value = TRUE, fixed = TRUE))
    if (!identical(out, r"(foo(arg = "\\dots", ...))"))
        stop("unexpected output: ", out)
}
check_dots_usage(Rd2HTML)
check_dots_usage(Rd2txt)
check_dots_usage(Rd2latex)
## the last two failed in R < 4.1.0; output was foo(arg = "\...", ...)
## check that all S3 methods in base are registered.
(function() {
  old <-  Sys.getlocale("LC_COLLATE")
  on.exit(Sys.setlocale("LC_COLLATE", old))
          Sys.setlocale("LC_COLLATE", "C")
  stopifnot(identical(base:::.S3_methods_table, # >>> end of ../../base/R/zzz.R ; update *there* !
                      tools:::.make_S3_methods_table_for_base()))
})()
\RdOpts{stage = build}   % emulate pre-4.2.0 default for \doi
\name{doi}
\title{Test \verb{\\doi} with hash or Rd specials}
\description{
  \doi{10.1000/456#789}  % example from DOI handbook (Section 2.5.2.3)
  
  \doi{10.1000/\{\}}     % hypothetical DOI with curly braces
}
require("tools")

(ud4 <- undoc("stats4"))
stopifnot(sapply(ud4, length) == 0)
