Expand description
Roxygen tag extraction and processing for R wrapper generation.
This module extracts roxygen2-style tags (e.g., @param, @examples) from Rust
doc comments and propagates them to generated R wrapper code.
§Usage
In Rust doc comments, use roxygen2 tags:
ⓘ
/// @param x A numeric input.
/// @return The squared value.
/// @examples
/// square(4)
#[miniextendr]
pub fn square(x: f64) -> f64 { x * x }§How doc lines carry over
Every reader here (explicit_roxygen_tags_from_attrs,
leading_prose_from_attrs, strip_roxygen_from_attrs) walks the same
lines (doc_lines) with the same roles (classify):
- Text before the first
@tagline is leading prose. It becomes@description(when the block has none) with its lines, blank lines and indentation kept, and it stays in rustdoc. Its[...]links lose their brackets unless the crate setsroxygen_prose_links = "keep"(ProseLinks). Under"keep", and in the text of every explicit tag but the code ones (CODE_TAGS), only a link roxygen2 can never resolve loses them (is_rustdoc_only_target). An inline link whose destination is such a Rust path ([text](crate::x)) keeps only its text under either setting (inline_rustdoc_destination); other[text](url)links stay. A block that renders no help page (its own@noRd, or a caller’sRdPage::Suppressed:noexport, a class without a page) loses every link in its prose and its non-code tag text, whatever the setting. - A tag runs from its
@tagline to the next one. A multi-line tag (@description,@return,@examples, …) keeps its blank lines (a roxygen2 paragraph break; a blank line in an example) and the indentation of its continuation lines, less the one space rustdoc’s///puts there. Trailing blank lines are dropped. roxygen2 markdown reads a continuation indented 4 or more spaces after a blank line as a code block, as rustdoc does. - A joined tag (
@title,@keywords,@concept,@aliases) folds its wrapped lines onto one line. - A single-line tag (
@export,@noRd,@rdname topic, …) ends at its line. Lines after it, up to the next tag, are rustdoc only. - Rustdoc keeps the leading prose and the rustdoc-only lines, and drops every tag with its text.
§R Package Configuration
For roxygen2 to process multiline tags correctly, add this to your DESCRIPTION file:
Roxygen: list(markdown = TRUE)Structs§
- DocLine 🔒
- One line of a string-literal doc attribute.
Enums§
- Line
Role 🔒 - What a doc line is to roxygen extraction and rustdoc stripping.
- Neutralize 🔒
- Which
[...]linkssanitize_roxygen_linksreduces to their text. - OpenTag 🔒
- How the tag that is open takes the lines that follow it.
- Prose
Links 🔒 - What leading prose does with
[...]link syntax on its way to@description: the crate’sroxygen_prose_linkssetting in[package.metadata.miniextendr]. - RdPage 🔒
- Whether a doc block’s roxygen text can reach a rendered help page, as far
as the caller knows, which decides what happens to its
[...]links.
Constants§
- CODE_
TAGS 🔒 - Tags whose text is R code or raw Rd, not markdown: their
[...]is never a link, soneutralize_tag_linksleaves them as written. - JOINED_
TAGS 🔒 - Tags whose wrapped continuation lines are joined back onto one line with a space instead of a newline: roxygen2 wants these on a single line (or reads them as one whitespace-separated list), but a long title, keyword list, concept, or alias list in a Rust doc comment can be wrapped by the author.
- METHOD_
ONLY_ 🔒TAGS - Roxygen tags that only make sense on individual methods, not on impl blocks.
- METHOD_
ONLY_ 🔒TAGS_ R6 - Tags stripped from impl-block docs for R6 classes — same as
METHOD_ONLY_TAGSminus"param", since roxygen2 8.0.0 inherits class-level@paramtags into all R6 methods and strips them from the rendered method entries automatically. This means/// @param breed …on an R6 impl block is valid and intentional, not a misplaced method-only tag. Keeping them avoids both the compile warning and the resulting(no documentation available)placeholder on subclass ctors. - MULTILINE_
TAGS 🔒 - Tags that allow multi-line content (continuation lines appended). All other tags are treated as single-line.
- ORDER_
AFTER_ 🔒TOPIC_ BLOCKS - The
@ordertag that sorts a generated block after every block without one, so the topic’s own block claims a merged page regardless of R file order (#1590). - PARAM_
FILLER_ 🔒MARKER - Prefix of a generated
@paramline in a standalone function’s wrapper (#' .__MX_PARAM_FILLER__ @param x (no documentation available)), for the wrapper registry to resolve when it writes the file (resolve_standalone_pagesinminiextendr-api/src/registry.rs, which spells the same prefix). Whether an author@rdname topicnames the function’s own page or its file’s stem page (the opt-in group page, #1289), and whether another function on the page documents the argument, is only known then. The registry keeps the line (without the prefix) when the function stays on its own or file-stem page and no other function there documents the argument, and drops it otherwise. roxygen2 keeps the later of two@paramlines for one name, so a filler written after the real description would replace it.
Functions§
- attrs_
have_ 🔒roxygen_ tag - Whether the doc comment in
attrshas the roxygen tagtag(matched ashas_roxygen_tagdoes), for a caller deciding a block’sRdPagebefore it reads the block’s tags. - class_
source_ 🔒tag - The
@sourceline for a class definition:Generated by miniextendr from Rust type `Type`, subject tosource_tag’s opt-in. - classify 🔒
- The role of each of
lines(doc_lines): the one rule the tag extractor, the leading-prose reader and the rustdoc strip share. - closes_
fence 🔒 - Whether
line, whose fence run isclose, ends the blockopenbegan: the same character, at least as long, and nothing after it. - common_
indent 🔒 - The leading whitespace every non-blank line of
linesstarts with. - describe_
in_ 🔒topic - The topic named by the tag list’s own
@describeIn <topic> <description>tag, if it has one. - doc_
conflict_ 🔒warnings - Check for conflicts between explicit
@title/@descriptiontags and implicit values. - doc_
lines 🔒 - The lines of every string-literal doc attribute in
attrs, in order. - explicit_
roxygen_ 🔒tags_ from_ attrs - Parse only the author-written
@taglines from doc attributes — no leading-prose promotion. - extract_
param_ 🔒names - Extract the set of parameter names declared via
@paramin a list of roxygen tags. - fence_
marker 🔒 - The fence run (3 or more
`or~) a CommonMark code-fence line starts with, after at most 3 spaces of indent. - find_
param_ 🔒tag - Like
param_documentedbut returns the matching tag itself rather than a bool, for callers that reuse the tag’s rendered text verbatim (S7 constructor param doc forwarding pushes the found tag as-is). - find_
tag_ 🔒value - Find the value of a specific roxygen tag (e.g., “title” for
@title ...). - formal_
name 🔒 - Extract the R parameter name from a single formal (e.g.
mode = c("a","b")→mode). Pair withsplit_r_formals, never a rawsplit(','). - format_
roxygen_ 🔒tags - Render roxygen tag lines as “#’ …” comment lines.
- forwarded_
member_ 🔒tag - Whether a method block without
\usage(an env methodType$method, a trait methodType$Trait$method) forwards the author tagtag: every tag but a bare@export. On such a block roxygen2’s namespace roclet turns a bare@exportintoexport("Type$method"), and R refuses to load the namespace (“undefined exports”). The member is reachable through its exported class, so exporting it is never valid. An@export <symbol>names its own target and is forwarded. - has_
export_ 🔒tag - Whether the author registers the function themselves, with
@exportor@exportS3Method(bare orpkg::generic), so a public standalone fn gets no automatic@export. Next to a delayed@exportS3Method pkg::generica bare@exportmakes roxygen2 write an eager registration as well, and the package fails to load whenpkgis only in Suggests (#1944). - has_
roxygen_ 🔒tag - Return true if the tag list contains a specific roxygen tag.
- implicit_
description_ 🔒from_ attrs - Extract the implicit description from doc attributes (second paragraph).
- implicit_
title_ 🔒from_ attrs - Extract the implicit title from doc attributes (first sentence, up to first
.or newline). - inherits_
params 🔒 - Whether the author’s tags inherit the parameter docs from another topic:
@inheritParams source, or@inherit sourcewhose field list includes params (roxygen2 inherits every field when none is listed). roxygen2 fills only the arguments the merged topic leaves undocumented, so a generated line would block the inheritance. - inline_
rustdoc_ 🔒destination - The end (past its
)) of the destination of an inline link[text](dest)starting at bytestart(just past the(), when that destination was written for rustdoc: a Rust path (is_rust_path) containing::, with an optional disambiguator prefix (strip_rustdoc_disambiguator), such ascrate::x,serde::Serializeorfn@Self::new. - is_
bare_ 🔒topic_ tag - A bare
@name/@rdname(topic written on the next///line, which roxygen2 accepts) takes exactly one continuation line as its topic. Once the tag has a topic it is single-line again, so following prose is not absorbed (seetest_rdname_stays_single_line). The wrapper registry decides page routing from the single#' @name <topic>line, so a dropped topic would silently change which page a function lands on. - is_
joined_ 🔒tag - Check if a tag’s continuation lines are joined with a space (see
JOINED_TAGS). - is_
multiline_ 🔒tag - Check if a tag name supports multi-line content.
- is_
rust_ 🔒path - Whether
destis a Rust path as an inline link destination writes it: identifiers joined by::, with an optional()or!suffix. A URL with a/,.,#,?or lone:never is one, even with a::in it (https://a.b/c::d). A bareFoocan be either, so the caller also asks for a::. - is_
rustdoc_ 🔒only_ target - Whether roxygen2 can never resolve the link target
target, so the link was written for rustdoc. - joins_
author_ 🔒topic - Whether the author’s tags put the block on a topic other than
default_page:@describeIn topic ..., or an@rdname topicthat names another page. The block then joins a topic whose own block (usually the author’s, often in R) documents the page, so generated lines that claim the page (a structural@param, the page\nameand title) must give way to it. - leading_
prose_ 🔒from_ attrs - Collect the leading prose of a doc comment (the lines before the first
@tag,LineRole::Prose) as roxygen@descriptiontext, its links treated per the crate’sProseLinkssetting (passed in, so the unit tests need no manifest;roxygen_tags_withpassesStripfor a block that renders no page). - method_
page 🔒 - The page a method’s block lands on: its
@describeIndestination (roxygen2 files a@describeInblock under the destination’s topic), its own@rdname, elsedefault_page(the class page). A companion block that must share the method’s page (the S3 generic block, whose class-qualified@nameis also the method’s alias) gets@rdnamethis. - method_
source_ 🔒tag - The
@sourceline for a class method:Generated by miniextendr from `Type::method`, subject tosource_tag’s opt-in. - neutralize_
tag_ 🔒links - An explicit tag with the
linksof its text neutralized: the rustdoc-only ones (Neutralize::RustdocOnly), or all of them in a block that renders no page (Neutralize::AllLinks). A code tag (CODE_TAGS) stays as written. - normalize_
for_ 🔒comparison - Normalize text for comparison: lowercase, collapse whitespace, strip trailing punctuation.
- orders_
after_ 🔒topic_ blocks - Whether a block with the author’s
tagsgets@order NaN(ORDER_AFTER_TOPIC_BLOCKS): it joins an author topic (joins_author_topicagainstdefault_page), the author did not order it with their own@order, and it renders a page (no@noRd). - param_
documented 🔒 - Returns
trueifnameis documented by any@paramtag intags. - param_
names_ 🔒token - Returns the
@paramname token (e.g.a,b,cin@param a,b,c desc) of a single tag, orNoneiftagisn’t an@paramtag. - params_
documented_ 🔒elsewhere - Returns
truewhen the author’s roxygen block takes its argument documentation from another block, so the generators must not add@paramlines for the arguments it leaves undocumented (#1590): - push_
fn_ 🔒param_ tags - Append the generated
@paramtags for a standalone function’s R parameters to the author’stags, and return the(doc_placeholder, rust_param)pair of every match_arg parameter that received the write-time placeholder (the resolver registry needs oneMX_MATCH_ARG_PARAM_DOCSentry each). - push_
order_ 🔒after_ topic_ blocks - Push
#' @order NaN(ORDER_AFTER_TOPIC_BLOCKS) whenorders_after_topic_blocksholds. - push_
rdname_ 🔒or_ default - Push
#' @rdname <topic>for a scaffolding block that follows its method: the method’s page (method_page: its@describeIndestination or own@rdname), elsedefault(the class page). - push_
roxygen_ 🔒tags - Push roxygen tag lines into a vector of R wrapper lines.
- push_
roxygen_ 🔒tags_ str - Like
push_roxygen_tagsbut takes&[&str]for filtered tag slices. - rdname_
value 🔒 - The topic named by the tag list’s own
@rdnametag, if it has one. - roxygen_
line 🔒 - One roxygen comment line:
#' text, or a bare#'for a blanktext(no trailing whitespace in the generated R). Render author tag text through this (or thepush_roxygen_tags*helpers), neverformat!("#' {}", ..). - roxygen_
tag_ 🔒name - Extract the tag name from a roxygen line (everything between
@and the first whitespace character). ReturnsNonefor lines that don’t start with a tag. - roxygen_
tags_ 🔒from_ attrs - Extract roxygen tag lines (starting with ‘@’) from Rust doc attributes.
- roxygen_
tags_ 🔒from_ attrs_ for_ r6_ method - Extract roxygen tags for an impl-block method.
- roxygen_
tags_ 🔒from_ attrs_ impl - Core implementation of roxygen tag extraction from
#[doc = "..."]attributes. - roxygen_
tags_ 🔒with roxygen_tags_from_attrs_implwith the crate’sProseLinkssetting passed in (testable without a manifest).- sanitize_
prose_ 🔒links sanitize_roxygen_linksover prose lines, one paragraph (the lines between blank lines) at a time, joined back with their line breaks.- sanitize_
roxygen_ 🔒links - Neutralize rustdoc intra-doc link syntax so prose is valid roxygen2 markdown.
- source_
tag 🔒 - The
@sourceprovenance line for a generated documentation block, orNoneunless the crate opted in with[package.metadata.miniextendr] source_tags = true(#1552). On a shared Rd page the tag collects one paragraph per function, so it is off by default; the# Generated from Rust fn … (file:line:col)comment above each wrapper stays as the navigation pointer. Every emitter goes through here (or the two specialisations below), so the knob has one implementation. - source_
tag_ 🔒with source_tagwith the crate setting passed in (testable without a manifest).- split_
r_ 🔒formals - Split an R formals/argument string on top-level commas only.
- strip_
method_ 🔒tags - Filter out method-specific roxygen tags from impl-block-level docs and emit compile warnings for each stripped tag.
- strip_
method_ 🔒tags_ r6 - Like
strip_method_tagsbut for R6 impl blocks. - strip_
roxygen_ 🔒from_ attrs - Strip roxygen tag lines from doc attributes, keeping only regular documentation.
- strip_
rustdoc_ 🔒disambiguator destwithout a rustdoc disambiguator prefix (fn@crate::x->crate::x). rustdoc’s prefixes are the item kinds below; any otherword@restis left whole and so failsis_rust_path.- strip_
tags_ 🔒in - Shared body of
strip_method_tagsandstrip_method_tags_r6: drop every tag whose name is inmethod_onlyand emit one warning const scope per dropped tag. The two public entry points differ only in the tag table. - tag_
documents_ 🔒param - Shared predicate: does this single
@paramtag documentname? - tag_
names 🔒 - Extract the set of tag names from a list of roxygen tag strings.