mirror of
				https://github.com/NotAShelf/nvf.git
				synced 2025-11-03 20:22:21 +00:00 
			
		
		
		
	
		
			
				
	
	
		
			181 lines
		
	
	
	
		
			5.8 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
			
		
		
	
	
			181 lines
		
	
	
	
		
			5.8 KiB
		
	
	
	
		
			Nix
		
	
	
	
	
	
{
 | 
						|
  config,
 | 
						|
  pkgs,
 | 
						|
  lib,
 | 
						|
  ...
 | 
						|
}: let
 | 
						|
  inherit (lib.options) mkEnableOption mkOption;
 | 
						|
  inherit (lib.modules) mkIf mkMerge;
 | 
						|
  inherit (lib.meta) getExe;
 | 
						|
  inherit (builtins) attrNames;
 | 
						|
  inherit (lib.types) listOf enum;
 | 
						|
  inherit (lib.nvim.types) mkGrammarOption;
 | 
						|
  inherit (lib.nvim.attrsets) mapListToAttrs;
 | 
						|
  inherit (lib.nvim.dag) entryBefore;
 | 
						|
  inherit (lib.generators) mkLuaInline;
 | 
						|
 | 
						|
  cfg = config.vim.languages.java;
 | 
						|
 | 
						|
  defaultServers = ["jdtls"];
 | 
						|
  servers = {
 | 
						|
    jdtls = {
 | 
						|
      enable = true;
 | 
						|
      cmd =
 | 
						|
        mkLuaInline
 | 
						|
        /*
 | 
						|
        lua
 | 
						|
        */
 | 
						|
        ''
 | 
						|
          {
 | 
						|
            '${getExe pkgs.jdt-language-server}',
 | 
						|
            '-configuration',
 | 
						|
            get_jdtls_config_dir(),
 | 
						|
            '-data',
 | 
						|
            get_jdtls_workspace_dir(),
 | 
						|
            get_jdtls_jvm_args(),
 | 
						|
          }
 | 
						|
        '';
 | 
						|
      filetypes = ["java"];
 | 
						|
      root_markers = [
 | 
						|
        # Multi-module projects
 | 
						|
        ".git"
 | 
						|
        "build.gradle"
 | 
						|
        "build.gradle.kts"
 | 
						|
        # Single-module projects
 | 
						|
        "build.xml" # Ant
 | 
						|
        "pom.xml" # Maven
 | 
						|
        "settings.gradle" # Gradle
 | 
						|
        "settings.gradle.kts" # Gradle
 | 
						|
      ];
 | 
						|
      init_options = {
 | 
						|
        workspace = mkLuaInline "get_jdtls_workspace_dir()";
 | 
						|
        jvm_args = {};
 | 
						|
        os_config = mkLuaInline "nil";
 | 
						|
      };
 | 
						|
      handlers = {
 | 
						|
        "textDocument/codeAction" = mkLuaInline "jdtls_on_textdocument_codeaction";
 | 
						|
        "textDocument/rename" = mkLuaInline "jdtls_on_textdocument_rename";
 | 
						|
        "workspace/applyEdit" = mkLuaInline "jdtls_on_workspace_applyedit";
 | 
						|
        "language/status" = mkLuaInline "vim.schedule_wrap(jdtls_on_language_status)";
 | 
						|
      };
 | 
						|
    };
 | 
						|
  };
 | 
						|
