From adf03e9ce863096ec8443ca0df6f7962a0765359 Mon Sep 17 00:00:00 2001 From: Pokey Rule <755842+pokey@users.noreply.github.com> Date: Fri, 9 Jun 2023 15:55:41 +0100 Subject: [PATCH] Implement more Typescript scope types using queries --- .../src/languages/typescript.ts | 54 ------ .../languages/typescript/clearFunk10.yml | 22 +++ .../languages/typescript/clearFunk11.yml | 18 ++ .../languages/typescript/clearFunk12.yml | 22 +++ .../languages/typescript/clearFunk13.yml | 22 +++ .../languages/typescript/clearFunk14.yml | 22 +++ .../languages/typescript/clearFunk15.yml | 22 +++ .../languages/typescript/clearFunk16.yml | 22 +++ .../languages/typescript/clearFunk17.yml | 28 +++ .../languages/typescript/clearFunk18.yml | 42 +++++ .../languages/typescript/clearFunk4.yml | 22 +++ .../languages/typescript/clearFunk5.yml | 22 +++ .../languages/typescript/clearFunk6.yml | 18 ++ .../languages/typescript/clearFunk7.yml | 22 +++ .../languages/typescript/clearFunk8.yml | 22 +++ .../languages/typescript/clearFunk9.yml | 18 ++ .../languages/typescript/clearFunkName2.yml | 22 +++ .../languages/typescript/clearFunkName3.yml | 22 +++ .../languages/typescript/clearFunkName4.yml | 22 +++ .../languages/typescript/clearFunkName5.yml | 22 +++ .../languages/typescript/clearFunkName6.yml | 18 ++ .../languages/typescript/clearFunkName7.yml | 28 +++ .../languages/typescript/clearLambda5.yml | 22 +++ .../languages/typescript/clearLambda6.yml | 18 ++ .../languages/typescript/clearLambda7.yml | 18 ++ queries/javascript.core.scm | 2 + queries/javascript.function.scm | 174 ++++++++++++++++++ queries/typescript.scm | 35 ++++ 28 files changed, 747 insertions(+), 54 deletions(-) create mode 100644 packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunk10.yml create mode 100644 packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunk11.yml create mode 100644 packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunk12.yml create mode 100644 packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunk13.yml create mode 100644 packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunk14.yml create mode 100644 packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunk15.yml create mode 100644 packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunk16.yml create mode 100644 packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunk17.yml create mode 100644 packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunk18.yml create mode 100644 packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunk4.yml create mode 100644 packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunk5.yml create mode 100644 packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunk6.yml create mode 100644 packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunk7.yml create mode 100644 packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunk8.yml create mode 100644 packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunk9.yml create mode 100644 packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunkName2.yml create mode 100644 packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunkName3.yml create mode 100644 packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunkName4.yml create mode 100644 packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunkName5.yml create mode 100644 packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunkName6.yml create mode 100644 packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunkName7.yml create mode 100644 packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearLambda5.yml create mode 100644 packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearLambda6.yml create mode 100644 packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearLambda7.yml create mode 100644 queries/javascript.function.scm diff --git a/packages/cursorless-engine/src/languages/typescript.ts b/packages/cursorless-engine/src/languages/typescript.ts index 04d8bca7da4..1a3b0263ca0 100644 --- a/packages/cursorless-engine/src/languages/typescript.ts +++ b/packages/cursorless-engine/src/languages/typescript.ts @@ -175,7 +175,6 @@ const nodeMatchers: Partial< patternMatcher("yield_expression.~yield!"), ), ifStatement: "if_statement", - anonymousFunction: ["arrow_function", "function"], comment: "comment", regularExpression: "regex", className: ["class_declaration[name]", "class[name]"], @@ -226,59 +225,6 @@ const nodeMatchers: Partial< "export_statement?.abstract_class_declaration", // export abstract class | abstract class "export_statement.class", // export default class ], - functionName: [ - // function - "function_declaration[name]", - // generator function - "generator_function_declaration[name]", - // export default function - "function[name]", - // class method - "method_definition[name]", - // abstract class method - "abstract_method_signature[name]", - // class arrow method - "public_field_definition[name].arrow_function", - // const foo = function() { } - "variable_declarator[name].function", - // const foo = () => { } - "variable_declarator[name].arrow_function", - // foo = function() { } - "assignment_expression[left].function", - // foo = () => { } - "assignment_expression[left].arrow_function", - ], - namedFunction: cascadingMatcher( - patternMatcher( - // [export] function - "export_statement?.function_declaration", - // export default function - // NB: We require export statement because otherwise it is an anonymous - // function - "export_statement.function", - // export default arrow - "export_statement.arrow_function", - // class method - "method_definition", - // class arrow method - "public_field_definition.arrow_function", - // [export] const foo = function() { } - "export_statement?.lexical_declaration.variable_declarator.function", - // [export] const foo = () => { } - "export_statement?.lexical_declaration.variable_declarator.arrow_function", - // foo = function() { } - "assignment_expression.function", - // foo = () => { } - "assignment_expression.arrow_function", - // foo = function*() { } - "generator_function_declaration", - ), - // abstract class method - matcher( - patternFinder("abstract_method_signature"), - extendForwardPastOptional(";"), - ), - ), type: cascadingMatcher( // Typed parameters, properties, and functions typeMatcher(), diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunk10.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunk10.yml new file mode 100644 index 00000000000..71f628f8e02 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunk10.yml @@ -0,0 +1,22 @@ +languageId: typescript +command: + version: 5 + spokenForm: clear funk + action: {name: clearAndSetSelection} + targets: + - type: primitive + modifiers: + - type: containingScope + scopeType: {type: namedFunction} + usePrePhraseSnapshot: true +initialState: + documentContents: const foo = function *bar() {} + selections: + - anchor: {line: 0, character: 12} + active: {line: 0, character: 12} + marks: {} +finalState: + documentContents: "const foo = " + selections: + - anchor: {line: 0, character: 12} + active: {line: 0, character: 12} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunk11.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunk11.yml new file mode 100644 index 00000000000..7feeafdd19c --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunk11.yml @@ -0,0 +1,18 @@ +languageId: typescript +command: + version: 5 + spokenForm: clear funk + action: {name: clearAndSetSelection} + targets: + - type: primitive + modifiers: + - type: containingScope + scopeType: {type: namedFunction} + usePrePhraseSnapshot: true +initialState: + documentContents: const foo = function *bar() {} + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} + marks: {} +thrownError: {name: NoContainingScopeError} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunk12.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunk12.yml new file mode 100644 index 00000000000..c0d95bbe84b --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunk12.yml @@ -0,0 +1,22 @@ +languageId: typescript +command: + version: 5 + spokenForm: clear funk + action: {name: clearAndSetSelection} + targets: + - type: primitive + modifiers: + - type: containingScope + scopeType: {type: namedFunction} + usePrePhraseSnapshot: true +initialState: + documentContents: export default function *() {} + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} + marks: {} +finalState: + documentContents: "" + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunk13.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunk13.yml new file mode 100644 index 00000000000..2a05bf5c741 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunk13.yml @@ -0,0 +1,22 @@ +languageId: javascript +command: + version: 5 + spokenForm: clear funk + action: {name: clearAndSetSelection} + targets: + - type: primitive + modifiers: + - type: containingScope + scopeType: {type: namedFunction} + usePrePhraseSnapshot: true +initialState: + documentContents: var foo = () => {}; + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} + marks: {} +finalState: + documentContents: "" + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunk14.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunk14.yml new file mode 100644 index 00000000000..2dc55c04857 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunk14.yml @@ -0,0 +1,22 @@ +languageId: javascript +command: + version: 5 + spokenForm: clear funk + action: {name: clearAndSetSelection} + targets: + - type: primitive + modifiers: + - type: containingScope + scopeType: {type: namedFunction} + usePrePhraseSnapshot: true +initialState: + documentContents: export var foo = () => {}; + selections: + - anchor: {line: 0, character: 8} + active: {line: 0, character: 8} + marks: {} +finalState: + documentContents: "" + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunk15.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunk15.yml new file mode 100644 index 00000000000..4231240e28c --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunk15.yml @@ -0,0 +1,22 @@ +languageId: javascript +command: + version: 5 + spokenForm: clear funk + action: {name: clearAndSetSelection} + targets: + - type: primitive + modifiers: + - type: containingScope + scopeType: {type: namedFunction} + usePrePhraseSnapshot: true +initialState: + documentContents: const foo = () => {}; + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} + marks: {} +finalState: + documentContents: "" + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunk16.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunk16.yml new file mode 100644 index 00000000000..3594f0e5fbb --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunk16.yml @@ -0,0 +1,22 @@ +languageId: javascript +command: + version: 5 + spokenForm: clear funk + action: {name: clearAndSetSelection} + targets: + - type: primitive + modifiers: + - type: containingScope + scopeType: {type: namedFunction} + usePrePhraseSnapshot: true +initialState: + documentContents: let foo = () => {}; + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} + marks: {} +finalState: + documentContents: "" + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunk17.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunk17.yml new file mode 100644 index 00000000000..b09b577db4d --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunk17.yml @@ -0,0 +1,28 @@ +languageId: typescript +command: + version: 5 + spokenForm: clear funk + action: {name: clearAndSetSelection} + targets: + - type: primitive + modifiers: + - type: containingScope + scopeType: {type: namedFunction} + usePrePhraseSnapshot: true +initialState: + documentContents: |- + interface Aaa { + bbb(): void; + } + selections: + - anchor: {line: 1, character: 16} + active: {line: 1, character: 16} + marks: {} +finalState: + documentContents: |- + interface Aaa { + + } + selections: + - anchor: {line: 1, character: 4} + active: {line: 1, character: 4} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunk18.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunk18.yml new file mode 100644 index 00000000000..b42129c7ff2 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunk18.yml @@ -0,0 +1,42 @@ +languageId: typescript +command: + version: 5 + spokenForm: clear funk + action: {name: clearAndSetSelection} + targets: + - type: primitive + modifiers: + - type: containingScope + scopeType: {type: namedFunction} + usePrePhraseSnapshot: true +initialState: + documentContents: |- + class MyClass { + constructor(value: string); + constructor(value: number); + + constructor(value: string | number) {} + } + selections: + - anchor: {line: 1, character: 31} + active: {line: 1, character: 31} + - anchor: {line: 2, character: 31} + active: {line: 2, character: 31} + - anchor: {line: 4, character: 42} + active: {line: 4, character: 42} + marks: {} +finalState: + documentContents: |- + class MyClass { + + + + + } + selections: + - anchor: {line: 1, character: 4} + active: {line: 1, character: 4} + - anchor: {line: 2, character: 4} + active: {line: 2, character: 4} + - anchor: {line: 4, character: 4} + active: {line: 4, character: 4} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunk4.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunk4.yml new file mode 100644 index 00000000000..97c7460f743 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunk4.yml @@ -0,0 +1,22 @@ +languageId: typescript +command: + version: 5 + spokenForm: clear funk + action: {name: clearAndSetSelection} + targets: + - type: primitive + modifiers: + - type: containingScope + scopeType: {type: namedFunction} + usePrePhraseSnapshot: true +initialState: + documentContents: export function *aaa() {} + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} + marks: {} +finalState: + documentContents: "" + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunk5.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunk5.yml new file mode 100644 index 00000000000..fdc0063dfc1 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunk5.yml @@ -0,0 +1,22 @@ +languageId: typescript +command: + version: 5 + spokenForm: clear funk + action: {name: clearAndSetSelection} + targets: + - type: primitive + modifiers: + - type: containingScope + scopeType: {type: namedFunction} + usePrePhraseSnapshot: true +initialState: + documentContents: (function foo() {}) + selections: + - anchor: {line: 0, character: 1} + active: {line: 0, character: 1} + marks: {} +finalState: + documentContents: () + selections: + - anchor: {line: 0, character: 1} + active: {line: 0, character: 1} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunk6.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunk6.yml new file mode 100644 index 00000000000..03f64276c14 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunk6.yml @@ -0,0 +1,18 @@ +languageId: typescript +command: + version: 5 + spokenForm: clear funk + action: {name: clearAndSetSelection} + targets: + - type: primitive + modifiers: + - type: containingScope + scopeType: {type: namedFunction} + usePrePhraseSnapshot: true +initialState: + documentContents: (function () {}) + selections: + - anchor: {line: 0, character: 1} + active: {line: 0, character: 1} + marks: {} +thrownError: {name: NoContainingScopeError} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunk7.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunk7.yml new file mode 100644 index 00000000000..e495cbfe548 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunk7.yml @@ -0,0 +1,22 @@ +languageId: typescript +command: + version: 5 + spokenForm: clear funk + action: {name: clearAndSetSelection} + targets: + - type: primitive + modifiers: + - type: containingScope + scopeType: {type: namedFunction} + usePrePhraseSnapshot: true +initialState: + documentContents: export const myFunk = () => {}; + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} + marks: {} +finalState: + documentContents: "" + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunk8.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunk8.yml new file mode 100644 index 00000000000..08f782e335e --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunk8.yml @@ -0,0 +1,22 @@ +languageId: typescript +command: + version: 5 + spokenForm: clear funk + action: {name: clearAndSetSelection} + targets: + - type: primitive + modifiers: + - type: containingScope + scopeType: {type: namedFunction} + usePrePhraseSnapshot: true +initialState: + documentContents: const foo = function bar() {} + selections: + - anchor: {line: 0, character: 12} + active: {line: 0, character: 12} + marks: {} +finalState: + documentContents: "const foo = " + selections: + - anchor: {line: 0, character: 12} + active: {line: 0, character: 12} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunk9.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunk9.yml new file mode 100644 index 00000000000..8d2963bf705 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunk9.yml @@ -0,0 +1,18 @@ +languageId: typescript +command: + version: 5 + spokenForm: clear funk + action: {name: clearAndSetSelection} + targets: + - type: primitive + modifiers: + - type: containingScope + scopeType: {type: namedFunction} + usePrePhraseSnapshot: true +initialState: + documentContents: const foo = function bar() {} + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} + marks: {} +thrownError: {name: NoContainingScopeError} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunkName2.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunkName2.yml new file mode 100644 index 00000000000..7926381d370 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunkName2.yml @@ -0,0 +1,22 @@ +languageId: typescript +command: + version: 5 + spokenForm: clear funk name + action: {name: clearAndSetSelection} + targets: + - type: primitive + modifiers: + - type: containingScope + scopeType: {type: functionName} + usePrePhraseSnapshot: true +initialState: + documentContents: export function *aaa() {} + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} + marks: {} +finalState: + documentContents: export function *() {} + selections: + - anchor: {line: 0, character: 17} + active: {line: 0, character: 17} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunkName3.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunkName3.yml new file mode 100644 index 00000000000..56823dad79f --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunkName3.yml @@ -0,0 +1,22 @@ +languageId: typescript +command: + version: 5 + spokenForm: clear funk name + action: {name: clearAndSetSelection} + targets: + - type: primitive + modifiers: + - type: containingScope + scopeType: {type: functionName} + usePrePhraseSnapshot: true +initialState: + documentContents: (function foo() {}) + selections: + - anchor: {line: 0, character: 1} + active: {line: 0, character: 1} + marks: {} +finalState: + documentContents: (function () {}) + selections: + - anchor: {line: 0, character: 10} + active: {line: 0, character: 10} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunkName4.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunkName4.yml new file mode 100644 index 00000000000..054fcd26b5f --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunkName4.yml @@ -0,0 +1,22 @@ +languageId: typescript +command: + version: 5 + spokenForm: clear funk name + action: {name: clearAndSetSelection} + targets: + - type: primitive + modifiers: + - type: containingScope + scopeType: {type: functionName} + usePrePhraseSnapshot: true +initialState: + documentContents: export const myFunk = () => {}; + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} + marks: {} +finalState: + documentContents: export const = () => {}; + selections: + - anchor: {line: 0, character: 13} + active: {line: 0, character: 13} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunkName5.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunkName5.yml new file mode 100644 index 00000000000..0da9351070d --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunkName5.yml @@ -0,0 +1,22 @@ +languageId: typescript +command: + version: 5 + spokenForm: clear funk name + action: {name: clearAndSetSelection} + targets: + - type: primitive + modifiers: + - type: containingScope + scopeType: {type: functionName} + usePrePhraseSnapshot: true +initialState: + documentContents: const foo = function bar() {} + selections: + - anchor: {line: 0, character: 12} + active: {line: 0, character: 12} + marks: {} +finalState: + documentContents: const foo = function () {} + selections: + - anchor: {line: 0, character: 21} + active: {line: 0, character: 21} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunkName6.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunkName6.yml new file mode 100644 index 00000000000..fda10309b58 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunkName6.yml @@ -0,0 +1,18 @@ +languageId: typescript +command: + version: 5 + spokenForm: clear funk name + action: {name: clearAndSetSelection} + targets: + - type: primitive + modifiers: + - type: containingScope + scopeType: {type: functionName} + usePrePhraseSnapshot: true +initialState: + documentContents: const foo = function bar() {} + selections: + - anchor: {line: 0, character: 0} + active: {line: 0, character: 0} + marks: {} +thrownError: {name: NoContainingScopeError} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunkName7.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunkName7.yml new file mode 100644 index 00000000000..45fc50e47ca --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearFunkName7.yml @@ -0,0 +1,28 @@ +languageId: typescript +command: + version: 5 + spokenForm: clear funk name + action: {name: clearAndSetSelection} + targets: + - type: primitive + modifiers: + - type: containingScope + scopeType: {type: functionName} + usePrePhraseSnapshot: true +initialState: + documentContents: |- + interface Aaa { + bbb(): void; + } + selections: + - anchor: {line: 1, character: 16} + active: {line: 1, character: 16} + marks: {} +finalState: + documentContents: |- + interface Aaa { + (): void; + } + selections: + - anchor: {line: 1, character: 4} + active: {line: 1, character: 4} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearLambda5.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearLambda5.yml new file mode 100644 index 00000000000..fcec61dc966 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearLambda5.yml @@ -0,0 +1,22 @@ +languageId: typescript +command: + version: 5 + spokenForm: clear lambda + action: {name: clearAndSetSelection} + targets: + - type: primitive + modifiers: + - type: containingScope + scopeType: {type: anonymousFunction} + usePrePhraseSnapshot: true +initialState: + documentContents: (function () {}) + selections: + - anchor: {line: 0, character: 1} + active: {line: 0, character: 1} + marks: {} +finalState: + documentContents: () + selections: + - anchor: {line: 0, character: 1} + active: {line: 0, character: 1} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearLambda6.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearLambda6.yml new file mode 100644 index 00000000000..0b2641cc14d --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearLambda6.yml @@ -0,0 +1,18 @@ +languageId: typescript +command: + version: 5 + spokenForm: clear lambda + action: {name: clearAndSetSelection} + targets: + - type: primitive + modifiers: + - type: containingScope + scopeType: {type: anonymousFunction} + usePrePhraseSnapshot: true +initialState: + documentContents: (function bar() {}) + selections: + - anchor: {line: 0, character: 1} + active: {line: 0, character: 1} + marks: {} +thrownError: {name: NoContainingScopeError} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearLambda7.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearLambda7.yml new file mode 100644 index 00000000000..2f6b3d76754 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/clearLambda7.yml @@ -0,0 +1,18 @@ +languageId: typescript +command: + version: 5 + spokenForm: clear lambda + action: {name: clearAndSetSelection} + targets: + - type: primitive + modifiers: + - type: containingScope + scopeType: {type: anonymousFunction} + usePrePhraseSnapshot: true +initialState: + documentContents: (function *bar() {}) + selections: + - anchor: {line: 0, character: 1} + active: {line: 0, character: 1} + marks: {} +thrownError: {name: NoContainingScopeError} diff --git a/queries/javascript.core.scm b/queries/javascript.core.scm index 93ec9109aac..7e5f3f7629f 100644 --- a/queries/javascript.core.scm +++ b/queries/javascript.core.scm @@ -1,3 +1,5 @@ +;; import javascript.function.scm + (_ name: (_) @name ) @_.domain diff --git a/queries/javascript.function.scm b/queries/javascript.function.scm new file mode 100644 index 00000000000..d624c93fb14 --- /dev/null +++ b/queries/javascript.function.scm @@ -0,0 +1,174 @@ +;; Anonymous functions +[ + ;; function() {} + (function + !name + ) + + ;; function *() {} + (generator_function + !name + ) + + ;; () => {} + (arrow_function) +] @anonymousFunction + +;; If we export an anonymous function as default, it semantically feels like a +;; named function. +(export_statement + [ + ;; export default function() {} + (function + !name + ) + + ;; export default function *() {} + (generator_function + !name + ) + + ;; export default () => {} + (arrow_function) + ] +) @namedFunction + +;; Named functions without export +( + [ + ;; function foo() {} + (function_declaration + name: (_) @functionName + ) + + ;; function *foo() {} + (generator_function_declaration + name: (_) @functionName + ) + + ;; (let | const) foo = () => {} + ;; (let | const) foo = function() {} + ;; (let | const) foo = function *() {} + (lexical_declaration + (variable_declarator + name: (_) @functionName + [ + (function + !name + ) + (generator_function + !name + ) + (arrow_function) + ] + ) + ) + + ;; var foo = () => {} + ;; var foo = function() {} + ;; var foo = function *() {} + ;; Note that we can't merge this with the variable declaration above because + ;; of https://github.com/tree-sitter/tree-sitter/issues/1442#issuecomment-1584628651 + (variable_declaration + (variable_declarator + name: (_) @functionName + [ + (function + !name + ) + (generator_function + !name + ) + (arrow_function) + ] + ) + ) + ] @namedFunction @functionName.domain + (#not-parent-type? @namedFunction export_statement) +) + +;; Exported named functions +(export_statement + [ + ;; export [default] function foo() {} + (function_declaration + name: (_) @functionName + ) + + ;; export [default] function *foo() {} + (generator_function_declaration + name: (_) @functionName + ) + + ;; export [default] (let | const | var) foo = () => {} + ;; export [default] (let | const | var) foo = function() {} + ;; export [default] (let | const | var) foo = function *() {} + (_ + (variable_declarator + name: (_) @functionName + [ + (function + !name + ) + (generator_function + !name + ) + (arrow_function) + ] + ) + ) + ] +) @namedFunction @functionName.domain + +;; Note that there are a few Typescript-specific function declarations that we +;; don't handle here; see typescript.scm. +[ + ;; (function foo() {}) + (function + name: (_) @functionName + ) + + ;; (function *foo() {}) + (generator_function + name: (_) @functionName + ) + + ;; foo() {} + ;; (in class bodies) + (method_definition + name: (_) @functionName + ) + + ;; foo = () => {}; + ;; foo = function() {}; + ;; foo = function *() {}; + ;; (inside class bodies) + (field_definition + name: (_) @functionName + value: [ + (function + !name + ) + (generator_function + !name + ) + (arrow_function) + ] + ) + + ;; foo = () => {}; + ;; foo = function() {}; + ;; foo = function *() {}; + (assignment_expression + left: (_) @functionName + right: [ + (function + !name + ) + (generator_function + !name + ) + (arrow_function) + ] + ) +] @namedFunction @functionName.domain diff --git a/queries/typescript.scm b/queries/typescript.scm index df1cd0f4565..ca6eb121921 100644 --- a/queries/typescript.scm +++ b/queries/typescript.scm @@ -11,3 +11,38 @@ (required_parameter (identifier) @name ) @_.domain + +( + [ + ;; foo(): void; + ;; (in interface) + ;; foo() {} + ;; (in class) + (method_signature + name: (_) @functionName + ) + + ;; abstract foo(): void; + (abstract_method_signature + name: (_) @functionName + ) + + ;; [public | private | protected] foo = () => {}; + ;; [public | private | protected] foo = function() {}; + ;; [public | private | protected] foo = function *() {}; + (public_field_definition + name: (_) @functionName + value: [ + (function + !name + ) + (generator_function + !name + ) + (arrow_function) + ] + ) + ] @namedFunction.start @functionName.domain.start + . + ";"? @namedFunction.end @functionName.domain.end +)