Skip to content

Commit

Permalink
refactor: improve health checks and logger
Browse files Browse the repository at this point in the history
  • Loading branch information
lopi-py committed Aug 16, 2024
1 parent a2b3229 commit 186fcea
Show file tree
Hide file tree
Showing 11 changed files with 126 additions and 114 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ local defaults = {
---@class luau-lsp.ClientConfig: vim.lsp.ClientConfig
server = {
---@type string[]
cmd = { "luau-lsp", "lsp" },
cmd = { vim.fn.exepath "luau-lsp", "lsp" },
---@type fun(path: string): string?
root_dir = function(path)
local server = require "luau-lsp.server"
Expand Down
2 changes: 1 addition & 1 deletion lua/luau-lsp/command.lua
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ local log = require "luau-lsp.log"
local commands = {
log = {
execute = function()
vim.cmd.tabnew(log.log_file)
vim.cmd.tabnew(log.filename)
end,
},

Expand Down
2 changes: 1 addition & 1 deletion lua/luau-lsp/config.lua
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ local defaults = {
---@class luau-lsp.ClientConfig: vim.lsp.ClientConfig
server = {
---@type string[]
cmd = { "luau-lsp", "lsp" },
cmd = { vim.fn.exepath "luau-lsp", "lsp" },
---@type fun(path: string): string?
root_dir = function(path)
local server = require "luau-lsp.server"
Expand Down
67 changes: 44 additions & 23 deletions lua/luau-lsp/health.lua
Original file line number Diff line number Diff line change
@@ -1,47 +1,68 @@
local Job = require "plenary.job"
local config = require "luau-lsp.config"

local M = {}

function M.check()
vim.health.start "luau-lsp"
---@param opts { name: string, cmd: string[], version?: string, required: boolean? }
local function check_executable(opts)
local ok, job = pcall(Job.new, Job, {
command = opts.cmd[1],
args = vim.list_slice(opts.cmd, 2),
})

if not ok then
local report = opts.required == false and vim.health.warn or vim.health.error
report(string.format("%s: not available", opts.name))
return
end

if vim.fn.executable "luau-lsp" == 1 then
local version = require("luau-lsp.server").version()
if vim.version.ge(version, "1.32.0") then
vim.health.ok(string.format("luau-lsp: `%s`", tostring(version)))
if opts.version then
local version = table.concat(job:sync(), "\n")
if vim.version.ge(version, opts.version) then
vim.health.ok(string.format("%s: `%s`", opts.name, tostring(version)))
else
vim.health.error(
string.format("luau-lsp: required version is `1.32.0`, found `%s`", tostring(version))
string.format(
"%s: required version is `%s`, found `%s`",
opts.name,
opts.version:gsub("a", "b"),
version
)
)
end
else
vim.health.error "luau-lsp: not available"
end
end

function M.check()
vim.health.start "luau-lsp"

check_executable {
name = "luau-lsp",
cmd = { config.get().server.cmd[1], "--version" },
version = "1.32.0",
}

local autocmds = vim.api.nvim_get_autocmds {
group = "lspconfig",
event = "FileType",
pattern = "luau",
}

if #autocmds == 0 then
vim.health.ok "No conflicts with `nvim-lspconfig`"
else
vim.health.error "`lspconfig.luau_lsp.setup` was called, it may cause conflicts"
end

vim.health.start "Rojo (required for sourcemap generation)"
vim.health.start "Rojo (required for automatic sourcemap generation)"

if vim.fn.executable "rojo" == 1 then
local version = require("luau-lsp.roblox.sourcemap").version()
if vim.version.ge(version, "7.3.0") then
vim.health.ok(string.format("rojo: `%s`", tostring(version)))
else
vim.health.error(
string.format("rojo: required version is `7.3.0`, found `%s`", tostring(version))
)
end
else
vim.health.warn "rojo: not available"
end
check_executable {
name = "rojo",
cmd = { config.get().sourcemap.rojo_path, "--version" },
version = "7.3.0",
required = config.get().platform.type == "roblox"
and config.get().sourcemap.enabled
and config.get().sourcemap.autogenerate,
}
end

return M
1 change: 1 addition & 0 deletions lua/luau-lsp/json.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ local M = {}

---@param str string
---@param opts? table<string, any>
---@return any
function M.decode(str, opts)
str = str
:gsub("//[^\n]*", "")
Expand Down
68 changes: 41 additions & 27 deletions lua/luau-lsp/log.lua
Original file line number Diff line number Diff line change
@@ -1,44 +1,58 @@
local Path = require "plenary.path"
local util = require "luau-lsp.util"

local PLUGIN_NAME = "luau-lsp.nvim"
local LOG_FILE = Path:new(util.storage_file "luau-lsp.log")
local M = {}

local levels_lookup = {}
for k, v in pairs(vim.log.levels) do
levels_lookup[v] = k
end
M.level = vim.log.levels.WARN
M.filename = util.storage_file "luau-lsp.log"

---@type file*?
local logfile

---@return boolean
local function supports_title()
local success = pcall(require, "notify")
return success
return package.loaded["notify"] ~= nil
end

---@param message string
---@param level string
local function write(message, level)
if not logfile then
logfile = io.open(M.filename, "a+")
end
assert(logfile)
logfile:write(string.format("%s[%s] %s", os.date "%H:%M:%S", level, message))
logfile:write "\n"
logfile:flush()
end

---@param message string
---@param level number
local notify = vim.schedule_wrap(function(message, level)
if supports_title() then
vim.notify(message, level, { title = "luau-lsp.nvim" })
else
vim.notify(string.format("[%s] %s", "luau-lsp.nvim", message), level)
end
end)

---@param level string
---@param levelnr number
---@return fun(message: string, ...: any)
local function create_logger(level)
return vim.schedule_wrap(function(message, ...)
local timestr = vim.fn.strftime "%H:%M:%S"
local function create_logger(level, levelnr)
return function(message, ...)
message = string.format(message, ...)

LOG_FILE:write(string.format("%s[%s]: %s\n", timestr, levels_lookup[level], message), "a")

if level >= vim.log.levels.WARN then
if not supports_title() then
message = string.format("[%s]: %s", PLUGIN_NAME, message)
end
write(message, level)

vim.notify(message, level, { title = PLUGIN_NAME })
if levelnr >= M.level then
notify(message, levelnr)
end
end)
end
end

local M = {}

M.log_file = tostring(LOG_FILE)
M.debug = create_logger(vim.log.levels.DEBUG)
M.info = create_logger(vim.log.levels.INFO)
M.warn = create_logger(vim.log.levels.WARN)
M.error = create_logger(vim.log.levels.ERROR)
M.debug = create_logger("DEBUG", vim.log.levels.DEBUG)
M.info = create_logger("INFO", vim.log.levels.INFO)
M.warn = create_logger("WARN", vim.log.levels.WARN)
M.error = create_logger("ERROR", vim.log.levels.ERROR)

return M
4 changes: 2 additions & 2 deletions lua/luau-lsp/roblox/init.lua
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ function M.prepare(opts)
table.insert(opts.cmd, "--docs=" .. api_docs_file())
end

function M.start()
M.start = vim.schedule_wrap(function()
if config.get().platform.type ~= "roblox" then
return
end
Expand All @@ -82,6 +82,6 @@ function M.start()
if config.get().plugin.enabled then
require("luau-lsp.roblox.studio").start()
end
end
end)

return M
45 changes: 18 additions & 27 deletions lua/luau-lsp/roblox/sourcemap.lua
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,13 @@ local job = nil

local M = {}

---@return string[]
function M.get_rojo_project_files()
local project_files = vim.split(vim.fn.glob "*.project.json", "\n")
table.sort(project_files)
return vim.tbl_filter(util.is_file, project_files)
end

local get_rojo_project_file = async.wrap(function(callback)
local project_file = config.get().sourcemap.rojo_project_file
if util.is_file(project_file) then
Expand Down Expand Up @@ -49,20 +56,25 @@ local function start_sourcemap_generation(project_file)
table.insert(args, "--include-non-scripts")
end

log.info("Starting sourcemap generation for `%s`", project_file)

job = Job:new {
local ok
ok, job = pcall(Job.new, Job, {
command = config.get().sourcemap.rojo_path,
args = args,
on_exit = function(self, code)
if code and code ~= 0 then
if code ~= 0 then
local err = table.concat(self:stderr_result(), "\n")
log.error("Failed to update sourcemap for `%s`: %s", project_file, err)
end

job = nil
end,
}
})

if not ok then
log.error "rojo executable not found"
return
end

log.info("Starting sourcemap generation for `%s`", project_file)
job:start()
end

Expand All @@ -72,27 +84,6 @@ local function stop_sourcemap_generation()
end
end

---@return vim.Version
function M.version()
local result = Job:new({
command = config.get().sourcemap.rojo_path,
args = { "--version" },
}):sync()

local version = vim.version.parse(result[1])
assert(version, "could not parse rojo version")

return version
end

---@return string[]
function M.get_rojo_project_files()
local project_files = vim.split(vim.fn.glob "*.project.json", "\n")
table.sort(project_files)

return vim.tbl_filter(util.is_file, project_files)
end

M.start = async.void(function(project_file)
if project_file and not util.is_file(project_file) then
log.error("Invalid project file `%s`", project_file)
Expand Down
33 changes: 14 additions & 19 deletions lua/luau-lsp/server.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
local Job = require "plenary.job"
local async = require "plenary.async"
local compat = require "luau-lsp.compat"
local config = require "luau-lsp.config"
Expand Down Expand Up @@ -53,8 +52,6 @@ end
local function get_cmd()
local cmd = vim.deepcopy(config.get().server.cmd)

util.expand_cmd(cmd)

for _, definition_file in ipairs(config.get().types.definition_files) do
definition_file = vim.fs.normalize(definition_file)
if util.is_file(definition_file) then
Expand Down Expand Up @@ -125,7 +122,7 @@ local function force_push_diagnostics(opts)
end

---@async
---@return number
---@return number?
local function start_language_server()
local opts = vim.tbl_deep_extend("force", config.get().server, {
name = "luau-lsp",
Expand All @@ -139,11 +136,12 @@ local function start_language_server()
require("luau-lsp.roblox").prepare(opts)

local client_id = vim.lsp.start_client(opts)
assert(client_id, "could not start luau-lsp")
if not client_id then
log.error "luau-lsp executable not found"
return
end

vim.schedule(function()
require("luau-lsp.roblox").start()
end)
require("luau-lsp.roblox").start()

return client_id
end
Expand All @@ -167,16 +165,6 @@ end

local M = {}

---@return vim.Version
function M.version()
local result = Job:new({ command = "luau-lsp", args = { "--version" } }):sync()

local version = vim.version.parse(result[1])
assert(version, "could not parse luau-lsp version")

return version
end

---@param bufnr? number
function M.start(bufnr)
bufnr = bufnr or vim.api.nvim_get_current_buf()
Expand All @@ -196,7 +184,14 @@ function M.start(bufnr)
end

if #pending_buffers == 0 then
async.run(start_language_server, vim.schedule_wrap(attach_pending_buffers))
async.run(
start_language_server,
vim.schedule_wrap(function(client_id)
if client_id then
attach_pending_buffers(client_id)
end
end)
)
end

table.insert(pending_buffers, bufnr)
Expand Down
8 changes: 0 additions & 8 deletions lua/luau-lsp/util.lua
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,4 @@ function M.get_client(bufnr)
return compat.get_clients({ name = "luau-lsp", bufnr = bufnr })[1]
end

---@param cmd string[]
function M.expand_cmd(cmd)
local exepath = vim.fn.exepath(cmd[1])
if exepath ~= "" then
cmd[1] = exepath
end
end

return M
Loading

0 comments on commit 186fcea

Please sign in to comment.