Skip to content

Commit 9742579

Browse files
Refactoring
1 parent 3da4d51 commit 9742579

File tree

10 files changed

+97
-97
lines changed

10 files changed

+97
-97
lines changed

data/fixtures/recorded/implicitExpansion/clearCoreToken.yml

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,4 @@ initialState:
1717
- anchor: {line: 0, character: 1}
1818
active: {line: 0, character: 1}
1919
marks: {}
20-
finalState:
21-
documentContents: ()
22-
selections:
23-
- anchor: {line: 0, character: 1}
24-
active: {line: 0, character: 1}
20+
thrownError: {name: NoContainingScopeError}

data/fixtures/recorded/modifiers/interior/changeInsideToken.yml

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

packages/cursorless-engine/src/languages/LanguageDefinition.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import type {
22
RawTreeSitterQueryProvider,
33
ScopeType,
4+
SimpleScopeType,
45
SimpleScopeTypeType,
56
TreeSitter,
67
} from "@cursorless/common";
@@ -77,7 +78,7 @@ export class LanguageDefinition {
7778
return undefined;
7879
}
7980

80-
return new TreeSitterScopeHandler(this.query, scopeType);
81+
return new TreeSitterScopeHandler(this.query, scopeType as SimpleScopeType);
8182
}
8283

