This is an important refactor of the way documentation generation works

* Installs luarocks WITH it's executable (easy to install other rocks if necessary)
* Use Lua supplied with luarocks
* Create Utils/luadocumentor.bat, which works with RELATIVE PATH ! -> Everybody can generate the doc
* Updated launch files accordingly
This commit is contained in:
Grey-Echo
2017-04-05 01:26:39 +02:00
parent 513a103947
commit 3b69cf992e
313 changed files with 16547 additions and 36807 deletions

View File

@@ -0,0 +1,106 @@
--------------------------------------------------------------------------------
-- Copyright (c) 2012-2014 Sierra Wireless.
-- All rights reserved. This program and the accompanying materials
-- are made available under the terms of the Eclipse Public License v1.0
-- which accompanies this distribution, and is available at
-- http://www.eclipse.org/legal/epl-v10.html
--
-- Contributors:
-- Kevin KIN-FOO <kkinfoo@sierrawireless.com>
-- - initial API and implementation and initial documentation
--------------------------------------------------------------------------------
return[[#
<div id="content">
# --
# -- Module name
# --
# if _file.name then
<h$(i)>Module <code>$(_file.name)</code></h$(i)>
# end
# --
# -- Descriptions
# --
# if _file.shortdescription then
$( format(_file.shortdescription) )
# end
# if _file.description and #_file.description > 0 then
$( format(_file.description) )
# end
# --
# -- Handle "@usage" special tag
# --
#if _file.metadata and _file.metadata.usage then
$( applytemplate(_file.metadata.usage, i+1) )
#end
# --
# -- Show quick description of current type
# --
#
# -- show quick description for globals
# if not isempty(_file.globalvars) then
<h$(i+1)>Global(s)</h$(i+1)>
<table class="function_list">
# for _, item in sortedpairs(_file.globalvars) do
<tr>
<td class="name" nowrap="nowrap">$( fulllinkto(item) )</td>
<td class="summary">$( format(item.shortdescription) )</td>
</tr>
# end
</table>
# end
#
# -- get type corresponding to this file (module)
# local currenttype
# local typeref = _file:moduletyperef()
# if typeref and typeref.tag == "internaltyperef" then
# local typedef = _file.types[typeref.typename]
# if typedef and typedef.tag == "recordtypedef" then
# currenttype = typedef
# end
# end
#
# -- show quick description type exposed by module
# if currenttype and not isempty(currenttype.fields) then
<h$(i+1)><a id="$(anchor(currenttype))" >Type <code>$(currenttype.name)</code></a></h$(i+1)>
$( applytemplate(currenttype, i+2, 'index') )
# end
# --
# -- Show quick description of other types
# --
# if _file.types then
# for name, type in sortedpairs( _file.types ) do
# if type ~= currenttype and type.tag == 'recordtypedef' and not isempty(type.fields) then
<h$(i+1)><a id="$(anchor(type))">Type <code>$(name)</code></a></h$(i+1)>
$( applytemplate(type, i+2, 'index') )
# end
# end
# end
# --
# -- Long description of globals
# --
# if not isempty(_file.globalvars) then
<h$(i+1)>Global(s)</h$(i+1)>
# for name, item in sortedpairs(_file.globalvars) do
$( applytemplate(item, i+2) )
# end
# end
# --
# -- Long description of current type
# --
# if currenttype then
<h$(i+1)><a id="$(anchor(currenttype))" >Type <code>$(currenttype.name)</code></a></h$(i+1)>
$( applytemplate(currenttype, i+2) )
# end
# --
# -- Long description of other types
# --
# if not isempty( _file.types ) then
# for name, type in sortedpairs( _file.types ) do
# if type ~= currenttype and type.tag == 'recordtypedef' then
<h$(i+1)><a id="$(anchor(type))" >Type <code>$(name)</code></a></h$(i+1)>
$( applytemplate(type, i+2) )
# end
# end
# end
</div>
]]

View File

