diff --git a/lua/neotest-vstest/client.lua b/lua/neotest-vstest/client.lua index 4aa4ae9..18f9513 100644 --- a/lua/neotest-vstest/client.lua +++ b/lua/neotest-vstest/client.lua @@ -10,9 +10,9 @@ local client_creation_semaphore = nio.control.semaphore(1) local clients = {} ---@param project DotnetProjectInfo? ----@param solution_dir string? path to the solution directory +---@param solution string? path to the solution file ---@return neotest-vstest.Client? -function client_discovery.get_client_for_project(project, solution_dir) +function client_discovery.get_client_for_project(project, solution) if not project then return nil end @@ -28,7 +28,7 @@ function client_discovery.get_client_for_project(project, solution_dir) -- Check if the project is part of a solution. -- If not then do not create a client. - local solution_projects = solution_dir and dotnet_utils.get_solution_projects(solution_dir) + local solution_projects = solution and dotnet_utils.get_solution_projects(solution) if solution_projects and #solution_projects.projects > 0 then if not vim.list_contains(solution_projects.projects, project) then logger.debug( @@ -45,7 +45,7 @@ function client_discovery.get_client_for_project(project, solution_dir) ) else logger.debug( - "neotest-vstest: no solution projects found, using solution: " .. vim.inspect(solution_dir) + "neotest-vstest: no solution projects found, using solution: " .. vim.inspect(solution) ) end diff --git a/lua/neotest-vstest/dotnet_utils.lua b/lua/neotest-vstest/dotnet_utils.lua index 961f881..efff5f4 100644 --- a/lua/neotest-vstest/dotnet_utils.lua +++ b/lua/neotest-vstest/dotnet_utils.lua @@ -232,35 +232,31 @@ local solution_discovery_semaphore = nio.control.semaphore(1) ---lists all projects in solution. ---Falls back to listing all project in directory. ---@async ----@param root string +---@param solution_path string ---@return { solution: string?, projects: DotnetProjectInfo[] } -function dotnet_utils.get_solution_projects(root) +function dotnet_utils.get_solution_projects(solution_path) solution_discovery_semaphore.acquire() if project_cache then solution_discovery_semaphore.release() return project_cache end - local solution = vim.fs.find(function(name) - return name:match("%.slnx?$") - end, { upward = false, type = "file", path = root, limit = 1 })[1] - - local solution_dir = vim.fs.dirname(solution) + local solution_dir = vim.fs.dirname(solution_path) local projects = {} - if solution then + if solution_path then local _, res = lib.process.run({ "dotnet", "sln", - solution, + solution_path, "list", }, { stderr = false, stdout = true, }) - logger.debug("neotest-vstest: dotnet sln " .. solution .. " list output:") + logger.debug("neotest-vstest: dotnet sln " .. solution_path .. " list output:") logger.debug(res.stdout) local relative_path_projects = vim.list_slice(nio.fn.split(res.stdout, "\n"), 3) @@ -268,10 +264,10 @@ function dotnet_utils.get_solution_projects(root) projects[#projects + 1] = vim.fs.joinpath(solution_dir, project) end else - logger.info("found no solution file in " .. root) + logger.info("found no solution file in " .. solution_path) projects = vim.fs.find(function(name, _) return name:match("%.[cf]sproj$") - end, { upward = false, type = "file", path = root }) + end, { upward = false, type = "file", path = solution_path }) end local test_projects = {} @@ -283,10 +279,10 @@ function dotnet_utils.get_solution_projects(root) end end - logger.info("found test projects in " .. root) + logger.info("found test projects in " .. solution_dir) logger.info(test_projects) - local res = { solution = solution, projects = test_projects } + local res = { solution = solution_path, projects = test_projects } project_cache = res diff --git a/lua/neotest-vstest/init.lua b/lua/neotest-vstest/init.lua index 562526f..be107fd 100644 --- a/lua/neotest-vstest/init.lua +++ b/lua/neotest-vstest/init.lua @@ -21,6 +21,7 @@ local dap_settings = { } local solution +local solution_dir ---@package ---@type neotest.Adapter @@ -28,15 +29,53 @@ local solution local DotnetNeotestAdapter = { name = "neotest-vstest" } function DotnetNeotestAdapter.root(path) - local solution_dir = lib.files.match_root_pattern("*.sln")(path) - or lib.files.match_root_pattern("*.slnx")(path) - if solution_dir then - client_discovery.discover_solution_tests(solution_dir) - solution = solution_dir + return solution_dir + end + + local first_solution = lib.files.match_root_pattern("*.sln", "*.slnx")(path) + + local solutions = vim.fs.find(function(name, _) + return name:match("%.slnx?$") + end, { upward = false, type = "file", path = first_solution, limit = math.huge }) + + logger.info(string.format("neotest-vstest: scanning %s for solution file...", first_solution)) + logger.info(solutions) + + if #solutions > 0 then + local solution_dir_future = nio.control.future() + + if #solutions == 1 then + solution = solutions[1] + solution_dir = vim.fs.dirname(solution) + solution_dir_future.set(solution_dir) + else + vim.ui.select(solutions, { + prompt = "Multiple solutions exists. Select a solution file: ", + format_item = function(item) + return vim.fs.basename(item) + end, + }, function(selected) + nio.run(function() + if selected then + solution = selected + solution_dir = vim.fs.dirname(selected) + end + logger.info(string.format("neotest-vstest: selected solution file %s", selected)) + solution_dir_future.set(solution_dir) + end) + end) + end + + if solution_dir_future.wait() then + logger.info(string.format("neotest-vstest: found solution file %s", solution)) + client_discovery.discover_solution_tests(solution) + return solution_dir + end end - return solution_dir or lib.files.match_root_pattern("*.[cf]sproj")(path) + logger.info(string.format("neotest-vstest: no solution file found in %s", path)) + return lib.files.match_root_pattern(".git")(path) or path end function DotnetNeotestAdapter.is_test_file(file_path) diff --git a/spec/root_detection_spec.lua b/spec/root_detection_spec.lua index d82a140..fa3b8e6 100644 --- a/spec/root_detection_spec.lua +++ b/spec/root_detection_spec.lua @@ -18,10 +18,4 @@ describe("Test root detection", function() local root = plugin.root(dir .. "/src/FsharpTest") assert.are_equal(dir, root) end) - nio.tests.it("Detect .fsproj file as root from project dir with no .sln file", function() - local plugin = require("neotest-vstest") - local dir = vim.fn.getcwd() .. "/spec/samples/test_project" - local root = plugin.root(dir) - assert.are_equal(dir, root) - end) end)