Docstrings
Shape docstrings are first-class language metadata. They are parsed from /// comments, attached directly to AST nodes, stored in structured form, and consumed by the LSP, package registry, and stdlib metadata.
Design Rules
Section titled “Design Rules”- Only
///creates documentation. /** ... */is not documentation.- Doc comments attach to the immediately following AST item or member.
- Documentation is structured data first and markdown second.
- Cross-links must use fully qualified targets.
- Invalid docs are diagnosed instead of guessed.
What Can Be Documented
Section titled “What Can Be Documented”/// doc comments can attach to:
- modules, functions, foreign functions, builtin declarations
- annotations, type aliases
- structs and struct fields
- enums and enum variants
- interfaces and interface members
- traits and trait members
- associated types, type parameters
Shape does not use parent-owned child tags. If a field, variant, method, or type parameter needs docs, document that declaration directly.
Basic Form
Section titled “Basic Form”/// Compute the spread between the maximum and minimum value.////// @param series Input series./// @returns max(series) - min(series).pub fn spread(series: Vec<number>) -> number { series.max() - series.min()}The first prose paragraph becomes the summary. Additional prose remains part of the markdown body.
Supported Tags
Section titled “Supported Tags”| Tag | Syntax | Purpose |
|---|---|---|
@module | @module <fully-qualified-module> | Declare module-level docs |
@typeparam | @typeparam <name> <description> | Document a type parameter |
@param | @param <name> <description> | Document a function parameter |
@returns | @returns <description> | Document the return value |
@throws | @throws <description> | Document possible errors |
@deprecated | @deprecated <description> | Mark as deprecated |
@requires | @requires <description> | Document capability requirements |
@since | @since <description> | Version when introduced |
@see | @see <fully-qualified-target> | Cross-reference another item |
@link | @link <fully-qualified-target> [label] | Cross-reference with custom label |
@note | @note <description> | Additional notes |
@example | @example (followed by code) | Usage example |
/// Compute a Hull moving average.////// @param series Input series./// @param period Window size./// @returns Hull moving average series./// @see std::finance::indicators::moving_averages::wma/// @example/// let value = hma(close, 21)pub fn hma(series, period) { // ...}Type Parameters, Fields, Variants, and Members
Section titled “Type Parameters, Fields, Variants, and Members”Type parameters have their own doc blocks:
fn identity< /// Element type preserved by the function. T>(value: T) -> T { value}Struct fields have their own doc blocks:
pub type Candle { /// Opening price. open: number, /// Highest traded price in the interval. high: number,}Trait and interface members can also be documented directly:
/// Convert a value into a human-readable string.trait Display { /// Render `self` as text. fn display() -> string;}Fully Qualified Cross-Links
Section titled “Fully Qualified Cross-Links”Cross-links are explicit and semantic.
Use @see for a simple reference:
/// @see std::core::utils::rolling::rolling_meanUse @link when you want a custom label:
/// @link std::finance::indicators::volatility::atr ATR helperRules:
- Targets must be fully qualified.
- Annotation targets use their canonical symbol path, with the final segment written as
@name. - Relative links are intentionally unsupported.
- Unresolved links are diagnosed by the LSP.
LSP Features
Section titled “LSP Features”The LSP uses the AST doc model directly.
Hover shows the declaration signature, markdown body text, structured sections (parameters, returns, notes, examples), and resolved @see/@link references.
Signature Help
Section titled “Signature Help”Signature help uses @param text for parameter documentation and the doc summary for function-level help.
Completion Inside Doc Comments
Section titled “Completion Inside Doc Comments”Inside /// blocks, the LSP offers completion for:
- tag names after
@ - parameter names inside
@param - type parameter names inside
@typeparam - fully qualified symbol targets inside
@seeand@link
This is semantic completion, not text matching. Parameter and type-parameter suggestions come from the attached AST owner.
Code Action: Generate Doc Comment
Section titled “Code Action: Generate Doc Comment”The Generate doc comment code action inserts a structured stub above supported declarations. The generated stub includes a summary placeholder, @typeparam entries when generics exist, @param entries for callable parameters, and @returns when the declaration can return a value.
Validation and Diagnostics
Section titled “Validation and Diagnostics”Shape validates doc comments semantically. The LSP reports:
- Unknown tag names
- Duplicate singleton tags (
@returns,@deprecated,@since,@module) - Duplicate
@paramor@typeparamentries @paramnames that do not exist on the callable@typeparamnames that do not exist on the item@returnson non-callable or void-only targets- Non-fully-qualified
@seeor@linktargets - Unresolved link targets
- Empty tags that require content
- Orphan doc comments without a valid AST target
Diagnostics are span-precise — the LSP highlights the exact tag or link target that is invalid.
Writing Good Docstrings
Section titled “Writing Good Docstrings”Good Shape docstrings should explain:
- Semantic meaning
- Invariants or edge cases
- Units and coordinate systems when relevant
- Availability or capability requirements
- Relationships to nearby APIs through
@seeand@link
Good docstrings should not duplicate:
- Obvious type information already present in the signature
- Syntax already visible in the declaration
Full Example
Section titled “Full Example”/// Score values for a custom review workflow.////// @typeparam T Value type evaluated by the scorer.trait Scorer<T> { /// Compute a score for the input value. /// /// @param value Value to score. /// @returns Numeric score used by downstream decisions. fn score(value: T) -> number;
/// Return whether the input value passes the requested threshold. /// /// @param value Value to evaluate. /// @param min_score Minimum score required for acceptance. /// @returns `true` when the value meets the threshold. fn passes(value: T, min_score: number) -> bool;}First-Class Data
Section titled “First-Class Data”Docstrings are not an editor-only feature. They exist as structured AST data (comment body, ordered tags, typed tag kinds, attachment target metadata, tag and link spans) and are embedded in compiled .shapec package bundles. This makes them available to the package registry for rendering API documentation pages.