@@ -0,0 +1,28 @@
--------------------------------------------------------------------------------
-- Copyright (c) 2012-2014 Sierra Wireless.
-- All rights reserved. This program and the accompanying materials
-- are made available under the terms of the Eclipse Public License v1.0
-- which accompanies this distribution, and is available at
-- http://www.eclipse.org/legal/epl-v10.html
--
-- Contributors:
-- Kevin KIN-FOO <kkinfoo@sierrawireless.com>
-- - initial API and implementation and initial documentation
--------------------------------------------------------------------------------
return
[[#
#if _index.modules then
<div id="content">
<h2>Module$( #_index.modules > 1 and 's' )</h2>
<table class="module_list">
# for _, module in sortedpairs( _index.modules ) do
# if module.tag ~= 'index' then
<tr>
<td class="name" nowrap="nowrap">$( fulllinkto(module) )</td>
<td class="summary">$( module.description and format(module.shortdescription) )</td>
</tr>
# end
# end
</table>
</div>
#end ]]

View File

@@ -0,0 +1,23 @@
--------------------------------------------------------------------------------
-- Copyright (c) 2012-2014 Sierra Wireless.
-- All rights reserved. This program and the accompanying materials
-- are made available under the terms of the Eclipse Public License v1.0
-- which accompanies this distribution, and is available at
-- http://www.eclipse.org/legal/epl-v10.html
--
-- Contributors:
-- Kevin KIN-FOO <kkinfoo@sierrawireless.com>
-- - initial API and implementation and initial documentation
--------------------------------------------------------------------------------
return [[#
# if not isempty(_recordtypedef.fields) then
<table class="function_list">
# for _, item in sortedpairs( _recordtypedef.fields ) do
<tr>
<td class="name" nowrap="nowrap">$( fulllinkto(item) )</td>
<td class="summary">$( format(item.shortdescription) )</td>
</tr>
# end
</table>
# end
# ]]

View File

@@ -0,0 +1,167 @@
--------------------------------------------------------------------------------
-- Copyright (c) 2012-2014 Sierra Wireless.
-- All rights reserved. This program and the accompanying materials
-- are made available under the terms of the Eclipse Public License v1.0
-- which accompanies this distribution, and is available at
-- http://www.eclipse.org/legal/epl-v10.html
--
-- Contributors:
-- Kevin KIN-FOO <kkinfoo@sierrawireless.com>
-- - initial API and implementation and initial documentation
--------------------------------------------------------------------------------
return
[[<dl class="function">
<dt>
# --
# -- Resolve item type definition
# --
# local typedef = _item:resolvetype()
# --
# -- Show item type for internal type
# --
#if _item.type and (not typedef or typedef.tag ~= 'functiontypedef') then
# --Show link only when available
# local link = fulllinkto(_item.type)
# if link then
<em>$( link )</em>
# else
<em>$(prettyname(_item.type))</em>
# end
#end
<a id="$(anchor(_item))" >
<strong>$( prettyname(_item) )</strong>
</a>
</dt>
<dd>
# if _item.shortdescription then
$( format(_item.shortdescription) )
# end
# if _item.description and #_item.description > 0 then
$( format(_item.description) )
# end
#
# --
# -- For function definitions, describe parameters and return values
# --
#if typedef and typedef.tag == 'functiontypedef' then
# --
# -- Describe parameters
# --
# local fdef = typedef
#
# -- Adjust parameter count if first one is 'self'
# local paramcount
# if #fdef.params > 0 and isinvokable(_item) then
# paramcount = #fdef.params - 1
# else
# paramcount = #fdef.params
# end
#
# -- List parameters
# if paramcount > 0 then
<h$(i)>Parameter$( paramcount > 1 and 's' )</h$(i)>
<ul>
# for position, param in ipairs( fdef.params ) do
# if not (position == 1 and isinvokable(_item)) then
<li>
# local paramline = "<code><em>"
# if param.type then
# local link = linkto( param.type )
# local name = prettyname( param.type )
# if link then
# paramline = paramline .. '<a href=\"' .. link .. '\">' .. name .. "</a>"
# else
# paramline = paramline .. name
# end
# end
#
# paramline = paramline .. " " .. param.name .. " "
#
# if param.optional then
# paramline = paramline .. "optional" .. " "
# end
# if param.hidden then
# paramline = paramline .. "hidden"
# end
#
# paramline = paramline .. "</em></code>: "
#
# if param.description and #param.description > 0 then
# paramline = paramline .. "\n" .. param.description
# end
#
$( format (paramline))
</li>
# end
# end
</ul>
# end
#
# --
# -- Describe returns types
# --
# if fdef and #fdef.returns > 0 then
<h$(i)>Return value$(#fdef.returns > 1 and 's')</h$(i)>
# --
# -- Format nice type list
# --
# local function niceparmlist( parlist )
# local typelist = {}
# for position, type in ipairs(parlist) do
# local link = linkto( type )
# local name = prettyname( type )
# if link then
# typelist[#typelist + 1] = '<a href="'..link..'">'..name..'</a>'
# else
# typelist[#typelist + 1] = name
# end
# -- Append end separator or separating comma
# typelist[#typelist + 1] = position == #parlist and ':' or ', '
# end
# return table.concat( typelist )
# end
# --
# -- Generate a list if they are several return clauses
# --
# if #fdef.returns > 1 then
<ol>
# for position, ret in ipairs(fdef.returns) do
<li>
# local returnline = "";
#
# local paramlist = niceparmlist(ret.types)
# if #ret.types > 0 and #paramlist > 0 then
# returnline = "<em>" .. paramlist .. "</em>"
# end
# returnline = returnline .. "\n" .. ret.description
$( format (returnline))
</li>
# end
</ol>
# else
# local paramlist = niceparmlist(fdef.returns[1].types)
# local isreturn = fdef.returns and #fdef.returns > 0 and #paramlist > 0
# local isdescription = fdef.returns and fdef.returns[1].description and #format(fdef.returns[1].description) > 0
#
# local returnline = "";
# -- Show return type if provided
# if isreturn then
# returnline = "<em>"..paramlist.."</em>"
# end
# if isdescription then
# returnline = returnline .. "\n" .. fdef.returns[1].description
# end
$( format(returnline))
# end
# end
#end
#
#--
#-- Show usage samples
#--
#if _item.metadata and _item.metadata.usage then
$( applytemplate(_item.metadata.usage, i) )
#end
</dd>
</dl>]]

View File

@@ -0,0 +1,68 @@
--------------------------------------------------------------------------------
-- Copyright (c) 2012-2014 Sierra Wireless.
-- All rights reserved. This program and the accompanying materials
-- are made available under the terms of the Eclipse Public License v1.0
-- which accompanies this distribution, and is available at
-- http://www.eclipse.org/legal/epl-v10.html
--
-- Contributors:
-- Kevin KIN-FOO <kkinfoo@sierrawireless.com>
-- - initial API and implementation and initial documentation
--------------------------------------------------------------------------------
return
[[<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html>
#if _page.headers and #_page.headers > 0 then
<head>
# for _, header in ipairs(_page.headers) do
$(header)
# end
</head>
#end
<body>
<div id="container">
<div id="product">
<div id="product_logo"></div>
<div id="product_name"><big><b></b></big></div>
<div id="product_description"></div>
</div>
<div id="main">
# --
# -- Generating lateral menu
# --
<div id="navigation">
# local index = 'index'
# if _page.modules then
<h2>Modules</h2>
# -- Check if an index is defined
# if _page.modules [ index ] then
# local module = _page.modules [ index ]
<ul><li>
# if module ~= _page.currentmodule then
<a href="$( linkto(module) )">$(module.name)</a>
# else
$(module.name)
# end
</li></ul>
# end
#
<ul>
# -- Generating links for all modules
# for _, module in sortedpairs( _page.modules ) do
# -- Except for current one
# if module.name ~= index then
# if module ~= _page.currentmodule then
<li><a href="$( linkto(module) )">$(module.name)</a></li>
# else
<li>$(module.name)</li>
# end
# end
# end
</ul>
# end
</div>
$( applytemplate(_page.currentmodule) )
</div>
</body>
</html>
]]

View File

@@ -0,0 +1,36 @@
--------------------------------------------------------------------------------
-- Copyright (c) 2012-2014 Sierra Wireless.
-- All rights reserved. This program and the accompanying materials
-- are made available under the terms of the Eclipse Public License v1.0
-- which accompanies this distribution, and is available at
-- http://www.eclipse.org/legal/epl-v10.html
--
-- Contributors:
-- Kevin KIN-FOO <kkinfoo@sierrawireless.com>
-- - initial API and implementation and initial documentation
--------------------------------------------------------------------------------
return [[#
# --
# -- Descriptions
# --
#if _recordtypedef.shortdescription and #_recordtypedef.shortdescription > 0 then
$( format( _recordtypedef.shortdescription ) )
#end
#if _recordtypedef.description and #_recordtypedef.description > 0 then
$( format( _recordtypedef.description ) )
#end
#--
#-- Describe usage
#--
#if _recordtypedef.metadata and _recordtypedef.metadata.usage then
$( applytemplate(_recordtypedef.metadata.usage, i) )
#end
# --
# -- Describe type fields
# --
#if not isempty( _recordtypedef.fields ) then
<h$(i)>Field(s)</h$(i)>
# for name, item in sortedpairs( _recordtypedef.fields ) do
$( applytemplate(item, i) )
# end
#end ]]

View File

@@ -0,0 +1,33 @@
--------------------------------------------------------------------------------
-- Copyright (c) 2012-2014 Sierra Wireless.
-- All rights reserved. This program and the accompanying materials
-- are made available under the terms of the Eclipse Public License v1.0
-- which accompanies this distribution, and is available at
-- http://www.eclipse.org/legal/epl-v10.html
--
-- Contributors:
-- Marc AUBRY <maubry@sierrawireless.com>
-- - initial API and implementation
--------------------------------------------------------------------------------
return[[#
#--
#-- Show usage samples
#--
#if _usage then
# if #_usage > 1 then
# -- Show all usages
<h$(i)>Usages:</h$(i)>
<ul>
# -- Loop over several usage description
# for _, usage in ipairs(_usage) do
<li><pre class="example"><code>$( securechevrons(usage.description) )</code></pre></li>
# end
</ul>
# elseif #_usage == 1 then
# -- Show unique usage sample
<h$(i)>Usage:</h$(i)>
# local usage = _usage[1]
<pre class="example"><code>$( securechevrons(usage.description) )</code></pre>
# end
#end
#]]

View File

@@ -0,0 +1,470 @@
--------------------------------------------------------------------------------
-- Copyright (c) 2012-2014 Sierra Wireless.
-- All rights reserved. This program and the accompanying materials
-- are made available under the terms of the Eclipse Public License v1.0
-- which accompanies this distribution, and is available at
-- http://www.eclipse.org/legal/epl-v10.html
--
-- Contributors:
-- Kevin KIN-FOO <kkinfoo@sierrawireless.com>
-- - initial API and implementation and initial documentation
--------------------------------------------------------------------------------
local apimodel = require 'models.apimodel'
---
-- @module docutils
-- Handles link generation, node quick description.
--
-- Provides:
-- * link generation
-- * anchor generation
-- * node quick description
local M = {}
function M.isempty(map)
local f = pairs(map)
return f(map) == nil
end
---
-- Provide a handling function for all supported anchor types
-- recordtypedef => #(typename)
-- item (field of recordtypedef) => #(typename).itemname
-- item (global) => itemname
M.anchortypes = {
recordtypedef = function (o) return string.format('#(%s)', o.name) end,
item = function(o)
if not o.parent or o.parent.tag == 'file' then
-- Handle items referencing globals
return o.name
elseif o.parent and o.parent.tag == 'recordtypedef' then
-- Handle items included in recordtypedef
local recordtypedef = o.parent
local recordtypedefanchor = M.anchor(recordtypedef)
if not recordtypedefanchor then
return nil, 'Unable to generate anchor for `recordtypedef parent.'
end
return string.format('%s.%s', recordtypedefanchor, o.name)
end
return nil, 'Unable to generate anchor for `item'
end
}
---
-- Provides anchor string for an object of API mode
--
-- @function [parent = #docutils] anchor
-- @param modelobject Object form API model
-- @result #string Anchor for an API model object, this function __may rise an error__
-- @usage # -- In a template
-- # local anchorname = anchor(someobject)
-- <a id="$(anchorname)" />
function M.anchor( modelobject )
local tag = modelobject.tag
if M.anchortypes[ tag ] then
return M.anchortypes[ tag ](modelobject)
end
return nil, string.format('No anchor available for `%s', tag)
end
local function getexternalmodule( item )
-- Get file which contains this item
local file
if item.parent then
if item.parent.tag =='recordtypedef' then
local recordtypedefparent = item.parent.parent
if recordtypedefparent and recordtypedefparent.tag =='file'then
file = recordtypedefparent
end
elseif item.parent.tag =='file' then
file = item.parent
else
return nil, 'Unable to fetch item parent'
end
end
return file
end
---
-- Provide a handling function for all supported link types
--
-- internaltyperef => ##(typename)
-- => #anchor(recordtyperef)
-- externaltyperef => modulename.html##(typename)
-- => linkto(file)#anchor(recordtyperef)
-- file(module) => modulename.html
-- index => index.html
-- recordtypedef => ##(typename)
-- => #anchor(recordtyperef)
-- item (internal field of recordtypedef) => ##(typename).itemname
-- => #anchor(item)
-- item (internal global) => #itemname
-- => #anchor(item)
-- item (external field of recordtypedef) => modulename.html##(typename).itemname
-- => linkto(file)#anchor(item)
-- item (externalglobal) => modulename.html#itemname
-- => linkto(file)#anchor(item)
M.linktypes = {
internaltyperef = function(o) return string.format('##(%s)', o.typename) end,
externaltyperef = function(o) return string.format('%s.html##(%s)', o.modulename, o.typename) end,
file = function(o) return string.format('%s.html', o.name) end,
index = function() return 'index.html' end,
recordtypedef = function(o)
local anchor = M.anchor(o)
if not anchor then
return nil, 'Unable to generate anchor for `recordtypedef.'
end
return string.format('#%s', anchor)
end,
item = function(o)
-- For every item get anchor
local anchor = M.anchor(o)
if not anchor then
return nil, 'Unable to generate anchor for `item.'
end
-- Built local link to item
local linktoitem = string.format('#%s', anchor)
--
-- For external item, prefix with the link to the module.
--
-- The "external item" concept is used only here for short/embedded
-- notation purposed. This concept and the `.external` field SHALL NOT
-- be used elsewhere.
--
if o.external then
-- Get link to file which contains this item
local file = getexternalmodule( o )
local linktofile = file and M.linkto( file )
if not linktofile then
return nil, 'Unable to generate link for external `item.'
end
-- Built external link to item
linktoitem = string.format("%s%s", linktofile, linktoitem)
end
return linktoitem
end
}
---
-- Generates text for HTML links from API model element
--
-- @function [parent = #docutils]
-- @param modelobject Object form API model
-- @result #string Links text for an API model element, this function __may rise an error__.
-- @usage # -- In a template
-- <a href="$( linkto(api) )">Some text</a>
function M.linkto( apiobject )
local tag = apiobject.tag
if M.linktypes[ tag ] then
return M.linktypes[tag](apiobject)
end
if not tag then
return nil, 'Link generation is impossible as no tag has been provided.'
end
return nil, string.format('No link generation available for `%s.', tag)
end
---
-- Provide a handling function for all supported pretty name types
-- primitivetyperef => #typename
-- internaltyperef => #typename
-- externaltyperef => modulename#typename
-- file(module) => modulename
-- index => index
-- recordtypedef => typename
-- item (internal function of recordtypedef) => typename.itemname(param1, param2,...)
-- item (internal func with self of recordtypedef) => typename:itemname(param2)
-- item (internal non func field of recordtypedef) => typename.itemname
-- item (internal func global) => functionname(param1, param2,...)
-- item (internal non func global) => itemname
-- item (external function of recordtypedef) => modulename#typename.itemname(param1, param2,...)
-- item (external func with self of recordtypedef) => modulename#typename:itemname(param2)
-- item (external non func field of recordtypedef) => modulename#typename.itemname
-- item (external func global) => functionname(param1, param2,...)
-- item (external non func global) => itemname
M.prettynametypes = {
primitivetyperef = function(o) return string.format('#%s', o.typename) end,
externaltyperef = function(o) return string.format('%s#%s', o.modulename, o.typename) end,
index = function(o) return "index" end,
file = function(o) return o.name end,
recordtypedef = function(o) return o.name end,
item = function( o )
-- Determine item name
-- ----------------------
local itemname = o.name
-- Determine scope
-- ----------------------
local parent = o.parent
local isglobal = parent and parent.tag == 'file'
local isfield = parent and parent.tag == 'recordtypedef'
-- Determine type name
-- ----------------------
local typename = isfield and parent.name
-- Fetch item definition
-- ----------------------
-- Get file object
local file
if isglobal then
file = parent
elseif isfield then
file = parent.parent
end
-- Get definition
local definition = o:resolvetype (file)
-- Build prettyname
-- ----------------------
local prettyname
if not definition or definition.tag ~= 'functiontypedef' then
-- Fields
if isglobal or not typename then
prettyname = itemname
else
prettyname = string.format('%s.%s', typename, itemname)
end
else
-- Functions
-- Build parameter list
local paramlist = {}
local isinvokable = M.isinvokable(o)
for position, param in ipairs(definition.params) do
-- For non global function, when first parameter is 'self',
-- it will not be part of listed parameters
if not (position == 1 and isinvokable and isfield) then
table.insert(paramlist, param.name)
if position ~= #definition.params then
table.insert(paramlist, ', ')
end
end
end
if isglobal or not typename then
prettyname = string.format('%s(%s)',itemname, table.concat(paramlist))
else
-- Determine function prefix operator,
-- ':' if 'self' is first parameter, '.' else way
local operator = isinvokable and ':' or '.'
-- Append function parameters
prettyname = string.format('%s%s%s(%s)',typename, operator, itemname, table.concat(paramlist))
end
end
-- Manage external Item prettyname
-- ----------------------
local externalmodule = o.external and getexternalmodule( o )
local externalmodulename = externalmodule and externalmodule.name
if externalmodulename then
return string.format('%s#%s',externalmodulename,prettyname)
else
return prettyname
end
end
}
M.prettynametypes.internaltyperef = M.prettynametypes.primitivetyperef
---
-- Check if the given item is a function that can be invoked
function M.isinvokable(item)
--test if the item is global
if item.parent and item.parent.tag == 'file' then
return false
end
-- check first param
local definition = item:resolvetype()
if definition and definition.tag == 'functiontypedef' then
if (#definition.params > 0) then
return definition.params[1].name == 'self'
end
end
end
---
-- Provide human readable overview from an API model element
--
-- Resolve all element needed to summurize nicely an element form API model.
-- @usage $ print( prettyname(item) )
-- module:somefunction(secondparameter)
-- @function [parent = #docutils]
-- @param apiobject Object form API model
-- @result #string Human readable description of given element.
-- @result #nil, #string In case of error.
function M.prettyname( apiobject )
local tag = apiobject.tag
if M.prettynametypes[tag] then
return M.prettynametypes[tag](apiobject)
elseif not tag then
return nil, 'No pretty name available as no tag has been provided.'
end
return nil, string.format('No pretty name for `%s.', tag)
end
---
-- Just make a string print table in HTML.
-- @function [parent = #docutils] securechevrons
-- @param #string String to convert.
-- @usage securechevrons('<markup>') => '&lt;markup&gt;'
-- @return #string Converted string.
function M.securechevrons( str )
if not str then return nil, 'String expected.' end
return string.gsub(str:gsub('<', '&lt;'), '>', '&gt;')
end
-------------------------------------------------------------------------------
-- Handling format of @{some#type} tag.
-- Following functions enable to recognize several type of references between
-- "{}".
-------------------------------------------------------------------------------
---
-- Provide API Model elements from string describing global elements
-- such as:
-- * `global#foo`
-- * `foo#global.bar`
local globals = function(str)
-- Handling globals from modules
for modulename, fieldname in str:gmatch('([%a%.%d_]+)#global%.([%a%.%d_]+)') do
local item = apimodel._item(fieldname)
local file = apimodel._file()
file.name = modulename
file:addglobalvar( item )
return item
end
-- Handling other globals
for name in str:gmatch('global#([%a%.%d_]+)') do
-- print("globale", name)
return apimodel._externaltypref('global', name)
end
return nil
end
---
-- Transform a string like `module#(type).field` in an API Model item
local field = function( str )
-- Match `module#type.field`
local mod, typename, fieldname = str:gmatch('([%a%.%d_]*)#([%a%.%d_]+)%.([%a%.%d_]+)')()
-- Try matching `module#(type).field`
if not mod then
mod, typename, fieldname = str:gmatch('([%a%.%d_]*)#%(([%a%.%d_]+)%)%.([%a%.%d_]+)')()
if not mod then
-- No match
return nil
end
end
-- Build according `item
local modulefielditem = apimodel._item( fieldname )
local moduletype = apimodel._recordtypedef(typename)
moduletype:addfield( modulefielditem )
local typeref
if #mod > 0 then
local modulefile = apimodel._file()
modulefile.name = mod
modulefile:addtype( moduletype )
typeref = apimodel._externaltypref(mod, typename)
modulefielditem.external = true
else
typeref = apimodel._internaltyperef(typename)
end
modulefielditem.type = typeref
return modulefielditem
end
---
-- Build an API internal reference from a string like: `#typeref`
local internal = function ( typestring )
for name in typestring:gmatch('#([%a%.%d_]+)') do
-- Do not handle this name is it starts with reserved name "global"
if name:find("global.") == 1 then return nil end
return apimodel._internaltyperef(name)
end
return nil
end
---
-- Build an API external reference from a string like: `mod.ule#type`
local extern = function (type)
-- Match `mod.ule#ty.pe`
local modulename, typename = type:gmatch('([%a%.%d_]+)#([%a%.%d_]+)')()
-- Trying `mod.ule#(ty.pe)`
if not modulename then
modulename, typename = type:gmatch('([%a%.%d_]+)#%(([%a%.%d_]+)%)')()
-- No match at all
if not modulename then
return nil
end
end
return apimodel._externaltypref(modulename, typename)
end
---
-- Build an API external reference from a string like: `mod.ule`
local file = function (type)
for modulename in type:gmatch('([%a%.%d_]+)') do
local file = apimodel._file()
file.name = modulename
return file
end
return nil
end
---
-- Provide API Model element from a string
-- @usage local externaltyperef = getelement("somemodule#somefield")
function M.getelement( str )
-- Order matters, more restrictive are at begin of table
local extractors = {
globals,
field,
extern,
internal,
file
}
-- Loop over extractors.
-- First valid result is used
for _, extractor in ipairs( extractors ) do
local result = extractor( str )
if result then return result end
end
return nil
end
--------------------------------------------------------------------------------
-- Iterator that iterates on the table in key ascending order.
--
-- @function [parent=#utils.table] sortedPairs
-- @param t table to iterate.
-- @return iterator function.
function M.sortedpairs(t)
local a = {}
local insert = table.insert
for n in pairs(t) do insert(a, n) end
table.sort(a)
local i = 0
return function()
i = i + 1
return a[i], t[a[i]]
end
end
return M