86 lines
3.5 KiB
Lua
86 lines
3.5 KiB
Lua
-- Kotlin LSP = fwcd kotlin-language-server (installed via Mason).
|
|
--
|
|
-- NOTE: the JetBrains `kotlin-lsp` (intellij-server) was tried but it imports
|
|
-- Android Gradle modules with an EMPTY set of source sets, so it resolves
|
|
-- nothing for Android (hover/definition/references all return empty). fwcd
|
|
-- resolves the Gradle compile classpath itself and DOES navigate Android
|
|
-- projects, so we use it here. (kotlin-lsp remains fine for plain Kotlin/JVM.)
|
|
--
|
|
-- CPU/Memory notes for Android projects:
|
|
-- - Formatting disabled in LSP capabilities — ktfmt in-process spawns a SECOND
|
|
-- Kotlin compiler, doubling memory (OOMs even at 4GB). Formatting is handled
|
|
-- externally by null-ls running ktfmt as a separate process.
|
|
-- - Linting enabled — runs on the same compiler already loaded for completions,
|
|
-- so no extra memory cost. Provides error diagnostics (red squiggles).
|
|
-- - Semantic tokens disabled — extra compilation passes, not worth the CPU.
|
|
-- - 500ms debounce reduces compilation frequency during typing.
|
|
-- - Persistent tmpdir so the SQLite compilation cache survives across sessions.
|
|
local bin = vim.fn.expand("~/.local/share/nvim/mason/bin/kotlin-language-server")
|
|
|
|
if vim.fn.executable(bin) == 0 then
|
|
vim.notify("kotlin-language-server not found — run :MasonInstall kotlin-language-server",
|
|
vim.log.levels.WARN)
|
|
return
|
|
end
|
|
|
|
-- Build capabilities, then strip formatting to prevent ktfmt OOMs.
|
|
local capabilities = require("cmp_nvim_lsp").default_capabilities()
|
|
capabilities.textDocument.formatting = nil
|
|
capabilities.textDocument.rangeFormatting = nil
|
|
capabilities.textDocument.onTypeFormatting = nil
|
|
|
|
-- 1. Configuration
|
|
vim.lsp.config('kotlin_language_server', {
|
|
cmd = { bin },
|
|
filetypes = { "kotlin" },
|
|
|
|
-- Kotlin/Android projects are rooted at a Gradle build file or git repo.
|
|
-- vim.lsp.config expects callback form: function(bufnr, on_dir).
|
|
root_dir = function(bufnr, on_dir)
|
|
local fname = vim.api.nvim_buf_get_name(bufnr)
|
|
local root = vim.fs.root(fname, {
|
|
"settings.gradle.kts",
|
|
"settings.gradle",
|
|
"build.gradle.kts",
|
|
"build.gradle",
|
|
"pom.xml",
|
|
".git",
|
|
})
|
|
on_dir(root or vim.fs.dirname(fname))
|
|
end,
|
|
|
|
capabilities = capabilities,
|
|
|
|
-- Strip formatting from the server's advertised capabilities.
|
|
-- client-side capabilities only prevent the server from expecting format
|
|
-- requests; server-side capabilities are what vim.lsp.buf.format() actually
|
|
-- checks. Without this, format-on-save routes through the LSP's ktfmt →
|
|
-- second Kotlin compiler → OOM.
|
|
on_attach = function(client)
|
|
client.server_capabilities.documentFormattingProvider = false
|
|
client.server_capabilities.documentRangeFormattingProvider = false
|
|
end,
|
|
|
|
-- 6GB heap — Android classpath is large (163 deps + 320 source files).
|
|
-- Persistent tmpdir so the compilation cache survives across sessions.
|
|
-- Use Android Studio's JBR 21 — optimised GC/JIT for Kotlin workloads.
|
|
cmd_env = {
|
|
KOTLIN_LANGUAGE_SERVER_OPTS = "-Xmx6G -Xms512m -Djava.io.tmpdir=/home/prabhat/.cache/kotlin-ls-fwcd",
|
|
JAVA_HOME = "/opt/android-studio/jbr",
|
|
},
|
|
|
|
init_options = {
|
|
debounceTextChanges = 500,
|
|
},
|
|
|
|
settings = {
|
|
kotlin = {
|
|
linting = { enabled = true },
|
|
completion = { enabled = true },
|
|
semanticTokens = { enabled = false },
|
|
},
|
|
},
|
|
})
|
|
|
|
-- 2. Enable the server
|
|
vim.lsp.enable('kotlin_language_server')
|