in {
 | 
						|
  options.vim.languages.java = {
 | 
						|
    enable = mkEnableOption "Java language support";
 | 
						|
 | 
						|
    treesitter = {
 | 
						|
      enable = mkEnableOption "Java treesitter" // {default = config.vim.languages.enableTreesitter;};
 | 
						|
      package = mkGrammarOption pkgs "java";
 | 
						|
    };
 | 
						|
 | 
						|
    lsp = {
 | 
						|
      enable = mkEnableOption "Java LSP support" // {default = config.vim.lsp.enable;};
 | 
						|
      servers = mkOption {
 | 
						|
        description = "Java LSP server to use";
 | 
						|
        type = listOf (enum (attrNames servers));
 | 
						|
        default = defaultServers;
 | 
						|
      };
 | 
						|
    };
 | 
						|
  };
 | 
						|
 | 
						|
  config = mkIf cfg.enable (mkMerge [
 | 
						|
    (mkIf cfg.lsp.enable {
 | 
						|
      vim.luaConfigRC.jdtls-util =
 | 
						|
        entryBefore ["lsp-servers"]
 | 
						|
        /*
 | 
						|
        lua
 | 
						|
        */
 | 
						|
        ''
 | 
						|
          local jdtls_handlers = require 'vim.lsp.handlers'
 | 
						|
 | 
						|
          local jdtls_env = {
 | 
						|
            HOME = vim.uv.os_homedir(),
 | 
						|
            XDG_CACHE_HOME = os.getenv 'XDG_CACHE_HOME',
 | 
						|
            JDTLS_JVM_ARGS = os.getenv 'JDTLS_JVM_ARGS',
 | 
						|
          }
 | 
						|
 | 
						|
          local function get_cache_dir()
 | 
						|
            return jdtls_env.XDG_CACHE_HOME and jdtls_env.XDG_CACHE_HOME or jdtls_env.HOME .. '/.cache'
 | 
						|
          end
 | 
						|
 | 
						|
          local function get_jdtls_cache_dir()
 | 
						|
            return get_cache_dir() .. '/jdtls'
 | 
						|
          end
 | 
						|
 | 
						|
          local function get_jdtls_config_dir()
 | 
						|
            return get_jdtls_cache_dir() .. '/config'
 | 
						|
          end
 | 
						|
 | 
						|
          local function get_jdtls_workspace_dir()
 | 
						|
            return get_jdtls_cache_dir() .. '/workspace'
 | 
						|
          end
 | 
						|
 | 
						|
          local function get_jdtls_jvm_args()
 | 
						|
            local args = {}
 | 
						|
            for a in string.gmatch((jdtls_env.JDTLS_JVM_ARGS or '''), '%S+') do
 | 
						|
              local arg = string.format('--jvm-arg=%s', a)
 | 
						|
              table.insert(args, arg)
 | 
						|
            end
 | 
						|
            return unpack(args)
 | 
						|
          end
 | 
						|
 | 
						|
          -- TextDocument version is reported as 0, override with nil so that
 | 
						|
          -- the client doesn't think the document is newer and refuses to update
 | 
						|
          -- See: https://github.com/eclipse/eclipse.jdt.ls/issues/1695
 | 
						|
          local function jdtls_fix_zero_version(workspace_edit)
 | 
						|
            if workspace_edit and workspace_edit.documentChanges then
 | 
						|
              for _, change in pairs(workspace_edit.documentChanges) do
 | 
						|
                local text_document = change.textDocument
 | 
						|
                if text_document and text_document.version and text_document.version == 0 then
 | 
						|
                  text_document.version = nil
 | 
						|
                end
 | 
						|
              end
 | 
						|
            end
 | 
						|
            return workspace_edit
 | 
						|
          end
 | 
						|
 | 
						|
          local function jdtls_on_textdocument_codeaction(err, actions, ctx)
 | 
						|
            for _, action in ipairs(actions) do
 | 
						|
              -- TODO: (steelsojka) Handle more than one edit?
 | 
						|
              if action.command == 'java.apply.workspaceEdit' then -- 'action' is Command in java format
 | 
						|
                action.edit = jdtls_fix_zero_version(action.edit or action.arguments[1])
 | 
						|
              elseif type(action.command) == 'table' and action.command.command == 'java.apply.workspaceEdit' then -- 'action' is CodeAction in java format
 | 
						|
                action.edit = jdtls_fix_zero_version(action.edit or action.command.arguments[1])
 | 
						|
              end
 | 
						|
            end
 | 
						|
 | 
						|
            jdtls_handlers[ctx.method](err, actions, ctx)
 | 
						|
          end
 | 
						|
 | 
						|
          local function jdtls_on_textdocument_rename(err, workspace_edit, ctx)
 | 
						|
            jdtls_handlers[ctx.method](err, jdtls_fix_zero_version(workspace_edit), ctx)
 | 
						|
          end
 | 
						|
 | 
						|
          local function jdtls_on_workspace_applyedit(err, workspace_edit, ctx)
 | 
						|
            jdtls_handlers[ctx.method](err, jdtls_fix_zero_version(workspace_edit), ctx)
 | 
						|
          end
 | 
						|
 | 
						|
          -- Non-standard notification that can be used to display progress
 | 
						|
          local function jdtls_on_language_status(_, result)
 | 
						|
            local command = vim.api.nvim_command
 | 
						|
            command 'echohl ModeMsg'
 | 
						|
            command(string.format('echo "%s"', result.message))
 | 
						|
            command 'echohl None'
 | 
						|
          end
 | 
						|
        '';
 | 
						|
 | 
						|
      vim.lsp.servers =
 | 
						|
        mapListToAttrs (n: {
 | 
						|
          name = n;
 | 
						|
          value = servers.${n};
 | 
						|
        })
 | 
						|
        cfg.lsp.servers;
 | 
						|
    })
 | 
						|
 | 
						|
    (mkIf cfg.treesitter.enable {
 | 
						|
      vim.treesitter.enable = true;
 | 
						|
      vim.treesitter.grammars = [cfg.treesitter.package];
 | 
						|
    })
 | 
						|
  ]);
 | 
						|
}
 |