-- lualanguageserver.lua
-- Implements the code for exporting definition files which can be used by a Lua-Language-Server
--- Cleans up the name of a parameter so it can be used in a definition file
--- Removes anything containing brackets and removes dashes and spaces.
local function CleanupParameterName(paramName)
paramName = paramName:gsub("[%- ]", "")
:gsub("<.->.-</.->", '');
return paramName
end
--- Cleans up a description so it can be used in a definition file.
--- Uses the standard cleanup function but also removes any newlines.
local function CleanUpDescriptionLLS(a_Desc)
return CleanUpDescription(a_Desc)
:gsub("\n", " ")
end
--- Writes a list of methods into the specified file in LLS format
local function WriteLLSMethods(f, a_NameSpace, a_Methods)
for _, func in ipairs(a_Methods or {}) do
f:write("\n---\n")
f:write("---", CleanUpDescriptionLLS(func.Notes or ""), "\n");
f:write("---\n");
local parameterList = {}
if (func.Params) then
local paramNr = 0;
for _, param in ipairs(func.Params) do
paramNr = paramNr + 1;
local paramName = CleanupParameterName(param.Name or ("param" .. paramNr));
if (paramName:find("%.%.%.")) then
paramName = "..."
end
table.insert(parameterList, paramName)
if (param.IsOptional and paramName ~= "...") then
paramName = paramName .. "?"
end
local paramType = param.Type;
if (paramType:find("%#")) then
paramType = paramType:match("%#(.+)");
end
f:write("---@param ", paramName, " ", paramType, "\n");
end
f:write("---\n");
end
if (func.Returns) then
for _, ret in ipairs(func.Returns) do
f:write("---@return ", ret.Type, "\n");
end
f:write("---\n");
end
local name = func.Name:find("constructor") and "__call" or func.Name;
name = name:find("operator") and "__meta" or name
local parameters = table.concat(parameterList, ", ");
f:write("function ")
if (a_NameSpace) then
f:write(a_NameSpace, ":")
end
f:write(name, "(", parameters, ") end\n\n");
end
end
--- Writes the list of constants. If the value is an enum the value is set from that enum.
--- This is a bit of a hack because Cuberite exports allot of enums as a constant inside
--- a class or global but documents them as if they are in their own table.
local function WriteLLSConstants(f, a_NameSpace, a_Constants, a_Enum)
if (not a_Constants) then
return;
end
local prefix = ""
if (a_NameSpace) then
prefix = a_NameSpace .. ".";
end
for _, const in pairs(a_Constants) do
f:write(prefix)
if (a_Enum) then
f:write(const.Name, " = ", prefix, a_Enum, ".", const.Name, "\n")
else
local constValue = tostring(const.Value):match("[%w%d]+") or "nil";
f:write(const.Name, " = ", constValue, "\n")
end
end
end
--- Writes a list of constants into the specified file in LLS format
local function WriteLLSEnums(f, a_NameSpace, a_ConstantGroups)
if (not a_ConstantGroups) then
return;
end
local prefix = "";
if (a_NameSpace) then
prefix = a_NameSpace .. "."
end
for _, group in pairs(a_ConstantGroups) do
f:write("---@enum ", group.Name, "\n");
f:write(prefix, group.Name, " = {\n")
for _, const in pairs(group.Constants) do
local constValue = tostring(const.Value):match("[%w%d]+") or "nil";
f:write("\t", const.Name, " = ", constValue, ",\n")
end
f:write("}\n")
WriteLLSConstants(f, a_NameSpace, group.Constants, group.Name);
end
end
--- Writes all the fields which a class has.
---@param f file*
---@param a_Variables table
local function WriteLLSVariables(f, a_Variables)
for _, variable in ipairs(a_Variables or {}) do
f:write("---@field ", variable.Name)
if (variable.Type) then
local type = variable.Type:match("%w+")
f:write(" ", type)
end
if (variable.Notes) then
f:write(" ", variable.Notes)
end
f:write("\n");
end
end
--- Writes one Cuberite class definition into the specified file in LLS format
local function WriteLLSClass(a_Class)
assert(type(a_Class) == "table")
local f = io.open("LLS/cuberite/library/" .. a_Class.Name .. ".lua", "w");
f:write("---@meta\n");
f:write("\n\n---\n---The ", a_Class.Name, " namespace\n");
local inherit = "";
if (a_Class.Inherits) then
inherit = ": " .. a_Class.Inherits.Name
end
f:write("---@class ", a_Class.Name, inherit, "\n");
WriteLLSVariables(f, a_Class.Variables);
for _, func in pairs(a_Class.Functions or {}) do
if (func.Name:find("constructor")) then
local parameters = {};
for _, param in ipairs(func.Parameters or {}) do
table.insert(parameters, param.Type);
end
f:write("---@operator call(", table.concat(parameters, ","), "):" .. a_Class.Name, "\n")
end
end
f:write("", a_Class.Name, " = {}\n");
-- Export methods and constants:
WriteLLSEnums(f, a_Class.Name, a_Class.ConstantGroups);
WriteLLSConstants(f, a_Class.Name, a_Class.Constants);
WriteLLSMethods(f, a_Class.Name, a_Class.Functions);
f:close();
end
--- Dumps the entire API table into a file in the LLS format
function DumpAPILLS(a_API)
LOG("Dumping LLS API description...")
cFile:CreateFolderRecursive("LLS/cuberite/library");
-- Export each class except Globals, store those aside:
local Globals
for _, cls in ipairs(a_API) do
if (cls.Name ~= "Globals") then
WriteLLSClass(cls)
else
Globals = cls
end
end
-- Export the globals:
if (Globals) then
local f = io.open("LLS/cuberite/library/Globals.lua", "w");
f:write("---@meta\n\n");
WriteLLSMethods(f, nil, Globals.Functions)
WriteLLSEnums(f, nil, Globals.ConstantGroups)
f:close();
end
-- Finish the file:
LOG("LLS API dumped...")
end