From cc584e30eaa8b89084fea5822b44ab03f7d6f7b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomek=20Wa=C5=82kuski?= Date: Mon, 31 Jul 2023 16:28:28 +0200 Subject: [PATCH 1/4] Initial Ada language support Tree-Sitter grammar and queries from: https://github.com/briot/tree-sitter-ada Language server from: https://github.com/AdaCore/ada_language_server Ada build tool: https://alire.ada.dev --- languages.toml | 14 +++ runtime/queries/ada/folds.scm | 15 +++ runtime/queries/ada/highlights.scm | 180 ++++++++++++++++++++++++++++ runtime/queries/ada/locals.scm | 33 +++++ runtime/queries/ada/textobjects.scm | 23 ++++ 5 files changed, 265 insertions(+) create mode 100644 runtime/queries/ada/folds.scm create mode 100644 runtime/queries/ada/highlights.scm create mode 100644 runtime/queries/ada/locals.scm create mode 100644 runtime/queries/ada/textobjects.scm diff --git a/languages.toml b/languages.toml index b6278730ea72..93cae13d7245 100644 --- a/languages.toml +++ b/languages.toml @@ -2091,6 +2091,20 @@ language-servers = [ "jsonnet-language-server" ] name = "jsonnet" source = { git = "https://github.com/sourcegraph/tree-sitter-jsonnet", rev = "0475a5017ad7dc84845d1d33187f2321abcb261d" } +[[language]] +name = "ada" +scope = "source.ada" +injection-regex = "ada" +file-types = ["adb", "ads"] +roots = ["alire.toml"] +comment-token = "--" +indent = { tab-width = 3, unit = " " } +language-server = { command = "ada_language_server" } + +[[grammar]] +name = "ada" +source = { git = "https://github.com/briot/tree-sitter-ada", rev = "ba7951a8f3fb08f9ea923625153e7670c89f30b4" } + [[language]] name = "astro" scope = "source.astro" diff --git a/runtime/queries/ada/folds.scm b/runtime/queries/ada/folds.scm new file mode 100644 index 000000000000..2839316199d7 --- /dev/null +++ b/runtime/queries/ada/folds.scm @@ -0,0 +1,15 @@ +;; Support for folding in Ada +;; za toggles folding a package, subprogram, if statement or loop + +[ + (package_declaration) + (generic_package_declaration) + (package_body) + (subprogram_declaration) + (subprogram_body) + (block_statement) + (if_statement) + (loop_statement) + (gnatprep_declarative_if_statement) + (gnatprep_if_statement) +] @fold diff --git a/runtime/queries/ada/highlights.scm b/runtime/queries/ada/highlights.scm new file mode 100644 index 000000000000..88420379145e --- /dev/null +++ b/runtime/queries/ada/highlights.scm @@ -0,0 +1,180 @@ +;; highlight queries. +;; See the syntax at https://tree-sitter.github.io/tree-sitter/using-parsers#pattern-matching-with-queries +;; See also https://github.com/nvim-treesitter/nvim-treesitter/blob/master/CONTRIBUTING.md#parser-configurations +;; for a list of recommended @ tags, though not all of them have matching +;; highlights in neovim. + +[ + "abort" + "abs" + "abstract" + "accept" + "access" + "all" + "array" + "at" + "begin" + "declare" + "delay" + "delta" + "digits" + "do" + "end" + "entry" + "exit" + "generic" + "interface" + "is" + "limited" + "null" + "of" + "others" + "out" + "pragma" + "private" + "range" + "synchronized" + "tagged" + "task" + "terminate" + "until" + "when" +] @keyword +[ + "aliased" + "constant" + "renames" +] @storageclass +[ + "mod" + "new" + "protected" + "record" + "subtype" + "type" +] @keyword.type +[ + "with" + "use" +] @include +[ + "body" + "function" + "overriding" + "procedure" + "package" + "separate" +] @keyword.function +[ + "and" + "in" + "not" + "or" + "xor" +] @keyword.operator +[ + "while" + "loop" + "for" + "parallel" + "reverse" + "some" +] @repeat +[ + "return" +] @keyword.return +[ + "case" + "if" + "else" + "then" + "elsif" + "select" +] @conditional +[ + "exception" + "raise" +] @exception +(comment) @comment +(comment) @spell ;; spell-check comments +(string_literal) @string +(string_literal) @spell ;; spell-check strings +(character_literal) @string +(numeric_literal) @number + +;; Highlight the name of subprograms +(procedure_specification name: (_) @function) +(function_specification name: (_) @function) +(package_declaration name: (_) @function) +(package_body name: (_) @function) +(generic_instantiation name: (_) @function) +(entry_declaration . (identifier) @function) + +;; Some keywords should take different categories depending on the context +(use_clause "use" @include "type" @include) +(with_clause "private" @include) +(with_clause "limited" @include) +(use_clause (_) @namespace) +(with_clause (_) @namespace) + +(loop_statement "end" @keyword.repeat) +(if_statement "end" @conditional) +(loop_parameter_specification "in" @keyword.repeat) +(loop_parameter_specification "in" @keyword.repeat) +(iterator_specification ["in" "of"] @keyword.repeat) +(range_attribute_designator "range" @keyword.repeat) + +(raise_statement "with" @exception) + +(gnatprep_declarative_if_statement) @preproc +(gnatprep_if_statement) @preproc +(gnatprep_identifier) @preproc + +(subprogram_declaration "is" @keyword.function "abstract" @keyword.function) +(aspect_specification "with" @keyword.function) + +(full_type_declaration "is" @keyword.type) +(subtype_declaration "is" @keyword.type) +(record_definition "end" @keyword.type) +(full_type_declaration (_ "access" @keyword.type)) +(array_type_definition "array" @keyword.type "of" @keyword.type) +(access_to_object_definition "access" @keyword.type) +(access_to_object_definition "access" @keyword.type + [ + (general_access_modifier "constant" @keyword.type) + (general_access_modifier "all" @keyword.type) + ] +) +(range_constraint "range" @keyword.type) +(signed_integer_type_definition "range" @keyword.type) +(index_subtype_definition "range" @keyword.type) +(record_type_definition "abstract" @keyword.type) +(record_type_definition "tagged" @keyword.type) +(record_type_definition "limited" @keyword.type) +(record_type_definition (record_definition "null" @keyword.type)) +(private_type_declaration "is" @keyword.type "private" @keyword.type) +(private_type_declaration "tagged" @keyword.type) +(private_type_declaration "limited" @keyword.type) +(task_type_declaration "task" @keyword.type "is" @keyword.type) + +;; Gray the body of expression functions +(expression_function_declaration + (function_specification) + "is" + (_) @attribute +) +(subprogram_declaration (aspect_specification) @attribute) + +;; Highlight full subprogram specifications +;(subprogram_body +; [ +; (procedure_specification) +; (function_specification) +; ] @function.spec +;) + +;; Highlight errors in red. This is not very useful in practice, as text will +;; be highlighted as user types, and the error could be elsewhere in the code. +;; This also requires defining :hi @error guifg=Red for instance. +(ERROR) @error + diff --git a/runtime/queries/ada/locals.scm b/runtime/queries/ada/locals.scm new file mode 100644 index 000000000000..eda50c6c03a6 --- /dev/null +++ b/runtime/queries/ada/locals.scm @@ -0,0 +1,33 @@ +;; Better highlighting by referencing to the definition, for variable +;; references. However, this is not yet supported by neovim +;; See https://tree-sitter.github.io/tree-sitter/syntax-highlighting#local-variables + +(compilation) @scope +(package_declaration) @scope +(package_body) @scope +(subprogram_declaration) @scope +(subprogram_body) @scope +(block_statement) @scope + +(with_clause (_) @definition.import) +(procedure_specification name: (_) @definition.function) +(function_specification name: (_) @definition.function) +(package_declaration name: (_) @definition.var) +(package_body name: (_) @definition.var) +(generic_instantiation . name: (_) @definition.var) +(component_declaration . (identifier) @definition.var) +(exception_declaration . (identifier) @definition.var) +(formal_object_declaration . (identifier) @definition.var) +(object_declaration . (identifier) @definition.var) +(parameter_specification . (identifier) @definition.var) +(full_type_declaration . (identifier) @definition.type) +(private_type_declaration . (identifier) @definition.type) +(private_extension_declaration . (identifier) @definition.type) +(incomplete_type_declaration . (identifier) @definition.type) +(protected_type_declaration . (identifier) @definition.type) +(formal_complete_type_declaration . (identifier) @definition.type) +(formal_incomplete_type_declaration . (identifier) @definition.type) +(task_type_declaration . (identifier) @definition.type) +(subtype_declaration . (identifier) @definition.type) + +(identifier) @reference diff --git a/runtime/queries/ada/textobjects.scm b/runtime/queries/ada/textobjects.scm new file mode 100644 index 000000000000..5d81701ac168 --- /dev/null +++ b/runtime/queries/ada/textobjects.scm @@ -0,0 +1,23 @@ +;; Support for high-level text objects selections. +;; For instance: +;; vaf (v)isually select (a) (f)unction or subprogram +;; vif (v)isually select (i)nside a (f)unction or subprogram +;; vai (v)isually select (a) (i)f statement (or loop) +;; vii (v)isually select (i)nside an (i)f statement (or loop) +;; +;; https://github.com/nvim-treesitter/nvim-treesitter-textobjects/blob/master/README.md + +(subprogram_body) @function.outer +(subprogram_body (non_empty_declarative_part) @function.inner) +(subprogram_body (handled_sequence_of_statements) @function.inner) +(function_specification) @function.outer +(procedure_specification) @function.outer +(package_declaration) @function.outer +(generic_package_declaration) @function.outer +(package_body) @function.outer +(if_statement) @block.outer +(if_statement statements: (_) @block.inner) +(if_statement else_statements: (_) @block.inner) +(elsif_statement_item statements: (_) @block.inner) +(loop_statement) @block.outer +(loop_statement statements: (_) @block.inner) From 338c517da3c1ca7498918b83655f311b62f08a98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomek=20Wa=C5=82kuski?= Date: Tue, 1 Aug 2023 10:07:48 +0200 Subject: [PATCH 2/4] Specify the LS correctly --- languages.toml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/languages.toml b/languages.toml index 93cae13d7245..075cc04d9fe8 100644 --- a/languages.toml +++ b/languages.toml @@ -3,6 +3,7 @@ [language-server] +ada-language-server = { command = "ada_language_server" } awk-language-server = { command = "awk-language-server" } bash-language-server = { command = "bash-language-server", args = ["start"] } bass = { command = "bass", args = ["--lsp"] } @@ -2099,7 +2100,7 @@ file-types = ["adb", "ads"] roots = ["alire.toml"] comment-token = "--" indent = { tab-width = 3, unit = " " } -language-server = { command = "ada_language_server" } +language-servers = [ "ada-language-server" ] [[grammar]] name = "ada" From c993d39f52162a26513bab8b7c3c11bd04f229e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomek=20Wa=C5=82kuski?= Date: Tue, 1 Aug 2023 10:17:02 +0200 Subject: [PATCH 3/4] Update lang support doc --- book/src/generated/lang-support.md | 1 + 1 file changed, 1 insertion(+) diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md index 4b19c4b80a38..47c6dd8e4113 100644 --- a/book/src/generated/lang-support.md +++ b/book/src/generated/lang-support.md @@ -1,5 +1,6 @@ | Language | Syntax Highlighting | Treesitter Textobjects | Auto Indent | Default LSP | | --- | --- | --- | --- | --- | +| ada | ✓ | ✓ | | `ada_language_server` | | astro | ✓ | | | | | awk | ✓ | ✓ | | `awk-language-server` | | bash | ✓ | | ✓ | `bash-language-server` | From 44a1817ddbb58a84888de46a6525a4899c1307b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomek=20Wa=C5=82kuski?= Date: Tue, 1 Aug 2023 13:01:51 +0200 Subject: [PATCH 4/4] Remove the (ERROR) @error pattern Co-authored-by: Michael Davis --- runtime/queries/ada/highlights.scm | 4 ---- 1 file changed, 4 deletions(-) diff --git a/runtime/queries/ada/highlights.scm b/runtime/queries/ada/highlights.scm index 88420379145e..16d163b15481 100644 --- a/runtime/queries/ada/highlights.scm +++ b/runtime/queries/ada/highlights.scm @@ -173,8 +173,4 @@ ; ] @function.spec ;) -;; Highlight errors in red. This is not very useful in practice, as text will -;; be highlighted as user types, and the error could be elsewhere in the code. -;; This also requires defining :hi @error guifg=Red for instance. -(ERROR) @error