-
Notifications
You must be signed in to change notification settings - Fork 229
Add support for one-step debugging for Blazor #1885
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
Changes from all commits
88e4fad
6757fca
ce06cf1
dbaabe5
76fc7a9
d239662
ea2e7b4
79475e0
b6795c7
2ed3e96
146d0dd
0fd5492
ea7b144
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -15,6 +15,7 @@ | |
| "typescript": "3.3.4000" | ||
| }, | ||
| "dependencies": { | ||
| "ps-list": "^7.0.0", | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Just remembered, you'll also need to make sure this is tracked in component governance as well: https://dev.azure.com/dnceng/internal/_componentGovernance/dotnet-aspnetcore-tooling?_a=alerts&typeId=1981311&alerts-view-option=active |
||
| "vscode-html-languageservice": "2.1.7", | ||
| "vscode-languageclient": "5.2.1" | ||
| }, | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,87 @@ | ||
| /* -------------------------------------------------------------------------------------------- | ||
| * Copyright (c) Microsoft Corporation. All rights reserved. | ||
| * Licensed under the MIT License. See License.txt in the project root for license information. | ||
| * ------------------------------------------------------------------------------------------ */ | ||
|
|
||
| import * as vscode from 'vscode'; | ||
|
|
||
| import { RazorLogger } from '../RazorLogger'; | ||
| import { onDidTerminateDebugSession } from './TerminateDebugHandler'; | ||
|
|
||
| export class BlazorDebugConfigurationProvider implements vscode.DebugConfigurationProvider { | ||
|
|
||
| constructor(private readonly logger: RazorLogger, private readonly vscodeType: typeof vscode) { } | ||
|
|
||
| public async resolveDebugConfiguration(folder: vscode.WorkspaceFolder | undefined, configuration: vscode.DebugConfiguration): Promise<vscode.DebugConfiguration | undefined> { | ||
| const shellPath = process.platform === 'win32' ? 'cmd.exe' : 'dotnet'; | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Missed this in the first pass. @gregg-miskelly do you all do anything special in the case
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For our implementation, the error will be visible in the terminal in the workspace. Not sure if we want to check for There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Assuming the C# extension is installed (I think it always will be?) the user will get a prompt telling them that dotnet could not be located. That said, lots of people ignore errors. So if you are just showing a generic 'file not found' error, it might be helpful to print out a bit extra. You could link to: https://aka.ms/VSCode-CS-DotnetNotFoundHelp In reply to: 424869410 [](ancestors = 424869410) |
||
| const shellArgs = process.platform === 'win32' ? ['/c', 'chcp 65001 >NUL & dotnet run'] : ['run']; | ||
| const spawnOptions = { | ||
| cwd: configuration.cwd || (folder && folder.uri && folder.uri.fsPath), | ||
| }; | ||
|
|
||
| const output = this.vscodeType.window.createTerminal({ | ||
| name: 'Blazor WebAssembly App', | ||
| shellPath, | ||
| shellArgs, | ||
| ...spawnOptions, | ||
| }); | ||
|
|
||
| /** | ||
| * On non-Windows platforms, we need to terminate the Blazor | ||
| * dev server and its child processes. | ||
| */ | ||
| const terminate = this.vscodeType.debug.onDidTerminateDebugSession(async event => { | ||
captainsafia marked this conversation as resolved.
Show resolved
Hide resolved
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This will fire when any debug session finishes -- you want to look at the session to make sure it's the one we care about. (e.g. I might have an API server written in some other language, stopping/restarting that shouldn't cause my blazor debugging to stop)
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Seems sensible. The |
||
| await onDidTerminateDebugSession(event, this.logger, await output.processId); | ||
NTaylorMullen marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| terminate.dispose(); | ||
| }); | ||
captainsafia marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| output.show(/*preserveFocus*/true); | ||
|
|
||
| const browser = { | ||
| name: '.NET Core Debug Blazor Web Assembly in Browser', | ||
| type: configuration.browser === 'edge' ? 'pwa-msedge' : 'pwa-chrome', | ||
| request: 'launch', | ||
| timeout: configuration.timeout || 30000, | ||
| url: configuration.url || 'https://localhost:5001', | ||
| webRoot: configuration.webRoot || '${workspaceFolder}', | ||
| inspectUri: '{wsProtocol}://{url.hostname}:{url.port}/_framework/debug/ws-proxy?browser={browserInspectUri}', | ||
| trace: configuration.trace || false, | ||
| noDebug: configuration.noDebug || false, | ||
| }; | ||
captainsafia marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| try { | ||
captainsafia marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| /** | ||
| * The browser debugger will immediately launch after the | ||
| * application process is started. It waits a `timeout` | ||
| * interval before crashing after being unable to find the launched | ||
| * process. | ||
| * | ||
| * We do this to provide immediate visual feedback to the user | ||
| * that their debugger session has started. | ||
| */ | ||
| await this.vscodeType.debug.startDebugging(folder, browser); | ||
| this.logger.logVerbose('[DEBUGGER] Launching browser debugger...'); | ||
captainsafia marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } catch (error) { | ||
| this.logger.logError( | ||
| '[DEBUGGER] Error when launching browser debugger: ', | ||
| error, | ||
| ); | ||
| const message = `There was an unexpected error while launching your debugging session. Check the console for helpful logs and visit the debugging docs for more info.`; | ||
| this.vscodeType.window.showErrorMessage(message, `View Debug Docs`, `Ignore`).then(async result => { | ||
| if (result === 'View Debug Docs') { | ||
| const debugDocsUri = 'https://aka.ms/blazorwasmcodedebug'; | ||
| await this.vscodeType.commands.executeCommand(`vcode.open`, debugDocsUri); | ||
| } | ||
| }); | ||
| } | ||
|
|
||
| /** | ||
| * If `resolveDebugConfiguration` returns undefined, then the debugger | ||
| * launch is canceled. Here, we opt to manually launch the browser | ||
| * configruation using `startDebugging` above instead of returning | ||
| * the configuration to avoid a bug where VS Code is unable to resolve | ||
| * the debug adapter for the browser debugger. | ||
| */ | ||
| return undefined; | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,43 @@ | ||
| /* -------------------------------------------------------------------------------------------- | ||
| * Copyright (c) Microsoft Corporation. All rights reserved. | ||
| * Licensed under the MIT License. See License.txt in the project root for license information. | ||
| * ------------------------------------------------------------------------------------------ */ | ||
|
|
||
| import * as psList from 'ps-list'; | ||
| import { DebugSession } from 'vscode'; | ||
|
|
||
| import { RazorLogger } from '../RazorLogger'; | ||
|
|
||
| export async function onDidTerminateDebugSession( | ||
| event: DebugSession, | ||
| logger: RazorLogger, | ||
| targetPid: number | undefined, | ||
| ) { | ||
| if (event.type !== 'pwa-chrome' && event.type !== 'pwa-msedge') { | ||
| return; | ||
| } | ||
| if (!targetPid) { | ||
| return; | ||
| } | ||
|
|
||
| logger.logVerbose(`[DEBUGGER] Terminating debugging session with PID ${targetPid}...`); | ||
|
|
||
| let processes: psList.ProcessDescriptor[] = []; | ||
| try { | ||
| processes = await psList(); | ||
| } catch (error) { | ||
| logger.logError(`Error retrieving processes under PID ${targetPid} to clean-up: `, error); | ||
| } | ||
|
|
||
| try { | ||
| process.kill(targetPid); | ||
| processes.map((proc) => { | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Rather than using
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'll add this in a future PR. |
||
| if (proc.ppid === targetPid) { | ||
| process.kill(proc.pid); | ||
| } | ||
| }); | ||
| logger.logVerbose(`[DEBUGGER] Debug process clean-up of PID ${targetPid} complete.`); | ||
| } catch (error) { | ||
| logger.logError(`[DEBUGGER] Error terminating debug processes with PID ${targetPid}: `, error); | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.