mrcjkb / rustaceanvim

Supercharge your Rust experience in Neovim! A heavily modified fork of rust-tools.nvim
GNU General Public License v2.0
1.27k stars 47 forks source link

Two ra instances attach to the same buffer after switch session with nvim-project #275

Closed xzbdmw closed 3 months ago

xzbdmw commented 4 months ago

Neovim version (nvim -v)

0.10

Operating system/version

macos 14.2

Output of :checkhealth rustaceanvim

==============================================================================
rustaceanvim: require("rustaceanvim.health").check()

Checking for Lua dependencies ~
- WARNING dap not installed. Needed for debugging features [mfussenegger/nvim-dap](https://github.com/mfussenegger/nvim-dap)

Checking external dependencies ~
- OK rust-analyzer: found rust-analyzer 1.76.0 (07dca489 2024-02-04)
- OK Cargo: found cargo 1.76.0 (c84b36747 2024-01-18)
- OK rustc: found rustc 1.76.0 (07dca489a 2024-02-04)
- OK debug adapter: found codelldb 

Checking config ~
- OK No errors found in config.

Checking for conflicting plugins ~
- OK No conflicting plugins detected.

Checking for tree-sitter parser ~
- OK tree-sitter parser for Rust detected.

How to reproduce the issue

init.lua

local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
if not vim.loop.fs_stat(lazypath) then
    vim.fn.system({
        "git",
        "clone",
        "--filter=blob:none",
        "https://github.com/folke/lazy.nvim.git",
        "--branch=stable", -- latest stable release
        lazypath,
    })
end
vim.opt.rtp:prepend(lazypath)

-- Options are automatically loaded before lazy.nvim startup
-- Default options that are always set: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/config/options.lua
-- Add any additional options here

-- Options are automatically loaded before lazy.nvim startup
-- Default options that are always set: https://github.com/LazyVim/LazyVim/blob/main/lua/lazyvim/config/options.lua
-- Add any additional options here
vim.g.loaded_netrw = 1
vim.g.loaded_netrwPlugin = 1
vim.g.neovide_unlink_border_highlights = false
vim.opt.relativenumber = false

-- vim.opt.number = false
vim.g.neovide_no_idle = true
vim.opt.shiftwidth = 4
vim.opt.tabstop = 4
vim.opt.jumpoptions = "stack"
vim.cmd("set nolist")
-- vim.o.guifont = "mcv sans mono,Symbols Nerd Font:h20"
-- vim.o.guifont = "JetBrains Mono light,Symbols Nerd Font:h19"
-- vim.o.guifont = "JetBrains Mono freeze freeze,Symbols Nerd Font:h20:#e-subpixelantialias:#h-none"
-- vim.o.guifont = "JetBrains Mono freeze freeze,Symbols Nerd Font:h20:#e-antialias:#h-normal"
-- vim.o.guifont = "hack,Symbols Nerd Font:h20:#e-subpixelantialias:#h-full"
-- vim.o.guifont = "JetBrains Mono freeze freeze,Symbols Nerd Font:h20"
vim.opt.linespace = 5
vim.opt.guicursor = "n-sm-ve:block,i-c-ci:ver22,r-cr-v-o:hor7"
vim.opt.swapfile = false
vim.g.neovide_transparency = 1
vim.opt.laststatus = 0
vim.opt.linebreak = true

vim.api.nvim_set_hl(0, "Statusline", { link = "Normal" })
vim.api.nvim_set_hl(0, "StatuslineNC", { link = "Normal" })

-- vim.opt.statusline = str
vim.g.neovide_remember_window_size = true
vim.g.neovide_input_macos_alt_is_meta = true
vim.g.neovide_refresh_rate = 120
vim.g.neovide_padding_top = 0
vim.g.neovide_padding_bottom = 0
vim.g.neovide_padding_right = 0
vim.g.neovide_underline_stroke_scale = 1.0
vim.g.neovide_padding_left = 0
vim.o.scrolloff = 6
vim.g.neovide_floating_shadow = false
-- vim.opt.whichwrap = "j,k"
vim.g.neovide_floating_z_height = 0
-- vim.o.showtabline = 0
vim.g.neovide_light_angle_degrees = 0
vim.g.neovide_light_radius = 0
vim.g.neovide_cursor_trail_size = 0
vim.g.neovide_cursor_animate_command_line = true
vim.g.neovide_touch_deadzone = 0
vim.g.neovide_scroll_animation_far_lines = 0
vim.g.neovide_scroll_animation_length = 0
vim.g.neovide_hide_mouse_when_typing = true
vim.g.rustaceanvim = {
    server = {
        settings = {
            -- rust-analyzer language server configuration
            ["rust-analyzer"] = {
                completion = {
                    fullFunctionSignatures = {
                        enable = true,
                    },
                    privateEditable = {
                        enable = true,
                    },
                },
                inlayHints = {
                    parameterHints = false,
                    closureReturnTypeHints = "with_block",
                },
                workspace = {
                    symbol = {
                        search = {
                            -- scope = "workspace_and_dependencies",
                            -- scope = "workspace",
                        },
                    },
                },
            },
        },
    },
    tools = {
        hover_actions = {
            replace_builtin_hover = true,
        },
        float_win_config = {
            border = "none",
            max_width = 70,
            max_height = 15,
            auto_focus = false,
        },
    },
}

require("lazy").setup({
    { "nvim-lua/plenary.nvim" },
    {
        "coffebar/neovim-project",
        -- enabled = false,
        opts = {
            last_session_on_startup = true,
            projects = { -- define project roots
                "~/Project/rust/*",
                "~/Project/Go/*",
                "~/.config/*",
            },
            session_manager_opts = {
                sessions_dir = "/Users/xzb/.local/share/nvimtest/sessiontest", -- The directory where the session files will be saved.
                session_filename_to_dir = session_filename_to_dir, -- Function that replaces symbols into separators and colons to transform filename into a session directory.
                dir_to_session_filename = dir_to_session_filename, -- Function that replaces separators and colons into special symbols to transform session directory into a filename. Should use `vim.loop.cwd()` if the passed `dir` is `nil`.
                -- autoload_mode = config.AutoloadMode.LastSession, -- Define what to do when Neovim is started without arguments. Possible values: Disabled, CurrentDir, LastSession
                autosave_last_session = true, -- Automatically save last session on exit and on session switch.
                autosave_ignore_not_normal = true, -- Plugin will not save a session when no buffers are opened, or all of them aren't writable or listed.
                autosave_ignore_dirs = {}, -- A list of directories where the session will not be autosaved.
                autosave_ignore_filetypes = { -- All buffers of these file types will be closed before the session is saved.
                    "gitcommit",
                    "gitrebase",
                },
                autosave_ignore_buftypes = {}, -- All buffers of these bufer types will be closed before the session is saved.
                autosave_only_in_session = false, -- Always autosaves session. If true, only autosaves after a session is active.
                max_path_length = 80, -- Shorten the display path if length exceeds this threshold. Use 0 if don't want to shorten the path at all.
            },
        },
        init = function()
            -- enable saving the state of plugins in the session
            vim.opt.sessionoptions:append("globals") -- save global variables that start with an uppercase letter and contain at least one lowercase letter.
        end,

        dependencies = {
            { "Shatur/neovim-session-manager" },
            { "nvim-telescope/telescope.nvim" },
            { "nvim-lua/plenary.nvim" },
        },
        lazy = false,
        priority = 100,
    },
    { "nvim-lua/plenary.nvim" },

    {
        "mrcjkb/rustaceanvim",
        -- version = "^3", -- Recommended
        ft = { "rust" },
    },
})

reproduce:

  1. set coffebar/neovim-project's projects option to the path that contains rust projects
  2. run :Telescope neovim-project discover select one rust project
  3. run above command again to select another rust project
  4. quit neovim
  5. start neovim, session will auto load last one
  6. run :Telescope neovim-project history to switch to another project
  7. code diagnose is doubled, showing there two ra instance runing before commit "a23ca1bd8fba6017f8c229a9db95ae8454fdf20b", there are no problem, I'm not sure which commit cause this.

Expected behaviour

one ra per project

Actual behaviour

two ra

The minimal config used to reproduce this issue.

see above
mrcjkb commented 4 months ago

Hey 👋

Thanks for reporting. The config you posted contains a lot that is irrelevant for reproducing the behaviour. Could you please try to reproduce this starting from the minimal config provided in the readme's troubleshooting section (without any other plugins or settings), adding plugins and settings gradually until you can reproduce it? 🙏

xzbdmw commented 4 months ago

The config just contains the project manage plugin(it depends on neovim-session-manager and telescope) and rustaceanvim, you can ignore those option settings( I copy paste it ), neovim-projet.nvim is a wrapper around neovim-session-manager and telescope is just used for change project. these are four basic plugins to reproduce it.

xzbdmw commented 4 months ago

you can try

local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
if not vim.loop.fs_stat(lazypath) then
    vim.fn.system({
        "git",
        "clone",
        "--filter=blob:none",
        "https://github.com/folke/lazy.nvim.git",
        "--branch=stable", -- latest stable release
        lazypath,
    })
end
vim.opt.rtp:prepend(lazypath)
require("lazy").setup({
    { "nvim-lua/plenary.nvim" },
    {
        "coffebar/neovim-project",
        -- enabled = false,
        opts = {
            last_session_on_startup = true,
            projects = { -- define project roots
                "~/Project/rust/*",
                "~/Project/Go/*",
                "~/.config/*",
            },
            session_manager_opts = {
                sessions_dir = "/Users/xzb/.local/share/nvimtest/sessiontest", -- The directory where the session files will be saved.
                session_filename_to_dir = session_filename_to_dir, -- Function that replaces symbols into separators and colons to transform filename into a session directory.
                dir_to_session_filename = dir_to_session_filename, -- Function that replaces separators and colons into special symbols to transform session directory into a filename. Should use `vim.loop.cwd()` if the passed `dir` is `nil`.
                -- autoload_mode = config.AutoloadMode.LastSession, -- Define what to do when Neovim is started without arguments. Possible values: Disabled, CurrentDir, LastSession
                autosave_last_session = true, -- Automatically save last session on exit and on session switch.
                autosave_ignore_not_normal = true, -- Plugin will not save a session when no buffers are opened, or all of them aren't writable or listed.
                autosave_ignore_dirs = {}, -- A list of directories where the session will not be autosaved.
                autosave_ignore_filetypes = { -- All buffers of these file types will be closed before the session is saved.
                    "gitcommit",
                    "gitrebase",
                },
                autosave_ignore_buftypes = {}, -- All buffers of these bufer types will be closed before the session is saved.
                autosave_only_in_session = false, -- Always autosaves session. If true, only autosaves after a session is active.
                max_path_length = 80, -- Shorten the display path if length exceeds this threshold. Use 0 if don't want to shorten the path at all.
            },
        },
        init = function()
            -- enable saving the state of plugins in the session
            vim.opt.sessionoptions:append("globals") -- save global variables that start with an uppercase letter and contain at least one lowercase letter.
        end,

        dependencies = {
            { "Shatur/neovim-session-manager" },
            { "nvim-telescope/telescope.nvim" },
            { "nvim-lua/plenary.nvim" },
        },
        lazy = false,
        priority = 100,
    },
    { "nvim-lua/plenary.nvim" },

    {
        "mrcjkb/rustaceanvim",
        -- version = "^3", -- Recommended
        ft = { "rust" },
    },
})
mrcjkb commented 4 months ago

The config just contains the project manage plugin(it depends on neovim-session-manager and telescope) and rustaceanvim, you can ignore those option settings( I copy paste it ), neovim-projet.nvim is a wrapper around neovim-session-manager and telescope is just used for change project. these are four basic plugins to reproduce it.

I know what each of the plugins do. Let me clarify:

I maintain this plugin in my free time, and do not have the capacity to account for non-standard behaviour that other plugins might be adding to neovim - especially if I don't use those plugins myself (there are a lot of neovim plugins out there and I have a lot of people asking for help with various problems, often related to other plugins).

That's why I provide a minimal config and instructions to try to reproduce the behaviour. First without any other plugins, and then to add plugins you suspect could be causing the behaviour one by one, so that you can identify which plugin (or which configuration) is the cause.

If you suspect this behaviour is caused by neovim-project, and neovim-project is a wrapper around neovim-session-manager, the steps to identify the culprit could be as follows:

  1. Use the minimal config with only rustaceanvim. Can the behaviour be reproduced? E.g. by opening a rust file from another project using :e ../path/to/other/project/file.rs
  2. If no, add neovim-session-manager (without neovim-project, and without Telescope, etc.). Can the behaviour be reproduced?
  3. If no, add neovim-project (without any opts and without Telescope). Can the behaviour be reproduced?
  4. If not, add opts (one by one, not all at once).
  5. And so on...

Furthermore, in your specific case, you provided this:

projects = { -- define project roots
                "~/Project/rust/*",
                "~/Project/Go/*",
                "~/.config/*",
},

I do not have a "Project/rust" or "Project/go" in my home directory. And I don't know which kinds of projects you have in those directories. To be able to understand how to reproduce this on my device, I would have to read through the neovim-project and neovim-session-manager plugins' documentations, and also make (possibly wrong) assumptions about your projects. That's why I ask for precise steps to reproduce.

For example:

mkdir -p /tmp/rust
cd /tmp/rust
cargo new foo
cargo new bar
cd foo
nvim
... etc

Once you have a minimal reproducible config, I am more than happy to invest time in finding a fix or helping to identify a bug in another plugin. But I do not have the capacity to determine which plugin is making rustaceanvim behave this way for you.

xzbdmw commented 4 months ago

I can't reproduce it using neovim-session-manager alone. and this commit https://github.com/mrcjkb/rustaceanvim/commit/5fb048d9a59872547f9ed94b964cf4b35ed6c2fc breaks neovim-project

local lazypath = vim.fn.stdpath("data") .. "/lazy/lazy.nvim"
if not vim.loop.fs_stat(lazypath) then
    vim.fn.system({
        "git",
        "clone",
        "--filter=blob:none",
        "https://github.com/folke/lazy.nvim.git",
        "--branch=stable", -- latest stable release
        lazypath,
    })
end
vim.opt.rtp:prepend(lazypath)
require("lazy").setup({
    {
        "coffebar/neovim-project",
        -- enabled = false,
        opts = {
            last_session_on_startup = true,
            projects = { -- define project roots
            "~/testsession/*",

            },
        },
        init = function()
            -- enable saving the state of plugins in the session
            vim.opt.sessionoptions:append("globals") -- save global variables that start with an uppercase letter and contain at least one lowercase letter.
        end,

        dependencies = {
            { "Shatur/neovim-session-manager" },
            { "nvim-telescope/telescope.nvim" },
            { "nvim-lua/plenary.nvim" },
        },
        lazy = false,
        priority = 100,
    },
    { "nvim-lua/plenary.nvim" },

    {
        "mrcjkb/rustaceanvim",
        -- version = "^3", -- Recommended
        ft = { "rust" },
    },
})

the detail reproduce steps:

  1. mkdir ~/testsession
  2. cd ~/testsession
  3. cargo new foo
  4. cargo new bar
  5. start nvim
  6. run :Telescope neovim-project discover select foo and open a rust file(:Telescope find_files select main.rs) see lsp works
  7. run above command again to select bar and open a rust file see lsp works
  8. quit neovim
  9. run nvim, session will auto load last one(bar) and make sure lsp works
  10. run :Telescope neovim-project history to switch to another project(foo)
  11. code diagnose is doubled, showing there two ra instance runing
mrcjkb commented 4 months ago

Thanks :pray:

I wasn't able to reproduce the issue with the config and steps you posted. :lua =#vim.lsp.buf_get_clients() outputs 1, showing that there is only one client attached.

Did you run Neovim as described in the README, to ensure there are no other configs or plugins polluting the environment?

mkdir -p /tmp/minimal/
NVIM_DATA_MINIMAL="/tmp/minimal" NVIM_APP_NAME="nvim-minimal" nvim -u NORC -u minimal.lua

This commit in neovim-project looks suspicious to me: https://github.com/coffebar/neovim-project/commit/68a31ba10d1071906ebc942838f008db800431c9

But it doesn't seem to be causing any problems on my end.

Commit https://github.com/mrcjkb/rustaceanvim/commit/5fb048d9a59872547f9ed94b964cf4b35ed6c2fc is a bug fix, and is the intended behaviour. vim.lsp.start won't attach a second LSP client if there is already one attached with the same workspace root.

xzbdmw commented 4 months ago

That's strange, I use the init.lua provided above

this is my version

rust-analyzer --version
rust-analyzer 1.76.0 (07dca489 2024-02-04)
xzbdmw commented 4 months ago

https://github.com/mrcjkb/rustaceanvim/assets/97848247/dea1d21a-5cf1-46a7-936f-3756ff4fd10e

A clean reproduce

mrcjkb commented 4 months ago

That's strange, I use the init.lua provided above

iShot_2024-03-08_01.26.47.mp4 this is my version

rust-analyzer --version
rust-analyzer 1.76.0 (07dca489 2024-02-04)

It looks like you're not using NVIM_DATA_MINIMAL or -u NORC -u minimal.lua (see the snippet in my previous comment). These are important to make sure you launch Neovim with a clean, repeatable environment that isn't polluted with configs that could be getting loaded without your knowledge.

xzbdmw commented 4 months ago

I will try

xzbdmw commented 4 months ago

Hello I can reproduce this using https://github.com/mrcjkb/rustaceanvim/blob/master/troubleshooting/minimal.lua, not sure what cause the difference😰

mrcjkb commented 4 months ago

Hello I can reproduce this using https://github.com/mrcjkb/rustaceanvim/blob/master/troubleshooting/minimal.lua, not sure what cause the difference😰

Wait, you can reproduce it without any other plugins now?

:thinking: maybe it's a neovim-nightly bug or a MacOS thing? Can you reproduce it with Neovim 0.9?

xzbdmw commented 4 months ago

0.9.5 have the same problem😇, luckily I can live before that commit.

mrcjkb commented 4 months ago

0.9.5 have the same problem😇, luckily I can live before that commit.

What are the steps to reproduce it without neovim-project? Perhaps I can try to reason about it and if not I'll add some logging that might help (I wanted to do that anyway) 😃

By the way, you could probably work around it with the vim.g.rustaceanvim.server.auto_attach option (see :h rustaceanvim.config) if I don't find a fix soon.

xzbdmw commented 4 months ago

Thanks 🙏

I wasn't able to reproduce the issue with the config and steps you posted. :lua =#vim.lsp.buf_get_clients() outputs 1, showing that there is only one client attached.

Did you run Neovim as described in the README, to ensure there are no other configs or plugins polluting the environment?

mkdir -p /tmp/minimal/
NVIM_DATA_MINIMAL="/tmp/minimal" NVIM_APP_NAME="nvim-minimal" nvim -u NORC -u minimal.lua

This commit in neovim-project looks suspicious to me: coffebar/neovim-project@68a31ba

But it doesn't seem to be causing any problems on my end.

Commit 5fb048d is a bug fix, and is the intended behaviour. vim.lsp.start won't attach a second LSP client if there is already one attached with the same workspace root.

yes before this commit in neovim-project there is no problem. So it is their issue though.

mrcjkb commented 4 months ago

Let's leave this issue open though. I think it's too early to rule out a bug in rustaceanvim.

xzbdmw commented 4 months ago

Because I can't reproduce using neovim-sessino-manager alone