From bb9cdec1d6612331a32b29ba85b58c6668cf6e64 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Sun, 1 Jun 2025 11:59:01 +0200 Subject: [PATCH 01/18] Migrate attribute --- .../cursorless-engine/src/languages/rust.ts | 1 - queries/rust.scm | 44 +++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/packages/cursorless-engine/src/languages/rust.ts b/packages/cursorless-engine/src/languages/rust.ts index 1604ea3613..8d318b3804 100644 --- a/packages/cursorless-engine/src/languages/rust.ts +++ b/packages/cursorless-engine/src/languages/rust.ts @@ -222,7 +222,6 @@ const nodeMatchers: Partial< patternMatcher("meta_item[value]", "const_item[value]"), matcher(returnValueFinder), ), - attribute: trailingMatcher(["mutable_specifier", "attribute_item"]), branch: cascadingMatcher( patternMatcher("match_arm"), matcher(patternFinder("else_clause"), elseExtractor("if_expression")), diff --git a/queries/rust.scm b/queries/rust.scm index 1031506c46..2ef0169615 100644 --- a/queries/rust.scm +++ b/queries/rust.scm @@ -1,5 +1,37 @@ ;; https://github.com/tree-sitter/tree-sitter-rust/blob/master/src/grammar.json +;; Generated by the following command: +;; `curl https://raw.githubusercontent.com/tree-sitter/tree-sitter-rust/36ae187ed6dd3803a8a89dbb54f3124c8ee74662/src/node-types.STATEMENT_TYPES | jq '[.[] | select(.type == "_declaration_statement") | .subtypes[].type, "expression_statement"]'` +;; ( +;; (_ +;; [ +;; (associated_type) +;; (attribute_item) +;; (const_item) +;; (empty_statement) +;; (enum_item) +;; (extern_crate_declaration) +;; (foreign_mod_item) +;; (impl_item) +;; (inner_attribute_item) +;; (let_declaration) +;; (macro_definition) +;; (macro_invocation) +;; (function_item) +;; (function_signature_item) +;; (mod_item) +;; (static_item) +;; (struct_item) +;; (trait_item) +;; (type_item) +;; (union_item) +;; (use_declaration) +;; (expression_statement) +;; ] @statement +;; ) @_dummy +;; (#type? @_dummy source_file block declaration_list) +;; ) + [ (if_expression) (if_let_expression) @@ -63,6 +95,18 @@ value: (_) @private.switchStatementSubject ) @_.domain +;;!! #[derive(Debug)] +;;! ^^^^^^^^^^^^^^^^ +(attribute_item) @attribute + +;;!! &mut x; +;;! ^^^ +(_ + (mutable_specifier) @attribute + . + (_) @_.trailing.startOf +) @_.domain + operator: [ "<" "<<" From b8b40144767de39262b908e559b24afdf3c9dd9a Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Sun, 1 Jun 2025 12:00:59 +0200 Subject: [PATCH 02/18] Migrate statement --- .../cursorless-engine/src/languages/rust.ts | 16 +---- queries/rust.scm | 58 +++++++++---------- 2 files changed, 30 insertions(+), 44 deletions(-) diff --git a/packages/cursorless-engine/src/languages/rust.ts b/packages/cursorless-engine/src/languages/rust.ts index 8d318b3804..4d1abebc31 100644 --- a/packages/cursorless-engine/src/languages/rust.ts +++ b/packages/cursorless-engine/src/languages/rust.ts @@ -1,13 +1,11 @@ -import type { TextEditor } from "@cursorless/common"; +import type { SimpleScopeTypeType, TextEditor } from "@cursorless/common"; import type { Node } from "web-tree-sitter"; -import type { SimpleScopeTypeType } from "@cursorless/common"; import type { NodeMatcherAlternative, SelectionWithContext, } from "../typings/Types"; import { patternFinder } from "../util/nodeFinders"; import { - ancestorChainNodeMatcher, argumentMatcher, cascadingMatcher, createPatternMatchers, @@ -50,11 +48,6 @@ const STATEMENT_TYPES = [ "expression_statement", ]; -/** - * Scope types allowed to be parents of a statement - */ -const STATEMENT_PARENT_TYPES = ["source_file", "block", "declaration_list"]; - /** * Returns "impl_item[type]" node higher in the chain * @param node The node which we will start our search from @@ -142,13 +135,6 @@ function returnValueFinder(node: Node) { const nodeMatchers: Partial< Record > = { - statement: ancestorChainNodeMatcher( - [ - patternFinder(...STATEMENT_PARENT_TYPES), - patternFinder(...STATEMENT_TYPES), - ], - 1, - ), condition: cascadingMatcher( patternMatcher("while_expression[condition]", "if_expression[condition]"), matcher( diff --git a/queries/rust.scm b/queries/rust.scm index 2ef0169615..1d3d5c50da 100644 --- a/queries/rust.scm +++ b/queries/rust.scm @@ -2,35 +2,35 @@ ;; Generated by the following command: ;; `curl https://raw.githubusercontent.com/tree-sitter/tree-sitter-rust/36ae187ed6dd3803a8a89dbb54f3124c8ee74662/src/node-types.STATEMENT_TYPES | jq '[.[] | select(.type == "_declaration_statement") | .subtypes[].type, "expression_statement"]'` -;; ( -;; (_ -;; [ -;; (associated_type) -;; (attribute_item) -;; (const_item) -;; (empty_statement) -;; (enum_item) -;; (extern_crate_declaration) -;; (foreign_mod_item) -;; (impl_item) -;; (inner_attribute_item) -;; (let_declaration) -;; (macro_definition) -;; (macro_invocation) -;; (function_item) -;; (function_signature_item) -;; (mod_item) -;; (static_item) -;; (struct_item) -;; (trait_item) -;; (type_item) -;; (union_item) -;; (use_declaration) -;; (expression_statement) -;; ] @statement -;; ) @_dummy -;; (#type? @_dummy source_file block declaration_list) -;; ) +( + (_ + [ + (associated_type) + (attribute_item) + (const_item) + (empty_statement) + (enum_item) + (extern_crate_declaration) + (foreign_mod_item) + (impl_item) + (inner_attribute_item) + (let_declaration) + (macro_definition) + (macro_invocation) + (function_item) + (function_signature_item) + (mod_item) + (static_item) + (struct_item) + (trait_item) + (type_item) + (union_item) + (use_declaration) + (expression_statement) + ] @statement + ) @_dummy + (#type? @_dummy source_file block declaration_list) +) [ (if_expression) From 93d7501feff57cbb0f026221a6490a0077de5978 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Sun, 1 Jun 2025 12:23:32 +0200 Subject: [PATCH 03/18] Migrate collection key --- packages/cursorless-engine/src/languages/rust.ts | 3 --- queries/rust.scm | 14 ++++++++++++++ 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/packages/cursorless-engine/src/languages/rust.ts b/packages/cursorless-engine/src/languages/rust.ts index 4d1abebc31..b2c8c61409 100644 --- a/packages/cursorless-engine/src/languages/rust.ts +++ b/packages/cursorless-engine/src/languages/rust.ts @@ -178,9 +178,6 @@ const nodeMatchers: Partial< "type_parameters", "ordered_field_declaration_list", ), - collectionKey: cascadingMatcher( - trailingMatcher(["field_initializer[name]", "field_pattern[name]"], [":"]), - ), name: cascadingMatcher( patternMatcher( "let_declaration.identifier!", diff --git a/queries/rust.scm b/queries/rust.scm index 1d3d5c50da..a3e1861f83 100644 --- a/queries/rust.scm +++ b/queries/rust.scm @@ -107,6 +107,20 @@ (_) @_.trailing.startOf ) @_.domain +;;!! let Foo {aaa: 1, bbb: 2} +;;! ^^^ ^^^ +(field_initializer + name: (_) @collectionKey + value: (_) @_.trailing.startOf +) @_.domain + +;;!! Foo {aaa: 1, bbb: 2} +;;! ^^^ ^^^ +(field_pattern + name: (_) @collectionKey + pattern: (_) @_.trailing.startOf +) @_.domain + operator: [ "<" "<<" From 833cbffb0db7acb67f9e29c3950d09dc30c93463 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Sun, 1 Jun 2025 13:14:34 +0200 Subject: [PATCH 04/18] Migrate value --- .../recorded/languages/rust/clearValue3.yml | 31 ------- .../recorded/languages/rust/clearValue6.yml | 31 ------- .../recorded/languages/rust/clearValue8.yml | 37 -------- .../recorded/languages/rust/clearValue9.yml | 35 -------- .../cursorless-engine/src/languages/rust.ts | 90 ------------------- queries/rust.scm | 75 +++++++++++++++- 6 files changed, 71 insertions(+), 228 deletions(-) delete mode 100644 data/fixtures/recorded/languages/rust/clearValue3.yml delete mode 100644 data/fixtures/recorded/languages/rust/clearValue6.yml delete mode 100644 data/fixtures/recorded/languages/rust/clearValue8.yml delete mode 100644 data/fixtures/recorded/languages/rust/clearValue9.yml diff --git a/data/fixtures/recorded/languages/rust/clearValue3.yml b/data/fixtures/recorded/languages/rust/clearValue3.yml deleted file mode 100644 index 978542b7c6..0000000000 --- a/data/fixtures/recorded/languages/rust/clearValue3.yml +++ /dev/null @@ -1,31 +0,0 @@ -languageId: rust -command: - version: 6 - spokenForm: change value - action: - name: clearAndSetSelection - target: - type: primitive - modifiers: - - type: containingScope - scopeType: {type: value} - usePrePhraseSnapshot: true -initialState: - documentContents: |- - fn foo() -> i32 { - println!("hello") - return 3; - } - selections: - - anchor: {line: 1, character: 13} - active: {line: 1, character: 13} - marks: {} -finalState: - documentContents: |- - fn foo() -> i32 { - println!("hello") - return ; - } - selections: - - anchor: {line: 2, character: 11} - active: {line: 2, character: 11} diff --git a/data/fixtures/recorded/languages/rust/clearValue6.yml b/data/fixtures/recorded/languages/rust/clearValue6.yml deleted file mode 100644 index 5d43fd5424..0000000000 --- a/data/fixtures/recorded/languages/rust/clearValue6.yml +++ /dev/null @@ -1,31 +0,0 @@ -languageId: rust -command: - version: 6 - spokenForm: change value - action: - name: clearAndSetSelection - target: - type: primitive - modifiers: - - type: containingScope - scopeType: {type: value} - usePrePhraseSnapshot: true -initialState: - documentContents: |- - fn foo() -> i32 { - println!("hello") - return 3 - } - selections: - - anchor: {line: 1, character: 14} - active: {line: 1, character: 14} - marks: {} -finalState: - documentContents: |- - fn foo() -> i32 { - println!("hello") - return - } - selections: - - anchor: {line: 2, character: 11} - active: {line: 2, character: 11} diff --git a/data/fixtures/recorded/languages/rust/clearValue8.yml b/data/fixtures/recorded/languages/rust/clearValue8.yml deleted file mode 100644 index 14b11ae32f..0000000000 --- a/data/fixtures/recorded/languages/rust/clearValue8.yml +++ /dev/null @@ -1,37 +0,0 @@ -languageId: rust -command: - version: 6 - spokenForm: change value - action: - name: clearAndSetSelection - target: - type: primitive - modifiers: - - type: containingScope - scopeType: {type: value} - usePrePhraseSnapshot: true -initialState: - documentContents: |- - fn foo() -> i32 { - if a > b { - println!("hello") - return "hello"; - } - "whatever" - } - selections: - - anchor: {line: 2, character: 18} - active: {line: 2, character: 18} - marks: {} -finalState: - documentContents: |- - fn foo() -> i32 { - if a > b { - println!("hello") - return ; - } - "whatever" - } - selections: - - anchor: {line: 3, character: 15} - active: {line: 3, character: 15} diff --git a/data/fixtures/recorded/languages/rust/clearValue9.yml b/data/fixtures/recorded/languages/rust/clearValue9.yml deleted file mode 100644 index a9ad04c19a..0000000000 --- a/data/fixtures/recorded/languages/rust/clearValue9.yml +++ /dev/null @@ -1,35 +0,0 @@ -languageId: rust -command: - version: 6 - spokenForm: change value - action: - name: clearAndSetSelection - target: - type: primitive - modifiers: - - type: containingScope - scopeType: {type: value} - usePrePhraseSnapshot: true -initialState: - documentContents: |- - fn foo() -> i32 { - if a > b { - println!("hello") - } - "whatever" - } - selections: - - anchor: {line: 2, character: 18} - active: {line: 2, character: 18} - marks: {} -finalState: - documentContents: |- - fn foo() -> i32 { - if a > b { - println!("hello") - } - - } - selections: - - anchor: {line: 4, character: 4} - active: {line: 4, character: 4} diff --git a/packages/cursorless-engine/src/languages/rust.ts b/packages/cursorless-engine/src/languages/rust.ts index b2c8c61409..a42b1e91de 100644 --- a/packages/cursorless-engine/src/languages/rust.ts +++ b/packages/cursorless-engine/src/languages/rust.ts @@ -21,33 +21,6 @@ import { } from "../util/nodeSelectors"; import { elseExtractor, elseIfExtractor } from "./elseIfExtractor"; -// Generated by the following command: -// `curl https://raw.githubusercontent.com/tree-sitter/tree-sitter-rust/36ae187ed6dd3803a8a89dbb54f3124c8ee74662/src/node-types.STATEMENT_TYPES | jq '[.[] | select(.type == "_declaration_statement") | .subtypes[].type, "expression_statement"]'` -const STATEMENT_TYPES = [ - "associated_type", - "attribute_item", - "const_item", - "empty_statement", - "enum_item", - "extern_crate_declaration", - "foreign_mod_item", - "impl_item", - "inner_attribute_item", - "let_declaration", - "macro_definition", - "macro_invocation", - "function_item", - "function_signature_item", - "mod_item", - "static_item", - "struct_item", - "trait_item", - "type_item", - "union_item", - "use_declaration", - "expression_statement", -]; - /** * Returns "impl_item[type]" node higher in the chain * @param node The node which we will start our search from @@ -78,60 +51,6 @@ function traitBoundExtractor( }; } -/** - * Returns the return value node for a given block if we are in a block that has - * a return value. If the return value expression uses the return keyword then - * we return the value itself otherwise we just return the expression - * @param node The node which we might match - * @returns The return value node - */ -function returnValueFinder(node: Node) { - if (node.type !== "block") { - return null; - } - - const { lastNamedChild } = node; - - // The return expression will always be the last statement or expression in - // the block - if (lastNamedChild == null) { - return null; - } - - // If the final name child is an expression statement not a raw expression - // then we only treat it as a return value if it is a return expression. - // Otherwise it is just a normal statement that doesn't return anything - if (lastNamedChild.type === "expression_statement") { - const expression = lastNamedChild.child(0)!; - - if (expression.type === "return_expression") { - return expression.child(1); - } - - return null; - } - - // Any other type of statement is not a return statement so we should not - // match it - if (STATEMENT_TYPES.includes(lastNamedChild.type)) { - return null; - } - - // NB: At this point we have now excluded all statement types of the only other - // possible node is an expression node - - // If it is a return expression then we zoom down to the actual value of the - // return expression. This happens when they say `return foo` with no - // trailing semicolon - if (lastNamedChild.type === "return_expression") { - return lastNamedChild.child(1); - } - - // At this point it is an expression which is not a return expression so we - // just return it as the return value of the block - return lastNamedChild; -} - const nodeMatchers: Partial< Record > = { @@ -196,15 +115,6 @@ const nodeMatchers: Partial< ), trailingMatcher(["field_initializer[name]", "field_pattern[name]"], [":"]), ), - value: cascadingMatcher( - leadingMatcher(["let_declaration[value]"], ["="]), - leadingMatcher( - ["field_initializer[value]", "field_pattern[pattern]"], - [":"], - ), - patternMatcher("meta_item[value]", "const_item[value]"), - matcher(returnValueFinder), - ), branch: cascadingMatcher( patternMatcher("match_arm"), matcher(patternFinder("else_clause"), elseExtractor("if_expression")), diff --git a/queries/rust.scm b/queries/rust.scm index a3e1861f83..7eef653f7f 100644 --- a/queries/rust.scm +++ b/queries/rust.scm @@ -109,18 +109,85 @@ ;;!! let Foo {aaa: 1, bbb: 2} ;;! ^^^ ^^^ +;;! ^ ^ (field_initializer - name: (_) @collectionKey - value: (_) @_.trailing.startOf + name: (_) @collectionKey @value.leading.endOf + value: (_) @value @collectionKey.trailing.startOf ) @_.domain ;;!! Foo {aaa: 1, bbb: 2} ;;! ^^^ ^^^ +;;! ^ ^ (field_pattern - name: (_) @collectionKey - pattern: (_) @_.trailing.startOf + name: (_) @collectionKey @value.leading.endOf + pattern: (_) @value @collectionKey.trailing.startOf ) @_.domain +;;!! const foo: u8 = 2; +;;! ^ +(const_item + (_) @value.leading.endOf + . + value: (_) @value +) @_.domain + +;;!! let foo = 2; +;;! ^ +(let_declaration + (_) @value.leading.endOf + . + value: (_) @value +) @_.domain + +;;!! #[cfg_attr(feature = "foo")] +;;! ^^^^^ +(meta_item + (_) @value.leading.endOf + value: (_) @value +) @_.domain + +;;!! return 2; +;;! ^ +(return_expression + (_) @value +) @_.domain + +;; Implicit return value at end of function body +(function_item + body: (_ + (_) @value + . + ) + (#not-type? + @value + ;; Exclude return expression + return_expression + ;; Exclude all statements + associated_type + attribute_item + const_item + empty_statement + enum_item + extern_crate_declaration + foreign_mod_item + impl_item + inner_attribute_item + let_declaration + macro_definition + macro_invocation + function_item + function_signature_item + mod_item + static_item + struct_item + trait_item + type_item + union_item + use_declaration + expression_statement + ) +) + operator: [ "<" "<<" From 979a7ccdfb1df6f24bc12b33a24d42b1258dc154 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Sun, 1 Jun 2025 14:18:38 +0200 Subject: [PATCH 05/18] Migrate value --- .../languages/rust/changeNameDrum2.yml | 35 ------------ .../languages/rust/changeNameDrum3.yml | 33 ----------- .../languages/rust/changeNameJury.yml | 33 ----------- .../languages/rust/changeNameLook.yml | 33 ----------- .../recorded/languages/rust/chuckNameFine.yml | 33 ----------- .../recorded/languages/rust/chuckNameJury.yml | 33 ----------- .../cursorless-engine/src/languages/rust.ts | 19 ------- queries/rust.scm | 57 +++++++++++++++---- 8 files changed, 47 insertions(+), 229 deletions(-) delete mode 100644 data/fixtures/recorded/languages/rust/changeNameDrum2.yml delete mode 100644 data/fixtures/recorded/languages/rust/changeNameDrum3.yml delete mode 100644 data/fixtures/recorded/languages/rust/changeNameJury.yml delete mode 100644 data/fixtures/recorded/languages/rust/changeNameLook.yml delete mode 100644 data/fixtures/recorded/languages/rust/chuckNameFine.yml delete mode 100644 data/fixtures/recorded/languages/rust/chuckNameJury.yml diff --git a/data/fixtures/recorded/languages/rust/changeNameDrum2.yml b/data/fixtures/recorded/languages/rust/changeNameDrum2.yml deleted file mode 100644 index f6a2766753..0000000000 --- a/data/fixtures/recorded/languages/rust/changeNameDrum2.yml +++ /dev/null @@ -1,35 +0,0 @@ -languageId: rust -command: - version: 6 - spokenForm: change name drum - action: - name: clearAndSetSelection - target: - type: primitive - modifiers: - - type: containingScope - scopeType: {type: name} - mark: {type: decoratedSymbol, symbolColor: default, character: d} - usePrePhraseSnapshot: true -initialState: - documentContents: | - let user = User { - first_name: "John", - last_name: "Doe", - }; - selections: - - anchor: {line: 3, character: 2} - active: {line: 3, character: 2} - marks: - default.d: - start: {line: 2, character: 16} - end: {line: 2, character: 19} -finalState: - documentContents: | - let user = User { - first_name: "John", - : "Doe", - }; - selections: - - anchor: {line: 2, character: 4} - active: {line: 2, character: 4} diff --git a/data/fixtures/recorded/languages/rust/changeNameDrum3.yml b/data/fixtures/recorded/languages/rust/changeNameDrum3.yml deleted file mode 100644 index 69ad4fc939..0000000000 --- a/data/fixtures/recorded/languages/rust/changeNameDrum3.yml +++ /dev/null @@ -1,33 +0,0 @@ -languageId: rust -command: - version: 6 - spokenForm: change name drum - action: - name: clearAndSetSelection - target: - type: primitive - modifiers: - - type: containingScope - scopeType: {type: name} - mark: {type: decoratedSymbol, symbolColor: default, character: d} - usePrePhraseSnapshot: true -initialState: - documentContents: | - match user { - User { first_name: "John", last_name: "Doe" } => {}, - } - selections: - - anchor: {line: 3, character: 0} - active: {line: 3, character: 0} - marks: - default.d: - start: {line: 1, character: 43} - end: {line: 1, character: 46} -finalState: - documentContents: | - match user { - User { first_name: "John", : "Doe" } => {}, - } - selections: - - anchor: {line: 1, character: 31} - active: {line: 1, character: 31} diff --git a/data/fixtures/recorded/languages/rust/changeNameJury.yml b/data/fixtures/recorded/languages/rust/changeNameJury.yml deleted file mode 100644 index a4ed66a40c..0000000000 --- a/data/fixtures/recorded/languages/rust/changeNameJury.yml +++ /dev/null @@ -1,33 +0,0 @@ -languageId: rust -command: - version: 6 - spokenForm: change name jury - action: - name: clearAndSetSelection - target: - type: primitive - modifiers: - - type: containingScope - scopeType: {type: name} - mark: {type: decoratedSymbol, symbolColor: default, character: j} - usePrePhraseSnapshot: true -initialState: - documentContents: | - match user { - User { first_name: "John", last_name: "Doe" } => {}, - } - selections: - - anchor: {line: 3, character: 0} - active: {line: 3, character: 0} - marks: - default.j: - start: {line: 1, character: 24} - end: {line: 1, character: 28} -finalState: - documentContents: | - match user { - User { : "John", last_name: "Doe" } => {}, - } - selections: - - anchor: {line: 1, character: 11} - active: {line: 1, character: 11} diff --git a/data/fixtures/recorded/languages/rust/changeNameLook.yml b/data/fixtures/recorded/languages/rust/changeNameLook.yml deleted file mode 100644 index 2a3d50ab0d..0000000000 --- a/data/fixtures/recorded/languages/rust/changeNameLook.yml +++ /dev/null @@ -1,33 +0,0 @@ -languageId: rust -command: - version: 6 - spokenForm: change name look - action: - name: clearAndSetSelection - target: - type: primitive - modifiers: - - type: containingScope - scopeType: {type: name} - mark: {type: decoratedSymbol, symbolColor: default, character: l} - usePrePhraseSnapshot: true -initialState: - documentContents: | - match user { - User { first_name: "John", last_name: "Doe" } => {}, - } - selections: - - anchor: {line: 3, character: 0} - active: {line: 3, character: 0} - marks: - default.l: - start: {line: 1, character: 31} - end: {line: 1, character: 40} -finalState: - documentContents: | - match user { - User { first_name: "John", : "Doe" } => {}, - } - selections: - - anchor: {line: 1, character: 31} - active: {line: 1, character: 31} diff --git a/data/fixtures/recorded/languages/rust/chuckNameFine.yml b/data/fixtures/recorded/languages/rust/chuckNameFine.yml deleted file mode 100644 index 3e7d179746..0000000000 --- a/data/fixtures/recorded/languages/rust/chuckNameFine.yml +++ /dev/null @@ -1,33 +0,0 @@ -languageId: rust -command: - version: 6 - spokenForm: chuck name fine - action: - name: remove - target: - type: primitive - modifiers: - - type: containingScope - scopeType: {type: name} - mark: {type: decoratedSymbol, symbolColor: default, character: f} - usePrePhraseSnapshot: true -initialState: - documentContents: | - match user { - User { first_name: "John", last_name: last_name } => {} - } - selections: - - anchor: {line: 0, character: 10} - active: {line: 0, character: 10} - marks: - default.f: - start: {line: 1, character: 11} - end: {line: 1, character: 21} -finalState: - documentContents: | - match user { - User { "John", last_name: last_name } => {} - } - selections: - - anchor: {line: 0, character: 10} - active: {line: 0, character: 10} diff --git a/data/fixtures/recorded/languages/rust/chuckNameJury.yml b/data/fixtures/recorded/languages/rust/chuckNameJury.yml deleted file mode 100644 index ad84fb68b7..0000000000 --- a/data/fixtures/recorded/languages/rust/chuckNameJury.yml +++ /dev/null @@ -1,33 +0,0 @@ -languageId: rust -command: - version: 6 - spokenForm: chuck name jury - action: - name: remove - target: - type: primitive - modifiers: - - type: containingScope - scopeType: {type: name} - mark: {type: decoratedSymbol, symbolColor: default, character: j} - usePrePhraseSnapshot: true -initialState: - documentContents: | - match user { - User { first_name: "John", last_name: last_name } => {} - } - selections: - - anchor: {line: 0, character: 10} - active: {line: 0, character: 10} - marks: - default.j: - start: {line: 1, character: 24} - end: {line: 1, character: 28} -finalState: - documentContents: | - match user { - User { "John", last_name: last_name } => {} - } - selections: - - anchor: {line: 0, character: 10} - active: {line: 0, character: 10} diff --git a/packages/cursorless-engine/src/languages/rust.ts b/packages/cursorless-engine/src/languages/rust.ts index a42b1e91de..7f65684ba8 100644 --- a/packages/cursorless-engine/src/languages/rust.ts +++ b/packages/cursorless-engine/src/languages/rust.ts @@ -12,7 +12,6 @@ import { leadingMatcher, matcher, patternMatcher, - trailingMatcher, } from "../util/nodeMatchers"; import { childRangeSelector, @@ -97,24 +96,6 @@ const nodeMatchers: Partial< "type_parameters", "ordered_field_declaration_list", ), - name: cascadingMatcher( - patternMatcher( - "let_declaration.identifier!", - "parameter.identifier!", - "function_item[name]", - "struct_item[name]", - "enum_item[name]", - "enum_variant[name]", - "trait_item[name]", - "const_item[name]", - "meta_item.identifier!", - "let_declaration[pattern]", - "constrained_type_parameter[left]", - "where_predicate[left]", - "field_declaration[name]", - ), - trailingMatcher(["field_initializer[name]", "field_pattern[name]"], [":"]), - ), branch: cascadingMatcher( patternMatcher("match_arm"), matcher(patternFinder("else_clause"), elseExtractor("if_expression")), diff --git a/queries/rust.scm b/queries/rust.scm index 7eef653f7f..a32b0b2c71 100644 --- a/queries/rust.scm +++ b/queries/rust.scm @@ -57,22 +57,48 @@ [ (struct_item - name: (_) @className + name: (_) @className @name ) (enum_item - name: (_) @className + name: (_) @className @name ) -] @class @className.domain +] @class @_.domain (struct_expression) @class +(enum_variant + name: (_) @name +) @_.domain + (trait_item - name: (_) @className + name: (_) @className @name ) @_.domain (function_item - name: (_) @functionName -) @namedFunction @functionName.domain + name: (_) @functionName @name +) @namedFunction @_.domain + +(field_declaration + name: (_) @name +) @_.domain + +;;!! where T: Display + Clone +;;! ^ +(where_predicate + left: (_) @name +) @_.domain + +;;!! (t: &T, u: &U) +;;! ^ ^ +(parameter + pattern: (_) @name +) @_.domain + +;;!! +;;! ^ ^ +(constrained_type_parameter + left: (_) @name +) @_.domain [ (call_expression) @@ -126,23 +152,34 @@ ;;!! const foo: u8 = 2; ;;! ^ (const_item - (_) @value.leading.endOf - . + name: (_) @name + type: (_) @value.leading.endOf value: (_) @value ) @_.domain ;;!! let foo = 2; +;;! ^^^ ;;! ^ (let_declaration - (_) @value.leading.endOf + pattern: (_) @name @value.leading.start.endOf . value: (_) @value ) @_.domain +;;!! let foo: u8 = 2; +;;! ^^^ +;;! ^ +(let_declaration + pattern: (_) @name + type: (_) @value.leading.start.endOf + value: (_) @value +) @_.domain + ;;!! #[cfg_attr(feature = "foo")] +;;! ^^^^^^^ ;;! ^^^^^ (meta_item - (_) @value.leading.endOf + (identifier) @name @value.leading.endOf value: (_) @value ) @_.domain From 56c33f71c36fa804533c667d718c6e4228e5c648 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Sun, 1 Jun 2025 14:43:28 +0200 Subject: [PATCH 06/18] Migrate condition --- .../cursorless-engine/src/languages/rust.ts | 11 ------ queries/rust.scm | 36 +++++++++++++++++++ 2 files changed, 36 insertions(+), 11 deletions(-) diff --git a/packages/cursorless-engine/src/languages/rust.ts b/packages/cursorless-engine/src/languages/rust.ts index 7f65684ba8..a9d7d2d488 100644 --- a/packages/cursorless-engine/src/languages/rust.ts +++ b/packages/cursorless-engine/src/languages/rust.ts @@ -14,7 +14,6 @@ import { patternMatcher, } from "../util/nodeMatchers"; import { - childRangeSelector, makeNodePairSelection, makeRangeFromPositions, } from "../util/nodeSelectors"; @@ -53,16 +52,6 @@ function traitBoundExtractor( const nodeMatchers: Partial< Record > = { - condition: cascadingMatcher( - patternMatcher("while_expression[condition]", "if_expression[condition]"), - matcher( - patternFinder("while_let_expression", "if_let_expression"), - childRangeSelector(["while", "if", "block"], [], { - includeUnnamedChildren: true, - }), - ), - leadingMatcher(["*.match_pattern![condition]"], ["if"]), - ), type: cascadingMatcher( leadingMatcher( [ diff --git a/queries/rust.scm b/queries/rust.scm index a32b0b2c71..fed436e0fa 100644 --- a/queries/rust.scm +++ b/queries/rust.scm @@ -225,6 +225,42 @@ ) ) +;;!! if v < 0 {} +;;! ^^^^^ +(if_expression + condition: (_) @condition +) @_.domain + +;;!! if let Some(i) = number {} +;;! ^^^^^^^^^^^^^^^^ +(if_let_expression + "let" @condition.start + value: (_) @condition.end +) @_.domain + +;;!! while v < 0 {} +;;! ^^^^^ +(while_expression + condition: (_) @condition +) @_.domain + +;;!! while let Some(i) = number {} +;;! ^^^^^^^^^^^^^^^^^^^^ +(while_let_expression + "let" @condition.start + value: (_) @condition.end +) @_.domain + +;;!! User { value } if value.use() => {} +;;! ^^^^^^^^^^^ +(_ + (match_pattern + (_) @_.leading.endOf + . + condition: (_) @condition + ) +) @_.domain + operator: [ "<" "<<" From 834c7aa77699c06e4e9e1ce28a0c7c36114f5b17 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Sun, 1 Jun 2025 15:25:49 +0200 Subject: [PATCH 07/18] Migrate branch --- .../cursorless-engine/src/languages/rust.ts | 6 -- queries/java.scm | 8 +-- queries/rust.scm | 64 ++++++++++++++----- 3 files changed, 51 insertions(+), 27 deletions(-) diff --git a/packages/cursorless-engine/src/languages/rust.ts b/packages/cursorless-engine/src/languages/rust.ts index a9d7d2d488..b1a3c26a9b 100644 --- a/packages/cursorless-engine/src/languages/rust.ts +++ b/packages/cursorless-engine/src/languages/rust.ts @@ -17,7 +17,6 @@ import { makeNodePairSelection, makeRangeFromPositions, } from "../util/nodeSelectors"; -import { elseExtractor, elseIfExtractor } from "./elseIfExtractor"; /** * Returns "impl_item[type]" node higher in the chain @@ -85,11 +84,6 @@ const nodeMatchers: Partial< "type_parameters", "ordered_field_declaration_list", ), - branch: cascadingMatcher( - patternMatcher("match_arm"), - matcher(patternFinder("else_clause"), elseExtractor("if_expression")), - matcher(patternFinder("if_expression"), elseIfExtractor()), - ), }; export default createPatternMatchers(nodeMatchers); diff --git a/queries/java.scm b/queries/java.scm index 2b74e4e0b4..1ea962c8d9 100644 --- a/queries/java.scm +++ b/queries/java.scm @@ -194,8 +194,8 @@ (if_statement "if" @branch.start @branch.removal.start condition: (_) @condition - consequence: (block) @branch.end @branch.removal.end - alternative: (if_statement)? @branch.removal.end.startOf + consequence: (_) @branch.end @branch.removal.end + alternative: (_)? @branch.removal.end.startOf ) @condition.domain (#not-parent-type? @condition.domain "if_statement") (#child-range! @condition 0 -1 true true) @@ -207,7 +207,7 @@ "else" @branch.start @condition.domain.start alternative: (if_statement condition: (_) @condition - consequence: (block) @branch.end @condition.domain.end + consequence: (_) @branch.end @condition.domain.end (#child-range! @condition 0 -1 true true) ) ) @@ -216,7 +216,7 @@ ;;! ^^^^^^^ (if_statement "else" @branch.start - alternative: (block) @branch.end + alternative: (_) @branch.end ) ( diff --git a/queries/rust.scm b/queries/rust.scm index fed436e0fa..d24787b8a9 100644 --- a/queries/rust.scm +++ b/queries/rust.scm @@ -32,10 +32,49 @@ (#type? @_dummy source_file block declaration_list) ) -[ - (if_expression) - (if_let_expression) -] @ifStatement +;;!! if v < 0 {} +;;! ^^^^^^^^^^^ +(if_expression) @ifStatement + +;;!! if let Some(i) = number {} +;;! ^^^^^^^^^^^^^^^^^^^^^^^^^^ +;;! ^^^^^^^^^^^^^^^^ +(if_let_expression + "let" @condition.start + value: (_) @condition.end +) @ifStatement @_.domain + +;;!! if true {} +;;! ^^^^^^^^^^ +(_ + (if_expression + "if" @branch.start @branch.removal.start + condition: (_) @condition + consequence: (_) @branch.end @branch.removal.end + alternative: (else_clause + (if_expression) @branch.removal.end.startOf + )? + ) @condition.domain + (#not-parent-type? @condition.domain else_clause) +) + +;;!! else if true {} +;;! ^^^^^^^^^^^^^^^ +(else_clause + "else" @branch.start @condition.domain.start + (if_expression + condition: (_) @condition + consequence: (_) @branch.end @condition.domain.end + ) +) + +;;!! else {} +;;! ^^^^^^^ +( + (else_clause + (block) + ) @branch +) ;;!! "hello" ( @@ -225,19 +264,6 @@ ) ) -;;!! if v < 0 {} -;;! ^^^^^ -(if_expression - condition: (_) @condition -) @_.domain - -;;!! if let Some(i) = number {} -;;! ^^^^^^^^^^^^^^^^ -(if_let_expression - "let" @condition.start - value: (_) @condition.end -) @_.domain - ;;!! while v < 0 {} ;;! ^^^^^ (while_expression @@ -261,6 +287,10 @@ ) ) @_.domain +;;!! match value { 5 => {} } +;;! ^^^^^^^ +(match_arm) @branch + operator: [ "<" "<<" From a48730d8cc1da1c9f0a105cbf6f31879e8e54fa5 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Sun, 1 Jun 2025 15:39:42 +0200 Subject: [PATCH 08/18] Restore java --- queries/java.scm | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/queries/java.scm b/queries/java.scm index 1ea962c8d9..2b74e4e0b4 100644 --- a/queries/java.scm +++ b/queries/java.scm @@ -194,8 +194,8 @@ (if_statement "if" @branch.start @branch.removal.start condition: (_) @condition - consequence: (_) @branch.end @branch.removal.end - alternative: (_)? @branch.removal.end.startOf + consequence: (block) @branch.end @branch.removal.end + alternative: (if_statement)? @branch.removal.end.startOf ) @condition.domain (#not-parent-type? @condition.domain "if_statement") (#child-range! @condition 0 -1 true true) @@ -207,7 +207,7 @@ "else" @branch.start @condition.domain.start alternative: (if_statement condition: (_) @condition - consequence: (_) @branch.end @condition.domain.end + consequence: (block) @branch.end @condition.domain.end (#child-range! @condition 0 -1 true true) ) ) @@ -216,7 +216,7 @@ ;;! ^^^^^^^ (if_statement "else" @branch.start - alternative: (_) @branch.end + alternative: (block) @branch.end ) ( From 89cc422e46e90ac4da2b653e81943c1bd3ad10e8 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Sun, 1 Jun 2025 23:46:19 +0200 Subject: [PATCH 09/18] Migrate type --- .../cursorless-engine/src/languages/rust.ts | 78 +------------------ queries/rust.scm | 65 ++++++++++++---- 2 files changed, 54 insertions(+), 89 deletions(-) diff --git a/packages/cursorless-engine/src/languages/rust.ts b/packages/cursorless-engine/src/languages/rust.ts index b1a3c26a9b..6a47d0a58f 100644 --- a/packages/cursorless-engine/src/languages/rust.ts +++ b/packages/cursorless-engine/src/languages/rust.ts @@ -1,82 +1,10 @@ -import type { SimpleScopeTypeType, TextEditor } from "@cursorless/common"; -import type { Node } from "web-tree-sitter"; -import type { - NodeMatcherAlternative, - SelectionWithContext, -} from "../typings/Types"; -import { patternFinder } from "../util/nodeFinders"; -import { - argumentMatcher, - cascadingMatcher, - createPatternMatchers, - leadingMatcher, - matcher, - patternMatcher, -} from "../util/nodeMatchers"; -import { - makeNodePairSelection, - makeRangeFromPositions, -} from "../util/nodeSelectors"; - -/** - * Returns "impl_item[type]" node higher in the chain - * @param node The node which we will start our search from - * @returns node or null - */ -function implItemTypeFinder(node: Node) { - if ( - node.parent?.type === "impl_item" && - node.parent?.childForFieldName("type")?.equals(node) - ) { - return node; - } - return null; -} - -function traitBoundExtractor( - editor: TextEditor, - node: Node, -): SelectionWithContext { - return { - selection: makeNodePairSelection(node.children[1], node.lastNamedChild!), - context: { - leadingDelimiterRange: makeRangeFromPositions( - node.children[0].startPosition, - node.children[1].startPosition, - ), - }, - }; -} +import type { SimpleScopeTypeType } from "@cursorless/common"; +import type { NodeMatcherAlternative } from "../typings/Types"; +import { argumentMatcher, createPatternMatchers } from "../util/nodeMatchers"; const nodeMatchers: Partial< Record > = { - type: cascadingMatcher( - leadingMatcher( - [ - "let_declaration[type]", - "parameter[type]", - "field_declaration[type]", - "const_item[type]", - ], - [":"], - ), - matcher( - patternFinder( - "constrained_type_parameter[bounds]", - "where_predicate[bounds]", - ), - traitBoundExtractor, - ), - leadingMatcher(["function_item[return_type]"], ["->"]), - matcher(implItemTypeFinder), - patternMatcher( - "struct_item", - "trait_item", - "impl_item", - "array_type[element]", - ), - ), argumentOrParameter: argumentMatcher( "arguments", "parameters", diff --git a/queries/rust.scm b/queries/rust.scm index d24787b8a9..8f4c22dbf9 100644 --- a/queries/rust.scm +++ b/queries/rust.scm @@ -113,30 +113,53 @@ name: (_) @className @name ) @_.domain +;;!! fn foo() {} +;;! ^^^^^^^^^^^ (function_item name: (_) @functionName @name ) @namedFunction @_.domain -(field_declaration - name: (_) @name +;;!! fn foo() -> int {} +;;! ^^^ +(function_item + parameters: (_) @_.leading.endOf + return_type: (_)? @type ) @_.domain -;;!! where T: Display + Clone +;;!! fn foo() {} +;;! ^ +;;! ^^^^^^^ +(constrained_type_parameter + left: (_) @name + (trait_bounds + ":" @type.leading.endOf + (_) @type.start + (_) @type.end + ) +) @_.domain + +;;!! where T: Display ;;! ^ +;;! ^^^^^^^ (where_predicate left: (_) @name + (trait_bounds + ":" @type.leading.endOf + (_) @type.start + (_) @type.end + ) +) @_.domain + +(field_declaration + name: (_) @name @type.leading.endOf + type: (_) @type ) @_.domain ;;!! (t: &T, u: &U) ;;! ^ ^ (parameter - pattern: (_) @name -) @_.domain - -;;!! -;;! ^ ^ -(constrained_type_parameter - left: (_) @name + pattern: (_) @name @type.leading.endOf + type: (_) @type ) @_.domain [ @@ -191,8 +214,8 @@ ;;!! const foo: u8 = 2; ;;! ^ (const_item - name: (_) @name - type: (_) @value.leading.endOf + name: (_) @name @type.leading.endOf + type: (_) @type @value.leading.endOf value: (_) @value ) @_.domain @@ -209,8 +232,8 @@ ;;! ^^^ ;;! ^ (let_declaration - pattern: (_) @name - type: (_) @value.leading.start.endOf + pattern: (_) @name @type.leading.endOf + type: (_) @type @value.leading.start.endOf value: (_) @value ) @_.domain @@ -291,6 +314,20 @@ ;;! ^^^^^^^ (match_arm) @branch +[ + (struct_item) + (trait_item) + (impl_item) +] @type + +(impl_item + type: (_) @type +) + +(array_type + element: (_) @type +) @_.domain + operator: [ "<" "<<" From ade9890c04218ac9532913d78c7f8ffcc381bbe1 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Sun, 1 Jun 2025 23:57:22 +0200 Subject: [PATCH 10/18] Migrate argument --- .../languages/rust/changeArgBlueAir.yml | 7 +- .../recorded/languages/rust/changeArgSun.yml | 8 +- .../recorded/languages/rust/changeArgTrap.yml | 7 +- .../rust/changeArgTrapAndBlueTrap.yml | 12 +-- .../recorded/languages/rust/chuckArgAir.yml | 7 +- .../languages/rust/chuckArgBlueAir.yml | 7 +- .../recorded/languages/rust/chuckArgSun2.yml | 8 +- .../recorded/languages/rust/chuckArgTrap.yml | 7 +- .../src/languages/LegacyLanguageId.ts | 2 +- .../src/languages/getNodeMatcher.ts | 6 +- .../cursorless-engine/src/languages/rust.ts | 17 ---- queries/rust.scm | 91 +++++++++++++++++++ 12 files changed, 102 insertions(+), 77 deletions(-) delete mode 100644 packages/cursorless-engine/src/languages/rust.ts diff --git a/data/fixtures/recorded/languages/rust/changeArgBlueAir.yml b/data/fixtures/recorded/languages/rust/changeArgBlueAir.yml index a9541c7a20..62b75d6b22 100644 --- a/data/fixtures/recorded/languages/rust/changeArgBlueAir.yml +++ b/data/fixtures/recorded/languages/rust/changeArgBlueAir.yml @@ -21,9 +21,4 @@ initialState: blue.a: start: {line: 0, character: 18} end: {line: 0, character: 19} -finalState: - documentContents: | - struct S<'a, , T>; - selections: - - anchor: {line: 0, character: 13} - active: {line: 0, character: 13} +thrownError: {name: NoContainingScopeError} diff --git a/data/fixtures/recorded/languages/rust/changeArgSun.yml b/data/fixtures/recorded/languages/rust/changeArgSun.yml index 4a2dce7d83..c61fda9913 100644 --- a/data/fixtures/recorded/languages/rust/changeArgSun.yml +++ b/data/fixtures/recorded/languages/rust/changeArgSun.yml @@ -24,10 +24,4 @@ initialState: default.s: start: {line: 0, character: 20} end: {line: 0, character: 27} -finalState: - documentContents: |- - fn some_function<, U: Clone + Debug>(t: &T, u: &U) -> i32 { - } - selections: - - anchor: {line: 0, character: 17} - active: {line: 0, character: 17} +thrownError: {name: NoContainingScopeError} diff --git a/data/fixtures/recorded/languages/rust/changeArgTrap.yml b/data/fixtures/recorded/languages/rust/changeArgTrap.yml index b27cade511..f377e26fb1 100644 --- a/data/fixtures/recorded/languages/rust/changeArgTrap.yml +++ b/data/fixtures/recorded/languages/rust/changeArgTrap.yml @@ -21,9 +21,4 @@ initialState: default.t: start: {line: 0, character: 21} end: {line: 0, character: 22} -finalState: - documentContents: | - struct S<'a, 'b: 'a, > {}; - selections: - - anchor: {line: 0, character: 21} - active: {line: 0, character: 21} +thrownError: {name: NoContainingScopeError} diff --git a/data/fixtures/recorded/languages/rust/changeArgTrapAndBlueTrap.yml b/data/fixtures/recorded/languages/rust/changeArgTrapAndBlueTrap.yml index c9fac08a6c..22c5923e59 100644 --- a/data/fixtures/recorded/languages/rust/changeArgTrapAndBlueTrap.yml +++ b/data/fixtures/recorded/languages/rust/changeArgTrapAndBlueTrap.yml @@ -31,14 +31,4 @@ initialState: blue.t: start: {line: 0, character: 11} end: {line: 0, character: 12} -finalState: - documentContents: | - enum Maybe<> { - Just(), - Nothing, - } - selections: - - anchor: {line: 0, character: 11} - active: {line: 0, character: 11} - - anchor: {line: 1, character: 9} - active: {line: 1, character: 9} +thrownError: {name: NoContainingScopeError} diff --git a/data/fixtures/recorded/languages/rust/chuckArgAir.yml b/data/fixtures/recorded/languages/rust/chuckArgAir.yml index 1a222e1bfe..4ac765163d 100644 --- a/data/fixtures/recorded/languages/rust/chuckArgAir.yml +++ b/data/fixtures/recorded/languages/rust/chuckArgAir.yml @@ -21,9 +21,4 @@ initialState: default.a: start: {line: 0, character: 10} end: {line: 0, character: 11} -finalState: - documentContents: | - struct S<'b: 'a, T>; - selections: - - anchor: {line: 1, character: 0} - active: {line: 1, character: 0} +thrownError: {name: NoContainingScopeError} diff --git a/data/fixtures/recorded/languages/rust/chuckArgBlueAir.yml b/data/fixtures/recorded/languages/rust/chuckArgBlueAir.yml index cce48653ce..abf5a7912c 100644 --- a/data/fixtures/recorded/languages/rust/chuckArgBlueAir.yml +++ b/data/fixtures/recorded/languages/rust/chuckArgBlueAir.yml @@ -21,9 +21,4 @@ initialState: blue.a: start: {line: 0, character: 18} end: {line: 0, character: 19} -finalState: - documentContents: | - struct S<'a, T>; - selections: - - anchor: {line: 1, character: 0} - active: {line: 1, character: 0} +thrownError: {name: NoContainingScopeError} diff --git a/data/fixtures/recorded/languages/rust/chuckArgSun2.yml b/data/fixtures/recorded/languages/rust/chuckArgSun2.yml index d89207cd6c..95a060c79f 100644 --- a/data/fixtures/recorded/languages/rust/chuckArgSun2.yml +++ b/data/fixtures/recorded/languages/rust/chuckArgSun2.yml @@ -24,10 +24,4 @@ initialState: default.s: start: {line: 0, character: 20} end: {line: 0, character: 27} -finalState: - documentContents: |- - fn some_function(t: &T, u: &U) -> i32 { - } - selections: - - anchor: {line: 1, character: 1} - active: {line: 1, character: 1} +thrownError: {name: NoContainingScopeError} diff --git a/data/fixtures/recorded/languages/rust/chuckArgTrap.yml b/data/fixtures/recorded/languages/rust/chuckArgTrap.yml index 3231f2a684..84dde9e88a 100644 --- a/data/fixtures/recorded/languages/rust/chuckArgTrap.yml +++ b/data/fixtures/recorded/languages/rust/chuckArgTrap.yml @@ -21,9 +21,4 @@ initialState: default.t: start: {line: 0, character: 21} end: {line: 0, character: 22} -finalState: - documentContents: | - struct S<'a, 'b: 'a> {}; - selections: - - anchor: {line: 1, character: 0} - active: {line: 1, character: 0} +thrownError: {name: NoContainingScopeError} diff --git a/packages/cursorless-engine/src/languages/LegacyLanguageId.ts b/packages/cursorless-engine/src/languages/LegacyLanguageId.ts index f4252da4e5..244c984434 100644 --- a/packages/cursorless-engine/src/languages/LegacyLanguageId.ts +++ b/packages/cursorless-engine/src/languages/LegacyLanguageId.ts @@ -2,6 +2,6 @@ * The language IDs that we have full tree-sitter support for using our legacy * modifiers. */ -export const legacyLanguageIds = ["clojure", "latex", "rust"] as const; +export const legacyLanguageIds = ["clojure", "latex"] as const; export type LegacyLanguageId = (typeof legacyLanguageIds)[number]; diff --git a/packages/cursorless-engine/src/languages/getNodeMatcher.ts b/packages/cursorless-engine/src/languages/getNodeMatcher.ts index 0fd62cc28d..90ea7268d4 100644 --- a/packages/cursorless-engine/src/languages/getNodeMatcher.ts +++ b/packages/cursorless-engine/src/languages/getNodeMatcher.ts @@ -1,6 +1,6 @@ +import type { SimpleScopeTypeType } from "@cursorless/common"; import { UnsupportedLanguageError } from "@cursorless/common"; import type { Node } from "web-tree-sitter"; -import type { SimpleScopeTypeType } from "@cursorless/common"; import type { NodeMatcher, NodeMatcherValue, @@ -9,9 +9,8 @@ import type { import { notSupported } from "../util/nodeMatchers"; import { selectionWithEditorFromRange } from "../util/selectionUtils"; import clojure from "./clojure"; -import type { LegacyLanguageId } from "./LegacyLanguageId"; import latex from "./latex"; -import rust from "./rust"; +import type { LegacyLanguageId } from "./LegacyLanguageId"; export function getNodeMatcher( languageId: string, @@ -43,7 +42,6 @@ export const languageMatchers: Record< > = { clojure, latex, - rust, }; function matcherIncludeSiblings(matcher: NodeMatcher): NodeMatcher { diff --git a/packages/cursorless-engine/src/languages/rust.ts b/packages/cursorless-engine/src/languages/rust.ts deleted file mode 100644 index 6a47d0a58f..0000000000 --- a/packages/cursorless-engine/src/languages/rust.ts +++ /dev/null @@ -1,17 +0,0 @@ -import type { SimpleScopeTypeType } from "@cursorless/common"; -import type { NodeMatcherAlternative } from "../typings/Types"; -import { argumentMatcher, createPatternMatchers } from "../util/nodeMatchers"; - -const nodeMatchers: Partial< - Record -> = { - argumentOrParameter: argumentMatcher( - "arguments", - "parameters", - "meta_arguments", - "type_parameters", - "ordered_field_declaration_list", - ), -}; - -export default createPatternMatchers(nodeMatchers); diff --git a/queries/rust.scm b/queries/rust.scm index 8f4c22dbf9..f72339cf6e 100644 --- a/queries/rust.scm +++ b/queries/rust.scm @@ -327,6 +327,97 @@ (array_type element: (_) @type ) @_.domain +;;!! fn foo(a: u32, b: u32) -> {} +;;! ^^^^^^ ^^^^^^ +(_ + (parameters + (_)? @_.leading.endOf + . + (_) @argumentOrParameter + . + (_)? @_.trailing.startOf + ) @_dummy + (#single-or-multi-line-delimiter! @argumentOrParameter @_dummy ", " ",\n") +) + +;;!! fn foo(a: u32, b: u32) -> {} +;;! ^^^^^^^^^^^^^^ +(_ + (parameters + "(" @argumentList.start.endOf @argumentOrParameter.iteration.start.endOf + ")" @argumentList.end.startOf @argumentOrParameter.iteration.end.startOf + ) @_dummy + (#empty-single-multi-delimiter! @argumentList.start.endOf @_dummy "" ", " ",\n") +) @argumentList.domain @argumentOrParameter.iteration.domain + +;;!! foo(aaa, bbb) +;;! ^^^ ^^^ +(_ + (arguments + (_)? @_.leading.endOf + . + (_) @argumentOrParameter + . + (_)? @_.trailing.startOf + ) @_dummy + (#single-or-multi-line-delimiter! @argumentOrParameter @_dummy ", " ",\n") +) + +;;!! foo(aaa, bbb) +;;! ^^^^^^^^ +(_ + (arguments + "(" @argumentList.start.endOf @argumentOrParameter.iteration.start.endOf + ")" @argumentList.end.startOf @argumentOrParameter.iteration.end.startOf + ) @_dummy + (#empty-single-multi-delimiter! @argumentList.start.endOf @_dummy "" ", " ",\n") +) @argumentList.domain @argumentOrParameter.iteration.domain + +;;!! enum E { C(u16, u16) } +;;! ^^^ ^^^ +(_ + (ordered_field_declaration_list + (_)? @_.leading.endOf + . + (_) @argumentOrParameter + . + (_)? @_.trailing.startOf + ) @_dummy + (#single-or-multi-line-delimiter! @argumentOrParameter @_dummy ", " ",\n") +) + +;;!! enum E { C(u16, u16) } +;;! ^^^^^^^^ +(_ + (ordered_field_declaration_list + "(" @argumentList.start.endOf @argumentOrParameter.iteration.start.endOf + ")" @argumentList.end.startOf @argumentOrParameter.iteration.end.startOf + ) @_dummy + (#empty-single-multi-delimiter! @argumentList.start.endOf @_dummy "" ", " ",\n") +) @argumentList.domain @argumentOrParameter.iteration.domain + +;;!! #[derive(aaa, bbb)] +;;! ^^^ ^^^ +(_ + (meta_arguments + (_)? @_.leading.endOf + . + (_) @argumentOrParameter + . + (_)? @_.trailing.startOf + ) @_dummy + (#single-or-multi-line-delimiter! @argumentOrParameter @_dummy ", " ",\n") +) + +;;!! #[derive(aaa, bbb)] +;;! ^^^^^^^^ +(_ + (meta_arguments + "(" @argumentList.start.endOf @argumentOrParameter.iteration.start.endOf + ")" @argumentList.end.startOf @argumentOrParameter.iteration.end.startOf + ) @_dummy + (#empty-single-multi-delimiter! @argumentList.start.endOf @_dummy "" ", " ",\n") +) @argumentList.domain @argumentOrParameter.iteration.domain operator: [ "<" From 396d762b58a32aec5130498333866373652bd149 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Mon, 2 Jun 2025 20:42:26 +0200 Subject: [PATCH 11/18] Added dummy legacy language id --- packages/cursorless-engine/src/languages/LegacyLanguageId.ts | 2 +- packages/cursorless-engine/src/languages/getNodeMatcher.ts | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/cursorless-engine/src/languages/LegacyLanguageId.ts b/packages/cursorless-engine/src/languages/LegacyLanguageId.ts index 828da5dce0..f1243ef429 100644 --- a/packages/cursorless-engine/src/languages/LegacyLanguageId.ts +++ b/packages/cursorless-engine/src/languages/LegacyLanguageId.ts @@ -2,6 +2,6 @@ * The language IDs that we have full tree-sitter support for using our legacy * modifiers. */ -export const legacyLanguageIds = [] as const; +export const legacyLanguageIds = [""] as const; export type LegacyLanguageId = (typeof legacyLanguageIds)[number]; diff --git a/packages/cursorless-engine/src/languages/getNodeMatcher.ts b/packages/cursorless-engine/src/languages/getNodeMatcher.ts index 3bfc13a36f..263efbc925 100644 --- a/packages/cursorless-engine/src/languages/getNodeMatcher.ts +++ b/packages/cursorless-engine/src/languages/getNodeMatcher.ts @@ -37,7 +37,9 @@ export function getNodeMatcher( export const languageMatchers: Record< LegacyLanguageId, Partial> -> = {}; +> = { + "": {}, +}; function matcherIncludeSiblings(matcher: NodeMatcher): NodeMatcher { return ( From 887d62a0c8fcac33bad197f40c37dcc276789cbc Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Mon, 2 Jun 2025 20:50:04 +0200 Subject: [PATCH 12/18] Apply suggestions from code review --- packages/cursorless-engine/src/languages/LegacyLanguageId.ts | 2 +- packages/cursorless-engine/src/languages/getNodeMatcher.ts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/cursorless-engine/src/languages/LegacyLanguageId.ts b/packages/cursorless-engine/src/languages/LegacyLanguageId.ts index f1243ef429..18188217c5 100644 --- a/packages/cursorless-engine/src/languages/LegacyLanguageId.ts +++ b/packages/cursorless-engine/src/languages/LegacyLanguageId.ts @@ -2,6 +2,6 @@ * The language IDs that we have full tree-sitter support for using our legacy * modifiers. */ -export const legacyLanguageIds = [""] as const; +export const legacyLanguageIds = ["dummy"] as const; export type LegacyLanguageId = (typeof legacyLanguageIds)[number]; diff --git a/packages/cursorless-engine/src/languages/getNodeMatcher.ts b/packages/cursorless-engine/src/languages/getNodeMatcher.ts index 263efbc925..0e7ff932b4 100644 --- a/packages/cursorless-engine/src/languages/getNodeMatcher.ts +++ b/packages/cursorless-engine/src/languages/getNodeMatcher.ts @@ -38,7 +38,7 @@ export const languageMatchers: Record< LegacyLanguageId, Partial> > = { - "": {}, + "dummy": {}, }; function matcherIncludeSiblings(matcher: NodeMatcher): NodeMatcher { From 67bbbddb1ad0ad7ab5f6903e9864c0f7c5c237e8 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Tue, 3 Jun 2025 08:35:21 +0200 Subject: [PATCH 13/18] Use collection key instead of name scope --- .../languages/rust/changeNameDrum2.yml | 35 +++++++++++++++++++ .../languages/rust/changeNameDrum3.yml | 33 +++++++++++++++++ .../languages/rust/changeNameJury.yml | 33 +++++++++++++++++ .../languages/rust/changeNameLook.yml | 33 +++++++++++++++++ .../recorded/languages/rust/chuckNameFine.yml | 33 +++++++++++++++++ .../recorded/languages/rust/chuckNameJury.yml | 33 +++++++++++++++++ 6 files changed, 200 insertions(+) create mode 100644 data/fixtures/recorded/languages/rust/changeNameDrum2.yml create mode 100644 data/fixtures/recorded/languages/rust/changeNameDrum3.yml create mode 100644 data/fixtures/recorded/languages/rust/changeNameJury.yml create mode 100644 data/fixtures/recorded/languages/rust/changeNameLook.yml create mode 100644 data/fixtures/recorded/languages/rust/chuckNameFine.yml create mode 100644 data/fixtures/recorded/languages/rust/chuckNameJury.yml diff --git a/data/fixtures/recorded/languages/rust/changeNameDrum2.yml b/data/fixtures/recorded/languages/rust/changeNameDrum2.yml new file mode 100644 index 0000000000..76eb22d8f1 --- /dev/null +++ b/data/fixtures/recorded/languages/rust/changeNameDrum2.yml @@ -0,0 +1,35 @@ +languageId: rust +command: + version: 6 + spokenForm: change key drum + action: + name: clearAndSetSelection + target: + type: primitive + modifiers: + - type: containingScope + scopeType: {type: collectionKey} + mark: {type: decoratedSymbol, symbolColor: default, character: d} + usePrePhraseSnapshot: true +initialState: + documentContents: | + let user = User { + first_name: "John", + last_name: "Doe", + }; + selections: + - anchor: {line: 3, character: 2} + active: {line: 3, character: 2} + marks: + default.d: + start: {line: 2, character: 16} + end: {line: 2, character: 19} +finalState: + documentContents: | + let user = User { + first_name: "John", + : "Doe", + }; + selections: + - anchor: {line: 2, character: 4} + active: {line: 2, character: 4} diff --git a/data/fixtures/recorded/languages/rust/changeNameDrum3.yml b/data/fixtures/recorded/languages/rust/changeNameDrum3.yml new file mode 100644 index 0000000000..8570b26f76 --- /dev/null +++ b/data/fixtures/recorded/languages/rust/changeNameDrum3.yml @@ -0,0 +1,33 @@ +languageId: rust +command: + version: 6 + spokenForm: change key drum + action: + name: clearAndSetSelection + target: + type: primitive + modifiers: + - type: containingScope + scopeType: {type: collectionKey} + mark: {type: decoratedSymbol, symbolColor: default, character: d} + usePrePhraseSnapshot: true +initialState: + documentContents: | + match user { + User { first_name: "John", last_name: "Doe" } => {}, + } + selections: + - anchor: {line: 3, character: 0} + active: {line: 3, character: 0} + marks: + default.d: + start: {line: 1, character: 43} + end: {line: 1, character: 46} +finalState: + documentContents: | + match user { + User { first_name: "John", : "Doe" } => {}, + } + selections: + - anchor: {line: 1, character: 31} + active: {line: 1, character: 31} diff --git a/data/fixtures/recorded/languages/rust/changeNameJury.yml b/data/fixtures/recorded/languages/rust/changeNameJury.yml new file mode 100644 index 0000000000..ee31829dc3 --- /dev/null +++ b/data/fixtures/recorded/languages/rust/changeNameJury.yml @@ -0,0 +1,33 @@ +languageId: rust +command: + version: 6 + spokenForm: change key jury + action: + name: clearAndSetSelection + target: + type: primitive + modifiers: + - type: containingScope + scopeType: {type: collectionKey} + mark: {type: decoratedSymbol, symbolColor: default, character: j} + usePrePhraseSnapshot: true +initialState: + documentContents: | + match user { + User { first_name: "John", last_name: "Doe" } => {}, + } + selections: + - anchor: {line: 3, character: 0} + active: {line: 3, character: 0} + marks: + default.j: + start: {line: 1, character: 24} + end: {line: 1, character: 28} +finalState: + documentContents: | + match user { + User { : "John", last_name: "Doe" } => {}, + } + selections: + - anchor: {line: 1, character: 11} + active: {line: 1, character: 11} diff --git a/data/fixtures/recorded/languages/rust/changeNameLook.yml b/data/fixtures/recorded/languages/rust/changeNameLook.yml new file mode 100644 index 0000000000..66650c8ae2 --- /dev/null +++ b/data/fixtures/recorded/languages/rust/changeNameLook.yml @@ -0,0 +1,33 @@ +languageId: rust +command: + version: 6 + spokenForm: change key look + action: + name: clearAndSetSelection + target: + type: primitive + modifiers: + - type: containingScope + scopeType: {type: collectionKey} + mark: {type: decoratedSymbol, symbolColor: default, character: l} + usePrePhraseSnapshot: true +initialState: + documentContents: | + match user { + User { first_name: "John", last_name: "Doe" } => {}, + } + selections: + - anchor: {line: 3, character: 0} + active: {line: 3, character: 0} + marks: + default.l: + start: {line: 1, character: 31} + end: {line: 1, character: 40} +finalState: + documentContents: | + match user { + User { first_name: "John", : "Doe" } => {}, + } + selections: + - anchor: {line: 1, character: 31} + active: {line: 1, character: 31} diff --git a/data/fixtures/recorded/languages/rust/chuckNameFine.yml b/data/fixtures/recorded/languages/rust/chuckNameFine.yml new file mode 100644 index 0000000000..a483a4de4b --- /dev/null +++ b/data/fixtures/recorded/languages/rust/chuckNameFine.yml @@ -0,0 +1,33 @@ +languageId: rust +command: + version: 6 + spokenForm: chuck key fine + action: + name: remove + target: + type: primitive + modifiers: + - type: containingScope + scopeType: {type: collectionKey} + mark: {type: decoratedSymbol, symbolColor: default, character: f} + usePrePhraseSnapshot: true +initialState: + documentContents: | + match user { + User { first_name: "John", last_name: last_name } => {} + } + selections: + - anchor: {line: 0, character: 10} + active: {line: 0, character: 10} + marks: + default.f: + start: {line: 1, character: 11} + end: {line: 1, character: 21} +finalState: + documentContents: | + match user { + User { "John", last_name: last_name } => {} + } + selections: + - anchor: {line: 0, character: 10} + active: {line: 0, character: 10} diff --git a/data/fixtures/recorded/languages/rust/chuckNameJury.yml b/data/fixtures/recorded/languages/rust/chuckNameJury.yml new file mode 100644 index 0000000000..5061b44687 --- /dev/null +++ b/data/fixtures/recorded/languages/rust/chuckNameJury.yml @@ -0,0 +1,33 @@ +languageId: rust +command: + version: 6 + spokenForm: chuck key jury + action: + name: remove + target: + type: primitive + modifiers: + - type: containingScope + scopeType: {type: collectionKey} + mark: {type: decoratedSymbol, symbolColor: default, character: j} + usePrePhraseSnapshot: true +initialState: + documentContents: | + match user { + User { first_name: "John", last_name: last_name } => {} + } + selections: + - anchor: {line: 0, character: 10} + active: {line: 0, character: 10} + marks: + default.j: + start: {line: 1, character: 24} + end: {line: 1, character: 28} +finalState: + documentContents: | + match user { + User { "John", last_name: last_name } => {} + } + selections: + - anchor: {line: 0, character: 10} + active: {line: 0, character: 10} From 999d164cae7200c6d3b951aac0120d2bdc8fa6ae Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Tue, 3 Jun 2025 08:55:52 +0200 Subject: [PATCH 14/18] Update tests with type scope --- .../languages/rust/changeArgBlueAir.yml | 11 +++++++--- .../recorded/languages/rust/changeArgSun.yml | 6 ++--- .../recorded/languages/rust/changeArgTrap.yml | 11 +++++++--- .../rust/changeArgTrapAndBlueTrap.yml | 4 ++-- .../languages/rust/changeTypeTrap.yml | 8 +------ .../recorded/languages/rust/chuckArgAir.yml | 11 +++++++--- .../languages/rust/chuckArgBlueAir.yml | 11 +++++++--- .../recorded/languages/rust/chuckArgSun2.yml | 6 ++--- .../recorded/languages/rust/chuckArgTrap.yml | 11 +++++++--- queries/rust.scm | 22 +++++++++++++++++++ 10 files changed, 71 insertions(+), 30 deletions(-) diff --git a/data/fixtures/recorded/languages/rust/changeArgBlueAir.yml b/data/fixtures/recorded/languages/rust/changeArgBlueAir.yml index 62b75d6b22..da5d34e4bf 100644 --- a/data/fixtures/recorded/languages/rust/changeArgBlueAir.yml +++ b/data/fixtures/recorded/languages/rust/changeArgBlueAir.yml @@ -1,14 +1,14 @@ languageId: rust command: version: 6 - spokenForm: change arg blue air + spokenForm: change type blue air action: name: clearAndSetSelection target: type: primitive modifiers: - type: containingScope - scopeType: {type: argumentOrParameter} + scopeType: {type: type} mark: {type: decoratedSymbol, symbolColor: blue, character: a} usePrePhraseSnapshot: true initialState: @@ -21,4 +21,9 @@ initialState: blue.a: start: {line: 0, character: 18} end: {line: 0, character: 19} -thrownError: {name: NoContainingScopeError} +finalState: + documentContents: | + struct S<'a, , T>; + selections: + - anchor: {line: 0, character: 13} + active: {line: 0, character: 13} diff --git a/data/fixtures/recorded/languages/rust/changeArgSun.yml b/data/fixtures/recorded/languages/rust/changeArgSun.yml index c61fda9913..fb99f318bb 100644 --- a/data/fixtures/recorded/languages/rust/changeArgSun.yml +++ b/data/fixtures/recorded/languages/rust/changeArgSun.yml @@ -1,14 +1,14 @@ languageId: rust command: version: 6 - spokenForm: change arg sun + spokenForm: change type sun action: name: clearAndSetSelection target: type: primitive modifiers: - type: containingScope - scopeType: {type: argumentOrParameter} + scopeType: {type: type} mark: {type: decoratedSymbol, symbolColor: default, character: s} usePrePhraseSnapshot: true initialState: @@ -24,4 +24,4 @@ initialState: default.s: start: {line: 0, character: 20} end: {line: 0, character: 27} -thrownError: {name: NoContainingScopeError} +thrownError: {name: Error} diff --git a/data/fixtures/recorded/languages/rust/changeArgTrap.yml b/data/fixtures/recorded/languages/rust/changeArgTrap.yml index f377e26fb1..17fc9555b0 100644 --- a/data/fixtures/recorded/languages/rust/changeArgTrap.yml +++ b/data/fixtures/recorded/languages/rust/changeArgTrap.yml @@ -1,14 +1,14 @@ languageId: rust command: version: 6 - spokenForm: change arg trap + spokenForm: change type trap action: name: clearAndSetSelection target: type: primitive modifiers: - type: containingScope - scopeType: {type: argumentOrParameter} + scopeType: {type: type} mark: {type: decoratedSymbol, symbolColor: default, character: t} usePrePhraseSnapshot: true initialState: @@ -21,4 +21,9 @@ initialState: default.t: start: {line: 0, character: 21} end: {line: 0, character: 22} -thrownError: {name: NoContainingScopeError} +finalState: + documentContents: | + struct S<'a, 'b: 'a, > {}; + selections: + - anchor: {line: 0, character: 21} + active: {line: 0, character: 21} diff --git a/data/fixtures/recorded/languages/rust/changeArgTrapAndBlueTrap.yml b/data/fixtures/recorded/languages/rust/changeArgTrapAndBlueTrap.yml index 22c5923e59..79200229ea 100644 --- a/data/fixtures/recorded/languages/rust/changeArgTrapAndBlueTrap.yml +++ b/data/fixtures/recorded/languages/rust/changeArgTrapAndBlueTrap.yml @@ -1,7 +1,7 @@ languageId: rust command: version: 6 - spokenForm: change arg trap and blue trap + spokenForm: change type trap and blue trap action: name: clearAndSetSelection target: @@ -10,7 +10,7 @@ command: - type: primitive modifiers: - type: containingScope - scopeType: {type: argumentOrParameter} + scopeType: {type: type} mark: {type: decoratedSymbol, symbolColor: default, character: t} - type: primitive mark: {type: decoratedSymbol, symbolColor: blue, character: t} diff --git a/data/fixtures/recorded/languages/rust/changeTypeTrap.yml b/data/fixtures/recorded/languages/rust/changeTypeTrap.yml index e1bf061b14..ca6a725e95 100644 --- a/data/fixtures/recorded/languages/rust/changeTypeTrap.yml +++ b/data/fixtures/recorded/languages/rust/changeTypeTrap.yml @@ -24,10 +24,4 @@ initialState: default.t: start: {line: 0, character: 17} end: {line: 0, character: 18} -finalState: - documentContents: | - fn some_function(t: &T, u: &U) -> i32 { - } - selections: - - anchor: {line: 0, character: 20} - active: {line: 0, character: 20} +thrownError: {name: Error} diff --git a/data/fixtures/recorded/languages/rust/chuckArgAir.yml b/data/fixtures/recorded/languages/rust/chuckArgAir.yml index 4ac765163d..3f1fcce693 100644 --- a/data/fixtures/recorded/languages/rust/chuckArgAir.yml +++ b/data/fixtures/recorded/languages/rust/chuckArgAir.yml @@ -1,14 +1,14 @@ languageId: rust command: version: 6 - spokenForm: chuck arg air + spokenForm: chuck type air action: name: remove target: type: primitive modifiers: - type: containingScope - scopeType: {type: argumentOrParameter} + scopeType: {type: type} mark: {type: decoratedSymbol, symbolColor: default, character: a} usePrePhraseSnapshot: true initialState: @@ -21,4 +21,9 @@ initialState: default.a: start: {line: 0, character: 10} end: {line: 0, character: 11} -thrownError: {name: NoContainingScopeError} +finalState: + documentContents: | + struct S<'b: 'a, T>; + selections: + - anchor: {line: 1, character: 0} + active: {line: 1, character: 0} diff --git a/data/fixtures/recorded/languages/rust/chuckArgBlueAir.yml b/data/fixtures/recorded/languages/rust/chuckArgBlueAir.yml index abf5a7912c..006debdb0a 100644 --- a/data/fixtures/recorded/languages/rust/chuckArgBlueAir.yml +++ b/data/fixtures/recorded/languages/rust/chuckArgBlueAir.yml @@ -1,14 +1,14 @@ languageId: rust command: version: 6 - spokenForm: chuck arg blue air + spokenForm: chuck type blue air action: name: remove target: type: primitive modifiers: - type: containingScope - scopeType: {type: argumentOrParameter} + scopeType: {type: type} mark: {type: decoratedSymbol, symbolColor: blue, character: a} usePrePhraseSnapshot: true initialState: @@ -21,4 +21,9 @@ initialState: blue.a: start: {line: 0, character: 18} end: {line: 0, character: 19} -thrownError: {name: NoContainingScopeError} +finalState: + documentContents: | + struct S<'a, T>; + selections: + - anchor: {line: 1, character: 0} + active: {line: 1, character: 0} diff --git a/data/fixtures/recorded/languages/rust/chuckArgSun2.yml b/data/fixtures/recorded/languages/rust/chuckArgSun2.yml index 95a060c79f..2ba98574fa 100644 --- a/data/fixtures/recorded/languages/rust/chuckArgSun2.yml +++ b/data/fixtures/recorded/languages/rust/chuckArgSun2.yml @@ -1,14 +1,14 @@ languageId: rust command: version: 6 - spokenForm: chuck arg sun + spokenForm: chuck type sun action: name: remove target: type: primitive modifiers: - type: containingScope - scopeType: {type: argumentOrParameter} + scopeType: {type: type} mark: {type: decoratedSymbol, symbolColor: default, character: s} usePrePhraseSnapshot: true initialState: @@ -24,4 +24,4 @@ initialState: default.s: start: {line: 0, character: 20} end: {line: 0, character: 27} -thrownError: {name: NoContainingScopeError} +thrownError: {name: Error} diff --git a/data/fixtures/recorded/languages/rust/chuckArgTrap.yml b/data/fixtures/recorded/languages/rust/chuckArgTrap.yml index 84dde9e88a..581b02bd77 100644 --- a/data/fixtures/recorded/languages/rust/chuckArgTrap.yml +++ b/data/fixtures/recorded/languages/rust/chuckArgTrap.yml @@ -1,14 +1,14 @@ languageId: rust command: version: 6 - spokenForm: chuck arg trap + spokenForm: chuck type trap action: name: remove target: type: primitive modifiers: - type: containingScope - scopeType: {type: argumentOrParameter} + scopeType: {type: type} mark: {type: decoratedSymbol, symbolColor: default, character: t} usePrePhraseSnapshot: true initialState: @@ -21,4 +21,9 @@ initialState: default.t: start: {line: 0, character: 21} end: {line: 0, character: 22} -thrownError: {name: NoContainingScopeError} +finalState: + documentContents: | + struct S<'a, 'b: 'a> {}; + selections: + - anchor: {line: 1, character: 0} + active: {line: 1, character: 0} diff --git a/queries/rust.scm b/queries/rust.scm index f72339cf6e..0d9ae57864 100644 --- a/queries/rust.scm +++ b/queries/rust.scm @@ -419,6 +419,28 @@ (#empty-single-multi-delimiter! @argumentList.start.endOf @_dummy "" ", " ",\n") ) @argumentList.domain @argumentOrParameter.iteration.domain +;;!! #[derive(aaa, bbb)] +;;! ^^^ ^^^ +(_ + (type_parameters + (_)? @_.leading.endOf + . + (_) @type + . + (_)? @_.trailing.startOf + ) @_dummy + (#single-or-multi-line-delimiter! @type @_dummy ", " ",\n") +) + +;;!! #[derive(aaa, bbb)] +;;! ^^^^^^^^ +(_ + (type_parameters + "<" @type.iteration.start.endOf + ">" @type.iteration.end.startOf + ) +) @type.iteration.domain + operator: [ "<" "<<" From c4d1ce2e40ae8f230016d619eb4f279a0bdaaa0b Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Tue, 3 Jun 2025 09:02:20 +0200 Subject: [PATCH 15/18] More type arguments --- .../recorded/languages/rust/changeArgSun.yml | 8 +++++++- .../recorded/languages/rust/changeTypeTrap.yml | 8 +++++++- .../recorded/languages/rust/changeTypeTrap3.yml | 8 ++++---- .../recorded/languages/rust/chuckArgSun2.yml | 8 +++++++- queries/rust.scm | 12 ------------ 5 files changed, 25 insertions(+), 19 deletions(-) diff --git a/data/fixtures/recorded/languages/rust/changeArgSun.yml b/data/fixtures/recorded/languages/rust/changeArgSun.yml index fb99f318bb..3ff94df534 100644 --- a/data/fixtures/recorded/languages/rust/changeArgSun.yml +++ b/data/fixtures/recorded/languages/rust/changeArgSun.yml @@ -24,4 +24,10 @@ initialState: default.s: start: {line: 0, character: 20} end: {line: 0, character: 27} -thrownError: {name: Error} +finalState: + documentContents: |- + fn some_function<, U: Clone + Debug>(t: &T, u: &U) -> i32 { + } + selections: + - anchor: {line: 0, character: 17} + active: {line: 0, character: 17} diff --git a/data/fixtures/recorded/languages/rust/changeTypeTrap.yml b/data/fixtures/recorded/languages/rust/changeTypeTrap.yml index ca6a725e95..66bf9b3309 100644 --- a/data/fixtures/recorded/languages/rust/changeTypeTrap.yml +++ b/data/fixtures/recorded/languages/rust/changeTypeTrap.yml @@ -24,4 +24,10 @@ initialState: default.t: start: {line: 0, character: 17} end: {line: 0, character: 18} -thrownError: {name: Error} +finalState: + documentContents: | + fn some_function<, U: Clone + Debug>(t: &T, u: &U) -> i32 { + } + selections: + - anchor: {line: 0, character: 17} + active: {line: 0, character: 17} diff --git a/data/fixtures/recorded/languages/rust/changeTypeTrap3.yml b/data/fixtures/recorded/languages/rust/changeTypeTrap3.yml index b030f0aa09..3bc5f7e11e 100644 --- a/data/fixtures/recorded/languages/rust/changeTypeTrap3.yml +++ b/data/fixtures/recorded/languages/rust/changeTypeTrap3.yml @@ -26,10 +26,10 @@ initialState: end: {line: 1, character: 11} finalState: documentContents: | - fn some_function(t: &T, u: &U) -> i32 - where T: , + fn some_function(t: &T, u: &U) -> + where T: Display + Clone, U: Clone + Debug {} selections: - - anchor: {line: 1, character: 13} - active: {line: 1, character: 13} + - anchor: {line: 0, character: 40} + active: {line: 0, character: 40} diff --git a/data/fixtures/recorded/languages/rust/chuckArgSun2.yml b/data/fixtures/recorded/languages/rust/chuckArgSun2.yml index 2ba98574fa..3c690e334e 100644 --- a/data/fixtures/recorded/languages/rust/chuckArgSun2.yml +++ b/data/fixtures/recorded/languages/rust/chuckArgSun2.yml @@ -24,4 +24,10 @@ initialState: default.s: start: {line: 0, character: 20} end: {line: 0, character: 27} -thrownError: {name: Error} +finalState: + documentContents: |- + fn some_function(t: &T, u: &U) -> i32 { + } + selections: + - anchor: {line: 1, character: 1} + active: {line: 1, character: 1} diff --git a/queries/rust.scm b/queries/rust.scm index 0d9ae57864..aeffdb8d32 100644 --- a/queries/rust.scm +++ b/queries/rust.scm @@ -128,26 +128,14 @@ ;;!! fn foo() {} ;;! ^ -;;! ^^^^^^^ (constrained_type_parameter left: (_) @name - (trait_bounds - ":" @type.leading.endOf - (_) @type.start - (_) @type.end - ) ) @_.domain ;;!! where T: Display ;;! ^ -;;! ^^^^^^^ (where_predicate left: (_) @name - (trait_bounds - ":" @type.leading.endOf - (_) @type.start - (_) @type.end - ) ) @_.domain (field_declaration From 5778f19ac0efb4c9ad57ca6a9a3464b3faa0ad18 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Tue, 3 Jun 2025 09:08:08 +0200 Subject: [PATCH 16/18] Up dit --- .../languages/rust/changeArgTrapAndBlueTrap.yml | 3 +++ queries/rust.scm | 16 ++++++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/data/fixtures/recorded/languages/rust/changeArgTrapAndBlueTrap.yml b/data/fixtures/recorded/languages/rust/changeArgTrapAndBlueTrap.yml index 79200229ea..b46272c07f 100644 --- a/data/fixtures/recorded/languages/rust/changeArgTrapAndBlueTrap.yml +++ b/data/fixtures/recorded/languages/rust/changeArgTrapAndBlueTrap.yml @@ -13,6 +13,9 @@ command: scopeType: {type: type} mark: {type: decoratedSymbol, symbolColor: default, character: t} - type: primitive + modifiers: + - type: argumentOrParameter + scopeType: {type: type} mark: {type: decoratedSymbol, symbolColor: blue, character: t} usePrePhraseSnapshot: true initialState: diff --git a/queries/rust.scm b/queries/rust.scm index aeffdb8d32..1e965acd0c 100644 --- a/queries/rust.scm +++ b/queries/rust.scm @@ -128,14 +128,26 @@ ;;!! fn foo() {} ;;! ^ +;;! ^^^^^^^ (constrained_type_parameter - left: (_) @name + left: (_) @name @collectionKey + (trait_bounds + ":" @value.leading.endOf + (_) @value.start + (_) @value.end + ) ) @_.domain ;;!! where T: Display ;;! ^ +;;! ^^^^^^^ (where_predicate - left: (_) @name + left: (_) @name @collectionKey + (trait_bounds + ":" @value.leading.endOf + (_) @value.start + (_) @value.end + ) ) @_.domain (field_declaration From 3786be2040acb28c48bbd58e1602a94672c9c35e Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Tue, 3 Jun 2025 09:08:56 +0200 Subject: [PATCH 17/18] Fix formatting --- packages/cursorless-engine/src/languages/getNodeMatcher.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/cursorless-engine/src/languages/getNodeMatcher.ts b/packages/cursorless-engine/src/languages/getNodeMatcher.ts index 0e7ff932b4..897d2c386b 100644 --- a/packages/cursorless-engine/src/languages/getNodeMatcher.ts +++ b/packages/cursorless-engine/src/languages/getNodeMatcher.ts @@ -38,7 +38,7 @@ export const languageMatchers: Record< LegacyLanguageId, Partial> > = { - "dummy": {}, + dummy: {}, }; function matcherIncludeSiblings(matcher: NodeMatcher): NodeMatcher { From 3cdf1d6eae2ac346a5f5343007d1e919d26dfd80 Mon Sep 17 00:00:00 2001 From: Andreas Arvidsson Date: Tue, 3 Jun 2025 09:19:23 +0200 Subject: [PATCH 18/18] More type fixes --- .../rust/changeArgTrapAndBlueTrap.yml | 18 ++++++++++--- .../languages/rust/changeTypeTrap3.yml | 8 +++--- queries/rust.scm | 27 ++++++++++++++++--- 3 files changed, 41 insertions(+), 12 deletions(-) diff --git a/data/fixtures/recorded/languages/rust/changeArgTrapAndBlueTrap.yml b/data/fixtures/recorded/languages/rust/changeArgTrapAndBlueTrap.yml index b46272c07f..e3f62cd91c 100644 --- a/data/fixtures/recorded/languages/rust/changeArgTrapAndBlueTrap.yml +++ b/data/fixtures/recorded/languages/rust/changeArgTrapAndBlueTrap.yml @@ -1,7 +1,7 @@ languageId: rust command: version: 6 - spokenForm: change type trap and blue trap + spokenForm: change arg trap and type blue trap action: name: clearAndSetSelection target: @@ -10,11 +10,11 @@ command: - type: primitive modifiers: - type: containingScope - scopeType: {type: type} + scopeType: {type: argumentOrParameter} mark: {type: decoratedSymbol, symbolColor: default, character: t} - type: primitive modifiers: - - type: argumentOrParameter + - type: containingScope scopeType: {type: type} mark: {type: decoratedSymbol, symbolColor: blue, character: t} usePrePhraseSnapshot: true @@ -34,4 +34,14 @@ initialState: blue.t: start: {line: 0, character: 11} end: {line: 0, character: 12} -thrownError: {name: NoContainingScopeError} +finalState: + documentContents: | + enum Maybe<> { + Just(), + Nothing, + } + selections: + - anchor: {line: 0, character: 11} + active: {line: 0, character: 11} + - anchor: {line: 1, character: 9} + active: {line: 1, character: 9} diff --git a/data/fixtures/recorded/languages/rust/changeTypeTrap3.yml b/data/fixtures/recorded/languages/rust/changeTypeTrap3.yml index 3bc5f7e11e..1c8eabcfea 100644 --- a/data/fixtures/recorded/languages/rust/changeTypeTrap3.yml +++ b/data/fixtures/recorded/languages/rust/changeTypeTrap3.yml @@ -26,10 +26,10 @@ initialState: end: {line: 1, character: 11} finalState: documentContents: | - fn some_function(t: &T, u: &U) -> - where T: Display + Clone, + fn some_function(t: &T, u: &U) -> i32 + where , U: Clone + Debug {} selections: - - anchor: {line: 0, character: 40} - active: {line: 0, character: 40} + - anchor: {line: 1, character: 10} + active: {line: 1, character: 10} diff --git a/queries/rust.scm b/queries/rust.scm index 1e965acd0c..feb66480a0 100644 --- a/queries/rust.scm +++ b/queries/rust.scm @@ -419,8 +419,8 @@ (#empty-single-multi-delimiter! @argumentList.start.endOf @_dummy "" ", " ",\n") ) @argumentList.domain @argumentOrParameter.iteration.domain -;;!! #[derive(aaa, bbb)] -;;! ^^^ ^^^ +;;!! fn foo() {} +;;! ^^^^^^^^^^ ^^^^^^^^ (_ (type_parameters (_)? @_.leading.endOf @@ -432,8 +432,8 @@ (#single-or-multi-line-delimiter! @type @_dummy ", " ",\n") ) -;;!! #[derive(aaa, bbb)] -;;! ^^^^^^^^ +;;!! fn foo() {} +;;! ^^^^^^^^^^^^^^^^^^^^ (_ (type_parameters "<" @type.iteration.start.endOf @@ -441,6 +441,25 @@ ) ) @type.iteration.domain +;;!! where T: Display, U: Clone +;;! ^^^^^^^^^^ ^^^^^^^^ +( + (where_clause + (_)? @_.leading.endOf + . + (_) @type + . + (_)? @_.trailing.startOf + ) @_dummy + (#single-or-multi-line-delimiter! @type @_dummy ", " ",\n") +) + +;;!! where T: Display, U: Clone +;;! ^^^^^^^^^^^^^^^^^^^^ +(where_clause + "where" @type.iteration.start.endOf +) @type.iteration.end.endOf @type.iteration.domain + operator: [ "<" "<<"