|
| 1 | +/*--------------------------------------------------------------------------------------------- |
| 2 | + * Copyright (c) Microsoft Corporation. All rights reserved. |
| 3 | + * Licensed under the MIT License. See License.txt in the project root for license information. |
| 4 | + *--------------------------------------------------------------------------------------------*/ |
| 5 | + |
| 6 | +import * as vscode from 'vscode'; |
| 7 | +import { DebugProtocol } from 'vscode-debugprotocol'; |
| 8 | +import { SetNextStatementHelpers } from './setNextStatementHelpers'; |
| 9 | + |
| 10 | +export default async function setNextStatement() : Promise<void> { |
| 11 | + try { |
| 12 | + const debugSession = vscode.debug.activeDebugSession; |
| 13 | + if (!debugSession) { |
| 14 | + throw new Error("There isn't an active .NET debug session."); |
| 15 | + } |
| 16 | + |
| 17 | + const debugType: string = debugSession.type; |
| 18 | + if (debugType !== "coreclr" && debugType !== "clr") { |
| 19 | + throw new Error("There isn't an active .NET debug session."); |
| 20 | + } |
| 21 | + |
| 22 | + const currentEditor = vscode.window.activeTextEditor; |
| 23 | + if (!currentEditor) { |
| 24 | + throw new Error("There isn't an active source file."); |
| 25 | + } |
| 26 | + |
| 27 | + const position = currentEditor.selection.active; |
| 28 | + if (!position) { |
| 29 | + throw new Error("There isn't a current source position."); |
| 30 | + } |
| 31 | + |
| 32 | + const currentDocument = currentEditor.document; |
| 33 | + if (currentDocument.isDirty) { |
| 34 | + throw new Error("The current document has unsaved edits."); |
| 35 | + } |
| 36 | + |
| 37 | + const gotoTargetsArg : DebugProtocol.GotoTargetsArguments = { |
| 38 | + source: { |
| 39 | + // NOTE: in the case of embedded documents, this is the rather odd value of something like the following, |
| 40 | + // but vsdbg-ui is okay with it, so I guess we will leave it. |
| 41 | + // "Source file extracted from PDB file. Original path: C:\Debuggee-Libraries-Build-Dir\EmbeddedSourceTest\Class1\Main.cs" |
| 42 | + path: currentDocument.uri.fsPath |
| 43 | + }, |
| 44 | + line: position.line + 1, |
| 45 | + column: position.character + 1 |
| 46 | + }; |
| 47 | + |
| 48 | + const gotoTargetsResponseBody = await debugSession.customRequest('gotoTargets', gotoTargetsArg); |
| 49 | + const targets: DebugProtocol.GotoTarget[] = gotoTargetsResponseBody.targets; |
| 50 | + if (targets.length === 0) { |
| 51 | + throw new Error(`No executable code is associated with line ${gotoTargetsArg.line}.`); |
| 52 | + } |
| 53 | + |
| 54 | + let selectedTarget = targets[0]; |
| 55 | + |
| 56 | + if (targets.length > 1) { |
| 57 | + |
| 58 | + // If we have multiple possible targets, then let the user pick. |
| 59 | + const labelDict: { [key: string]: DebugProtocol.GotoTarget } = SetNextStatementHelpers.makeLabelsUnique(targets); |
| 60 | + const labels : string[] = targets.map((target) => target.label); |
| 61 | + |
| 62 | + const options: vscode.QuickPickOptions = { |
| 63 | + matchOnDescription: true, |
| 64 | + placeHolder: "Choose the specific location" |
| 65 | + }; |
| 66 | + |
| 67 | + const selectedLabelName : string = await vscode.window.showQuickPick(labels, options); |
| 68 | + if (!selectedLabelName) { |
| 69 | + return; // operation was cancelled |
| 70 | + } |
| 71 | + selectedTarget = labelDict[selectedLabelName]; |
| 72 | + } |
| 73 | + |
| 74 | + // NOTE: we don't have a thread id, so this doesn't furfill the contract of 'GotoArguments'. So we will make vsdbg-ui guess the thread id. |
| 75 | + // The following bug tracks fixing this the right way: https://github.com/Microsoft/vscode/issues/63943 |
| 76 | + const gotoArg /*: DebugProtocol.GotoArguments*/ = { |
| 77 | + targetId: selectedTarget.id |
| 78 | + }; |
| 79 | + |
| 80 | + await debugSession.customRequest('goto', gotoArg); |
| 81 | + } |
| 82 | + catch (err) { |
| 83 | + vscode.window.showErrorMessage(`Unable to set the next statement. ${err}`); |
| 84 | + } |
| 85 | +} |
0 commit comments