Skip to content

Commit 5694551

Browse files
Reworked weak target (#888)
* Renamed weak target, Renamed is weak, Added explicit range attribute * Don't remove leading or trailing delimited ranges for empty selection * Added clone parameters * Updated comment * Always create continuous range * Renamed UnTypedRangeTarget to UnTypedTarget * Process targets before test recorded command hook * Added tests * Renamed to ifUntyped * Added item tests * Cleanup * Update src/typings/targetDescriptor.types.ts Co-authored-by: Pokey Rule <[email protected]> * Update src/typings/targetDescriptor.types.ts Co-authored-by: Pokey Rule <[email protected]> * Cleanup * Cleanup * Added tests * Cleanup * Added tests * added tests * Use undefined return value in error test cases * Docstring * Better error type for no inside / bounds * Remove code sharing from ThatStage and CursorStage * Doc strings * Switch test subset * Fix docstring link * Record alternate "leading funk" test * Record some more tests * Add a bunch of tests * Cleaned up from review * Docstring * More tests * One more test * Another test * Rollback imports to avoid circular import * Improve test * Revert "Rollback imports to avoid circular import" This reverts commit 9ad7e9f. * Fix imports * Add tests; fix bug with `"every block"` * Minor tweak * Fix doc * Docstrings Co-authored-by: Pokey Rule <[email protected]>
1 parent a1a52e4 commit 5694551

File tree

125 files changed

+3668
-217
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

125 files changed

+3668
-217
lines changed

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -546,6 +546,7 @@
546546
"@types/vscode": "~1.61.0",
547547
"@typescript-eslint/eslint-plugin": "^5.20.0",
548548
"@typescript-eslint/parser": "^5.20.0",
549+
"@vscode/test-electron": "^2.1.3",
549550
"esbuild": "^0.11.12",
550551
"eslint": "^8.13.0",
551552
"eslint-config-prettier": "^8.5.0",
@@ -558,8 +559,7 @@
558559
"semver": "^7.3.7",
559560
"sinon": "^11.1.1",
560561
"ts-unused-exports": "8.0.0",
561-
"typescript": "^4.5.5",
562-
"@vscode/test-electron": "^2.1.3"
562+
"typescript": "^4.5.5"
563563
},
564564
"dependencies": {
565565
"@types/lodash": "^4.14.168",

src/actions/EditNew/EditNew.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { weakContainingLineStage } from "../../processTargets/modifiers/commonWeakContainingScopeStages";
1+
import { containingLineIfUntypedStage } from "../../processTargets/modifiers/commonContainingScopeIfUntypedStages";
22
import PositionStage from "../../processTargets/modifiers/PositionStage";
33
import { ModifierStage } from "../../processTargets/PipelineStages.types";
44
import { Target } from "../../typings/target.types";
@@ -14,7 +14,7 @@ import { runEditTargets } from "./runEditTargets";
1414

1515
export class EditNew implements Action {
1616
getFinalStages(): ModifierStage[] {
17-
return [weakContainingLineStage];
17+
return [containingLineIfUntypedStage];
1818
}
1919

2020
constructor(private graph: Graph) {

src/actions/InsertCopy.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
import { flatten, zip } from "lodash";
22
import { DecorationRangeBehavior, Selection, TextEditor } from "vscode";
33
import { performEditsAndUpdateSelectionsWithBehavior } from "../core/updateSelections/updateSelections";
4-
import { weakContainingLineStage } from "../processTargets/modifiers/commonWeakContainingScopeStages";
4+
import { containingLineIfUntypedStage } from "../processTargets/modifiers/commonContainingScopeIfUntypedStages";
55
import { Target } from "../typings/target.types";
66
import { Graph } from "../typings/Types";
77
import { setSelectionsWithoutFocusingEditor } from "../util/setSelectionsAndFocusEditor";
88
import { createThatMark, runOnTargetsForEachEditor } from "../util/targetUtils";
99
import { Action, ActionReturnValue } from "./actions.types";
1010

1111
class InsertCopy implements Action {
12-
getFinalStages = () => [weakContainingLineStage];
12+
getFinalStages = () => [containingLineIfUntypedStage];
1313

1414
constructor(private graph: Graph, private isBefore: boolean) {
1515
this.run = this.run.bind(this);

src/actions/InsertSnippet.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import {
44
callFunctionAndUpdateSelectionInfos,
55
getSelectionInfo,
66
} from "../core/updateSelections/updateSelections";
7-
import ModifyIfWeakStage from "../processTargets/modifiers/ModifyIfWeakStage";
7+
import ModifyIfUntypedStage from "../processTargets/modifiers/ModifyIfUntypedStage";
88
import { Snippet, SnippetDefinition } from "../typings/snippet";
99
import { Target } from "../typings/target.types";
1010
import { Graph } from "../typings/Types";
@@ -29,8 +29,8 @@ export default class InsertSnippet implements Action {
2929
}
3030

3131
return [
32-
new ModifyIfWeakStage({
33-
type: "modifyIfWeak",
32+
new ModifyIfUntypedStage({
33+
type: "modifyIfUntyped",
3434
modifier: {
3535
type: "cascading",
3636
modifiers: defaultScopeTypes.map((scopeType) => ({

src/actions/Rewrap.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
import { performEditsAndUpdateRanges } from "../core/updateSelections/updateSelections";
2-
import { weakContainingSurroundingPairStage } from "../processTargets/modifiers/commonWeakContainingScopeStages";
2+
import { containingSurroundingPairIfUntypedStage } from "../processTargets/modifiers/commonContainingScopeIfUntypedStages";
33
import { Target } from "../typings/target.types";
44
import { Graph } from "../typings/Types";
55
import { createThatMark, runOnTargetsForEachEditor } from "../util/targetUtils";
66
import { Action, ActionReturnValue } from "./actions.types";
77

88
export default class Rewrap implements Action {
9-
getFinalStages = () => [weakContainingSurroundingPairStage];
9+
getFinalStages = () => [containingSurroundingPairIfUntypedStage];
1010

1111
constructor(private graph: Graph) {
1212
this.run = this.run.bind(this);

src/actions/ToggleBreakpoint.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
66
SourceBreakpoint,
77
Uri,
88
} from "vscode";
9-
import { weakContainingLineStage } from "../processTargets/modifiers/commonWeakContainingScopeStages";
9+
import { containingLineIfUntypedStage } from "../processTargets/modifiers/commonContainingScopeIfUntypedStages";
1010
import { Target } from "../typings/target.types";
1111
import { Graph } from "../typings/Types";
1212
import { createThatMark } from "../util/targetUtils";
@@ -22,7 +22,7 @@ function getBreakpoints(uri: Uri, range: Range) {
2222
}
2323

2424
export default class ToggleBreakpoint implements Action {
25-
getFinalStages = () => [weakContainingLineStage];
25+
getFinalStages = () => [containingLineIfUntypedStage];
2626

2727
constructor(private graph: Graph) {
2828
this.run = this.run.bind(this);

src/actions/WrapWithSnippet.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { commands } from "vscode";
22
import { callFunctionAndUpdateSelections } from "../core/updateSelections/updateSelections";
3-
import ModifyIfWeakStage from "../processTargets/modifiers/ModifyIfWeakStage";
3+
import ModifyIfUntypedStage from "../processTargets/modifiers/ModifyIfUntypedStage";
44
import { Target } from "../typings/target.types";
55
import { Graph } from "../typings/Types";
66
import {
@@ -28,8 +28,8 @@ export default class WrapWithSnippet implements Action {
2828
}
2929

3030
return [
31-
new ModifyIfWeakStage({
32-
type: "modifyIfWeak",
31+
new ModifyIfUntypedStage({
32+
type: "modifyIfUntyped",
3333
modifier: {
3434
type: "containingScope",
3535
scopeType: {

src/processTargets/getMarkStage.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,7 @@ import CursorStage from "./marks/CursorStage";
33
import DecoratedSymbolStage from "./marks/DecoratedSymbolStage";
44
import LineNumberStage from "./marks/LineNumberStage";
55
import NothingStage from "./marks/NothingStage";
6-
import SourceStage from "./marks/SourceStage";
7-
import ThatStage from "./marks/ThatStage";
6+
import { SourceStage, ThatStage } from "./marks/ThatStage";
87
import { MarkStage } from "./PipelineStages.types";
98

109
export default (mark: Mark): MarkStage => {

src/processTargets/getModifierStage.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ import {
1212
} from "./modifiers/InteriorStage";
1313
import ItemStage from "./modifiers/ItemStage";
1414
import { LeadingStage, TrailingStage } from "./modifiers/LeadingTrailingStages";
15-
import ModifyIfWeakStage from "./modifiers/ModifyIfWeakStage";
15+
import ModifyIfUntypedStage from "./modifiers/ModifyIfUntypedStage";
1616
import OrdinalRangeSubTokenStage, {
1717
OrdinalRangeSubTokenModifier,
1818
} from "./modifiers/OrdinalRangeSubTokenStage";
@@ -70,8 +70,8 @@ export default (modifier: Modifier): ModifierStage => {
7070
);
7171
case "cascading":
7272
return new CascadingStage(modifier);
73-
case "modifyIfWeak":
74-
return new ModifyIfWeakStage(modifier);
73+
case "modifyIfUntyped":
74+
return new ModifyIfUntypedStage(modifier);
7575
}
7676
};
7777

src/processTargets/marks/CursorStage.ts

Lines changed: 11 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3,24 +3,20 @@ import type { CursorMark } from "../../typings/targetDescriptor.types";
33
import { ProcessedTargetsContext } from "../../typings/Types";
44
import { isReversed } from "../../util/selectionUtils";
55
import { MarkStage } from "../PipelineStages.types";
6-
import WeakTarget from "../targets/WeakTarget";
7-
import TokenTarget from "../targets/TokenTarget";
6+
import UntypedTarget from "../targets/UntypedTarget";
87

98
export default class CursorStage implements MarkStage {
10-
constructor(_modifier: CursorMark) {
11-
// takes mark for consistency and does nothing
12-
}
9+
constructor(private modifier: CursorMark) {}
1310

1411
run(context: ProcessedTargetsContext): Target[] {
15-
return context.currentSelections.map((selection) => {
16-
const parameters = {
17-
editor: selection.editor,
18-
isReversed: isReversed(selection.selection),
19-
contentRange: selection.selection,
20-
};
21-
return selection.selection.isEmpty
22-
? new WeakTarget(parameters)
23-
: new TokenTarget(parameters);
24-
});
12+
return context.currentSelections.map(
13+
(selection) =>
14+
new UntypedTarget({
15+
editor: selection.editor,
16+
isReversed: isReversed(selection.selection),
17+
contentRange: selection.selection,
18+
hasExplicitRange: !selection.selection.isEmpty,
19+
})
20+
);
2521
}
2622
}

src/processTargets/marks/DecoratedSymbolStage.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { Target } from "../../typings/target.types";
22
import { DecoratedSymbolMark } from "../../typings/targetDescriptor.types";
33
import { ProcessedTargetsContext } from "../../typings/Types";
44
import { MarkStage } from "../PipelineStages.types";
5-
import { WeakTarget } from "../targets";
5+
import { UntypedTarget } from "../targets";
66

77
export default class implements MarkStage {
88
constructor(private modifier: DecoratedSymbolMark) {}
@@ -20,10 +20,11 @@ export default class implements MarkStage {
2020
}
2121

2222
return [
23-
new WeakTarget({
23+
new UntypedTarget({
2424
editor: token.editor,
2525
contentRange: token.range,
2626
isReversed: false,
27+
hasExplicitRange: false,
2728
}),
2829
];
2930
}

src/processTargets/marks/SourceStage.ts

Lines changed: 0 additions & 23 deletions
This file was deleted.

src/processTargets/marks/ThatStage.ts

Lines changed: 31 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,45 @@
11
import { Target } from "../../typings/target.types";
2-
import { ThatMark } from "../../typings/targetDescriptor.types";
3-
import { ProcessedTargetsContext } from "../../typings/Types";
2+
import { SourceMark, ThatMark } from "../../typings/targetDescriptor.types";
3+
import {
4+
ProcessedTargetsContext,
5+
SelectionWithEditor,
6+
} from "../../typings/Types";
47
import { isReversed } from "../../util/selectionUtils";
58
import { MarkStage } from "../PipelineStages.types";
6-
import WeakTarget from "../targets/WeakTarget";
9+
import { UntypedTarget } from "../targets";
710

8-
export default class implements MarkStage {
11+
export class ThatStage implements MarkStage {
912
constructor(private modifier: ThatMark) {}
1013

1114
run(context: ProcessedTargetsContext): Target[] {
1215
if (context.thatMark.length === 0) {
1316
throw Error("No available that marks");
1417
}
15-
return context.thatMark.map((selection) => {
16-
return new WeakTarget({
18+
19+
return selectionsToTarget(context.thatMark);
20+
}
21+
}
22+
23+
export class SourceStage implements MarkStage {
24+
constructor(private modifier: SourceMark) {}
25+
26+
run(context: ProcessedTargetsContext): Target[] {
27+
if (context.sourceMark.length === 0) {
28+
throw Error("No available source marks");
29+
}
30+
31+
return selectionsToTarget(context.sourceMark);
32+
}
33+
}
34+
35+
function selectionsToTarget(selections: SelectionWithEditor[]) {
36+
return selections.map(
37+
(selection) =>
38+
new UntypedTarget({
1739
editor: selection.editor,
1840
isReversed: isReversed(selection.selection),
1941
contentRange: selection.selection,
20-
});
21-
});
22-
}
42+
hasExplicitRange: !selection.selection.isEmpty,
43+
})
44+
);
2345
}

src/processTargets/modifiers/InteriorStage.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@ import {
55
} from "../../typings/targetDescriptor.types";
66
import { ProcessedTargetsContext } from "../../typings/Types";
77
import { ModifierStage } from "../PipelineStages.types";
8-
import { weakContainingSurroundingPairStage } from "./commonWeakContainingScopeStages";
8+
import { containingSurroundingPairIfUntypedStage } from "./commonContainingScopeIfUntypedStages";
99

1010
export class InteriorOnlyStage implements ModifierStage {
1111
constructor(private modifier: InteriorOnlyModifier) {}
1212

1313
run(context: ProcessedTargetsContext, target: Target): Target[] {
14-
return weakContainingSurroundingPairStage
14+
return containingSurroundingPairIfUntypedStage
1515
.run(context, target)
1616
.flatMap((target) => target.getInteriorStrict());
1717
}
@@ -21,7 +21,7 @@ export class ExcludeInteriorStage implements ModifierStage {
2121
constructor(private modifier: ExcludeInteriorModifier) {}
2222

2323
run(context: ProcessedTargetsContext, target: Target): Target[] {
24-
return weakContainingSurroundingPairStage
24+
return containingSurroundingPairIfUntypedStage
2525
.run(context, target)
2626
.flatMap((target) => target.getBoundaryStrict());
2727
}

src/processTargets/modifiers/ItemStage/ItemStage.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,10 @@ export default class ItemStage implements ModifierStage {
4040
private getEveryTarget(context: ProcessedTargetsContext, target: Target) {
4141
const itemInfos = getItemInfosForIterationScope(context, target);
4242

43-
// If weak expand to all items in iteration scope
44-
const filteredItemInfos = target.isWeak
45-
? itemInfos
46-
: filterItemInfos(target, itemInfos);
43+
// If target has explicit range filter to items in that range. Otherwise expand to all items in iteration scope.
44+
const filteredItemInfos = target.hasExplicitRange
45+
? filterItemInfos(target, itemInfos)
46+
: itemInfos;
4747

4848
if (filteredItemInfos.length === 0) {
4949
throw new NoContainingScopeError(this.modifier.scopeType.type);

src/processTargets/modifiers/LeadingTrailingStages.ts

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,27 @@ import {
55
} from "../../typings/targetDescriptor.types";
66
import { ProcessedTargetsContext } from "../../typings/Types";
77
import { ModifierStage } from "../PipelineStages.types";
8-
import { weakContainingTokenStage } from "./commonWeakContainingScopeStages";
8+
import { containingTokenIfUntypedStage } from "./commonContainingScopeIfUntypedStages";
9+
10+
/**
11+
* Throw this error if user has requested leading or trailing delimiter but no
12+
* such delimiter exists on the given target.
13+
*/
14+
class NoDelimiterError extends Error {
15+
constructor(type: "leading" | "trailing") {
16+
super(`Target has no ${type} delimiter.`);
17+
this.name = "NoDelimiterError";
18+
}
19+
}
920

1021
export class LeadingStage implements ModifierStage {
1122
constructor(private modifier: LeadingModifier) {}
1223

1324
run(context: ProcessedTargetsContext, target: Target): Target[] {
14-
return weakContainingTokenStage.run(context, target).map((target) => {
25+
return containingTokenIfUntypedStage.run(context, target).map((target) => {
1526
const leading = target.getLeadingDelimiterTarget();
1627
if (leading == null) {
17-
throw Error("No available leading delimiter range");
28+
throw new NoDelimiterError("leading");
1829
}
1930
return leading;
2031
});
@@ -25,10 +36,10 @@ export class TrailingStage implements ModifierStage {
2536
constructor(private modifier: TrailingModifier) {}
2637

2738
run(context: ProcessedTargetsContext, target: Target): Target[] {
28-
return weakContainingTokenStage.run(context, target).map((target) => {
39+
return containingTokenIfUntypedStage.run(context, target).map((target) => {
2940
const trailing = target.getTrailingDelimiterTarget();
3041
if (trailing == null) {
31-
throw Error("No available trailing delimiter range");
42+
throw new NoDelimiterError("trailing");
3243
}
3344
return trailing;
3445
});

0 commit comments

Comments
 (0)