Jump to: navigation, search

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

< LDT
(Global comment block)
m (Sample mixing code and comments)
(16 intermediate revisions by 5 users not shown)
Line 3: Line 3:
 
= Concepts =
 
= Concepts =
  
Our documentation language introduce some concepts which may not be described explicitly in Lua, but help for API description and tooling.
+
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 ==
 
== Type ==
  
This is the most important one. A ''type'' is a set of values, accessible through fields. It is not scalar like <code>string</code>, <code>number</code> or <code>nil</code>. Theses fields can point to functions, scalar values or other types.
+
This is the most important one. A compound ''type'' is a set of values, accessible through fields. It is not a primitive type like <code>string</code>, <code>number</code> or <code>nil</code>. 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.
 
It is the way to explicitly ensure the structure of a Lua table.
Line 13: Line 13:
 
== Module ==
 
== Module ==
  
It is ''requireable'' entity - you can use the <code>require</code> function on it- able to modify global environment which return a ''type''. Most of the time people refer to the returned type instance as module.
+
It is ''requireable'' entity - you can use the <tt>require</tt> function on it- <br>
 +
This concept allow you to express :
 +
* which ''type'' will be return by the <tt>require</tt> function for your module,
 +
* which new global variables will be available after your module was loaded.<br>
 +
Most of the time people refer to the returned type instance as module.
  
 
== Field ==
 
== 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. It can be typed with a type different from parent one.
+
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 ==
 
== Function ==
  
It is a special type 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.
+
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 ==
 
== Global ==
  
In Lua you can affect and read globals at anytime. To handle those cases, the predefined type ''global'' is available. It is a reserved type which will be available everywhere, enabling you to attach field and function to it.
+
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 field and function to it.
 +
This is a way to express the creation of new global variables when module is loaded.
  
 
== Type references ==
 
== 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 or a function, they are several kinds of references available.
+
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 ===
 
=== Primitive references ===
Line 62: Line 67:
 
First of all, only ''special comments'' are parsed as part of Lua documentation. To mark your comment as special, just start it with <code>---</code>.
 
First of all, only ''special comments'' are parsed as part of Lua documentation. To mark your comment as special, just start it with <code>---</code>.
  
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://fr.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 [[Koneki/LDT/Technical_Documentation/Documentation_Language#Concepts|concept]]'''.
Line 74: Line 79:
 
</pre></code>
 
</pre></code>
 
