From 69a8efd53579b1f99b00f90c4164b627d969c988 Mon Sep 17 00:00:00 2001 From: Pascal Eberhard Date: Sun, 24 Mar 2024 17:45:19 +0100 Subject: [PATCH] add initial support for bitbake language Signed-off-by: Pascal Eberhard --- book/src/generated/lang-support.md | 1 + languages.toml | 12 + runtime/queries/bitbake/folds.scm | 29 ++ runtime/queries/bitbake/highlights.scm | 360 +++++++++++++++++++++++++ runtime/queries/bitbake/injections.scm | 14 + runtime/queries/bitbake/locals.scm | 99 +++++++ 6 files changed, 515 insertions(+) create mode 100644 runtime/queries/bitbake/folds.scm create mode 100644 runtime/queries/bitbake/highlights.scm create mode 100644 runtime/queries/bitbake/injections.scm create mode 100644 runtime/queries/bitbake/locals.scm diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index 2030949eb465c..a491296fb82f5 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -9,6 +9,7 @@ | beancount | ✓ | | | | | bibtex | ✓ | | | `texlab` | | bicep | ✓ | | | `bicep-langserver` | +| bitbake | ✓ | | | `bitbake-language-server` | | blade | ✓ | | | | | blueprint | ✓ | | | `blueprint-compiler` | | c | ✓ | ✓ | ✓ | `clangd` | diff --git a/languages.toml b/languages.toml index 9eb80414f36b0..bea94fbd62871 100644 --- a/languages.toml +++ b/languages.toml @@ -12,6 +12,7 @@ awk-language-server = { command = "awk-language-server" } bash-language-server = { command = "bash-language-server", args = ["start"] } bass = { command = "bass", args = ["--lsp"] } bicep-langserver = { command = "bicep-langserver" } +bitbake-language-server = { command = "bitbake-language-server" } bufls = { command = "bufls", args = ["serve"] } cairo-language-server = { command = "cairo-language-server", args = [] } cl-lsp = { command = "cl-lsp", args = [ "stdio" ] } @@ -3209,6 +3210,17 @@ indent = { tab-width = 2, unit = " " } name = "dbml" source = { git = "https://github.com/dynamotn/tree-sitter-dbml", rev = "2e2fa5640268c33c3d3f27f7e676f631a9c68fd9" } +[[language]] +name = "bitbake" +language-servers = [ "bitbake-language-server" ] +scope = "source.bitbake" +file-types = ["bb", "bbappend", "bbclass", {glob = "conf/*.conf" }, {glob = "conf/*/*.{inc,conf}" }, { glob = "recipe-*/*/*.inc" }] +comment-token = "#" + +[[grammar]] +name = "bitbake" +source = { git = "https://github.com/tree-sitter-grammars/tree-sitter-bitbake", rev = "10bacac929ff36a1e8f4056503fe4f8717b21b94" } + [[language]] name = "log" scope = "source.log" diff --git a/runtime/queries/bitbake/folds.scm b/runtime/queries/bitbake/folds.scm new file mode 100644 index 0000000000000..9fc865e84864a --- /dev/null +++ b/runtime/queries/bitbake/folds.scm @@ -0,0 +1,29 @@ +[ + (function_definition) + (anonymous_python_function) + (python_function_definition) + + (while_statement) + (for_statement) + (if_statement) + (with_statement) + (try_statement) + + (import_from_statement) + (parameters) + (argument_list) + + (parenthesized_expression) + (generator_expression) + (list_comprehension) + (set_comprehension) + (dictionary_comprehension) + + (tuple) + (list) + (set) + (dictionary) + + (string) + (python_string) +] @fold diff --git a/runtime/queries/bitbake/highlights.scm b/runtime/queries/bitbake/highlights.scm new file mode 100644 index 0000000000000..9d8ade6de0f30 --- /dev/null +++ b/runtime/queries/bitbake/highlights.scm @@ -0,0 +1,360 @@ +; Includes + +[ + "inherit" + "include" + "require" + "export" + "import" +] @include + +; Keywords + +[ + "unset" + "EXPORT_FUNCTIONS" + "python" + + "assert" + "exec" + "global" + "nonlocal" + "pass" + "print" + "with" + "as" +] @keyword + +[ + "async" + "await" +] @keyword.coroutine + +[ + "return" + "yield" +] @keyword.return +(yield "from" @keyword.return) + +(future_import_statement + "from" @include + "__future__" @constant.builtin) +(import_from_statement "from" @include) +"import" @include + +(aliased_import "as" @include) + +["if" "elif" "else"] @conditional + +["for" "while" "break" "continue"] @repeat + +[ + "try" + "except" + "except*" + "raise" + "finally" +] @exception + +(raise_statement "from" @exception) + +(try_statement + (else_clause + "else" @exception)) + +[ + "addtask" + "deltask" + "addhandler" + "def" + "lambda" +] @keyword.function + +[ + "before" + "after" +] @storageclass + +[ + "append" + "prepend" + "remove" +] @type.qualifier + +; Variables + +[ + (identifier) + (python_identifier) +] @variable + +[ + "noexec" + "INHERIT" + "OVERRIDES" + "$BB_ENV_PASSTHROUGH" + "$BB_ENV_PASSTHROUGH_ADDITIONS" +] @variable.builtin + +; Reset highlighting in f-string interpolations +(interpolation) @none + +;; Identifier naming conventions +((python_identifier) @type + (#lua-match? @type "^[A-Z].*[a-z]")) +([(identifier) (python_identifier)] @constant + (#lua-match? @constant "^[A-Z][A-Z_0-9]*$")) + +((python_identifier) @constant.builtin + (#lua-match? @constant.builtin "^__[a-zA-Z0-9_]*__$")) + +((python_identifier) @constant.builtin + (#any-of? @constant.builtin + ;; https://docs.python.org/3/library/constants.html + "NotImplemented" + "Ellipsis" + "quit" + "exit" + "copyright" + "credits" + "license")) + +((assignment + left: (python_identifier) @type.definition + (type (python_identifier) @_annotation)) + (#eq? @_annotation "TypeAlias")) + +((assignment + left: (python_identifier) @type.definition + right: (call + function: (python_identifier) @_func)) + (#any-of? @_func "TypeVar" "NewType")) + +; Fields + +(flag) @field + +((attribute + attribute: (python_identifier) @field) + (#lua-match? @field "^[%l_].*$")) + +; Functions + +(call + function: (python_identifier) @function.call) + +(call + function: (attribute + attribute: (python_identifier) @method.call)) + +((call + function: (python_identifier) @constructor) + (#lua-match? @constructor "^%u")) + +((call + function: (attribute + attribute: (python_identifier) @constructor)) + (#lua-match? @constructor "^%u")) + +((call + function: (python_identifier) @function.builtin) + (#any-of? @function.builtin + "abs" "all" "any" "ascii" "bin" "bool" "breakpoint" "bytearray" "bytes" "callable" "chr" "classmethod" + "compile" "complex" "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" "vars" "zip" "__import__")) + +(python_function_definition + name: (python_identifier) @function) + +(type (python_identifier) @type) +(type + (subscript + (python_identifier) @type)) ; type subscript: Tuple[int] + +((call + function: (python_identifier) @_isinstance + arguments: (argument_list + (_) + (python_identifier) @type)) + (#eq? @_isinstance "isinstance")) + +(anonymous_python_function (identifier) @function) + +(function_definition (identifier) @function) + +(addtask_statement (identifier) @function) + +(deltask_statement (identifier) @function) + +(export_functions_statement (identifier) @function) + +(addhandler_statement (identifier) @function) + +(python_function_definition + body: + (block + . (expression_statement (python_string) @string.documentation @spell))) + +; Namespace + +(inherit_path) @namespace + +;; Normal parameters +(parameters + (python_identifier) @parameter) +;; Lambda parameters +(lambda_parameters + (python_identifier) @parameter) +(lambda_parameters + (tuple_pattern + (python_identifier) @parameter)) +; Default parameters +(keyword_argument + name: (python_identifier) @parameter) +; Naming parameters on call-site +(default_parameter + name: (python_identifier) @parameter) +(typed_parameter + (python_identifier) @parameter) +(typed_default_parameter + (python_identifier) @parameter) +; Variadic parameters *args, **kwargs +(parameters + (list_splat_pattern ; *args + (python_identifier) @parameter)) +(parameters + (dictionary_splat_pattern ; **kwargs + (python_identifier) @parameter)) + +;; Literals + +(none) @constant.builtin +[(true) (false)] @boolean +((python_identifier) @variable.builtin + (#eq? @variable.builtin "self")) +((python_identifier) @variable.builtin + (#eq? @variable.builtin "cls")) + +(integer) @number +(float) @float + +; Operators + +[ + "?=" + "??=" + ":=" + "=+" + ".=" + "=." + "-" + "-=" + ":=" + "!=" + "*" + "**" + "**=" + "*=" + "/" + "//" + "//=" + "/=" + "&" + "&=" + "%" + "%=" + "^" + "^=" + "+" + "+=" + "<" + "<<" + "<<=" + "<=" + "<>" + "=" + "==" + ">" + ">=" + ">>" + ">>=" + "@" + "@=" + "|" + "|=" + "~" + "->" +] @operator + +[ + "and" + "in" + "is" + "not" + "or" + "is not" + "not in" + + "del" +] @keyword.operator + +; Literals + +[ + (string) + (python_string) + "\"" +] @string + +(include_path) @string.special + +[ + (escape_sequence) + (escape_interpolation) +] @string.escape + +; Punctuation + +[ "(" ")" "{" "}" "[" "]" ] @punctuation.bracket + +[ + ":" + "->" + ";" + "." + "," + (ellipsis) +] @punctuation.delimiter + +(variable_expansion [ "${" "}" ] @punctuation.special) +(inline_python [ "${@" "}" ] @punctuation.special) +(interpolation + "{" @punctuation.special + "}" @punctuation.special) + +(type_conversion) @function.macro + +([(identifier) (python_identifier)] @type.builtin + (#any-of? @type.builtin + ;; https://docs.python.org/3/library/exceptions.html + "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" + ;; https://docs.python.org/3/library/stdtypes.html + "bool" "int" "float" "complex" "list" "tuple" "range" "str" + "bytes" "bytearray" "memoryview" "set" "frozenset" "dict" "type" "object")) + +(comment) @comment @spell + +(ERROR) @error diff --git a/runtime/queries/bitbake/injections.scm b/runtime/queries/bitbake/injections.scm new file mode 100644 index 0000000000000..819487bc5d18d --- /dev/null +++ b/runtime/queries/bitbake/injections.scm @@ -0,0 +1,14 @@ +(call + function: (attribute + object: (python_identifier) @_re) + arguments: (argument_list (python_string + (string_content) @injection.content) @_string) + (#eq? @_re "re") + (#lua-match? @_string "^r.*") + (#set! injection.language "regex")) + +((shell_content) @injection.content + (#set! injection.language "bash")) + +((comment) @injection.content + (#set! injection.language "comment")) diff --git a/runtime/queries/bitbake/locals.scm b/runtime/queries/bitbake/locals.scm new file mode 100644 index 0000000000000..baf835cc57c7b --- /dev/null +++ b/runtime/queries/bitbake/locals.scm @@ -0,0 +1,99 @@ +; References +[ + (python_identifier) + (identifier) +] @reference + +; Imports +(aliased_import + alias: (python_identifier) @definition.import) +(import_statement + name: (dotted_name ((python_identifier) @definition.import))) +(import_from_statement + name: (dotted_name ((python_identifier) @definition.import))) + +; Function with parameters, defines parameters +(parameters + (python_identifier) @definition.parameter) + +(default_parameter + (python_identifier) @definition.parameter) + +(typed_parameter + (python_identifier) @definition.parameter) + +(typed_default_parameter + (python_identifier) @definition.parameter) + +; *args parameter +(parameters + (list_splat_pattern + (python_identifier) @definition.parameter)) + +; **kwargs parameter +(parameters + (dictionary_splat_pattern + (python_identifier) @definition.parameter)) + +; Function defines function and scope +((python_function_definition + name: (python_identifier) @definition.function) @scope + (#set! definition.function.scope "parent")) + +(function_definition (identifier) @definition.function) + +(anonymous_python_function (identifier) @definition.function) + +;;; Loops +; not a scope! +(for_statement + left: (pattern_list + (python_identifier) @definition.var)) +(for_statement + left: (tuple_pattern + (python_identifier) @definition.var)) +(for_statement + left: (python_identifier) @definition.var) + +; not a scope! +;(while_statement) @scope + +; for in list comprehension +(for_in_clause + left: (python_identifier) @definition.var) +(for_in_clause + left: (tuple_pattern + (python_identifier) @definition.var)) +(for_in_clause + left: (pattern_list + (python_identifier) @definition.var)) + +(dictionary_comprehension) @scope +(list_comprehension) @scope +(set_comprehension) @scope + +;;; Assignments + +(assignment + left: (python_identifier) @definition.var) + +(assignment + left: (pattern_list + (python_identifier) @definition.var)) +(assignment + left: (tuple_pattern + (python_identifier) @definition.var)) + +(assignment + left: (attribute + (python_identifier) + (python_identifier) @definition.field)) + +(variable_assignment (identifier) operator: [ "=" "?=" "??=" ":=" ] @definition.var) + +; Walrus operator x := 1 +(named_expression + (python_identifier) @definition.var) + +(as_pattern + alias: (as_pattern_target) @definition.var)