From 6e6352f671fca4bb31e7e2394c592e623120292e Mon Sep 17 00:00:00 2001 From: Mathias Fussenegger Date: Sun, 9 Jul 2023 10:12:41 +0200 Subject: [PATCH] Add test generation functionality (optional with vscode-java-test) --- README.md | 2 ++ doc/jdtls.txt | 7 ++++ lemmy.sh | 2 +- lua/jdtls.lua | 26 +++++++++++++- lua/jdtls/tests.lua | 85 +++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 120 insertions(+), 2 deletions(-) create mode 100644 lua/jdtls/tests.lua diff --git a/README.md b/README.md index 1491c19..eeb2d0b 100644 --- a/README.md +++ b/README.md @@ -37,6 +37,8 @@ alternative: - [x] `jol` command to show memory usage of current file (`jol_path` must be set) - [x] `jshell` command to open up `jshell` with `classpath` from project set - [x] Debugger support via [nvim-dap][5] +- [x] Optional vscode-java-test extensions + - [x] Generate tests via `require("jdtls.tests").generate()` Take a look at [a demo](https://github.com/mfussenegger/nvim-jdtls/issues/3) to see some of the functionality in action. diff --git a/doc/jdtls.txt b/doc/jdtls.txt index 6b0b5db..47ab933 100644 --- a/doc/jdtls.txt +++ b/doc/jdtls.txt @@ -250,4 +250,11 @@ JdtTestOpts *JdtTestOpts* {lnum?} (number) 1-indexed line number. Used to find nearest test. Defaults to cursor position of the current window. +============================================================================== +Functions which require vscode-java-test *jdtls.tests* + +M.generate() *jdtls.tests.generate* + Generate tests for the current class + + vim:tw=78:ts=8:noet:ft=help:norl: diff --git a/lemmy.sh b/lemmy.sh index 7ae0a49..b5f81ec 100755 --- a/lemmy.sh +++ b/lemmy.sh @@ -1,4 +1,4 @@ #!/usr/bin/env bash set -Eeuo pipefail -lemmy-help -f lua/jdtls.lua lua/jdtls/dap.lua >doc/jdtls.txt +lemmy-help -f lua/jdtls.lua lua/jdtls/dap.lua lua/jdtls/tests.lua >doc/jdtls.txt diff --git a/lua/jdtls.lua b/lua/jdtls.lua index b5de96c..404770d 100644 --- a/lua/jdtls.lua +++ b/lua/jdtls.lua @@ -761,7 +761,9 @@ local function java_override_methods(_, context) print("Error getting workspace edits: " .. err2.message) return end - vim.lsp.util.apply_workspace_edit(result2, offset_encoding) + if result2 then + vim.lsp.util.apply_workspace_edit(result2, offset_encoding) + end end)() end @@ -777,6 +779,28 @@ M.commands = { ['java.action.generateConstructorsPrompt'] = java_generate_constructors_prompt; ['java.action.generateDelegateMethodsPrompt'] = java_generate_delegate_methods_prompt; ['java.action.overrideMethodsPrompt'] = java_override_methods; + ['_java.test.askClientForChoice'] = function(args) + local prompt = args[1] + local choices = args[2] + local pick_many = args[3] + return require("jdtls.tests")._ask_client_for_choice(prompt, choices, pick_many) + end, + ['_java.test.advancedAskClientForChoice'] = function(args) + local prompt = args[1] + local choices = args[2] + -- local advanced_action = args[3] + local pick_many = args[4] + return require("jdtls.tests")._ask_client_for_choice(prompt, choices, pick_many) + end, + ['_java.test.askClientForInput'] = function(args) + local prompt = args[1] + local default = args[2] + local result = vim.fn.input({ + prompt = prompt .. ': ', + default = default + }) + return result and result or vim.NIL + end, } if vim.lsp.commands then diff --git a/lua/jdtls/tests.lua b/lua/jdtls/tests.lua new file mode 100644 index 0000000..bc706b6 --- /dev/null +++ b/lua/jdtls/tests.lua @@ -0,0 +1,85 @@ +---@mod jdtls.tests Functions which require vscode-java-test + + +local api = vim.api +local M = {} + +--- Generate tests for the current class +function M.generate() + local bufnr = api.nvim_get_current_buf() + local win = api.nvim_get_current_win() + local cursor = api.nvim_win_get_cursor(win) -- (1, 0) indexed + local lnum = cursor[1] + local line = api.nvim_buf_get_lines(bufnr, lnum -1, lnum, true)[1] + local byteoffset = vim.fn.line2byte(lnum) + vim.str_byteindex(line, cursor[2], true) + local command = { + title = "Generate tests", + command = "vscode.java.test.generateTests", + arguments = {vim.uri_from_bufnr(bufnr), byteoffset}, + } + ---@param result? lsp.WorkspaceEdit + local on_result = function(err, result) + assert(not err, err) + if not result then + return + end + vim.lsp.util.apply_workspace_edit(result, "utf-16") + + if not api.nvim_win_is_valid(win) or api.nvim_win_get_buf(win) ~= bufnr then + return + end + + -- Set buffer of window to first created/changed file + local uri = next(result.changes or {}) + if uri then + local changed_buf = vim.uri_to_bufnr(uri) + api.nvim_win_set_buf(win, changed_buf) + else + -- documentChanges?: ( TextDocumentEdit[] | (TextDocumentEdit | CreateFile | RenameFile | DeleteFile)[]); + local changes = result.documentChanges or {} + local _, change = next(changes) + ---@diagnostic disable-next-line: undefined-field + local document = changes.textDocument or change.textDocument + if change.uri and change.kind ~= "delete" then + local changed_buf = vim.uri_to_bufnr(change.uri) + api.nvim_win_set_buf(win, changed_buf) + elseif document then + local changed_buf = vim.uri_to_bufnr(document.uri) + api.nvim_win_set_buf(win, changed_buf) + end + end + end + require("jdtls.util").execute_command(command, on_result, bufnr) +end + + +---@private +function M._ask_client_for_choice(prompt, choices, pick_many) + local label = function(x) + local description = x.description and (' ' .. x.description) or '' + return x.label .. description + end + local ui = require("jdtls.ui") + if pick_many then + local opts = { + is_selected = function(x) return x.picked end + } + local result = ui.pick_many(choices, prompt, label, opts) + return vim.tbl_map(function(x) return x.value or x.label end, result) + else + local co, is_main = coroutine.running() + local choice + if co and not is_main then + ui.pick_one_async(choices, prompt, label, function(result) + coroutine.resume(co, result) + end) + choice = coroutine.yield() + else + choice = ui.pick_one(choices, prompt, label) + end + return choice and (choice.value or choice.label) or vim.NIL + end +end + + +return M