seblj / roslyn.nvim

Roslyn LSP plugin for neovim
MIT License
190 stars 21 forks source link

Performance issue when switching buffers #51

Closed joohing closed 1 month ago

joohing commented 1 month ago

When switching to a .cs buffer, I encounter half a second of lag. It is due to this autocmd that you create in init.lua:

    vim.api.nvim_create_autocmd({ "BufEnter" }, {
        group = vim.api.nvim_create_augroup("Roslyn", { clear = true }),
        pattern = "*.cs",
        callback = function(opt)
            if not valid_buffer(opt.buf) then
                return
            end

            local csproj_files = utils.try_get_csproj_files(opt.buf)
            if csproj_files then
                return start_with_projects(cmd, csproj_files, roslyn_config)
            end

            local sln_files = utils.get_solution_files(opt.buf)
            if sln_files and not vim.tbl_isempty(sln_files) then
                return start_with_solution(opt.buf, cmd, sln_files, roslyn_config, on_init_sln)
            end

            local csproj = utils.get_project_files(opt.buf)
            if csproj then
                return start_with_projects(cmd, csproj, roslyn_config)
            end

            -- Fallback to the selected solution if we don't find anything.
            -- This makes it work kind of like vscode for the decoded files
            if vim.g.roslyn_nvim_selected_solution then
                local sln_dir = vim.fs.root(opt.buf, vim.g.roslyn_nvim_selected_solution) --[[@as string]]
                return wrap_roslyn(cmd, sln_dir, roslyn_config, "sln", on_init_sln(vim.g.roslyn_nvim_selected_solution))
            end
        end,
    })

Which ends up calling logic which (without having looked at it too much) selects a solution and tells the server to start etc. Maybe this is not the cause of the issue and I'm stupid (not unlikely) but in that case, one of the functions must have a side effect that costs more time to run than anticipated.

I fixed it by moving the last paragraph up below the valid_buffer check, and now everything is fast as frick. Like this:

    vim.api.nvim_create_autocmd({ "BufEnter" }, {
        group = vim.api.nvim_create_augroup("Roslyn", { clear = true }),
        pattern = "*.cs",
        callback = function(opt)
            if not valid_buffer(opt.buf) then
                return
            end

            -- Fallback to the selected solution if we don't find anything.
            -- This makes it work kind of like vscode for the decoded files
            if vim.g.roslyn_nvim_selected_solution then
                local sln_dir = vim.fs.root(opt.buf, vim.g.roslyn_nvim_selected_solution) --[[@as string]]
                return wrap_roslyn(cmd, sln_dir, roslyn_config, "sln", on_init_sln(vim.g.roslyn_nvim_selected_solution))
            end

            local csproj_files = utils.try_get_csproj_files(opt.buf)
            if csproj_files then
                return start_with_projects(cmd, csproj_files, roslyn_config)
            end

            local sln_files = utils.get_solution_files(opt.buf)
            if sln_files and not vim.tbl_isempty(sln_files) then
                return start_with_solution(opt.buf, cmd, sln_files, roslyn_config, on_init_sln)
            end

            local csproj = utils.get_project_files(opt.buf)
            if csproj then
                return start_with_projects(cmd, csproj, roslyn_config)
            end
        end,
    })
seblj commented 1 month ago

Are you on the latest master? https://github.com/seblj/roslyn.nvim/issues/45

From the code you are not. Please update to the latest master before reporting issues😅

joohing commented 1 month ago

Yeah that was it - sorry for wasting your time!

seblj commented 1 month ago

No problem! I am wondering if I should make that the default behaviour even if it is a hack

joohing commented 1 month ago

It's a good question, I think there might be problems if the buffer is outside the solution though. Maybe it would be best to check if the selected solution contains the buffer first, and only if not, then try to find a csproj and so on.

    vim.api.nvim_create_autocmd({ "BufEnter" }, {
        group = vim.api.nvim_create_augroup("Roslyn", { clear = true }),
        pattern = "*.cs",
        callback = function(opt)
            -- If buffer in solution
            if vim.g.roslyn_nvim_selected_solution then
                if check_if_buffer_in_solution(whatever) then
                   .... start lsp.... 
                end
            end

            if not valid_buffer(opt.buf) then
                return
            end

            local csproj_files = utils.try_get_csproj_files()
            if csproj_files then
                return start_with_projects(cmd, opt.buf, csproj_files, roslyn_config)
            end

            local sln_files = utils.get_solution_files(opt.buf, roslyn_config.broad_search)
            if sln_files and not vim.tbl_isempty(sln_files) then
                return start_with_solution(opt.buf, cmd, sln_files, roslyn_config, on_init_sln)
            end

            local csproj = utils.get_project_files(opt.buf)
            if csproj then
                return start_with_projects(cmd, opt.buf, csproj, roslyn_config)
            end

            -- If buffer not in solution and also couldn't find any solution in the buffer's dir
            if vim.g.roslyn_nvim_selected_solution then
                local sln_dir = vim.fs.dirname(vim.g.roslyn_nvim_selected_solution)
                return lsp_start(cmd, opt.buf, sln_dir, roslyn_config, on_init_sln(vim.g.roslyn_nvim_selected_solution))
            end
        end,
    })
seblj commented 1 month ago

How could I check if the solution contains the buffer though? I looked into getting all files contained in a solution for something else, and I couldn't find any good way to do that

joohing commented 1 month ago

If "file is in the folder of the solution" implies "file is part of solution" (which I honestly don't know if it does), then my first thought would be

I don't even have a degree yet so I'm sorry if all that completely misses the mark 😄

seblj commented 1 month ago

Yeah maybe something like that + some extra checks could work, but I don't think that it is worth it🤷‍♂️ it seems pretty fast as it is now after I fixed the problems in the other issue