diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index a5b4df03..ba2bee71 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -189,6 +189,7 @@ | mint | | | | | | `mint` | | miseconfig | ✓ | ✓ | ✓ | | | `taplo`, `tombi` | | mojo | ✓ | ✓ | ✓ | | | `pixi` | +| moonbit | ✓ | ✓ | ✓ | ✓ | | `moonbit-lsp` | | move | ✓ | | ✓ | | | | | msbuild | ✓ | | ✓ | | | | | nasm | ✓ | ✓ | | | | `asm-lsp` | diff --git a/languages.toml b/languages.toml index 051dede8..547265d6 100644 --- a/languages.toml +++ b/languages.toml @@ -327,6 +327,9 @@ args = ["server", "--stdio"] [language-server.drools-lsp] command = "drools-lsp" +[language-server.moonbit-lsp] +command = "moonbit-lsp" + [language-server.millet] command = "millet-ls" @@ -5527,6 +5530,22 @@ comment-token = "//" name = "tql" source = { git = "https://github.com/tenzir/tree-sitter-tql", rev = "477e8ba230867b9135deb7af88ea96f160900173" } +[[language]] +name = "moonbit" +scope = "source.moonbit" +injection-regex = "moonbit|mbt" +file-types = ["mbt", "mbti"] +roots = ["moon.mod.json"] +comment-tokens = ["//", "///"] +block-comment-tokens = { start = "/*", end = "*/" } +indent = { tab-width = 2, unit = " " } +language-servers = ["moonbit-lsp"] +auto-format = true + +[[grammar]] +name = "moonbit" +source = { git = "https://github.com/moonbitlang/tree-sitter-moonbit", rev = "36191d7fe4ec4298c8c1f251af6a82939f8e9a67" } + [[language]] name = "concerto" scope = "source.concerto" diff --git a/runtime/queries/moonbit/highlights.scm b/runtime/queries/moonbit/highlights.scm new file mode 100644 index 00000000..9b0a255d --- /dev/null +++ b/runtime/queries/moonbit/highlights.scm @@ -0,0 +1,251 @@ +; Packages + +(package_identifier) @namespace + +; Variables + +(positional_parameter (lowercase_identifier) @variable.parameter) +(labelled_parameter (label (lowercase_identifier)) @variable.parameter) +(optional_parameter (optional_label (lowercase_identifier)) @variable.parameter) +(optional_parameter_with_default (label (lowercase_identifier)) @variable.parameter) +((positional_parameter (lowercase_identifier) @variable.builtin) + (#any-of? @variable.builtin "self")) +((labelled_parameter (label (lowercase_identifier)) @variable.builtin) + (#any-of? @variable.builtin "self")) +((optional_parameter (optional_label (lowercase_identifier)) @variable.builtin) + (#any-of? @variable.builtin "self")) +((optional_parameter_with_default (label (lowercase_identifier)) @variable.builtin) + (#any-of? @variable.builtin "self")) + +(tuple_pattern (lowercase_identifier) @variable) +(constructor_pattern_argument . (lowercase_identifier) @variable .) +(constructor_pattern_argument "=" (lowercase_identifier) @variable) +(constructor_pattern_argument (label (lowercase_identifier) @variable)) +(case_clause (lowercase_identifier) @variable "=>") +(matrix_case_clause (lowercase_identifier) @variable "=>") +(let_expression (lowercase_identifier) @variable) + +(qualified_identifier (lowercase_identifier) @variable) +((qualified_identifier (lowercase_identifier) @variable.builtin) + (#any-of? @variable.builtin "self")) +(qualified_identifier (dot_lowercase_identifier) @variable) + +(value_definition (lowercase_identifier) @variable) +(let_mut_expression (lowercase_identifier) @variable) +(for_in_expression "for" (lowercase_identifier) @variable "in") +(for_binder (lowercase_identifier) @variable) +(package_statement_identifier) @variable +(package_assignment_statement + name: (package_statement_identifier) @variable) + +; Constructors + +(enum_constructor) @constructor +(constructor_expression (uppercase_identifier) @constructor) +(constructor_expression (dot_uppercase_identifier) @constructor) + +; Constants + +(const_definition (uppercase_identifier) @constant) +((constructor_expression (uppercase_identifier) @constant) + (#match? @constant "^[A-Z][A-Z_]+$")) +((constructor_expression (dot_uppercase_identifier) @constant) + (#match? @constant "^\.[A-Z][A-Z_]+$")) + +; Types + +(type_identifier) @type +(qualified_type_identifier) @type + +(enum_definition (identifier) @type) +(struct_definition (identifier) @type) +(tuple_struct_definition (identifier) @type) +(type_definition (identifier) @type) +(trait_definition (identifier) @type) +(type_alias_targets (identifier) @type) +(type_alias_targets (dot_identifier) @type) +(type_alias_target (identifier) @type) +(error_type_definition (identifier) @type) +(trait_alias_targets (identifier) @type) +(trait_alias_targets (dot_identifier) @type) +(trait_alias_target (identifier) @type) + +((qualified_type_identifier) @type.builtin + (#any-of? @type.builtin + "Unit" "Bool" "Byte" + "Int16" "UInt16" "Int" "UInt" "Int64" "UInt64" + "Float" "Double" + "FixedArray" "Array" "Bytes" "String" "Error" "Self")) + +((qualified_type_identifier) @type.builtin + (#any-of? @type.builtin + "Eq" "Compare" "Hash" "Show" "Default" "ToJson" "FromJson")) + +; Fields + +(struct_field_declaration (lowercase_identifier) @variable.other.member) +(struct_expression (labeled_expression (lowercase_identifier) @variable.other.member)) +(struct_expression (labeled_expression_pun (lowercase_identifier) @variable.other.member)) +(struct_field_expression (labeled_expression (lowercase_identifier) @variable.other.member)) +(struct_field_expression (labeled_expression_pun (lowercase_identifier) @variable.other.member)) +(struct_pattern (struct_field_pattern (labeled_pattern (lowercase_identifier) @variable.other.member))) +(struct_pattern (struct_field_pattern (labeled_pattern_pun (lowercase_identifier) @variable.other.member))) +(access_expression (accessor (dot_identifier) @variable.other.member)) +(constructor_pattern_argument (lowercase_identifier) @variable.other.member "=") +(apply_expression (constructor_expression) (arguments (argument (labelled_argument (lowercase_identifier) @variable.other.member "=")))) + +; Attributes + +(attribute) @attribute + +; Function calls + +(apply_expression (qualified_identifier (lowercase_identifier) @function)) +(apply_expression (qualified_identifier (dot_lowercase_identifier) @function)) +(package_apply_statement + name: (package_statement_identifier) @function) + +; Method calls + +(method_expression (lowercase_identifier) @function.method) +(dot_apply_expression (dot_identifier) @function.method) +(dot_dot_apply_expression (dot_dot_identifier) @function.method) + +; Function definitions + +(function_definition (function_identifier (lowercase_identifier) @function)) +(struct_constructor_declaration (lowercase_identifier) @function) +(function_alias_targets (lowercase_identifier) @function) +(function_alias_targets (dot_lowercase_identifier) @function) +(function_alias_target (lowercase_identifier) @function) +(trait_method_declaration (function_identifier) @function) +(impl_definition (function_identifier) @function) + +; Method definitions + +(function_definition (function_identifier (type_name (qualified_type_identifier)) (lowercase_identifier) @function.method)) + +; Labels + +(loop_label) @label +("continue" (label) @label) +("break" (label) @label) +(package_argument + label: (package_statement_identifier) @label) +(package_argument + label: (string_literal) @label) +(package_map_entry + key: (string_literal) @label) +(where_clause_field (lowercase_identifier) @label) + +; Operators + +[ + "+" "-" "*" "/" "%" + "<<" ">>" "|" "&" "^" + "=" "+=" "-=" "*=" "/=" "%=" + "<" ">" ">=" "<=" "==" "!=" + "&&" "||" + "|>" + "=>" "->" + "!" "!!" "?" +] @operator + +; Keywords + +[ (mutability) "mut" ] @keyword.storage.modifier + +[ + "struct" "enum" "type" "trait" "typealias" "traitalias" "suberror" +] @keyword.storage.type + +[ + "pub" "priv" "readonly" "all" "open" "extern" +] @keyword.storage.modifier + +[ + "guard" "let" "letrec" "and" "const" + "with" "as" "is" "lexmatch?" "using" "where" "longest" "nobreak" + "defer" +] @keyword + +"derive" @keyword + +[ "package" "import" ] @keyword.control.import + +[ "fn" "test" "impl" "fnalias" ] @keyword.function +"return" @keyword.control.return +[ "while" "loop" "for" "break" "continue" "in" ] @keyword.control.repeat + +[ + "if" + "else" + "match" +] @keyword.control.conditional + +"async" @keyword + +[ "try" "raise" "catch" "noraise" ] @keyword.control.exception + +((lowercase_identifier) @keyword + (#any-of? @keyword + "import" "using" + "proof_assert" "proof_let" + "defer" "lexmatch" "recur")) + +((lowercase_identifier) @keyword.control.exception + (#eq? @keyword.control.exception "except")) + +; Delimiters + +[ + ";" + "," +] @punctuation.delimiter + +":" @punctuation.delimiter +"::" @punctuation.delimiter +"." @punctuation.delimiter +".." @punctuation.delimiter + +(array_sub_pattern "..") @operator +(dot_dot_apply_expression (dot_dot_identifier ".." @punctuation.delimiter)) + +[ + "..<" + "..=" + "..<=" + "..>" + "..>=" +] @operator + +[ + "(" ")" + "{" "}" + "[" "]" +] @punctuation.bracket + +; Literals + +(string_interpolation) @string +(string_literal) @string +(multiline_string_literal) @string +(escape_sequence) @constant.character.escape + +(interpolator + "\\{" @punctuation.special + "}" @punctuation.special) + +(integer_literal) @constant.numeric.integer +(float_literal) @constant.numeric.float +(boolean_literal) @constant.builtin.boolean +(char_literal) @constant.character + +; Comments + +(comment) @comment +(block_comment) @comment.block + +; Errors + +(ERROR) @error diff --git a/runtime/queries/moonbit/indents.scm b/runtime/queries/moonbit/indents.scm new file mode 100644 index 00000000..47ccb6cd --- /dev/null +++ b/runtime/queries/moonbit/indents.scm @@ -0,0 +1,21 @@ +[ + (block_expression) + (loop_expression) + (match_expression) + (struct_expression) + (function_definition) + (struct_definition) + (enum_definition) + (trait_definition) + (impl_definition) + (apply_expression) + (dot_apply_expression) + (arguments) + (parameters) +] @indent + +[ + ")" + "}" + "]" +] @outdent diff --git a/runtime/queries/moonbit/injections.scm b/runtime/queries/moonbit/injections.scm new file mode 100644 index 00000000..aebb54d9 --- /dev/null +++ b/runtime/queries/moonbit/injections.scm @@ -0,0 +1,5 @@ +((comment) @injection.content + (#set! injection.language "comment")) + +((block_comment) @injection.content + (#set! injection.language "comment")) diff --git a/runtime/queries/moonbit/locals.scm b/runtime/queries/moonbit/locals.scm new file mode 100644 index 00000000..b786d898 --- /dev/null +++ b/runtime/queries/moonbit/locals.scm @@ -0,0 +1,36 @@ +; Scopes + +[ + (structure) + (function_definition) + (anonymous_lambda_expression) + (named_lambda_expression) + (block_expression) +] @local.scope + +; Definitions + +(value_definition (lowercase_identifier) @local.definition.variable) +(let_expression (lowercase_identifier) @local.definition.variable) +(letrec_expression (lowercase_identifier) @local.definition.variable) +(and_expression (lowercase_identifier) @local.definition.variable) +(guard_let_expression (lowercase_identifier) @local.definition.variable) +(let_mut_expression (lowercase_identifier) @local.definition.variable.mutable) + +(positional_parameter (lowercase_identifier) @local.definition.variable.parameter) +(labelled_parameter (label (lowercase_identifier)) @local.definition.variable.parameter) +(optional_parameter (optional_label (lowercase_identifier)) @local.definition.variable.parameter) +(optional_parameter_with_default (label (lowercase_identifier)) @local.definition.variable.parameter) + +((positional_parameter (lowercase_identifier) @local.definition.variable.builtin) + (#eq? @local.definition.variable.builtin "self")) +((labelled_parameter (label (lowercase_identifier)) @local.definition.variable.builtin) + (#eq? @local.definition.variable.builtin "self")) +((optional_parameter (optional_label (lowercase_identifier)) @local.definition.variable.builtin) + (#eq? @local.definition.variable.builtin "self")) +((optional_parameter_with_default (label (lowercase_identifier)) @local.definition.variable.builtin) + (#eq? @local.definition.variable.builtin "self")) + +; References + +(qualified_identifier) @local.reference diff --git a/runtime/queries/moonbit/tags.scm b/runtime/queries/moonbit/tags.scm new file mode 100644 index 00000000..e2f3d874 --- /dev/null +++ b/runtime/queries/moonbit/tags.scm @@ -0,0 +1,29 @@ +(function_definition + (function_identifier (lowercase_identifier) @name)) @definition.function + +(struct_constructor_declaration + (lowercase_identifier) @name) @definition.function + +(trait_method_declaration + (function_identifier (lowercase_identifier) @name)) @definition.function + +(struct_definition + (identifier) @name) @definition.struct + +(tuple_struct_definition + (identifier) @name) @definition.struct + +(enum_definition + (identifier) @name) @definition.enum + +(type_definition + (identifier) @name) @definition.type + +(error_type_definition + (identifier) @name) @definition.type + +(trait_definition + (identifier) @name) @definition.interface + +(const_definition + (uppercase_identifier) @name) @definition.constant diff --git a/runtime/queries/moonbit/textobjects.scm b/runtime/queries/moonbit/textobjects.scm new file mode 100644 index 00000000..cdcf608c --- /dev/null +++ b/runtime/queries/moonbit/textobjects.scm @@ -0,0 +1,80 @@ +; Functions + +((function_definition + ("fn" + (block_expression) @function.inside) + (#offset! @function.inside 0 1 0 -1)) + @function.around) + +((function_definition + (external_source (_) @function.inside) + .) + @function.around) + +(trait_method_declaration) @function.around + +((impl_definition + ("impl" + (block_expression) @function.inside) + (#offset! @function.inside 0 1 0 -1)) + @function.around) + +; Tests + +((test_definition + ("test" + (block_expression) @test.inside) + (#offset! @test.inside 0 1 0 -1)) + @test.around) + +; Classes (type-like definitions) + +(struct_definition) @class.around +(enum_definition) @class.around +(trait_definition) @class.around +(type_definition) @class.around + +; Parameters + +((parameters + . + (parameter) @parameter.inside + . + ","? @_end) + (#make-range! "parameter.around" @parameter.inside @_end)) + +((trait_method_declaration + (trait_method_parameter) @parameter.inside + . + ","? @_end) + (#make-range! "parameter.around" @parameter.inside @_end)) + +((apply_expression + (arguments + (argument) @parameter.inside + . + ","? @_end)) + (#make-range! "parameter.around" @parameter.inside @_end)) + +((dot_apply_expression + (argument) @parameter.inside + . + ","? @_end) + (#make-range! "parameter.around" @parameter.inside @_end)) + +((dot_dot_apply_expression + (argument) @parameter.inside + . + ","? @_end) + (#make-range! "parameter.around" @parameter.inside @_end)) + +((array_expression + (_) @parameter.inside + . + ","? @_end) + (#make-range! "parameter.around" @parameter.inside @_end)) + +; Comments + +(comment) @comment.around +(block_comment) @comment.around