Setup Neovim for D Language
Setting up Neovim for D language development with proper LSP support.
The Problem
After installing serve-d via Mason and setting up a D project with dub dependencies (raylib-d, dyaml), autocomplete for standard library modules worked fine. However, typing raylib. or dyaml. produced no suggestions.
The LSP log showed warnings:
[warning] Could not resolve location of module 'raylib'
[warning] Could not resolve location of module 'dyaml'
Verifying Dub
First, confirm dub itself can resolve the dependencies:
$ 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 issue lies with serve-d, not your project configuration.
Configuration Attempts
I tried explicit LSP configuration in lspconfig.lua:
serve_d = {
settings = {
d = {
dubPath = "/usr/bin/dub",
dmdPath = "/usr/sbin/dmd",
stdlibPath = "/usr/include/dlang/dmd",
}
},
},
This had no effect. Switching to init_options instead of settings also failed.
Root Cause
Mason installed serve-d v0.7.6, built with LDC v2.106. My system ran DMD v2.112.0. This version gap caused incompatibilities in how serve-d’s bundled dub resolved project dependencies.
Solution
Install serve-d nightly and bypass 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 binary:
serve_d = {
cmd = { "/home/user/.local/bin/serve-d" },
init_options = {
d = {
enableFormatting = false,
}
},
},
Restart Neovim. Autocomplete for dub dependencies now works.
Installing outside Mason means updates are manual. Running :MasonUpdate won’t affect your custom binary.
Treesitter Highlighting for Aliased Types
Types like string, size_t, and ptrdiff_t appear as plain identifiers because they are aliases defined in D’s runtime object module, not language primitives. Treesitter cannot distinguish them from user-defined names.
To fix this, create a custom 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 highlight as built-in types.