-
-
Notifications
You must be signed in to change notification settings - Fork 960
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
Debug Adapter Protocol Support #322
Comments
Is possbile to execute command and send request to a running language server started by coc, so it's possible to make a coc extension for it. |
I would consider vimspector support for neovim, but only after I have made vimspector fully tested and stable (e.g. a "v1 version") on vim, as that's the platform I use. Contributions are of course welcome. |
@chemzqm How can we write these kind of extensions? I can help you. |
@XVilka I checked it out, but the last few comments do not look promising. |
Better ref puremourning/vimspector#29 |
@puremourning Thanks for reference. That actually looks quite promising. |
@chemzqm |
@chemzqm I'm interested in help too. |
Better ref neovim/neovim#11732. That way, it isn't bound to Coc and can be packaged with a stable release of Neovim one day. |
Vimspector neovim support is now fully functional and just needs testing. |
@hariamoor What should this plugin provide, that isn't already provided by Vimspector? AFAIK auto-completion is the only thing missing and also the original reason I created this feature request here. |
You’re right. Now that vimspector has neovim support (nearly). Vimspector has cmdline completion (sort of) for evaluate and watch. And for the console prompt buffer, it’s possible manually/planned generally to make an omnifunc which would work with standard completion and/or YCM etc. I suppose one thing that would help is coc could expose an equivalent to the command to that YCM does to allow starting the java debug adapter (which is a plugin to jdt.ls). In YCM user runs But other than that it seems out of scope for coc. |
@hariamoor this is coc issue tracker, for a possible coc debugging extension. It doesn't make sense to request coc author to write a standalone debugging interface, for NeoVim only, in Lua. |
So based on @puremourning's comment... currently is there a way to start debug session on java language server from within coc ( |
Here's an example: function! JavaStartDebugCallback(err, port)
execute "cexpr! 'Java debug started on port: " . a:port . "'"
call vimspector#LaunchWithSettings({ "configuration": "Java Attach", "AdapterPort": a:port })
endfunction
function! JavaStartDebug()
call CocActionAsync('runCommand', 'vscode.java.startDebugSession', function('JavaStartDebugCallback'))
endfunction
nmap <F1> :call JavaStartDebug()<CR> |
Thank you @dansomething. Here how it goes when I press F1 to invoke your function: (1 of 1): Java debug started on port: null Press ENTER or type command to continue Enter value for debugPort: 8000 Here it opens complete empty vimspector window with asking for the port at the bottom again: Enter port to connect to: 8000 Debugging works flawlessly in vscode but can't get it to work in nvim. Not sure if it's caused by vimspector itself or coc is somehow preventing vscode-debugger and vimspector to talk to each other. |
Yeah, you'll need to get the Java Debug extension loaded into jdt.ls. Currently Vimspector won't do this for you. The vscode-java-debug plugin does it like this. See the jdt.ls extension docs for more info. I've hacked to together an extension for coc.nvim to do this same thing. You're welcome to try it, but I can't make any guarantees for your setup. Being experimental, its currently not available as an npm package. To install the coc-java-debug extension:
To uninstall it
|
Oh, here's the {
"adapters": {
"java-debug-server": {
"name": "vscode-java",
"port": "${AdapterPort}"
}
},
"configurations": {
"Java Attach": {
"adapter": "java-debug-server",
"configuration": {
"request": "attach",
"host": "127.0.0.1",
"port": "5005"
},
"breakpoints": {
"exception": {
"caught": "N",
"uncaught": "N"
}
}
}
}
} See the Vimspector config for more info on this setup. |
Great. Thanks for the guidance. After hours of struggling... finally once your plugin was installed, it started to work like a charm. Oh man this is plain awesome 🙂 With coc and vimspector, I don't ever need to touch my ide anymore. 👍 |
this! Let's hope the process keeps on getting better and smoother thanks to all the hard work of these project maintainers. |
correction : can't. |
@dansomething - if you're feeling generous, would you mind writing this up on the vimspector wiki? I really appreciate the work you put in to make that smooth and to help others to get it working too |
Sure, I'll give it a shot. And thanks for the clarification above. Its the responsibility of the code that starts jdt.ls to provide the config to enable the java-debug server extension. |
@puremourning I had some progress started on the readme for coc-java-debug so I just pushed that up. Feel free to copy/tweak or link to that for the vimspector wiki. |
To install mason along |
It would be awesome if coc could support dap like it does lsp... |
@luisdavim what do you mean by "support dap like it does lsp"? LSP is a protocol, and DAP is another, so, how does former supports the latter? |
They are different protocols, currently, coc supports one but not the other. What I'm saying is that coc should support both. |
Is the request to replace vimspector in a coc plugin? I just got into vimspector and haven't configured it all the way yet but came here thinking that coc might have a debugging interface that I wasn't aware of. |
OP probably meant integrating nvim-dap(-ui)/vimspector like vscode? For example, using rust analyzer, there are run/debug commands (and virtual texts) for main function and tests atm. I just tried debugging one, and instead of starting my DAP client automatically, I got
I'm not sure if Edit: Ah |
I found the auto-completion feature can be achieved in the varies watch window of vimspector by introduce plug Youcompleteme. And I tried to modify the vimrc file to do the same thing by coc.vim but failed. Can this feature be realized in the future? |
Here is something i have whipped up for java, if someone is interested, it integrates both CoC and native nvim lsp with nvim-dap (install coc-java-debug (needed to inject the debug jar bundles) and coc-java for coc, or configure init_options for nvim-jdtls with java-debug) local HOTCODEREPLACE_TYPE = {
END = "END",
ERROR = "ERROR",
WARNING = "WARNING",
STARTING = "STARTING",
BUILD_COMPLETE = "BUILD_COMPLETE",
}
local SETTINGS = {}
local function cache_settings()
if vim.g.did_coc_loaded ~= nil then
SETTINGS = vim.fn["coc#util#get_config"]("java")
else
SETTINGS = {}
end
end
require("dap").listeners.before["event_hotcodereplace"]["jdtls"] = function(session, body)
if body.changeType == HOTCODEREPLACE_TYPE.BUILD_COMPLETE then
session:request("redefineClasses", nil, function(err)
if err then
vim.notify("Error during hot reload", vim.log.levels.WARN)
else
vim.notify("Applied hot code reload", vim.log.levels.WARN)
end
end)
elseif body.message then
vim.notify(body.message, vim.log.levels.WARN)
end
end
local function execute_command(command, callback, bufnr)
if vim.g.did_coc_loaded ~= nil then
if not command.arguments then
command.arguments = {}
end
if type(command.arguments) ~= "table" then
command.arguments = { command.arguments }
end
table.insert(command.arguments, function(error, result)
error = error ~= vim.NIL and { message = error } or nil
callback(error, result, {
name = "jdtls",
config = {
settings = {
java = SETTINGS,
},
},
})
end)
vim.fn.CocActionAsync("runCommand", command.command, unpack(command.arguments))
else
local clients = {}
for _, c in pairs(vim.lsp.get_active_clients({ bufnr = bufnr }) or {}) do
local command_provider = c.server_capabilities.executeCommandProvider
local commands = type(command_provider) == "table" and command_provider.commands or {}
if vim.tbl_contains(commands, command.command) then
table.insert(clients, c)
end
end
if vim.tbl_count(clients) == 0 then
vim.notify(string.format("Unable to find client that supports %s", command.command), vim.log.levels.WARN)
else
clients[1].request("workspace/executeCommand", command, function(err, resp)
if callback then
callback(err, resp)
elseif err then
vim.notify(string.format("Could not execute command action: %s", err.message), vim.log.levels.WARN)
end
end)
end
end
end
local function init_debug_session(cb, bufnr)
execute_command({
command = "vscode.java.startDebugSession",
}, function(err, port)
if err ~= nil then
vim.notify(string.format("Unable to initiate java debug session %s", err.message), vim.log.levels.WARN)
else
cb(port)
end
end, bufnr)
end
local function fetch_java_executable(mainclass, project, cb, bufnr)
if not project or #project == 0 then
local binary = vim.env.JAVA_HOME and string.format("%s/%s", vim.fs.normalize(vim.env.JAVA_HOME), "bin/java") or "java"
if vim.fn.executable(binary) then
cb(binary)
else
vim.notify(string.format("Unable to resolve default system java executable for %s", mainclass), vim.log.levels.WARN)
end
else
execute_command({
command = "vscode.java.resolveJavaExecutable",
arguments = { mainclass, project },
}, function(err, java_exec)
if err then
vim.notify(
string.format("Unable to resolve java executable for %s/%s: %s", project, mainclass, err.message),
vim.log.levels.WARN
)
else
cb(java_exec)
end
end, bufnr)
end
end
local function fetch_needs_preview(mainclass, project, cb, bufnr)
if not project or #project == 0 then
cb("")
else
execute_command({
command = "vscode.java.checkProjectSettings",
arguments = vim.fn.json_encode({
className = mainclass,
projectName = project,
inheritedOptions = true,
expectedOptions = { ["org.eclipse.jdt.core.compiler.problem.enablePreviewFeatures"] = "enabled" },
}),
}, function(err, use_preview)
vim.print(err, use_preview, "preview")
if err then
vim.notify(
string.format("Unable to resolve preview feature for %s/%s: %s", project, mainclass, err.message),
vim.log.levels.WARN
)
else
use_preview = use_preview and "--enable-preview" or ""
cb(use_preview)
end
end, bufnr)
end
end
local function fetch_main_definitions(cb, bufnr)
execute_command({
command = "vscode.java.resolveMainClass",
}, function(err, mainclasses)
if err then
vim.notify(string.format("Unable to resolve any main project definitions", err.message), vim.log.levels.WARN)
else
cb(mainclasses)
end
end, bufnr)
end
local function fetch_project_paths(mainclass, project, cb, bufnr)
if not project or #project == 0 then
cb(nil, nil)
else
execute_command({
command = "vscode.java.resolveClasspath",
arguments = { mainclass, project },
}, function(err, paths)
if err then
vim.notify(string.format("Unable to resolve classpath for %s/%s: %s", project, mainclass, err.message), vim.log.levels.WARN)
else
cb(paths[1], paths[2])
end
end, bufnr)
end
end
local function fetch_dap_configs(callback)
cache_settings()
local bufnr = vim.api.nvim_get_current_buf()
fetch_main_definitions(function(mainclasses)
local configurations = {} -- clean config map
if mainclasses == nil or #mainclasses == 0 then
callback(configurations)
return
end
local remaining = #mainclasses
for _, mc in pairs(mainclasses) do
local mainclass = mc.mainClass
local project = mc.projectName
fetch_java_executable(mainclass, project, function(java_exec)
fetch_needs_preview(mainclass, project, function(use_preview)
fetch_project_paths(mainclass, project, function(module_paths, class_paths)
remaining = remaining - 1
if module_paths and class_paths then
-- insert new fresh config entry
table.insert(configurations, {
vmArgs = use_preview,
javaExec = java_exec,
projectName = project,
mainClass = mainclass,
classPaths = class_paths,
modulePaths = module_paths,
})
end
if remaining == 0 then
callback(configurations)
end
end, bufnr)
end, bufnr)
end, bufnr)
end
end, bufnr)
end
return function(opts)
local function attempt_enrich_config(config, on_config)
if not config.__template then
-- flat config, already resolved, just enrich
-- we have nothing more to do to this config
opts.enricher(config, on_config)
else
-- config table here is a copy of the original,
-- but the result will have the main class resolved
-- we know it was 'template' but yet not resolved
-- we resolve it and the template flag will be cleared
-- within the default dap enricher later on
fetch_dap_configs(function(configs)
if #configs > 1 then
local list = {}
for i, c in ipairs(configs) do
table.insert(list, string.format("%s: %s", i, c.mainClass))
end
vim.ui.select(list, { prompt = "Select application entry point" }, function(selection)
if selection == nil or selection == "" then
return
end
local mainid = tonumber(selection:match("(%d+)")) -- get the config index
opts.enricher(vim.tbl_extend("force", config, configs[mainid]), on_config)
end)
vim.notify("Multiple entrypoints have been detected", vim.log.levels.WARN)
else
opts.enricher(vim.tbl_extend("force", config, configs[1]), on_config)
end
end)
end
end
return {
adapter = function(callback, _)
init_debug_session(function(port)
callback({
type = "server",
enrich_config = attempt_enrich_config,
host = opts.server_host or "127.0.0.1",
port = opts.server_port or port,
})
end, vim.api.nvim_get_current_buf())
end,
configurations = {
default_launch = {
__template = true,
type = "java",
request = "launch",
cwd = "${workspaceFolder}",
console = "integratedTerminal",
name = "Default launch (java)",
},
},
}
end
|
Is your feature request related to a problem? Please describe.
I would like to have additional debugging support in coc.nvim. There are no debug extensions for neovim, that provide proper auto-completion, because this would require additional IDE level language support.
Describe the solution you'd like
VS Code integrates a multitude of debuggers via its Debug Adapter Protocol. They offer a node based sdk as a separate NPM Package. Additional info can be found here. coc.nvim would need to:
Describe alternatives you've considered
I checked two existing debugger extensions:
I found out later, that vimspector doesn't plan to support neovim
Additional context
All debug adapters known to me only exist as a vscode extension and in the case of Java Debug even require its LSP counterpart. I realize, that debugging is not coc.nvim's main focus, but if this can be implemented for neovim, then likely only on top of coc.nvim. I don't know any other plugin, that integrates the vscode ecosystem so well and also provides LSP-support.
The text was updated successfully, but these errors were encountered: