Skip to content

Commit 26d2a33

Browse files
committed
src/debugAdapter: indicate that conditional breakpoints are supported
Set supportsConditionalBreakpoints to be true on initialization to let clients of the debug adapter know that we provide this capability. Test that the capability is true and run a simple test for stopping on conditional breakpoints. Updates #781 Change-Id: I7b1dd5156fd346bb293582914fd809fabed368d1 Reviewed-on: https://go-review.googlesource.com/c/vscode-go/+/262346 Trust: Suzy Mueller <suzmue@golang.org> Run-TryBot: Suzy Mueller <suzmue@golang.org> TryBot-Result: kokoro <noreply+kokoro@google.com> Reviewed-by: Polina Sokolova <polina@google.com>
1 parent 8fc4183 commit 26d2a33

File tree

4 files changed

+194
-2
lines changed

4 files changed

+194
-2
lines changed

src/debugAdapter/goDebug.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -825,7 +825,8 @@ export class GoDebugSession extends LoggingDebugSession {
825825
args: DebugProtocol.InitializeRequestArguments
826826
): void {
827827
log('InitializeRequest');
828-
// This debug adapter implements the configurationDoneRequest.
828+
// Set the capabilities that this debug adapter supports.
829+
response.body.supportsConditionalBreakpoints = true;
829830
response.body.supportsConfigurationDoneRequest = true;
830831
response.body.supportsSetVariable = true;
831832
this.sendResponse(response);

test/fixtures/condbp/condbp.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package main
2+
3+
import "fmt"
4+
5+
func main() {
6+
for i := 0; i < 4; i++ {
7+
fmt.Printf("i = %d\n", i)
8+
}
9+
}

test/fixtures/condbp/go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module github.com/microsoft/vscode-go/gofixtures/condbp
2+
3+
go 1.14

test/integration/goDebug.test.ts

Lines changed: 180 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import * as fs from 'fs';
33
import * as path from 'path';
44
import * as sinon from 'sinon';
55
import {DebugClient} from 'vscode-debugadapter-testsupport';
6-
import { ILocation } from 'vscode-debugadapter-testsupport/lib/debugClient';
76
import {DebugProtocol} from 'vscode-debugprotocol';
87
import {
98
Delve,
@@ -313,7 +312,9 @@ suite('Go Debug Adapter', function () {
313312
test('should return supported features', () => {
314313
return dc.initializeRequest().then((response) => {
315314
response.body = response.body || {};
315+
assert.strictEqual(response.body.supportsConditionalBreakpoints, true);
316316
assert.strictEqual(response.body.supportsConfigurationDoneRequest, true);
317+
assert.strictEqual(response.body.supportsSetVariable, true);
317318
});
318319
});
319320

@@ -491,6 +492,184 @@ suite('Go Debug Adapter', function () {
491492

492493
});
493494

495+
suite('conditionalBreakpoints', () => {
496+
test('should stop on conditional breakpoint', () => {
497+
498+
const PROGRAM = path.join(DATA_ROOT, 'condbp');
499+
const FILE = path.join(DATA_ROOT, 'condbp', 'condbp.go');
500+
const BREAKPOINT_LINE = 7;
501+
const location = getBreakpointLocation(FILE, BREAKPOINT_LINE);
502+
503+
const config = {
504+
name: 'Launch',
505+
type: 'go',
506+
request: 'launch',
507+
mode: 'auto',
508+
program: PROGRAM,
509+
};
510+
const debugConfig = debugConfigProvider.resolveDebugConfiguration(undefined, config);
511+
return Promise.all([
512+
513+
dc.waitForEvent('initialized').then(() => {
514+
return dc.setBreakpointsRequest({
515+
lines: [ location.line ],
516+
breakpoints: [ { line: location.line, condition: 'i == 2' } ],
517+
source: { path: location.path }
518+
});
519+
}).then(() => {
520+
return dc.configurationDoneRequest();
521+
}),
522+
523+
dc.launch(debugConfig),
524+
525+
dc.assertStoppedLocation('breakpoint', location)
526+
527+
]).then(() =>
528+
// The program is stopped at the breakpoint, check to make sure 'i == 1'.
529+
dc.threadsRequest().then((threadsResponse) =>
530+
dc.stackTraceRequest({threadId: threadsResponse.body.threads[0].id}).then((stackTraceResponse) =>
531+
dc.scopesRequest({frameId: stackTraceResponse.body.stackFrames[0].id}).then((scopesResponse) =>
532+
dc.variablesRequest({variablesReference: scopesResponse.body.scopes[0].variablesReference})
533+
.then((variablesResponse) => {
534+
assert.strictEqual(variablesResponse.body.variables[0].name, 'i');
535+
assert.strictEqual(variablesResponse.body.variables[0].value, '2');
536+
})
537+
)
538+
)
539+
)
540+
);
541+
});
542+
543+
test('should add breakpoint condition', async () => {
544+
545+
const PROGRAM = path.join(DATA_ROOT, 'condbp');
546+
const FILE = path.join(DATA_ROOT, 'condbp', 'condbp.go');
547+
const BREAKPOINT_LINE = 7;
548+
const location = getBreakpointLocation(FILE, BREAKPOINT_LINE);
549+
550+
const config = {
551+
name: 'Launch',
552+
type: 'go',
553+
request: 'launch',
554+
mode: 'auto',
555+
program: PROGRAM,
556+
};
557+
const debugConfig = debugConfigProvider.resolveDebugConfiguration(undefined, config);
558+
559+
return dc.hitBreakpoint(debugConfig, location).then(() =>
560+
// The program is stopped at the breakpoint, check to make sure 'i == 0'.
561+
dc.threadsRequest().then((threadsResponse) =>
562+
dc.stackTraceRequest({threadId: threadsResponse.body.threads[0].id}).then((stackTraceResponse) =>
563+
dc.scopesRequest({frameId: stackTraceResponse.body.stackFrames[0].id}).then((scopesResponse) =>
564+
dc.variablesRequest({variablesReference: scopesResponse.body.scopes[0].variablesReference})
565+
.then((variablesResponse) => {
566+
assert.strictEqual(variablesResponse.body.variables[0].name, 'i');
567+
assert.strictEqual(variablesResponse.body.variables[0].value, '0');
568+
})
569+
)
570+
)
571+
)
572+
).then(() =>
573+
// Add a condition to the breakpoint, and make sure it runs until 'i == 2'.
574+
dc.setBreakpointsRequest({
575+
lines: [ location.line ],
576+
breakpoints: [ { line: location.line, condition: 'i == 2' } ],
577+
source: { path: location.path }
578+
}).then(() =>
579+
Promise.all([
580+
dc.continueRequest({threadId: 1}),
581+
dc.assertStoppedLocation('breakpoint', location)
582+
]).then(() =>
583+
// The program is stopped at the breakpoint, check to make sure 'i == 2'.
584+
dc.threadsRequest().then((threadsResponse) =>
585+
dc.stackTraceRequest({threadId: threadsResponse.body.threads[0].id}).then((stackTraceResponse) =>
586+
dc.scopesRequest({frameId: stackTraceResponse.body.stackFrames[0].id}).then((scopesResponse) =>
587+
dc.variablesRequest({variablesReference: scopesResponse.body.scopes[0].variablesReference})
588+
.then((variablesResponse) => {
589+
assert.strictEqual(variablesResponse.body.variables[0].name, 'i');
590+
assert.strictEqual(variablesResponse.body.variables[0].value, '2');
591+
})
592+
)
593+
)
594+
)
595+
)
596+
)
597+
);
598+
});
599+
600+
test('should remove breakpoint condition', () => {
601+
602+
const PROGRAM = path.join(DATA_ROOT, 'condbp');
603+
const FILE = path.join(DATA_ROOT, 'condbp', 'condbp.go');
604+
const BREAKPOINT_LINE = 7;
605+
const location = getBreakpointLocation(FILE, BREAKPOINT_LINE);
606+
607+
const config = {
608+
name: 'Launch',
609+
type: 'go',
610+
request: 'launch',
611+
mode: 'auto',
612+
program: PROGRAM,
613+
};
614+
const debugConfig = debugConfigProvider.resolveDebugConfiguration(undefined, config);
615+
return Promise.all([
616+
617+
dc.waitForEvent('initialized').then(() => {
618+
return dc.setBreakpointsRequest({
619+
lines: [ location.line ],
620+
breakpoints: [ { line: location.line, condition: 'i == 2' } ],
621+
source: { path: location.path }
622+
});
623+
}).then(() => {
624+
return dc.configurationDoneRequest();
625+
}),
626+
627+
dc.launch(debugConfig),
628+
629+
dc.assertStoppedLocation('breakpoint', location)
630+
631+
]).then(() =>
632+
// The program is stopped at the breakpoint, check to make sure 'i == 2'.
633+
dc.threadsRequest().then((threadsResponse) =>
634+
dc.stackTraceRequest({threadId: threadsResponse.body.threads[0].id}).then((stackTraceResponse) =>
635+
dc.scopesRequest({frameId: stackTraceResponse.body.stackFrames[0].id}).then((scopesResponse) =>
636+
dc.variablesRequest({variablesReference: scopesResponse.body.scopes[0].variablesReference})
637+
.then((variablesResponse) => {
638+
assert.strictEqual(variablesResponse.body.variables[0].name, 'i');
639+
assert.strictEqual(variablesResponse.body.variables[0].value, '2');
640+
})
641+
)
642+
)
643+
)
644+
).then(() =>
645+
// Remove the breakpoint condition, and make sure the program runs until 'i == 3'.
646+
dc.setBreakpointsRequest({
647+
lines: [ location.line ],
648+
breakpoints: [ { line: location.line } ],
649+
source: { path: location.path }
650+
}).then(() =>
651+
Promise.all([
652+
dc.continueRequest({threadId: 1}),
653+
dc.assertStoppedLocation('breakpoint', location)
654+
]).then(() =>
655+
// The program is stopped at the breakpoint, check to make sure 'i == 3'.
656+
dc.threadsRequest().then((threadsResponse) =>
657+
dc.stackTraceRequest({threadId: threadsResponse.body.threads[0].id}).then((stackTraceResponse) =>
658+
dc.scopesRequest({frameId: stackTraceResponse.body.stackFrames[0].id}).then((scopesResponse) =>
659+
dc.variablesRequest({variablesReference: scopesResponse.body.scopes[0].variablesReference})
660+
.then((variablesResponse) => {
661+
assert.strictEqual(variablesResponse.body.variables[0].name, 'i');
662+
assert.strictEqual(variablesResponse.body.variables[0].value, '3');
663+
})
664+
)
665+
)
666+
)
667+
)
668+
)
669+
);
670+
});
671+
});
672+
494673
suite('panicBreakpoints', () => {
495674

496675
test('should stop on panic', () => {

0 commit comments

Comments
 (0)