ray-x / lsp_signature.nvim

LSP signature hint as you type
Apache License 2.0
2.07k stars 57 forks source link

java lsp not work #97

Closed xuliefeng closed 3 years ago

xuliefeng commented 3 years ago

hi, I followed the plugin and it works fine in lua but not work for java。Please help me to see if the configuration is wrong

require'lsp_signature'.setup { bind = true, floating_window = true, hint_enable = false, hint_prefix = "", extra_trigger_chars = {"(", ","}, hi_parameter = "Search", float_window_above_cur_line = false, log_path = vim.fn.expand("$HOME") .. ".cache/nvim/sig.log", handler_opts = { border = 'single'}, }

I am using vim-cmp at the same time, and it works fine

ray-x commented 3 years ago

I can reproduce the issue. From what I saw, JDTLS does not send any signature help back to neovim. What I got is

{
  bufnr = 1,
  client_id = 1,
  method = "textDocument/signatureHelp"
}

I tried to send lua vim.lsp.buf.signature_help(), Also there is no response .

If it is not issue from jdtls, then there maybe something wrong with neovim lsp framework.

xuliefeng commented 3 years ago

我可以重现这个问题。 据我所知,JDTLS 不会将任何签名帮助发送回 Neovim。 我得到的是

{ 
   缓冲区 =  1 , 
   客户端 ID =  1 , 
   方法 =  " 文本文档/签名帮助 " 
 } 

我试着发送 lua vim.lsp.buf.signature_help(),也没有回应。

如果不是 jdtls 的问题,那么可能是 neovim lsp 框架有问题。

ok thanks

ray-x commented 3 years ago

I believe jdtls disable signature by default, please check these threads on how to turn it on

https://github.com/eclipse/eclipse.jdt.ls/issues/1436

and

https://github.com/mfussenegger/nvim-jdtls/issues/88

xuliefeng commented 3 years ago

Yes, I have solved it. Now it works normally. thanks

ray-x commented 3 years ago

For document purpose: JDTLS setup need to include:

local jdtcfg = {
    settings = {
      java = {signatureHelp = {enabled = true}, contentProvider = {preferred = 'fernflower'}}
    },
    on_init = function(client)
      if client.config.settings then
        client.notify('workspace/didChangeConfiguration', {settings = client.config.settings})
      end
    end
  }

require('lspconfig').setup(jdtcfg)

Alsp please make sure the $JDTLS_HOME and $JAVA_HOME is correct.

gangov commented 1 year ago

can you please how would this look like with the following:

  {
    "ray-x/lsp_signature.nvim",
    config = function()
      require"lsp_signature".setup({
        -- …
      })
    end,
  }
ray-x commented 1 year ago

Is your java lsp up and running? what is the output of LspInfo command?

gangov commented 1 year ago

this is what it says

 Language client log: /Users/gangov/.local/state/lvim/lsp.log
 Detected filetype:   java

 1 client(s) attached to this buffer: 

 Client: jdtls (id: 2, bufnr: [32])
    filetypes:       java
    autostart:       true
    root directory:  /Users/gangov/Development/work/allServices/serviceName
    cmd:             jdtls -configuration /Users/gangov/.cache/jdtls/config -data /Users/gangov/.cache/jdtls/workspace --jvm-arg=-javaagent:/Users/gangov/.local/share/java/lombok.jar

 1 active client(s) not attached to this buffer: 

 Client: tsserver (id: 1, bufnr: [19])
    filetypes:       javascript, javascriptreact, javascript.jsx, typescript, typescriptreact, typescript.tsx
    autostart:       true
    root directory:  Running in single file mode.
    cmd:             typescript-language-server --stdio

 Configured servers list: jdtls, tsserver, tailwindcss
ray-x commented 1 year ago

I do not use java. But from my earlier comments, it seems jdtls disabled the signature by default. You might need to set up lspconfig like this:

local jdtcfg = {
    settings = {
      java = {signatureHelp = {enabled = true}, contentProvider = {preferred = 'fernflower'}}
    },
    on_init = function(client)
      if client.config.settings then
        client.notify('workspace/didChangeConfiguration', {settings = client.config.settings})
      end
    end
  }

