Skip to content

Commit f626075

Browse files
authored
feat: solution selector (#12)
* feat: add solution selector * auto-select when only one solution
1 parent 8eb050d commit f626075

File tree

4 files changed

+59
-30
lines changed

4 files changed

+59
-30
lines changed

lua/neotest-vstest/client.lua

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,9 @@ local client_creation_semaphore = nio.control.semaphore(1)
1010
local clients = {}
1111

1212
---@param project DotnetProjectInfo?
13-
---@param solution_dir string? path to the solution directory
13+
---@param solution string? path to the solution file
1414
---@return neotest-vstest.Client?
15-
function client_discovery.get_client_for_project(project, solution_dir)
15+
function client_discovery.get_client_for_project(project, solution)
1616
if not project then
1717
return nil
1818
end
@@ -28,7 +28,7 @@ function client_discovery.get_client_for_project(project, solution_dir)
2828

2929
-- Check if the project is part of a solution.
3030
-- If not then do not create a client.
31-
local solution_projects = solution_dir and dotnet_utils.get_solution_projects(solution_dir)
31+
local solution_projects = solution and dotnet_utils.get_solution_projects(solution)
3232
if solution_projects and #solution_projects.projects > 0 then
3333
if not vim.list_contains(solution_projects.projects, project) then
3434
logger.debug(
@@ -45,7 +45,7 @@ function client_discovery.get_client_for_project(project, solution_dir)
4545
)
4646
else
4747
logger.debug(
48-
"neotest-vstest: no solution projects found, using solution: " .. vim.inspect(solution_dir)
48+
"neotest-vstest: no solution projects found, using solution: " .. vim.inspect(solution)
4949
)
5050
end
5151

lua/neotest-vstest/dotnet_utils.lua

Lines changed: 10 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -232,46 +232,42 @@ local solution_discovery_semaphore = nio.control.semaphore(1)
232232
---lists all projects in solution.
233233
---Falls back to listing all project in directory.
234234
---@async
235-
---@param root string
235+
---@param solution_path string
236236
---@return { solution: string?, projects: DotnetProjectInfo[] }
237-
function dotnet_utils.get_solution_projects(root)
237+
function dotnet_utils.get_solution_projects(solution_path)
238238
solution_discovery_semaphore.acquire()
239239
if project_cache then
240240
solution_discovery_semaphore.release()
241241
return project_cache
242242
end
243243

244-
local solution = vim.fs.find(function(name)
245-
return name:match("%.slnx?$")
246-
end, { upward = false, type = "file", path = root, limit = 1 })[1]
247-
248-
local solution_dir = vim.fs.dirname(solution)
244+
local solution_dir = vim.fs.dirname(solution_path)
249245

250246
local projects = {}
251247

252-
if solution then
248+
if solution_path then
253249
local _, res = lib.process.run({
254250
"dotnet",
255251
"sln",
256-
solution,
252+
solution_path,
257253
"list",
258254
}, {
259255
stderr = false,
260256
stdout = true,
261257
})
262258

263-
logger.debug("neotest-vstest: dotnet sln " .. solution .. " list output:")
259+
logger.debug("neotest-vstest: dotnet sln " .. solution_path .. " list output:")
264260
logger.debug(res.stdout)
265261

266262
local relative_path_projects = vim.list_slice(nio.fn.split(res.stdout, "\n"), 3)
267263
for _, project in ipairs(relative_path_projects) do
268264
projects[#projects + 1] = vim.fs.joinpath(solution_dir, project)
269265
end
270266
else
271-
logger.info("found no solution file in " .. root)
267+
logger.info("found no solution file in " .. solution_path)
272268
projects = vim.fs.find(function(name, _)
273269
return name:match("%.[cf]sproj$")
274-
end, { upward = false, type = "file", path = root })
270+
end, { upward = false, type = "file", path = solution_path })
275271
end
276272

277273
local test_projects = {}
@@ -283,10 +279,10 @@ function dotnet_utils.get_solution_projects(root)
283279
end
284280
end
285281

286-
logger.info("found test projects in " .. root)
282+
logger.info("found test projects in " .. solution_dir)
287283
logger.info(test_projects)
288284

289-
local res = { solution = solution, projects = test_projects }
285+
local res = { solution = solution_path, projects = test_projects }
290286

291287
project_cache = res
292288

lua/neotest-vstest/init.lua

Lines changed: 45 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,22 +21,61 @@ local dap_settings = {
2121
}
2222

2323
local solution
24+
local solution_dir
2425

2526
---@package
2627
---@type neotest.Adapter
2728
---@diagnostic disable-next-line: missing-fields
2829
local DotnetNeotestAdapter = { name = "neotest-vstest" }
2930

3031
function DotnetNeotestAdapter.root(path)
31-
local solution_dir = lib.files.match_root_pattern("*.sln")(path)
32-
or lib.files.match_root_pattern("*.slnx")(path)
33-
3432
if solution_dir then
35-
client_discovery.discover_solution_tests(solution_dir)
36-
solution = solution_dir
33+
return solution_dir
34+
end
35+
36+
local first_solution = lib.files.match_root_pattern("*.sln", "*.slnx")(path)
37+
38+
local solutions = vim.fs.find(function(name, _)
39+
return name:match("%.slnx?$")
40+
end, { upward = false, type = "file", path = first_solution, limit = math.huge })
41+
42+
logger.info(string.format("neotest-vstest: scanning %s for solution file...", first_solution))
43+
logger.info(solutions)
44+
45+
if #solutions > 0 then
46+
local solution_dir_future = nio.control.future()
47+
48+
if #solutions == 1 then
49+
solution = solutions[1]
50+
solution_dir = vim.fs.dirname(solution)
51+
solution_dir_future.set(solution_dir)
52+
else
53+
vim.ui.select(solutions, {
54+
prompt = "Multiple solutions exists. Select a solution file: ",
55+
format_item = function(item)
56+
return vim.fs.basename(item)
57+
end,
58+
}, function(selected)
59+
nio.run(function()
60+
if selected then
61+
solution = selected
62+
solution_dir = vim.fs.dirname(selected)
63+
end
64+
logger.info(string.format("neotest-vstest: selected solution file %s", selected))
65+
solution_dir_future.set(solution_dir)
66+
end)
67+
end)
68+
end
69+
70+
if solution_dir_future.wait() then
71+
logger.info(string.format("neotest-vstest: found solution file %s", solution))
72+
client_discovery.discover_solution_tests(solution)
73+
return solution_dir
74+
end
3775
end
3876

39-
return solution_dir or lib.files.match_root_pattern("*.[cf]sproj")(path)
77+
logger.info(string.format("neotest-vstest: no solution file found in %s", path))
78+
return lib.files.match_root_pattern(".git")(path) or path
4079
end
4180

4281
function DotnetNeotestAdapter.is_test_file(file_path)

spec/root_detection_spec.lua

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,4 @@ describe("Test root detection", function()
1818
local root = plugin.root(dir .. "/src/FsharpTest")
1919
assert.are_equal(dir, root)
2020
end)
21-
nio.tests.it("Detect .fsproj file as root from project dir with no .sln file", function()
22-
local plugin = require("neotest-vstest")
23-
local dir = vim.fn.getcwd() .. "/spec/samples/test_project"
24-
local root = plugin.root(dir)
25-
assert.are_equal(dir, root)
26-
end)
2721
end)

0 commit comments

Comments
 (0)