leblocks/hopcsharp.nvim

github github
programming-languages-support
stars 9
issues 7
subscribers 1
forks 1
CREATED

UPDATED


hopcsharp.nvim

Cached treesitter navigation on a big projects, an attempt to make navigation in large c# projects better

Description

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.

How does it work?

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.

Requirements

  • sqlite.lua

    • windows may require you to download sqlite dll and additional configuration, take a look at installation instructions.
  • fd to be on PATH

  • c_sharp tree-sitter grammer installed

Installation

Using packer.nvim:

use({ 'leblocks/hopcsharp.nvim', requires = { { 'kkharji/sqlite.lua' } } })

API

This plugin exposes only a small set of functions, allowing you to build various interfaces and workflows on top of them.

init_database

require('hopcsharp').init_database()

This function launches the database initialization process in a separate headless Neovim instance to avoid blocking the current session.

hop_to_definition

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.

hop_to_implementation

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.

get_type_hierarchy

require('hopcsharp').get_type_hierarchy()

Opens read-only buffer with type hierarchy.

get_db

require('hopcsharp').get_db()

Returns opened sqlite_db object, you can create custom flows querying it with SQL queries from lua. See customization

Example customizations

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