Doc comments
Document members with doc { } and whole files with rootdoc { }, and shot check makes sure every code name you put in backticks still exists.
A doc sits right above what it documents and shows up wherever that is read: in shot outline, shot api and shot map, and as comments in the compiled Luau. Named sections inside a doc hold a system's rules, how to extend it and examples.
Doc
doc { } documents the thing directly below it. One line or several:
doc { The name shown above the player }
public Name : string
doc {
Moves the player to a spawn point.
Yields until the character exists.
}
public RespawnAsync(spawn : SpawnLocation)
...
endIt works above:
- class fields, constructors, methods and static functions,
- module properties and functions,
- a public type or internal type in Types.shot.
doc { Why a player's coins changed }
public type Reason = "Pickup" | "Shop"Rootdoc
rootdoc { } documents the whole file. One per file ("a file can only have one rootdoc"). Put it above the declaration:
types script.Parent.Types
rootdoc {
Cleanup stores connections and callbacks.
Cleanup:Run() disconnects them all and runs the callbacks.
}
class Cleanup = {
...
}A doc { } above the declaration counts as the rootdoc too, which is the natural way to document a func (it has no members). A file can't have both.
Sections
A doc or rootdoc can hold named sections after its summary:
rootdoc {
The coins one player owns. `Bank` keeps one for each player in `Bank.Wallets`.
section Rules {
A wallet works like a bank account that only the server can write to. Its whole API is
`Wallet.new`, `Wallet.Empty`, `Wallet.Coins` and `Wallet.Add`. There is no Spend or Set: a
purchase is an Add with a negative amount, made by the server after it has checked the price.
Only the server changes coins. A client asks through `BuyRequest` and the server decides,
because a change made on the client is never saved and would let a player give themselves coins.
Every change carries a `Reason`, and a reason that isn't in that union doesn't compile:
"TypeError: Expected this to be '"Pickup" | "Shop"', but got '"Quest"'; none of the union
options are compatible". Add the value to `Reason` before writing the code that earns with it.
}
section Extend {
- a new way to earn coins: add its name to `Reason`, then call `Wallet.Add` with it on the server.
}
}
class Wallet = { ... }- The text before the first section is the summary; its first sentence is what
shot mapandshot outlineprint. section Name { }starts on its own line; braces inside it pair up like in any doc. Each name once per doc ("a doc can only have one section Rules").- Three names mean something to
shot; any other name is fine and kept for readers:
section Rules | what a reader needs to use the system right without opening its files, in full sentences (see WRITING RULES below). shot outline, shot api and shot overview print it in full. |
section Extend | how to add to the system: which union to grow, which catalog to register in, which event to subscribe to. |
section Examples | how to call it, as code. Works on member docs too. |
An Examples section on a member's doc:
doc {
Adds coins to a player's wallet, as a pickup.
section Examples {
Bank.Give(player, 25)
}
}
function Give(player : Player, amount : number)Give every system's entry file (the folder's same-named file) Rules and Extend sections when it has rules like that, so shot api, shot outline and shot overview print them and a reader doesn't have to find them in the source.
Writing rules
Write the Rules of every shared module (a signal, a cleanup list, a value container, a scheduler) and of every system's entry file for a reader who will not open the file. In this order, in full sentences:
- 1. What it works like: something the reader already knows ("works like a bank account").
- 2. Its whole API, and what it doesn't have ("There is no Spend or Set"), so nobody looks for it.
- 3. Every behaviour a reader would get wrong, one paragraph each: what happens, why, what goes wrong when they don't know it, and the exact error it raises.
- 4. Contracts with other systems: what must happen in what order, which side is in charge, Roblox gotchas.
A member's own fact goes in its doc's first sentence: shot outline prints that sentence on the member's line.
Code names in backticks
Write a name from the code in backticks, as the Rules above do: Bank.Give, module.Count, self.Coins, Reason, BuyRequest (an instance file), Market/MarketClient.Open, @shot.Wallet. shot check makes sure each one still exists, so a doc can't keep pointing at something renamed or removed:
Wallet/Wallet.shot:11:67 `Wallet.Addd` in this doc: Wallet has no Addd (renamed or removed?)
Wallet/Wallet.shot:4:30 `Nope.Thing` in this doc: Nope names nothing in this project, Roblox or Luau (renamed or removed?)- A name may be a declaration (class, module, func, split module) and its members down the chain (
Market.Server.Startfollows the split to MarketServer), a type, an instance file, a folder, a local of the file, a parameter or local of the documented member, a member of the documented class or module, or a Roblox or Luau name (Players,RemoteEvent:FireClient,table.insert). moduleworks in a module's docs andselfin a class's; a trailing () is fine (Market.Server.Start()).- Once a chain reaches a field, property or method, the rest is not checked (
self.Changed:Fire). - Backticks around anything that isn't a plain name (
"Pickup",local x = 1,{string}) are only formatting and are not checked. Event names are strings: write them in quotes, "CoinsGiven".
Writing them
docandrootdocmust be the first word on their line.- Braces inside are fine as long as they pair up:
doc { Returns {Wallet} sorted by coins }works. - Blank lines between a doc and its member are allowed.
- A doc must come before what it documents. Below the declaration, outside any class or module, it is an error: "doc must sit above a member inside a class or module".
- An unclosed
doc {runs on to the next unmatched}, so the error usually reads "module Open is never closed with }" (or "doc { is never closed with }" when no } is left in the file).
Where they show up
shot outline: one line per member, its signature then "-- " and its doc's first sentence (left out when it only repeats the signature); a doc's Rules and Extend in full, other sections folded to one line ("-- section Examples (3 lines, --full)");--fullprints every doc whole, above its member. The rootdoc's first sentence and sections go under the file's header.shot api <folder>: the entry file's Rules and Extend sections under the folder line.shot map: the first line of each file's rootdoc, after the names of its sections ([Rules, Extend]).- The compiled Luau:
--[[$doc ... ]]and--[[$rootdoc ... ]]comments, and comments on the types in the Types module.
