diff --git a/.config/nvim/ftplugin/java.lua b/.config/nvim/ftplugin/java.lua index c388a10..32b21ed 100644 --- a/.config/nvim/ftplugin/java.lua +++ b/.config/nvim/ftplugin/java.lua @@ -1,6 +1,8 @@ local caps = require("cmp_nvim_lsp").default_capabilities(vim.lsp.protocol.make_client_capabilities()) local mztenv = require "mzte_nv" +local bundle_info = mztenv.jdtls.getBundleInfo() + require("jdtls").start_or_attach { cmd = { "jdtls", @@ -12,13 +14,23 @@ require("jdtls").start_or_attach { capabilities = caps, - root_dir = require("jdtls.setup").find_root { ".git", "mvnw", "gradlew", "build.gradle" }, + root_dir = require("jdtls.setup").find_root { + ".git", + "mvnw", + "gradlew", + "build.gradle", + }, settings = { java = { configuration = { runtimes = mztenv.jdtls.findRuntimes(), }, + contentProvider = bundle_info.content_provider, }, }, + + init_options = { + bundles = bundle_info.bundles, + }, } diff --git a/mzte-nv/src/main.zig b/mzte-nv/src/main.zig index 04ecd83..3811faf 100644 --- a/mzte-nv/src/main.zig +++ b/mzte-nv/src/main.zig @@ -3,7 +3,7 @@ const ffi = @import("ffi.zig"); const ser = @import("ser.zig"); const c = ffi.c; -pub const version = "0.1.0"; +pub const version = "0.2.0"; const modules = struct { const jdtls = @import("modules/jdtls.zig"); diff --git a/mzte-nv/src/modules/jdtls.zig b/mzte-nv/src/modules/jdtls.zig index 3a190ad..892f821 100644 --- a/mzte-nv/src/modules/jdtls.zig +++ b/mzte-nv/src/modules/jdtls.zig @@ -8,6 +8,7 @@ const c = ffi.c; pub fn luaPush(l: *c.lua_State) void { ser.luaPushAny(l, .{ .findRuntimes = ffi.luaFunc(lFindRuntimes), + .getBundleInfo = ffi.luaFunc(lGetBundleInfo), }); } @@ -66,3 +67,70 @@ fn lFindRuntimes(l: *c.lua_State) !c_int { return 1; } + +/// Returns a list of JDTLS bundles (plugins basically) and the preferred content provider +/// +/// https://github.com/dgileadi/vscode-java-decompiler/tree/master/server +// TODO: add command to download these maybe? +fn lGetBundleInfo(l: *c.lua_State) !c_int { + const home = std.os.getenv("HOME") orelse return error.HomeNotSet; + + const bundle_path = try std.fs.path.join( + std.heap.c_allocator, + // I kinda made this path up, but I think it makes sense. + &.{ home, ".eclipse", "jdtls", "bundles" }, + ); + defer std.heap.c_allocator.free(bundle_path); + + var dir = std.fs.cwd().openIterableDir(bundle_path, .{}) catch |e| { + if (e == error.FileNotFound) { + // Just return an empty table if the bundles dir doesn't exist + ser.luaPushAny(l, .{ + .content_provider = .{}, + .bundles = .{}, + }); + return 1; + } + + return e; + }; + defer dir.close(); + + // return value + c.lua_newtable(l); + + // bundles + c.lua_newtable(l); + + var has_fernflower = false; + var iter = dir.iterate(); + var idx: c_int = 1; + while (try iter.next()) |f| { + if (f.kind != .File or !std.mem.endsWith(u8, f.name, ".jar")) + continue; + + if (!has_fernflower and std.mem.containsAtLeast(u8, f.name, 1, "fernflower")) + has_fernflower = true; + + const path = try std.fs.path.joinZ(std.heap.c_allocator, &.{ bundle_path, f.name }); + defer std.heap.c_allocator.free(path); + + c.lua_pushstring(l, path.ptr); + c.lua_rawseti(l, -2, idx); + idx += 1; + } + + c.lua_setfield(l, -2, "bundles"); + + // content_provider + c.lua_newtable(l); + + if (has_fernflower) { + c.lua_pushstring(l, "fernflower"); + c.lua_setfield(l, -2, "preferred"); + } + + c.lua_setfield(l, -2, "content_provider"); + + return 1; +}