Setup Neovim for D Language

Setting up Neovim for D lan­guage de­vel­op­ment with proper LSP sup­port.

The Problem

After in­stalling serve-d via Mason and set­ting up a D pro­ject with dub de­pen­den­cies (raylib-d, dyaml), au­to­com­plete for stan­dard li­brary mod­ules worked fine. However, typ­ing raylib. or dyaml. pro­duced no sug­ges­tions.

The LSP log showed warn­ings:

[warning] Could not resolve location of module 'raylib'
[warning] Could not resolve location of module 'dyaml'

Verifying Dub

First, con­firm dub it­self can re­solve the de­pen­den­cies:

$ dub describe --data=import-paths
-I/home/user/project/source/
-I/home/user/.dub/packages/dyaml/0.10.0/dyaml/source/
-I/home/user/.dub/packages/raylib-d/5.5.3/raylib-d/source/

If this works, the is­sue lies with serve-d, not your pro­ject con­fig­u­ra­tion.

Configuration Attempts

I tried ex­plicit LSP con­fig­u­ra­tion in lspconfig.lua:

serve_d = {
  settings = {
    d = {
      dubPath = "/usr/bin/dub",
      dmdPath = "/usr/sbin/dmd",
      stdlibPath = "/usr/include/dlang/dmd",
    }
  },
},

This had no ef­fect. Switching to init_options in­stead of settings also failed.

Root Cause

Mason in­stalled serve-d v0.7.6, built with LDC v2.106. My sys­tem ran DMD v2.112.0. This ver­sion gap caused in­com­pat­i­bil­i­ties in how serve-d’s bun­dled dub re­solved pro­ject de­pen­den­cies.

Solution

Install serve-d nightly and by­pass Mason:

# Download the nightly release
curl -L -o /tmp/serve-d-nightly.tar.xz \
  https://github.com/Pure-D/serve-d/releases/download/nightly/serve-d_linux-nightly-x86_64-20251231-3c1601.tar.xz

# Extract and install
tar -xf /tmp/serve-d-nightly.tar.xz -C /tmp/
mkdir -p ~/.local/bin
cp /tmp/serve-d ~/.local/bin/serve-d
chmod +x ~/.local/bin/serve-d

# Remove Mason's version
rm -rf ~/.local/share/nvim/mason/packages/serve-d
rm ~/.local/share/nvim/mason/bin/serve-d

Update lspconfig.lua to use the new bi­nary:

serve_d = {
  cmd = { "/home/user/.local/bin/serve-d" },
  init_options = {
    d = {
      enableFormatting = false,
    }
  },
},

Restart Neovim. Autocomplete for dub de­pen­den­cies now works.

Caution

Installing out­side Mason means up­dates are man­ual. Running :MasonUpdate won’t af­fect your cus­tom bi­nary.

Treesitter Highlighting for Aliased Types

Types like string, size_t, and ptrdiff_t ap­pear as plain iden­ti­fiers be­cause they are aliases de­fined in D’s run­time object mod­ule, not lan­guage prim­i­tives. Treesitter can­not dis­tin­guish them from user-de­fined names.

To fix this, cre­ate a cus­tom query file:

~/.config/nvim/after/queries/d/highlights.scm

; extends
((identifier) @type.builtin
  (#any-of? @type.builtin
    "string" "wstring" "dstring"
    "size_t" "ptrdiff_t" "noreturn"))

Restart Neovim. The aliased types now high­light as built-in types.