summaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/build-doc.lua197
-rw-r--r--tools/configuration.lua125
-rw-r--r--tools/locale.lua20
-rw-r--r--tools/love-api.lua32
-rw-r--r--tools/lovr-api.lua32
-rw-r--r--tools/lua51.lua2
6 files changed, 394 insertions, 14 deletions
diff --git a/tools/build-doc.lua b/tools/build-doc.lua
new file mode 100644
index 00000000..fbf5fa6b
--- /dev/null
+++ b/tools/build-doc.lua
@@ -0,0 +1,197 @@
+package.path = package.path .. ';script/?.lua;tools/?.lua'
+
+local fs = require 'bee.filesystem'
+local config = require 'configuration'
+local markdown = require 'provider.markdown'
+local util = require 'utility'
+local lloader = require 'locale-loader'
+local json = require 'json-beautify'
+local diagd = require 'proto.diagnostic'
+
+local function mergeDiagnosticGroupLocale(locale)
+ for groupName, names in pairs(diagd.diagnosticGroups) do
+ local key = ('config.diagnostics.%s'):format(groupName)
+ local list = {}
+ for name in util.sortPairs(names) do
+ list[#list+1] = ('* %s'):format(name)
+ end
+ local desc = table.concat(list, '\n')
+ locale[key] = desc
+ end
+end
+
+local function getLocale()
+ local locale = {}
+
+ for dirPath in fs.pairs(fs.path 'locale') do
+ local lang = dirPath:filename():string()
+ local text = util.loadFile((dirPath / 'setting.lua'):string())
+ if text then
+ locale[lang] = lloader(text, lang)
+ -- add `config.diagnostics.XXX`
+ mergeDiagnosticGroupLocale(locale[lang])
+ end
+ end
+
+ return locale
+end
+
+local localeMap = getLocale()
+
+local function getDesc(lang, desc)
+ if not desc then
+ return nil
+ end
+ if desc:sub(1, 1) ~= '%' or desc:sub(-1, -1) ~= '%' then
+ return desc
+ end
+ local locale = localeMap[lang]
+ if not locale then
+ return desc
+ end
+ local id = desc:sub(2, -2)
+ return locale[id]
+end
+
+local function buildType(md, lang, conf)
+ md:add('md', '## type')
+ if type(conf.type) == 'table' then
+ md:add('ts', ('%s | %s'):format(conf.type[1], conf.type[2]))
+ elseif conf.type == 'array' then
+ md:add('ts', ('Array<%s>'):format(conf.items.type))
+ elseif conf.type == 'object' then
+ if conf.properties then
+ local _, first = next(conf.properties)
+ assert(first)
+ md:add('ts', ('object<string, %s>'):format(first.type))
+ elseif conf.patternProperties then
+ local _, first = next(conf.patternProperties)
+ assert(first)
+ md:add('ts', ('Object<string, %s>'):format(first.type))
+ else
+ md:add('ts', '**Unknown object type!!**')
+ end
+ else
+ md:add('ts', ('%s'):format(conf.type))
+ end
+end
+
+local function buildDesc(md, lang, conf)
+ local desc = conf.markdownDescription or conf.description
+ desc = getDesc(lang, desc)
+ if desc then
+ md:add('md', desc)
+ else
+ md:add('md', '**Missing description!!**')
+ end
+ md:emptyLine()
+end
+
+local function buildDefault(md, lang, conf)
+ local default = conf.default
+ if default == json.null then
+ default = nil
+ end
+ md:add('md', '## default')
+ if conf.type == 'object' then
+ if not default then
+ default = {}
+ for k, v in pairs(conf.properties) do
+ default[k] = v.default
+ end
+ end
+ local list = util.getTableKeys(default, true)
+ if #list == 0 then
+ md:add('jsonc', '{}')
+ return
+ end
+ md:add('jsonc', '{')
+ for i, k in ipairs(list) do
+ local desc = getDesc(lang, conf.properties[k].description)
+ if desc then
+ md:add('jsonc', ' /*')
+ md:add('jsonc', (' %s'):format(desc:gsub('\n', '\n ')))
+ md:add('jsonc', ' */')
+ end
+ if i == #list then
+ md:add('jsonc',(' %s: %s'):format(json.encode(k), json.encode(default[k])))
+ else
+ md:add('jsonc',(' %s: %s,'):format(json.encode(k), json.encode(default[k])))
+ end
+ end
+ md:add('jsonc', '}')
+ else
+ md:add('jsonc', ('%s'):format(json.encode(default)))
+ end
+end
+
+local function buildEnum(md, lang, conf)
+ if conf.enum then
+ md:add('md', '## enum')
+ md:emptyLine()
+ for i, enum in ipairs(conf.enum) do
+ local desc = getDesc(lang, conf.markdownEnumDescriptions and conf.markdownEnumDescriptions[i])
+ if desc then
+ md:add('md', ('* ``%s``: %s'):format(json.encode(enum), desc))
+ else
+ md:add('md', ('* ``%s``'):format(json.encode(enum)))
+ end
+ end
+ md:emptyLine()
+ return
+ end
+
+ if conf.type == 'object' and conf.properties then
+ local _, first = next(conf.properties)
+ if first and first.enum then
+ md:add('md', '## enum')
+ md:emptyLine()
+ for i, enum in ipairs(first.enum) do
+ local desc = getDesc(lang, conf.markdownEnumDescriptions and conf.markdownEnumDescriptions[i])
+ if desc then
+ md:add('md', ('* ``%s``: %s'):format(json.encode(enum), desc))
+ else
+ md:add('md', ('* ``%s``'):format(json.encode(enum)))
+ end
+ end
+ md:emptyLine()
+ return
+ end
+ end
+
+ if conf.type == 'array' and conf.items.enum then
+ md:add('md', '## enum')
+ md:emptyLine()
+ for i, enum in ipairs(conf.items.enum) do
+ local desc = getDesc(lang, conf.markdownEnumDescriptions and conf.markdownEnumDescriptions[i])
+ if desc then
+ md:add('md', ('* ``%s``: %s'):format(json.encode(enum), desc))
+ else
+ md:add('md', ('* ``%s``'):format(json.encode(enum)))
+ end
+ end
+ md:emptyLine()
+ return
+ end
+end
+
+local function buildMarkdown(lang)
+ local dir = fs.path 'doc' / lang
+ fs.create_directories(dir)
+ local configDoc = markdown()
+
+ for name, conf in util.sortPairs(config) do
+ configDoc:add('md', '# ' .. name:gsub('^Lua%.', ''))
+ configDoc:emptyLine()
+ buildDesc(configDoc, lang, conf)
+ buildType(configDoc, lang, conf)
+ buildEnum(configDoc, lang, conf)
+ buildDefault(configDoc, lang, conf)
+ end
+
+ util.saveFile((dir / 'config.md'):string(), configDoc:string())
+end
+
+for lang in pairs(localeMap) do
+ buildMarkdown(lang)
+end
diff --git a/tools/configuration.lua b/tools/configuration.lua
new file mode 100644
index 00000000..285ac334
--- /dev/null
+++ b/tools/configuration.lua
@@ -0,0 +1,125 @@
+local json = require 'json'
+local template = require 'config.template'
+local util = require 'utility'
+
+local function getType(temp)
+ if temp.name == 'Boolean' then
+ return 'boolean'
+ end
+ if temp.name == 'String' then
+ return 'string'
+ end
+ if temp.name == 'Integer' then
+ return 'integer'
+ end
+ if temp.name == 'Nil' then
+ return 'null'
+ end
+ if temp.name == 'Array' then
+ return 'array'
+ end
+ if temp.name == 'Hash' then
+ return 'object'
+ end
+ if temp.name == 'Or' then
+ return { getType(temp.subs[1]), getType(temp.subs[2]) }
+ end
+ error('Unknown type: ' .. temp.name)
+end
+
+local function getDefault(temp)
+ local default = temp.default
+ if default == nil and temp.hasDefault then
+ default = json.null
+ end
+ if type(default) == 'table' and getType(temp) == 'object' then
+ setmetatable(default, json.object)
+ end
+ return default
+end
+
+local function getEnum(temp)
+ return temp.enums
+end
+
+local function getEnumDesc(name, temp)
+ if not temp.enums then
+ return nil
+ end
+ local descs = {}
+
+ for _, enum in ipairs(temp.enums) do
+ descs[#descs+1] = name:gsub('^Lua', '%%config') .. '.' .. enum .. '%'
+ end
+
+ return descs
+end
+
+local function insertArray(conf, temp)
+ conf.items = {
+ type = getType(temp.sub),
+ enum = getEnum(temp.sub),
+ }
+end
+
+local function insertHash(name, conf, temp)
+ conf.title = name:match '[^%.]+$'
+ conf.additionalProperties = false
+
+ if type(conf.default) == 'table' and next(conf.default) then
+ local default = conf.default
+ conf.default = nil
+ conf.properties = {}
+ local descHead = name:gsub('^Lua', '%%config')
+ if util.stringStartWith(descHead, '%config.diagnostics') then
+ descHead = '%config.diagnostics'
+ end
+ for key, value in pairs(default) do
+ conf.properties[key] = {
+ type = getType( temp.subvalue),
+ default = value,
+ enum = getEnum( temp.subvalue),
+ description = descHead .. '.' .. key .. '%',
+ }
+ end
+ else
+ conf.patternProperties = {
+ ['.*'] = {
+ type = getType( temp.subvalue),
+ default = getDefault( temp.subvalue),
+ enum = getEnum( temp.subvalue),
+ }
+ }
+ end
+end
+
+local config = {}
+
+for name, temp in pairs(template) do
+ if not util.stringStartWith(name, 'Lua.') then
+ goto CONTINUE
+ end
+ config[name] = {
+ scope = 'resource',
+ type = getType(temp),
+ default = getDefault(temp),
+ enum = getEnum(temp),
+
+ markdownDescription = name:gsub('^Lua', '%%config') .. '%',
+ markdownEnumDescriptions = getEnumDesc(name, temp),
+ }
+
+ if temp.name == 'Array' then
+ insertArray(config[name], temp)
+ end
+
+ if temp.name == 'Hash' then
+ insertHash(name, config[name], temp)
+ end
+
+ ::CONTINUE::
+end
+
+config['Lua.telemetry.enable'].tags = { 'telemetry' }
+
+return config
diff --git a/tools/locale.lua b/tools/locale.lua
index 3cbaf534..650cb5ec 100644
--- a/tools/locale.lua
+++ b/tools/locale.lua
@@ -3,6 +3,15 @@ package.path = package.path .. ';script/?.lua;tools/?.lua'
local fs = require 'bee.filesystem'
local util = require 'utility'
+local function getLongStringMark(text)
+ return text:match '^%[[=]*%['
+end
+
+local function isLongStringFinish(text, mark)
+ local emark = mark:gsub('%[', ']')
+ return util.stringEndWith(text, emark)
+end
+
local function loadLocaleFile(filePath)
local fileContent = util.loadFile(filePath:string())
local data = {
@@ -13,12 +22,12 @@ local function loadLocaleFile(filePath)
return data
end
local current
- local inLongString = false
+ local inLongString
for line, lineCount in util.eachLine(fileContent) do
if inLongString then
current.content[#current.content+1] = line
- if line:sub(-2) == ']]' then
- inLongString = false
+ if isLongStringFinish(line, inLongString) then
+ inLongString = nil
end
goto CONTINUE
end
@@ -44,8 +53,9 @@ local function loadLocaleFile(filePath)
current = nil
else
current.content[#current.content+1] = line
- if line:sub(1, 2) == '[[' then
- inLongString = true
+ inLongString = getLongStringMark(line)
+ if inLongString and isLongStringFinish(line, inLongString) then
+ inLongString = false
end
end
end
diff --git a/tools/love-api.lua b/tools/love-api.lua
index 54369acb..7300ccc3 100644
--- a/tools/love-api.lua
+++ b/tools/love-api.lua
@@ -50,6 +50,22 @@ local function formatIndex(key)
return ('[%q]'):format(key)
end
+local function getOptional(param)
+ if param.type == 'table' then
+ if not param.table then
+ return ''
+ end
+ for _, field in ipairs(param.table) do
+ if field.default == nil then
+ return ''
+ end
+ end
+ return '?'
+ else
+ return (param.default ~= nil) and '?' or ''
+ end
+end
+
local buildType
local function buildDocTable(tbl)
@@ -112,9 +128,9 @@ local function buildDocFunc(variant, overload)
params[#params+1] = '...'
else
if param.name:find '^[\'"]' then
- params[#params+1] = ('%s: %s|%q'):format(param.name:sub(2, -2), getTypeName(param.type), param.name)
+ params[#params+1] = ('%s%s: %s|%s'):format(param.name, getOptional(param), getTypeName(param.type), param.name)
else
- params[#params+1] = ('%s: %s'):format(param.name, getTypeName(param.type))
+ params[#params+1] = ('%s%s: %s'):format(param.name, getOptional(param), getTypeName(param.type))
end
end
end
@@ -148,7 +164,15 @@ local function buildFunction(func, node, typeName)
params[#params+1] = paramName
text[#text+1] = ('---@param %s%s %s # %s'):format(
paramName,
- param.default == nil and '' or '?',
+ getOptional(param),
+ buildType(param),
+ param.description
+ )
+ end
+
+ if param.name == "..." then
+ params[#params+1] = param.name
+ text[#text+1] = ('---@vararg %s # %s'):format(
buildType(param),
param.description
)
@@ -216,7 +240,7 @@ local function buildFile(class, defs)
text[#text+1] = ('---@alias %s'):format(getTypeName(enum.name))
for _, constant in ipairs(enum.constants) do
text[#text+1] = buildDescription(constant.description, constant.notes)
- text[#text+1] = ([[---| '%s']]):format(('%q'):format(constant.name):gsub("'", "\\'"))
+ text[#text+1] = ([[---| %q]]):format(constant.name)
end
end
diff --git a/tools/lovr-api.lua b/tools/lovr-api.lua
index ca7c414e..f045afa8 100644
--- a/tools/lovr-api.lua
+++ b/tools/lovr-api.lua
@@ -51,6 +51,22 @@ local function formatIndex(key)
return ('[%q]'):format(key)
end
+local function getOptional(param)
+ if param.type == 'table' then
+ if not param.table then
+ return ''
+ end
+ for _, field in ipairs(param.table) do
+ if field.default == nil then
+ return ''
+ end
+ end
+ return '?'
+ else
+ return (param.default ~= nil) and '?' or ''
+ end
+end
+
local buildType
local function buildDocTable(tbl)
@@ -116,9 +132,9 @@ local function buildDocFunc(variant, overload)
params[#params+1] = '...'
else
if param.name:find '^[\'"]' then
- params[#params+1] = ('%s: %s|%q'):format(param.name:sub(2, -2), getTypeName(param.type), param.name)
+ params[#params+1] = ('%s%s: %s|%s'):format(param.name, getOptional(param), getTypeName(param.type), param.name)
else
- params[#params+1] = ('%s: %s'):format(param.name, getTypeName(param.type))
+ params[#params+1] = ('%s%s: %s'):format(param.name, getOptional(param), getTypeName(param.type))
end
end
end
@@ -152,7 +168,15 @@ local function buildFunction(func, typeName)
params[#params+1] = paramName
text[#text+1] = ('---@param %s%s %s # %s'):format(
paramName,
- param.default == nil and '' or '?',
+ getOptional(param),
+ buildType(param),
+ param.description
+ )
+ end
+
+ if param.name == "..." then
+ params[#params+1] = param.name
+ text[#text+1] = ('---@vararg %s # %s'):format(
buildType(param),
param.description
)
@@ -211,7 +235,7 @@ local function buildFile(defs)
text[#text+1] = ('---@alias %s'):format(getTypeName(enum.name))
for _, constant in ipairs(enum.values) do
text[#text+1] = buildDescription(constant.description, constant.notes)
- text[#text+1] = ([[---| '%s']]):format(('%q'):format(constant.name):gsub("'", "\\'"))
+ text[#text+1] = ([[---| %q]]):format(constant.name)
end
end
diff --git a/tools/lua51.lua b/tools/lua51.lua
index fb13d294..20e3335d 100644
--- a/tools/lua51.lua
+++ b/tools/lua51.lua
@@ -374,7 +374,7 @@ lua51.os.difftime = os.difftime
lua51.os.execute = os.execute
function lua51.os.exit(code)
code = tonumber(code) or 0
- osExit(code)
+ osExit(code--[[@as integer]])
end
lua51.os.getenv = os.getenv
lua51.os.remove = os.remove