8384
/**

packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/FallbackScopeHandler.ts

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,32 +18,39 @@ export class FallbackScopeHandler extends BaseScopeHandler {
1818
public scopeType = undefined;
1919
protected isHierarchical = true;
2020

21-
get iterationScopeType(): ScopeType {
22-
throw new NoContainingScopeError(
23-
"Iteration scope for FallbackScopeHandler",
21+
static create(
22+
scopeHandlerFactory: ScopeHandlerFactory,
23+
scopeType: FallbackScopeType,
24+
languageId: string,
25+
): ScopeHandler {
26+
const scopeHandlers: ScopeHandler[] = scopeType.scopeTypes.map(
27+
(scopeType) => scopeHandlerFactory.create(scopeType, languageId),
2428
);
29+
30+
return this.createFromScopeHandlers(scopeHandlers);
2531
}
2632

27-
constructor(
28-
public scopeHandlerFactory: ScopeHandlerFactory,
29-
private fallbackScopeType: FallbackScopeType,
30-
private languageId: string,
31-
) {
33+
static createFromScopeHandlers(scopeHandlers: ScopeHandler[]): ScopeHandler {
34+
return new FallbackScopeHandler(scopeHandlers);
35+
}
36+
37+
private constructor(private scopeHandlers: ScopeHandler[]) {
3238
super();
3339
}
3440

41+
get iterationScopeType(): ScopeType {
42+
throw new NoContainingScopeError(
43+
"Iteration scope for FallbackScopeHandler",
44+
);
45+
}
46+
3547
*generateScopeCandidates(
3648
editor: TextEditor,
3749
position: Position,
3850
direction: Direction,
3951
hints: ScopeIteratorRequirements,
4052
): Iterable<TargetScope> {
41-
const scopeHandlers: ScopeHandler[] = this.fallbackScopeType.scopeTypes.map(
42-
(scopeType) =>
43-
this.scopeHandlerFactory.create(scopeType, this.languageId),
44-
);
45-
46-
for (const scopeHandler of scopeHandlers) {
53+
for (const scopeHandler of this.scopeHandlers) {
4754
yield* scopeHandler.generateScopes(editor, position, direction, hints);
4855
}
4956
}

packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/ScopeHandlerFactoryImpl.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,7 @@ export class ScopeHandlerFactoryImpl implements ScopeHandlerFactory {
132132
case "oneOf":
133133
return OneOfScopeHandler.create(this, scopeType, languageId);
134134
case "fallback":
135-
return new FallbackScopeHandler(this, scopeType, languageId);
135+
return FallbackScopeHandler.create(this, scopeType, languageId);
136136
case "conditional":
137137
return new ConditionalScopeHandler(this, scopeType, languageId);
138138
case "instance":

packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/SurroundingPairScopeHandler/InteriorScopeHandler.ts

Lines changed: 59 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@ import {
88
type TextEditor,
99
} from "@cursorless/common";
1010
import type { LanguageDefinitions } from "../../../../languages/LanguageDefinitions";
11+
import type { Target } from "../../../../typings/target.types";
12+
import { InteriorTarget } from "../../../targets";
1113
import { BaseScopeHandler } from "../BaseScopeHandler";
14+
import { FallbackScopeHandler } from "../FallbackScopeHandler";
1215
import { OneOfScopeHandler } from "../OneOfScopeHandler";
1316
import type { TargetScope } from "../scope.types";
1417
import type {
@@ -42,6 +45,7 @@ export class InteriorScopeHandler extends BaseScopeHandler {
4245
direction: Direction,
4346
hints: ScopeIteratorRequirements,
4447
): Iterable<TargetScope> {
48+
const targetDomain = new Range(position, hints.distalPosition);
4549
const scopeHandler = this.getScopeHandler();
4650

4751
if (scopeHandler == null) {
@@ -55,22 +59,9 @@ export class InteriorScopeHandler extends BaseScopeHandler {
5559
hints,
5660
);
5761

58-
// No explicit scope type. Just yield all scopes.
59-
if (!this.scopeType.explicitScopeType) {
60-
yield* scopes;
61-
return;
62-
}
63-
64-
const targetDomain = new Range(position, hints.distalPosition);
65-
66-
// For an explicit scope type we only yield scopes that are contained within
67-
// the target domain. E.g the user said "inside token", then we don't want
68-
// to yield scopes that are larger than the token. The definition of an
69-
// interior is that it's inside the scope.
70-
7162
for (const scope of scopes) {
72-
if (targetDomain.contains(scope.domain)) {
73-
yield scope;
63+
if (this.shouldYield(targetDomain, scope)) {
64+
yield createInteriorScope(scope);
7465
}
7566
}
7667
}
@@ -80,29 +71,31 @@ export class InteriorScopeHandler extends BaseScopeHandler {
8071
.get(this.languageId)
8172
?.getScopeHandler(this.scopeType);
8273

74+
const pairScopeHandler = this.scopeHandlerFactory.create(
75+
{
76+
type: "surroundingPair",
77+
delimiter: "any",
78+
},
79+
this.languageId,
80+
);
81+
8382
// If the scope type is explicit (ie, the user has specified a scope
84-
// type), then we don't want to include matching pairs. The user might
83+
// type), then we want to prioritize language scopes. The user might
8584
// have said something like "inside element" and then we don't want to
86-
// yield the interior of the `<div>` pair.
85+
// yield the interior of the `<div>` pair first.
8786

8887
if (this.scopeType.explicitScopeType) {
8988
if (languageScopeHandler == null) {
90-
return undefined;
89+
return pairScopeHandler;
9190
}
92-
return languageScopeHandler;
91+
return FallbackScopeHandler.createFromScopeHandlers([
92+
languageScopeHandler,
93+
pairScopeHandler,
94+
]);
9395
}
9496

95-
const pairInteriorScopeHandler = this.scopeHandlerFactory.create(
96-
{
97-
type: "surroundingPairInterior",
98-
delimiter: "any",
99-
allowWeakContainment: true,
100-
},
101-
this.languageId,
102-
);
103-
10497
if (languageScopeHandler == null) {
105-
return pairInteriorScopeHandler;
98+
return pairScopeHandler;
10699
}
107100

108101
return OneOfScopeHandler.createFromScopeHandlers(
@@ -111,11 +104,46 @@ export class InteriorScopeHandler extends BaseScopeHandler {
111104
type: "oneOf",
112105
scopeTypes: [
113106
languageScopeHandler.scopeType,
114-
pairInteriorScopeHandler.scopeType!,
107+
pairScopeHandler.scopeType!,
115108
],
116109
},
117-
[languageScopeHandler, pairInteriorScopeHandler],
110+
[languageScopeHandler, pairScopeHandler],
118111
this.languageId,
119112
);
120113
}
114+
115+
private shouldYield(targetDomain: Range, scope: TargetScope): boolean {
116+
// For an explicit scope type we only yield scopes that are contained within
117+
// the target domain. E.g the user said "inside token", then we don't want
118+
// to yield scopes that are larger than the token. The definition of an
119+
// interior is that it's inside the scope.
120+
121+
return (
122+
!this.scopeType.explicitScopeType || targetDomain.contains(scope.domain)
123+
);
124+
}
125+
}
126+
127+
function createInteriorScope(scope: TargetScope): TargetScope {
128+
return {
129+
editor: scope.editor,
130+
domain: scope.domain,
131+
getTargets(isReversed) {
132+
return scope.getTargets(isReversed).flatMap(createInteriorTarget);
133+
},
134+
};
135+
}
136+
137+
function createInteriorTarget(target: Target): Target[] {
138+
const interior = target.getInterior();
139+
if (interior != null) {
140+
return interior;
141+
}
142+
return [
143+
new InteriorTarget({
144+
editor: target.editor,
145+
isReversed: target.isReversed,
146+
fullInteriorRange: target.contentRange,
147+
}),
148+
];
121149
}

packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/SurroundingPairScopeHandler/SurroundingPairInteriorScopeHandler.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ export class SurroundingPairInteriorScopeHandler extends BaseScopeHandler {
2121
{
2222
type: "surroundingPair",
2323
delimiter: this.scopeType.delimiter,
24-
requireStrongContainment: !this.scopeType.allowWeakContainment,
24+
requireStrongContainment: true,
2525
},
2626
this.languageId,
2727
);

packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/TreeSitterScopeHandler/TreeSitterIterationScopeHandler.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
import type { ScopeType, TextEditor } from "@cursorless/common";
1+
import type {
2+
ScopeType,
3+
SimpleScopeType,
4+
TextEditor,
5+
} from "@cursorless/common";
26
import type { TreeSitterQuery } from "../../../../languages/TreeSitterQuery";
37
import type { QueryMatch } from "../../../../languages/TreeSitterQuery/QueryCapture";
48
import { PlainTarget } from "../../../targets";
@@ -22,7 +26,7 @@ export class TreeSitterIterationScopeHandler extends BaseTreeSitterScopeHandler
2226
constructor(
2327
query: TreeSitterQuery,
2428
/** The scope type for which we are the iteration scope */
25-
private iterateeScopeType: ScopeType,
29+
private iterateeScopeType: SimpleScopeType,
2630
) {
2731
super(query);
2832
}

