Nothing
thin <- make_cran_thinner()
test_that("DocParser parses @description annotations", {
thin()
tmp <- tempfile(fileext = ".arl")
on.exit(unlink(tmp))
writeLines(c(
"(module test-mod",
" (export my-fn)",
"",
" ;;' @description Add two numbers.",
" ;;' @examples",
" ;;' (my-fn 1 2) ; => 3",
" ;;' @seealso sub-fn",
" (define my-fn",
" (lambda (a b) (+ a b)))",
")"
), tmp)
parser <- DocParser$new()
result <- parser$parse_file(tmp)
expect_true("my-fn" %in% names(result$functions))
fn <- result$functions[["my-fn"]]
expect_equal(fn$description, "Add two numbers.")
expect_match(fn$examples, "my-fn 1 2")
expect_equal(fn$seealso, "sub-fn")
})
test_that("DocParser parses @section annotations", {
thin()
tmp <- tempfile(fileext = ".arl")
on.exit(unlink(tmp))
writeLines(c(
"(module test-mod",
" (export f1 f2)",
"",
" ;;' @section Math Helpers",
"",
" ;;' @description Double a number.",
" (define f1 (lambda (x) (* x 2)))",
"",
" ;;' @description Triple a number.",
" (define f2 (lambda (x) (* x 3)))",
")"
), tmp)
parser <- DocParser$new()
result <- parser$parse_file(tmp)
expect_equal(length(result$sections), 1)
expect_equal(result$sections[[1]]$name, "Math Helpers")
expect_equal(result$functions[["f1"]]$section, "Math Helpers")
expect_equal(result$functions[["f2"]]$section, "Math Helpers")
})
test_that("DocParser parses @note and @signature", {
thin()
tmp <- tempfile(fileext = ".arl")
on.exit(unlink(tmp))
writeLines(c(
"(module test-mod",
" (export my-fn)",
"",
" ;;' @signature (my-fn a b)",
" ;;' @description A function.",
" ;;' @note This is a note.",
" (define my-fn (lambda (a b) (+ a b)))",
")"
), tmp)
parser <- DocParser$new()
result <- parser$parse_file(tmp)
fn <- result$functions[["my-fn"]]
expect_equal(fn$note, "This is a note.")
expect_equal(fn$signature, "(my-fn a b)")
})
test_that("DocParser get_exports extracts module exports", {
thin()
tmp <- tempfile(fileext = ".arl")
on.exit(unlink(tmp))
writeLines(c(
"(module test-mod",
" (export foo bar baz)",
" (define foo 1)",
" (define bar 2)",
" (define baz 3)",
")"
), tmp)
parser <- DocParser$new()
exports <- parser$get_exports(tmp)
expect_true("foo" %in% exports)
expect_true("bar" %in% exports)
expect_true("baz" %in% exports)
})
test_that("DocParser handles defmacro definitions", {
thin()
tmp <- tempfile(fileext = ".arl")
on.exit(unlink(tmp))
writeLines(c(
"(module test-mod",
" (export my-macro)",
"",
" ;;' @description A test macro.",
" ;;' @examples",
" ;;' (my-macro x)",
" (defmacro my-macro (x) x)",
")"
), tmp)
parser <- DocParser$new()
result <- parser$parse_file(tmp)
expect_true("my-macro" %in% names(result$functions))
fn <- result$functions[["my-macro"]]
expect_equal(fn$description, "A test macro.")
expect_match(fn$examples, "my-macro x")
})
test_that("DocParser skips standalone sections without definitions", {
thin()
tmp <- tempfile(fileext = ".arl")
on.exit(unlink(tmp))
writeLines(c(
"(module test-mod",
" (export f1)",
"",
" ;;' @section Standalone Section",
" ;;' This section has prose but no following definition.",
"",
" ;;' @description A function.",
" (define f1 (lambda () 42))",
")"
), tmp)
parser <- DocParser$new()
result <- parser$parse_file(tmp)
# Standalone section should be recorded
expect_true(length(result$sections) >= 1)
# f1 should still be parsed
expect_true("f1" %in% names(result$functions))
})
test_that("parse_text parses annotations from string input", {
thin()
code <- "(module str-mod
(export add)
;;' @description Add two numbers together.
;;' @examples
;;' (add 1 2) ; => 3
(define add (lambda (a b) (+ a b)))
)"
parser <- DocParser$new()
result <- parser$parse_text(code)
expect_true("add" %in% names(result$functions))
fn <- result$functions[["add"]]
expect_equal(fn$description, "Add two numbers together.")
expect_match(fn$examples, "add 1 2")
expect_null(result$file)
})
test_that("string-input modules get annotation-based docs via eval_text", {
thin()
code <- "(module str-ann-mod
(export greet)
;;' @description Create a greeting message.
;;' @examples
;;' (greet \"world\") ; => \"hello, world\"
(define greet (lambda (name) (string-append \"hello, \" name)))
)"
engine <- make_engine()
env <- engine$get_env()
engine$eval_text(code, env = env)
engine$eval_text("(import str-ann-mod :refer :all)", env = env)
fn <- engine$eval_text("greet", env = env)
doc <- attr(fn, "arl_doc", exact = TRUE)
expect_false(is.null(doc))
expect_equal(doc$description, "Create a greeting message.")
expect_match(doc$examples, "greet")
})
test_that("DocParser parses @internal tag", {
thin()
tmp <- tempfile(fileext = ".arl")
on.exit(unlink(tmp))
writeLines(c(
"(module test-mod",
" (export-all)",
"",
" ;;' @internal",
" ;;' @description Internal helper.",
" (define __helper (lambda (x) x))",
"",
" ;;' @description Public function.",
" (define pub-fn (lambda (x) x))",
")"
), tmp)
parser <- DocParser$new()
result <- parser$parse_file(tmp)
expect_true(result$functions[["__helper"]]$internal)
expect_false(result$functions[["pub-fn"]]$internal)
})
test_that("DocParser parses @noeval tag", {
thin()
tmp <- tempfile(fileext = ".arl")
on.exit(unlink(tmp))
writeLines(c(
"(module test-mod",
" (export io-fn pure-fn)",
"",
" ;;' @noeval",
" ;;' @description Reads a file.",
" ;;' @examples",
" ;;' (io-fn \"test.txt\")",
" (define io-fn (lambda (path) path))",
"",
" ;;' @description Pure function.",
" ;;' @examples",
" ;;' (pure-fn 42)",
" (define pure-fn (lambda (x) x))",
")"
), tmp)
parser <- DocParser$new()
result <- parser$parse_file(tmp)
expect_true(result$functions[["io-fn"]]$noeval)
expect_false(result$functions[["pure-fn"]]$noeval)
})
test_that("annotation-based docs are available via compiler", {
thin()
tmp <- tempfile(fileext = ".arl")
on.exit(unlink(tmp))
writeLines(c(
"(module test-ann-mod",
" (export add)",
"",
" ;;' @description Add two numbers together.",
" ;;' @examples",
" ;;' (add 1 2) ; => 3",
" ;;' @seealso sub",
" (define add",
" (lambda (a b) (+ a b)))",
")"
), tmp)
engine <- make_engine()
env <- engine$get_env()
# Load the module from file (triggers annotation parsing in compiler)
engine$eval(engine$read(sprintf('(load "%s")', arl_path(tmp)))[[1]], env = env)
engine$eval(engine$read("(import test-ann-mod :refer :all)")[[1]], env = env)
# The function should have annotation-based arl_doc
fn <- engine$eval(engine$read("add")[[1]], env = env)
doc <- attr(fn, "arl_doc", exact = TRUE)
expect_false(is.null(doc))
expect_equal(doc$description, "Add two numbers together.")
expect_match(doc$examples, "add 1 2")
expect_equal(doc$seealso, "sub")
})
test_that("DocParser loads reference docs and filters by kind", {
thin()
parser <- DocParser$new()
docs_path <- system.file("reference-docs.dcf", package = "arl")
expect_true(nzchar(docs_path))
all_docs <- parser$load_reference_docs(docs_path)
expect_true(length(all_docs) > 0)
expect_true("if" %in% names(all_docs))
expect_true("eval" %in% names(all_docs))
expect_equal(all_docs[["if"]]$kind, "special-form")
builtins <- parser$load_builtins(docs_path)
expect_true("eval" %in% names(builtins))
expect_false("if" %in% names(builtins))
})
test_that("@param tags are parsed correctly", {
thin()
parser <- DocParser$new()
result <- parser$parse_text(paste(
"(module param-test",
" (export add)",
"",
" ;;' @description Add two numbers.",
" ;;' @param a First number",
" ;;' @param b Second number",
" (define add (lambda (a b) (+ a b)))",
")",
sep = "\n"
))
fn <- result$functions[["add"]]
expect_false(is.null(fn))
expect_equal(length(fn$params), 2)
expect_equal(fn$params[[1]]$name, "a")
expect_equal(fn$params[[1]]$description, "First number")
expect_equal(fn$params[[2]]$name, "b")
expect_equal(fn$params[[2]]$description, "Second number")
})
test_that("unknown @ tags emit a warning", {
thin()
parser <- DocParser$new()
expect_warning(
parser$parse_text(paste(
"(module warn-test",
" (export foo)",
"",
" ;;' @description A function.",
" ;;' @bogus something",
" (define foo (lambda () 1))",
")",
sep = "\n"
)),
"@bogus"
)
})
test_that("@param tags produce arl_doc$arguments via compiler", {
thin()
tmp <- tempfile(fileext = ".arl")
on.exit(unlink(tmp))
writeLines(c(
"(module param-compiler-test",
" (export add)",
"",
" ;;' @description Add two numbers.",
" ;;' @param a First number",
" ;;' @param b Second number",
" (define add",
" (lambda (a b) (+ a b)))",
")"
), tmp)
engine <- make_engine()
env <- engine$get_env()
engine$eval(engine$read(sprintf('(load "%s")', arl_path(tmp)))[[1]], env = env)
engine$eval(engine$read("(import param-compiler-test :refer :all)")[[1]], env = env)
fn <- engine$eval(engine$read("add")[[1]], env = env)
doc <- attr(fn, "arl_doc", exact = TRUE)
expect_false(is.null(doc))
expect_false(is.null(doc$arguments))
expect_match(doc$arguments, "a")
expect_match(doc$arguments, "First number")
expect_match(doc$arguments, "b")
expect_match(doc$arguments, "Second number")
})
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.