Skip to content
Open
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