diff --git a/README.md b/README.md
index 454f68c..2655f3e 100644
--- a/README.md
+++ b/README.md
@@ -5,16 +5,16 @@ Cached treesitter navigation on a big projects, an attempt to make navigation in
## Description
_hopcsharp_ is a lightweight code navigation tool inspired by [ctags](https://github.com/universal-ctags/ctags), built
-for large C# projects. It uses [tree-sitter](https://tree-sitter.github.io/tree-sitter/) to quickly (not blazing fast
-but still good) parse code and store marks in a SQLite database for fast access, after that you can navigate freely in
-code base using built in methods or writing queries on your own against sqlite database.
+for large C# projects. It uses [tree-sitter](https://tree-sitter.github.io/tree-sitter/) to quickly parse code and
+store marks in a SQLite database for fast access, after that you can navigate freely in
+code base using built in methods or writing queries on your own against sqlite database. Important to understand that this is
+not an _LSP server_ this tool is intended for code navigation and read. It won't be as precise as full blown _LSP server_ but
+it won't require you to compile code as well :) so basically any c# codebase can be opened and parsed with this plugin.
-__This plugin is in its early stages__ expect lots of bugs :D, I hope that there will be people's interest and
+I hope that there will be people's interest and
contributions as well. I'll try to improve it little by little.
-
-
-
+[](https://gifyu.com/image/bvT1Q)
## How does it work?
@@ -39,6 +39,31 @@ Using [packer.nvim](https://github.com/wbthomason/packer.nvim):
use({ 'leblocks/hopcsharp.nvim', requires = { { 'kkharji/sqlite.lua' } } })
```
+## Quick Start
+
+Example keybinding configuration:
+
+```lua
+local hopcsharp = require('hopcsharp')
+
+-- database
+vim.keymap.set('n', 'hD', hopcsharp.init_database, { desc = 'hopcsharp: init database' })
+
+-- navigation
+vim.keymap.set('n', 'hd', hopcsharp.hop_to_definition, { desc = 'hopcsharp: go to definition' })
+vim.keymap.set('n', 'hi', hopcsharp.hop_to_implementation, { desc = 'hopcsharp: go to implementation' })
+vim.keymap.set('n', 'hr', hopcsharp.hop_to_reference, { desc = 'hopcsharp: go to reference' })
+vim.keymap.set('n', 'ht', hopcsharp.get_type_hierarchy, { desc = 'hopcsharp: type hierarchy' })
+
+-- fzf pickers (requires fzf-lua)
+local pickers = require('hopcsharp.pickers.fzf')
+vim.keymap.set('n', 'hf', pickers.source_files, { desc = 'hopcsharp: find source files' })
+vim.keymap.set('n', 'ha', pickers.all_definitions, { desc = 'hopcsharp: all definitions' })
+vim.keymap.set('n', 'hc', pickers.class_definitions, { desc = 'hopcsharp: class definitions' })
+vim.keymap.set('n', 'hn', pickers.interface_definitions, { desc = 'hopcsharp: interface definitions' })
+vim.keymap.set('n', 'he', pickers.enum_definitions, { desc = 'hopcsharp: enum definitions' })
+```
+
## API
This plugin exposes only a small set of functions, allowing you to build various interfaces and workflows on top of them.
@@ -91,56 +116,25 @@ Opens read-only buffer with type hierarchy.
require('hopcsharp').get_db()
```
-Returns opened _[sqlite_db](https://github.com/kkharji/sqlite.lua/blob/50092d60feb242602d7578398c6eb53b4a8ffe7b/doc/sqlite.txt#L76)_ object, you can create custom flows querying it with SQL queries from lua. See customization
-
-## Example customizations
+Returns opened _[sqlite_db](https://github.com/kkharji/sqlite.lua/blob/50092d60feb242602d7578398c6eb53b4a8ffe7b/doc/sqlite.txt#L76)_ object, you can create custom flows querying it with SQL queries from lua. See `:h hopcsharp.get_db` for more details.
-[Here](https://github.com/leblocks/dotfiles/blob/master/packages/neovim/config/lua/plugins/hopcsharp.lua) (this is my
-configuration that I use day to day) you can take a look at example configuration based on _get_db()_ method and _[fzf-lua](https://github.com/ibhagwan/fzf-lua)_,
-here is demo usage of it on a [net framework reference source](https://github.com/microsoft/referencesource) repository
+## FZF Pickers
-
-
-
+hopcsharp ships with built-in [fzf-lua](https://github.com/ibhagwan/fzf-lua) pickers for browsing definitions and source files. Requires the `fzf-lua` plugin to be installed.
-Create repository _.cs_ files fzf-lua picker that were previously stored in a db:
+All pickers are available via `require('hopcsharp.pickers.fzf')`:
-
-
-
+| Picker | Description |
+|---|---|
+| `source_files` | Browse all `.cs` source files in the database |
+| `all_definitions` | Browse all definitions |
+| `class_definitions` | Browse class definitions |
+| `interface_definitions` | Browse interface definitions |
+| `method_definitions` | Browse method definitions |
+| `struct_definitions` | Browse struct definitions |
+| `enum_definitions` | Browse enum definitions |
+| `record_definitions` | Browse record definitions |
+| `attribute_definitions` | Browse attribute definitions |
-```lua
-local list_files = function()
- -- get database (connection is always opened)
- fzf_lua.fzf_exec(function(fzf_cb)
- coroutine.wrap(function()
- local db = hopcsharp.get_db()
- local co = coroutine.running()
- local items = db:eval([[ SELECT path FROM files ]])
-
- if type(items) ~= 'table' then
- items = {}
- end
-
- for _, entry in pairs(items) do
- fzf_cb(entry.path, function() coroutine.resume(co) end)
- coroutine.yield()
- end
- fzf_cb()
- end)()
- end, {
- actions = {
- ["enter"] = actions.file_edit_or_qf,
- ["ctrl-s"] = actions.file_split,
- ["ctrl-v"] = actions.file_vsplit,
- ["ctrl-t"] = actions.file_tabedit,
- ["alt-q"] = actions.file_sel_to_qf,
- ["alt-Q"] = actions.file_sel_to_ll,
- ["alt-i"] = actions.toggle_ignore,
- ["alt-h"] = actions.toggle_hidden,
- ["alt-f"] = actions.toggle_follow,
- }
- })
-end
-```
+See `:h hopcsharp-fzf-pickers` for more details.
diff --git a/doc/hopcsharp.txt b/doc/hopcsharp.txt
index 32d33b9..9e1de19 100644
--- a/doc/hopcsharp.txt
+++ b/doc/hopcsharp.txt
@@ -1,5 +1,5 @@
==============================================================================
-INTRODUCTION *hopcsharp.txt
+INTRODUCTION *hopcsharp.txt*
Author: a.f.gurevich@gmail.com
@@ -14,9 +14,10 @@ CONTENTS *hopcsharp-contents*
3. Installation .............. |hopcsharp-installation|
4. Configuration ............. |hopcsharp-configuration|
5. API ....................... |hopcsharp-api|
- 6. Commands .................. |hopcsharp-commands|
- 7 Schema .................... |hopcsharp-database|
- 8. Troubleshooting ........... |hopcsharp-troubleshooting|
+ 6. FZF Pickers ............... |hopcsharp-fzf-pickers|
+ 7. Commands .................. |hopcsharp-commands|
+ 8. Schema .................... |hopcsharp-database|
+ 9. Troubleshooting ........... |hopcsharp-troubleshooting|
==============================================================================
@@ -232,6 +233,112 @@ Example: >
]], { name = 'MyClassName' })
<
+==============================================================================
+FZF PICKERS *hopcsharp-fzf-pickers*
+
+hopcsharp.nvim provides built-in fzf-lua pickers for navigating definitions
+and source files. These require the |fzf-lua| plugin to be installed.
+https://github.com/ibhagwan/fzf-lua
+
+All pickers support the following keybindings:
+- `enter` - open file
+- `ctrl-s` - open in horizontal split
+- `ctrl-v` - open in vertical split
+- `ctrl-t` - open in new tab
+- `alt-q` - send selection to quickfix list
+
+
+------------------------------------------------------------------------------
+ *hopcsharp.pickers.fzf.source_files*
+hopcsharp.pickers.fzf.source_files()
+
+Opens fzf-lua picker listing all `.cs` source files stored in the database.
+
+Example: >
+ require('hopcsharp.pickers.fzf').source_files()
+<
+
+------------------------------------------------------------------------------
+ *hopcsharp.pickers.fzf.all_definitions*
+hopcsharp.pickers.fzf.all_definitions()
+
+Opens fzf-lua picker listing all definitions (classes, interfaces, methods,
+structs, enums, records, and attributes).
+
+Example: >
+ require('hopcsharp.pickers.fzf').all_definitions()
+<
+
+------------------------------------------------------------------------------
+ *hopcsharp.pickers.fzf.class_definitions*
+hopcsharp.pickers.fzf.class_definitions()
+
+Opens fzf-lua picker listing class definitions.
+
+Example: >
+ require('hopcsharp.pickers.fzf').class_definitions()
+<
+
+------------------------------------------------------------------------------
+ *hopcsharp.pickers.fzf.interface_definitions*
+hopcsharp.pickers.fzf.interface_definitions()
+
+Opens fzf-lua picker listing interface definitions.
+
+Example: >
+ require('hopcsharp.pickers.fzf').interface_definitions()
+<
+
+------------------------------------------------------------------------------
+ *hopcsharp.pickers.fzf.method_definitions*
+hopcsharp.pickers.fzf.method_definitions()
+
+Opens fzf-lua picker listing method definitions.
+
+Example: >
+ require('hopcsharp.pickers.fzf').method_definitions()
+<
+
+------------------------------------------------------------------------------
+ *hopcsharp.pickers.fzf.struct_definitions*
+hopcsharp.pickers.fzf.struct_definitions()
+
+Opens fzf-lua picker listing struct definitions.
+
+Example: >
+ require('hopcsharp.pickers.fzf').struct_definitions()
+<
+
+------------------------------------------------------------------------------
+ *hopcsharp.pickers.fzf.enum_definitions*
+hopcsharp.pickers.fzf.enum_definitions()
+
+Opens fzf-lua picker listing enum definitions.
+
+Example: >
+ require('hopcsharp.pickers.fzf').enum_definitions()
+<
+
+------------------------------------------------------------------------------
+ *hopcsharp.pickers.fzf.record_definitions*
+hopcsharp.pickers.fzf.record_definitions()
+
+Opens fzf-lua picker listing record definitions.
+
+Example: >
+ require('hopcsharp.pickers.fzf').record_definitions()
+<
+
+------------------------------------------------------------------------------
+ *hopcsharp.pickers.fzf.attribute_definitions*
+hopcsharp.pickers.fzf.attribute_definitions()
+
+Opens fzf-lua picker listing attribute definitions.
+
+Example: >
+ require('hopcsharp.pickers.fzf').attribute_definitions()
+<
+
==============================================================================
DATABASE SCHEMA *hopcsharp-database*
diff --git a/lua/hopcsharp/health.lua b/lua/hopcsharp/health.lua
index 26be2a2..e4ac117 100644
--- a/lua/hopcsharp/health.lua
+++ b/lua/hopcsharp/health.lua
@@ -42,10 +42,21 @@ local function check_treesitter_c_sharp_grammar_installation()
end
end
+local function check_fzf_lua_optional()
+ vim.health.start('fzf-lua [optional]')
+ local ok, _ = pcall(require, 'fzf-lua')
+ if ok then
+ vim.health.ok('fzf-lua is installed')
+ else
+ vim.health.error('fzf-lua is not installed')
+ end
+end
+
M.check = function()
check_fd()
check_sqlite_installation()
check_treesitter_c_sharp_grammar_installation()
+ check_fzf_lua_optional()
end
return M
diff --git a/lua/hopcsharp/hop/init.lua b/lua/hopcsharp/hop/init.lua
index 82882f5..623d78f 100644
--- a/lua/hopcsharp/hop/init.lua
+++ b/lua/hopcsharp/hop/init.lua
@@ -1,4 +1,3 @@
-local utils = require('hopcsharp.utils')
local hop_utils = require('hopcsharp.hop.utils')
local dbutils = require('hopcsharp.database.utils')
@@ -8,42 +7,6 @@ local implementation_providers = require('hopcsharp.hop.providers.implementation
local M = {}
-local stop_callback = nil
-
-local function populate_quickfix(entries, jump_on_quickfix, type_converter)
- -- stop previous quickfix population
- -- won't work 100% but it much better
- -- rathen that nothing
- if stop_callback then
- stop_callback()
- stop_callback = nil
- end
-
- -- remove previous quickfix entries
- vim.fn.setqflist({}, 'r')
-
- utils.__scheduled_iteration(entries, function(i, item, _, stop)
- if i == 1 then
- stop_callback = stop
- end
-
- vim.fn.setqflist({
- {
- filename = item.path,
- lnum = item.row + 1,
- col = item.col,
- text = string.format('%-15s | %s', type_converter(item.type), item.namespace or ''),
- },
- }, 'a')
- end)
-
- vim.cmd([[ :copen ]])
-
- if jump_on_quickfix then
- vim.cmd([[ :cc! ]])
- end
-end
-
local function filter_entry_under_cursor(entries)
local filtered_entries = {}
local current_line = vim.fn.getcurpos()[2] -- 2 for line number
@@ -98,9 +61,8 @@ M.__hop_to = function(hop_providers, config)
-- sent to quickfix if there is too much
if #filtered_items > 1 then
- -- TODO cover this in test
local converter = type_converter or dbutils.get_type_name
- populate_quickfix(filtered_items, jump_on_quickfix, converter)
+ hop_utils.__populate_quickfix(filtered_items, jump_on_quickfix, converter)
end
return
diff --git a/lua/hopcsharp/hop/utils.lua b/lua/hopcsharp/hop/utils.lua
index 0414def..31bbd4e 100644
--- a/lua/hopcsharp/hop/utils.lua
+++ b/lua/hopcsharp/hop/utils.lua
@@ -1,5 +1,9 @@
+local utils = require('hopcsharp.utils')
+
local M = {}
+local stop_callback = nil
+
M.__open_buffer = function(path, exists_callback, not_exists_callback)
local buffers = vim.api.nvim_list_bufs()
-- check if the file is already open in any buffer
@@ -54,4 +58,38 @@ M.__thop = function(path, row, column)
vim.fn.setcursorcharpos(row, column + 1)
end
+M.__populate_quickfix = function(entries, jump_on_quickfix, type_converter)
+ -- stop previous quickfix population
+ -- won't work 100% but it much better
+ -- rathen that nothing
+ if stop_callback then
+ stop_callback()
+ stop_callback = nil
+ end
+
+ -- remove previous quickfix entries
+ vim.fn.setqflist({}, 'r')
+
+ utils.__scheduled_iteration(entries, function(i, item, _, stop)
+ if i == 1 then
+ stop_callback = stop
+ end
+
+ vim.fn.setqflist({
+ {
+ filename = item.path,
+ lnum = item.row + 1,
+ col = item.col,
+ text = string.format('%-15s | %s', type_converter(item.type), item.namespace or ''),
+ },
+ }, 'a')
+ end)
+
+ vim.cmd([[ :copen ]])
+
+ if jump_on_quickfix then
+ vim.cmd([[ :cc! ]])
+ end
+end
+
return M
diff --git a/lua/hopcsharp/pickers/fzf/file.lua b/lua/hopcsharp/pickers/fzf/file.lua
new file mode 100644
index 0000000..f508109
--- /dev/null
+++ b/lua/hopcsharp/pickers/fzf/file.lua
@@ -0,0 +1,42 @@
+local hopcsharp = require('hopcsharp')
+
+local M = {}
+
+M.__source_files = function(fzf)
+ return function()
+ fzf.fzf_exec(function(fzf_cb)
+ coroutine.wrap(function()
+ local db = hopcsharp.get_db()
+ local co = coroutine.running()
+ local items = db:eval([[ SELECT path FROM files ]])
+
+ if type(items) ~= 'table' then
+ items = {}
+ end
+
+ for _, entry in pairs(items) do
+ fzf_cb(entry.path, function()
+ coroutine.resume(co)
+ end)
+ coroutine.yield()
+ end
+ fzf_cb()
+ end)()
+ end, {
+ actions = {
+ ['enter'] = fzf.actions.file_edit_or_qf,
+ ['ctrl-s'] = fzf.actions.file_split,
+ ['ctrl-v'] = fzf.actions.file_vsplit,
+ ['ctrl-t'] = fzf.actions.file_tabedit,
+ ['alt-q'] = fzf.actions.file_sel_to_qf,
+ ['alt-Q'] = fzf.actions.file_sel_to_ll,
+ ['alt-i'] = fzf.actions.toggle_ignore,
+ ['alt-h'] = fzf.actions.toggle_hidden,
+ ['alt-f'] = fzf.actions.toggle_follow,
+ },
+ previewer = 'builtin',
+ })
+ end
+end
+
+return M
diff --git a/lua/hopcsharp/pickers/fzf/init.lua b/lua/hopcsharp/pickers/fzf/init.lua
new file mode 100644
index 0000000..401c80a
--- /dev/null
+++ b/lua/hopcsharp/pickers/fzf/init.lua
@@ -0,0 +1,51 @@
+local ok, _ = pcall(require, 'fzf-lua')
+if not ok then
+ error("hopcsharp.pickers.fzf was required but 'fzf-lua' plugin was not found")
+end
+
+local fzf = require('fzf-lua')
+local builtin = require('fzf-lua.previewer.builtin')
+local hopcsharp = require('hopcsharp')
+local file = require('hopcsharp.pickers.fzf.file')
+local utils = require('hopcsharp.pickers.fzf.utils')
+local db_query = require('hopcsharp.database.query')
+local db_utils = require('hopcsharp.database.utils')
+
+local M = {}
+
+local get_items_by_type = function(type)
+ local db = hopcsharp.get_db()
+ return function()
+ return db:eval(db_query.get_definition_by_type, { type = type })
+ end
+end
+
+local get_items_by_type_picker = function(item_type)
+ return utils.__get_picker(fzf, builtin, get_items_by_type(item_type), utils.__format_name_and_namespace)
+end
+
+M.source_files = file.__source_files(fzf)
+
+M.all_definitions = utils.__get_picker(fzf, builtin, function()
+ local db = hopcsharp.get_db()
+ return db:eval(db_query.get_all_definitions)
+end, utils.__format_name_and_namespace)
+
+M.class_definitions = get_items_by_type_picker(db_utils.types.CLASS)
+
+M.interface_definitions = get_items_by_type_picker(db_utils.types.INTERFACE)
+
+M.method_definitions = get_items_by_type_picker(db_utils.types.METHOD)
+
+M.struct_definitions = get_items_by_type_picker(db_utils.types.STRUCT)
+
+M.enum_definitions = get_items_by_type_picker(db_utils.types.ENUM)
+
+M.record_definitions = get_items_by_type_picker(db_utils.types.RECORD)
+
+M.attribute_definitions = utils.__get_picker(fzf, builtin, function()
+ local db = hopcsharp.get_db()
+ return db:eval(db_query.get_attributes)
+end, utils.__format_name_and_namespace)
+
+return M
diff --git a/lua/hopcsharp/pickers/fzf/utils.lua b/lua/hopcsharp/pickers/fzf/utils.lua
new file mode 100644
index 0000000..c04a67a
--- /dev/null
+++ b/lua/hopcsharp/pickers/fzf/utils.lua
@@ -0,0 +1,122 @@
+local hop_utils = require('hopcsharp.hop.utils')
+local db_utils = require('hopcsharp.database.utils')
+
+local M = {}
+
+local function parse_entry(entry, items)
+ local id = nil
+
+ -- lookup id of the item in items
+ for part in string.gmatch(entry, '%[(%d+)%]') do
+ id = tonumber(part)
+ end
+
+ local item = items[id]
+
+ return item.path, item.row, item.column, item.type, item.namespace
+end
+
+M.__format_entry_name_type_namespace = function(i, entry)
+ local type_name = db_utils.get_type_name(entry.type)
+ return string.format('%-50s %-20s %-30s [%s]', entry.name, type_name, entry.namespace, i)
+end
+
+M.__format_name_and_namespace = function(i, entry)
+ return string.format('%-70s %-30s [%s]', entry.name, entry.namespace, i)
+end
+
+M.__get_picker = function(fzf, builtin_previewer, items_provider, formatter)
+ -- store items in a closure
+ -- so after db call and render
+ -- we can retrieve info from here
+ local items = {}
+
+ -- see example here https://github.com/ibhagwan/fzf-lua/wiki/Advanced#preview-nvim-builtin
+ local custom_previewer = builtin_previewer.buffer_or_file:extend()
+
+ function custom_previewer:new(o, opts, fzf_win)
+ custom_previewer.super.new(self, o, opts, fzf_win)
+ setmetatable(self, custom_previewer)
+ return self
+ end
+
+ function custom_previewer:parse_entry(entry_str)
+ local path, line, col = parse_entry(entry_str, items)
+ return { path = path, line = line + 1, col = col + 1 }
+ end
+
+ local picker = function()
+ -- get database (connection is always opened)
+ fzf.fzf_exec(function(fzf_cb)
+ coroutine.wrap(function()
+ local co = coroutine.running()
+ items = items_provider()
+
+ if type(items) ~= 'table' then
+ items = {}
+ end
+
+ for i, entry in ipairs(items) do
+ fzf_cb(formatter(i, entry), function()
+ coroutine.resume(co)
+ end)
+ coroutine.yield()
+ end
+ fzf_cb()
+ end)()
+ end, {
+ actions = {
+ -- on select hop to definition by path row and column
+ ['default'] = function(selected)
+ local path, row, column = parse_entry(selected[1], items)
+ -- fixing row by + 1 because __hop internally fixies column already
+ -- TODO do those fixes in a single place
+ hop_utils.__hop(path, row + 1, column)
+ end,
+
+ ['ctrl-v'] = function(selected)
+ local path, row, column = parse_entry(selected[1], items)
+ hop_utils.__vhop(path, row + 1, column)
+ end,
+
+ ['ctrl-s'] = function(selected)
+ local path, row, column = parse_entry(selected[1], items)
+ hop_utils.__shop(path, row + 1, column)
+ end,
+
+ ['ctrl-t'] = function(selected)
+ local path, row, column = parse_entry(selected[1], items)
+ hop_utils.__thop(path, row + 1, column)
+ end,
+
+ ['alt-q'] = function(selected)
+ local quickfix_entries = {}
+ for _, selected_item in ipairs(selected) do
+ -- not fixing here row and column by + 1
+ -- because populate_quickfix already does that
+ local path, row, column, type, namespace = parse_entry(selected_item, items)
+ table.insert(quickfix_entries, {
+ path = path,
+ row = row,
+ column = column,
+ type = type,
+ namespace = namespace,
+ })
+ end
+
+ hop_utils.__populate_quickfix(quickfix_entries, true, db_utils.get_type_name)
+ end,
+ },
+
+ previewer = custom_previewer,
+
+ fzf_opts = {
+ ['--wrap'] = false,
+ ['--multi'] = true,
+ },
+ })
+ end
+ return picker
+end
+
+return M
diff --git a/test/hop/hop_to_spec.lua b/test/hop/hop_to_spec.lua
index 309d0c2..b125702 100644
--- a/test/hop/hop_to_spec.lua
+++ b/test/hop/hop_to_spec.lua
@@ -25,6 +25,37 @@ describe('hop_to', function()
assert(called_get_hops)
end)
+ it('__hop_to calls type_converter if providers returns it', function()
+ local called_can_handle = false
+ local called_get_hops = false
+ local called_type_provider = false
+
+ local provider = function(current_word, node)
+ return {
+ can_handle = function()
+ called_can_handle = true
+ return true
+ end,
+
+ get_hops = function()
+ called_get_hops = true
+ return {
+ { row = 10, column = 10, path = 'dummy1', name = 'dummy_name' },
+ { row = 11, column = 10, path = 'dummy2', name = 'dummy_name' },
+ }, function()
+ called_type_provider = true
+ end
+ end,
+ }
+ end
+
+ hop.__hop_to({ provider('test', nil) }, {})
+
+ assert(called_type_provider)
+ assert(called_can_handle)
+ assert(called_get_hops)
+ end)
+
it("__hop_to calls providers that can handle hop and won't call other providers", function()
local called_can_handle1 = false
local called_get_hops1 = false
diff --git a/test/hop/utils_spec.lua b/test/hop/utils_spec.lua
new file mode 100644
index 0000000..328437f
--- /dev/null
+++ b/test/hop/utils_spec.lua
@@ -0,0 +1,28 @@
+local hop_utils = require('hopcsharp.hop.utils')
+
+describe('hop_utils', function()
+ it('__populate_quickfix calls type converter', function()
+ local type_converter_called = false
+
+ local type_converter = function()
+ type_converter_called = true
+ end
+
+ local entries = {
+ { path = 'testpath1', row = 1, col = 1, type = 42, namespace = 'namespace1' },
+ { path = 'testpath2', row = 1, col = 1, type = 42, namespace = 'namespace2' },
+ { path = 'testpath3', row = 1, col = 1, type = 42, namespace = 'namespace3' },
+ { path = 'testpath4', row = 1, col = 1, type = 42, namespace = 'namespace4' },
+ }
+
+ -- check that qf is empty
+ assert(#vim.fn.getqflist() == 0)
+
+ -- this one runs via vim.schedule
+ -- there is no safe way to assume that it (that I'm aware of)
+ -- finished something
+ hop_utils.__populate_quickfix(entries, false, type_converter)
+
+ assert(type_converter_called)
+ end)
+end)