From 0ac75e4d2332bb4cb7988815995a802e3e58bbed Mon Sep 17 00:00:00 2001 From: doryan Date: Fri, 2 Aug 2024 23:39:31 +0400 Subject: [PATCH] feat(rust): my treesitter file implementation for rust --- rust/folds.scm | 25 +++ rust/highlights.scm | 463 ++++++++++++++++++++++++++++++++++++++++++++ rust/indents.scm | 117 +++++++++++ rust/injections.scm | 91 +++++++++ rust/locals.scm | 101 ++++++++++ 5 files changed, 797 insertions(+) create mode 100644 rust/folds.scm create mode 100644 rust/highlights.scm create mode 100644 rust/indents.scm create mode 100644 rust/injections.scm create mode 100644 rust/locals.scm diff --git a/rust/folds.scm b/rust/folds.scm new file mode 100644 index 0000000..5429041 --- /dev/null +++ b/rust/folds.scm @@ -0,0 +1,25 @@ +[ + (mod_item) + (foreign_mod_item) + (function_item) + (struct_item) + (trait_item) + (enum_item) + (impl_item) + (type_item) + (union_item) + (const_item) + (use_declaration)+ + (let_declaration) + (loop_expression) + (for_expression) + (while_expression) + (if_expression) + (match_expression) + (call_expression) + (array_expression) + (macro_definition) + (macro_invocation) + (attribute_item) + (block) +] @fold diff --git a/rust/highlights.scm b/rust/highlights.scm new file mode 100644 index 0000000..f411dda --- /dev/null +++ b/rust/highlights.scm @@ -0,0 +1,463 @@ +; Forked from https://github.com/tree-sitter/tree-sitter-rust +; Copyright (c) 2017 Maxim Sokolov +; Licensed under the MIT license. +; Identifier conventions +(shebang) @keyword.directive + +(identifier) @variable + +((identifier) @type + (#lua-match? @type "^[A-Z]")) + +(const_item + name: (identifier) @constant) + +; Assume all-caps names are constants +((identifier) @constant + (#lua-match? @constant "^[A-Z][A-Z%d_]*$")) + +; Other identifiers +(type_identifier) @type + +(primitive_type) @type.builtin + +(field_identifier) @variable.member + +(shorthand_field_initializer + (identifier) @variable.member) + +(mod_item + name: (identifier) @module) + +[ + (self) + "_" +] @variable.builtin + +(label + [ + "'" + (identifier) + ] @label) + +; Function definitions +(function_item + (identifier) @function) + +(function_signature_item + (identifier) @function) + +(parameter + [ + (identifier) + "_" + ] @variable.parameter) + +(closure_parameters + (_) @variable.parameter) + +; Function calls +(call_expression + function: (identifier) @function.call) + +(call_expression + function: (scoped_identifier + (identifier) @function.call .)) + +(call_expression + function: (field_expression + field: (field_identifier) @function.call)) + +(generic_function + function: (identifier) @function.call) + +(generic_function + function: (scoped_identifier + name: (identifier) @function.call)) + +(generic_function + function: (field_expression + field: (field_identifier) @function.call)) + +; Assume other uppercase names are enum constructors +((field_identifier) @constant + (#lua-match? @constant "^[A-Z]")) + +(enum_variant + name: (identifier) @constant) + +; Assume that uppercase names in paths are types +(scoped_identifier + path: (identifier) @module) + +(scoped_identifier + (scoped_identifier + name: (identifier) @module)) + +(scoped_type_identifier + path: (identifier) @module) + +(scoped_type_identifier + path: (identifier) @type + (#lua-match? @type "^[A-Z]")) + +(scoped_type_identifier + (scoped_identifier + name: (identifier) @module)) + +((scoped_identifier + path: (identifier) @type) + (#lua-match? @type "^[A-Z]")) + +((scoped_identifier + name: (identifier) @type) + (#lua-match? @type "^[A-Z]")) + +((scoped_identifier + name: (identifier) @constant) + (#lua-match? @constant "^[A-Z][A-Z%d_]*$")) + +((scoped_identifier + path: (identifier) @type + name: (identifier) @constant) + (#lua-match? @type "^[A-Z]") + (#lua-match? @constant "^[A-Z]")) + +((scoped_type_identifier + path: (identifier) @type + name: (type_identifier) @constant) + (#lua-match? @type "^[A-Z]") + (#lua-match? @constant "^[A-Z]")) + +[ + (crate) + (super) +] @module + +(scoped_use_list + path: (identifier) @module) + +(scoped_use_list + path: (scoped_identifier + (identifier) @module)) + +(use_list + (scoped_identifier + (identifier) @module + . + (_))) + +(use_list + (identifier) @type + (#lua-match? @type "^[A-Z]")) + +(use_as_clause + alias: (identifier) @type + (#lua-match? @type "^[A-Z]")) + +; Correct enum constructors +(call_expression + function: (scoped_identifier + "::" + name: (identifier) @constant) + (#lua-match? @constant "^[A-Z]")) + +; Assume uppercase names in a match arm are constants. +((match_arm + pattern: (match_pattern + (identifier) @constant)) + (#lua-match? @constant "^[A-Z]")) + +((match_arm + pattern: (match_pattern + (scoped_identifier + name: (identifier) @constant))) + (#lua-match? @constant "^[A-Z]")) + +((identifier) @constant.builtin + (#any-of? @constant.builtin "Some" "None" "Ok" "Err")) + +; Macro definitions +"$" @function.macro + +(metavariable) @function.macro + +(macro_definition + "macro_rules!" @function.macro) + +; Attribute macros +(attribute_item + (attribute + (identifier) @function.macro)) + +(inner_attribute_item + (attribute + (identifier) @function.macro)) + +(attribute + (scoped_identifier + (identifier) @function.macro .)) + +; Derive macros (assume all arguments are types) +; (attribute +; (identifier) @_name +; arguments: (attribute (attribute (identifier) @type)) +; (#eq? @_name "derive")) +; Function-like macros +(macro_invocation + macro: (identifier) @function.macro) + +(macro_invocation + macro: (scoped_identifier + (identifier) @function.macro .)) + +; Literals +[ + (line_comment) + (block_comment) +] @comment @spell + +(line_comment + (doc_comment)) @comment.documentation + +(block_comment + (doc_comment)) @comment.documentation + +(boolean_literal) @boolean + +(integer_literal) @number + +(float_literal) @number.float + +[ + (raw_string_literal) + (string_literal) +] @string + +(escape_sequence) @string.escape + +(char_literal) @character + +; Keywords +[ + "use" + "mod" +] @keyword.import + +(use_as_clause + "as" @keyword.import) + +[ + "default" + "impl" + "let" + "move" + "unsafe" + "where" +] @keyword + +[ + "enum" + "struct" + "union" + "trait" + "type" +] @keyword.type + +[ + "async" + "await" +] @keyword.coroutine + +"try" @keyword.exception + +[ + "ref" + "pub" + (mutable_specifier) + "const" + "static" + "dyn" + "extern" +] @keyword.modifier + +(lifetime + "'" @keyword.modifier) + +(lifetime + (identifier) @attribute) + +(lifetime + (identifier) @attribute.builtin + (#any-of? @attribute.builtin "static" "_")) + +"fn" @keyword.function + +[ + "return" + "yield" +] @keyword.return + +(type_cast_expression + "as" @keyword.operator) + +(qualified_type + "as" @keyword.operator) + +(use_list + (self) @module) + +(scoped_use_list + (self) @module) + +(scoped_identifier + [ + (crate) + (super) + (self) + ] @module) + +(visibility_modifier + [ + (crate) + (super) + (self) + ] @module) + +[ + "if" + "else" + "match" +] @keyword.conditional + +[ + "break" + "continue" + "in" + "loop" + "while" +] @keyword.repeat + +"for" @keyword + +(for_expression + "for" @keyword.repeat) + +; Operators +[ + "!" + "!=" + "%" + "%=" + "&" + "&&" + "&=" + "*" + "*=" + "+" + "+=" + "-" + "-=" + ".." + "..=" + "..." + "/" + "/=" + "<" + "<<" + "<<=" + "<=" + "=" + "==" + ">" + ">=" + ">>" + ">>=" + "?" + "@" + "^" + "^=" + "|" + "|=" + "||" +] @operator + +(use_wildcard + "*" @character.special) + +; Punctuation +[ + "(" + ")" + "[" + "]" + "{" + "}" +] @punctuation.bracket + +(closure_parameters + "|" @punctuation.bracket) + +(type_arguments + [ + "<" + ">" + ] @punctuation.bracket) + +(type_parameters + [ + "<" + ">" + ] @punctuation.bracket) + +(bracketed_type + [ + "<" + ">" + ] @punctuation.bracket) + +(for_lifetimes + [ + "<" + ">" + ] @punctuation.bracket) + +[ + "," + "." + ":" + "::" + ";" + "->" + "=>" +] @punctuation.delimiter + +(attribute_item + "#" @punctuation.special) + +(inner_attribute_item + [ + "!" + "#" + ] @punctuation.special) + +(macro_invocation + "!" @function.macro) + +(never_type + "!" @type.builtin) + +(macro_invocation + macro: (identifier) @keyword.exception + "!" @keyword.exception + (#eq? @keyword.exception "panic")) + +(macro_invocation + macro: (identifier) @keyword.exception + "!" @keyword.exception + (#contains? @keyword.exception "assert")) + +(macro_invocation + macro: (identifier) @keyword.debug + "!" @keyword.debug + (#eq? @keyword.debug "dbg")) diff --git a/rust/indents.scm b/rust/indents.scm new file mode 100644 index 0000000..dfe0a38 --- /dev/null +++ b/rust/indents.scm @@ -0,0 +1,117 @@ +[ + (mod_item) + (struct_item) + (enum_item) + (impl_item) + (struct_expression) + (struct_pattern) + (tuple_struct_pattern) + (tuple_expression) + (tuple_type) + (tuple_pattern) + (match_block) + (call_expression) + (assignment_expression) + (arguments) + (block) + (where_clause) + (use_list) + (array_expression) + (ordered_field_declaration_list) + (field_declaration_list) + (enum_variant_list) + (parameters) + (token_tree) + (token_repetition) + (macro_definition) +] @indent.begin + +; Typing in "(" inside macro definitions breaks the tree entirely +; Making macro_definition becoming errors +; Offset this by adding back one indent for start of macro rules +(ERROR + . + "macro_rules!" + [ + "(" + "{" + "[" + ] @indent.begin + (#set! indent.immediate) + (#set! indent.start_at_same_line)) + +(macro_definition + [ + ")" + "}" + "]" + ] @indent.end) + +(trait_item + body: (_) @indent.begin) + +(string_literal + (escape_sequence)) @indent.begin + +(block + "}" @indent.end) + +(enum_item + body: (enum_variant_list + "}" @indent.end)) + +(impl_item + body: (declaration_list + "}" @indent.end)) + +(match_expression + body: (match_block + "}" @indent.end)) + +(mod_item + body: (declaration_list + "}" @indent.end)) + +(struct_item + body: (field_declaration_list + "}" @indent.end)) + +(struct_expression + body: (field_initializer_list + "}" @indent.end)) + +(struct_pattern + "}" @indent.end) + +(tuple_struct_pattern + ")" @indent.end) + +(tuple_type + ")" @indent.end) + +(tuple_pattern + ")" @indent.end) + +(trait_item + body: (declaration_list + "}" @indent.end)) + +(impl_item + (where_clause) @indent.dedent) + +[ + "where" + ")" + "]" + "}" +] @indent.branch + +(impl_item + (declaration_list) @indent.branch) + +[ + (line_comment) + (string_literal) +] @indent.ignore + +(raw_string_literal) @indent.auto diff --git a/rust/injections.scm b/rust/injections.scm new file mode 100644 index 0000000..c8c3601 --- /dev/null +++ b/rust/injections.scm @@ -0,0 +1,91 @@ +(macro_invocation + macro: [ + (scoped_identifier + name: (_) @_macro_name) + (identifier) @_macro_name + ] + (token_tree) @injection.content + (#not-eq? @_macro_name "slint") + (#set! injection.language "rust") + (#set! injection.include-children)) + +(macro_invocation + macro: [ + (scoped_identifier + name: (_) @_macro_name) + (identifier) @_macro_name + ] + (token_tree) @injection.content + (#eq? @_macro_name "slint") + (#offset! @injection.content 0 1 0 -1) + (#set! injection.language "slint") + (#set! injection.include-children)) + +(macro_definition + (macro_rule + left: (token_tree_pattern) @injection.content + (#set! injection.language "rust"))) + +(macro_definition + (macro_rule + right: (token_tree) @injection.content + (#set! injection.language "rust"))) + +([ + (line_comment) + (block_comment) +] @injection.content + (#set! injection.language "comment")) + +((macro_invocation + macro: (identifier) @injection.language + (token_tree) @injection.content) + (#any-of? @injection.language "html" "json")) + +(call_expression + function: (scoped_identifier + path: (identifier) @_regex + (#any-of? @_regex "Regex" "ByteRegexBuilder") + name: (identifier) @_new + (#eq? @_new "new")) + arguments: (arguments + (raw_string_literal) @injection.content) + (#set! injection.language "regex")) + +(call_expression + function: (scoped_identifier + path: (scoped_identifier + (identifier) @_regex + (#any-of? @_regex "Regex" "ByteRegexBuilder") .) + name: (identifier) @_new + (#eq? @_new "new")) + arguments: (arguments + (raw_string_literal) @injection.content) + (#set! injection.language "regex")) + +(call_expression + function: (scoped_identifier + path: (identifier) @_regex + (#any-of? @_regex "RegexSet" "RegexSetBuilder") + name: (identifier) @_new + (#eq? @_new "new")) + arguments: (arguments + (array_expression + (raw_string_literal) @injection.content)) + (#set! injection.language "regex")) + +(call_expression + function: (scoped_identifier + path: (scoped_identifier + (identifier) @_regex + (#any-of? @_regex "RegexSet" "RegexSetBuilder") .) + name: (identifier) @_new + (#eq? @_new "new")) + arguments: (arguments + (array_expression + (raw_string_literal) @injection.content)) + (#set! injection.language "regex")) + +((block_comment) @injection.content + (#match? @injection.content "/\\*!([a-zA-Z]+:)?re2c") + (#set! injection.language "re2c")) diff --git a/rust/locals.scm b/rust/locals.scm new file mode 100644 index 0000000..2b1469b --- /dev/null +++ b/rust/locals.scm @@ -0,0 +1,101 @@ +; Imports +(extern_crate_declaration + name: (identifier) @local.definition.import) + +(use_declaration + argument: (scoped_identifier + name: (identifier) @local.definition.import)) + +(use_as_clause + alias: (identifier) @local.definition.import) + +(use_list + (identifier) @local.definition.import) ; use std::process::{Child, Command, Stdio}; + +; Functions +(function_item + name: (identifier) @local.definition.function) + +(function_item + name: (identifier) @local.definition.method + parameters: (parameters + (self_parameter))) + +; Variables +(parameter + pattern: (identifier) @local.definition.var) + +(let_declaration + pattern: (identifier) @local.definition.var) + +(const_item + name: (identifier) @local.definition.var) + +(tuple_pattern + (identifier) @local.definition.var) + +(let_condition + pattern: (_ + (identifier) @local.definition.var)) + +(tuple_struct_pattern + (identifier) @local.definition.var) + +(closure_parameters + (identifier) @local.definition.var) + +(self_parameter + (self) @local.definition.var) + +(for_expression + pattern: (identifier) @local.definition.var) + +; Types +(struct_item + name: (type_identifier) @local.definition.type) + +(constrained_type_parameter + left: (type_identifier) @local.definition.type) ; the P in remove_file>(path: P) + +(enum_item + name: (type_identifier) @local.definition.type) + +; Fields +(field_declaration + name: (field_identifier) @local.definition.field) + +(enum_variant + name: (identifier) @local.definition.field) + +; References +(identifier) @local.reference + +((type_identifier) @local.reference + (#set! reference.kind "type")) + +((field_identifier) @local.reference + (#set! reference.kind "field")) + +; Macros +(macro_definition + name: (identifier) @local.definition.macro) + +; Module +(mod_item + name: (identifier) @local.definition.namespace) + +; Scopes +[ + (block) + (function_item) + (closure_expression) + (while_expression) + (for_expression) + (loop_expression) + (if_expression) + (match_expression) + (match_arm) + (struct_item) + (enum_item) + (impl_item) +] @local.scope