diff --git a/init.lua b/init.lua index 4dea6841..05f061ab 100644 --- a/init.lua +++ b/init.lua @@ -201,10 +201,6 @@ vim.keymap.set('n', '', 'echo "Use j to move!!"') -- Use CTRL+ to switch between windows -- -- See `:help wincmd` for a list of all window commands -vim.keymap.set('n', '', '', { desc = 'Move focus to the left window' }) -vim.keymap.set('n', '', '', { desc = 'Move focus to the right window' }) -vim.keymap.set('n', '', '', { desc = 'Move focus to the lower window' }) -vim.keymap.set('n', '', '', { desc = 'Move focus to the upper window' }) vim.keymap.set('n', 'h', '', { desc = 'Move focus to the left window' }) vim.keymap.set('n', 'l', '', { desc = 'Move focus to the right window' }) vim.keymap.set('n', 'j', '', { desc = 'Move focus to the lower window' }) diff --git a/lua/custom/plugins/jdtls.lua b/lua/custom/plugins/jdtls.lua new file mode 100644 index 00000000..bdba5778 --- /dev/null +++ b/lua/custom/plugins/jdtls.lua @@ -0,0 +1,180 @@ +return { + 'mfussenegger/nvim-jdtls', + ft = { 'java' }, + config = function() + vim.api.nvim_create_autocmd({ 'BufEnter', 'BufWinEnter' }, { + group = vim.api.nvim_create_augroup('JonaJDTLS', {}), + pattern = { '*.java' }, + callback = function() + -- Based on https://github.com/Nawy/nvim-config-examples/blob/main/lsp-java/ftplugin/java.lua + -- Java Language Server configuration. + -- Locations: + -- 'nvim/ftplugin/java.lua'. + -- 'nvim/lang-servers/intellij-java-google-style.xml' + + local jdtls_ok, _ = pcall(require, 'jdtls') + if not jdtls_ok then + vim.notify 'JDTLS not found, install with `:LspInstall jdtls`' + return + end + + -- See `:help vim.lsp.start_client` for an overview of the supported `config` options. + local jdtls_path = vim.fn.stdpath 'data' .. '/mason/packages/jdtls' + local path_to_lsp_server = jdtls_path .. '/config_linux' + local path_to_plugins = jdtls_path .. '/plugins/' + local path_to_jar = path_to_plugins .. 'org.eclipse.equinox.launcher_1.6.800.v20240304-1850.jar' + local lombok_path = jdtls_path .. '/lombok.jar' + + -- local root_markers = { ".git", "mvnw", "gradlew", "pom.xml", "build.gradle" } + local root_markers = { '.git', 'mvnw', 'pom.xml', 'gradlew' } + local root_dir = require('jdtls.setup').find_root(root_markers) + if root_dir == '' then + return + end + + local project_name = vim.fn.fnamemodify(vim.fn.getcwd(), ':p:h:t') + local workspace_dir = vim.fn.stdpath 'data' .. '/site/java/workspace-root/' .. project_name + os.execute('mkdir -p ' .. workspace_dir) + + -- Main Config + local config = { + + -- The command that starts the language server + -- See: https://github.com/eclipse/eclipse.jdt.ls#running-from-the-command-line + cmd = { + 'java', + '-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', + '-javaagent:' .. lombok_path, + '-Xms1g', + '--add-modules=ALL-SYSTEM', + '--add-opens', + 'java.base/java.util=ALL-UNNAMED', + '--add-opens', + 'java.base/java.lang=ALL-UNNAMED', + + '-jar', + path_to_jar, + '-configuration', + path_to_lsp_server, + '-data', + workspace_dir, + }, + + -- This is the default if not provided, you can remove it. Or adjust as needed. + -- One dedicated LSP server & client will be started per unique root_dir + root_dir = root_dir, + + -- Here you can configure eclipse.jdt.ls specific settings + -- See https://github.com/eclipse/eclipse.jdt.ls/wiki/Running-the-JAVA-LS-server-from-the-command-line#initialize-request + -- for a list of options + settings = { + java = { + home = '/usr/lib/jvm/jre-21-openjdk/', + eclipse = { + downloadSources = true, + }, + configuration = { + updateBuildConfiguration = 'interactive', + runtimes = { + { + name = 'JavaSE-22', + path = '/usr/lib/jvm/jre-22-openjdk/', + }, + { + name = 'JavaSE-21', + path = '/usr/lib/jvm/jre-21-openjdk/', + }, + { + name = 'JavaSE-17', + path = '/usr/lib/jvm/jre-17-openjdk/', + }, + }, + }, + maven = { + downloadSources = true, + }, + implementationsCodeLens = { + enabled = true, + }, + referencesCodeLens = { + enabled = true, + }, + references = { + includeDecompiledSources = true, + }, + format = { + enabled = true, + settings = { + url = vim.fn.stdpath 'config' .. '/lang-servers/eclipse-java-google-style.xml', + profile = 'GoogleStyle', + }, + }, + }, + signatureHelp = { enabled = true }, + 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.*', + }, + importOrder = { + 'java', + 'javax', + 'com', + 'org', + }, + }, + -- extendedClientCapabilities = extendedClientCapabilities, + sources = { + organizeImports = { + starThreshold = 9999, + staticStarThreshold = 9999, + }, + }, + codeGeneration = { + toString = { + template = '${object.className}{${member.name()}=${member.value}, ${otherMembers}}', + }, + useBlocks = true, + }, + }, + + flags = { + allow_incremental_sync = true, + }, + init_options = { + bundles = {}, + }, + } + + -- config['on_attach'] = function(client, bufnr) + -- require'keymaps'.map_java_keys(bufnr); + -- require "lsp_signature".on_attach({ + -- bind = true, -- This is mandatory, otherwise border config won't get registered. + -- floating_window_above_cur_line = false, + -- padding = '', + -- handler_opts = { + -- border = "rounded" + -- } + -- }, bufnr) + -- end + + -- vim.lsp.set_log_level 'trace' + + config['on_attach'] = require('jona.lsp').on_attach + + -- This starts a new client & server, + -- or attaches to an existing client & server depending on the `root_dir`. + require('jdtls').start_or_attach(config) + end, + }) + end, +} diff --git a/lua/custom/plugins/lsp.lua b/lua/custom/plugins/lsp.lua index 501f11af..9bf661e6 100644 --- a/lua/custom/plugins/lsp.lua +++ b/lua/custom/plugins/lsp.lua @@ -46,85 +46,7 @@ return { -- LSP Configuration & Plugins -- function will be executed to configure the current buffer vim.api.nvim_create_autocmd('LspAttach', { group = vim.api.nvim_create_augroup('kickstart-lsp-attach', { clear = true }), - callback = function(event) - -- NOTE: Remember that Lua is a real programming language, and as such it is possible - -- to define small helper and utility functions so you don't have to repeat yourself. - -- - -- In this case, we create a function that lets us more easily define mappings specific - -- for LSP related items. It sets the mode, buffer and description for us each time. - local map = function(keys, func, desc) - vim.keymap.set('n', keys, func, { buffer = event.buf, desc = 'LSP: ' .. desc }) - end - - -- Jump to the definition of the word under your cursor. - -- This is where a variable was first declared, or where a function is defined, etc. - -- To jump back, press . - map('gd', require('telescope.builtin').lsp_definitions, '[G]oto [D]efinition') - - -- Find references for the word under your cursor. - map('gr', require('telescope.builtin').lsp_references, '[G]oto [R]eferences') - - -- Jump to the implementation of the word under your cursor. - -- Useful when your language has ways of declaring types without an actual implementation. - map('gI', require('telescope.builtin').lsp_implementations, '[G]oto [I]mplementation') - - -- Jump to the type of the word under your cursor. - -- Useful when you're not sure what type a variable is and you want to see - -- the definition of its *type*, not where it was *defined*. - map('D', require('telescope.builtin').lsp_type_definitions, 'Type [D]efinition') - - -- Fuzzy find all the symbols in your current document. - -- Symbols are things like variables, functions, types, etc. - map('ds', require('telescope.builtin').lsp_document_symbols, '[D]ocument [S]ymbols') - - -- Fuzzy find all the symbols in your current workspace. - -- Similar to document symbols, except searches over your entire project. - map('ws', require('telescope.builtin').lsp_dynamic_workspace_symbols, '[W]orkspace [S]ymbols') - - -- Rename the variable under your cursor. - -- Most Language Servers support renaming across files, etc. - map('rn', vim.lsp.buf.rename, '[R]e[n]ame') - - -- Execute a code action, usually your cursor needs to be on top of an error - -- or a suggestion from your LSP for this to activate. - map('ca', vim.lsp.buf.code_action, '[C]ode [A]ction') - - -- Opens a popup that displays documentation about the word under your cursor - -- See `:help K` for why this keymap. - map('K', vim.lsp.buf.hover, 'Hover Documentation') - - -- WARN: This is not Goto Definition, this is Goto Declaration. - -- For example, in C this would take you to the header. - map('gD', vim.lsp.buf.declaration, '[G]oto [D]eclaration') - - -- The following two autocommands are used to highlight references of the - -- word under your cursor when your cursor rests there for a little while. - -- See `:help CursorHold` for information about when this is executed - -- - -- When you move your cursor, the highlights will be cleared (the second autocommand). - local client = vim.lsp.get_client_by_id(event.data.client_id) - if client and client.server_capabilities.documentHighlightProvider then - vim.api.nvim_create_autocmd({ 'CursorHold', 'CursorHoldI' }, { - buffer = event.buf, - callback = vim.lsp.buf.document_highlight, - }) - - vim.api.nvim_create_autocmd({ 'CursorMoved', 'CursorMovedI' }, { - buffer = event.buf, - callback = vim.lsp.buf.clear_references, - }) - end - - -- The following autocommand is used to enable inlay hints in your - -- code, if the language server you are using supports them - -- - -- This may be unwanted, since they displace some of your code - if client and client.server_capabilities.inlayHintProvider and vim.lsp.inlay_hint then - map('th', function() - vim.lsp.inlay_hint.enable(not vim.lsp.inlay_hint.is_enabled()) - end, '[T]oggle Inlay [H]ints') - end - end, + callback = require('jona.lsp').on_attach, }) -- LSP servers and clients are able to communicate to each other what features they support. @@ -197,7 +119,9 @@ return { -- LSP Configuration & Plugins -- by the server configuration above. Useful when disabling -- certain features of an LSP (for example, turning off formatting for tsserver) server.capabilities = vim.tbl_deep_extend('force', {}, capabilities, server.capabilities or {}) - require('lspconfig')[server_name].setup(server) + if server_name ~= 'jdtls' then + require('lspconfig')[server_name].setup(server) + end end, }, } diff --git a/lua/jona/lsp.lua b/lua/jona/lsp.lua new file mode 100644 index 00000000..d0959920 --- /dev/null +++ b/lua/jona/lsp.lua @@ -0,0 +1,87 @@ +local M = {} + +M.on_attach = function(event) + -- NOTE: Remember that Lua is a real programming language, and as such it is possible + -- to define small helper and utility functions so you don't have to repeat yourself. + -- + -- In this case, we create a function that lets us more easily define mappings specific + -- for LSP related items. It sets the mode, buffer and description for us each time. + local map = function(keys, func, desc) + vim.keymap.set('n', keys, func, { buffer = event.buf, desc = 'LSP: ' .. desc }) + end + + -- Jump to the definition of the word under your cursor. + -- This is where a variable was first declared, or where a function is defined, etc. + -- To jump back, press . + map('gd', vim.lsp.buf.definition, '[G]oto [D]efinition') + + -- Find references for the word under your cursor. + map('gr', vim.lsp.buf.references, '[G]oto [R]eferences') + + -- Jump to the implementation of the word under your cursor. + -- Useful when your language has ways of declaring types without an actual implementation. + map('gI', vim.lsp.buf.implementation, '[G]oto [I]mplementation') + + -- Jump to the type of the word under your cursor. + -- Useful when you're not sure what type a variable is and you want to see + -- the definition of its *type*, not where it was *defined*. + map('D', require('telescope.builtin').lsp_type_definitions, 'Type [D]efinition') + + -- Fuzzy find all the symbols in your current document. + -- Symbols are things like variables, functions, types, etc. + map('ds', require('telescope.builtin').lsp_document_symbols, '[D]ocument [S]ymbols') + + -- Fuzzy find all the symbols in your current workspace. + -- Similar to document symbols, except searches over your entire project. + map('ws', require('telescope.builtin').lsp_dynamic_workspace_symbols, '[W]orkspace [S]ymbols') + + -- Rename the variable under your cursor. + -- Most Language Servers support renaming across files, etc. + map('rr', vim.lsp.buf.rename, '[R]e[n]ame') + + -- Execute a code action, usually your cursor needs to be on top of an error + -- or a suggestion from your LSP for this to activate. + map('ca', vim.lsp.buf.code_action, '[C]ode [A]ction') + + -- Opens a popup that displays documentation about the word under your cursor + -- See `:help K` for why this keymap. + map('K', vim.lsp.buf.hover, 'Hover Documentation') + + -- WARN: This is not Goto Definition, this is Goto Declaration. + -- For example, in C this would take you to the header. + map('gD', vim.lsp.buf.declaration, '[G]oto [D]eclaration') + + -- The following two autocommands are used to highlight references of the + -- word under your cursor when your cursor rests there for a little while. + -- See `:help CursorHold` for information about when this is executed + -- + -- When you move your cursor, the highlights will be cleared (the second autocommand). + local client = vim.lsp.get_client_by_id(event.data.client_id) + if client and client.server_capabilities.documentHighlightProvider then + vim.api.nvim_create_autocmd({ 'CursorHold', 'CursorHoldI' }, { + buffer = event.buf, + callback = vim.lsp.buf.document_highlight, + }) + + vim.api.nvim_create_autocmd({ 'CursorMoved', 'CursorMovedI' }, { + buffer = event.buf, + callback = vim.lsp.buf.clear_references, + }) + end + + -- The following autocommand is used to enable inlay hints in your + -- code, if the language server you are using supports them + -- + -- This may be unwanted, since they displace some of your code + if client and client.server_capabilities.inlayHintProvider and vim.lsp.inlay_hint then + map('th', function() + vim.lsp.inlay_hint.enable(not vim.lsp.inlay_hint.is_enabled()) + end, '[T]oggle Inlay [H]ints') + end + + -- if client.server_capabilities.documentSymbolProvider then + -- require('nvim-navic').attach(client, event.buf) + -- end +end + +return M