Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Roxygen #440

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
65 changes: 52 additions & 13 deletions R/register.R
Original file line number Diff line number Diff line change
Expand Up @@ -77,17 +77,16 @@
cli::cli_alert_success("generated file {.file {basename(r_path)}}")
}


call_entries <- get_call_entries(path, funs$name, package)

cpp_function_registration <- glue::glue_data(funs, ' {{
"_cpp11_{name}", (DL_FUNC) &_{package}_{name}, {n_args}}}, ',
n_args = viapply(funs$args, nrow)
)

cpp_function_registration <- glue::glue_collapse(cpp_function_registration, sep = "\n")
cpp_function_registration <- glue::glue_collapse(cpp_function_registration, sep = "\n")

extra_includes <- character()
extra_includes <- character()
if (pkg_links_to_rcpp(path)) {
extra_includes <- c(extra_includes, "#include <cpp11/R.hpp>", "#include <Rcpp.h>", "using namespace Rcpp;")
}
Expand Down Expand Up @@ -215,35 +214,75 @@
}

generate_r_functions <- function(funs, package = "cpp11", use_package = FALSE) {
funs <- funs[c("name", "return_type", "args")]
funs <- funs[c("name", "return_type", "args", "file", "line", "decoration")]

if (use_package) {
package_call <- glue::glue(', PACKAGE = "{package}"')
package_names <- glue::glue_data(funs, '"_{package}_{name}"')
} else {
package_names <- glue::glue_data(funs, '`_{package}_{name}`')
package_names <- glue::glue_data(funs, "`_{package}_{name}`")
package_call <- ""
}

funs$package <- package
funs$package_call <- package_call
funs$list_params <- vcapply(funs$args, glue_collapse_data, "{name}")
funs$params <- vcapply(funs$list_params, function(x) if (nzchar(x)) paste0(", ", x) else x)
is_void <- funs$return_type == "void"
funs$calls <- ifelse(is_void,
glue::glue_data(funs, 'invisible(.Call({package_names}{params}{package_call}))'),
glue::glue_data(funs, '.Call({package_names}{params}{package_call})')
glue::glue_data(funs, "invisible(.Call({package_names}{params}{package_call}))"),
glue::glue_data(funs, ".Call({package_names}{params}{package_call})")
)

out <- glue::glue_data(funs, '
{name} <- function({list_params}) {{
{calls}
}}
')
# Parse and associate Roxygen comments
funs$roxygen_comment <- mapply(function(file, line) {
if (file.exists(file)) {
comments <- extract_roxygen_comments(file)
matched_comment <- ""
for (comment in comments) {
# Check if the comment directly precedes the function without gaps
if (line == comment$line + 1) {
matched_comment <- comment$text
break

Check warning on line 245 in R/register.R

View check run for this annotation

Codecov / codecov/patch

R/register.R#L243-L245

Added lines #L243 - L245 were not covered by tests
}
}
matched_comment
} else {
""
}
}, funs$file, funs$line, SIMPLIFY = TRUE)

# Generate R functions with or without Roxygen comments
out <- mapply(function(name, list_params, calls, roxygen_comment) {
if (nzchar(roxygen_comment)) {
glue::glue("{roxygen_comment}\n{name} <- function({list_params}) {{\n\t{calls}\n}}")

Check warning on line 257 in R/register.R

View check run for this annotation

Codecov / codecov/patch

R/register.R#L257

Added line #L257 was not covered by tests
} else {
glue::glue("{name} <- function({list_params}) {{\n {calls}\n}}")
}
}, funs$name, funs$list_params, funs$calls, funs$roxygen_comment, SIMPLIFY = TRUE)

out <- glue::trim(out)
out <- glue::glue_collapse(out, sep = "\n\n")
unclass(out)
}

extract_roxygen_comments <- function(file) {
lines <- readLines(file)
roxygen_start <- grep("^/\\* roxygen start", lines)
roxygen_end <- grep("roxygen end \\*/$", lines)

if (length(roxygen_start) == 0 || length(roxygen_end) == 0) {
return(list())
}

roxygen_comments <- mapply(function(start, end) {
roxygen_lines <- lines[(start + 1):(end - 1)]
roxygen_lines <- sub("^", "#' ", roxygen_lines)
list(line = end, text = paste(roxygen_lines, collapse = "\n"))
}, roxygen_start, roxygen_end, SIMPLIFY = FALSE)

Check warning on line 281 in R/register.R

View check run for this annotation

Codecov / codecov/patch

R/register.R#L277-L281

Added lines #L277 - L281 were not covered by tests

roxygen_comments

Check warning on line 283 in R/register.R

View check run for this annotation

Codecov / codecov/patch

R/register.R#L283

Added line #L283 was not covered by tests
}

wrap_call <- function(name, return_type, args) {
call <- glue::glue('{name}({list_params})', list_params = glue_collapse_data(args, "cpp11::as_cpp<cpp11::decay_t<{type}>>({name})"))
if (return_type == "void") {
Expand Down
2 changes: 1 addition & 1 deletion cpp11test/DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,4 @@ Suggests:
xml2
LazyData: true
Roxygen: list(markdown = TRUE)
RoxygenNote: 7.1.1
RoxygenNote: 7.3.2
5 changes: 5 additions & 0 deletions cpp11test/NAMESPACE
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
# Generated by roxygen2: do not edit by hand

export(roxcpp2_)
export(roxcpp3_)
export(roxcpp4_)
export(roxcpp5_)
export(roxcpp7_)
export(run_tests)
exportPattern("_$")
importFrom(Rcpp,sourceCpp)
Expand Down
57 changes: 57 additions & 0 deletions cpp11test/R/cpp11.R
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,63 @@ rcpp_release_ <- function(n) {
invisible(.Call(`_cpp11test_rcpp_release_`, n))
}

notroxcpp1_ <- function(x) {
.Call(`_cpp11test_notroxcpp1_`, x)
}

#' @title Roxygenise C++ function II
#' @param x numeric value
#' @description Dummy function to test roxygen2. It adds 2.0 to a double.
#' @export
#' @examples roxcpp2_(1.0)
roxcpp2_ <- function(x) {
.Call(`_cpp11test_roxcpp2_`, x)
}

#' @title Roxygenise C++ function III
#' @param x numeric value
#' @description Dummy function to test roxygen2. It adds 3.0 to a double.
#' @export
#' @examples roxcpp3_(1.0)
roxcpp3_ <- function(x) {
.Call(`_cpp11test_roxcpp3_`, x)
}

#' @title Roxygenise C++ function IV
#' @param x numeric value
#' @description Dummy function to test roxygen2. It adds 4.0 to a double.
#' @export
#' @examples roxcpp4_(1.0)
roxcpp4_ <- function(x) {
.Call(`_cpp11test_roxcpp4_`, x)
}

#' @title Roxygenise C++ function V
#' @param x numeric value
#' @description Dummy function to test roxygen2. It adds 5.0 to a double.
#' @export
#' @examples roxcpp5_(1.0)
roxcpp5_ <- function(x) {
.Call(`_cpp11test_roxcpp5_`, x)
}

notroxcpp6_ <- function(x) {
.Call(`_cpp11test_notroxcpp6_`, x)
}

#' @title Roxygenise C++ function VII
#' @param x numeric value
#' @description Dummy function to test roxygen2. It adds 7.0 to a double.
#' @export
#' @examples
#' my_fun <- function(x) {
#' roxcpp7_(x)
#' }
#' @seealso \code{\link{roxcpp1_}}
roxcpp7_ <- function(x) {
.Call(`_cpp11test_roxcpp7_`, x)
}

cpp11_safe_ <- function(x_sxp) {
.Call(`_cpp11test_cpp11_safe_`, x_sxp)
}
Expand Down
17 changes: 17 additions & 0 deletions cpp11test/man/roxcpp2_.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions cpp11test/man/roxcpp3_.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions cpp11test/man/roxcpp4_.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

17 changes: 17 additions & 0 deletions cpp11test/man/roxcpp5_.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

22 changes: 22 additions & 0 deletions cpp11test/man/roxcpp7_.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

56 changes: 56 additions & 0 deletions cpp11test/src/cpp11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -303,6 +303,55 @@ extern "C" SEXP _cpp11test_rcpp_release_(SEXP n) {
return R_NilValue;
END_CPP11
}
// roxygen1.cpp
double notroxcpp1_(double x);
extern "C" SEXP _cpp11test_notroxcpp1_(SEXP x) {
BEGIN_CPP11
return cpp11::as_sexp(notroxcpp1_(cpp11::as_cpp<cpp11::decay_t<double>>(x)));
END_CPP11
}
// roxygen1.cpp
double roxcpp2_(double x);
extern "C" SEXP _cpp11test_roxcpp2_(SEXP x) {
BEGIN_CPP11
return cpp11::as_sexp(roxcpp2_(cpp11::as_cpp<cpp11::decay_t<double>>(x)));
END_CPP11
}
// roxygen2.cpp
double roxcpp3_(double x);
extern "C" SEXP _cpp11test_roxcpp3_(SEXP x) {
BEGIN_CPP11
return cpp11::as_sexp(roxcpp3_(cpp11::as_cpp<cpp11::decay_t<double>>(x)));
END_CPP11
}
// roxygen2.cpp
double roxcpp4_(double x);
extern "C" SEXP _cpp11test_roxcpp4_(SEXP x) {
BEGIN_CPP11
return cpp11::as_sexp(roxcpp4_(cpp11::as_cpp<cpp11::decay_t<double>>(x)));
END_CPP11
}
// roxygen3.cpp
double roxcpp5_(double x);
extern "C" SEXP _cpp11test_roxcpp5_(SEXP x) {
BEGIN_CPP11
return cpp11::as_sexp(roxcpp5_(cpp11::as_cpp<cpp11::decay_t<double>>(x)));
END_CPP11
}
// roxygen3.cpp
double notroxcpp6_(double x);
extern "C" SEXP _cpp11test_notroxcpp6_(SEXP x) {
BEGIN_CPP11
return cpp11::as_sexp(notroxcpp6_(cpp11::as_cpp<cpp11::decay_t<double>>(x)));
END_CPP11
}
// roxygen3.cpp
double roxcpp7_(double x);
extern "C" SEXP _cpp11test_roxcpp7_(SEXP x) {
BEGIN_CPP11
return cpp11::as_sexp(roxcpp7_(cpp11::as_cpp<cpp11::decay_t<double>>(x)));
END_CPP11
}
// safe.cpp
SEXP cpp11_safe_(SEXP x_sxp);
extern "C" SEXP _cpp11test_cpp11_safe_(SEXP x_sxp) {
Expand Down Expand Up @@ -500,6 +549,8 @@ static const R_CallMethodDef CallEntries[] = {
{"_cpp11test_my_warning_n1", (DL_FUNC) &_cpp11test_my_warning_n1, 1},
{"_cpp11test_my_warning_n1fmt", (DL_FUNC) &_cpp11test_my_warning_n1fmt, 1},
{"_cpp11test_my_warning_n2fmt", (DL_FUNC) &_cpp11test_my_warning_n2fmt, 2},
{"_cpp11test_notroxcpp1_", (DL_FUNC) &_cpp11test_notroxcpp1_, 1},
{"_cpp11test_notroxcpp6_", (DL_FUNC) &_cpp11test_notroxcpp6_, 1},
{"_cpp11test_protect_many_", (DL_FUNC) &_cpp11test_protect_many_, 1},
{"_cpp11test_protect_many_cpp11_", (DL_FUNC) &_cpp11test_protect_many_cpp11_, 1},
{"_cpp11test_protect_many_preserve_", (DL_FUNC) &_cpp11test_protect_many_preserve_, 1},
Expand All @@ -518,6 +569,11 @@ static const R_CallMethodDef CallEntries[] = {
{"_cpp11test_rcpp_sum_int_for_", (DL_FUNC) &_cpp11test_rcpp_sum_int_for_, 1},
{"_cpp11test_remove_altrep", (DL_FUNC) &_cpp11test_remove_altrep, 1},
{"_cpp11test_row_sums", (DL_FUNC) &_cpp11test_row_sums, 1},
{"_cpp11test_roxcpp2_", (DL_FUNC) &_cpp11test_roxcpp2_, 1},
{"_cpp11test_roxcpp3_", (DL_FUNC) &_cpp11test_roxcpp3_, 1},
{"_cpp11test_roxcpp4_", (DL_FUNC) &_cpp11test_roxcpp4_, 1},
{"_cpp11test_roxcpp5_", (DL_FUNC) &_cpp11test_roxcpp5_, 1},
{"_cpp11test_roxcpp7_", (DL_FUNC) &_cpp11test_roxcpp7_, 1},
{"_cpp11test_string_proxy_assignment_", (DL_FUNC) &_cpp11test_string_proxy_assignment_, 0},
{"_cpp11test_string_push_back_", (DL_FUNC) &_cpp11test_string_push_back_, 0},
{"_cpp11test_sum_dbl_accumulate2_", (DL_FUNC) &_cpp11test_sum_dbl_accumulate2_, 1},
Expand Down
22 changes: 22 additions & 0 deletions cpp11test/src/roxygen1.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
#include "cpp11/doubles.hpp"
using namespace cpp11;

// Test: not documented + documented

// Not Roxygenised C++ function I
[[cpp11::register]] double notroxcpp1_(double x) {
double y = x + 1.0;
return y;
}

/* roxygen start
@title Roxygenise C++ function II
@param x numeric value
@description Dummy function to test roxygen2. It adds 2.0 to a double.
@export
@examples roxcpp2_(1.0)
roxygen end */
[[cpp11::register]] double roxcpp2_(double x) {
double y = x + 2.0;
return y;
}
Loading
Loading