Skip to content

Commit

Permalink
Allow debug configs to be added to launch.json from the Invocation Pa…
Browse files Browse the repository at this point in the history
…nel. Fixes #45 (#109)

* Allow debug configs to be added to launch.json from the Invocation Panel. Fixes #45

* fix UI after merge
  • Loading branch information
djnicholson authored Feb 25, 2020
1 parent 8d7ebf9 commit 883d251
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 5 deletions.
58 changes: 55 additions & 3 deletions src/invocationPanel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -188,10 +188,16 @@ export class InvocationPanel {
this.panel.webview.postMessage({ viewState: this.viewState });
} else if (message.e === invokeEvents.Debug) {
this.viewState.invocationError = undefined;
if (!(await this.startDebugging(message.c))) {
if (!(await this.startDebugging(message.c, false))) {
this.viewState.invocationError = this.viewState.invocationError || 'There was an error launching the debugger.';
this.panel.webview.postMessage({ viewState: this.viewState });
}
} else if (message.e === invokeEvents.AddDebugConfig) {
this.viewState.invocationError = undefined;
if (!(await this.startDebugging(message.c, true))) {
this.viewState.invocationError = this.viewState.invocationError || 'There was an error creating the debug configuration.';
this.panel.webview.postMessage({ viewState: this.viewState });
}
} else if (message.e === invokeEvents.Search) {
await this.startSearch(message.c);
}
Expand Down Expand Up @@ -297,7 +303,7 @@ export class InvocationPanel {
}
}

private async startDebugging(methodName: string) {
private async startDebugging(methodName: string, addToLaunchJson: boolean) {
try {
for (let i = 0; i < this.viewState.contracts.length; i++) {
const contractHash = this.viewState.contracts[i].hash;
Expand Down Expand Up @@ -344,7 +350,11 @@ export class InvocationPanel {
if (method.selectedCheckpoint) {
debugConfiguration['checkpoint'] = method.selectedCheckpoint;
}
return await vscode.debug.startDebugging(undefined, debugConfiguration);
if (addToLaunchJson) {
return await this.addToLaunchJson(debugConfiguration);
} else {
return await vscode.debug.startDebugging(undefined, debugConfiguration);
}
} else {
this.viewState.invocationError = 'Could not find an AVM file for this contract in the current workspace.';
return false;
Expand All @@ -362,6 +372,48 @@ export class InvocationPanel {
return false;
}

private async addToLaunchJson(debugConfiguration: vscode.DebugConfiguration) {
if (!vscode.workspace.workspaceFolders || !vscode.workspace.workspaceFolders.length) {
this.viewState.invocationError = 'The current workspace does not contain any folders.';
return false;
}

let workspaceFolder = vscode.workspace.workspaceFolders[0].uri;
if (vscode.workspace.workspaceFolders.length > 1) {
const selectedWorkspace = await vscode.window.showQuickPick(
vscode.workspace.workspaceFolders.map(_ => _.uri.toString()),
{ placeHolder: 'Select a workspace folder' });
if (!selectedWorkspace) {
this.viewState.invocationError = 'A workspace folder must be selected.';
return false;
}
workspaceFolder = vscode.Uri.parse(selectedWorkspace);
}
const config = vscode.workspace.getConfiguration('launch', workspaceFolder);
const debugConfigurations = config.configurations || [];

const desiredName = debugConfiguration.name;
let deDuplicationIndex = 0;
while (debugConfigurations.find((_: vscode.DebugConfiguration) => _.name === debugConfiguration.name)) {
deDuplicationIndex++;
debugConfiguration.name = desiredName + '-' + deDuplicationIndex;
}

const workspaceFolderString = workspaceFolder.fsPath.toString();
if (debugConfiguration.program && debugConfiguration.program.startsWith(workspaceFolderString)) {
debugConfiguration.program = '${workspaceFolder}' + debugConfiguration.program.substr(workspaceFolderString.length);
}
if (debugConfiguration.checkpoint && debugConfiguration.checkpoint.startsWith(workspaceFolderString)) {
debugConfiguration.checkpoint = '${workspaceFolder}' + debugConfiguration.checkpoint.substr(workspaceFolderString.length);
}

debugConfigurations.push(debugConfiguration);
await config.update('configurations', debugConfigurations, vscode.ConfigurationTarget.WorkspaceFolder);
await vscode.window.showTextDocument(
await vscode.workspace.openTextDocument(path.join(workspaceFolderString, '.vscode', 'launch.json')));
return true;
}

private static extractArguments(parameters: any[]) {
if (parameters.length === 0) {
return undefined;
Expand Down
5 changes: 4 additions & 1 deletion src/panels/invoke.html
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,10 @@ <h5>Launch contract in debugger</h5>
</tr>
</table>
<div class="text-right">
<button class="launchDebugger">Debug</button>
<button class="launchDebugger">Debug now</button>
</div>
<div class="text-right m-t">
<button class="addDebugConfig">Save debug configuration</button>
</div>
</div>
<div class="group">
Expand Down
7 changes: 6 additions & 1 deletion src/panels/invoke.scss
Original file line number Diff line number Diff line change
Expand Up @@ -244,4 +244,9 @@ ul {
width: 70%;
margin: 0px;
overflow: auto;
}
}

/* Helper class to add a top margin to any element: */
.m-t {
margin-top: 5px;
}
1 change: 1 addition & 0 deletions src/panels/invokeEvents.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ const invokeEvents = {
Update: 'update',
Dismiss: 'dismiss',
Debug: 'debug',
AddDebugConfig: 'addDebugConfig',
Search: 'search',
};

Expand Down
4 changes: 4 additions & 0 deletions src/panels/invokeRenderers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,10 @@ const invokeRenderers = {
if (launchDebuggerButton) {
htmlHelpers.setOnClickEvent(launchDebuggerButton, invokeEvents.Debug, methodData.name, postMessage);
}
const addDebugConfigButton = thisMethodDetail.querySelector(invokeSelectors.AddDebugConfigButton);
if (addDebugConfigButton) {
htmlHelpers.setOnClickEvent(addDebugConfigButton, invokeEvents.AddDebugConfig, methodData.name, postMessage);
}
const invokeOffChainButton = thisMethodDetail.querySelector(invokeSelectors.InvokeOffChainButton);
if (invokeOffChainButton) {
htmlHelpers.setOnClickEvent(invokeOffChainButton, invokeEvents.InvokeOffChain, methodData.name, postMessage);
Expand Down
1 change: 1 addition & 0 deletions src/panels/invokeSelectors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const invokeSelectors = {
InvokeOnChainButton: '.invokeOnChainButton',
InvokeOffChainButton: '.invokeOffChainButton',
LaunchDebuggerButton: '.launchDebugger',
AddDebugConfigButton: '.addDebugConfig',
InvocationResultPopup: '#invocationResultPopup',
InvocationResultGasUsed: '#gas-used-value',
InvocationResultVMState: '#vm-state-value',
Expand Down

0 comments on commit 883d251

Please sign in to comment.