packages/cursorless-engine/src/processTargets/modifiers/scopeHandlers/TreeSitterScopeHandler/TreeSitterScopeHandler.ts

Lines changed: 2 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
import type { ScopeType, TextEditor } from "@cursorless/common";
1+
import type { SimpleScopeType, TextEditor } from "@cursorless/common";
22
import type { TreeSitterQuery } from "../../../../languages/TreeSitterQuery";
33
import type { QueryMatch } from "../../../../languages/TreeSitterQuery/QueryCapture";
4-
import { InteriorTarget } from "../../../targets";
54
import { ScopeTypeTarget } from "../../../targets/ScopeTypeTarget";
65
import type { CustomScopeType } from "../scopeHandler.types";
76
import { getCollectionItemRemovalRange } from "../util/getCollectionItemRemovalRange";
@@ -18,7 +17,7 @@ export class TreeSitterScopeHandler extends BaseTreeSitterScopeHandler {
1817

1918
constructor(
2019
query: TreeSitterQuery,
21-
public scopeType: ScopeType,
20+
public scopeType: SimpleScopeType,
2221
) {
2322
super(query);
2423
}
@@ -54,21 +53,6 @@ export class TreeSitterScopeHandler extends BaseTreeSitterScopeHandler {
5453
const domain =
5554
getRelatedRange(match, scopeTypeType, "domain", true) ?? contentRange;
5655

57-
if (scopeTypeType === "interior") {
58-
return {
59-
editor,
60-
domain,
61-
allowMultiple,
62-
getTargets: (isReversed) => [
63-
new InteriorTarget({
64-
editor,
65-
isReversed,
66-
fullInteriorRange: contentRange,
67-
}),
68-
],
69-
};
70-
}
71-
7256
const prefixRange = getRelatedRange(
7357
match,
7458
scopeTypeType,

packages/cursorless-engine/src/processTargets/targets/ScopeTypeTarget.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import type { Range, ScopeTypeType } from "@cursorless/common";
1+
import type { Range, SimpleScopeTypeType } from "@cursorless/common";
22
import type { Target } from "../../typings/target.types";
33
import type { CommonTargetParameters } from "./BaseTarget";
44
import { BaseTarget } from "./BaseTarget";
@@ -11,7 +11,7 @@ import {
1111
} from "./util/insertionRemovalBehaviors/TokenInsertionRemovalBehavior";
1212

1313
export interface ScopeTypeTargetParameters extends CommonTargetParameters {
14-
readonly scopeTypeType: ScopeTypeType;
14+
readonly scopeTypeType: SimpleScopeTypeType;
1515
readonly insertionDelimiter?: string;
1616
readonly prefixRange?: Range;
1717
readonly removalRange?: Range;
@@ -21,7 +21,7 @@ export interface ScopeTypeTargetParameters extends CommonTargetParameters {
2121

2222
export class ScopeTypeTarget extends BaseTarget<ScopeTypeTargetParameters> {
2323
type = "ScopeTypeTarget";
24-
private scopeTypeType_: ScopeTypeType;
24+
private scopeTypeType_: SimpleScopeTypeType;
2525
private removalRange_?: Range;
2626
private leadingDelimiterRange_?: Range;
2727
private trailingDelimiterRange_?: Range;
@@ -118,7 +118,7 @@ export class ScopeTypeTarget extends BaseTarget<ScopeTypeTargetParameters> {
118118
}
119119
}
120120

121-
function getInsertionDelimiter(scopeType: ScopeTypeType): string {
121+
function getInsertionDelimiter(scopeType: SimpleScopeTypeType): string {
122122
switch (scopeType) {
123123
case "class":
124124
case "namedFunction":

0 commit comments

Comments
 (0)