Files
eepp/docs/doxyrest/frame/cfamily/utils.lua
2022-03-11 11:51:07 -03:00

1166 lines
29 KiB
Lua

--------------------------------------------------------------------------------
--
-- This file is part of the Doxyrest toolkit.
--
-- Doxyrest is distributed under the MIT license.
-- For details see accompanying license.txt file,
-- the public copy of which is also available at:
-- http://tibbo.com/downloads/archive/doxyrest/license.txt
--
--------------------------------------------------------------------------------
g_cfamilyUtilsIncluded = true
dofile(g_frameDir .. "/../common/string.lua")
dofile(g_frameDir .. "/../common/table.lua")
dofile(g_frameDir .. "/../common/item.lua")
dofile(g_frameDir .. "/../common/doc.lua")
dofile(g_frameDir .. "/../common/toc.lua")
if not LANGUAGE then
LANGUAGE = "cpp"
end
if not INDEX_TITLE then
INDEX_TITLE = "My Project Documentation"
end
if not EXTRA_PAGE_LIST then
EXTRA_PAGE_LIST = {}
end
if not EXTERNAL_CREF_DB then
EXTERNAL_CREF_DB = {}
end
if ML_PARAM_LIST_COUNT_THRESHOLD then
ML_PARAM_LIST_COUNT_THRESHOLD = tonumber(ML_PARAM_LIST_COUNT_THRESHOLD)
end
if ML_PARAM_LIST_LENGTH_THRESHOLD then
ML_PARAM_LIST_LENGTH_THRESHOLD = tonumber(ML_PARAM_LIST_LENGTH_THRESHOLD)
end
if string.match(LANGUAGE, "^c[px+]*$") then
g_nameDelimiter = "::"
else
g_nameDelimiter = "."
end
g_protectionKindMap = {
public = 0,
protected = 1,
private = 2,
package = 3,
}
g_protectionNameMap = {
[0] = "public",
[1] = "protected",
[2] = "private",
[3] = "package",
}
g_minProtectionValue = 0
g_maxProtectionValue = 3
if PROTECTION_FILTER then
g_protectionFilterValue = g_protectionKindMap[PROTECTION_FILTER]
else
g_protectionFilterValue = 0
end
if PRE_PARAM_LIST_SPACE then
g_preParamSpace = " "
g_preOperatorParamSpace = ""
elseif PRE_OPERATOR_PARAM_LIST_SPACE then
g_preParamSpace = ""
g_preOperatorParamSpace = " "
else
g_preParamSpace = ""
g_preOperatorParamSpace = ""
end
if PRE_OPERATOR_NAME_SPACE then
g_preOperatorNameSpace = " "
else
g_preOperatorNameSpace = ""
end
if PRE_BODY_NL then
g_preBodySpace = "\n\t"
else
g_preBodySpace = " "
end
if not g_globalNamespace.title then
g_globalNamespace.title = "Global Namespace"
end
g_currentCompoundId = nil
-------------------------------------------------------------------------------
function getNormalizedCppString(string)
local s = string
s = string.gsub(s, "%s*%*", "*")
s = string.gsub(s, "%s*&", "&")
s = string.gsub(s, "%s*<%s*", g_preParamSpace .. "<")
s = string.gsub(s, "%s+>", ">")
s = string.gsub(s, "%s*%(%s*", g_preParamSpace .. "(")
s = string.gsub(s, "%s+%)", ")")
return s
end
function getLinkedTextString(text, isRef)
if not text then
return ""
end
if not isRef then
return getNormalizedCppString(text.plainText)
end
local s = ""
for i = 1, #text.refTextArray do
local refText = text.refTextArray[i]
local text = getNormalizedCppString(refText.text)
if refText.id ~= "" and refText.id ~= g_currentCompoundId then
text = string.gsub(text, "<", "\\<") -- escape left chevron
s = s .. ":ref:`" .. text .. "<doxid-" .. refText.id .. ">`"
else
s = s .. text
end
end
s = string.gsub(s, "\n", " ") -- callsites of getLinkedTextString don't expect newline chars
return s
end
function findLinkedTextEnum(text)
for i = 1, #text.refTextArray do
local refText = text.refTextArray[i]
if refText.id ~= "" then
local member = findMemberById(refText.id)
if member ~= nil and member.memberKind == "enum" then
return member
end
end
end
return nil
end
-------------------------------------------------------------------------------
-- param array formatting
function getParamString(param, isRef)
local s = ""
local name
if not param.type.isEmpty then
s = s .. getLinkedTextString(param.type, isRef)
end
if param.declarationName ~= "" then
name = param.declarationName
else
name = param.definitionName
end
if name ~= "" then
if s ~= "" then
s = s .. " "
end
s = s .. getNormalizedCppString(name)
end
if param.array ~= "" then
s = s .. g_preParamSpace .. param.array
end
if not param.defaultValue.isEmpty then
s = s .. " = " .. getLinkedTextString(param.defaultValue, isRef)
end
return s
end
function getParamArrayString_sl(paramArray, isRef, lbrace, rbrace)
local s
local count = #paramArray
if count == 0 then
s = lbrace .. rbrace
else
s = lbrace .. getParamString(paramArray[1], isRef)
for i = 2, count do
s = s .. ", " .. getParamString(paramArray[i], isRef)
end
s = s .. rbrace
end
return s
end
function getParamArrayString_ml(paramArray, isRef, lbrace, rbrace, indent, nl)
local s
local count = #paramArray
if count == 0 then
s = lbrace .. rbrace
elseif count == 1 then
s = lbrace .. getParamString(paramArray[1], isRef) .. rbrace
else
s = lbrace .. nl
for i = 1, count do
s = s .. indent .. "\t" .. getParamString(paramArray[i], isRef)
if i ~= count then
s = s .. ","
end
s = s .. nl
end
s = s .. indent .. rbrace
end
return s
end
function getParamArrayString(prefix, paramArray, isRef, lbrace, rbrace, indent, nl)
if not lbrace then
lbrace = "("
end
if not rbrace then
rbrace = ")"
end
if not indent then
indent = "\t"
end
if not nl then
nl = "\n"
end
local s = ""
local space = ""
if PRE_PARAM_LIST_SPACE then
space = " "
end
if ML_PARAM_LIST_COUNT_THRESHOLD and
#paramArray > ML_PARAM_LIST_COUNT_THRESHOLD then
s = getParamArrayString_ml(paramArray, isRef, lbrace, rbrace, indent, nl)
else
s = getParamArrayString_sl(paramArray, isRef, lbrace, rbrace)
if ML_PARAM_LIST_LENGTH_THRESHOLD then
local decl = prefix .. space .. s
decl = replaceRolesWithPlainText(decl)
if string.len(decl) > ML_PARAM_LIST_LENGTH_THRESHOLD then
s = getParamArrayString_ml(paramArray, isRef, lbrace, rbrace, indent, nl)
end
end
end
s = space .. s
return s
end
-------------------------------------------------------------------------------
function getItemKindString(item, itemKindString)
local s = ""
if item.modifiers ~= "" then
s = item.modifiers .. " "
end
s = s .. itemKindString
return s
end
function getItemImportArray(item)
if item.importArray and next(item.importArray) ~= nil then
return item.importArray
end
local text = getItemInternalDocumentation(item)
local importArray = {}
local i = 1
for import in string.gmatch(text, ":import%(([^:]+)%)") do
importArray[i] = import
i = i + 1
end
return importArray
end
function getItemImportString(item)
local importArray = getItemImportArray(item)
if next(importArray) == nil then
return ""
end
local indent = getLineText()
local importPrefix
local importSuffix
if string.match(LANGUAGE, "^c[px+]*$") or LANGUAGE == "idl" then
importPrefix = "#include <"
importSuffix = ">\n" .. indent
elseif string.match(LANGUAGE, "^ja?ncy?$") then
importPrefix = "import \""
importSuffix = "\"\n" .. indent
else
importPrefix = "import "
importSuffix = "\n" .. indent
end
local s = ""
for i = 1, #importArray do
local import = importArray[i]
s = s .. importPrefix .. import .. importSuffix
end
return s
end
function getEnumImportString(item)
local importArray = getItemImportArray(item)
if next(importArray) ~= nil then
return getItemImportArray(item)
end
local file = string.gsub(item.location.file, ".*[\\/]", "")
if string.match(LANGUAGE, "^c[px+]*$") and string.match(file, "%.h[px+]*$") then
return "#include <" .. file .. ">\n"
else
return ""
end
end
function getTemplateSpecSuffix(item)
if not item.templateSpecParamArray or #item.templateSpecParamArray == 0 then
return ""
end
return getParamArrayString_sl(item.templateSpecParamArray, false, "<", ">")
end
function getItemSimpleName(item)
return item.name .. getTemplateSpecSuffix(item)
end
function getItemQualifiedName(item)
local name = string.gsub(item.path, "/", g_nameDelimiter)
return name .. getTemplateSpecSuffix(item)
end
getItemName = getItemQualifiedName
function getItemNameForOverview(item)
local template = getItemNameTemplate(item)
local name = getItemName(item)
return fillItemNameTemplate(template, name, item.id)
end
function getFunctionModifierDelimiter(indent)
if ML_SPECIFIER_MODIFIER_LIST then
return "\n" .. indent
else
return " "
end
end
function getPropertyDeclString(item, nameTemplate, indent)
local s = getLinkedTextString(item.returnType, true)
if item.modifiers ~= "" then
s = string.gsub(s, "property$", item.modifiers .. " property")
end
s = s .. getFunctionModifierDelimiter(indent)
s = s .. fillItemNameTemplate(nameTemplate, getItemName(item), item.id)
if #item.paramArray > 0 then
s = s .. getParamArrayString(s, item.paramArray, true, "(", ")", indent)
end
return s
end
function getFunctionDeclStringImpl(item, returnType, nameTemplate, indent)
local s = ""
if item.templateParamArray and #item.templateParamArray > 0 or
item.templateSpecParamArray and #item.templateSpecParamArray > 0 then
s = "template " .. getParamArrayString(s, item.templateParamArray, false, "<", ">") .. "\n" .. indent
end
if string.find(item.flags, "static") then
s = s .. "static" .. getFunctionModifierDelimiter(indent)
elseif item.virtualKind == "pure-virtual" then
s = s .. "virtual" .. getFunctionModifierDelimiter(indent)
elseif item.virtualKind ~= "non-virtual" then
s = s .. item.virtualKind .. getFunctionModifierDelimiter(indent)
end
if returnType and returnType ~= "" then
s = s .. returnType .. getFunctionModifierDelimiter(indent)
end
if item.modifiers ~= "" then
s = s .. item.modifiers .. getFunctionModifierDelimiter(indent)
end
local name = getItemName(item)
local isOperator = string.find(name, "operator")
if isOperator then
name = string.gsub(
name,
"operator%s*([()[%]+%-*&=!<>]+)%s*",
"operator" .. g_preOperatorNameSpace .. "%1"
)
name = string.gsub(name, "%%", "%%%%")
end
s = s .. fillItemNameTemplate(nameTemplate, name, item.id)
if isOperator then -- ensure spacce after operator
s = s .. g_preOperatorParamSpace
end
s = s .. getParamArrayString(s, item.paramArray, true, "(", ")", indent)
if string.find(item.flags, "const") then
s = s .. " const"
end
if item.virtualKind == "pure-virtual" then
s = s .. " = 0"
end
return s
end
function getFunctionDeclString(func, nameTemplate, indent)
return getFunctionDeclStringImpl(
func,
getLinkedTextString(func.returnType, true),
nameTemplate,
indent
)
end
function getVoidFunctionDeclString(func, nameTemplate, indent)
return getFunctionDeclStringImpl(
func,
nil,
nameTemplate,
indent
)
end
function getEventDeclString(event, nameTemplate, indent)
return getFunctionDeclStringImpl(
event,
"event",
nameTemplate,
indent
)
end
function getDefineDeclString(define, nameTemplate, indent)
local s = "#define "
s = s .. fillItemNameTemplate(nameTemplate, define.name, define.id)
if #define.paramArray > 0 then
-- no space between name and params!
s = s .. getParamArrayString(s, define.paramArray, false, "(", ")", indent, " \\\n")
end
return s
end
function getTypedefDeclString(typedef, nameTemplate, indent)
local s
local name = fillItemNameTemplate(nameTemplate, getItemName(typedef), typedef.id)
local declName
if TYPEDEF_TO_USING then
s = "using " .. name .. " ="
declName = ""
else
s = "typedef"
declName = name
end
if next(typedef.paramArray) == nil then
local type = getLinkedTextString(typedef.type, true)
if string.match(type, "%(%*$") then -- quickfix for function pointers
s = s .. " " .. string.sub(type, 1, -3) .. " (*"
else
s = s .. " " .. type .. " "
end
s = s .. declName
if typedef.argString ~= "" then
s = s .. formatArgDeclString(typedef.argString, indent)
end
return s
end
s = s .. getFunctionModifierDelimiter(indent) .. getLinkedTextString(typedef.type, true) .. getFunctionModifierDelimiter(indent)
s = s .. declName
s = s .. getParamArrayString(s, typedef.paramArray, true, "(", ")", indent)
return s
end
function getClassDeclString(class, nameTemplate, indent)
local s = ""
if #class.templateParamArray > 0 or #class.templateSpecParamArray > 0 then
s = "template"
if not PRE_PARAM_LIST_SPACE then
s = s .. " "
end
s = s .. getParamArrayString(s, class.templateParamArray, false, "<", ">", indent) .. "\n" .. indent
end
s = s .. class.compoundKind .. " "
s = s .. fillItemNameTemplate(nameTemplate, getItemName(class), class.id)
return s
end
function getBaseClassString(class, protection)
local s = ""
if string.match(LANGUAGE, "^c[px+]*$") then
s = protection .. " "
end
if class.id ~= "" then
s = s .. ":ref:`" .. getItemQualifiedName(class) .. "<doxid-" .. class.id .. ">`"
else
-- class without id (imported)
local url = EXTERNAL_CREF_DB[class.name]
if url then
s = s .. ":ref:`" .. class.name .. "<" .. url .. ">`"
else
s = s .. class.name
end
end
return s
end
function isMemberOfUnnamedType(item)
local text = getItemInternalDocumentation(item)
return string.match(text, ":unnamed%(([%w/:]+)%)")
end
g_closingBracketChar =
{
["("] = ")",
["["] = "]",
["<"] = ">",
["{"] = "}",
}
function formatArgDeclString(decl, indent)
local bracket = {}
bracket[0] = {}
bracket[0].result = ""
local level = 0
local pos = 1
local len = string.len(decl)
for i = 1, len do
local c = string.sub(decl, i, i)
if c == "(" or c == "[" or c == "<" or c == "{" then
local chunk = trimLeadingWhitespace(string.sub(decl, pos, i))
pos = i + 1
bracket[level].result = bracket[level].result .. chunk
level = level + 1
bracket[level] = {}
bracket[level].closingChar = g_closingBracketChar[c]
bracket[level].result = ""
elseif level > 0 then
if c == ',' then
if not bracket[level].delimiter then
bracket[level].delimiter = "\n" .. indent .. string.rep("\t", level)
bracket[level].result = bracket[level].delimiter .. bracket[level].result
end
local chunk = trimLeadingWhitespace(string.sub(decl, pos, i))
pos = i + 1
bracket[level].result = bracket[level].result .. chunk .. bracket[level].delimiter
pos = i + 1
elseif c == bracket[level].closingChar then
local chunk = trimLeadingWhitespace(string.sub(decl, pos, i - 1))
pos = i
bracket[level].result = bracket[level].result .. chunk
if bracket[level].delimiter then
bracket[level].result = bracket[level].result .. bracket[level].delimiter
end
level = level - 1
bracket[level].result = bracket[level].result .. bracket[level + 1].result
end
end
end
if pos <= len then
bracket[0].result = bracket[0].result .. string.sub(decl, pos)
end
return bracket[0].result
end
function getNamespaceTree(nspace, indent)
local s = ""
if not indent then
indent = ""
end
s = "\t" .. indent .. "namespace :ref:`" .. getItemQualifiedName(nspace) .. "<doxid-" .. nspace.id ..">`;\n"
for i = 1, #nspace.namespaceArray do
s = s .. getNamespaceTree(nspace.namespaceArray[i], indent .. "\t")
end
return s
end
-------------------------------------------------------------------------------
-- item filtering utils
function getDefaultProtectionKind(compound)
if compound.compoundKind ~= "class" or string.match(LANGUAGE, "^ja?ncy?$") then
return 0
else
return 2
end
end
function getProtectionValue(protectionKind)
local protectionValue = g_protectionKindMap[protectionKind]
if not protectionValue then
protectionValue = 0 -- assume public
end
return protectionValue
end
function isItemExcludedByProtectionFilter(item)
local protectionValue = g_protectionKindMap[item.protectionKind]
if protectionValue and protectionValue > g_protectionFilterValue then
return true
end
return false
end
function hasNonPublicItems(array)
if next(array) == nil then
return false
end
local lastItem = array[#array]
local protectionValue = g_protectionKindMap[lastItem.protectionKind]
return protectionValue and protectionValue > 0
end
function isItemExcludedByLocationFilter(item)
if not item.location then
return false
end
return
-- exclude explicitly specified locations
EXCLUDE_LOCATION_PATTERN and
string.match(item.location.file, EXCLUDE_LOCATION_PATTERN)
end
function filterItemArray(itemArray)
if next(itemArray) == nil then
return
end
for i = #itemArray, 1, -1 do
local item = itemArray[i]
local isExcluded =
isItemExcludedByProtectionFilter(item) or
isItemExcludedByLocationFilter(item)
if isExcluded then
table.remove(itemArray, i)
end
end
end
function filterEnumArray(enumArray)
if next(enumArray) == nil then
return
end
for i = #enumArray, 1, -1 do
local enum = enumArray[i]
local isExcluded =
isItemExcludedByProtectionFilter(enum) or
isItemExcludedByLocationFilter(enum) or
isUnnamedItem(enum) and #enum.enumValueArray == 0
if isExcluded then
table.remove(enumArray, i)
end
end
end
function filterNamespaceArray(namespaceArray)
if next(namespaceArray) == nil then
return
end
for i = #namespaceArray, 1, -1 do
local item = namespaceArray[i]
local isExcluded =
isUnnamedItem(item) or
isItemExcludedByLocationFilter(item)
if isExcluded then
table.remove(namespaceArray, i)
end
end
end
function filterConstructorArray(constructorArray)
filterItemArray(constructorArray)
if #constructorArray == 1 then
local item = constructorArray[1]
local isExcluded =
isItemExcludedByProtectionFilter(item) or
EXCLUDE_DEFAULT_CONSTRUCTORS and #item.paramArray == 0
if isExcluded then
table.remove(constructorArray, 1)
end
end
end
function filterDefineArray(defineArray)
if next(defineArray) == nil then
return
end
for i = #defineArray, 1, -1 do
local item = defineArray[i]
local isExcluded =
isItemExcludedByLocationFilter(item) or
EXCLUDE_DEFINE_PATTERN and string.match(item.name, EXCLUDE_DEFINE_PATTERN) or
EXCLUDE_EMPTY_DEFINES and item.initializer.isEmpty and
item.briefDescription.isEmpty and item.detailedDescription.isEmpty
if isExcluded then
table.remove(defineArray, i)
end
end
end
function filterTypedefArray(typedefArray)
if next(typedefArray) == nil then
return
end
for i = #typedefArray, 1, -1 do
local item = typedefArray[i]
local isExcluded =
isItemExcludedByProtectionFilter(item) or
isItemExcludedByLocationFilter(item)
if not isExcluded and EXCLUDE_PRIMITIVE_TYPEDEFS then
local typeKind, name = string.match(
item.type.plainText,
"(%a+)%s+(%w[%w_]*)"
)
if name == item.name then
isExcluded =
item.briefDescription.isEmpty and
item.detailedDescription.isEmpty
end
end
if isExcluded then
table.remove(typedefArray, i)
end
end
end
-------------------------------------------------------------------------------
-- base compound is an artificial compound holding all inherited members
function addToBaseCompound(baseCompound, baseTypeArray)
for i = 1, #baseTypeArray do
local baseType = baseTypeArray[i]
-- prevent adding the same base type multiple times
if not baseCompound.baseTypeMap[baseType] and
baseType.compoundKind ~= "<undefined>" then
baseCompound.baseTypeMap[baseType] = true
prepareCompound(baseType)
if next(baseType.baseTypeArray) ~= nil then
addToBaseCompound(baseCompound, baseType.baseTypeArray)
end
concatenateTables(baseCompound.typedefArray, baseType.typedefArray)
concatenateTables(baseCompound.enumArray, baseType.enumArray)
concatenateTables(baseCompound.structArray, baseType.structArray)
concatenateTables(baseCompound.unionArray, baseType.unionArray)
concatenateTables(baseCompound.interfaceArray, baseType.interfaceArray)
concatenateTables(baseCompound.protocolArray, baseType.protocolArray)
concatenateTables(baseCompound.exceptionArray, baseType.exceptionArray)
concatenateTables(baseCompound.classArray, baseType.classArray)
concatenateTables(baseCompound.singletonArray, baseType.singletonArray)
concatenateTables(baseCompound.serviceArray, baseType.serviceArray)
concatenateTables(baseCompound.variableArray, baseType.variableArray)
concatenateTables(baseCompound.propertyArray, baseType.propertyArray)
concatenateTables(baseCompound.eventArray, baseType.eventArray)
concatenateTables(baseCompound.functionArray, baseType.functionArray)
concatenateTables(baseCompound.aliasArray, baseType.aliasArray)
end
end
end
function createPseudoCompound(compoundKind)
local compound = {}
compound.compoundKind = compoundKind
compound.baseTypeMap = {}
compound.namespaceArray = {}
compound.typedefArray = {}
compound.enumArray = {}
compound.structArray = {}
compound.unionArray = {}
compound.interfaceArray = {}
compound.protocolArray = {}
compound.exceptionArray = {}
compound.classArray = {}
compound.singletonArray = {}
compound.serviceArray = {}
compound.variableArray = {}
compound.propertyArray = {}
compound.eventArray = {}
compound.constructorArray = {}
compound.functionArray = {}
compound.aliasArray = {}
compound.defineArray = {}
return compound
end
function createBaseCompound(compound)
local baseCompound = createPseudoCompound("base-compound")
baseCompound.isBaseCompound = true
addToBaseCompound(baseCompound, compound.baseTypeArray)
baseCompound.hasItems = hasCompoundItems(baseCompound)
handleCompoundProtection(baseCompound)
compound.baseCompound = baseCompound
end
function sortByProtection(array)
if next(array) == nil then
return
end
local bucketArray = {}
for i = g_minProtectionValue, g_maxProtectionValue do
bucketArray[i] = {}
end
for i = 1, #array do
local item = array[i]
local protectionValue = getProtectionValue(item.protectionKind)
table.insert(bucketArray[protectionValue], item)
end
local result = {}
local k = 1
for i = g_minProtectionValue, g_maxProtectionValue do
local bucket = bucketArray[i]
for j = 1, #bucket do
array[k] = bucket[j]
k = k + 1
end
end
assert(k == #array + 1)
return #array - #bucketArray[0]
end
function addToProtectionCompounds(compound, arrayName)
local array = compound[arrayName]
if next(array) == nil then
return
end
for i = 1, #array do
local item = array[i]
local protectionValue = getProtectionValue(item.protectionKind)
local protectionCompound = compound.protectionCompoundArray[protectionValue]
local targetArray = protectionCompound[arrayName]
table.insert(targetArray, item)
protectionCompound.isEmpty = false
end
end
function handleCompoundProtection(compound)
compound.protectionCompoundArray = {}
for i = g_minProtectionValue, g_maxProtectionValue do
local protectionCompound = createPseudoCompound("protection-compound")
protectionCompound.isEmpty = true
protectionCompound.isBaseCompound = compound.isBaseCompound
compound.protectionCompoundArray[i] = protectionCompound
end
addToProtectionCompounds(compound, "namespaceArray")
addToProtectionCompounds(compound, "typedefArray")
addToProtectionCompounds(compound, "enumArray")
addToProtectionCompounds(compound, "structArray")
addToProtectionCompounds(compound, "unionArray")
addToProtectionCompounds(compound, "interfaceArray")
addToProtectionCompounds(compound, "protocolArray")
addToProtectionCompounds(compound, "exceptionArray")
addToProtectionCompounds(compound, "classArray")
addToProtectionCompounds(compound, "singletonArray")
addToProtectionCompounds(compound, "serviceArray")
addToProtectionCompounds(compound, "variableArray")
addToProtectionCompounds(compound, "propertyArray")
addToProtectionCompounds(compound, "eventArray")
addToProtectionCompounds(compound, "constructorArray")
addToProtectionCompounds(compound, "functionArray")
addToProtectionCompounds(compound, "aliasArray")
addToProtectionCompounds(compound, "defineArray")
if compound.destructor then
local protectionValue = getProtectionValue(compound.destructor.protectionKind)
local protectionCompound = compound.protectionCompoundArray[protectionValue]
protectionCompound.destructor = compound.destructor
protectionCompound.isEmpty = false
end
-- eliminate empty protection compounds
for i = g_minProtectionValue, g_maxProtectionValue do
if compound.protectionCompoundArray[i].isEmpty then
compound.protectionCompoundArray[i] = nil
end
end
end
-------------------------------------------------------------------------------
-- compound & enum prep
function hasCompoundItems(compound)
return
#compound.namespaceArray ~= 0 or
#compound.typedefArray ~= 0 or
#compound.enumArray ~= 0 or
#compound.structArray ~= 0 or
#compound.unionArray ~= 0 or
#compound.interfaceArray ~= 0 or
#compound.protocolArray ~= 0 or
#compound.exceptionArray ~= 0 or
#compound.classArray ~= 0 or
#compound.singletonArray ~= 0 or
#compound.serviceArray ~= 0 or
#compound.variableArray ~= 0 or
#compound.propertyArray ~= 0 or
#compound.eventArray ~= 0 or
#compound.constructorArray ~= 0 or
#compound.functionArray ~= 0 or
#compound.aliasArray ~= 0 or
#compound.defineArray ~= 0
end
function prepareCompound(compound)
if compound.stats then
return compound.stats
end
local stats = {}
-- filter invisible items out
if compound.derivedTypeArray then
filterItemArray(compound.derivedTypeArray)
end
filterNamespaceArray(compound.namespaceArray)
filterTypedefArray(compound.typedefArray)
filterEnumArray(compound.enumArray)
filterItemArray(compound.structArray)
filterItemArray(compound.unionArray)
filterItemArray(compound.interfaceArray)
filterItemArray(compound.protocolArray)
filterItemArray(compound.exceptionArray)
filterItemArray(compound.classArray)
filterItemArray(compound.singletonArray)
filterItemArray(compound.serviceArray)
filterItemArray(compound.variableArray)
filterItemArray(compound.propertyArray)
filterItemArray(compound.eventArray)
filterConstructorArray(compound.constructorArray)
filterItemArray(compound.functionArray)
filterItemArray(compound.aliasArray)
filterDefineArray(compound.defineArray)
stats.hasItems = hasCompoundItems(compound)
-- scan for documentation and create subgroups
stats.hasUnnamedEnums = false
stats.hasDocumentedUnnamedEnumValues = false
for i = 1, #compound.enumArray do
local item = compound.enumArray[i]
if isUnnamedItem(item) then
stats.hasUnnamedEnums = true
if prepareItemArrayDocumentation(item.enumValueArray, compound) then
stats.hasDocumentedUnnamedEnumValues = true
end
end
end
stats.hasDocumentedTypedefs = prepareItemArrayDocumentation(compound.typedefArray, compound)
stats.hasDocumentedVariables = prepareItemArrayDocumentation(compound.variableArray, compound)
stats.hasDocumentedProperties = prepareItemArrayDocumentation(compound.propertyArray, compound)
stats.hasDocumentedEvents = prepareItemArrayDocumentation(compound.eventArray, compound)
stats.hasDocumentedFunctions = prepareItemArrayDocumentation(compound.functionArray, compound)
stats.hasDocumentedAliases = prepareItemArrayDocumentation(compound.aliasArray, compound)
stats.hasDocumentedDefines = prepareItemArrayDocumentation(compound.defineArray, compound)
stats.hasDocumentedConstruction = prepareItemArrayDocumentation(compound.constructorArray, compound)
if not EXCLUDE_DESTRUCTORS and compound.destructor then
prepareItemDocumentation(compound.destructor, compound)
stats.hasDocumentedConstruction = stats.hasDocumentedConstruction or compound.destructor.hasDocumentation
end
stats.hasDocumentedItems =
stats.hasDocumentedUnnamedEnumValues or
stats.hasDocumentedTypedefs or
stats.hasDocumentedVariables or
stats.hasDocumentedProperties or
stats.hasDocumentedEvents or
stats.hasDocumentedConstruction or
stats.hasDocumentedFunctions or
stats.hasDocumentedAliases or
stats.hasDocumentedDefines
stats.hasBriefDocumentation = not isDocumentationEmpty(compound.briefDescription)
stats.hasDetailedDocumentation = not isDocumentationEmpty(compound.detailedDescription)
-- sort items -- only the ones producing separate pages;
-- also, defines, which always go to the global namespace
table.sort(compound.groupArray, cmpGroups)
table.sort(compound.namespaceArray, cmpNames)
table.sort(compound.enumArray, cmpNames)
table.sort(compound.structArray, cmpNames)
table.sort(compound.unionArray, cmpNames)
table.sort(compound.interfaceArray, cmpNames)
table.sort(compound.protocolArray, cmpNames)
table.sort(compound.exceptionArray, cmpNames)
table.sort(compound.classArray, cmpNames)
table.sort(compound.serviceArray, cmpNames)
table.sort(compound.defineArray, cmpNames)
compound.stats = stats
if compound.baseTypeArray and next(compound.baseTypeArray) ~= nil then
createBaseCompound(compound)
end
handleCompoundProtection(compound)
return stats
end
function prepareEnum(enum)
local stats = {}
local maxLength = 0
for i = 1, #enum.enumValueArray do
local item = enum.enumValueArray[i]
local length = string.len(item.name)
if length > maxLength then
maxLength = length
end
end
stats.hasDocumentedEnumValues = prepareItemArrayDocumentation(enum.enumValueArray)
stats.hasBriefDocumentation = not isDocumentationEmpty(enum.briefDescription)
stats.hasDetailedDocumentation = not isDocumentationEmpty(enum.detailedDescription)
stats.maxEnumValueNameLength = maxLength
return stats
end
-------------------------------------------------------------------------------