diff --git a/data/fixtures/recorded/languages/rust/changeArgBlueAir.yml b/data/fixtures/recorded/languages/rust/changeArgBlueAir.yml index a9541c7a20..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: diff --git a/data/fixtures/recorded/languages/rust/changeArgSun.yml b/data/fixtures/recorded/languages/rust/changeArgSun.yml index 4a2dce7d83..3ff94df534 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: diff --git a/data/fixtures/recorded/languages/rust/changeArgTrap.yml b/data/fixtures/recorded/languages/rust/changeArgTrap.yml index b27cade511..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: diff --git a/data/fixtures/recorded/languages/rust/changeArgTrapAndBlueTrap.yml b/data/fixtures/recorded/languages/rust/changeArgTrapAndBlueTrap.yml index c9fac08a6c..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 arg trap and blue trap + spokenForm: change arg trap and type blue trap action: name: clearAndSetSelection target: @@ -13,6 +13,9 @@ command: scopeType: {type: argumentOrParameter} mark: {type: decoratedSymbol, symbolColor: default, character: t} - type: primitive + modifiers: + - type: containingScope + scopeType: {type: type} mark: {type: decoratedSymbol, symbolColor: blue, character: t} usePrePhraseSnapshot: true initialState: diff --git a/data/fixtures/recorded/languages/rust/changeNameDrum2.yml b/data/fixtures/recorded/languages/rust/changeNameDrum2.yml index f6a2766753..76eb22d8f1 100644 --- a/data/fixtures/recorded/languages/rust/changeNameDrum2.yml +++ b/data/fixtures/recorded/languages/rust/changeNameDrum2.yml @@ -1,14 +1,14 @@ languageId: rust command: version: 6 - spokenForm: change name drum + spokenForm: change key drum action: name: clearAndSetSelection target: type: primitive modifiers: - type: containingScope - scopeType: {type: name} + scopeType: {type: collectionKey} mark: {type: decoratedSymbol, symbolColor: default, character: d} usePrePhraseSnapshot: true initialState: diff --git a/data/fixtures/recorded/languages/rust/changeNameDrum3.yml b/data/fixtures/recorded/languages/rust/changeNameDrum3.yml index 69ad4fc939..8570b26f76 100644 --- a/data/fixtures/recorded/languages/rust/changeNameDrum3.yml +++ b/data/fixtures/recorded/languages/rust/changeNameDrum3.yml @@ -1,14 +1,14 @@ languageId: rust command: version: 6 - spokenForm: change name drum + spokenForm: change key drum action: name: clearAndSetSelection target: type: primitive modifiers: - type: containingScope - scopeType: {type: name} + scopeType: {type: collectionKey} mark: {type: decoratedSymbol, symbolColor: default, character: d} usePrePhraseSnapshot: true initialState: diff --git a/data/fixtures/recorded/languages/rust/changeNameJury.yml b/data/fixtures/recorded/languages/rust/changeNameJury.yml index a4ed66a40c..ee31829dc3 100644 --- a/data/fixtures/recorded/languages/rust/changeNameJury.yml +++ b/data/fixtures/recorded/languages/rust/changeNameJury.yml @@ -1,14 +1,14 @@ languageId: rust command: version: 6 - spokenForm: change name jury + spokenForm: change key jury action: name: clearAndSetSelection target: type: primitive modifiers: - type: containingScope - scopeType: {type: name} + scopeType: {type: collectionKey} mark: {type: decoratedSymbol, symbolColor: default, character: j} usePrePhraseSnapshot: true initialState: diff --git a/data/fixtures/recorded/languages/rust/changeNameLook.yml b/data/fixtures/recorded/languages/rust/changeNameLook.yml index 2a3d50ab0d..66650c8ae2 100644 --- a/data/fixtures/recorded/languages/rust/changeNameLook.yml +++ b/data/fixtures/recorded/languages/rust/changeNameLook.yml @@ -1,14 +1,14 @@ languageId: rust command: version: 6 - spokenForm: change name look + spokenForm: change key look action: name: clearAndSetSelection target: type: primitive modifiers: - type: containingScope - scopeType: {type: name} + scopeType: {type: collectionKey} mark: {type: decoratedSymbol, symbolColor: default, character: l} usePrePhraseSnapshot: true initialState: diff --git a/data/fixtures/recorded/languages/rust/changeTypeTrap.yml b/data/fixtures/recorded/languages/rust/changeTypeTrap.yml index e1bf061b14..66bf9b3309 100644 --- a/data/fixtures/recorded/languages/rust/changeTypeTrap.yml +++ b/data/fixtures/recorded/languages/rust/changeTypeTrap.yml @@ -26,8 +26,8 @@ initialState: end: {line: 0, character: 18} finalState: documentContents: | - fn some_function(t: &T, u: &U) -> i32 { + fn some_function<, U: Clone + Debug>(t: &T, u: &U) -> i32 { } selections: - - anchor: {line: 0, character: 20} - active: {line: 0, character: 20} + - 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..1c8eabcfea 100644 --- a/data/fixtures/recorded/languages/rust/changeTypeTrap3.yml +++ b/data/fixtures/recorded/languages/rust/changeTypeTrap3.yml @@ -27,9 +27,9 @@ initialState: finalState: documentContents: | fn some_function(t: &T, u: &U) -> i32 - where T: , + where , U: Clone + Debug {} selections: - - anchor: {line: 1, character: 13} - active: {line: 1, character: 13} + - anchor: {line: 1, character: 10} + active: {line: 1, character: 10} diff --git a/data/fixtures/recorded/languages/rust/chuckArgAir.yml b/data/fixtures/recorded/languages/rust/chuckArgAir.yml index 1a222e1bfe..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: diff --git a/data/fixtures/recorded/languages/rust/chuckArgBlueAir.yml b/data/fixtures/recorded/languages/rust/chuckArgBlueAir.yml index cce48653ce..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: diff --git a/data/fixtures/recorded/languages/rust/chuckArgSun2.yml b/data/fixtures/recorded/languages/rust/chuckArgSun2.yml index d89207cd6c..3c690e334e 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: diff --git a/data/fixtures/recorded/languages/rust/chuckArgTrap.yml b/data/fixtures/recorded/languages/rust/chuckArgTrap.yml index 3231f2a684..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: diff --git a/data/fixtures/recorded/languages/rust/chuckNameFine.yml b/data/fixtures/recorded/languages/rust/chuckNameFine.yml index 3e7d179746..a483a4de4b 100644 --- a/data/fixtures/recorded/languages/rust/chuckNameFine.yml +++ b/data/fixtures/recorded/languages/rust/chuckNameFine.yml @@ -1,14 +1,14 @@ languageId: rust command: version: 6 - spokenForm: chuck name fine + spokenForm: chuck key fine action: name: remove target: type: primitive modifiers: - type: containingScope - scopeType: {type: name} + scopeType: {type: collectionKey} mark: {type: decoratedSymbol, symbolColor: default, character: f} usePrePhraseSnapshot: true initialState: diff --git a/data/fixtures/recorded/languages/rust/chuckNameJury.yml b/data/fixtures/recorded/languages/rust/chuckNameJury.yml index ad84fb68b7..5061b44687 100644 --- a/data/fixtures/recorded/languages/rust/chuckNameJury.yml +++ b/data/fixtures/recorded/languages/rust/chuckNameJury.yml @@ -1,14 +1,14 @@ languageId: rust command: version: 6 - spokenForm: chuck name jury + spokenForm: chuck key jury action: name: remove target: type: primitive modifiers: - type: containingScope - scopeType: {type: name} + scopeType: {type: collectionKey} mark: {type: decoratedSymbol, symbolColor: default, character: j} usePrePhraseSnapshot: true initialState: 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/LegacyLanguageId.ts b/packages/cursorless-engine/src/languages/LegacyLanguageId.ts index 83864b9bae..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 = ["rust"] 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 390e1dfde9..897d2c386b 100644 --- a/packages/cursorless-engine/src/languages/getNodeMatcher.ts +++ b/packages/cursorless-engine/src/languages/getNodeMatcher.ts @@ -9,7 +9,6 @@ import type { import { notSupported } from "../util/nodeMatchers"; import { selectionWithEditorFromRange } from "../util/selectionUtils"; import type { LegacyLanguageId } from "./LegacyLanguageId"; -import rust from "./rust"; export function getNodeMatcher( languageId: string, @@ -39,7 +38,7 @@ export const languageMatchers: Record< LegacyLanguageId, Partial> > = { - rust, + dummy: {}, }; 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 1604ea3613..0000000000 --- a/packages/cursorless-engine/src/languages/rust.ts +++ /dev/null @@ -1,233 +0,0 @@ -import type { 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, - leadingMatcher, - matcher, - patternMatcher, - trailingMatcher, -} from "../util/nodeMatchers"; -import { - childRangeSelector, - makeNodePairSelection, - makeRangeFromPositions, -} 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", -]; - -/** - * 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 - * @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, - ), - }, - }; -} - -/** - * 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 -> = { - statement: ancestorChainNodeMatcher( - [ - patternFinder(...STATEMENT_PARENT_TYPES), - patternFinder(...STATEMENT_TYPES), - ], - 1, - ), - 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( - [ - "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", - "meta_arguments", - "type_parameters", - "ordered_field_declaration_list", - ), - collectionKey: cascadingMatcher( - trailingMatcher(["field_initializer[name]", "field_pattern[name]"], [":"]), - ), - 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]"], [":"]), - ), - value: cascadingMatcher( - leadingMatcher(["let_declaration[value]"], ["="]), - leadingMatcher( - ["field_initializer[value]", "field_pattern[pattern]"], - [":"], - ), - 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")), - matcher(patternFinder("if_expression"), elseIfExtractor()), - ), -}; - -export default createPatternMatchers(nodeMatchers); diff --git a/queries/rust.scm b/queries/rust.scm index 1031506c46..feb66480a0 100644 --- a/queries/rust.scm +++ b/queries/rust.scm @@ -1,9 +1,80 @@ ;; https://github.com/tree-sitter/tree-sitter-rust/blob/master/src/grammar.json -[ - (if_expression) - (if_let_expression) -] @ifStatement +;; 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 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" ( @@ -25,22 +96,71 @@ [ (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 +;;!! fn foo() {} +;;! ^^^^^^^^^^^ +(function_item + name: (_) @functionName @name +) @namedFunction @_.domain + +;;!! fn foo() -> int {} +;;! ^^^ (function_item - name: (_) @functionName -) @namedFunction @functionName.domain + parameters: (_) @_.leading.endOf + return_type: (_)? @type +) @_.domain + +;;!! fn foo() {} +;;! ^ +;;! ^^^^^^^ +(constrained_type_parameter + left: (_) @name @collectionKey + (trait_bounds + ":" @value.leading.endOf + (_) @value.start + (_) @value.end + ) +) @_.domain + +;;!! where T: Display +;;! ^ +;;! ^^^^^^^ +(where_predicate + left: (_) @name @collectionKey + (trait_bounds + ":" @value.leading.endOf + (_) @value.start + (_) @value.end + ) +) @_.domain + +(field_declaration + name: (_) @name @type.leading.endOf + type: (_) @type +) @_.domain + +;;!! (t: &T, u: &U) +;;! ^ ^ +(parameter + pattern: (_) @name @type.leading.endOf + type: (_) @type +) @_.domain [ (call_expression) @@ -63,6 +183,283 @@ value: (_) @private.switchStatementSubject ) @_.domain +;;!! #[derive(Debug)] +;;! ^^^^^^^^^^^^^^^^ +(attribute_item) @attribute + +;;!! &mut x; +;;! ^^^ +(_ + (mutable_specifier) @attribute + . + (_) @_.trailing.startOf +) @_.domain + +;;!! let Foo {aaa: 1, bbb: 2} +;;! ^^^ ^^^ +;;! ^ ^ +(field_initializer + name: (_) @collectionKey @value.leading.endOf + value: (_) @value @collectionKey.trailing.startOf +) @_.domain + +;;!! Foo {aaa: 1, bbb: 2} +;;! ^^^ ^^^ +;;! ^ ^ +(field_pattern + name: (_) @collectionKey @value.leading.endOf + pattern: (_) @value @collectionKey.trailing.startOf +) @_.domain + +;;!! const foo: u8 = 2; +;;! ^ +(const_item + name: (_) @name @type.leading.endOf + type: (_) @type @value.leading.endOf + value: (_) @value +) @_.domain + +;;!! let foo = 2; +;;! ^^^ +;;! ^ +(let_declaration + pattern: (_) @name @value.leading.start.endOf + . + value: (_) @value +) @_.domain + +;;!! let foo: u8 = 2; +;;! ^^^ +;;! ^ +(let_declaration + pattern: (_) @name @type.leading.endOf + type: (_) @type @value.leading.start.endOf + value: (_) @value +) @_.domain + +;;!! #[cfg_attr(feature = "foo")] +;;! ^^^^^^^ +;;! ^^^^^ +(meta_item + (identifier) @name @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 + ) +) + +;;!! 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 + +;;!! match value { 5 => {} } +;;! ^^^^^^^ +(match_arm) @branch + +[ + (struct_item) + (trait_item) + (impl_item) +] @type + +(impl_item + type: (_) @type +) + +(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 + +;;!! fn foo() {} +;;! ^^^^^^^^^^ ^^^^^^^^ +(_ + (type_parameters + (_)? @_.leading.endOf + . + (_) @type + . + (_)? @_.trailing.startOf + ) @_dummy + (#single-or-multi-line-delimiter! @type @_dummy ", " ",\n") +) + +;;!! fn foo() {} +;;! ^^^^^^^^^^^^^^^^^^^^ +(_ + (type_parameters + "<" @type.iteration.start.endOf + ">" @type.iteration.end.startOf + ) +) @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: [ "<" "<<"