summaryrefslogtreecommitdiffstats
path: root/lua/conf/plugins/mason-lspconfig.lua
diff options
context:
space:
mode:
Diffstat (limited to 'lua/conf/plugins/mason-lspconfig.lua')
-rw-r--r--lua/conf/plugins/mason-lspconfig.lua369
1 files changed, 369 insertions, 0 deletions
diff --git a/lua/conf/plugins/mason-lspconfig.lua b/lua/conf/plugins/mason-lspconfig.lua
new file mode 100644
index 0000000..edeaf93
--- /dev/null
+++ b/lua/conf/plugins/mason-lspconfig.lua
@@ -0,0 +1,369 @@
+local misc = require('core.misc')
+local map, auto, augroup = misc.map, misc.auto, misc.augroup
+
+return { 'williamboman/mason-lspconfig.nvim',
+ requires = {
+ 'williamboman/mason.nvim',
+ 'mfussenegger/nvim-jdtls',
+ 'neovim/nvim-lspconfig'
+ },
+ function()
+ local util = require('lspconfig.util')
+
+ -- configure lsp when attached
+ local function lsp_attach(client, bufnr)
+ -- helper function(s)
+ local function set_lsp_sign(name, text)
+ vim.fn.sign_define(name, { text = text, texthl = name })
+ end
+
+ set_lsp_sign("DiagnosticSignError", "x")
+ set_lsp_sign("DiagnosticSignWarn" , "!")
+ set_lsp_sign("DiagnosticSignInfo" , "i")
+ set_lsp_sign("DiagnosticSignHint" , "h")
+
+ local opts = { buffer = bufnr }
+ -- LSP actions
+ map('n', 'K', vim.lsp.buf.hover, opts)
+ map('n', 'gD', vim.lsp.buf.definition, opts)
+ -- map('n', 'gD', '<cmd>lua vim.lsp.buf.declaration()<cr>')
+ map('n', 'gI', vim.lsp.buf.implementation, opts)
+ map('n', 'gY', vim.lsp.buf.type_definition, opts)
+ map('n', 'gR', vim.lsp.buf.references, opts)
+ map('n', '<S-Tab>', vim.lsp.buf.signature_help, opts)
+ map('n', '<leader>lr', vim.lsp.buf.rename, opts)
+ map('n', '<F2>', vim.lsp.buf.rename, opts)
+ map('n', 'gA', vim.lsp.buf.code_action, {
+ buffer = bufnr,
+ desc = 'check code actions',
+ })
+ map('n', '<F4>', vim.lsp.buf.code_action, {
+ buffer = bufnr,
+ desc = 'check code actions'
+ })
+
+ -- Diagnostics
+ map('n', '[d', vim.diagnostic.goto_prev)
+ map('n', ']d', vim.diagnostic.goto_next)
+ end
+
+ -- setup lsp capabilities
+ local capabilities = vim.lsp.protocol.make_client_capabilities()
+ capabilities.textDocument.completion.completionItem = {
+ documentationFormat = { "markdown", "plaintext" },
+ snippetSupport = true,
+ preselectSupport = true,
+ insertReplaceSupport = true,
+ labelDetailsSupport = true,
+ deprecatedSupport = true,
+ commitCharactersSupport = true,
+ tagSupport = {
+ valueSet = { 1 }
+ },
+ resolveSupport = {
+ properties = {
+ "documentation",
+ "detail",
+ "additionalTextEdits"
+ }
+ }
+ }
+
+ -- setup language servers
+ require('mason-lspconfig').setup {
+ ensure_installed = {
+ "lua_ls",
+ "clangd",
+ "jdtls",
+ "tsserver",
+ "phpactor",
+ "html",
+ "cssls",
+ "bashls",
+ "zls"
+ -- "asm-lsp", -- seems to be broken
+ }
+ }
+ require('mason-lspconfig').setup_handlers {
+ function(server_name)
+ require('lspconfig')[server_name].setup {
+ on_attach = lsp_attach,
+ capabilities = capabilities
+ }
+ end,
+
+ -- setup luals
+ ["lua_ls"] = function(server_name)
+ local root_files = { '.luarc.json', '.luarc.jsonc', '.luacheckrc',
+ '.stylua.toml', 'stylua.toml', 'selene.toml', 'selene.yml',
+ 'README.md'
+ }
+
+ -- FIXME: for some reason luals randomly resets the indentation of code
+ -- when pressing o or O. Right now this is a minor annoyance I will deal
+ -- with in exchange for really good lua lsp support.
+ --
+ -- FIXME: luals also seems to start up twice and sends back twice the
+ -- completions (one configured with the below settings and one without)
+ require('lspconfig')[server_name].setup {
+ on_attach = lsp_attach,
+ settings = {
+ Lua = {
+ diagnostics = {
+ globals = { "vim", 'mp' }
+ },
+ runtime = {
+ version = 'LuaJIT'
+ },
+ format = {
+ enable = false
+ },
+ workspace = {
+ checkThirdParty = false,
+ library = {
+ vim.env.VIMRUNTIME
+ }
+ }
+ }
+ },
+
+ root_dir = function(fname)
+ local root = util.root_pattern(unpack(root_files))(fname)
+ if root and root ~= vim.env.HOME then
+ return root
+ end
+
+ root = util.root_pattern('lua/')(fname)
+ if root then
+ return root
+ end
+ return util.find_git_ancestor(fname)
+ end
+ }
+ end,
+
+ -- setup clangd
+ ["clangd"] = function(server_name)
+ require('lspconfig')[server_name].setup {
+ on_attach = function(client, bufnr)
+ lsp_attach(client, bufnr)
+
+ -- add some clangd specific mappings
+ local opts = { buffer = bufnr }
+ map("n", "<leader>o", "<cmd>ClangdSwitchSourceHeader<CR>", opts)
+ end,
+ capabilities = capabilities,
+
+ cmd = {
+ "clangd",
+ "--background-index",
+ "--clang-tidy",
+ "--header-insertion=iwyu",
+ "--completion-style=detailed",
+ "--function-arg-placeholders",
+ "--fallback-style=llvm"
+ },
+ init_options = {
+ usePlaceholders = true,
+ clangdFileStatus = true,
+ fallback_flags = {
+ "-xc" -- makes clangd think we're using c instead of c++
+ }
+ }
+ }
+ end,
+
+ -- setup jdtls
+ ["jdtls"] = function(server_name)
+ auto("Filetype", {
+ pattern = "java",
+ callback = function()
+ -- must be a java interpreter of version 17 or greater
+ local java = "java"
+
+ local buffer = {}
+ ---@type function
+ local startlsp
+
+ -- check if version of java in use is high enough
+ vim.fn.jobstart({ java, vim.fn.stdpath('config').."/extras/JavaVersion.java" }, {
+ stdin = nil,
+ on_stdout = function(_, data, _)
+ table.insert(buffer, table.concat(data))
+ end,
+ on_exit = function(_, exit_code, _)
+ local v = vim.version.parse(table.concat(buffer))
+
+ -- if there's an error, no version info, or the java version is
+ -- less than 17 stop the lsp from starting
+ if exit_code ~= 0 then
+ vim.notify(string.format(
+ "java version check failed: exit code %s", exit_code),
+ vim.log.levels.ERROR, { title = misc.appid })
+ return
+ elseif not v then
+ vim.notify("no java version info found", vim.log.levels.ERROR,
+ { title = misc.appid })
+ return
+ elseif v.major < 17 then
+ vim.notify(string.format(
+ "java version %s < 17.0.0 Cannot run jdtls, bailing out",
+ v[1].."."..v[2].."."..v[3]),
+ vim.log.levels.ERROR, { title = misc.appid })
+ return
+ end
+
+ startlsp()
+ end
+ })
+
+ function startlsp()
+ local ok, jdtls = pcall(require, "jdtls")
+ if not ok then
+ vim.notify("jdtls not found, can't start java lsp",
+ vim.log.levels.ERROR, {})
+ return
+ end
+
+ local config = {}
+
+ config.on_attach = function(client, bufnr)
+ lsp_attach(client, bufnr)
+
+ -- add some jdtls specific mappings
+ local opts = { buffer = bufnr }
+ map('n', 'cri', jdtls.organize_imports, opts)
+ map('n', 'crv', jdtls.extract_variable, opts)
+ map('n', 'crc', jdtls.extract_constant, opts)
+ map('x', 'crv', "<esc><cmd>lua require('jdtls').extract_variable(true)<cr>", opts)
+ map('x', 'crc', "<esc><cmd>lua require('jdtls').extract_constant(true)<cr>", opts)
+ map('x', 'crm', "<esc><Cmd>lua require('jdtls').extract_method(true)<cr>", opts)
+
+ -- refresh the codelens every time after writing the file
+ local jdtls_cmds = augroup("jdtls_cmds")
+
+ pcall(vim.lsp.codelens.refresh)
+ auto('BufWritePost', {
+ buffer = bufnr,
+ group = jdtls_cmds,
+ desc = 'refresh codelens',
+ callback = function()
+ pcall(vim.lsp.codelens.refresh)
+ end
+ })
+ end
+
+ -- setup path stuff
+ local path = {}
+ local jdtls_install = require('mason-registry').get_package('jdtls'):get_install_path()
+ path.data_dir = vim.fn.stdpath('cache')..'/nvim-jdtls'
+ path.java_agent = jdtls_install..'/lombok.jar'
+ path.launcher_jar = vim.fn.glob(jdtls_install..'/plugins/org.eclipse.equinox.launcher_*.jar')
+ path.platform_config = jdtls_install..'/config_linux'
+ path.bundles = {}
+
+ -- data dir
+ local data_dir = path.data_dir..'/'..vim.fn.fnamemodify(vim.fn.getcwd(), ':p:h:t')
+
+ -- enable basic capabilities
+ config.capabilities = capabilities
+
+ -- enable some extended client capabilities
+ local extendedClientCapabilities = jdtls.extendedClientCapabilities
+ extendedClientCapabilities.resolveAdditionalTextEditsSupport = true
+
+ -- command to start the lsp server
+ config.cmd = {
+ java, -- this has to be java17 or newer
+ '-Declipse.application=org.eclipse.jdt.ls.core.id1',
+ '-Dosgi.bundles.defaultStartLevel=4',
+ '-Declipse.product=org.eclipse.jdt.ls.core.product',
+ '-Dlog.protocol=true',
+ '-Dlog.level=ALL',
+ '-Xmx1G',
+ '--add-modules=ALL-SYSTEM',
+ '--add-opens', 'java.base/java.util=ALL-UNNAMED',
+ '--add-opens', 'java.base/java.lang=ALL-UNNAMED',
+ '-jar', path.launcher_jar,
+ '-configuration', path.platform_config,
+ '-data', data_dir
+ }
+
+ -- settings
+ config.settings = {
+ java = {
+ eclipse = { downloadSources = true },
+ gradle = { enabled = true },
+ maven = { downloadSources = true },
+ implementationsCodeLens = { enabled = true },
+ referencesCodeLens = { enabled = true },
+ references = { includeDecompiledSources = true },
+ symbols = { includeSourceMethodDeclarations = true },
+ inlayHints = {
+ parameterNames = {
+ enabled = "all"
+ }
+ },
+ completion = {
+ favoriteStaticMembers = {
+ "org.hamcrest.MatcherAssert.assertThat",
+ "org.hamcrest.Matchers.*",
+ "org.hamcrest.CoreMatchers.*",
+ "org.junit.jupiter.api.Assertions.*",
+ "java.util.Objects.requireNonNull",
+ "java.util.Objects.requireNonNullElse",
+ "org.mockito.Mockito.*"
+ },
+ filteredTypes = {
+ "com.sun.*",
+ "io.micrometer.shaded.*",
+ "java.awt.*",
+ "jdk.*",
+ "sun.*"
+ },
+ importOrder = {
+ "java",
+ "javax",
+ "com",
+ "org"
+ }
+ },
+ sources = {
+ organizeImports = {
+ starThreshold = 9999,
+ staticStarThreshold = 9999
+ }
+ },
+ codeGeneration = {
+ toString = {
+ template = '${object.className}{${member.name()}=${member.value}, ${otherMembers}}'
+ },
+ hashCodeEquals = { useJava7Objects = true },
+ useBlocks = true,
+ }
+ }
+ }
+ config.signatureHelp = { enabled = true }
+ config.flags = { allow_incremental_sync = true }
+
+ -- disable all messages from printing
+ config.handlers = {
+ ['language/status'] = function() end
+ }
+
+ config.init_options = {
+ extendedClientCapabilities = extendedClientCapabilities,
+ }
+
+ config.root_dir = vim.fs.root(0, { ".git", "mvnw", ".gradle",
+ "gradlew" })
+
+ -- start it up
+ jdtls.start_or_attach(config)
+ end
+ end
+ })
+ end
+ }
+ end
+}