lsp4j icon indicating copy to clipboard operation
lsp4j copied to clipboard

Provide documentation to implement the Debug Adapter protocol

Open apupier opened this issue 5 years ago • 14 comments

there is a section for Language Server Protocol: https://github.com/eclipse/lsp4j/blob/master/documentation/README.md#implement-your-language-server

it would be nice to have documentation for the Debug Adapter protocol too. If it can contain or point to a concrete example it would be even better.

apupier avatar Sep 24 '18 09:09 apupier

Does lsp4j indeed provide plumbing for implementing Debug Adapters? I cannot find any Debug Adapter implementations that use lsp4j to do so.

The Java Debugger for VSCode doesn't seem to use it (AFAICS): https://marketplace.visualstudio.com/items?itemName=vscjava.vscode-java-debug

I'd like to at least like to see/create 2 implementations: for Graal Truffle and Rhino (for legacy reasons), so any pointers to existing Debug Adapter implementations based on lsp4j and/or documentation how to create Debug Adapters using LSP4j much appreciated

p-bakker avatar Jan 13 '19 09:01 p-bakker

Java Debugger for VSCode

This was implemented about the same time that Debug Adapter Protocol was added to LSP4J. The main consumer of lsp4j debug adapter protocol is the Eclipse IDE, via LSP4E, so the other side of the communication.

jonahgraham avatar Jan 13 '19 15:01 jonahgraham

Does that mean lsp4j doesn't have anything to easy/jumpstart the implementation of a debug adapter for debug targets like truffle languages or nashorn/rhino? Or are you saying that it is just not yet not being used like that?

p-bakker avatar Jan 13 '19 16:01 p-bakker

Does that mean lsp4j doesn't have anything to easy/jumpstart the implementation of a debug adapter for debug targets like truffle languages or nashorn/rhino?

It has a lot to help jump start that, a whole communication layer that is implementable from both sides. To start you need to implement IDebugProtocolServer - same as you would implement LanguageServer if you were implementing one of them.

Or are you saying that it is just not yet not being used like that?

Yes, I am saying that it is not being used like that yet, at least in the main open source projects. IIRC some other people have been looking at using it, but it hasn't been my focus.

My focus (being supported by Renesas) has been on enabling integration of existing debug adapters into the Eclipse IDE. Some products are already out there thanks to other people adopting this, for example Eclipse Wild Web Developer, Eclipse aCute already use it, and Eclipse CDT will start using it soon. Some work was done to support Eclipse Che too, but as Che is moving in the Theia direction, that never really left the early stages.

jonahgraham avatar Jan 13 '19 17:01 jonahgraham

Ok, good to hear! Tnx for the info/pointers, will start from there

p-bakker avatar Jan 13 '19 17:01 p-bakker

@p-bakker For another server-side implementation of a debug adapter using LSP4J, you could take a look at Kotlin Debug Adapter.

fwcd avatar Jun 20 '20 21:06 fwcd

@fwcd been a while but thx, helpful to have such a clean example!

p-bakker avatar Jul 03 '21 11:07 p-bakker

Have been looking at this a bit recently, but feel like I'm missing some key concepts...

I understand that the heavy lifting is to be done in a implementation of IDebugProtocolServer, whos methods are called with messages received from the Debug Client.

So, for the Debug Client (f.e. VS Code) to be able to send these messages to the process where the debugee lives (and thus the IDebugProtocolServer impl. lives), there has to be some communication channel.

This is where I'm lost: scrambled this code together, but not sure what to do about the Input/OutputStreams:

		InputStream in = ...; 
		OutputStream out = ...;
		IDebugProtocolServer ds = new MyDABImpl();
		Launcher<IDebugProtocolClient> l = DSPLauncher.createServerLauncher(ds, in, out);
		l.startListening();

I would've expected LSP4J to somehow take care that, as I assume DAP Clients support an X number of communication mechanisms between the client and server, so LSP4J would offer those out of the box, so: a. not every DAB server has to implement them from scratch b. clients only have to implement X number of communication protocols to talk to any DAB server c. LSP4J having done the heavy lifting on supporting those communication mechanisms

I can find info on the content of the messages going back and forth, but not so much on the communication protocol itself.

Or am I way off/overlooking the obvious?

Any pointers appreciated

p-bakker avatar Jul 06 '21 15:07 p-bakker

@p-bakker DAP (and LSP) are transport-independent, so you can use whatever you want here, though stdio is usually the default and pretty easy to implement:

InputStream in = System.in;
OutputStream out = System.out;
...

For logging you should use either stderr or the DAP/LSP-provided log methods.

Some language servers and debug adapters provide options to use TCP or Node IPC instead, though that usually requires a small bit of client-specific support (e.g. for VSCode you could specify the transport when setting up the LanguageClient in the extension).

fwcd avatar Jul 06 '21 16:07 fwcd

@p-bakker You are mostly correct - the scope of the LSP4J project does not include that part (For LSP or for DAP). That said, additional bundles (like org.eclipse.lsp4j.websocket) have been contributed in the past to wrap up special use cases.

The reason for this is the launching of a DAP (or LSP) process is not nearly as generic as the running once the process is launched. i.e. there can be (very!) numerous ways the front end client and the server communicate (sockets, stdin/out, websockets, etc). In LSP4J the InputStream and OutputStream abstraction handles all of that of course.

So, to answer your question, the normal case (e.g. VSCode) is that the input and output to the server is just stdin/stdout. Most debug adapter process their command line options and provide a --server command line option so you can start the adapter in a server mode for debugging. Have a look at the entry point for the mock debug adapter (in typescript) to see what is involved in handling the startup.

The Debug Adapter Protcol doesn't cover these issues, but the Debugger Extension for VSCode docs do briefly cover this.

jonahgraham avatar Jul 06 '21 16:07 jonahgraham

BTW if someone does ever take on providing this better documentation task, providing an equivalent to the mock debug adapter would be a good starting example.

jonahgraham avatar Jul 06 '21 16:07 jonahgraham

Tnx for all the input, very useful.

If I can find the time (assuming I figure it all out) I'll try to provide some docs

p-bakker avatar Jul 06 '21 16:07 p-bakker

@fwcd Is there an equivalent to LanguageClientAware but for the DebugServer? Otherwise how does a DebugServer send messages back?

edaena avatar Jun 18 '22 22:06 edaena

I don't think using LanguageClientAware is necessary for LSP case - it is just a recommendation as nothing in LSP4J implements or calls anything in there*. A debug server sends messages back using the debug specific Launcher<IDebugProtocolClient> getRemoteProxy method.

* but someone else can confirm that - as I am not sure what I am missing, i.e. what is the value in this method.

jonahgraham avatar Jun 19 '22 01:06 jonahgraham