From 36f97b6aadec1a5c0cc61859d4f456f005983be0 Mon Sep 17 00:00:00 2001
From: Garrett D'Amore <garrett@damore.org>
Date: Thu, 20 Oct 2022 14:54:17 -0700
Subject: [PATCH] Add support for D (#4372)

Co-authored-by: Michael Davis <mcarsondavis@gmail.com>
---
 book/src/generated/lang-support.md |   1 +
 languages.toml                     |  15 ++
 runtime/queries/d/highlights.scm   | 231 +++++++++++++++++++++++++++++
 runtime/queries/d/indents.scm      |  17 +++
 runtime/queries/d/injections.scm   |   2 +
 runtime/queries/d/textobjects.scm  |   9 ++
 6 files changed, 275 insertions(+)
 create mode 100644 runtime/queries/d/highlights.scm
 create mode 100644 runtime/queries/d/indents.scm
 create mode 100644 runtime/queries/d/injections.scm
 create mode 100644 runtime/queries/d/textobjects.scm

diff --git a/book/src/generated/lang-support.md b/book/src/generated/lang-support.md
index 3fe9ef70..c6edc66d 100644
--- a/book/src/generated/lang-support.md
+++ b/book/src/generated/lang-support.md
@@ -15,6 +15,7 @@
 | cpp | ✓ | ✓ | ✓ | `clangd` |
 | css | ✓ |  |  | `vscode-css-language-server` |
 | cue | ✓ |  |  | `cuelsp` |
+| d | ✓ | ✓ | ✓ | `serve-d` |
 | dart | ✓ |  | ✓ | `dart` |
 | devicetree | ✓ |  |  |  |
 | diff | ✓ |  |  |  |
diff --git a/languages.toml b/languages.toml
index 51ffaef1..5ad5c6e6 100644
--- a/languages.toml
+++ b/languages.toml
@@ -1835,3 +1835,18 @@ roots = []
 [[grammar]]
 name = "wast"
 source = { git = "https://github.com/wasm-lsp/tree-sitter-wasm", rev = "2ca28a9f9d709847bf7a3de0942a84e912f59088", subpath = "wast" }
+
+[[language]]
+name = "d"
+scope = "source.d"
+file-types = [ "d", "dd" ]
+roots = []
+comment-token = "//"
+injection-regex = "d"
+indent = { tab-width = 4, unit = "    "}
+language-server = { command = "serve-d" }
+formatter = { command = "dfmt" }
+
+[[grammar]]
+name = "d"
+source = { git = "https://github.com/gdamore/tree-sitter-d", rev="601c4a1e8310fb2f3c43fa8a923d0d27497f3c04" }
diff --git a/runtime/queries/d/highlights.scm b/runtime/queries/d/highlights.scm
new file mode 100644
index 00000000..b5db8431
--- /dev/null
+++ b/runtime/queries/d/highlights.scm
@@ -0,0 +1,231 @@
+; highlights.scm
+;
+; Highlighting queries for D code for use by Tree-Sitter.
+;
+; Copyright 2022 Garrett D'Amore
+;
+; Distributed under the MIT License.
+; (See accompanying file LICENSE.txt or https://opensource.org/licenses/MIT)
+; SPDX-License-Identifier: MIT
+
+; these are listed first, because they override keyword queries
+(identity_expression (in) @operator)
+(identity_expression (is) @operator)
+
+(storage_class) @keyword.storage
+
+(function_declaration (identifier) @function)
+
+(call_expression (identifier) @function)
+(call_expression (type (identifier) @function))
+
+(module_fqn) @namespace
+
+[
+    (abstract)
+    (alias)
+    (align)
+    (asm)
+    (assert)
+    (auto)
+    (cast)
+    (const)
+    (debug)
+    (delete)
+    (deprecated)
+    (export)
+    (extern)
+    (final)
+    (immutable)
+    (in)
+    (inout)
+    (invariant)
+    (is)
+    (lazy)
+    ; "macro" - obsolete
+    (mixin)
+    (module)
+    (new)
+    (nothrow)
+    (out)
+    (override)
+    (package)
+    (pragma)
+    (private)
+    (protected)
+    (public)
+    (pure)
+    (ref)
+    (scope)
+    (shared)
+    (static)
+    (super)
+    (synchronized)
+    (template)
+    (this)
+    (throw)
+    (typeid)
+    (typeof)
+    (unittest)
+    (version)
+    (with)
+    (gshared)
+    (traits)
+    (vector)
+    (parameters_)
+] @keyword
+
+[
+    (class)
+    (struct)
+    (interface)
+    (union)
+    (enum)
+    (function)
+    (delegate)
+] @keyword.storage.type
+
+[
+    (break)
+    (case)
+    (catch)
+    (continue)
+    (do)
+    (default)
+    (finally)
+    (else)
+    (goto)
+    (if)
+    (switch)
+    (try)
+] @keyword.control
+
+(return) @keyword.control.return
+
+(import) @keyword.control.import
+
+[
+    (for)
+    (foreach)
+    (foreach_reverse)
+    (while)
+] @keyword.control.repeat
+
+[
+    (not_in)
+    (not_is)
+    "/="
+    "/"
+    ".."
+    "..."
+    "&"
+    "&="
+    "&&"
+    "|"
+    "|="
+    "||"
+    "-"
+    "-="
+    "--"
+    "+"
+    "+="
+    "++"
+    "<"
+    "<="
+    "<<"
+    "<<="
+    ">"
+    ">="
+    ">>="
+    ">>>="
+    ">>"
+    ">>>"
+    "!"
+    "!="
+    "?"
+    "$"
+    "="
+    "=="
+    "*"
+    "*="
+    "%"
+    "%="
+    "^"
+    "^="
+    "^^"
+    "^^="
+    "~"
+    "~="
+    "@"
+    "=>"
+] @operator
+
+[
+    "("
+    ")"
+    "["
+    "]"
+] @punctuation.bracket
+
+[
+    ";"
+    "."
+    ":"
+    ","
+] @punctuation.delimiter
+
+[
+    (true)
+    (false)
+] @constant.builtin.boolean
+
+(null) @constant.builtin
+
+(special_keyword) @constant.builtin
+
+(directive) @keyword.directive
+(shebang) @keyword.directive
+
+(comment) @comment
+
+[
+    (void)
+    (bool)
+    (byte)
+    (ubyte)
+    (char)
+    (short)
+    (ushort)
+    (wchar)
+    (dchar)
+    (int)
+    (uint)
+    (long)
+    (ulong)
+    (real)
+    (double)
+] @type.builtin
+
+[
+    (cent)
+    (ucent)
+    (ireal)
+    (idouble)
+    (ifloat)
+    (creal)
+    (double)
+    (cfloat)
+] @warning ; these types are deprecated
+
+(label (identifier) @label)
+(goto_statement (goto) @keyword (identifier) @label)
+
+(string_literal) @string
+(int_literal) @constant.numeric.integer
+(float_literal) @constant.numeric.float
+(char_literal) @constant.character
+(identifier) @variable
+(at_attribute) @attribute
+
+; everything after __EOF_ is plain text
+(end_file) @ui.text
diff --git a/runtime/queries/d/indents.scm b/runtime/queries/d/indents.scm
new file mode 100644
index 00000000..73ff0b82
--- /dev/null
+++ b/runtime/queries/d/indents.scm
@@ -0,0 +1,17 @@
+[
+  (parameters)
+  (template_parameters)
+  (expression_statement)
+  (aggregate_body)
+  (function_body)
+  (scope_statement)
+  (block_statement)
+  (case_statement)
+] @indent
+
+[
+  (case)
+  (default)
+  "}"
+  "]"
+] @outdent
diff --git a/runtime/queries/d/injections.scm b/runtime/queries/d/injections.scm
new file mode 100644
index 00000000..321c90ad
--- /dev/null
+++ b/runtime/queries/d/injections.scm
@@ -0,0 +1,2 @@
+((comment) @injection.content
+ (#set! injection.language "comment"))
diff --git a/runtime/queries/d/textobjects.scm b/runtime/queries/d/textobjects.scm
new file mode 100644
index 00000000..9ca07160
--- /dev/null
+++ b/runtime/queries/d/textobjects.scm
@@ -0,0 +1,9 @@
+(function_declaration (function_body) @function.inside) @function.around
+(comment) @comment.inside
+(comment)+ @comment.around
+(class_declaration (aggregate_body) @class.inside) @class.around
+(interface_declaration (aggregate_body) @class.inside) @class.around
+(struct_declaration (aggregate_body) @class.inside) @class.around
+(unittest_declaration (block_statement) @test.insid) @test.around
+(parameter) @parameter.inside
+(template_parameter) @parameter.inside
\ No newline at end of file