A luau-lsp extension to improve your experience in neovim.
demo.mp4
- Neovim 0.10+
- plenary.nvim
Use your favorite plugin manager to install luau-lsp.nvim
lazy.nvim
{
"lopi-py/luau-lsp.nvim",
opts = {
...
},
dependencies = {
"nvim-lua/plenary.nvim",
},
}
packer.nvim
use {
"lopi-py/luau-lsp.nvim",
config = function()
require("luau-lsp").setup {
...
}
end,
requires = {
"nvim-lua/plenary.nvim",
},
}
Caution
lspconfig.luau_lsp.setup
should NOT be called, it may cause conflicts with the plugin
require("luau-lsp").setup {
...
}
require("mason-lspconfig").setup_handlers {
luau_lsp = function()
require("luau-lsp").setup {
...
}
end,
}
Roblox types are downloaded from the luau-lsp repository and passed to the language server.
require("luau-lsp").setup {
platform = {
type = "roblox",
},
types = {
roblox_security_level = "PluginSecurity",
},
}
Sourcemap generation is done by running rojo sourcemap --watch default.project.json --output sourcemap.json
.
require("luau-lsp").setup {
sourcemap = {
enabled = true,
autogenerate = true, -- automatic generation when the server is attached
rojo_project_file = "default.project.json",
sourcemap_file = "sourcemap.json",
},
}
:LuauLsp regenerate_sourcemap {file}
is provided to start sourcemap generation with the project file passed as argument (optional).
You can install the companion plugin here.
require("luau-lsp").setup {
plugin = {
enabled = true,
port = 3667,
},
}
require("luau-lsp").setup {
types = {
definition_files = { "path/to/definitions/file" },
documentation_files = { "path/to/documentation/file" },
},
}
require("luau-lsp").setup {
fflags = {
sync = true, -- sync currently enabled fflags with roblox's published fflags
override = {
LuauSolverV2 = "True", -- enable the new solver
},
},
}
:LuauLsp bytecode
and :LuauLsp compiler_remarks
open a new window and show the current Luau file bytecode and compiler remarks. It will automatically update if you change the file or edit it. Close with q
.
bytecode.mp4
The server is not able to read .luaurc
aliases yet, but require("luau-lsp").aliases()
can read .luaurc
if it exists and returns a table containing the aliases with @
.
.luaurc
lookup order:
.luaurc
lib/.luaurc
src/.luaurc
require("luau-lsp").setup {
server = {
settings = {
["luau-lsp"] = {
require = {
directoryAliases = require("luau-lsp").aliases(),
},
},
},
},
}
require("luau-lsp").setup {
server = {
settings = {
-- https://github.com/folke/neoconf.nvim/blob/main/schemas/luau_lsp.json
["luau-lsp"] = {
completion = {
imports = {
enabled = true, -- enable auto imports
},
},
},
},
},
}
Add the following to your .nvim.lua
require("luau-lsp").config {
...
}
For more info about .nvim.lua
, check :help 'exrc'
Defaults
---@alias luau-lsp.PlatformType "standard" | "roblox"
---@alias luau-lsp.RobloxSecurityLevel "None" | "LocalUserSecurity" | "PluginSecurity" | "RobloxScriptSecurity"
---@class luau-lsp.Config
local defaults = {
platform = {
---@type luau-lsp.PlatformType
type = "roblox",
},
sourcemap = {
enabled = true,
autogenerate = true,
rojo_path = "rojo",
rojo_project_file = "default.project.json",
include_non_scripts = true,
sourcemap_file = "sourcemap.json",
},
types = {
---@type string[]
definition_files = {},
---@type string[]
documentation_files = {},
---@type luau-lsp.RobloxSecurityLevel
roblox_security_level = "PluginSecurity",
},
fflags = {
enable_by_default = false,
sync = true,
---@type table<string, string>
override = {},
},
plugin = {
enabled = false,
port = 3667,
},
---@class luau-lsp.ClientConfig: vim.lsp.ClientConfig
server = {
---@type string[]
cmd = { "luau-lsp", "lsp" },
---@type fun(path: string): string?
root_dir = function(path)
return vim.fs.root(path, function(name)
return name:match ".+%.project%.json$"
end) or vim.fs.root(path, {
".git",
".luaurc",
"stylua.toml",
"selene.toml",
"selene.yml",
})
end,
},
}
To verify the setup, run :checkhealth luau-lsp
To open the luau-lsp.nvim
log file, run :LuauLsp log
Make sure to enable the file watcher capability and pass it in the server options
-- there are couple ways to get the default capabilities, it depends on your distribution or the completion plugin you are using
local capabilities = vim.lsp.protocol.make_client_capabilities()
-- example using nvim-cmp
capabilities = vim.tbl_deep_extend("force", capabilities, require("nvim_cmp_lsp").default_capabilities())
-- manually enable the file watcher capability so luau-lsp will know when the sourcemap changes
-- only needed if you are on Linux
capabilities.workspace.didChangeWatchedFiles.dynamicRegistration = true
require("luau-lsp").setup {
server = {
capabilities = capabilities,
},
}
local function rojo_project()
return vim.fs.root(0, function(name)
return name:match ".+%.project%.json$"
end)
end
require("luau-lsp").setup {
platform = {
type = rojo_project() and "roblox" or "standard",
},
}
local function rojo_project()
return vim.fs.root(0, function(name)
return name:match ".+%.project%.json$"
end)
end
if rojo_project() then
vim.filetype.add {
extension = {
lua = function(path)
return path:match "%.nvim%.lua$" and "lua" or "luau"
end,
},
}
end