From c0cce2155974ddffea8897c861855a195e9cd071 Mon Sep 17 00:00:00 2001 From: Niels Breuker Date: Sun, 12 Mar 2023 14:23:19 +0100 Subject: Added code to export definitions for a lua-language-server --- Server/Plugins/APIDump/main_APIDump.lua | 5 +- Server/Plugins/APIDump/vscode.lua | 223 ++++++++++++++++++++++++++++++++ 2 files changed, 227 insertions(+), 1 deletion(-) create mode 100644 Server/Plugins/APIDump/vscode.lua diff --git a/Server/Plugins/APIDump/main_APIDump.lua b/Server/Plugins/APIDump/main_APIDump.lua index 735a6ec05..7bd2c80be 100644 --- a/Server/Plugins/APIDump/main_APIDump.lua +++ b/Server/Plugins/APIDump/main_APIDump.lua @@ -1473,7 +1473,7 @@ end --- Returns the string with extra tabs and CR/LFs removed -local function CleanUpDescription(a_Desc) +function CleanUpDescription(a_Desc) -- Get rid of indent and newlines, normalize whitespace: local res = a_Desc:gsub("[\n\t]", "") res = a_Desc:gsub("%s%s+", " ") @@ -1858,6 +1858,9 @@ local function DumpApi() -- Dump all available API objects in format used by ZeroBraneStudio API descriptions: DumpAPIZBS(API) + -- Dump all available API objects in format used by VSCode API descriptions: + DumpAPIVSCode(API); + -- Export the API in a format used by LuaCheck DumpLuaCheck(API) diff --git a/Server/Plugins/APIDump/vscode.lua b/Server/Plugins/APIDump/vscode.lua new file mode 100644 index 000000000..907a7230a --- /dev/null +++ b/Server/Plugins/APIDump/vscode.lua @@ -0,0 +1,223 @@ +-- vscode.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 CleanUpDescriptionVSCode(a_Desc) + return CleanUpDescription(a_Desc) + :gsub("\n", " ") +end + + + + + +--- Writes a list of methods into the specified file in VSCode format +local function WriteVSCodeMethods(f, a_NameSpace, a_Methods) + for _, func in ipairs(a_Methods or {}) do + f:write("\n---\n") + f:write("---", CleanUpDescriptionVSCode(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 WriteVSCodeConstants(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 VSCode format +local function WriteVSCodeEnums(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") + WriteVSCodeConstants(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 WriteVSCodeVariables(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 VSCode format +local function WriteVSCodeClass(a_Class) + assert(type(a_Class) == "table") + + local f = io.open("vscode/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"); + WriteVSCodeVariables(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: + WriteVSCodeEnums(f, a_Class.Name, a_Class.ConstantGroups); + WriteVSCodeConstants(f, a_Class.Name, a_Class.Constants); + WriteVSCodeMethods(f, a_Class.Name, a_Class.Functions); + + f:close(); +end + + + + + +--- Dumps the entire API table into a file in the VSCode format +function DumpAPIVSCode(a_API) + LOG("Dumping VSCode API description...") + cFile:CreateFolderRecursive("vscode/cuberite/library"); + + -- Export each class except Globals, store those aside: + local Globals + for _, cls in ipairs(a_API) do + if (cls.Name ~= "Globals") then + WriteVSCodeClass(cls) + else + Globals = cls + end + end + + -- Export the globals: + if (Globals) then + local f = io.open("vscode/cuberite/library/Globals.lua", "w"); + f:write("---@meta\n\n"); + WriteVSCodeMethods(f, nil, Globals.Functions) + WriteVSCodeEnums(f, nil, Globals.ConstantGroups) + f:close(); + end + + -- Finish the file: + LOG("VSCode API dumped...") +end + + + + -- cgit v1.2.3