Skip to content

Commit d016357

Browse files
Improve out of range error (#2755)
`Scope index out of range` is a bit confusing. At least add the scope type and witch index to the error message. Fixes #1540 ## Checklist - [/] I have added [tests](https://www.cursorless.org/docs/contributing/test-case-recorder/) - [/] I have updated the [docs](https://github.com/cursorless-dev/cursorless/tree/main/docs) and [cheatsheet](https://github.com/cursorless-dev/cursorless/tree/main/cursorless-talon/src/cheatsheet) - [/] I have not broken the cheatsheet --------- Co-authored-by: Phil Cohen <[email protected]>
1 parent a5e8366 commit d016357

File tree

6 files changed

+35
-13
lines changed

6 files changed

+35
-13
lines changed

packages/cursorless-engine/src/processTargets/modifiers/InstanceStage.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,11 @@ export class InstanceStage implements ModifierStage {
5555

5656
private handleOrdinalScope(
5757
target: Target,
58-
{ start, length }: OrdinalScopeModifier,
58+
{ start, length, scopeType }: OrdinalScopeModifier,
5959
): Target[] {
6060
return this.getEveryRanges(target).flatMap(([editor, searchRange]) =>
6161
takeFromOffset(
62+
scopeType,
6263
this.getTargetIterable(
6364
target,
6465
editor,
@@ -73,7 +74,7 @@ export class InstanceStage implements ModifierStage {
7374

7475
private handleRelativeScope(
7576
target: Target,
76-
{ direction, offset, length }: RelativeScopeModifier,
77+
{ direction, offset, length, scopeType }: RelativeScopeModifier,
7778
): Target[] {
7879
const referenceTargets = this.storedTargets.get("instanceReference") ?? [
7980
target,
@@ -97,6 +98,7 @@ export class InstanceStage implements ModifierStage {
9798
);
9899

99100
return takeFromOffset(
101+
scopeType,
100102
this.getTargetIterable(target, editor, iterationRange, direction),
101103
offset === 0 ? 0 : offset - 1,
102104
length,
@@ -206,6 +208,7 @@ function getFilterScopeType(target: Target): ScopeType | null {
206208
* starting at `offset`
207209
*/
208210
function takeFromOffset<T>(
211+
scopeType: ScopeType,
209212
iterable: Iterable<T>,
210213
offset: number,
211214
count: number,
@@ -217,7 +220,7 @@ function takeFromOffset<T>(
217220
const items = Array.from(itake(count, iterable));
218221

219222
if (items.length < count) {
220-
throw new OutOfRangeError();
223+
throw new OutOfRangeError(scopeType, offset + count - 1);
221224
}
222225

223226
return items;

packages/cursorless-engine/src/processTargets/modifiers/OrdinalScopeStage.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ import type { OrdinalScopeModifier } from "@cursorless/common";
22
import type { Target } from "../../typings/target.types";
33
import type { ModifierStageFactory } from "../ModifierStageFactory";
44
import type { ModifierStage } from "../PipelineStages.types";
5+
import { sliceStrict } from "./listUtils";
56
import {
67
createRangeTargetFromIndices,
78
getEveryScopeTargets,
89
} from "./targetSequenceUtils";
9-
import { sliceStrict } from "./listUtils";
1010

1111
export class OrdinalScopeStage implements ModifierStage {
1212
constructor(
@@ -26,11 +26,17 @@ export class OrdinalScopeStage implements ModifierStage {
2626
const endIndex = startIndex + this.modifier.length - 1;
2727

2828
if (this.modifier.isEvery) {
29-
return sliceStrict(targets, startIndex, endIndex);
29+
return sliceStrict(
30+
this.modifier.scopeType,
31+
targets,
32+
startIndex,
33+
endIndex,
34+
);
3035
}
3136

3237
return [
3338
createRangeTargetFromIndices(
39+
this.modifier.scopeType,
3440
target.isReversed,
3541
targets,
3642
startIndex,

packages/cursorless-engine/src/processTargets/modifiers/RelativeScopeStage.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,10 @@ export class RelativeScopeStage implements ModifierStage {
4747
);
4848

4949
if (scopes.length < this.modifier.length) {
50-
throw new OutOfRangeError();
50+
throw new OutOfRangeError(
51+
this.modifier.scopeType,
52+
this.modifier.offset + this.modifier.length - 1,
53+
);
5154
}
5255

5356
const { isReversed } = target;
Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,35 @@
1+
import type { ScopeType } from "@cursorless/common";
2+
13
export class OutOfRangeError extends Error {
2-
constructor() {
3-
super("Scope index out of range");
4+
constructor(scopeType: ScopeType, index?: number) {
5+
const numberStr = index != null ? ` #${index + 1}` : "";
6+
super(`Scope '${scopeType.type}'${numberStr} is out of range`);
47
this.name = "OutOfRangeError";
58
}
69
}
710

811
/** Slice list of by given indices */
912
export function sliceStrict<T>(
13+
scopeType: ScopeType,
1014
targets: T[],
1115
startIndex: number,
1216
endIndex: number,
1317
): T[] {
14-
assertIndices(targets, startIndex, endIndex);
18+
assertIndices(scopeType, targets, startIndex, endIndex);
1519

1620
return targets.slice(startIndex, endIndex + 1);
1721
}
1822

1923
export function assertIndices<T>(
24+
scopeType: ScopeType,
2025
targets: T[],
2126
startIndex: number,
2227
endIndex: number,
2328
): void {
24-
if (startIndex < 0 || endIndex >= targets.length) {
25-
throw new OutOfRangeError();
29+
if (startIndex < 0 || startIndex >= targets.length) {
30+
throw new OutOfRangeError(scopeType, startIndex);
31+
}
32+
if (endIndex < 0 || endIndex >= targets.length) {
33+
throw new OutOfRangeError(scopeType, endIndex);
2634
}
2735
}

packages/cursorless-engine/src/processTargets/modifiers/relativeScopeLegacy.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ function calculateIndicesAndCreateTarget(
7272

7373
return [
7474
createRangeTargetFromIndices(
75+
modifier.scopeType,
7576
target.isReversed,
7677
targets,
7778
startIndex,
@@ -108,7 +109,7 @@ function computeProximalIndex(
108109
);
109110

110111
if (adjacentTargetIndex === -1) {
111-
throw new OutOfRangeError();
112+
throw new OutOfRangeError(modifier.scopeType);
112113
}
113114

114115
// For convenience, if they ask to include intersecting indices, we just

packages/cursorless-engine/src/processTargets/modifiers/targetSequenceUtils.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,13 @@ import { assertIndices } from "./listUtils";
1414
* end of the range
1515
*/
1616
export function createRangeTargetFromIndices(
17+
scopeType: ScopeType,
1718
isReversed: boolean,
1819
targets: Target[],
1920
startIndex: number,
2021
endIndex: number,
2122
): Target {
22-
assertIndices(targets, startIndex, endIndex);
23+
assertIndices(scopeType, targets, startIndex, endIndex);
2324

2425
if (startIndex === endIndex) {
2526
return targets[startIndex];

0 commit comments

Comments
 (0)