Doc Comments
safeguard doc builds a library's API reference from its declarations and the comments on them. This page is the convention it reads: which comments document what, how they are written, and which declarations appear. The std API reference is built the same way from std's sources.
Where a doc comment goes
A doc comment is a run of comment lines directly above a declaration — no blank line between — or a comment on the declaration's own line, after it:
/// A point with integer coordinates.
///
/// Created with [Point::new]; compare with [Point::eq].
struct Point {
int x; ///< horizontal coordinate
int y; ///< vertical coordinate
/// A point at (`x`, `y`).
static struct Point new(int x, int y);
/// Squared distance from the origin.
long long norm2() const;
};
/** Kinds of shape [shape_area] knows. */
enum ShapeKind {
SHAPE_SQUARE = 1, ///< four equal sides
SHAPE_CIRCLE, ///< `s` is the radius
};
| Form | Documents |
|---|---|
/// text (lines) |
the declaration below |
/** text */ |
the declaration below |
int x; ///< text or int x; // text |
the declaration on the same line — what fields, enumerators and short methods use; comment-only lines below it, aligned with it, continue it |
//! text |
the file itself (its module page) |
// text (lines) |
the declaration below — std's convention (see below) |
A block with any /// or /** line uses only those lines, so ordinary // notes can sit beside a doc comment without being published. Both a leading comment and a trailing one on the same declaration are shown, the leading one first.
Everything that can be declared is documented: namespaces' contents (shown with their path, geo::Point), structs and unions with their fields and methods, enums with their enumerators, traits with their required methods, functions (generic ones with their generic<T: Bound> parameters), macros, constants and globals, type aliases and newtypes.
Declared in a header, defined elsewhere. A method declared in its struct and defined out of line (long long Point::norm2() const { … }), or a function declared in a header and defined in a .sc file, is one item: the header's comment wins, the definition's is used when the header has none, and the page links to both locations.
Module docs
Each header is a module, nested by directory: include/geo/shapes.h is geo::shapes. Its doc is its //! lines:
#pragma once
//! Points and vectors in the plane.
//!
//! ```c
//! struct Point p = Point::new(3, 4);
//! ```
Without //! lines, the file's first comment block is the module's doc when something other than a declaration follows it (a blank line, #include, #pragma) — the layout every std header uses. A license header (Copyright …, SPDX-License-Identifier) is skipped. The package's README.md (or [package] readme) is the front page.
Markdown
Doc comments are Markdown — CommonMark with GitHub's tables, strikethrough and autolinks. Raw HTML is shown as text, not inserted. Headings in a doc comment sit below the page's own, so # Examples is a sub-heading of the item.
Code examples
Fenced code blocks are highlighted; a fence without a language is SafeC:
/// Area of a shape of `kind` and size `s`, rounded down.
///
/// # Examples
///
/// ```
/// long long a = geo::shape_area(SHAPE_SQUARE, 3); // 9
/// ```
long long shape_area(enum ShapeKind kind, int s);
Examples are shown, not compiled: put the ones that must keep working in tests/.
Intra-doc links
A name in square brackets links to that item's page:
| Write | Links to |
|---|---|
[Point], [`Point`] |
the struct Point |
[Point::norm2], [Point::norm2()] |
the method on Point's page (#method.norm2) |
[geo::Point] |
the same, by its namespace path |
[shape_area] |
the function |
[SHAPE_CIRCLE], [ShapeKind::SHAPE_CIRCLE] |
the enumerator |
[geo::shapes] |
a module |
[String], [std::Vec::push] |
items in std — links into the std API reference |
[the norm](Point::norm2) |
any link text, with an item as the target |
A name that doesn't resolve stays plain text. In signatures, every type and function name that resolves is linked the same way.
std's plain comments
std documents its API with ordinary // comments directly above or beside declarations, written as prose rather than Markdown. The reference reads them too, with one adjustment: a run of lines indented by two or more spaces, after a blank comment line or a line ending in :, is a code example:
// Copies 'len' elements starting at 'items'.
generic<T>
struct Vec<T> Vec::from_arr(const &T items, unsigned long len);
// SafeC Standard Library — Vec<T> (dynamic array)
//
// struct Vec<int> v = std::Vec::new();
// v.push(3);
A separator line — // ── Section ──, // -----, // ===== — ends a comment block: it and the lines above it are not part of the declaration's doc. New code should prefer ///: it is unambiguous Markdown, and a /// block leaves nearby // notes out of the docs.
What is documented
- In a package with headers, the reference is its headers (
include/andsrc/): what a dependent can#include. Declarations only in.scfiles are implementation. A package without headers documents its.scfiles. staticfunctions and globals are private to their file and left out.- Names that start or end with
_(std's type-erased_raw_helpers) are hidden, and so is any declaration whose doc comment has a line that is just@hidden(or#[doc(hidden)]). - An
externdeclaration of a C function is shown only when it has a doc comment.
safeguard doc --private shows the hidden items too.