-
Notifications
You must be signed in to change notification settings - Fork 131
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 protocol: Support browser launching #23
Comments
Proposal: If a client (frontend) supports the 'openExternal' request, it must announce this by setting the /** Arguments for 'initialize' request. */
export interface InitializeRequestArguments {
// ...
/** Client supports the openExternal request. */
supportsOpenExternalRequest?: boolean;
} And a debug adapter can then use the 'openExternal' request by passing the uri as the only (mandatory) argument: /** OpenExternal request; value of command field is 'openExternal'.
This request is sent from the debug adapter to the client to open a url in an external program, e.g. a http(s) or mailto-link, using the default application.
*/
export interface OpenExternalRequest extends Request {
// command: 'openExternal';
arguments: OpenExternalArguments;
}
/** Arguments for 'openExternal' request. */
export interface OpenExternalArguments {
/** The uri that should be opened. */
url: string;
}
/** Response to 'openExternal' request. This is just an acknowledgement, so no body field is required. */
export interface OpenExternalResponse extends Response {
} |
@gregg-miskelly @andrewcrawley @chuckries @DonJayamanne @pieandcakes For your convenience I've added the corresponding TypeScript definitions above. I'd appreciate any feedback. |
Sounds, good, however wouldn't a custom request also solve this. |
Yes, a custom request picked up in the corresponding extension could do the same. However, including this new request in the DAP simplifies the case where debug adapters are hosted by a different client than VS Code. |
One aspect we should think about here, is how this potentially could play together with other debug adaptors in VS Code? A typical scenario for ASP.Net developers is
Ideas: In the .net DA, for the If no debugging is wished, fallback to new |
@auchenberg multi-debugger cases like your scenario are best handled in an extension since a debug adapter has no access to VS Code's extension API (and cannot assume that it runs in VS Code at all). The @roblourens and @gregg-miskelly please chime in for additional thoughts... |
I didn't see any changes in your branch, but the type script definitions above look good to me. |
@gregg-miskelly sorry, I forgot to push. The commit is ac0289e |
LGTM |
The original scenario is that your C# app is running a server and you want to launch a browser to see the page. If someone wants to debug the page in vscode, this doesn't help with that. For that we would need a way for the chrome debug extension to know when the server is ready and what the url is. Or the C# extension could generate a chrome launch config and start it. Are you also thinking about that scenario? If that's not what you're focusing on right now this is fine for just launching the system's default app for some uri. |
@roblourens your scenario sounds more like Kenneth's use case from above: you want to debug both the client and the server. This is a useful scenario but probably out of scope for DAP because launching a second debug session from a DA (via a generated launch config) needs to make too many assumptions about the frontend (e.g. VS Code). Such a scenario is best served from an extension (which has access to VS Code's debugger API). The scenario to be addressed by the "openExternal" request is the single debug session case where a C# app is running a server and a browser is just launched to access the server's web UI. @gregg-miskelly Is this a correct representation of your scenario/needs? |
In order to address dotnet/vscode-csharp#2657 in a clean way, what I need is a way for a debug adapter to be able to request the client launch a web browser. The current proposal solves this, so it is fine with me. That said, I certainly don't have a problem if this is a more general solution, at least if it doesn't significantly impact the amount of work. For example, an alternate solution might be some sort of 'WebServerReady' event that VS Code cold initially handle by launching a web browser, but, if we wanted to support debugging client side and server side code at the same time, VS Code could add another builtin launch.json setting (like
|
Is the |
No, it is something that I made up as an example. |
Oh right, got it. |
I like the idea of a 'WebServerReady' DAP event but I don't like if VS Code core would have to implement that event and launch a browser or start a debug session. But we could easily delegate this to an extension. An extension could handle the event and launch a browser based on the information found in the launch config: "webBrowserAction": {
"type": "chrome",
"request": "launch",
"name": "Launch Chrome",
"webRoot": "${workspaceFolder}"
} The extension can even contribute the schema for the "webBrowserAction" JSON, so that Intellisense works seamlessly. The 'WebServerReady' DAP event could provide port information or a full URL. The extension would create a url based on the info from the 'WebServerReady' event and use Based on the "webBrowserAction" configuration it could launch a Chrome debug session with the URL. The extension could be
@gregg-miskelly @andrewcrawley @chuckries @DonJayamanne @pieandcakes @roblourens |
@weinand Would the One concern could be that |
@auchenberg yes, the Probably the event would be called The semantics would be: The "information" could be a How the debug adapter determines when to fire the event and what port or URI to include, is an implementation detail of the DA. The implementation might involve scraping terminal output. |
I've just created an extension server-ready that implements the "serverReady" approach based on scraping debug console output. After installing the extension it is possible to add this to any(!) launch config: "serverReadyAction": {
"pattern": "listening on port ([0-9]+)",
"debug": true
} The extension looks for the "pattern" in the debug console output and extracts the port number. Here are all supported properties and their default values: "serverReadyAction": {
"pattern": "listening on port ([0-9]+)",
"urlFormat": "http://localhost:%s",
"webRoot": "${workspaceFolder}",
"debug": false
} Here is the complete code of the extension: import * as vscode from 'vscode';
import * as util from 'util';
export function activate(context: vscode.ExtensionContext) {
// scan debug console output for a PORT message
vscode.debug.registerDebugAdapterTrackerFactory('*', {
createDebugAdapterTracker(session: vscode.DebugSession) {
const args = session.configuration.serverReadyAction;
if (args && args.pattern) {
const regexp = new RegExp(args.pattern);
return {
onDidSendMessage: m => {
if (m.type === 'event' && m.event === 'output' && m.body.output) {
const result = regexp.exec(m.body.output);
if (result && result.length === 2) {
openExternalWithUri(session, util.format(args.urlFormat || 'http://localhost:%s', result[1]));
}
}
}
};
}
}
});
}
function openExternalWithUri(session: vscode.DebugSession, uri: string) {
const args = session.configuration.serverReadyAction;
if (args.debug) {
vscode.debug.startDebugging(session.workspaceFolder, {
type: 'chrome',
name: 'Chrome Debug',
request: 'launch',
url: uri,
webRoot: args.webRoot || '${workspaceFolder}'
});
} else {
vscode.env.openExternal(vscode.Uri.parse(uri));
}
} @auchenberg @gregg-miskelly @andrewcrawley @chuckries @DonJayamanne @pieandcakes Do we still need a @gregg-miskelly how would you implement the @roblourens should this extension become part of Chrome debug? Or should we include this extension in VS Code or ship it via the marketplace? |
I feel that we should avoid having elaborate extension-specific stuff allowed in the protocol. This is an error that was mace in the language-server protocol where it is not possible to have a completely generic client implementation. Currently Vimspector has absolutely no adapter-specific knowledge and i want to keep it that way. If the protocol requires that we support launching a web browser (something i am strongly opposed to), then so be it, but i would strongly resist requiring debug-adapter-protocol implementations to have knowledge of adapter-specific handling instructions, code, methods or behaviours. |
I should say that for the record, this is already somewhat of a problem, if you take for example the way the java debug adapter is a sort of parasite on jdt.ls (perhaps, sympathetically, symbiotic rather than parasitic! :)), but ultimately once even that adapter is started up, there's no problem having a generic implementation of the protocol. |
I think the original "openExternal" is no longer an option as the discussion has shifted to an event based approach ("serverReady" event). |
I have no problem with additional events, so long as a generic DAP client knows what to do with them without adapter-specific configuration or code. An example is runInTerminal. This is a pretty straightforward requirement: Fire up a terminal, with some well defined properties and semantics. OK that might not be easy for some clients to implement, but it is well-defined. An event that is like "something happened" with the expectation that clients do unique and marvellous things depending on some adapter-specific client-side code is what is irksome because it requires developers of clients to know about adapter-specifics. And adapter vendors will simply only make it work in VSCode, because why would they repeat their work for all clients? So if the request was "runInBrowser" and the body properties were just a URL (or something like that), then sure, I could make that happen (Vim could guess what your default browser is and launch that). It wouldn't be easy or fun, but it would be generic. When coupled with a capability flag, this works nicely. The main problem with your extension is that is explicitly only works in VSCode meaning that the adapter is useless in other clients. Or at the least crippled. |
I don't understand what you mean by "the adapter is useless in other clients". My extension does not have an adapter. It is just a VS Code extension that contributes a schema and a bit glue code to VS Code. The extension implements a VS Code specific feature based on the official DAP. It does not rely on any changes in the DA. If you want to support the same feature in your client, you can do it. |
Sorry I meant in context of the original request:
I.e. the request appeared to suggest that the adapter wanted to instruct the client to fire up a web browser, as this is typical or required of the debugging experience for the adapter (similar to the I interpreted this requirement as generic, not specific to some particular adapter or client. |
As said before:
|
I see. though, TBH I didn't follow why that was. As @gregg-miskelly said:
|
The discussion has now moved to the approach sketched in Gregg's next paragraph:
|
I think what I'm saying is that this alternative approach restricts the solution to VSCode only. If that's the intention then sobeit, but it would be nice for us as a community providing tools to users to provide those tools consistently. As I understood it, the idea of DAP is to allow multiple clients to enjoy the benefits of having the excellent debugging experience we get from the wealth of great adapters. And we, the community, are super thankful for that. By introducing protocol elements which are there to facilitate things that uniquely work in one client, this would IMO go against the ethos of the protocol. But you're in control of the protocol, and its ethos, not me. I'm just one guy, trying to make a useful tool :). I will just never say I support this event, request, whatever and my users just won't get this feature. They still get loads of really cool features though from the base protocol though. So I'm still pretty happy. I just would like to avoid the LSP-problem where each client has to have server-specific knowledge by default. Hence why I was suggesting steering the conversation back to a generic event. |
Why does the "alternative approach restricts the solution to VSCode only"? The "alternative approach" proposes that the DA sends out an event to the client that says "the debugged server is ready and here is a URI you could use to talk to the server". Where do you see a VSCode restriction here? |
What would a generic client be expected to do with such an event? i.e. what would the documentation for the event say the client should do in response to this event? If it says something along the lines of "for particular languages..." or "you might wish to..." or "adapter specific hooks should ...." or something then it's not a clear and consise protocol that can be implemented independently of servers. If the instruction is "upon receiving this event clients must launch a web browser pointing at the address supplied in |
To be clear, it's the |
@puremourning "runInTerminal" is a request because the DA relies on it to launch a target. If "runInTerminal" fails, launching a target fails. The "runInTerminal" spec is a "must". "serverReady" is an event because it does not require anything from a client. Events don't fail and they don't return a result. Events are used for loose coupling. The "serverReady" spec would be a "might" (like all event specs). If a headless DAP client decides to not handle "serverReady" because it does not have a browser, then that's perfectly fine and the spec should make this clear. Eliminating "could" and "shoulds" from a spec like DAP doesn't make sense, because the protocol spec neither covers the functionality or scope of a client (frontend), nor the functionality or scope of the DA (backend). |
The "Server Ready" extension mentioned above is now available for Insiders here: https://marketplace.visualstudio.com/items?itemName=andreweinand.server-ready It does not require any new DAP features and works with all existing debugger extensions (as long as they use DAP "output" events for sending output to the debug console). |
Ok thanks for the explanation. :) |
Detecting when ASP.NET is ready
The C# debugger currently is also just scrapping stdout. We look for lines that start with 'Now listening on '. If we want to avoid adding the new
Server-ready extensionI would be fine with replacing our current browser launch code either with something that raised the For reference, here is the output from starting a 'hello world' ASP.NET Core app --
|
Playing devils advocate here @gregg-miskelly: If you already are listening to the process output, why can't your VS Code extension that wraps the Debug Adaptor, just call |
@auchenberg personally that feels like a hack to me. There are lots of programming languages that are popular for creating web servers. If we expect folks will want to use a VS Code API to start a web browser then we shouldn't make every language tie their debug adapter to VS Code to do so. |
We propose the following:
|
Looking forward to this |
This is a really interesting use of the debug adapter tracker API! It could technically be used for other things besides waiting for a server to be ready so I wonder if we would want to generalize the naming of it beyond "server ready". Could call it a "launch config trigger" or something like that. For example, when I debug vscode, I sometimes want to attach to the search process, but it doesn't start until some time after vscode starts, so a normal compound config doesn't work. I could write to the console when it starts, and set up a node attach config to trigger when that output is detected. |
@roblourens glad you liked it ;-) The next Insider build (Monday) will have the |
I've create a new feature microsoft/vscode#69311 for February to cover the built-in extension created for this. |
I'm closing this request for a DAP addition because we could address the need by a client/frontend implementation (microsoft/vscode#69311). |
Currently the debug protocol has no way for a debug adapter to request that the IDE open up a web browser. Some debug adapters, such as the C# debug adapter, can start a web browser as part of launching a web server project. The debug adapter needs some control to be able to signal when the web server is ready.
This could either be designed as an event (ex: WebServerReady) or as a callback request like starting processes in the terminal.
Dependent issue: dotnet/vscode-csharp#2657
Related issue: microsoft/vscode-debugadapter-node#153
The text was updated successfully, but these errors were encountered: