diff --git a/packages/cursorless-engine/src/languages/typescript.ts b/packages/cursorless-engine/src/languages/typescript.ts index 9b7b2d3270..300cf8f393 100644 --- a/packages/cursorless-engine/src/languages/typescript.ts +++ b/packages/cursorless-engine/src/languages/typescript.ts @@ -1,10 +1,6 @@ import { SimpleScopeTypeType } from "@cursorless/common"; import type { SyntaxNode } from "web-tree-sitter"; -import { - NodeMatcher, - NodeMatcherAlternative, - SelectionWithEditor, -} from "../typings/Types"; +import { NodeMatcherAlternative, SelectionWithEditor } from "../typings/Types"; import { patternFinder } from "../util/nodeFinders"; import { argumentMatcher, @@ -20,9 +16,6 @@ import { extendForwardPastOptional, getNodeInternalRange, getNodeRange, - pairSelectionExtractor, - selectWithLeadingDelimiter, - simpleSelectionExtractor, unwrapSelectionExtractor, } from "../util/nodeSelectors"; import { branchMatcher } from "./branchMatcher"; @@ -69,61 +62,6 @@ const STATEMENT_TYPES = [ "with_statement", ]; -function typeMatcher(): NodeMatcher { - const delimiterSelector = selectWithLeadingDelimiter(":"); - return function (selection: SelectionWithEditor, node: SyntaxNode) { - if ( - node.parent?.type === "new_expression" && - node.type !== "new" && - node.type !== "arguments" - ) { - const identifierNode = node.parent.children.find( - (n) => n.type === "identifier", - ); - const argsNode = node.parent.children.find( - (n) => n.type === "type_arguments", - ); - if (identifierNode && argsNode) { - return [ - { - node, - selection: pairSelectionExtractor( - selection.editor, - identifierNode, - argsNode, - ), - }, - ]; - } else if (identifierNode) { - return [ - { - node: identifierNode, - selection: simpleSelectionExtractor( - selection.editor, - identifierNode, - ), - }, - ]; - } - } - - const typeAnnotationNode = node.children.find((child) => - ["type_annotation", "opting_type_annotation"].includes(child.type), - ); - const targetNode = typeAnnotationNode?.lastChild; - - if (targetNode) { - return [ - { - node: targetNode, - selection: delimiterSelector(selection.editor, targetNode), - }, - ]; - } - return null; - }; -} - const mapTypes = ["object", "object_pattern"]; const listTypes = ["array", "array_pattern"]; @@ -194,25 +132,6 @@ const nodeMatchers: Partial< "export_statement?.abstract_class_declaration", // export abstract class | abstract class "export_statement.class", // export default class ], - type: cascadingMatcher( - // Typed parameters, properties, and functions - typeMatcher(), - // matcher(findTypeNode, selectWithLeadingDelimiter(":")), - patternMatcher( - // Type alias/interface declarations - "export_statement?.type_alias_declaration", - "export_statement?.interface_declaration", - // as type declarations - "as_expression.generic_type!", - "as_expression.predefined_type!", - // satisfies type declaration - "satisfies_expression.generic_type!", - "satisfies_expression.predefined_type!", - // declaration - "type_assertion.type_arguments.generic_type!", - "type_assertion.type_arguments.predefined_type!", - ), - ), argumentOrParameter: argumentMatcher("formal_parameters", "arguments"), // XML, JSX attribute: ["jsx_attribute"], diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/changeEveryType.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/changeEveryType.yml new file mode 100644 index 0000000000..22dce551ce --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/changeEveryType.yml @@ -0,0 +1,29 @@ +languageId: typescript +command: + version: 6 + spokenForm: change every type + action: + name: clearAndSetSelection + target: + type: primitive + modifiers: + - type: everyScope + scopeType: {type: type} + usePrePhraseSnapshot: true +initialState: + documentContents: |- + const aaa: number = 0; + const bbb: number = 0; + selections: + - anchor: {line: 1, character: 22} + active: {line: 1, character: 22} + marks: {} +finalState: + documentContents: |- + const aaa: = 0; + const bbb: = 0; + selections: + - anchor: {line: 0, character: 11} + active: {line: 0, character: 11} + - anchor: {line: 1, character: 11} + active: {line: 1, character: 11} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/changeEveryType2.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/changeEveryType2.yml new file mode 100644 index 0000000000..ea58ee0508 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/changeEveryType2.yml @@ -0,0 +1,33 @@ +languageId: typescript +command: + version: 6 + spokenForm: change every type + action: + name: clearAndSetSelection + target: + type: primitive + modifiers: + - type: everyScope + scopeType: {type: type} + usePrePhraseSnapshot: true +initialState: + documentContents: |- + function ccc() { + const aaa: number = 0; + const bbb: number = 0; + } + selections: + - anchor: {line: 2, character: 26} + active: {line: 2, character: 26} + marks: {} +finalState: + documentContents: |- + function ccc() { + const aaa: = 0; + const bbb: = 0; + } + selections: + - anchor: {line: 1, character: 15} + active: {line: 1, character: 15} + - anchor: {line: 2, character: 15} + active: {line: 2, character: 15} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/changeEveryType3.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/changeEveryType3.yml new file mode 100644 index 0000000000..3aa8f6544f --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/changeEveryType3.yml @@ -0,0 +1,25 @@ +languageId: typescript +command: + version: 6 + spokenForm: change every type + action: + name: clearAndSetSelection + target: + type: primitive + modifiers: + - type: everyScope + scopeType: {type: type} + usePrePhraseSnapshot: true +initialState: + documentContents: "function ccc(aaa: string, bbb: string) {}" + selections: + - anchor: {line: 0, character: 13} + active: {line: 0, character: 13} + marks: {} +finalState: + documentContents: "function ccc(aaa: , bbb: ) {}" + selections: + - anchor: {line: 0, character: 18} + active: {line: 0, character: 18} + - anchor: {line: 0, character: 25} + active: {line: 0, character: 25} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/changeType7.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/changeType7.yml new file mode 100644 index 0000000000..4209ffa5d4 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/changeType7.yml @@ -0,0 +1,113 @@ +languageId: typescript +command: + version: 6 + spokenForm: change type + action: + name: clearAndSetSelection + target: + type: primitive + modifiers: + - type: containingScope + scopeType: {type: type} + usePrePhraseSnapshot: true +initialState: + documentContents: |- + const aaa: number = 0; + let bbb: number = 0; + var hhh: number = 0; + const ddd: number = 0, eee: number = 0; + let fff: number = 0, ggg: number = 0; + var iii: number = 0; + export const jjj: number = 0; + export let kkk: number = 0; + export var lll: number = 0; + export const mmm: number = 0, nnn: number = 0; + export let ooo: number = 0, ppp: number = 0; + let qqq: number; + var rrr: number; + let sss: number, ttt: number; + selections: + - anchor: {line: 0, character: 22} + active: {line: 0, character: 22} + - anchor: {line: 1, character: 20} + active: {line: 1, character: 20} + - anchor: {line: 2, character: 20} + active: {line: 2, character: 20} + - anchor: {line: 3, character: 39} + active: {line: 3, character: 39} + - anchor: {line: 4, character: 37} + active: {line: 4, character: 37} + - anchor: {line: 5, character: 20} + active: {line: 5, character: 20} + - anchor: {line: 6, character: 29} + active: {line: 6, character: 29} + - anchor: {line: 7, character: 27} + active: {line: 7, character: 27} + - anchor: {line: 8, character: 27} + active: {line: 8, character: 27} + - anchor: {line: 9, character: 46} + active: {line: 9, character: 46} + - anchor: {line: 10, character: 44} + active: {line: 10, character: 44} + - anchor: {line: 11, character: 16} + active: {line: 11, character: 16} + - anchor: {line: 12, character: 16} + active: {line: 12, character: 16} + - anchor: {line: 13, character: 29} + active: {line: 13, character: 29} + marks: {} +finalState: + documentContents: |- + const aaa: = 0; + let bbb: = 0; + var hhh: = 0; + 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; + let qqq: ; + var rrr: ; + let sss: , ttt: ; + selections: + - anchor: {line: 0, character: 11} + active: {line: 0, character: 11} + - anchor: {line: 1, character: 9} + active: {line: 1, character: 9} + - anchor: {line: 2, character: 9} + active: {line: 2, character: 9} + - anchor: {line: 3, character: 11} + active: {line: 3, character: 11} + - anchor: {line: 3, character: 22} + active: {line: 3, character: 22} + - anchor: {line: 4, character: 9} + active: {line: 4, character: 9} + - anchor: {line: 4, character: 20} + active: {line: 4, character: 20} + - anchor: {line: 5, character: 9} + active: {line: 5, character: 9} + - anchor: {line: 6, character: 18} + active: {line: 6, character: 18} + - anchor: {line: 7, character: 16} + active: {line: 7, character: 16} + - anchor: {line: 8, character: 16} + active: {line: 8, character: 16} + - anchor: {line: 9, character: 18} + active: {line: 9, character: 18} + - anchor: {line: 9, character: 29} + active: {line: 9, character: 29} + - anchor: {line: 10, character: 16} + active: {line: 10, character: 16} + - anchor: {line: 10, character: 27} + active: {line: 10, character: 27} + - anchor: {line: 11, character: 9} + active: {line: 11, character: 9} + - anchor: {line: 12, character: 9} + active: {line: 12, character: 9} + - anchor: {line: 13, character: 9} + active: {line: 13, character: 9} + - anchor: {line: 13, character: 16} + active: {line: 13, character: 16} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/changeType8.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/changeType8.yml new file mode 100644 index 0000000000..bceb2cd1ff --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/changeType8.yml @@ -0,0 +1,43 @@ +languageId: typescript +command: + version: 6 + spokenForm: change type + action: + name: clearAndSetSelection + target: + type: primitive + modifiers: + - type: containingScope + scopeType: {type: type} + usePrePhraseSnapshot: true +initialState: + documentContents: |- + const ddd: number = 0, eee: number = 0; + let fff: number = 0, ggg: number = 0; + export const mmm: number = 0, nnn: number = 0; + export let ooo: number = 0, ppp: number = 0; + selections: + - anchor: {line: 0, character: 38} + active: {line: 0, character: 38} + - anchor: {line: 1, character: 36} + active: {line: 1, character: 36} + - anchor: {line: 2, character: 45} + active: {line: 2, character: 45} + - anchor: {line: 3, character: 43} + active: {line: 3, character: 43} + marks: {} +finalState: + documentContents: |- + const ddd: number = 0, eee: = 0; + let fff: number = 0, ggg: = 0; + export const mmm: number = 0, nnn: = 0; + export let ooo: number = 0, ppp: = 0; + selections: + - anchor: {line: 0, character: 28} + active: {line: 0, character: 28} + - anchor: {line: 1, character: 26} + active: {line: 1, character: 26} + - anchor: {line: 2, character: 35} + active: {line: 2, character: 35} + - anchor: {line: 3, character: 33} + active: {line: 3, character: 33} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/chuckName.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/chuckName.yml new file mode 100644 index 0000000000..98d3b3a125 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/chuckName.yml @@ -0,0 +1,55 @@ +languageId: typescript +command: + version: 6 + spokenForm: chuck name + action: + name: remove + target: + type: primitive + modifiers: + - type: containingScope + scopeType: {type: name} + usePrePhraseSnapshot: true +initialState: + documentContents: |- + const aaa: number = 0; + let bbb: number = 0; + var hhh: number = 0; + const ddd: number = 0, eee: number = 0; + let fff: number = 0, ggg: number = 0; + var iii: number = 0; + selections: + - anchor: {line: 0, character: 22} + active: {line: 0, character: 22} + - anchor: {line: 1, character: 20} + active: {line: 1, character: 20} + - anchor: {line: 2, character: 20} + active: {line: 2, character: 20} + - anchor: {line: 3, character: 39} + active: {line: 3, character: 39} + - anchor: {line: 4, character: 37} + active: {line: 4, character: 37} + - anchor: {line: 5, character: 20} + active: {line: 5, character: 20} + marks: {} +finalState: + documentContents: |- + 0; + 0; + 0; + 0, 0; + 0, 0; + 0; + selections: + - anchor: {line: 0, character: 2} + active: {line: 0, character: 2} + - anchor: {line: 1, character: 2} + active: {line: 1, character: 2} + - anchor: {line: 2, character: 2} + active: {line: 2, character: 2} + - anchor: {line: 3, character: 5} + active: {line: 3, character: 5} + - anchor: {line: 4, character: 5} + active: {line: 4, character: 5} + - anchor: {line: 5, character: 2} + active: {line: 5, character: 2} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/chuckType.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/chuckType.yml new file mode 100644 index 0000000000..b5384c9514 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/chuckType.yml @@ -0,0 +1,103 @@ +languageId: typescript +command: + version: 6 + spokenForm: chuck type + action: + name: remove + target: + type: primitive + modifiers: + - type: containingScope + scopeType: {type: type} + usePrePhraseSnapshot: true +initialState: + documentContents: |- + const aaa: number = 0; + let bbb: number = 0; + var hhh: number = 0; + const ddd: number = 0, eee: number = 0; + let fff: number = 0, ggg: number = 0; + var iii: number = 0; + export const jjj: number = 0; + export let kkk: number = 0; + export var lll: number = 0; + export const mmm: number = 0, nnn: number = 0; + export let ooo: number = 0, ppp: number = 0; + let qqq: number; + var rrr: number; + let sss: number, ttt: number; + selections: + - anchor: {line: 0, character: 22} + active: {line: 0, character: 22} + - anchor: {line: 1, character: 20} + active: {line: 1, character: 20} + - anchor: {line: 2, character: 20} + active: {line: 2, character: 20} + - anchor: {line: 3, character: 39} + active: {line: 3, character: 39} + - anchor: {line: 4, character: 37} + active: {line: 4, character: 37} + - anchor: {line: 5, character: 20} + active: {line: 5, character: 20} + - anchor: {line: 6, character: 29} + active: {line: 6, character: 29} + - anchor: {line: 7, character: 27} + active: {line: 7, character: 27} + - anchor: {line: 8, character: 27} + active: {line: 8, character: 27} + - anchor: {line: 9, character: 46} + active: {line: 9, character: 46} + - anchor: {line: 10, character: 44} + active: {line: 10, character: 44} + - anchor: {line: 11, character: 16} + active: {line: 11, character: 16} + - anchor: {line: 12, character: 16} + active: {line: 12, character: 16} + - anchor: {line: 13, character: 29} + active: {line: 13, character: 29} + marks: {} +finalState: + documentContents: |- + const aaa = 0; + let bbb = 0; + var hhh = 0; + 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; + let qqq; + var rrr; + let sss, ttt; + 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: 23} + active: {line: 3, character: 23} + - anchor: {line: 4, character: 21} + active: {line: 4, character: 21} + - anchor: {line: 5, character: 12} + active: {line: 5, character: 12} + - anchor: {line: 6, character: 21} + active: {line: 6, character: 21} + - anchor: {line: 7, character: 19} + active: {line: 7, character: 19} + - anchor: {line: 8, character: 19} + active: {line: 8, character: 19} + - anchor: {line: 9, character: 30} + active: {line: 9, character: 30} + - anchor: {line: 10, character: 28} + active: {line: 10, character: 28} + - anchor: {line: 11, character: 8} + active: {line: 11, character: 8} + - anchor: {line: 12, character: 8} + active: {line: 12, character: 8} + - anchor: {line: 13, character: 13} + active: {line: 13, character: 13} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/chuckType2.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/chuckType2.yml new file mode 100644 index 0000000000..bf4a234195 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/chuckType2.yml @@ -0,0 +1,43 @@ +languageId: typescript +command: + version: 6 + spokenForm: chuck type + action: + name: remove + target: + type: primitive + modifiers: + - type: containingScope + scopeType: {type: type} + usePrePhraseSnapshot: true +initialState: + documentContents: |- + const ddd: number = 0, eee: number = 0; + let fff: number = 0, ggg: number = 0; + export const mmm: number = 0, nnn: number = 0; + export let ooo: number = 0, ppp: number = 0; + selections: + - anchor: {line: 0, character: 38} + active: {line: 0, character: 38} + - anchor: {line: 1, character: 36} + active: {line: 1, character: 36} + - anchor: {line: 2, character: 45} + active: {line: 2, character: 45} + - anchor: {line: 3, character: 43} + active: {line: 3, character: 43} + marks: {} +finalState: + documentContents: |- + const ddd: number = 0, eee = 0; + let fff: number = 0, ggg = 0; + export const mmm: number = 0, nnn = 0; + export let ooo: number = 0, ppp = 0; + selections: + - anchor: {line: 0, character: 30} + active: {line: 0, character: 30} + - anchor: {line: 1, character: 28} + active: {line: 1, character: 28} + - anchor: {line: 2, character: 37} + active: {line: 2, character: 37} + - anchor: {line: 3, character: 35} + active: {line: 3, character: 35} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/chuckType3.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/chuckType3.yml new file mode 100644 index 0000000000..98c66b1bdf --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/chuckType3.yml @@ -0,0 +1,23 @@ +languageId: typescript +command: + version: 6 + spokenForm: chuck type + action: + name: remove + target: + type: primitive + modifiers: + - type: containingScope + scopeType: {type: type} + usePrePhraseSnapshot: true +initialState: + documentContents: const aaa = bbb; + selections: + - anchor: {line: 0, character: 23} + active: {line: 0, character: 23} + marks: {} +finalState: + documentContents: const aaa = bbb; + selections: + - anchor: {line: 0, character: 15} + active: {line: 0, character: 15} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/chuckType4.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/chuckType4.yml new file mode 100644 index 0000000000..353fae2e9f --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/chuckType4.yml @@ -0,0 +1,31 @@ +languageId: typescript +command: + version: 6 + spokenForm: chuck type + action: + name: remove + target: + type: primitive + modifiers: + - type: containingScope + scopeType: {type: type} + usePrePhraseSnapshot: true +initialState: + documentContents: |- + const aaa = bbb as string; + const ccc = ddd satisfies string; + selections: + - anchor: {line: 0, character: 12} + active: {line: 0, character: 12} + - anchor: {line: 1, character: 12} + active: {line: 1, character: 12} + marks: {} +finalState: + documentContents: |- + const aaa = bbb; + const ccc = ddd; + selections: + - anchor: {line: 0, character: 12} + active: {line: 0, character: 12} + - anchor: {line: 1, character: 12} + active: {line: 1, character: 12} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/chuckValue2.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/chuckValue2.yml new file mode 100644 index 0000000000..d48d3e78e4 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/chuckValue2.yml @@ -0,0 +1,85 @@ +languageId: typescript +command: + version: 6 + spokenForm: chuck value + action: + name: remove + target: + type: primitive + modifiers: + - type: containingScope + scopeType: {type: value} + usePrePhraseSnapshot: true +initialState: + documentContents: |- + const aaa: number = 0; + let bbb: number = 0; + var hhh: number = 0; + const ddd: number = 0, eee: number = 0; + let fff: number = 0, ggg: number = 0; + var iii: number = 0; + export const jjj: number = 0; + export let kkk: number = 0; + export var lll: number = 0; + export const mmm: number = 0, nnn: number = 0; + export let ooo: number = 0, ppp: number = 0; + selections: + - anchor: {line: 0, character: 22} + active: {line: 0, character: 22} + - anchor: {line: 1, character: 20} + active: {line: 1, character: 20} + - anchor: {line: 2, character: 20} + active: {line: 2, character: 20} + - anchor: {line: 3, character: 39} + active: {line: 3, character: 39} + - anchor: {line: 4, character: 37} + active: {line: 4, character: 37} + - anchor: {line: 5, character: 20} + active: {line: 5, character: 20} + - anchor: {line: 6, character: 29} + active: {line: 6, character: 29} + - anchor: {line: 7, character: 27} + active: {line: 7, character: 27} + - anchor: {line: 8, character: 27} + active: {line: 8, character: 27} + - anchor: {line: 9, character: 46} + active: {line: 9, character: 46} + - anchor: {line: 10, character: 44} + active: {line: 10, character: 44} + marks: {} +finalState: + documentContents: |- + const aaa: number; + let bbb: number; + var hhh: number; + const ddd: number, eee: number; + let fff: number, ggg: number; + var iii: number; + export const jjj: number; + export let kkk: number; + export var lll: number; + export const mmm: number, nnn: number; + export let ooo: number, ppp: number; + selections: + - anchor: {line: 0, character: 18} + active: {line: 0, character: 18} + - anchor: {line: 1, character: 16} + active: {line: 1, character: 16} + - anchor: {line: 2, character: 16} + active: {line: 2, character: 16} + - anchor: {line: 3, character: 31} + active: {line: 3, character: 31} + - anchor: {line: 4, character: 29} + active: {line: 4, character: 29} + - anchor: {line: 5, character: 16} + active: {line: 5, character: 16} + - anchor: {line: 6, character: 25} + active: {line: 6, character: 25} + - anchor: {line: 7, character: 23} + active: {line: 7, character: 23} + - anchor: {line: 8, character: 23} + active: {line: 8, character: 23} + - anchor: {line: 9, character: 38} + active: {line: 9, character: 38} + - anchor: {line: 10, character: 36} + active: {line: 10, character: 36} diff --git a/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/chuckValue3.yml b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/chuckValue3.yml new file mode 100644 index 0000000000..a282ba6508 --- /dev/null +++ b/packages/cursorless-vscode-e2e/src/suite/fixtures/recorded/languages/typescript/chuckValue3.yml @@ -0,0 +1,43 @@ +languageId: typescript +command: + version: 6 + spokenForm: chuck value + action: + name: remove + target: + type: primitive + modifiers: + - type: containingScope + scopeType: {type: value} + usePrePhraseSnapshot: true +initialState: + documentContents: |- + const ddd: number = 0, eee: number = 0; + let fff: number = 0, ggg: number = 0; + export const mmm: number = 0, nnn: number = 0; + export let ooo: number = 0, ppp: number = 0; + selections: + - anchor: {line: 0, character: 38} + active: {line: 0, character: 38} + - anchor: {line: 1, character: 36} + active: {line: 1, character: 36} + - anchor: {line: 2, character: 45} + active: {line: 2, character: 45} + - anchor: {line: 3, character: 43} + active: {line: 3, character: 43} + marks: {} +finalState: + documentContents: |- + const ddd: number = 0, eee: number; + let fff: number = 0, ggg: number; + export const mmm: number = 0, nnn: number; + export let ooo: number = 0, ppp: number; + selections: + - anchor: {line: 0, character: 34} + active: {line: 0, character: 34} + - anchor: {line: 1, character: 32} + active: {line: 1, character: 32} + - anchor: {line: 2, character: 41} + active: {line: 2, character: 41} + - anchor: {line: 3, character: 39} + active: {line: 3, character: 39} diff --git a/queries/javascript.core.scm b/queries/javascript.core.scm index 9f55bee43d..371adda430 100644 --- a/queries/javascript.core.scm +++ b/queries/javascript.core.scm @@ -47,8 +47,8 @@ (lexical_declaration . (variable_declarator - name: (_) @name @name.removal.end.endOf @value.leading.start.endOf - value: (_)? @value @name.removal.end.startOf @value.leading.end.startOf + name: (_) @name @name.removal.end.endOf + value: (_)? @name.removal.end.startOf ) ) @@ -67,8 +67,8 @@ (variable_declaration . (variable_declarator - name: (_) @name @name.removal.end.endOf @value.leading.start.endOf - value: (_)? @value @name.removal.end.startOf @value.leading.end.startOf + name: (_) @name @name.removal.end.endOf + value: (_)? @name.removal.end.startOf ) ) ] @_.domain @name.removal.start.startOf @@ -78,7 +78,6 @@ ;;!! (let | const | var) aaa = ..., ccc = ...; ;;! --------------------^^^--------^^^------- (#allow-multiple! @name) - (#allow-multiple! @value) ) ;; Note that the same domains below will also have the first variable @@ -99,8 +98,8 @@ (variable_declarator) . (variable_declarator - name: (_) @name @name.trailing.start.endOf @value.leading.start.endOf - value: (_)? @value @name.trailing.end.startOf @value.leading.end.startOf + name: (_) @name @name.trailing.start.endOf + value: (_)? @name.trailing.end.startOf ) ) @@ -120,8 +119,8 @@ (variable_declarator) . (variable_declarator - name: (_) @name @name.trailing.start.endOf @value.leading.start.endOf - value: (_)? @value @name.trailing.end.startOf @value.leading.end.startOf + name: (_) @name @name.trailing.start.endOf + value: (_)? @name.trailing.end.startOf ) ) ] @_.domain @@ -131,7 +130,6 @@ ;;!! (let | const | var) aaa = ..., ccc = ...; ;;! --------------------^^^--------^^^------- (#allow-multiple! @name) - (#allow-multiple! @value) ) ( @@ -148,8 +146,8 @@ ;;! xxxx ;;! ----------------------------------- (variable_declarator - name: (_) @name @name.trailing.start.endOf @value.leading.start.endOf - value: (_)? @value @name.trailing.end.startOf @value.leading.end.startOf + name: (_) @name @name.trailing.start.endOf + value: (_)? @name.trailing.end.startOf ) ) ) @_.domain @@ -158,7 +156,6 @@ ;;!! var foo = ..., bar = ...; ;;! ----^^^--------^^^------- (#allow-multiple! @name) - (#allow-multiple! @value) ) ;; name: @@ -171,36 +168,106 @@ ;;! ^ ;;! xxxx ;;! ------- -( - (_ - . - (variable_declarator - name: (_) @name @name.removal.end.endOf @value.leading.start.endOf - value: (_)? @value @name.removal.end.startOf @value.leading.end.startOf - ) @_.domain - . - (variable_declarator) - ) @dummy @name.removal.start.startOf -) +(_ + . + (variable_declarator + name: (_) @name @name.removal.end.endOf + value: (_)? @name.removal.end.startOf + ) @_.domain + . + (variable_declarator) +) @name.removal.start.startOf -;; name: -;;!! (const | let | var) aaa = 0, bbb = 0; -;;!1 ^^^ -;;!1 xxxxxx -;;!1 ------- -;; value: ;;!! (const | let | var) aaa = 0, bbb = 0; -;;!1 ^ -;;!1 xxxx -;;!1 ------- +;;! ^^^ +;;! xxxxxx +;;! ------- (_ (variable_declarator) . (variable_declarator - name: (_) @name @name.trailing.start.endOf @value.leading.start.endOf - value: (_)? @value @name.trailing.end.startOf @value.leading.end.startOf + name: (_) @name @name.trailing.start.endOf + value: (_)? @name.trailing.end.startOf ) @_.domain -) @dummy +) + +;; Special cases for `(let | const | var) foo = ...;` because the full statement +;; is actually a grandparent of the `name` node, so we want the domain to include +;; this full grandparent statement. +( + [ + ;;!! (const | let) aaa: Bbb = 0; + ;;! ^ + ;;! xxxx + ;;! --------------------------- + (lexical_declaration + (variable_declarator + (_) @value.leading.start.endOf + . + value: (_)? @value @value.leading.end.startOf + ) + ) + + ;;!! var aaa: Bbb = 0; + ;;! ^ + ;;! xxxx + ;;! ----------------- + ;; 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 + (_) @value.leading.start.endOf + . + value: (_)? @value @value.leading.end.startOf + ) + ) + ] @_.domain + (#not-parent-type? @_.domain export_statement) + + ;; Handle multiple variable declarators in one statement, eg + ;;!! (let | const | var) aaa: Bbb = ..., ccc: Ddd = ...; + ;;! -------------------------------^^^-------------^^^- + (#allow-multiple! @value) +) + +( + (export_statement + (_ + ;;!! export (const | let | var) aaa: Bbb = 0; + ;;! ^ + ;;! xxxx + ;;! ---------------------------------------- + (variable_declarator + (_) @value.leading.start.endOf + . + value: (_)? @value @value.leading.end.startOf + ) + ) + ) @_.domain + + ;; Handle multiple variable declarators in one statement, eg + ;;!! export (let | const | var) aaa: Bbb = ..., ccc: Ddd = ...; + ;;! --------------------------------------^^^-------------^^^- + (#allow-multiple! @value) +) + +;;!! (const | let | var) aaa: Ccc = 0, bbb: Ddd = 0; +;;!1 ^ +;;!1 xxxx +;;!1 ------------ +;;!2 ^ +;;!2 xxxx +;;!2 ------------ +( + (_ + (variable_declarator + (_) @value.leading.start.endOf + . + value: (_)? @value @value.leading.end.startOf + ) @_.domain + ) @dummy + (#has-multiple-children-of-type? @dummy variable_declarator) +) (expression_statement [ @@ -327,7 +394,7 @@ [ (program) (formal_parameters) -] @name.iteration @value.iteration +] @name.iteration @value.iteration @type.iteration ;; Treat interior of all bodies as iteration scopes for `name`, eg ;;!! function foo() { } @@ -335,8 +402,8 @@ (_ body: (_ . - "{" @name.iteration.start.endOf @value.iteration.start.endOf - "}" @name.iteration.end.startOf @value.iteration.end.startOf + "{" @name.iteration.start.endOf @value.iteration.start.endOf @type.iteration.start.endOf + "}" @name.iteration.end.startOf @value.iteration.end.startOf @type.iteration.end.startOf . ) ) diff --git a/queries/typescript.core.scm b/queries/typescript.core.scm new file mode 100644 index 0000000000..12ec9443e8 --- /dev/null +++ b/queries/typescript.core.scm @@ -0,0 +1,217 @@ +;; Note that we don't just import `javascript.scm` because that includes +;; `javascript.jsx.scm`, and tree-sitter would complain because those node +;; types are not defined in the typescript grammar. + +;; import javascript.core.scm + +;;!! function aaa(bbb?: Ccc = "ddd") {} +;;! ^^^-------------- +(optional_parameter + (identifier) @name +) @_.domain + +;;!! function aaa(bbb: Ccc = "ddd") {} +;;! ^^^------------- +(required_parameter + (identifier) @name +) @_.domain + +;; Define these here because these node types don't exist in javascript. +( + [ + ;;!! class Foo { foo() {} } + ;;! ^^^^^^^^ + ;;!! interface Foo { foo(): void; } + ;;! ^^^^^^^^^^^^ + (method_signature + name: (_) @functionName @name + ) + + ;;!! class Foo { abstract foo(): void; } + ;;! ^^^^^^^^^^^^^^^^^^^^^ + (abstract_method_signature + name: (_) @functionName @name + ) + + ;;!! class Foo { + ;;!! (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 @name.domain.start + . + ";"? @namedFunction.end @functionName.domain.end @name.domain.end +) + +( + ;;!! (public | private | protected) foo = ...; + ;;! -------------------------------^^^------- + (public_field_definition + name: (_) @name + ) @name.domain.start + . + ";"? @name.domain.end +) + +[ + (interface_declaration) + (object_type) +] @namedFunction.iteration @functionName.iteration + +;; Special cases for `(let | const | var) foo = ...;` because the full statement +;; is actually a grandparent of the `name` node, so we want the domain to include +;; this full grandparent statement. +( + [ + ;;!! (const | let) aaa: Bbb = 0; + ;;! ^^^ + ;;! xxxxx + ;;! --------------------------- + (lexical_declaration + (variable_declarator + type: (type_annotation + (_) @type + ) @type.removal + ) + ) + + ;;!! var aaa: Bbb = 0; + ;;! ^^^ + ;;! xxxxx + ;;! ----------------- + ;; 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 + type: (type_annotation + (_) @type + ) @type.removal + ) + ) + ] @_.domain + (#not-parent-type? @_.domain export_statement) + + ;; Handle multiple variable declarators in one statement, eg + ;;!! (let | const | var) aaa: Bbb = ..., ccc: Ddd = ...; + ;;! -------------------------^^^-------------^^^------- + (#allow-multiple! @type) +) + +( + (export_statement + (_ + ;;!! export (const | let | var) aaa: Bbb = 0; + ;;! ^^^ + ;;! xxxxx + ;;! ---------------------------------------- + (variable_declarator + type: (type_annotation + (_) @type + ) @type.removal + ) + ) + ) @_.domain + + ;; Handle multiple variable declarators in one statement, eg + ;;!! export (let | const | var) aaa: Bbb = ..., ccc: Ddd = ...; + ;;! --------------------------------^^^-------------^^^------- + (#allow-multiple! @type) +) + +;;!! (const | let | var) aaa: Ccc = 0, bbb: Ddd = 0; +;;!1 ^^^ +;;!1 xxxxx +;;!1 ------------ +;;!2 ^^^ +;;!2 xxxxx +;;!2 ------------ +( + (_ + (variable_declarator + type: (type_annotation + (_) @type + ) @type.removal + ) @_.domain + ) @dummy + (#has-multiple-children-of-type? @dummy variable_declarator) +) + +;; Generic type matcher +( + (_ + [ + type: (_ + (_) @type + ) + return_type: (_ + (_) @type + ) + ] @type.removal + ) @_.domain + (#not-type? @_.domain variable_declarator) +) + +;;!! new Aaa() +;;! ^^^^^^^^ +(new_expression + constructor: (_) @type.start + type_arguments: (_)? @type.end +) + +;;!! interface Aaa {} +;;!! type Aaa = Bbb; +( + [ + (type_alias_declaration) + (interface_declaration) + ] @type + (#not-parent-type? @type export_statement) +) + +;;!! export interface Aaa {} +;;!! export type Aaa = Bbb; +(export_statement + [ + (type_alias_declaration) + (interface_declaration) + ] @type +) @_.domain + +;;!! aaa as Bbb +;;! ^^^ +;;! xxxxxxx +;;! ---------- +(as_expression + (_) @_.leading.start.endOf + [ + (generic_type) + (predefined_type) + ] @type @_.leading.end.startOf +) @_.domain + +;;!! aaa satisfies Bbb +;;! ^^^ +;;! xxxxxxxxxxxxxx +;;! ----------------- +(satisfies_expression + (_) @_.leading.start.endOf + [ + (generic_type) + (predefined_type) + ] @type @_.leading.end.startOf +) @_.domain diff --git a/queries/typescript.scm b/queries/typescript.scm index 9e724f2380..f885360bde 100644 --- a/queries/typescript.scm +++ b/queries/typescript.scm @@ -1,74 +1,16 @@ -;; Note that we don't just import `javascript.scm` because that includes -;; `javascript.jsx.scm`, and tree-sitter would complain because those node -;; types are not defined in the typescript grammar. - -;; import javascript.core.scm - -;;!! function aaa(bbb?: Ccc = "ddd") {} -;;! ^^^-------------- -(optional_parameter - (identifier) @name +;; import typescript.core.scm + +;; Define this here because type assertions don't exist in TSX because +;; they are not valid JSX. +;;!! bbb +;;! ^^^ +;;! xxxxx +;;! -------- +(type_assertion + (type_arguments + [ + (generic_type) + (predefined_type) + ] @type + ) @_.removal ) @_.domain - -;;!! function aaa(bbb: Ccc = "ddd") {} -;;! ^^^------------- -(required_parameter - (identifier) @name -) @_.domain - -;; Define these here because these node types don't exist in javascript. -( - [ - ;;!! class Foo { foo() {} } - ;;! ^^^^^^^^ - ;;!! interface Foo { foo(): void; } - ;;! ^^^^^^^^^^^^ - (method_signature - name: (_) @functionName @name - ) - - ;;!! class Foo { abstract foo(): void; } - ;;! ^^^^^^^^^^^^^^^^^^^^^ - (abstract_method_signature - name: (_) @functionName @name - ) - - ;;!! class Foo { - ;;!! (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 @name.domain.start - . - ";"? @namedFunction.end @functionName.domain.end @name.domain.end -) - -( - ;;!! (public | private | protected) foo = ...; - ;;! -------------------------------^^^------- - (public_field_definition - name: (_) @name - ) @name.domain.start - . - ";"? @name.domain.end -) - -[ - (interface_declaration) - (object_type) -] @namedFunction.iteration @functionName.iteration diff --git a/queries/typescriptreact.scm b/queries/typescriptreact.scm index 934357070c..b01d30a0f9 100644 --- a/queries/typescriptreact.scm +++ b/queries/typescriptreact.scm @@ -1,2 +1,2 @@ ;; import javascript.jsx.scm -;; import typescript.scm +;; import typescript.core.scm