diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/build-doc.lua | 197 | ||||
-rw-r--r-- | tools/configuration.lua | 125 | ||||
-rw-r--r-- | tools/locale.lua | 20 | ||||
-rw-r--r-- | tools/love-api.lua | 32 | ||||
-rw-r--r-- | tools/lovr-api.lua | 32 | ||||
-rw-r--r-- | tools/lua51.lua | 2 |
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 |