Skip to main content
Jump to: navigation, search

Difference between revisions of "LDT/User Area/Documentation Language"

< LDT
 
(13 intermediate revisions by 3 users not shown)
Line 37: Line 37:
 
*the global is created dynamically during runtime : in this case, it's very difficult to know where the global variable must be available in autocompletion.  
 
*the global is created dynamically during runtime : in this case, it's very difficult to know where the global variable must be available in autocompletion.  
  
The first case (preloaded global var) is managed by the use of a global.lua file in [[Koneki/LDT/User_Area/Execution_Environment_file_format#Execution_Environment | execution environment]] which must contains all preloaded global variables. (Those global vars will always be available in autocompletion)
+
The first case (preloaded global var) is managed by the use of a global.lua file in [[LDT/User_Area/Execution_Environment_file_format#Execution_Environment | execution environment]] which must contains all preloaded global variables. (Those global vars will always be available in autocompletion)
  
 
The other case, LDT lets you choose between (customizable in ''Preference/Lua''):
 
The other case, LDT lets you choose between (customizable in ''Preference/Lua''):
Line 51: Line 51:
  
 
A '''map''' is a set of  key/value pairs stored in a table.
 
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 ==
 
== Type references ==
Line 78: Line 82:
 
* <code>modulename#typename</code> will refer to type ''typename'' defined in module ''modulename''.
 
* <code>modulename#typename</code> will refer to type ''typename'' defined in module ''modulename''.
 
* <code>modulename#modulename</code> will refer to type ''modulename'' returned in module ''modulename''.
 
* <code>modulename#modulename</code> will refer to type ''modulename'' returned in module ''modulename''.
 +
 +
== Structure types ==
 +
 +
Enables to describe list and map structures.
 +
 +
* <code>#list<#valuetype></code> where ''#valuetype'' is the reference to the type contained in the list.
 +
* <code>#map<#keyvalue,#valuetype></code> 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 =
 
= Comments =
Line 90: Line 101:
 
Special comments can contain a short and an long description. The ''short description'' start at the beginning of the comment and continue till <code>.</code> or <code>?</code>. The ''long description'' is the text coming after. By the way, [http://en.wikipedia.org/wiki/Markdown Markdown]  is supported in ''all'' descriptions.
 
Special comments can contain a short and an long description. The ''short description'' start at the beginning of the comment and continue till <code>.</code> or <code>?</code>. The ''long description'' is the text coming after. By the way, [http://en.wikipedia.org/wiki/Markdown Markdown]  is supported in ''all'' descriptions.
  
Special comments are handled '''only if they describe a [[Koneki/LDT/Technical_Documentation/Documentation_Language#Concepts|concept]]'''.
+
Special comments are handled '''only if they describe a [[LDT/Technical_Documentation/Documentation_Language#Concepts|concept]]'''.
  
 
'''Note''':  All leading <code>-</code>'s in special comments are trimmed.
 
'''Note''':  All leading <code>-</code>'s in special comments are trimmed.
 
 
<source lang="lua">
 
<source lang="lua">
 
--------------------------------------------------------------------------------
 
--------------------------------------------------------------------------------
Line 99: Line 109:
 
-- Long _markdown_ description
 
-- Long _markdown_ description
 
</source>
 
</source>
 +
 
<center><small>Special comment with trimmed first line </small></center>
 
<center><small>Special comment with trimmed first line </small></center>
 +
 
'''Note''': <code>_markdown_</code> is supposed to be interpreted by [http://en.wikipedia.org/wiki/Markdown Markdown].
 
'''Note''': <code>_markdown_</code> is supposed to be interpreted by [http://en.wikipedia.org/wiki/Markdown Markdown].
  
Line 122: Line 134:
 
== Type comment block ==
 
== Type comment block ==
  
A [[Koneki/LDT/Technical_Documentation/Documentation_Language#Type|type]] comment block is a ''special comment'' with a type declaration with <code>@type</code> key word followed by desired type name.<br/>
+
A [[LDT/User_Area/Documentation_Language#Type|type]] comment block is a ''special comment'' with a type declaration with <code>@type</code> key word followed by desired type name.<br/>
  
 +
{|  border="1" cellspacing="0" valign="top"
 +
|valign="top"|
 
<source lang="lua">
 
<source lang="lua">
 
--------------------------------------------------------------------------------
 
--------------------------------------------------------------------------------
Line 131: Line 145:
 
-- @type typename
 
-- @type typename
 
</source>
 
</source>
<center><small>Sample of type declaration</small></center>
+
|-
 +
|<center><small>Sample of type declaration</small></center>
 +
|}
  
'''Since 1.2''': <code>@list</code> and <code>@map</code> tags. The '''list''' and '''map''' tags allow to describe if the type is used as a [[Koneki/LDT/Technical_Documentation/Documentation_Language#List|list]] or a [[Koneki/LDT/Technical_Documentation/Documentation_Language#Map|map]] of elements.
+
'''Since 1.2''': <code>@list</code> and <code>@map</code> tags. The '''list''' and '''map''' tags allow to describe if the type is used as a [[LDT/User_Area/Documentation_Language#List|list]] or a [[LDT/User_Area/Documentation_Language#Map|map]] of elements.
  
 
{|  border="1" cellspacing="0" valign="top"
 
{|  border="1" cellspacing="0" valign="top"
 
|valign="top"|
 
|valign="top"|
 
 
<source lang="lua">
 
<source lang="lua">
 
--------------------------------------------------------------------------------
 
--------------------------------------------------------------------------------
Line 158: Line 173:
 
|<center><small>Sample of type declaration used as a list.</small></center>
 
|<center><small>Sample of type declaration used as a list.</small></center>
 
|<center><small>Sample of type declaration used as a map.</small></center>
 
|<center><small>Sample of type declaration used as a map.</small></center>
 +
|}
 +
 +
'''Since 1.2''': <code>@extends</code> tag. The '''extend''' tag allow to define that current type is [[LDT/User_Area/Documentation_Language#Type_Extending|extending]] the given super-type.
 +
 +
{|  border="1" cellspacing="0" valign="top"
 +
|valign="top"|
 +
<source lang="lua">
 +
--------------------------------------------------------------------------------
 +
-- Type short description.
 +
-- Type long description
 +
--
 +
-- @type typename
 +
-- @extends anothermodule#supertype
 +
</source>
 +
|-
 +
|<center><small>Sample of a type extending a super-type.</small></center>
 
|}
 
|}
  
 
== Module comment block ==
 
== Module comment block ==
  
Denoted by <code>@module</code> keyword and followed by a module name, a [[Koneki/LDT/Technical_Documentation/Documentation_Language#Module|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.<br/>
+
Denoted by <code>@module</code> keyword and followed by a module name, a [[LDT/User_Area/Documentation_Language#Module|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.<br/>
  
 +
{|  border="1" cellspacing="0" valign="top"
 +
|valign="top"|
 
<source lang="lua">
 
<source lang="lua">
 
--------------------------------------------------------------------------------
 
--------------------------------------------------------------------------------
Line 171: Line 204:
 
-- @module modulename
 
-- @module modulename
 
</source>
 
</source>
<center><small>Sample of module declaration.</small></center>
+
|-
 +
|<center><small>Sample of module declaration.</small></center>
 +
|}
  
 
When a module is declared, a type with its name is automatically created and returned. So, the following is equivalent to first module sample.
 
When a module is declared, a type with its name is automatically created and returned. So, the following is equivalent to first module sample.
  
 +
{|  border="1" cellspacing="0" valign="top"
 +
|valign="top"|
 
<source lang="lua">
 
<source lang="lua">
 
--------------------------------------------------------------------------------
 
--------------------------------------------------------------------------------
Line 185: Line 222:
 
---@type modulename
 
---@type modulename
 
</source>
 
</source>
<center><small>Sample of verbose module declaration</small></center>
+
|-
'''Note''': We used <code>#modulename</code> to refer to a declared type, if you want to know more about it refer to [[Koneki/LDT/Technical_Documentation/Documentation_Language#Type_references|type reference section]].
+
|<center><small>Sample of verbose module declaration</small></center>
 +
|}
 +
'''Note''': We used <code>#modulename</code> to refer to a declared type, if you want to know more about it refer to [[LDT/User_Area/Documentation_Language#Type_references|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.
 
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.
  
 +
{|  border="1" cellspacing="0" valign="top"
 +
|valign="top"|
 
<source lang="lua">
 
<source lang="lua">
 
--------------------------------------------------------------------------------
 
--------------------------------------------------------------------------------
Line 198: Line 239:
 
-- @return #string
 
-- @return #string
 
</source>
 
</source>
<center><small>Sample of module returning custom type</small></center>
+
|-
'''Note''': We used <code>#string</code> to refer to a [[Koneki/LDT/Technical_Documentation/Documentation_Language#Primitive_references|primitive type]].
+
|<center><small>Sample of module returning custom type</small></center>
 +
|}
 +
'''Note''': We used <code>#string</code> to refer to a [[LDT/User_Area/Documentation_Language#Primitive_references|primitive type]].
  
'''Since 1.2''': <code>@list</code> and <code>@map</code> tags. The '''list''' and '''map''' tags allow to describe if the module is used as a [[Koneki/LDT/Technical_Documentation/Documentation_Language#List|list]] or a [[Koneki/LDT/Technical_Documentation/Documentation_Language#Map|map]] of elements.
+
'''Since 1.2''': <code>@list</code> and <code>@map</code> tags. The '''list''' and '''map''' tags allow to describe if the module is used as a [[LDT/User_Area/Documentation_Language#List|list]] or a [[LDT/User_Area/Documentation_Language#Map|map]] of elements.
  
 
{|  border="1" cellspacing="0" valign="top"
 
{|  border="1" cellspacing="0" valign="top"
Line 225: Line 268:
 
|<center><small>Sample of module declaration used as a list.</small></center>
 
|<center><small>Sample of module declaration used as a list.</small></center>
 
|<center><small>Sample of module declaration used as a map.</small></center>
 
|<center><small>Sample of module declaration used as a map.</small></center>
 +
|}
 +
 +
'''Since 1.2''': <code>@extends</code> tag. The '''extend''' tag allow to define that current module is [[LDT/User_Area/Documentation_Language#Type_Extending|extending]] the given super-type.
 +
 +
{|  border="1" cellspacing="0" valign="top"
 +
|valign="top"|
 +
 +
<source lang="lua">
 +
--------------------------------------------------------------------------------
 +
-- Module short description.
 +
-- Module long description
 +
--
 +
-- @module modulename
 +
-- @extends anothermodule#supertype
 +
</source>
 +
|-
 +
|<center><small>Sample of a module extending a super-type.</small></center>
 
|}
 
|}
  
 
== Field comment block ==
 
== Field comment block ==
  
The field block represents a [[Koneki/LDT/Technical_Documentation/Documentation_Language#Field|field of a type]]. It is possible to declare one with <code>@field</code> keyword followed by optional [[Koneki/LDT/Technical_Documentation/Documentation_Language#Type_references|type reference]], field name and optional description.
+
The field block represents a [[LDT/User_Area/Documentation_Language#Field|field of a type]]. It is possible to declare one with <code>@field</code> keyword followed by optional [[LDT/User_Area/Documentation_Language#Type_references|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.
 
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.
  
 +
{|  border="1" cellspacing="0" valign="top"
 +
|valign="top"|
 
<source lang="lua">
 
<source lang="lua">
 
--------------------------------------------------------------------------------
 
--------------------------------------------------------------------------------
Line 241: Line 303:
 
-- @field #string fieldname Field description
 
-- @field #string fieldname Field description
 
</source>
 
</source>
<center><small>Sample of field declaration in parent type block</small></center>
+
|valign="top"|
 
+
 
<source lang="lua">
 
<source lang="lua">
---
+
--------------------------------------------------------------------------------
 
-- Type short description.
 
-- Type short description.
 
-- Type long description
 
-- Type long description
Line 255: Line 316:
 
-- @field [parent=#typename] #string fieldname  
 
-- @field [parent=#typename] #string fieldname  
 
</source>
 
</source>
<center><small>Sample of field declaration in dedicated block</small></center>
+
|-
 +
|<center><small>Sample of field declaration in parent type block</small></center>
 +
|<center><small>Sample of field declaration in dedicated block</small></center>
 +
|}
  
 
== Function comment block ==
 
== Function comment block ==
  
The function comment block has to be attached to a type. Its keyword is <code>@function</code>. A [[Koneki/LDT/Technical_Documentation/Documentation_Language#Function|function]] can have several parameters denoted by keyword <code>@param</code>, they can be optionally typed with a [[Koneki/LDT/Technical_Documentation/Documentation_Language#Type_references|type reference]] and have an optional descriptions. Several <code>@return</code> 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 <code>@return</code> markup. Returned values can be optionally typed using a [[Koneki/LDT/Technical_Documentation/Documentation_Language#Type_references|type reference]].<br/>
+
The function comment block has to be attached to a type. Its keyword is <code>@function</code>. A [[LDT/User_Area/Documentation_Language#Function|function]] can have several parameters denoted by keyword <code>@param</code>, they can be optionally typed with a [[LDT/User_Area/Documentation_Language#Type_references|type reference]] and have an optional descriptions. Several <code>@return</code> 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 <code>@return</code> markup. Returned values can be optionally typed using a [[LDT/User_Area/Documentation_Language#Type_references|type reference]].<br/>
 
'''Note''': If the first <code>@param</code> is called ''self'', LDT will show completion proposal without this parameter but using <code>:</code> invocation operator.<br/>
 
'''Note''': If the first <code>@param</code> is called ''self'', LDT will show completion proposal without this parameter but using <code>:</code> invocation operator.<br/>
  
 +
{|  border="1" cellspacing="0" valign="top"
 +
|valign="top"|
 
<source lang="lua">
 
<source lang="lua">
 
--------------------------------------------------------------------------------
 
--------------------------------------------------------------------------------
Line 274: Line 340:
 
-- @return Untyped return description
 
-- @return Untyped return description
 
</source>
 
</source>
<center><small>Sample of function declaration</small></center>
+
|-
 +
|<center><small>Sample of function declaration</small></center>
 +
|}
  
 
'''Note''': It is also possible to document function for types which name contains <code>"."</code>.
 
'''Note''': It is also possible to document function for types which name contains <code>"."</code>.
  
 +
{|  border="1" cellspacing="0" valign="top"
 +
|valign="top"|
 
<source lang="lua">
 
<source lang="lua">
 
--------------------------------------------------------------------------------
 
--------------------------------------------------------------------------------
Line 285: Line 355:
 
-- @function [parent=#typeprefix.typename] functionname
 
-- @function [parent=#typeprefix.typename] functionname
 
</source>
 
</source>
<center><small>Sample of function declaration related to a type which name contains <code>"."</code></small></center>
+
|-
 +
|<center><small>Sample of function declaration related to a type which name contains <code>"."</code></small></center>
 +
|}
  
 
'''Since 1.2''': <code>@callof</code> tag. In Lua a table can be call using the metatable keyword '''__call'''. To set a type callable just add <code>@callof #typename</code> in the function behind the '''__call''' metamethod. The first param should be ''self'' and of the type given to ''callof''.
 
'''Since 1.2''': <code>@callof</code> tag. In Lua a table can be call using the metatable keyword '''__call'''. To set a type callable just add <code>@callof #typename</code> in the function behind the '''__call''' metamethod. The first param should be ''self'' and of the type given to ''callof''.
  
 +
{|  border="1" cellspacing="0" valign="top"
 +
|valign="top"|
 
<source lang="lua">
 
<source lang="lua">
 
--------------------------------------------------------------------------------
 
--------------------------------------------------------------------------------
Line 295: Line 369:
 
--
 
--
 
-- @callof #typename
 
-- @callof #typename
-- @param #typename self
+
-- @param #typename self
 
-- @param #paramtype paramname
 
-- @param #paramtype paramname
 
</source>
 
</source>
<center><small>Sample of function declaration related </small></center>
+
|-
 +
|<center><small>Sample of function declaration related </small></center>
 +
|}
  
 
== Global comment block ==
 
== Global comment block ==
  
To declare a function or a field with a [[Koneki/LDT/Technical_Documentation/Documentation_Language#Type_references|type reference]] as ''[[Koneki/LDT/Technical_Documentation/Documentation_Language#Global|global]]'', you just have to attach it to the <code>global</code> type.
+
To declare a function or a field with a [[LDT/User_Area/Documentation_Language#Type_references|type reference]] as ''[[LDT/User_Area/Documentation_Language#Global|global]]'', you just have to attach it to the <code>global</code> type.
  
 +
{|  border="1" cellspacing="0" valign="top"
 +
|valign="top"|
 
<source lang="lua">
 
<source lang="lua">
 
--------------------------------------------------------------------------------
 
--------------------------------------------------------------------------------
Line 316: Line 394:
 
-- @param self
 
-- @param self
 
</source>
 
</source>
<center><small>Sample of global field and function</small></center>
+
|-
 +
|<center><small>Sample of global field and function</small></center>
 +
|}
  
 
= Samples =
 
= Samples =
Line 476: Line 556:
  
 
== Callof sample ==  
 
== Callof sample ==  
 +
 +
The ''@callof'' tag is only available since the '''v1.2'''
 +
 
{|  border="1" cellspacing="0" valign="top"
 
{|  border="1" cellspacing="0" valign="top"
 
|valign="top"|
 
|valign="top"|
Line 504: Line 587:
 
   return newcircle
 
   return newcircle
 
end
 
end
 +
 +
setmetatable(M,{__call=new})
 
   
 
   
 
return M
 
return M
  
 
</source>
 
</source>
 +
|valign="top"|
 +
<source lang="lua">
 +
local circlemodule = require "circleModule"
 +
 +
local firstcircle = circlemodule(10,0,0)
 +
local secondcircle = circlemodule(50,10,0)
 +
 +
firstcircle.radius = 20
 +
</source>
 +
 
|-
 
|-
|<center><small>The @callof tag ir only available since the v1.2</small></center>
+
|<center><small>Circle module sample</small></center>
 +
|<center><small>Usage of the circle module</small></center>
 
|}
 
|}
  
== List sample ==  
+
== List and Map samples ==  
 +
 
 +
The ''@list'' and ''@map'' tags are only available since the '''v1.2'''
 +
 
 
{|  border="1" cellspacing="0" valign="top"
 
{|  border="1" cellspacing="0" valign="top"
 
|valign="top"|
 
|valign="top"|
 
<source lang="lua">
 
<source lang="lua">
 
---
 
---
 +
-- A simple addressbook module
 +
--
 
-- @module addressbook
 
-- @module addressbook
-- @list <#contact>  
+
-- @list <#contact>
 
local M = {}
 
local M = {}
  
 
--- @type contact
 
--- @type contact
-- @field #string name
+
-- @field #string name Contact full name
-- @field #number phone
+
-- @field #number phone Contact landline
 +
 
 +
function M.empty()
 +
  return M[1] == nil
 +
end
  
 
function M:add(name,phonenumber)
 
function M:add(name,phonenumber)
table.insert(self,{name = name, phone = phonenumber})
+
  table.insert(self,{name = name, phone = phonenumber})
 
end
 
end
  
Line 533: Line 638:
 
-- @return nil, errormsg
 
-- @return nil, errormsg
 
function M:find(name)
 
function M:find(name)
for _, contact in pairs(self) do
+
  for _, contact in pairs(self) do
if (contact.name == name) then
+
    if (contact.name == name) then
return contact
+
      return contact
end
+
    end
end
+
  end
return nil, string.format("No contact found under the name %s", name)
+
  return nil, string.format("No contact found under the name %s", name)
 
end
 
end
  
 
return M
 
return M
 +
</source>
 +
|valign="top"|
 +
<source lang="lua">
 +
---
 +
-- System made of users
 +
--
 +
-- @module system
 +
-- @map <#string, #user> users All users sorted by identifier
 +
local M = { }
  
 +
---
 +
-- User description at system level
 +
--
 +
-- @type user
 +
-- @field #string name User full name
 +
-- @field #number rights
 +
local users = { }
 +
 +
---
 +
-- Sanity checks
 +
function M.checks()
 +
  if not (M.root and M.root.rights == 777) then
 +
    error('No root user found.')
 +
  end
 +
end
 +
 +
return M
 
</source>
 
</source>
 
|-
 
|-
|<center><small>The @list and @maps tags are only available since the v1.2</small></center>
+
|<center><small>Sample using a list</small></center>
 +
|<center><small>Sample using a map</small></center>
 +
|}
 +
 
 +
== Extends sample ==
 +
 
 +
The ''@extends'' tag is only available since the '''v1.2'''
 +
 
 +
{|  border="1" cellspacing="0" valign="top"
 +
|valign="top"|
 +
<source lang="lua">
 +
---
 +
-- @module mymath
 +
-- @extends math#math
 +
local M = require "math"
 +
 
 +
--- Generate a Fibonacci sequence
 +
-- @param #number n the size of sequence (10 by default)
 +
-- @return #list<#number>
 +
function M.fibonacci(n)
 +
  assert(n>0)
 +
  local size = n or 10
 +
  local sequence = {}
 +
 
 +
  for i = 1,size do
 +
    if (i == 1) then
 +
      sequence[i] = 0
 +
    elseif (i == 2) then
 +
      sequence[i] = 1
 +
    else
 +
      sequence[i] = sequence[i-1] + sequence[i-2]
 +
    end
 +
  end
 +
 
 +
  return sequence
 +
end
 +
 
 +
return M
 +
</source>
 +
 
 +
|-
 +
|<center><small>My extended math module sample</small></center>
 
|}
 
|}
  

Latest revision as of 11:52, 16 July 2014

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.

Idea.png
global variable auto-completion behavior

To be aware of where a global variable should be accessible is a real challenge for tooling. Actually, there are two possibilities :

  • the global variable is preloaded by the interpreter (VM) at launch : in this case, it's easy, the global variable is always accessible.
  • the global is created dynamically during runtime : in this case, it's very difficult to know where the global variable must be available in autocompletion.

The first case (preloaded global var) is managed by the use of a global.lua file in execution environment which must contains all preloaded global variables. (Those global vars will always be available in autocompletion)

The other case, LDT lets you choose between (customizable in Preference/Lua):

  • All (default): display all global variables available in project sourcepath/buildpath. (with the risk to reference globals where they are not effectively available at runtime)
  • None: do not propose any global of this kind.


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.

--------------------------------------------------------------------------------
-- Type short description.
-- Type long description
--
-- @type typename
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.

--------------------------------------------------------------------------------
-- Type short description.
-- Type long description
--
-- @type typename
-- @list <#valuetypename>
--------------------------------------------------------------------------------
-- Type short description.
-- Type long description
--
-- @type typename
-- @map <#keytype,#valuetype>
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.

--------------------------------------------------------------------------------
-- Type short description.
-- Type long description
--
-- @type typename
-- @extends anothermodule#supertype
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.

--------------------------------------------------------------------------------
-- Module short description.
-- Module long description
--
-- @module modulename
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.

--------------------------------------------------------------------------------
-- Module short description.
-- Module long description
--
-- @module modulename
-- @return #modulename
 
---@type modulename
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.

--------------------------------------------------------------------------------
-- Module short description.
-- Module long description
--
-- @module modulename
-- @return #string
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.

--------------------------------------------------------------------------------
-- Module short description.
-- Module long description
--
-- @module modulename
-- @list <#valuetype>
--------------------------------------------------------------------------------
-- Module short description.
-- Module long description
--
-- @module modulename
-- @map <#keytype,#valuetype>
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.

--------------------------------------------------------------------------------
-- Module short description.
-- Module long description
--
-- @module modulename
-- @extends anothermodule#supertype
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.

--------------------------------------------------------------------------------
-- Type short description.
-- Type long description
--
-- @type typename
-- @field #string fieldname Field description
--------------------------------------------------------------------------------
-- Type short description.
-- Type long description
--
-- @type typename
 
---
-- Field description
--
-- @field [parent=#typename] #string fieldname
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.

--------------------------------------------------------------------------------
-- Function short description.
-- Function long description
--
-- @function [parent=#typename] functionname
-- @param self Parameter description
-- @param #string parametername Parameter description
-- @return #number Typed return description
-- @return #nil, #string Traditional nil and error message
-- @return Untyped return description
Sample of function declaration

Note: It is also possible to document function for types which name contains ".".

--------------------------------------------------------------------------------
-- Function short description.
-- Function long description
--
-- @function [parent=#typeprefix.typename] functionname
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.

--------------------------------------------------------------------------------
-- Function short description.
-- Function long description
--
-- @callof #typename
-- @param #typename self
-- @param #paramtype paramname
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.

--------------------------------------------------------------------------------
-- Field long description
--
-- @field [parent=#global] #string fieldname
 
--------------------------------------------------------------------------------
-- Function short description. Function long description
--
-- @function [parent=#global] functionname
-- @param self
Sample of global field and function

Samples

Simple module sample

---
-- Module short description.
-- Module _long description_
--
-- @module modulename
local M = {}
 
---
-- Field description
--
-- @field [parent=#modulename] #string fieldname 
M.fieldname = 'field value'
 
---
-- Function short description.
-- Function long description
--
-- @function [parent=#modulename] functionname
-- @param #number n Parameter description
-- @return #number Typed return description
-- @return #nil, #string Traditional nil and error message
function M.functionname(n)
  if n then return n else return nil, "error" end
end
return M
---
-- Module short description.
-- Module _long description_
local M = {}
 
---
-- Field description
M.fieldname = 'field value'
 
---
-- Function short description.
-- Function long description
-- @param #number n Parameter description
-- @return #number Typed return description
-- @return #nil, #string Traditional nil and error message
function M.functionname(n)
  if n then return n else return nil, "error" end
end
return M
---
-- Module short description.
-- Module _long description_
--
-- @module modulename
 
---
-- Field description
--
-- @field [parent=#modulename] #string fieldname 
 
---
-- Function short description.
-- Function long description
--
-- @function [parent=#modulename] functionname
-- @param #number n Parameter description
-- @return #number Typed return description
-- @return #nil, #string Traditional nil and error message
return nil
Full Documentation sample
Minimal Documentation
Documentation Only

Object-oriented sample

--- A module that allow to manage geometry shapes
-- @module geometry
local M = {}
 
--- A rectangle 
-- @type rectangle
-- @field #number x 
-- @field #number y 
-- @field #number width
-- @field #number height
local R = {x=0, y=0, width=100, height=100, }
 
--- Move the rectangle
-- @function [parent=#rectangle] move
-- @param self
-- @param x
-- @param y
function R.move(self,x,y)
  self.x = self.x + x
  self.y = self.y + y
end
 
--- Create a new rectangle
-- @function [parent=#geometry] newRectangle
-- @param x
-- @param y
-- @param width
-- @param height
-- @return #rectangle the created rectangle
function M.newRectangle(x,y,width,height)
  local newrectangle = {x=x,y=y,width=width,height=height}
 
  -- Set to new rectangle the properties of a rectangle
  setmetatable(newrectangle, {__index = R})
  return newrectangle
end
 
return M
--- A module that allow to manage geometry shapes
local M = {}
 
--- A rectangle 
-- @type rectangle
local R = {x=0, y=0, width=100, height=100, }
 
--- Move the rectangle
function R.move(self,x,y)
  self.x = self.x + x
  self.y = self.y + y
end
 
--- Create a new rectangle
-- @return #rectangle the created rectangle
function M.newRectangle(x,y,width,height)
  local newrectangle = {x=x,y=y,width=width,height=height}
 
  -- set to new rectangle the properties of a rectangle
  setmetatable(newrectangle, {__index = R})
  return newrectangle
end
 
return M
Full Documentation Sample
Minimal Documentation

Callof sample

The @callof tag is only available since the v1.2

--- A module that allow to manage circle shapes
-- @module circleModule
local M = {}
 
--- A circle
-- @type circle
local C = {radius=0, x=0, y=100}
 
--- Move the circle
-- @function [parent=#circle] move
function C.move(self,x,y)
  self.x = self.x + x
  self.y = self.y + y
end
 
--- Create a new circle
-- @callof #circleModule
-- @return #circle the created cicle
local function new(self,radius,x,y)
  local newcircle = {radius=radius,x=x,y=y}
 
  -- Set to new circle the properties of a circle
  setmetatable(newcircle, {__index = C})
  return newcircle
end
 
setmetatable(M,{__call=new})
 
return M
local circlemodule = require "circleModule"
 
local firstcircle = circlemodule(10,0,0)
local secondcircle = circlemodule(50,10,0)
 
firstcircle.radius = 20
Circle module sample
Usage of the circle module

List and Map samples

The @list and @map tags are only available since the v1.2

---
-- A simple addressbook module
--
-- @module addressbook
-- @list <#contact>
local M = {}
 
--- @type contact
-- @field #string name Contact full name
-- @field #number phone Contact landline
 
function M.empty()
  return M[1] == nil
end
 
function M:add(name,phonenumber)
  table.insert(self,{name = name, phone = phonenumber})
end
 
---
-- @return #contact
-- @return nil, errormsg
function M:find(name)
  for _, contact in pairs(self) do
    if (contact.name == name) then
      return contact
    end
  end
  return nil, string.format("No contact found under the name %s", name)
end
 
return M
---
-- System made of users
--
-- @module system
-- @map <#string, #user> users All users sorted by identifier
local M = { }
 
---
-- User description at system level
--
-- @type user
-- @field #string name User full name
-- @field #number rights
local users = { }
 
---
-- Sanity checks
function M.checks()
  if not (M.root and M.root.rights == 777) then
    error('No root user found.')
  end
end
 
return M
Sample using a list
Sample using a map

Extends sample

The @extends tag is only available since the v1.2

---
-- @module mymath
-- @extends math#math
local M = require "math"
 
--- Generate a Fibonacci sequence
-- @param #number n the size of sequence (10 by default)
-- @return #list<#number>
function M.fibonacci(n)
  assert(n>0)
  local size = n or 10
  local sequence = {}
 
  for i = 1,size do
    if (i == 1) then
      sequence[i] = 0
    elseif (i == 2) then
      sequence[i] = 1
    else
      sequence[i] = sequence[i-1] + sequence[i-2]
    end
  end
 
  return sequence
end
 
return M
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.

Copyright © Eclipse Foundation, Inc. All Rights Reserved.