Skip to content

Commit c776b83

Browse files
committed
Rework breakpoint implementation
1 parent 2b8d7f9 commit c776b83

File tree

4 files changed

+77
-24
lines changed

4 files changed

+77
-24
lines changed

src/actions/ToggleBreakpoint.ts

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Range } from "@cursorless/common";
1+
import { BreakpointDescriptor } from "../libs/common/types/TextEditor";
22
import ide from "../libs/cursorless-engine/singletons/ide.singleton";
33
import { containingLineIfUntypedStage } from "../processTargets/modifiers/commonContainingScopeIfUntypedStages";
44
import { Target } from "../typings/target.types";
@@ -22,16 +22,25 @@ export default class ToggleBreakpoint implements Action {
2222
);
2323

2424
await runOnTargetsForEachEditor(targets, async (editor, targets) => {
25-
const ranges = targets.map((target) => {
26-
const range = target.contentRange;
27-
// The action preference give us line content but line breakpoints are registered on character 0
28-
if (target.isLine) {
29-
return new Range(range.start.line, 0, range.end.line, 0);
30-
}
31-
return range;
32-
});
25+
const breakpointDescriptors: BreakpointDescriptor[] = targets.map(
26+
(target) => {
27+
const range = target.contentRange;
28+
return target.isLine
29+
? {
30+
type: "line",
31+
startLine: range.start.line,
32+
endLine: range.end.line,
33+
}
34+
: {
35+
type: "inline",
36+
range,
37+
};
38+
},
39+
);
3340

34-
await ide().getEditableTextEditor(editor).toggleBreakpoint(ranges);
41+
await ide()
42+
.getEditableTextEditor(editor)
43+
.toggleBreakpoint(breakpointDescriptors);
3544
});
3645

3746
return {

src/ide/vscode/VscodeTextEditorImpl.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import {
2+
BreakpointDescriptor,
23
EditableTextEditor,
34
Position,
45
Range,
@@ -127,8 +128,8 @@ export class VscodeTextEditorImpl implements EditableTextEditor {
127128
return vscodeUnfold(this.ide, this, ranges);
128129
}
129130

130-
public toggleBreakpoint(ranges?: Range[]): Promise<void> {
131-
return vscodeToggleBreakpoint(this, ranges);
131+
public toggleBreakpoint(descriptors?: BreakpointDescriptor[]): Promise<void> {
132+
return vscodeToggleBreakpoint(this, descriptors);
132133
}
133134

134135
public async toggleLineComment(_ranges?: Range[]): Promise<void> {
Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,36 @@
1-
import { Range } from "@cursorless/common";
1+
import { BreakpointDescriptor } from "@cursorless/common";
22
import { toVscodeRange } from "@cursorless/vscode-common";
33
import * as vscode from "vscode";
44
import { VscodeTextEditorImpl } from "./VscodeTextEditorImpl";
55

66
export async function vscodeToggleBreakpoint(
77
editor: VscodeTextEditorImpl,
8-
ranges: Range[] | undefined,
8+
descriptors: BreakpointDescriptor[] | undefined,
99
): Promise<void> {
10+
if (descriptors == null) {
11+
return await vscode.commands.executeCommand(
12+
"editor.debug.action.toggleBreakpoint",
13+
);
14+
}
15+
1016
const uri = editor.document.uri;
1117
const toAdd: vscode.Breakpoint[] = [];
1218
const toRemove: vscode.Breakpoint[] = [];
13-
const actualRanges = ranges ?? editor.selections;
1419

15-
actualRanges.forEach((range) => {
16-
const vscodeRange = toVscodeRange(range);
17-
const existing = getBreakpoints(uri, vscodeRange);
20+
descriptors.forEach((descriptor) => {
21+
const existing = getBreakpoints(uri, descriptor);
1822
if (existing.length > 0) {
1923
toRemove.push(...existing);
2024
} else {
2125
toAdd.push(
22-
new vscode.SourceBreakpoint(new vscode.Location(uri, vscodeRange)),
26+
new vscode.SourceBreakpoint(
27+
new vscode.Location(
28+
uri,
29+
descriptor.type === "line"
30+
? new vscode.Range(descriptor.startLine, 0, descriptor.endLine, 0)
31+
: toVscodeRange(descriptor.range),
32+
),
33+
),
2334
);
2435
}
2536
});
@@ -28,11 +39,22 @@ export async function vscodeToggleBreakpoint(
2839
vscode.debug.removeBreakpoints(toRemove);
2940
}
3041

31-
function getBreakpoints(uri: vscode.Uri, range: vscode.Range) {
42+
function getBreakpoints(uri: vscode.Uri, descriptor: BreakpointDescriptor) {
43+
let descriptorIntersectsRange: (range: vscode.Range) => boolean;
44+
45+
if (descriptor.type === "line") {
46+
descriptorIntersectsRange = ({ start, end }) =>
47+
descriptor.startLine <= start.line && descriptor.endLine >= end.line;
48+
} else {
49+
const descriptorRange = toVscodeRange(descriptor.range);
50+
descriptorIntersectsRange = (range) =>
51+
range.intersection(descriptorRange) != null;
52+
}
53+
3254
return vscode.debug.breakpoints.filter(
3355
(breakpoint) =>
3456
breakpoint instanceof vscode.SourceBreakpoint &&
3557
breakpoint.location.uri.toString() === uri.toString() &&
36-
breakpoint.location.range.intersection(range) != null,
58+
descriptorIntersectsRange(breakpoint.location.range),
3759
);
3860
}

src/libs/common/types/TextEditor.ts

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -155,10 +155,13 @@ export interface EditableTextEditor extends TextEditor {
155155
clipboardPaste(ranges?: Range[]): Promise<void>;
156156

157157
/**
158-
* Toggle breakpoints
159-
* @param ranges A list of {@link Range ranges}
158+
* Toggle breakpoints. For each of the descriptors in {@link descriptors},
159+
* remove all breakpoints overlapping with the given descriptor if it overlaps
160+
* with any existing breakpoint, otherwise add a new breakpoint at the given
161+
* location.
162+
* @param descriptors A list of breakpoint descriptors
160163
*/
161-
toggleBreakpoint(ranges?: Range[]): Promise<void>;
164+
toggleBreakpoint(descriptors?: BreakpointDescriptor[]): Promise<void>;
162165

163166
/**
164167
* Toggle line comments
@@ -239,3 +242,21 @@ export interface EditableTextEditor extends TextEditor {
239242
*/
240243
extractVariable(range?: Range): Promise<void>;
241244
}
245+
246+
interface LineBreakpointDescriptor {
247+
type: "line";
248+
startLine: number;
249+
/**
250+
* Last line, inclusive
251+
*/
252+
endLine: number;
253+
}
254+
255+
interface InlineBreakpointDescriptor {
256+
type: "inline";
257+
range: Range;
258+
}
259+
260+
export type BreakpointDescriptor =
261+
| LineBreakpointDescriptor
262+
| InlineBreakpointDescriptor;

0 commit comments

Comments
 (0)