This documentation language has been developed as part of LDT, its main goal is to describe the API supplied by a file. It is strongly inspired by LDoc. Information given with this language is parsed by LDT and supply advanced features such as code completion and documentation view. Before diving into syntax, it is time to enumerate the underlying concepts, knowing them will enable you to write documentation more efficiently.
Concepts
Our documentation language introduce some concepts which may not be described explicitly in Lua, but help to defined the contract between the library provider and the user.
Type
This is the most important one. A compound type is a set of values, accessible through fields. It is not a primitive type like string
, number
or nil
. Theses fields can point to functions, primitive values or other compound types.
It is the way to explicitly ensure the structure of a Lua table.
Module
It is requireable entity - you can use the require
function on it-
This concept allow you to express :
- which type will be return by the
require
function for your module, - which new global variables will be available after your module was loaded.
Most of the time people refer to the returned type instance as module.
Field
It is always a field of a type. This is the way to ensure the presence of a value in a table which implement a type.
Function
It is a special kind of field which can have parameters and return values, just as Lua functions. Both parameters and returned values can be typed. This concept allow to express a contract about which parameters suit a function and expected outputs.
Global
When a module is required, it could modify the global environment. To handle those cases, the predefined type global is available. It is a reserved type which will be available everywhere, enabling you to attach fields and functions to it. This is a way to express the creation of new global variables when a module is loaded.
List
A list is a sequence of values stored in a table under numeric indexes.
Map
A map is a set of key/value pairs stored in a table.
Type Extending
When a sub-type extend a super-type all super-type fields and functions are available from the sub-type.
Type references
It is often needed to refer to a type. There is a notation for this. It is based on types. So if you want to type a field, a function parameter or returned value, they are several kinds of references available.
Primitive references
Refer to Lua primitive types, it is the type prefixed with #
.
#boolean
#nil
#number
#string
#table
Internal references
Enables to refer to types defined in current module, it is type name prefixed with #
.
#typename
will refer to type typename defined in current module.
External references
Enables to refer to a type defined in another module, it is targeted module name followed by internal reference which could be used in targeted module.
modulename#typename
will refer to type typename defined in module modulename.modulename#modulename
will refer to type modulename returned in module modulename.
Structure types
Enables to describe list and map structures.
#list<#valuetype>
where #valuetype is the reference to the type contained in the list.#map<#keyvalue,#valuetype>
where #valuetype is the reference to the type contained in the map and #keyvalue the reference of the type used to index map values.
Comments
You could describe explicitly all file API just with our documentation language. But LDT is able to guess quite a lot of this information from code. (see samples)
Special comments
First of all, only special comments are parsed as part of Lua documentation. To mark your comment as special, just start it with ---
.
Special comments can contain a short and an long description. The short description start at the beginning of the comment and continue till .
or ?
. The long description is the text coming after. By the way, Markdown is supported in all descriptions.
Special comments are handled only if they describe a concept.
Note: All leading -
's in special comments are trimmed.
--------------------------------------------------------------------------------
-- Short description.
-- Long _markdown_ description
Special comment with trimmed first line
Note: _markdown_
is supposed to be interpreted by Markdown.
---
-- Short description.
-- Long description
Special comment composed of short comments format
--[[-
Short description.
Long description
]]
Special comment with long comment format
--- Short description. Long description
Special comment in one line
Type comment block
A type comment block is a special comment with a type declaration with @type
key word followed by desired type name.
|
Sample of type declaration |
Since 1.2: @list
and @map
tags. The list and map tags allow to describe if the type is used as a list or a map of elements.
|
|
Sample of type declaration used as a list. |
Sample of type declaration used as a map. |
Since 1.2: @extends
tag. The extend tag allow to define that current type is extending the given super-type.
|
Sample of a type extending a super-type. |
Module comment block
Denoted by @module
keyword and followed by a module name, a module is the type described in a file. This is why there should be only one module declaration per file. Here is the simplest way to declare a module.
|
Sample of module declaration. |
When a module is declared, a type with its name is automatically created and returned. So, the following is equivalent to first module sample.
|
Sample of verbose module declaration |
Note: We used #modulename
to refer to a declared type, if you want to know more about it refer to type reference section.
In previous sample, you may wonder in which case it could be of any use to return manually a type for a module. It is useful when you want to return a type different from the one automatically created.
|
Sample of module returning custom type |
Note: We used #string
to refer to a primitive type.
Since 1.2: @list
and @map
tags. The list and map tags allow to describe if the module is used as a list or a map of elements.
|
|
Sample of module declaration used as a list. |
Sample of module declaration used as a map. |
Since 1.2: @extends
tag. The extend tag allow to define that current module is extending the given super-type.
|
Sample of a module extending a super-type. |
Field comment block
The field block represents a field of a type. It is possible to declare one with @field
keyword followed by optional type reference, field name and optional description.
There are two ways of defining a field, in its parent block type or in a separate documentation block where you have to mention field parent type.
|
|
Sample of field declaration in parent type block |
Sample of field declaration in dedicated block |
Function comment block
The function comment block has to be attached to a type. Its keyword is @function
. A function can have several parameters denoted by keyword @param
, they can be optionally typed with a type reference and have an optional descriptions. Several @return
cases are also possible, but LDT inference -which is used for code assistance- only handles the first one. As Lua functions allow to return several values at once, it is possible to define several returned values per @return
markup. Returned values can be optionally typed using a type reference.
Note: If the first @param
is called self, LDT will show completion proposal without this parameter but using :
invocation operator.
|
Sample of function declaration |
Note: It is also possible to document function for types which name contains "."
.
|
Sample of function declaration related to a type which name contains |
Since 1.2: @callof
tag. In Lua a table can be call using the metatable keyword __call. To set a type callable just add @callof #typename
in the function behind the __call metamethod. The first param should be self and of the type given to callof.
|
Sample of function declaration related |
Global comment block
To declare a function or a field with a type reference as global, you just have to attach it to the global
type.
|
Sample of global field and function |
Samples
Simple module sample
|
|
|
Full Documentation sample |
Minimal Documentation |
Documentation Only |
Object-oriented sample
|
|
Full Documentation Sample |
Minimal Documentation |
Callof sample
The @callof tag is only available since the v1.2
|
|
Circle module sample |
Usage of the circle module |
List and Map samples
The @list and @map tags are only available since the v1.2
|
|
Sample using a list |
Sample using a map |
Extends sample
The @extends tag is only available since the v1.2
|
My extended math module sample |
Short references
It is way to reference a types and their fields in a textual description. You just have to surround a type reference with @{}
. You can reference a types and their fields, functions are handled as a specific type of fields.
- Reference to types
@{#typename}
will refer to type typename defined in current module.@{modulename}
will refer to module named modulename.@{modulename#typename}
will refer to type typename defined in module modulename.
- Reference to fields
@{#typename.fieldname}
will refer to fieldname which could be a function or field attached to type typename defined in current module.@{modulename#typename.fieldname}
will refer to fieldname which could be a function or field attached to type typename defined in modulename module.
Note: So far, there are no short references for globals.
--------------------------------------------------------------------------------
-- Short description. Long description with a reference to @{io#io.flush}.
--
-- @function [parent=#typename] functionname
Sample of type reference in a description
Ambiguity
It is possible to use dots in type names, but then it becomes hard to differentiate type name from field name. Let's explained the default behavior:
- Everything before # is module name
- Everything between # and last dot is type name.
- Everything after last dot is field name
So in @{module.name#type.name.fieldname}
will refer to field fieldname of type named type.name from module module.name. Well, but what happens when we simply want to reference a type name containing dots? It is possible to surround type name with parenthesis to remove ambiguity.
@{modulenamed#(type.name).fieldname}
will refer to field named fieldname from type named type.name defined in module named modulename.@{modulenamed#(type.name)}
will refer to type named type.name from module named modulename@{#(type.name)}
will refer to type named type.name.
Limitations
Markdown
Markdown allows reusable element. As each description is parsed separately, you cannot reuse an element from another description.
Parsing
We use Metalua to parse comments, and it can't parse only comments. So if you write a documentation only file, ensure it contains a least a valid statement. Most of the time we use, return nil
at end of file.
Tips
Usage
When you have a comment block related to a concept, you can give one or several samples of how it should be used by using the @usage
keyword.
--------------------------------------------------------------------------------
-- Module short description.
-- Module long description
--
-- @module modulename
-- @usage local modulename = require 'modulename'
-- @usage require('modulename')
Sample of module declaration with usage markup.