kawre / leetcode.nvim

A Neovim plugin enabling you to solve LeetCode problems.
MIT License
1.04k stars 44 forks source link

Rust_Analyzer doesn't provide LSP completion #86

Closed GustavoJCL closed 5 months ago

GustavoJCL commented 5 months ago

Hi, when I try to solve any problem using Rust the lsp completion doesn't work, there a capture of another project of rust: image but in leetcode.nvim it didn't work:

image

there the LspInfo of this problem, it seems the standalone mode is running and the formatting also works, but the issue is just with completion image this is my config of leetcode.nvim

{
    "kawre/leetcode.nvim",
    lazy = leet_arg ~= vim.fn.argv()[1],
    build = ":TSUpdate html",
    dependencies = {
      "nvim-telescope/telescope.nvim",
      "nvim-lua/plenary.nvim", -- required by telescope
      "MunifTanjim/nui.nvim",

      -- optional
      "nvim-treesitter/nvim-treesitter",
      "rcarriga/nvim-notify",
      "nvim-tree/nvim-web-devicons",
    },
    opts = {
      arg = leet_arg,
      lang = "rust",
      -- directory = "/media/gus/proyectos/leetcode/",
      ---@type boolean
      image_support = true,
      ---@type lc.storage
      storage = {
        home = vim.fn.stdpath "data" .. "/leetcode",
        cache = vim.fn.stdpath "cache" .. "/leetcode",
      },
      ---@type boolean
      logging = true,
      ---@type table<string, boolean>
      plugins = {
        non_standalone = false,
      },

      console = {
        open_on_runcode = true, ---@type boolean

        dir = "row", ---@type lc.direction

        size = { ---@type lc.size
          width = "90%",
          height = "75%",
        },

        result = {
          size = "60%", ---@type lc.size
        },

        testcase = {
          virt_text = true, ---@type boolean

          size = "40%", ---@type lc.size
        },
      },

      description = {
        position = "left", ---@type lc.position
        width = "40%", ---@type lc.size
        show_stats = true, ---@type boolean
      },
      injector = {}, ---@type table<lc.lang, lc.inject>
      cache = {
        update_interval = 60 * 60 * 24 * 7, ---@type integer 7 days
      },
      keys = {
        toggle = { "q" }, ---@type string|string[]
        confirm = { "<CR>" }, ---@type string|string[]

        reset_testcases = "r", ---@type string
        use_testcase = "U", ---@type string
        focus_testcases = "H", ---@type string
        focus_result = "L", ---@type string
      },
    },
  },

I tried with other languages like c/c++ and java, in this languages it works fine: image

kawre commented 5 months ago

It's a lsp related issue. You might have to add some root markers like rust-project.json

GustavoJCL commented 5 months ago

ok, but what should i add in this file? I found a config like this, but it didn't worked:

{
  "rust-analyzer.linkedProjects": [
    {
      "sysroot_src": "/home/gus/.rustup/toolchains/stable-x86_64-unknown-linux-gnu/lib/rustlib/src/rust/library/",
      "crates": [
        {
          "root_module": "*.rs",
          "edition": "2021",
          "deps": [],
        },
      ]
    }
  ]
}
zakissimo commented 5 months ago

I think you can't use '*' in your rust-project.json, that's why it wont work for you but take a look at this issue. I yoinked the sh script. Put it in the leetcode folder. Run it after your problem file has been created and it will generate the rust-project.json for you.

#!/bin/sh

for f in *.rs; do
    crates="${crates}${next}{\"root_module\": \"$f\",\"edition\": \"2021\",\"deps\": []}"
    next=","
done

sysroot_src="$(rustc --print sysroot)/lib/rustlib/src/rust/library"

echo "{\"sysroot_src\": \"$sysroot_src\", \"crates\": [$crates]}" | jq '.' >rust-project.json

Maybe you can create a job in neovim that does that for you automatically after a problem is loaded + restart the lsp ? (I'll try and look into that later maybe?)

GustavoJCL commented 5 months ago

thanks, it works fine, i just restarted the lsp and work perfectly

GustavoJCL commented 5 months ago

i added this to the kooks part in my config of leetcode:

hooks = {
        ---@type fun(question: lc.ui.Question)[]
        ["question_enter"] = {
          function()
            -- os.execute "sleep 1"
            local file_extension = vim.fn.expand "%:e"
            if file_extension == "rs" then
              local bash_script = tostring(vim.fn.stdpath "data" .. "/leetcode/rust_init.sh")
              local success, error_message = os.execute(bash_script)
              if success then
                print "Successfully updated rust-project.json"
                vim.cmd "LspRestart rust_analyzer"
              else
                print("Failed update rust-project.json. Error: " .. error_message)
              end
            end
          end,
        },
mbwilding commented 3 months ago

Sorry to necro bump but if you want to do this in pure lua, without a shell script or needing jq, so your config is portable, under hooks

["question_enter"] = {
    function()
        local file_extension = vim.fn.expand("%:e")
        if file_extension == "rs" then
            local target_dir = vim.fn.stdpath("data") .. "/leetcode"
            local output_file = target_dir .. "/rust-project.json"

            if vim.fn.isdirectory(target_dir) == 1 then
                local crates = ""
                local next = ""

                local rs_files = vim.fn.globpath(target_dir, "*.rs", false, true)
                for _, f in ipairs(rs_files) do
                    local file_path = f
                    crates = crates ..
                        next ..
                        "{\"root_module\": \"" .. file_path .. "\",\"edition\": \"2021\",\"deps\": []}"
                    next = ","
                end

                if crates == "" then
                    print("No .rs files found in directory: " .. target_dir)
                    return
                end

                local sysroot_src = vim.fn.system("rustc --print sysroot"):gsub("\n", "") ..
                    "/lib/rustlib/src/rust/library"

                local json_content = "{\"sysroot_src\": \"" ..
                    sysroot_src .. "\", \"crates\": [" .. crates .. "]}"

                local file = io.open(output_file, "w")
                if file then
                    file:write(json_content)
                    file:close()

                    local clients = vim.lsp.get_clients()
                    local rust_analyzer_attached = false
                    for _, client in ipairs(clients) do
                        if client.name == "rust_analyzer" then
                            rust_analyzer_attached = true
                            break
                        end
                    end

                    if rust_analyzer_attached then
                        vim.cmd("LspRestart rust_analyzer")
                    end
                else
                    print("Failed to open file: " .. output_file)
                end
            else
                print("Directory " .. target_dir .. " does not exist.")
            end
        end
    end,
},