From 311a2a670d43909b442085c20bcc8ffabdebff4a Mon Sep 17 00:00:00 2001 From: Dmitry Salin Date: Wed, 15 May 2024 17:24:57 +0300 Subject: [PATCH] Add support for Mojo (#10743) * Add support for Mojo * Update grammar * Fix queries * Fix docs * Use inheritance for some files --- book/src/generated/lang-support.md | 1 + languages.toml | 17 ++ runtime/queries/mojo/highlights.scm | 250 +++++++++++++++++++++++++++ runtime/queries/mojo/indents.scm | 1 + runtime/queries/mojo/injections.scm | 1 + runtime/queries/mojo/locals.scm | 1 + runtime/queries/mojo/textobjects.scm | 1 + 7 files changed, 272 insertions(+) create mode 100644 runtime/queries/mojo/highlights.scm create mode 100644 runtime/queries/mojo/indents.scm create mode 100644 runtime/queries/mojo/injections.scm create mode 100644 runtime/queries/mojo/locals.scm create mode 100644 runtime/queries/mojo/textobjects.scm diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index 27fd583c230b..d013f20120b8 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -125,6 +125,7 @@ | mermaid | ✓ | | | | | meson | ✓ | | ✓ | | | mint | | | | `mint` | +| mojo | ✓ | ✓ | ✓ | `mojo-lsp-server` | | move | ✓ | | | | | msbuild | ✓ | | ✓ | | | nasm | ✓ | ✓ | | | diff --git a/languages.toml b/languages.toml index 2cfa7309b683..8776947a8c50 100644 --- a/languages.toml +++ b/languages.toml @@ -55,6 +55,7 @@ markdown-oxide = { command = "markdown-oxide" } marksman = { command = "marksman", args = ["server"] } metals = { command = "metals", config = { "isHttpEnabled" = true, metals = { inlayHints = { typeParameters = {enable = true} , hintsInPatternMatch = {enable = true} } } } } mint = { command = "mint", args = ["ls"] } +mojo-lsp = { command = "mojo-lsp-server" } nil = { command = "nil" } nimlangserver = { command = "nimlangserver" } nimlsp = { command = "nimlsp" } @@ -372,6 +373,22 @@ block-comment-tokens = { start = "/*", end = "*/" } language-servers = [ "mint" ] indent = { tab-width = 2, unit = " " } +[[language]] +name = "mojo" +scope = "source.mojo" +roots = ["__init__.mojo"] +injection-regex = "mojo" +file-types = ["mojo", "🔥"] +language-servers = [ "mojo-lsp" ] +comment-token = "#" +indent = { tab-width = 4, unit = " " } +auto-format = true +formatter = { command = "mojo", args = ["format", "-q", "-"]} + +[[grammar]] +name = "mojo" +source = { git = "https://github.com/lsh/tree-sitter-mojo", rev = "3d7c53b8038f9ebbb57cd2e61296180aa5c1cf64" } + [[language]] name = "janet" scope = "source.janet" diff --git a/runtime/queries/mojo/highlights.scm b/runtime/queries/mojo/highlights.scm new file mode 100644 index 000000000000..7acaf1eadeb8 --- /dev/null +++ b/runtime/queries/mojo/highlights.scm @@ -0,0 +1,250 @@ +; Docstrings + +(expression_statement (string) @comment.block.documentation) + +; Imports + +(dotted_name + (identifier)* @namespace) + +(aliased_import + alias: (identifier) @namespace) + +; Builtin functions + +((call + function: (identifier) @function.builtin) + (#match? + @function.builtin + "^(abs|all|always_inline|any|ascii|bin|bool|breakpoint|bytearray|bytes|callable|chr|classmethod|compile|complex|constrained|delattr|dict|dir|divmod|enumerate|eval|exec|filter|float|format|frozenset|getattr|globals|hasattr|hash|help|hex|id|input|int|isinstance|issubclass|iter|len|list|locals|map|max|memoryview|min|next|object|oct|open|ord|pow|print|property|range|repr|reversed|round|set|setattr|slice|sorted|staticmethod|str|sum|super|tuple|type|unroll|vars|zip|__mlir_attr|__mlir_op|__mlir_type|__import__)$")) + +; Function calls + +[ + "def" + "lambda" + "fn" +] @keyword.function + +(call + function: (attribute attribute: (identifier) @constructor) + (#match? @constructor "^[A-Z]")) + +(call + function: (identifier) @constructor + (#match? @constructor "^[A-Z]")) + +(call + function: (attribute attribute: (identifier) @function.method)) + +(call + function: (identifier) @function) + +; Function definitions + +(function_definition + name: (identifier) @constructor + (#match? @constructor "^(__new__|__init__|__moveinit__|__copyinit__)$")) + +(function_definition + name: (identifier) @function) + +; Decorators + +(decorator) @function +(decorator (identifier) @function) +(decorator (attribute attribute: (identifier) @function)) +(decorator (call + function: (attribute attribute: (identifier) @function))) + +; Parameters + +((identifier) @variable.builtin + (#match? @variable.builtin "^(self|cls)$")) + +(parameters (identifier) @variable.parameter) +(parameters (typed_parameter (identifier) @variable.parameter)) +(parameters (default_parameter name: (identifier) @variable.parameter)) +(parameters (typed_default_parameter name: (identifier) @variable.parameter)) + +(parameters + (list_splat_pattern ; *args + (identifier) @variable.parameter)) + +(parameters + (dictionary_splat_pattern ; **kwargs + (identifier) @variable.parameter)) + +(lambda_parameters + (identifier) @variable.parameter) + +; Types + +((identifier) @type.builtin + (#match? + @type.builtin + "^(bool|bytes|dict|float|frozenset|int|list|set|str|tuple)$")) + +; In type hints make everything types to catch non-conforming identifiers +; (e.g., datetime.datetime) and None +(type [(identifier) (none)] @type) +; Handle [] . and | nesting 4 levels deep +(type + (_ [(identifier) (none)]? @type + (_ [(identifier) (none)]? @type + (_ [(identifier) (none)]? @type + (_ [(identifier) (none)]? @type))))) + +(class_definition name: (identifier) @type) +(class_definition superclasses: (argument_list (identifier) @type)) + +; Variables + +((identifier) @constant + (#match? @constant "^_*[A-Z][A-Z\\d_]*$")) + +((identifier) @type + (#match? @type "^[A-Z]")) + +(attribute attribute: (identifier) @variable.other.member) +(identifier) @variable + +; Literals +(none) @constant.builtin +[ + (true) + (false) +] @constant.builtin.boolean + +(integer) @constant.numeric.integer +(float) @constant.numeric.float +(comment) @comment +(string) @string +(escape_sequence) @constant.character.escape + +["," "." ":" ";" (ellipsis)] @punctuation.delimiter +(interpolation + "{" @punctuation.special + "}" @punctuation.special) @embedded +["(" ")" "[" "]" "{" "}"] @punctuation.bracket + +[ + "-" + "-=" + "!=" + "*" + "**" + "**=" + "*=" + "/" + "//" + "//=" + "/=" + "&" + "&=" + "%" + "%=" + "^" + "^=" + "+" + "->" + "+=" + "<" + "<<" + "<<=" + "<=" + "<>" + "=" + ":=" + "==" + ">" + ">=" + ">>" + ">>=" + "|" + "|=" + "~" + "@=" +] @operator + +[ + "as" + "assert" + "await" + "from" + "pass" + "with" +] @keyword.control + +[ + "if" + "elif" + "else" + "match" + "case" +] @keyword.control.conditional + +[ + "while" + "for" + "break" + "continue" +] @keyword.control.repeat + +[ + "return" + "yield" +] @keyword.control.return + +(yield "from" @keyword.control.return) + +[ + "raise" + "raises" + "try" + "except" + "finally" +] @keyword.control.exception + +(raise_statement "from" @keyword.control.exception) +"import" @keyword.control.import + +(for_statement "in" @keyword.control) +(for_in_clause "in" @keyword.control) + +[ + "alias" + "async" + "class" + "exec" + "global" + "nonlocal" + "print" + "struct" + ; "trait" +] @keyword + +[ + "and" + "or" + "not in" + "in" + "not" + "del" + "is not" + "is" +] @keyword.operator + +"var" @keyword.storage + +[ + "borrowed" + "inout" + "owned" +] @keyword.storage.modifier + +((identifier) @type.builtin + (#match? @type.builtin + "^(BaseException|Exception|ArithmeticError|BufferError|LookupError|AssertionError|AttributeError|EOFError|FloatingPointError|GeneratorExit|ImportError|ModuleNotFoundError|IndexError|KeyError|KeyboardInterrupt|MemoryError|NameError|NotImplementedError|OSError|OverflowError|RecursionError|ReferenceError|RuntimeError|StopIteration|StopAsyncIteration|SyntaxError|IndentationError|TabError|SystemError|SystemExit|TypeError|UnboundLocalError|UnicodeError|UnicodeEncodeError|UnicodeDecodeError|UnicodeTranslateError|ValueError|ZeroDivisionError|EnvironmentError|IOError|WindowsError|BlockingIOError|ChildProcessError|ConnectionError|BrokenPipeError|ConnectionAbortedError|ConnectionRefusedError|ConnectionResetError|FileExistsError|FileNotFoundError|InterruptedError|IsADirectoryError|NotADirectoryError|PermissionError|ProcessLookupError|TimeoutError|Warning|UserWarning|DeprecationWarning|PendingDeprecationWarning|SyntaxWarning|RuntimeWarning|FutureWarning|ImportWarning|UnicodeWarning|BytesWarning|ResourceWarning)$")) + +(ERROR) @error diff --git a/runtime/queries/mojo/indents.scm b/runtime/queries/mojo/indents.scm new file mode 100644 index 000000000000..0b920cbf91ca --- /dev/null +++ b/runtime/queries/mojo/indents.scm @@ -0,0 +1 @@ +; inherits: python diff --git a/runtime/queries/mojo/injections.scm b/runtime/queries/mojo/injections.scm new file mode 100644 index 000000000000..0b920cbf91ca --- /dev/null +++ b/runtime/queries/mojo/injections.scm @@ -0,0 +1 @@ +; inherits: python diff --git a/runtime/queries/mojo/locals.scm b/runtime/queries/mojo/locals.scm new file mode 100644 index 000000000000..0b920cbf91ca --- /dev/null +++ b/runtime/queries/mojo/locals.scm @@ -0,0 +1 @@ +; inherits: python diff --git a/runtime/queries/mojo/textobjects.scm b/runtime/queries/mojo/textobjects.scm new file mode 100644 index 000000000000..0b920cbf91ca --- /dev/null +++ b/runtime/queries/mojo/textobjects.scm @@ -0,0 +1 @@ +; inherits: python