Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feature: spring boot support #37

Open
s1n7ax opened this issue Dec 1, 2023 · 11 comments
Open

feature: spring boot support #37

s1n7ax opened this issue Dec 1, 2023 · 11 comments
Assignees
Labels
enhancement New feature or request
Milestone

Comments

@s1n7ax
Copy link
Member

s1n7ax commented Dec 1, 2023

No description provided.

@s1n7ax s1n7ax self-assigned this Dec 1, 2023
@s1n7ax s1n7ax added the enhancement New feature or request label Dec 1, 2023
@s1n7ax s1n7ax added this to the v1.0.0 milestone Dec 1, 2023
@s1n7ax
Copy link
Member Author

s1n7ax commented Dec 1, 2023

@s1n7ax s1n7ax modified the milestones: v1.0.0, v2.0.0 Dec 10, 2023
@jvalkeal
Copy link

Hi, I'm in a Spring team and was planning to experiment this boot-ls/neovim integration during the upcoming holiday season and then noticed that you setup this new org. I have a rough idea how this integration should be done but wanted to ask if you've done any more experiments outside what you've shared in these various gh issues I found?

You just need to give me some rope here as I'm a recent neovim convert(I've used vi last 25 years but not for coding) so my lua skills are still a bit rusty.

@jvalkeal
Copy link

Due to limitations in an lsp protocol a relationship between jdtls and boot-ls is somewhat complex.

  • boot-ls is a separate process similar to jdtls and thus needs same type of facilities to control its lifecycle.
  • boot-ls is using jdtls extension points(osgi fun) to extend jdtls itself(you started by adding some boot-ls jars into jdtls), meaning part of boot-ls code runs within jdtls.
  • lsp protocol don't have any kind of server to server communication, thus some boot-ls related code running on jdtls need to communicate with separate boot-ls process itself.
  • Order to hook boot-ls and jdtls together an lsp client is used to dispatch these messages. That's where classpath.ts and java-data.ts comes into play.
  • This client side logic to dispatch messages from jdtls to boot-ls is somewhat similar what i.e. nvim-jdtls do in jdtls.lua. We need to handle all those boot-ls messages send from jdtls and run workspace commands which neovim would then send to boot-ls. We need to mimic this logic from classpath.ts and java-data.ts.
  • There's additional complexities i.e in vscode where syntax server may be launched before main lsp server takes over. Syntax server provides limited features until full lsp is available. boot-ls needs a full lsp to be available. This is not an issue in neovim until nvim-jdtls implements this syntax server functionality.

@s1n7ax
Copy link
Member Author

s1n7ax commented Dec 15, 2023

@jvalkeal Nothing other than what's in the linked branch.

I think it is,

  1. Neovim request to register a callback function to be called on classpath change
  2. When jdtls sends a changed event, neovim receives it and then pass it to boot-ls

What I don't understand is, by looking at the LSP client APIs implemented in neovim, it doesn't look like there is bidirectional communication. It's so far a request response mechanism. I'm not quite sure how jdtls can do server to client communication. May be some TCP stuff yet to implement (someone said that they created non LSP changes to something to get this working or something of that sort)? In coming weeks I will give it a try and let you know the findings.

@s1n7ax
Copy link
Member Author

s1n7ax commented Dec 16, 2023

There is one more 'twist' to this story. It is not currently possible using the available standard LSP protocol for a language server to execute commands on the client. So to make that possible we had to add some custom protocol to allow our jdt.ls extension to execute vscode commands so we can invoke the 'callbacks' to send information whenever classpaths are changed. This bit was done via a PR on the redhat vscode-java code base, which they were kind enough to accept. This can be found here:

This is what I was talking about:
spring-projects/sts4#76 (comment)

@jvalkeal
Copy link

Yes that "twist" originates from microsoft/language-server-protocol#1119.

I'm about to try writing some code. Lsp client functionality in vscode vs neovim is slightly different what comes for hooking into client side processing. Kris has been away but I'll chat with him after holidays if there's more into a story. I think vscode's client layer has been more closed for outside access which may be reason why we needed those hooks. Neovim however is a bit more open for hooking into things.

I was looking into Handlers which imho theoretically would let us replicate that same functionality(just assumption as I've yet to try it).

@s1n7ax
Copy link
Member Author

s1n7ax commented Dec 20, 2023

@jvalkeal LSP is new to me but it seems those are just some wrappers Neovim or Lspconfig has for us to be able to override the response handlers. I suspect it is vim.lsp.commands is what we are looking for.

Take a look at these two command implementations for example. One is there to make the request, however java.action.organizeImports.chooseImports is placed to handle a text changes.

https://github.com/mfussenegger/nvim-jdtls/blob/66b5ace68a5d1c45fdfb1afa8d847e87af2aa1f8/lua/jdtls.lua?plain=1#L783-L784

vscode-java is also doing something similar

This is where the exact command is defined
https://github.com/redhat-developer/vscode-java/blob/1cb8d0c77fb2a0da1381520bac65e36826a40c84/src/commands.ts?plain=1#L201

Here they are registering the command

https://github.com/redhat-developer/vscode-java/blob/1cb8d0c77fb2a0da1381520bac65e36826a40c84/src/sourceAction.ts?plain=1#L121-L122

@s1n7ax
Copy link
Member Author

s1n7ax commented Dec 27, 2023

@jvalkeal I think you were correct about the handler being the interface between these language servers. I was just messing around and found out these.

I created this language server config in lspconfig project called boot_ls. For workspace/executeClientCommand, I get following messages.

******************
{
  arguments = {},
  command = "_java.reloadBundles.command"
}
{
  client_id = 1,
  method = "workspace/executeClientCommand"
}
******************
{
  arguments = {},
  command = "vscode-spring-boot.ls.start"
}
{
  client_id = 1,
  method = "workspace/executeClientCommand"
}
local util = require 'lspconfig.util'

if not vim.lsp.handlers['workspace/executeClientCommand'] then
  vim.lsp.handlers['workspace/executeClientCommand'] = function(_, params, ctx) -- luacheck: ignore 122
    vim.print '******************'
    vim.print(params, ctx)
  end
end

local root_files = {
  {
    'build.xml',
    'pom.xml',
    'settings.gradle',
    'settings.gradle.kts',
  },
  { 'build.gradle', 'build.gradle.kts' },
}

return {
  default_config = {
    cmd = {
      'java',
      '-Dsts.lsp.client=vscode',
      '-jar',
      '/home/s1n7ax/Downloads/Test/spring-boot-language-server-1.2.0-201812201920.jar',
    },
    filetypes = { 'java' },
    root_dir = function(fname)
      for _, patterns in ipairs(root_files) do
        local root = util.root_pattern(unpack(patterns))(fname)
        if root then
          return root
        end
      end
    end,
    init_options = {},
  },
  docs = {
    description = [[
    ]],
    default_config = {
      root_dir = [[]],
    },
  },
}

@mycf
Copy link

mycf commented May 3, 2024

https://github.com/JavaHello/spring-boot.nvim

@s1n7ax
Copy link
Member Author

s1n7ax commented May 3, 2024

@mycf Holy shit. I will look into it.

@JavaHello
Copy link

If you have the VS Code Spring Boot extension installed, this configuration should work correctly.

require("spring_boot").init_lsp_commands()

require("lspconfig").jdtls.setup {
  init_options = {
    bundles = require("spring_boot").java_extensions(),
  },
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
Status: Blocked
Development

No branches or pull requests

4 participants