Cached treesitter navigation on a big projects, an attempt to make navigation in large c# projects better
hopcsharp is a lightweight code navigation tool inspired by ctags, built for large C# projects. It uses 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.
This plugin is in its early stages expect lots of bugs :D, I hope that there will be people's interest and contributions as well. I'll try to improve it little by little.
hopcsharp parses code base with help of tree-sitter and stores data on type locations \ definitions in local sqlite database. This database provides data for navigation in code. It won't be as precise as LSP but it provides a fast way with pretty good precision for navigation in a codebase.
fd to be on PATH
c_sharp tree-sitter grammer installed
Using packer.nvim:
use({ 'leblocks/hopcsharp.nvim', requires = { { 'kkharji/sqlite.lua' } } })
This plugin exposes only a small set of functions, allowing you to build various interfaces and workflows on top of them.
require('hopcsharp').init_database()
This function launches the database initialization process in a separate headless Neovim instance to avoid blocking the current session.
require('hopcsharp').hop_to_definition(config)
Opens new buffer or switches to existing one on a line and column where definition is defined. If it finds more than
one definition it will add those to quickfix list and will open it. See :h hopcsharp.hop_to_definition for more details.
require('hopcsharp').hop_to_implementation(config)
Opens new buffer or switches to existing one on a line and column where implementation is defined. If it finds more than
one implementation it will add those to quickfix list and will open it. See :h hopcsharp.hop_to_definition for more details.
require('hopcsharp').get_type_hierarchy()
Opens read-only buffer with type hierarchy.
require('hopcsharp').get_db()
Returns opened sqlite_db object, you can create custom flows querying it with SQL queries from lua. See customization
Here (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, here is demo usage of it on a net framework reference source repository
Create repository .cs files fzf-lua picker that were previously stored in a db:
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