How to write inline comments, rustdoc, and module documentation in the Biome codebase. The audience is Biome developers reading the source, not end users. Use whenever writing or editing `//` comments, `///` item docs, or `//!` module docs — including comments added incidentally while fixing bugs or implementing features.
79
100%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Passed
No findings from the security scan
Comments and doc comments in this repository are read by contributors, months or years after they were written, with none of the context you have right now. This skill defines who that reader is, what each kind of comment is for, and which patterns are banned.
Scope boundary: rustdoc inside declare_lint_rule! / declare_assist_rule!
blocks is end-user documentation — it is generated into the website. This skill
does not apply there; see lint-rule-development.
Write for a Biome contributor who is competent in Rust but has no access to your current context: not this conversation, not the pull request, not the issue, not the diff. They see only the repository at HEAD.
Two consequences follow directly:
| Kind | Job | Contains |
|---|---|---|
//! module docs | Explanation | Why the module exists, core concepts and terminology, how the pieces relate, design rationale |
/// item docs | Reference | The contract: behavior, inputs and outputs, invariants, panics, errors. Neutral and factual |
// inline comments | Rationale | Only what the code cannot say: constraints, workarounds (with issue links), non-obvious coupling, why the obvious alternative is wrong |
Do not mix the jobs. Implementation details do not belong in /// docs — put
them as // comments inside the body. The contract does not belong scattered
across inline comments — put it on the item.
Before writing any comment, ask: does this state something the reader cannot recover from the code itself?
When editing later, the same test applies in reverse: a comment that no longer passes it should be deleted, not left to rot.
Narrating the next line. Delete these on sight:
// Increment the generation counter
generation += 1;Change-history narration. Rewrite as present-tense rationale:
// BAD: We now intern types instead of cloning them.
// GOOD: Interning avoids cloning these types on every lookup.Reviewer-addressed justification. Move the argument to the PR:
// BAD: This correctly handles the overload case from the bug report.
// GOOD: Overloads are matched by arity before parameter types, so a
// partial-arity call cannot select the wrong candidate.Restated rustdoc. A /// doc that rewords the item name says nothing:
// BAD:
/// Handles the type inference.
fn infer_types(...)
// GOOD:
/// Infers the type of `expr` in the scope of `module`, returning
/// `TypeData::Unknown` when the expression references an unresolved import.
fn infer_types(...)Vague hedging. "Some cases", "various reasons", "handles edge cases", "etc." — either name them or drop the sentence.
Ad-hoc section banners (// ----- helpers -----, // ==== TYPES ====).
For grouping in long files, use the region comment pattern below instead.
Long files group related items with paired region markers:
// #region FILE-LEVEL METHODS
...
// #endregionThis is an established convention across the codebase (biome_service,
biome_module_graph, biome_rowan, the parsers). The Workspace trait in
crates/biome_service/src/workspace.rs
uses it to group its methods (PROJECT-LEVEL METHODS, FILE-LEVEL METHODS,
SEARCH-RELATED METHODS). Editors fold on these markers, which is the point:
they exist for navigation, not documentation.
Rules:
// #region has a matching // #endregion. An unpaired marker breaks
editor folding silently.Shared helpers) or anchored to a function (#region parse_thematic_break_parts)
when the region holds one entry point and its private support code.impl/trait blocks
long enough that folding helps. A file that fits on two screens does not
need them.The //! module docs at the top of
crates/biome_service/src/workspace.rs
show the target register. They define a term the rest of the module depends on
("open documents") and give its meaning in both the LSP and CLI contexts; they
explain a design decision the signatures alone would make confusing (the
workspace is stateful, yet every method takes &self, because the trait must
be thread-safe and caching happens internally); and they state the error
philosophy once, at the top, instead of repeating it on every method.
Everything is present tense; nothing mentions how the design evolved or
defends a change.
After completing any task that touched comments, re-read only the comments in your diff, in isolation from the code changes:
Fix or delete what fails. Deletion is the default; a missing comment is cheaper than a misleading one.
c50a853
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.