<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://fr.wikipedia.org/wiki/Markdown Markdown].
+
'''Note''': <code>_markdown_</code> is supposed to be interpreted by [http://en.wikipedia.org/wiki/Markdown Markdown].
  
 
<code><pre>
 
<code><pre>
Line 133: Line 138:
 
</pre></code>
 
</pre></code>
 
<center><small>Sample of verbose module declaration</small></center>
 
<center><small>Sample of verbose module declaration</small></center>
'''Note''': We used <code>#typename</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]].
+
'''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]].
  
 
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.
Line 180: Line 185:
 
== 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 fist 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 [[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/>
 
'''Note''': If the first <code>@param</code> is called ''self'', LDT will show completion proposal without this parameter but using <code>:</code> invocation operator.
 
'''Note''': If the first <code>@param</code> is called ''self'', LDT will show completion proposal without this parameter but using <code>:</code> invocation operator.
  
Line 196: Line 201:
 
</pre></code>
 
</pre></code>
 
<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>.
 +
 +
<code><pre>
 +
--------------------------------------------------------------------------------
 +
-- Function short description.
 +
-- Function long description
 +
--
 +
-- @function [parent=#typeprefix.typename] functionname
 +
</pre></code>
 +
<center><small>Sample of function declaration related to a type which name contains <code>"."</code></small></center>
  
 
== Global comment block ==
 
== Global comment block ==
Line 245: Line 261:
 
<center><small>Sample of documented module</small></center>
 
<center><small>Sample of documented module</small></center>
  
== Short references ==
+
<code><pre>
 +
--- A module that allow to manage geometry shapes
 +
-- @module geometry
 +
local M = {}
 +
 
 +
--- A rectangle
 +
-- @type rectangle
 +
-- @field [parent=#rectangle] #number x horizontal position, 0 by default
 +
-- @field [parent=#rectangle] #number y vertical position, 0 by default
 +
-- @field [parent=#rectangle] #number width, 100 by default
 +
-- @field [parent=#rectangle] #number height, 100 by default
 +
local R = {x=0, y=0, width=100, height=100, }
 +
 
 +
--- Move the rectangle
 +
-- @function [parent=#rectangle] move
 +
-- @param #rectangle self
 +
-- @param #number x
 +
-- @param #number 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 #number x
 +
-- @param #number y
 +
-- @param #number width
 +
-- @param #number 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
 +
</pre></code>
 +
<center><small>Sample of documented in-module type</small></center>
 +
 
 +
= 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 <code>@{}</code>. You can reference a types and their fields, functions are handled as a specific type of fields.
 
It is way to reference a types and their fields ''in a textual description''. You just have to surround a type reference with <code>@{}</code>. You can reference a types and their fields, functions are handled as a specific type of fields.
Line 251: Line 309:
 
* Reference to types
 
* Reference to types
 
** <code>@{#typename}</code> will refer to type ''typename'' defined in current module.
 
** <code>@{#typename}</code> will refer to type ''typename'' defined in current module.
** <code>@{#modulename}</code> equivalent to previous notation, as a module is the type returned by a file.
+
** <code>@{modulename}</code> will refer to module named ''modulename''.
 
** <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''.
 
* Reference to fields
 
* Reference to fields
 
** <code>@{#typename.fieldname}</code> will refer to ''fieldname'' which could be a function or field attached to type ''typename'' defined in current module.
 
** <code>@{#typename.fieldname}</code> will refer to ''fieldname'' which could be a function or field attached to type ''typename'' defined in current module.
*** <code>@{#{type.name}.fieldname}</code> to remove ambiguity, when type name contains <code>"."</code>.
 
 
** <code>@{modulename#typename.fieldname}</code> will refer to ''fieldname'' which could be a function or field attached to type ''typename'' defined in ''modulename'' module.
 
** <code>@{modulename#typename.fieldname}</code> 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''.
  
 
<code><pre>
 
<code><pre>
 
--------------------------------------------------------------------------------
 
--------------------------------------------------------------------------------
-- Short description and reference to @{io#io.flush}.
+
-- Short description. Long description with a reference to @{io#io.flush}.
 
--
 
--
 
-- @function [parent=#typename] functionname
 
-- @function [parent=#typename] functionname
Line 266: Line 324:
 
<center><small>Sample of type reference in a description</small></center>
 
<center><small>Sample of type reference in a description</small></center>
  
= Limitations =
+
'''Ambiguity'''
  
== Identifiers ==
+
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 <code>@{module.name#type.name.fieldname}</code> 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.
 +
* <code>@{modulenamed#(type.name).fieldname}</code> will refer to field named ''fieldname'' from type named ''type.name'' defined in module named ''modulename''.
 +
* <code>@{modulenamed#(type.name)}</code> will refer to type named ''type.name'' from module named ''modulename''
 +
* <code>@{#(type.name)}</code> will refer to type named ''type.name''.
 +
 
 +
= Limitations =
  
Due to our way of parsing, is not possible to use tag names as identifiers. So assume that the following identifiers are reserved:
 
  
* field
 
* function
 
* module
 
* param
 
* return
 
* type
 
  
 
== Markdown ==
 
== Markdown ==
Line 295: Line 356:
 
== Usage ==
 
== Usage ==
  
When you have a comment block related to a concept, you can give a sample of it should be used by using the <code>@usage</code> keyword.
+
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 <code>@usage</code> keyword.
  
 
<code><pre>
 
<code><pre>
Line 304: Line 365:
 
-- @module modulename
 
-- @module modulename
 
-- @usage local modulename = require 'modulename'
 
-- @usage local modulename = require 'modulename'
 +
-- @usage require('modulename')
 
</pre></code>
 
</pre></code>
 
<center><small>Sample of module declaration with usage markup.</small></center>
 
<center><small>Sample of module declaration with usage markup.</small></center>

Revision as of 10:07, 10 June 2013

This documentation language has been developed as part of Koneki, 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 field and function to it. This is a way to express the creation of new global variables when module is loaded.

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.

Comments

It is the only source of information of our documentation language. So far, there is no inference from code. So all aspect of the API has to be described explicitly.

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

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.

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
Sample of field declaration in parent type block
---
-- Type short description.
-- Type long description
--
-- @type typename

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

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

Sample mixing code and comments

---
-- 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 self Parameter description
-- @return #number Typed return description
-- @return #nil, #string Traditional nil and error message
function M.functionname(self)
    return 0
end
return M
Sample of documented module
--- A module that allow to manage geometry shapes
-- @module geometry
local M = {}

--- A rectangle 
-- @type rectangle
-- @field [parent=#rectangle] #number x horizontal position, 0 by default
-- @field [parent=#rectangle] #number y vertical position, 0 by default
-- @field [parent=#rectangle] #number width, 100 by default
-- @field [parent=#rectangle] #number height, 100 by default
local R = {x=0, y=0, width=100, height=100, }

--- Move the rectangle
-- @function [parent=#rectangle] move
-- @param #rectangle self
-- @param #number x
-- @param #number 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 #number x
-- @param #number y
-- @param #number width
-- @param #number 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
Sample of documented in-module type

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.

Inference

So far, all information about the documented module has to be explicitly described. There is no inference enabling us to extract documentation-valuable information from the code ... yet.

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.