Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@
/_
/nvim-treesitter
/todo.txt
/spec/fixtures/**/obj/
/spec/fixtures/**/target/
5 changes: 3 additions & 2 deletions lua/nvim-test/init.lua
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
local notifier = require "nvim-test.notify"
local api = vim.api
local suite_runner
local Runner = require "nvim-test.runner"
local M = {
config = vim.deepcopy(require "nvim-test.config"),
runners = require "nvim-test.runners",
Expand All @@ -27,9 +26,11 @@ function M.run(scope)
-- Find tests
if scope == "nearest" then
opts.tests = runner:find_nearest_test(filetype)
elseif scope == "file" then
opts.tests = runner:find_tests_in_file(filetype)
end

-- Find file
-- Find test file
if scope ~= "suite" then
filename =
vim.fn.expand("%" .. (runner.config.filename_modifier or M.config.filename_modifier))
Expand Down
34 changes: 22 additions & 12 deletions lua/nvim-test/runner.lua
Original file line number Diff line number Diff line change
Expand Up @@ -36,26 +36,29 @@ function Runner:setup(config)
return self
end

function Runner:find_tests_in_file(filetype)
return nil
end

function Runner:find_nearest_test(filetype)
local query_get = ts.query.get or ts.get_query -- neovim 0.8 support
local query = query_get(ts_parsers.ft_to_lang(filetype), "nvim-test")
local result = {}
if query then
local curnode = ts_utils.get_node_at_cursor()
while curnode do
local iter = query:iter_captures(curnode, 0)
local capture_id, capture_node = iter()
if capture_node == curnode and query.captures[capture_id] == "scope-root" then
while query.captures[capture_id] ~= "test-name" do
capture_id, capture_node = iter()
if not capture_id then
return result
end
for pattern, match, metadata in query:iter_matches(curnode, 0) do
for id, node in pairs(match) do
local name = query.captures[id]
if name == "test-name" then
local test_name = self:parse_testname(ts.query.get_node_text(node, 0))
local fqn = self:get_fully_qualified_name(filetype, node, test_name)
table.insert(result, fqn)
return result
end
end
end
local name = self:parse_testname(ts.get_node_text(capture_node, 0))
table.insert(result, 1, name)
end
curnode = curnode:parent()
curnode = curnode:parent()
end
end
return result
Expand Down Expand Up @@ -104,6 +107,13 @@ function Runner:find_working_directory(filename)
return self.config.working_directory
end

---@param curnode tstree
---@param name string
---@return string
function Runner:get_fully_qualified_name(filetype, curnode, name)
return name
end

-- Build command list
---
---@return table cmd command list
Expand Down
40 changes: 35 additions & 5 deletions lua/nvim-test/runners/cargo-test.lua
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
-- TODO
--
local Runner = require "nvim-test.runner"
local ts_parsers = require("nvim-treesitter.parsers")
local ts_utils = require("nvim-treesitter.ts_utils")
local utils = require "nvim-test.utils"
local ts = vim.treesitter

local cargotest = Runner:init({ command = "cargo", args = { "test" }, package = false }, {
rust = [[
local query = [[
(
(
mod_item name: (identifier) @test-name
Expand All @@ -17,9 +18,38 @@ local cargotest = Runner:init({ command = "cargo", args = { "test" }, package =
(#match? @test-name "[Tt]est")
)
@scope-root)
]],
]]

local cargotest = Runner:init({ command = "cargo", args = { "test" }, package = false }, {
rust = query,
})

function cargotest:find_nearest_test(filetype)
local ts_query = ts.get_query(ts_parsers.ft_to_lang(filetype), "nvim-test")
local result = {}
if ts_query then
local curnode = ts_utils.get_node_at_cursor()
while curnode do
for pattern, match, _ in ts_query:iter_matches(curnode, 0) do
for id, node in pairs(match) do
local name = ts_query.captures[id]
if name == "test-name" then
local test_name = cargotest:parse_testname(ts.query.get_node_text(node, 0))
local parse_testname_func = function (t_name)
return self:parse_testname(t_name)
end
local fqn = utils:get_fully_qualified_name(filetype, node, test_name, parse_testname_func, "::")
table.insert(result, fqn)
return result
end
end
end
curnode = curnode:parent()
end
end
return result
end

function cargotest:build_args(args, filename, opts)
-- for whole suite do nothing
if not filename then
Expand Down
108 changes: 91 additions & 17 deletions lua/nvim-test/runners/dotnet.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
local Runner = require "nvim-test.runner"
local utils = require "nvim-test.utils"
local ts_parsers = require("nvim-treesitter.parsers")
local ts_utils = require("nvim-treesitter.ts_utils")
local ts = vim.treesitter

local cstest = Runner:init({
command = "dotnet",
Expand All @@ -7,28 +11,98 @@ local cstest = Runner:init({
find_files = { "{name}Tests.{ext}", "Tests.{ext}" }, -- find testfile for a file
}, {
c_sharp = [[
; Namespace
((namespace_declaration name: (identifier) @test-name) @scope-root)

; Class
((class_declaration name: (identifier) @test-name) @scope-root)

; Method
((method_declaration
(attribute_list
(attribute name: (identifier) @attribute-name
(#match? @attribute-name "(Fact|Theory|Test|TestMethod)")
; attributes used by xunit, nunit and mstest
))
name: (identifier) @test-name)
@scope-root)
(
(method_declaration
(attribute_list
(attribute name: (identifier) @attribute-name
(#match? @attribute-name "(Fact|Theory|Test|TestMethod)")
; attributes used by xunit, nunit and mstest
))
name: (identifier) @test-name)
@scope-root
)

]],
})

function cstest:build_test_args(args, tests)
table.insert(args, "--filter")
table.insert(args, "FullyQualifiedName=" .. table.concat(tests, "."))
function cstest:find_tests_in_file(filetype)
local parser_name = ts_parsers.ft_to_lang(filetype)
local query = ts.get_query(parser_name, "nvim-test")
local result = {}
if query then
local parser = ts.get_parser(0, parser_name)
local root = unpack(parser:parse()):root()
for pattern, match, metadata in query:iter_matches(root, 0) do
for id, node in pairs(match) do
local name = query.captures[id]
if name == "test-name" then
local test_name = self:parse_testname(ts.query.get_node_text(node, 0))
local fqn = self:get_fully_qualified_name(filetype, node, test_name)
table.insert(result, fqn)
end
end
end
end
return result
end

function cstest:find_nearest_test(filetype)
local query = ts.get_query(ts_parsers.ft_to_lang(filetype), "nvim-test")
local result = {}
if query then
local curnode = ts_utils.get_node_at_cursor()
while curnode do
for pattern, match, metadata in query:iter_matches(curnode, 0) do
for id, node in pairs(match) do
local name = query.captures[id]
if name == "test-name" then
local test_name = self:parse_testname(ts.query.get_node_text(node, 0))
local fqn = self:get_fully_qualified_name(filetype, node, test_name)
table.insert(result, fqn)
return result
end
end
end
curnode = curnode:parent()
end
end
return result
end

function cstest:get_fully_qualified_name(filetype, curnode, name)
while curnode do
local type = curnode:type()
if type == "class_declaration" or
type == "namespace_declaration" or
type == "file_scoped_namespace_declaration"
then
for node, field_name in curnode:iter_children() do
if node:named() then
if field_name == "name" then
name = ts.query.get_node_text(node, 0) .. "." .. name
end
end
end
end
curnode = curnode:parent()
end
return name
end

function cstest:find_working_directory(filename)
local root = self.config.working_directory
if not root then
root = utils.find_relative_root(filename, "^.+%.csproj$")
end
return root
end

function cstest:build_args(args, filename, opts)
if opts.tests and #opts.tests > 0 then
table.insert(args, "--filter")
table.insert(args, "FullyQualifiedName=" .. table.concat(opts.tests, "|"))
end
end

return cstest
40 changes: 40 additions & 0 deletions lua/nvim-test/runners/hspec.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,18 @@
local Runner = require "nvim-test.runner"
local ts_parsers = require("nvim-treesitter.parsers")
local ts_utils = require("nvim-treesitter.ts_utils")
local utils = require "nvim-test.utils"
local ts = vim.treesitter

local fqn_query = [[
((stmt (exp_infix (exp_apply
(exp_name) @exp-name
(#match? @exp-name "^(describe)")
(exp_literal) @test-name
)
))
@scope-root)
]]

local hspec = Runner:init({
command = { "runhaskell" },
Expand All @@ -16,6 +30,32 @@ local hspec = Runner:init({
]],
})

function hspec:find_nearest_test(filetype)
local ts_query = ts.get_query(ts_parsers.ft_to_lang(filetype), "nvim-test")
local result = {}
if ts_query then
local curnode = ts_utils.get_node_at_cursor()
while curnode do
for pattern, match, _ in ts_query:iter_matches(curnode, 0) do
for id, node in pairs(match) do
local name = ts_query.captures[id]
if name == "test-name" then
local test_name = self:parse_testname(ts.query.get_node_text(node, 0))
local parse_testname_func = function (t_name)
return self:parse_testname(t_name)
end
local fqn = utils:get_fully_qualified_name(filetype, node, test_name, parse_testname_func, "/", fqn_query)
table.insert(result, fqn)
return result
end
end
end
curnode = curnode:parent()
end
end
return result
end

function hspec:parse_testname(name)
return name:gsub("^[\"'`]", ""):gsub("[\"'`]$", "")
end
Expand Down
29 changes: 29 additions & 0 deletions lua/nvim-test/runners/jest.lua
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
local Runner = require "nvim-test.runner"
local ts_parsers = require("nvim-treesitter.parsers")
local ts_utils = require("nvim-treesitter.ts_utils")
local ts = vim.treesitter
local utils = require "nvim-test.utils"

local query = [[
Expand All @@ -23,6 +26,32 @@ local jest = Runner:init({
typescript = query,
})

function jest:find_nearest_test(filetype)
local ts_query = ts.get_query(ts_parsers.ft_to_lang(filetype), "nvim-test")
local result = {}
if ts_query then
local curnode = ts_utils.get_node_at_cursor()
while curnode do
for pattern, match, _ in ts_query:iter_matches(curnode, 0) do
for id, node in pairs(match) do
local name = ts_query.captures[id]
if name == "test-name" then
local parse_testname_func = function (t_name)
return jest:parse_testname(t_name)
end
local test_name = parse_testname_func(ts.query.get_node_text(node, 0))
local fqn = utils:get_fully_qualified_name(filetype, node, test_name, parse_testname_func)
table.insert(result, fqn)
return result
end
end
end
curnode = curnode:parent()
end
end
return result
end

function jest:parse_testname(name)
return name:gsub("^[\"'`]", ""):gsub("[\"'`]$", "")
end
Expand Down
Loading