diff options
Diffstat (limited to 'Server/Plugins')
-rw-r--r-- | Server/Plugins/APIDump/APIDesc.lua | 4 | ||||
-rw-r--r-- | Server/Plugins/APIDump/SettingUpLuaLanguageServer.html | 42 | ||||
-rw-r--r-- | Server/Plugins/APIDump/Static/vscode_lua_addon.png | bin | 0 -> 72014 bytes | |||
-rw-r--r-- | Server/Plugins/APIDump/Static/vscode_lua_settings.png | bin | 0 -> 24284 bytes | |||
-rw-r--r-- | Server/Plugins/APIDump/_preload.lua | 22 | ||||
-rw-r--r-- | Server/Plugins/APIDump/lualanguageserver.lua | 223 | ||||
-rw-r--r-- | Server/Plugins/APIDump/main_APIDump.lua | 7 |
7 files changed, 296 insertions, 2 deletions
diff --git a/Server/Plugins/APIDump/APIDesc.lua b/Server/Plugins/APIDump/APIDesc.lua index 0bcbca848..54a8d4e4f 100644 --- a/Server/Plugins/APIDump/APIDesc.lua +++ b/Server/Plugins/APIDump/APIDesc.lua @@ -19247,6 +19247,10 @@ end Title = "Setting up the ZeroBrane Studio Lua IDE", }, { + FileName = "SettingUpLuaLanguageServer.html", + Title = "Setting up Lua-Language-Server (VSCode/Emacs)" + }, + { FileName = "UsingChunkStays.html", Title = "Using ChunkStays", }, diff --git a/Server/Plugins/APIDump/SettingUpLuaLanguageServer.html b/Server/Plugins/APIDump/SettingUpLuaLanguageServer.html new file mode 100644 index 000000000..ffe79aed9 --- /dev/null +++ b/Server/Plugins/APIDump/SettingUpLuaLanguageServer.html @@ -0,0 +1,42 @@ +<!DOCTYPE html> + +<html> + <head> + <title>Cuberite - Setting up the Lua-Language-Server (VSCode)</title> + <link rel="canonical" href="https://api.cuberite.org/SettingUpLuaLanguageServer.html"> + <link rel="stylesheet" type="text/css" href="main.css" /> + <link rel="stylesheet" type="text/css" href="prettify.css" /> + <script src="prettify.js"></script> + <script src="lang-lua.js"></script> + <meta charset="UTF-8"> + </head> + <body> + <div id="content"> + <h1>Setting up the Lua-Language-Server (VSCode)</h1> + <p>This article will explain how to configure an IDE that is able to use the <a href="https://github.com/LuaLS/lua-language-server">Lua-Language-Server</a>. This article will show how it's done using Visual Studio Code, but it should work with any IDE that supports language servers.</p> + + <h2>About Language Servers</h2> + + <p>IDE's in the past always implemented every programming language they supported on their own, it was baked in. Because of this everyone supported different features. With language servers this all changes. A single language server can be created with a community which can be shared across any number of IDE's which support the protocol. To learn more about language servers and IDE's that support them see <a href="https://langserver.org/">langserver.org</a></p> + + <h2>First-time setup</h2> + <p>Visual Studio Code doesn't support Lua by default. Instead it has a marketplace where extensions can be downloaded from. In this example we're going to use the Lua extension by Sumneko who also created the language server.</p> + + <img src="Static/vscode_lua_addon.png" /> + + <h3>Libraries</h3> + <p>The extension doesn't know the Cuberite API by default. The extension, or rather the language server, supports the inclusion of libraries. In order to generate the definitions required by the language server you have to activate the APIDump plugin in Cuberite which is included by default but not enabled. When the plugin is enabled the entire API can be exported by using the 'api' command in the console. Once this has completed there is a new folder next to the Cuberite executable called LLS.</p> + <p>In order to use these definition files you need to create a settings.json file in the plugin folder you're developing for. This file should be in a folder called '.vscode'. If it doesn't exist yet you have to create it yourself. There are two important settings to configure: + <ul> + <li><b>Lua.runtime.version</b> which has to be set to "Lua 5.1". Cuberite only supports Lua 5.1.</li> + <li><b>Lua.workspace.library</b> which is an array containing all libraries used in the project. In this case it needs to point to the newly generated definition files. If you're developing your plugin using the same Cuberite instance as where you generated the definitions using the APIDump plugin you can set this to "../../LLS/cuberite/library". If your definitions are on a different location you will have to point to it yourself. Absolute paths are also supported.</li> + </ul> + </p> + + <p>After configuring your settings.json file would something like this:</p> + <img src="Static/vscode_lua_settings.png" /> + + <p>After saving the settings.json file the IDE should recognize Cuberite's API.</p> + </div> + </body> +</html> diff --git a/Server/Plugins/APIDump/Static/vscode_lua_addon.png b/Server/Plugins/APIDump/Static/vscode_lua_addon.png Binary files differnew file mode 100644 index 000000000..109f220ce --- /dev/null +++ b/Server/Plugins/APIDump/Static/vscode_lua_addon.png diff --git a/Server/Plugins/APIDump/Static/vscode_lua_settings.png b/Server/Plugins/APIDump/Static/vscode_lua_settings.png Binary files differnew file mode 100644 index 000000000..aee427c1e --- /dev/null +++ b/Server/Plugins/APIDump/Static/vscode_lua_settings.png diff --git a/Server/Plugins/APIDump/_preload.lua b/Server/Plugins/APIDump/_preload.lua new file mode 100644 index 000000000..becc691c4 --- /dev/null +++ b/Server/Plugins/APIDump/_preload.lua @@ -0,0 +1,22 @@ + +-- _preload.lua + +-- First thing executed when the plugin loads. Replaces the global environment (_G) with an empty table +-- with __index set to the old environment. This way any function or variable that is created globally by the plugin +-- won't be reported as new or undocumented. + + + + + +local newEnv, oldEnv = {}, _G +local setmetatable = setmetatable +for k, v in pairs(_G) do + newEnv[k] = v; + oldEnv[k] = nil; +end +_G = setmetatable(oldEnv, {__index = newEnv}); + + + + diff --git a/Server/Plugins/APIDump/lualanguageserver.lua b/Server/Plugins/APIDump/lualanguageserver.lua new file mode 100644 index 000000000..2e1b86410 --- /dev/null +++ b/Server/Plugins/APIDump/lualanguageserver.lua @@ -0,0 +1,223 @@ +-- 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 + + + + diff --git a/Server/Plugins/APIDump/main_APIDump.lua b/Server/Plugins/APIDump/main_APIDump.lua index 735a6ec05..5d6f5255f 100644 --- a/Server/Plugins/APIDump/main_APIDump.lua +++ b/Server/Plugins/APIDump/main_APIDump.lua @@ -136,7 +136,7 @@ local function CreateAPITables() return res; end - for i, v in pairs(_G) do + for i, v in pairs(getmetatable(_G).__index) do if ( (v ~= _G) and -- don't want the global namespace (v ~= _G.packages) and -- don't want any packages @@ -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 Lua-Language-Server API descriptions: + DumpAPILLS(API); + -- Export the API in a format used by LuaCheck DumpLuaCheck(API) |