Skip to content

Commit

Permalink
Migrate Typescript "value" to next gen; improve "name" (cursorless-de…
Browse files Browse the repository at this point in the history
  • Loading branch information
pokey authored and fidgetingbits committed Nov 3, 2023
1 parent 4d060cc commit 7c0f561
Show file tree
Hide file tree
Showing 21 changed files with 1,111 additions and 60 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,21 @@ export abstract class QueryPredicateOperator<T extends HasSchema> {
...args: AcceptFunctionArgs<z.infer<InferSchemaType<T>>>
): boolean;

/**
* Whether it is ok for a node argument to be missing. If true, then the
* operator will just accept the pattern if the given node is missing. If
* false, then the operator will throw an error if the node is missing.
*
* This is useful if we want to set some flag on a node, but only if it's
* present.
*
* @returns A boolean indicating whether it is ok for a node argument to be
* missing.
*/
protected allowMissingNode(): boolean {
return false;
}

/**
* Given a list of operands, return a predicate function that can be used to
* test whether a given match satisfies the predicate.
Expand All @@ -62,8 +77,21 @@ export abstract class QueryPredicateOperator<T extends HasSchema> {
return result.success
? {
success: true,
predicate: (match: MutableQueryMatch) =>
this.run(...this.constructAcceptArgs(result.data, match)),
predicate: (match: MutableQueryMatch) => {
try {
const acceptArgs = this.constructAcceptArgs(result.data, match);
return this.run(...acceptArgs);
} catch (err) {
if (
err instanceof CaptureNotFoundError &&
this.allowMissingNode()
) {
return true;
}

throw err;
}
},
}
: {
success: false,
Expand All @@ -89,13 +117,7 @@ export abstract class QueryPredicateOperator<T extends HasSchema> {
);

if (capture == null) {
// FIXME: We could allow some predicates to be forgiving,
// because it's possible to have a capture on an optional nodeInfo.
// In that case we'd prob just return `true` if any capture was
// `null`, but we should check that the given capture name
// appears statically in the given pattern. But we don't yet
// have a use case so let's leave it for now.
throw new Error(`Could not find capture ${operand.name}`);
throw new CaptureNotFoundError(operand.name);
}

return capture;
Expand All @@ -117,3 +139,9 @@ interface FailedPredicateResult {
}

type PredicateResult = SuccessfulPredicateResult | FailedPredicateResult;

class CaptureNotFoundError extends Error {
constructor(operandName: string) {
super(`Could not find capture ${operandName}`);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -150,10 +150,25 @@ class ShrinkToMatch extends QueryPredicateOperator<ShrinkToMatch> {
}
}

/**
* Indicates that it is ok for multiple captures to have the same domain but
* different targets. For example, if we have the query `(#allow-multiple!
* @foo)`, then if we define the query so that `@foo` appears multiple times
* with the same domain but different targets, then the given domain will end up
* with multiple targets. The canonical example is `tags` in HTML / jsx.
*
* This operator is allowed to be applied to a capture that doesn't actually
* appear; ie we can make it so that we allow multiple if the capture appears in
* the pattern.
*/
class AllowMultiple extends QueryPredicateOperator<AllowMultiple> {
name = "allow-multiple!" as const;
schema = z.tuple([q.node]);

protected allowMissingNode(): boolean {
return true;
}

run(nodeInfo: MutableQueryCapture) {
nodeInfo.allowMultiple = true;

Expand Down
33 changes: 0 additions & 33 deletions packages/cursorless-engine/src/languages/typescript.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,34 +124,6 @@ function typeMatcher(): NodeMatcher {
};
}

function valueMatcher() {
const pFinder = patternFinder(
"assignment_expression[right]",
"augmented_assignment_expression[right]",
"*[value]",
"shorthand_property_identifier",
);
return matcher(
(node: SyntaxNode) =>
node.type === "jsx_attribute" ? node.lastChild : pFinder(node),
selectWithLeadingDelimiter(
":",
"=",
"+=",
"-=",
"*=",
"/=",
"%=",
"**=",
"&=",
"|=",
"^=",
"<<=",
">>=",
),
);
}

const mapTypes = ["object", "object_pattern"];
const listTypes = ["array", "array_pattern"];

Expand All @@ -171,11 +143,6 @@ const nodeMatchers: Partial<
],
[":"],
),
value: cascadingMatcher(
valueMatcher(),
patternMatcher("return_statement.~return!"),
patternMatcher("yield_expression.~yield!"),
),
ifStatement: "if_statement",
comment: "comment",
regularExpression: "regex",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
languageId: javascript
command:
version: 6
spokenForm: change every value
action:
name: clearAndSetSelection
target:
type: primitive
modifiers:
- type: everyScope
scopeType: {type: value}
usePrePhraseSnapshot: true
initialState:
documentContents: |-
function aaa() {
const bbb = 0;
const ccc = 0;
}
selections:
- anchor: {line: 2, character: 18}
active: {line: 2, character: 18}
marks: {}
finalState:
documentContents: |-
function aaa() {
const bbb = ;
const ccc = ;
}
selections:
- anchor: {line: 1, character: 16}
active: {line: 1, character: 16}
- anchor: {line: 2, character: 16}
active: {line: 2, character: 16}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
languageId: javascript
command:
version: 6
spokenForm: change every value
action:
name: clearAndSetSelection
target:
type: primitive
modifiers:
- type: everyScope
scopeType: {type: value}
usePrePhraseSnapshot: true
initialState:
documentContents: |-
const bbb = 0;
const ccc = 0;
selections:
- anchor: {line: 1, character: 14}
active: {line: 1, character: 14}
marks: {}
finalState:
documentContents: |-
const bbb = ;
const ccc = ;
selections:
- anchor: {line: 0, character: 12}
active: {line: 0, character: 12}
- anchor: {line: 1, character: 12}
active: {line: 1, character: 12}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
languageId: javascript
command:
version: 6
spokenForm: change name
action:
name: clearAndSetSelection
target:
type: primitive
modifiers:
- type: containingScope
scopeType: {type: name}
usePrePhraseSnapshot: true
initialState:
documentContents: const aaa = "bbb", ccc = "ddd";
selections:
- anchor: {line: 0, character: 30}
active: {line: 0, character: 30}
marks: {}
finalState:
documentContents: const aaa = "bbb", = "ddd";
selections:
- anchor: {line: 0, character: 19}
active: {line: 0, character: 19}
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
languageId: javascript
command:
version: 6
spokenForm: change name
action:
name: clearAndSetSelection
target:
type: primitive
modifiers:
- type: containingScope
scopeType: {type: name}
usePrePhraseSnapshot: true
initialState:
documentContents: |-
const aaa = 0;
let bbb = 0;
var hhh = 0;
ccc = 0;
kkk += 1;
const ddd = 0, eee = 0;
let fff = 0, ggg = 0;
var iii = 0;
export const jjj = 0;
export let kkk = 0;
export var lll = 0;
export const mmm = 0, nnn = 0;
export let ooo = 0, ppp = 0;
selections:
- anchor: {line: 0, character: 14}
active: {line: 0, character: 14}
- anchor: {line: 1, character: 12}
active: {line: 1, character: 12}
- anchor: {line: 2, character: 12}
active: {line: 2, character: 12}
- anchor: {line: 3, character: 8}
active: {line: 3, character: 8}
- anchor: {line: 4, character: 9}
active: {line: 4, character: 9}
- anchor: {line: 5, character: 23}
active: {line: 5, character: 23}
- anchor: {line: 6, character: 21}
active: {line: 6, character: 21}
- anchor: {line: 7, character: 12}
active: {line: 7, character: 12}
- anchor: {line: 8, character: 21}
active: {line: 8, character: 21}
- anchor: {line: 9, character: 19}
active: {line: 9, character: 19}
- anchor: {line: 10, character: 19}
active: {line: 10, character: 19}
- anchor: {line: 11, character: 30}
active: {line: 11, character: 30}
- anchor: {line: 12, character: 28}
active: {line: 12, character: 28}
marks: {}
finalState:
documentContents: |-
const = 0;
let = 0;
var = 0;
= 0;
+= 1;
const = 0, = 0;
let = 0, = 0;
var = 0;
export const = 0;
export let = 0;
export var = 0;
export const = 0, = 0;
export let = 0, = 0;
selections:
- anchor: {line: 0, character: 6}
active: {line: 0, character: 6}
- anchor: {line: 1, character: 4}
active: {line: 1, character: 4}
- anchor: {line: 2, character: 4}
active: {line: 2, character: 4}
- anchor: {line: 3, character: 0}
active: {line: 3, character: 0}
- anchor: {line: 4, character: 0}
active: {line: 4, character: 0}
- anchor: {line: 5, character: 6}
active: {line: 5, character: 6}
- anchor: {line: 5, character: 12}
active: {line: 5, character: 12}
- anchor: {line: 6, character: 4}
active: {line: 6, character: 4}
- anchor: {line: 6, character: 10}
active: {line: 6, character: 10}
- anchor: {line: 7, character: 4}
active: {line: 7, character: 4}
- anchor: {line: 8, character: 13}
active: {line: 8, character: 13}
- anchor: {line: 9, character: 11}
active: {line: 9, character: 11}
- anchor: {line: 10, character: 11}
active: {line: 10, character: 11}
- anchor: {line: 11, character: 13}
active: {line: 11, character: 13}
- anchor: {line: 11, character: 19}
active: {line: 11, character: 19}
- anchor: {line: 12, character: 11}
active: {line: 12, character: 11}
- anchor: {line: 12, character: 17}
active: {line: 12, character: 17}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
languageId: javascript
command:
version: 6
spokenForm: change name
action:
name: clearAndSetSelection
target:
type: primitive
modifiers:
- type: containingScope
scopeType: {type: name}
usePrePhraseSnapshot: true
initialState:
documentContents: |-
hhh = 0, iii = 0, jjj=0;
lll += 1, mmm += 1, nnn += 1;
selections:
- anchor: {line: 0, character: 0}
active: {line: 0, character: 0}
- anchor: {line: 0, character: 9}
active: {line: 0, character: 9}
- anchor: {line: 0, character: 18}
active: {line: 0, character: 18}
- anchor: {line: 1, character: 0}
active: {line: 1, character: 0}
- anchor: {line: 1, character: 10}
active: {line: 1, character: 10}
- anchor: {line: 1, character: 20}
active: {line: 1, character: 20}
marks: {}
finalState:
documentContents: |2-
= 0, = 0, =0;
+= 1, += 1, += 1;
selections:
- anchor: {line: 0, character: 0}
active: {line: 0, character: 0}
- anchor: {line: 0, character: 6}
active: {line: 0, character: 6}
- anchor: {line: 0, character: 12}
active: {line: 0, character: 12}
- anchor: {line: 1, character: 0}
active: {line: 1, character: 0}
- anchor: {line: 1, character: 7}
active: {line: 1, character: 7}
- anchor: {line: 1, character: 14}
active: {line: 1, character: 14}
Loading

0 comments on commit 7c0f561

Please sign in to comment.