require('lspconfig').setup(jdtcfg)
gangov commented 1 year ago

so something like this doesn't work:

local jdtcfg = {
  settings = {
    java = {signatureHelp = {enabled = true}, contentProvider = {preferred = 'fernflower'}}
  },
  on_init = function(client)
    if client.config.settings then
      client.notify('workspace/didChangeConfiguration', {settings = client.config.settings})
    end
  end
}

lvim.plugins = {
  {
    "ray-x/lsp_signature.nvim",
    config = function()
      require('lspconfig').setup(jdtcfg)
    end,
  }
}
ray-x commented 1 year ago

I wish I could offer more help but I spent half an hour without even getting jdtls running. I checked the behaviour of vscode and it also failed to get lsp setup and do some simple tasks like auto-complete. From what I saw you may need something like https://github.com/mfussenegger/nvim-jdtls

gangov commented 1 year ago

no worries @ray-x I appreciate your help and the work you put into this tool! 🤜🤛

TheRustifyer commented 8 months ago

so something like this doesn't work:

local jdtcfg = {
  settings = {
    java = {signatureHelp = {enabled = true}, contentProvider = {preferred = 'fernflower'}}
  },
  on_init = function(client)
    if client.config.settings then
      client.notify('workspace/didChangeConfiguration', {settings = client.config.settings})
    end
  end
}

lvim.plugins = {
  {
    "ray-x/lsp_signature.nvim",
    config = function()
      require('lspconfig').setup(jdtcfg)
    end,
  }
}

For future readers, and for reference, here's how a JDTLS configuration should look like. Note that JDTLS is a bit special, as any other thing in the Java world. Best and easy way to configure JDTLS is by having a java.lua file under a folder named ftplugin on your Neovim's config directory (on the root of the config folder)

local jdtls = require('jdtls')

local procs = require('the-rustifyer.utils.procedures')
local globals = require('the-rustifyer.core.globals')
local consts = require('the-rustifyer.core.constants')

local p_sep = globals.path.sep
local mason_path = consts.dirs.nvim_data .. p_sep .. 'mason' .. p_sep .. 'packages'

local jdtls_path = mason_path .. p_sep .. 'jdtls'
local jdtls_jar_path = vim.fn.glob(jdtls_path .. '/plugins/org.eclipse.equinox.launcher_*.jar')
-- local root_dir = require('jdtls.setup').find_root({ '.gitignore', 'code/', '.gitattributtes', 'README.md' })

local on_attach = function(_client, bufnr)
    local bufopts = { noremap = true, silent = true, buffer = bufnr }
    -- Java extensions provided by jdtls
    procs.nnoremap("<C-o>", jdtls.organize_imports, bufopts, "Organize imports")
    procs.nnoremap("<space>ev", jdtls.extract_variable, bufopts, "Extract variable")
    procs.nnoremap("<space>ec", jdtls.extract_constant, bufopts, "Extract constant")
    vim.keymap.set('v', "<space>em", [[<ESC><CMD>lua require('jdtls').extract_method(true)<CR>]],
    { noremap = true, silent = true, buffer = bufnr, desc = "Extract method" })
end

local bundles = {
  -- Path to the Microsoft's Java debug plugin
  vim.fn.glob(mason_path .. p_sep .. 'java-debug-adapter/extension/server/com.microsoft.java.debug.plugin-*.jar', 1),
}
-- Extending the bundles table to add the plugin that allows us to debug Java tests within Neovim
vim.list_extend(bundles, vim.split(vim.fn.glob(mason_path .. p_sep .. "java-test/extension/server/*.jar", 1), "\n"))

