From 51c462301b93eccbce6b9ed67675c8d26b998a7d Mon Sep 17 00:00:00 2001 From: Daniil Rozanov Date: Sat, 4 May 2024 01:41:56 +0300 Subject: fix: properly read for large number of targets in fileapi reply --- lua/cmake/actions.lua | 2 +- lua/cmake/config.lua | 3 +++ lua/cmake/fileapi.lua | 49 +++++++++++++++++++++---------------------------- lua/cmake/project.lua | 2 +- lua/cmake/utils.lua | 8 ++++++++ 5 files changed, 34 insertions(+), 30 deletions(-) diff --git a/lua/cmake/actions.lua b/lua/cmake/actions.lua index d17096c..230e1e3 100644 --- a/lua/cmake/actions.lua +++ b/lua/cmake/actions.lua @@ -189,7 +189,7 @@ M.build_select = function(opts) format_item = function(item) return table.concat(item.name, config.variants_display.short.sep) end, - }, function(choice, idx) + }, function(_, idx) if not idx then return end diff --git a/lua/cmake/config.lua b/lua/cmake/config.lua index a0cdf0c..55ba38b 100644 --- a/lua/cmake/config.lua +++ b/lua/cmake/config.lua @@ -14,6 +14,9 @@ ---@field build_tool_args string[] An array of additional arguments to pass to the underlying build tool ---@field generator? string Set to a string to override CMake Tools’ preferred generator logic. If this is set, CMake will unconditionally use it as the -G CMake generator command line argument ---@field parallel_jobs? number By specifying a number, you can define how many jobs are run in parallel during the build +---@field build_directory string Build directory template +---@field environment {[string]:string} Environment for all `cmake` commands +---@field build_environment {[string]:string} Environment for all `cmake --build` commands ---@class CMakeVariant ---@field default string Default choice diff --git a/lua/cmake/fileapi.lua b/lua/cmake/fileapi.lua index 6beffcb..612fd59 100644 --- a/lua/cmake/fileapi.lua +++ b/lua/cmake/fileapi.lua @@ -1,5 +1,4 @@ local capabilities = require("cmake.capabilities") -local Path = require("plenary.path") local scan = require("plenary.scandir") local utils = require("cmake.utils") @@ -37,7 +36,7 @@ function FileApi.create(path, callback) end function FileApi.read_reply(path, callback) - local reply_dir = Path:new(path, unpack(reply_dir_suffix)):absolute() + local reply_dir = vim.fs.joinpath(path, unpack(reply_dir_suffix)) utils.file_exists(reply_dir, function(exists) if not exists then return @@ -54,33 +53,27 @@ function FileApi.read_reply(path, callback) local index = vim.json.decode(index_data) for _, object in ipairs(index.objects) do if object.kind == "codemodel" then - utils.read_file(Path:new(reply_dir, object.jsonFile):absolute(), function(codemodel_data) + utils.read_file(vim.fs.joinpath(reply_dir, object.jsonFile), function(codemodel_data) local codemodel = vim.json.decode(codemodel_data) - --FIX: this loop does not read all files if codemodel contains many targets (is will crash actually). - --This is because libuv (or some external settings) forbids to open files - -- in async mode more than some limit number. Seems like the solution is - -- to queue these calls and limit max number for opened files per time for _, target in ipairs(codemodel.configurations[1].targets) do - utils.read_file( - Path:new(reply_dir, target.jsonFile):absolute(), - function(target_data) - local target_json = vim.json.decode(target_data) - ---@type CMakeTarget - local _target = { - id = target_json.id, - name = target_json.name, - type = target_json.type, - path = nil, - } - if target_json.artifacts then - --NOTE: add_library( OBJECT ...) could contain more than ohe object in artifacts - -- so maybe in future it will be useful to handle not only first one. Current behaviour - -- aims to get path for only EXECUTABLE targets - _target.path = target_json.artifacts[1].path - end - callback(_target) + local work = vim.uv.new_work(utils.read_file_sync, function(target_data) + local target_json = vim.json.decode(target_data) + ---@type CMakeTarget + local _target = { + id = target_json.id, + name = target_json.name, + type = target_json.type, + path = nil, + } + if target_json.artifacts then + --NOTE: add_library( OBJECT ...) could contain more than ohe object in artifacts + -- so maybe in future it will be useful to handle not only first one. Current behaviour + -- aims to get path for only EXECUTABLE targets + _target.path = target_json.artifacts[1].path end - ) + callback(_target) + end) + vim.uv.queue_work(work, vim.fs.joinpath(reply_dir, target.jsonFile)) end end) end @@ -93,7 +86,7 @@ function FileApi.read_reply(path, callback) end function FileApi.query_exists(path, callback) - utils.file_exists(Path:new(path, unpack(query_path_suffix)):normalize(), function(query_exists) + utils.file_exists(vim.fs.joinpath(path, unpack(query_path_suffix)), function(query_exists) callback(query_exists) end) end @@ -103,7 +96,7 @@ function FileApi.exists(path, callback) if not query_exists then callback(false) else - utils.file_exists(Path:new(path, unpack(reply_dir_suffix)):normalize(), function(reply_exists) + utils.file_exists(vim.fs.joinpath(path, unpack(reply_dir_suffix)), function(reply_exists) callback(reply_exists) end) end diff --git a/lua/cmake/project.lua b/lua/cmake/project.lua index 5524fbd..0edbb02 100644 --- a/lua/cmake/project.lua +++ b/lua/cmake/project.lua @@ -174,7 +174,7 @@ end --- Set current build option by index --- @param idx number function Project.set_current_build_option(idx) - local _size = #Project[current_config].build_options + local _size = #configs[current_config].build_options assert(not (idx < 1 or idx > _size), "Index is out of range. Index is " .. idx .. " for " .. _size .. "config(s)") configs[current_config].current_build = idx end diff --git a/lua/cmake/utils.lua b/lua/cmake/utils.lua index 0c16658..ce6d213 100644 --- a/lua/cmake/utils.lua +++ b/lua/cmake/utils.lua @@ -56,6 +56,14 @@ function utils.read_file(path, callback) end) end +function utils.read_file_sync(path) + local fd = assert(vim.uv.fs_open(path, "r", 438)) + local stat = assert(vim.uv.fs_fstat(fd)) + local data = assert(vim.uv.fs_read(fd, stat.size, 0)) + assert(vim.uv.fs_close(fd)) + return data +end + function utils.write_file(path, txt, callback) uv.fs_open(path, "w", 438, function(err, fd) assert(not err, err) -- cgit v1.2.3