local config = {
    flags = {
        debounce_text_changes = 80,
    },
    on_attach = on_attach, -- We pass our on_attach keybindings to the configuration map
    root_dir = vim.fn.getcwd(), -- Set the root directory to our found root_marker
    -- Here you can configure eclipse.jdt.ls specific settings
    -- These are defined by the eclipse.jdt.ls project and will be passed to eclipse when starting.
    -- See https://github.com/eclipse/eclipse.jdt.ls/wiki/Running-the-JAVA-LS-server-from-the-command-line#initialize-request
    -- for a list of options

    -- See: https://github.com/eclipse/eclipse.jdt.ls#running-from-the-command-line
    -- The command that starts the language server

    -- 💀
    -- This is the default if not provided, you can remove it. Or adjust as needed.
    -- One dedicated LSP server & client will be started per unique root_dir

    init_options = {
        bundles = bundles,
    },

    cmd = {
        -- 💀
        'java', -- or '/path/to/java17_or_newer/bin/java'
        -- depends on if `java` is in your $PATH env variable and if it points to the right version.

        '-Declipse.application=org.eclipse.jdt.ls.core.id1',
        '-Dosgi.bundles.defaultStartLevel=4',
        '-Declipse.product=org.eclipse.jdt.ls.core.product',
        '-Dlog.protocol=true',
        '-Dlog.level=ALL',
        '-Xmx1g',
        '--add-modules=ALL-SYSTEM',
        '--add-opens', 'java.base/java.util=ALL-UNNAMED',
        '--add-opens', 'java.base/java.lang=ALL-UNNAMED',
        '-javaagent:' .. jdtls_path .. '/lombok.jar',
        -- 💀
        '-jar', jdtls_jar_path,
        -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^                                       ^^^^^^^^^^^^^^
        -- Must point to the                                                     Change this to
        -- eclipse.jdt.ls installation                                           the actual version

        -- 💀 I only work with Java on Windows or Linux, no need to check anything else
        '-configuration', jdtls_path .. '/config_' .. (globals.sys.is_windows and 'win' or 'linux'),
        -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^        ^^^^^^
        -- Must point to the                      Change to one of `linux`, `win` or `mac`
        -- eclipse.jdt.ls installation            Depending on your system.

        -- 💀
        -- See `data directory configuration` section in the README
        '-data',
        -- project_root_dir
        vim.fn.getcwd()
    },

    -- Here you can configure eclipse.jdt.ls specific settings
    -- See https://github.com/eclipse/eclipse.jdt.ls/wiki/Running-the-JAVA-LS-server-from-the-command-line#initialize-request
    -- for a list of options
    settings = {
        java = {
            signatureHelp = { enabled = true },
            contentProvider = { preferred = 'fernflower' },  -- Use fernflower to decompile library code
            -- Specify any completion options
            completion = {
                favoriteStaticMembers = {
                    "org.hamcrest.MatcherAssert.assertThat",
                    "org.hamcrest.Matchers.*",
                    "org.hamcrest.CoreMatchers.*",
                    "org.junit.jupiter.api.Assertions.*",
                    "java.util.Objects.requireNonNull",
                    "java.util.Objects.requireNonNullElse",
                    "org.mockito.Mockito.*"
                },
                filteredTypes = {
                    "com.sun.*",
                    "io.micrometer.shaded.*",
                    "java.awt.*",
                    "jdk.*", "sun.*",
                },
            },
            -- Specify any options for organizing imports
            sources = {
                organizeImports = {
                    starThreshold = 9999;
                    staticStarThreshold = 9999;
                },
            },
            -- How code generation should act
            codeGeneration = {
                toString = {
                    template = "${object.className}{${member.name()}=${member.value}, ${otherMembers}}"
                },
                hashCodeEquals = {
                    useJava7Objects = true,
                },
                useBlocks = true,
            },

        }
    },
}

-- This starts a new client & server,
-- or attaches to an existing client & server depending on the `root_dir`.
require('jdtls').start_or_attach(config)

I set up a lot of variables defined on my configuration for make it more convenient, but the important point is just the "skeleton" of the configuration.

I just use Java only professionaly, and I am able to use it every day without issues in my job, so I really hope that this could help anybody in the same situation

EDIT: I download everything related with Java via Mason, so it's very convinient to quickly automate everything if you have multiple set ups, because it's tedious to download everything manually and have to figure all the paths on your own, and that gets worse if you use different OS (this is just for readers to take in consideration why some path variables looks like in the configuration I shared)

gangov commented 8 months ago

thanks for sharing @TheRustifyer