diff --git a/modules/performance.nix b/modules/performance.nix index 567f6d9371..d88222bac4 100644 --- a/modules/performance.nix +++ b/modules/performance.nix @@ -1,12 +1,6 @@ -{ - lib, - pkgs, - config, - ... -}: +{ lib, ... }: let inherit (lib) types; - cfg = config.performance; pathsToLink = [ # :h rtp @@ -95,17 +89,6 @@ in }; }; - # FIXME: The performance options do not correctly propagate lua module dependencies. - # We can explicitly specify 'plenary-nvim', as it is a very common dependency. - # While this is enough for our test suite to pass, end-users may be affected by other dependencies not covered by our test suite. - # - # See https://github.com/nix-community/nixvim/pull/3099 - config.extraPlugins = - lib.mkIf (cfg.combinePlugins.enable || (cfg.byteCompileLua.enable && cfg.byteCompileLua.plugins)) - [ - pkgs.vimPlugins.plenary-nvim - ]; - # Set option value with default priority so that values are appended by default config.performance.combinePlugins = { inherit pathsToLink; }; } diff --git a/modules/top-level/plugins/mk-plugin-pack.nix b/modules/top-level/plugins/mk-plugin-pack.nix index 6bb7adc297..e0f6e8b391 100644 --- a/modules/top-level/plugins/mk-plugin-pack.nix +++ b/modules/top-level/plugins/mk-plugin-pack.nix @@ -28,24 +28,38 @@ let (builtins.concatMap (f: f ps)) ]; + # propagatedBuildInputs contain lua dependencies + propagatedBuildInputs = lib.pipe pluginsToCombine [ + (builtins.catAttrs "plugin") + (builtins.catAttrs "propagatedBuildInputs") + builtins.concatLists + lib.unique + ]; + # Combined plugin - combinedPlugin = pkgs.vimUtils.toVimPlugin ( - pkgs.buildEnv { - name = "plugin-pack"; - paths = overriddenPlugins; - inherit pathsToLink; + combinedPlugin = + lib.pipe + { + name = "plugin-pack"; + paths = overriddenPlugins; + inherit pathsToLink; - # Remove empty directories and activate vimGenDocHook - # TODO: figure out why we are running the `preFixup` hook in `postBuild` - postBuild = '' - find $out -type d -empty -delete - runHook preFixup - ''; - passthru = { - inherit python3Dependencies; - }; - } - ); + # buildEnv uses runCommand under the hood. runCommand doesn't run any build phases. + # To run custom commands buildEnv takes postBuild argument. + # fixupPhase is used for propagating build inputs and to trigger vimGenDocHook + postBuild = '' + find $out -type d -empty -delete + fixupPhase + ''; + passthru = { + inherit python3Dependencies; + }; + } + [ + pkgs.buildEnv + pkgs.vimUtils.toVimPlugin + (drv: drv.overrideAttrs { inherit propagatedBuildInputs; }) + ]; # Combined plugin configs combinedConfig = lib.pipe pluginsToCombine [ diff --git a/tests/test-sources/modules/performance/byte-compile-lua.nix b/tests/test-sources/modules/performance/byte-compile-lua.nix index 5375425af6..a3041a5e00 100644 --- a/tests/test-sources/modules/performance/byte-compile-lua.nix +++ b/tests/test-sources/modules/performance/byte-compile-lua.nix @@ -248,8 +248,8 @@ in extraPlugins = with pkgs.vimPlugins; [ nvim-lspconfig - # Depends on plenary-nvim - telescope-nvim + # Depends on nui-nvim + noice-nvim # buildCommand plugin with python3 dependency ((pkgs.writeTextDir "/plugin/test.lua" "vim.opt.tabstop = 2").overrideAttrs { passthru.python3Dependencies = ps: [ ps.pyyaml ]; @@ -263,8 +263,8 @@ in -- Plugins are loadable require("lspconfig") - require("telescope") - require("plenary") + require("noice") + require("nui.popup") require("nvim-treesitter") -- Python modules are importable @@ -276,16 +276,13 @@ in test_rtp_file("plugin/lspconfig.lua", true) test_rtp_file("doc/lspconfig.txt", false) - -- telescope-nvim - test_rtp_file("lua/telescope/init.lua", true) - test_rtp_file("lua/telescope/builtin/init.lua", true) - test_rtp_file("plugin/telescope.lua", true) - test_rtp_file("autoload/health/telescope.vim", false) - test_rtp_file("doc/telescope.txt", false) + -- noice-nvim + test_rtp_file("lua/noice/init.lua", true) + test_rtp_file("lua/noice/config/init.lua", true) + test_rtp_file("doc/noice.nvim.txt", false) - -- Dependency of telescope-nvim (plenary-nvim) - test_rtp_file("lua/plenary/init.lua", true) - test_rtp_file("plugin/plenary.vim", false) + -- Dependency of noice-nvim (nui-nvim) + test_rtp_file("lua/nui/popup/init.lua", true) -- Test plugin test_rtp_file("plugin/test.lua", true) diff --git a/tests/test-sources/modules/performance/combine-plugins.nix b/tests/test-sources/modules/performance/combine-plugins.nix index b200db1d0b..fe0c3c4674 100644 --- a/tests/test-sources/modules/performance/combine-plugins.nix +++ b/tests/test-sources/modules/performance/combine-plugins.nix @@ -2,57 +2,157 @@ let inherit (pkgs) lib; - # Count plugins of given type excluding 'build.extraFiles' - pluginCount = - pkg: files: type: - builtins.length (builtins.filter (p: p != files) pkg.packpathDirs.myNeovimPackages.${type}); + # Assertion for a number of plugins of given type defined in nvimPackage.packpathDirs + expectNPlugins = + config: type: n: + let + # 'build.extraFiles' must not be combined, so exclude it from counting + plugins = builtins.filter ( + p: p != config.build.extraFiles + ) config.build.nvimPackage.packpathDirs.myNeovimPackages.${type}; + numPlugins = builtins.length plugins; + in + { + assertion = numPlugins == n; + message = "Expected ${toString n} '${type}' plugins defined in 'nvimPackage.packpathDirs', got ${toString numPlugins}: ${ + lib.concatMapStringsSep ", " lib.getName plugins + }."; + }; + # Assertion that exactly one start plugin is defined in nvimPackage.packpathDirs + expectOneStartPlugin = config: expectNPlugins config "start" 1; + + # Stub plugins + mkPlugin = + name: args: + pkgs.vimUtils.buildVimPlugin ( + { + pname = name; + version = "2025-04-27"; + src = pkgs.runCommand "${name}-source" { } '' + mkdir "$out" + # Add some colliding files + echo "# ${name}" > "$out/README.md" + echo "Copyright (c) ${name}" > "$out/LICENSE" + mkdir "$out/tests" + echo "return '${name}'" > "$out/tests/test.lua" + # Add import path + mkdir -p "$out/lua/${name}" + echo "return '${name}'" > "$out/lua/${name}/init.lua" + # Add doc + mkdir "$out/doc" + echo "*${name}.txt* ${name}" > "$out/doc/${name}.txt" + ''; + } + // args + ); + # Simple plugins without any features + simplePlugin1 = mkPlugin "simple-plugin-1" { }; + simplePlugin2 = mkPlugin "simple-plugin-2" { }; + simplePlugin3 = mkPlugin "simple-plugin-3" { }; + # Plugins with dependencies + pluginWithDeps1 = mkPlugin "plugin-with-deps-1" { + dependencies = [ simplePlugin1 ]; + }; + pluginWithDeps2 = mkPlugin "plugin-with-deps-2" { + dependencies = [ simplePlugin2 ]; + }; + pluginWithDeps3 = mkPlugin "plugin-with-deps-3" { + dependencies = [ simplePlugin3 ]; + }; + # Plugin with recursive dependencies + pluginWithRecDeps = mkPlugin "plugin-with-rec-deps" { + dependencies = [ + pluginWithDeps1 + pluginWithDeps2 + ]; + }; + # Plugin with non-standard files + pluginWithExtraFiles = mkPlugin "plugin-with-extra-files" { + postInstall = '' + mkdir "$out/_extra" + touch "$out/_extra/test" + ''; + }; + # Plugins with Python dependencies + pluginWithPyDeps1 = mkPlugin "plugin-with-py-deps-1" { + passthru.python3Dependencies = ps: [ ps.pyyaml ]; + }; + pluginWithPyDeps2 = mkPlugin "plugin-with-py-deps-2" { + passthru.python3Dependencies = ps: [ ps.pyyaml ]; + }; + pluginWithPyDeps3 = mkPlugin "plugin-with-py-deps-3" { + passthru.python3Dependencies = ps: [ ps.requests ]; + }; + # Plugins with Lua dependencies + ensureDep = + drv: dep: + drv.overrideAttrs (prev: { + propagatedBuildInputs = lib.unique ( + prev.propagatedBuildInputs or [ ] ++ [ prev.passthru.lua.pkgs.${dep} ] + ); + }); + pluginWithLuaDeps1 = ensureDep pkgs.vimPlugins.telescope-nvim "plenary-nvim"; + pluginWithLuaDeps2 = ensureDep pkgs.vimPlugins.nvim-cmp "plenary-nvim"; + pluginWithLuaDeps3 = ensureDep pkgs.vimPlugins.gitsigns-nvim "nui-nvim"; in { # Test basic functionality default = { config, ... }: + let + extraPlugins = [ + simplePlugin1 + simplePlugin2 + simplePlugin3 + ]; + in { performance.combinePlugins.enable = true; - extraPlugins = with pkgs.vimPlugins; [ - nvim-lspconfig - nvim-treesitter - ]; - extraConfigLuaPost = '' - -- Plugins are loadable - require("lspconfig") - require("nvim-treesitter") + inherit extraPlugins; + extraConfigLuaPost = lib.concatMapStringsSep "\n" ( + name: + # lua + '' + -- Plugin is loadable + require("${name}") - -- No separate plugin entries in nvim_list_runtime_paths - assert(not vim.iter(vim.api.nvim_list_runtime_paths()):any(function(entry) - return entry:find("treesitter") or entry:find("lspconfig") - end), "separate plugins are found in runtime") + -- No separate plugin entry in vim.api.nvim_list_runtime_paths() + assert(not vim.iter(vim.api.nvim_list_runtime_paths()):any(function(entry) + return entry:find("${name}", 1, true) + end), "plugin '${name}' found in runtime, expected to be combined") - -- Help tags are generated - assert(vim.fn.getcompletion("lspconfig", "help")[1], "no help tags for nvim-lspconfig") - assert(vim.fn.getcompletion("nvim-treesitter", "help")[1], "no help tags for nvim-treesitter") - ''; + -- Help tags are generated + assert(vim.fn.getcompletion("${name}", "help")[1], "no help tags for '${name}'") + '') (map lib.getName extraPlugins); assertions = [ - { - assertion = pluginCount config.build.nvimPackage config.build.extraFiles "start" == 1; - message = "More than one plugin is defined in packpathDirs, expected one plugin pack."; - } + (expectOneStartPlugin config) ]; }; # Test disabled option disabled = { config, ... }: + let + extraPlugins = [ + simplePlugin1 + simplePlugin2 + simplePlugin3 + ]; + in { performance.combinePlugins.enable = false; - extraPlugins = with pkgs.vimPlugins; [ - nvim-lspconfig - nvim-treesitter - ]; + inherit extraPlugins; + extraConfigLuaPost = lib.concatMapStringsSep "\n" ( + name: + # lua + '' + -- Separate plugin entry in vim.api.nvim_list_runtime_paths() + assert(vim.iter(vim.api.nvim_list_runtime_paths()):any(function(entry) + return entry:find("${name}", 1, true) + end), "plugin '${name}' isn't found in runtime as a separate entry, expected not to be combined") + '') (map lib.getName extraPlugins); assertions = [ - { - assertion = pluginCount config.build.nvimPackage config.build.extraFiles "start" >= 2; - message = "Only one plugin is defined in packpathDirs, expected at least two."; - } + (expectNPlugins config "start" (builtins.length extraPlugins)) ]; }; @@ -61,27 +161,29 @@ in { config, ... }: { performance.combinePlugins.enable = true; - extraPlugins = with pkgs.vimPlugins; [ - # Depends on nvim-cmp - cmp-dictionary - # We have to manually add cmp-dictionary's dependence: nvim-cmp - nvim-cmp - # Depends on telescope-nvim which itself depends on plenary-nvim - telescope-undo-nvim + extraPlugins = [ + # Depends on pluginWithDeps1 and pluginWithDeps2 which themselves depend on simplePlugin1 and simplePlugin2 + pluginWithRecDeps + # Depends on simplePlugin3 + pluginWithDeps3 + # Duplicated dependency + pluginWithDeps2 + # Duplicated plugin + simplePlugin2 ]; extraConfigLuaPost = '' - -- Plugins and its dependencies are loadable - require("cmp_dictionary") - require("cmp") - require("telescope-undo") - require("telescope") - require("plenary") + -- Plugin 'pluginWithRecDeps' and its dependencies are loadable + require("plugin-with-rec-deps") + require("plugin-with-deps-1") + require("plugin-with-deps-2") + require("simple-plugin-1") + require("simple-plugin-2") + -- Plugin 'pluginWithDeps3' and its dependencies are loadable + require("plugin-with-deps-3") + require("simple-plugin-3") ''; assertions = [ - { - assertion = pluginCount config.build.nvimPackage config.build.extraFiles "start" == 1; - message = "More than one plugin is defined in packpathDirs."; - } + (expectOneStartPlugin config) ]; }; @@ -91,25 +193,18 @@ in { performance.combinePlugins = { enable = true; - # fzf native library is in build directory - pathsToLink = [ "/build" ]; + pathsToLink = [ "/_extra" ]; }; - extraPlugins = [ pkgs.vimPlugins.telescope-fzf-native-nvim ]; + extraPlugins = [ pluginWithExtraFiles ]; extraConfigLuaPost = '' - -- Native library is in runtimepath + -- Test file is in runtime assert( - vim.api.nvim_get_runtime_file("build/libfzf.so", false)[1], - "build/libfzf.so is not found in runtimepath" + vim.api.nvim_get_runtime_file("_extra/test", false)[1], + "'_extra/test' file isn't found in runtime, expected to be found" ) - - -- Native library is loadable - require("fzf_lib") ''; assertions = [ - { - assertion = pluginCount config.build.nvimPackage config.build.extraFiles "start" == 1; - message = "More than one plugin is defined in packpathDirs."; - } + (expectOneStartPlugin config) ]; }; @@ -118,14 +213,14 @@ in { config, ... }: { performance.combinePlugins.enable = true; - extraPlugins = with pkgs.vimPlugins; [ + extraPlugins = [ # No python3 dependencies - plenary-nvim - # Duplicate python3 dependencies - (nvim-lspconfig.overrideAttrs { passthru.python3Dependencies = ps: [ ps.pyyaml ]; }) - (nvim-treesitter.overrideAttrs { passthru.python3Dependencies = ps: [ ps.pyyaml ]; }) - # Another python3 dependency - (nvim-cmp.overrideAttrs { passthru.python3Dependencies = ps: [ ps.requests ]; }) + simplePlugin1 + # Duplicated python3-pyyaml dependency + pluginWithPyDeps1 + pluginWithPyDeps2 + # Python3-requests dependency + pluginWithPyDeps3 ]; extraConfigLuaPost = '' -- Python modules are importable @@ -133,10 +228,33 @@ in vim.cmd.py3("import requests") ''; assertions = [ - { - assertion = pluginCount config.build.nvimPackage config.build.extraFiles "start" == 1; - message = "More than one plugin is defined in packpathDirs."; - } + (expectOneStartPlugin config) + ]; + }; + + # Test that plugin lua dependencies are handled + lua-dependencies = + { config, ... }: + { + performance.combinePlugins.enable = true; + extraPlugins = [ + simplePlugin1 + # Duplicated plenary-nvim dependency + pluginWithLuaDeps1 + pluginWithLuaDeps2 + # nui-nvim dependency + pluginWithLuaDeps3 + ]; + extraConfigLuaPost = '' + -- All packages and its dependencies are importable + require("telescope") + require("plenary") + require("cmp") + require("gitsigns") + require("nui.popup") + ''; + assertions = [ + (expectOneStartPlugin config) ]; }; @@ -145,56 +263,49 @@ in { config, ... }: { performance.combinePlugins.enable = true; - extraPlugins = with pkgs.vimPlugins; [ + extraPlugins = [ # Start plugins - plenary-nvim - nvim-lspconfig + simplePlugin1 + simplePlugin2 # Optional plugin { - plugin = nvim-treesitter; + plugin = simplePlugin3; optional = true; } - # Optional plugin with dependency on plenary-nvim + # Optional plugin with dependency on simplePlugin1 # Dependencies should not be duplicated { - plugin = telescope-nvim; + plugin = pluginWithDeps1; optional = true; } ]; extraConfigLuaPost = '' -- Start plugins are loadable - require("plenary") - require("lspconfig") + require("simple-plugin-1") + require("simple-plugin-2") -- Opt plugins are not loadable - local ok = pcall(require, "nvim-treesitter") - assert(not ok, "nvim-treesitter plugin is loadable") - ok = pcall(require, "telescope") - assert(not ok, "telescope-nvim plugin is loadable") + local ok = pcall(require, "simple-plugin-3") + assert(not ok, "simplePlugin3 is loadable, expected it to be an opt plugin") + ok = pcall(require, "plugin-with-deps-1") + assert(not ok, "pluginWithDeps1 is loadable, expected it to be an opt plugin") -- Load plugins - vim.cmd.packadd("nvim-treesitter") - vim.cmd.packadd("telescope.nvim") + vim.cmd.packadd("simple-plugin-3") + vim.cmd.packadd("plugin-with-deps-1") -- Now opt plugins are loadable - require("nvim-treesitter") - require("telescope") + require("simple-plugin-3") + require("plugin-with-deps-1") - -- Only one copy of plenary-nvim should be available - assert( - #vim.api.nvim_get_runtime_file("lua/plenary/init.lua", true) == 1, - "plenary-nvim is duplicated" - ) + -- Only one copy of simplePlugin1 should be available + local num_plugins = #vim.api.nvim_get_runtime_file("lua/simple-plugin-1/init.lua", true) + assert(num_plugins == 1, "expected 1 copy of simplePlugin1, got " .. num_plugins) ''; assertions = [ - { - assertion = pluginCount config.build.nvimPackage config.build.extraFiles "start" == 1; - message = "More than one start plugin is defined in packpathDirs"; - } - { - assertion = pluginCount config.build.nvimPackage config.build.extraFiles "opt" == 2; - message = "Less than two opt plugins are defined in packpathDirs"; - } + (expectOneStartPlugin config) + # simplePlugin3 pluginWithDeps1 + (expectNPlugins config "opt" 2) ]; }; @@ -203,41 +314,28 @@ in { config, ... }: { performance.combinePlugins.enable = true; - extraPlugins = with pkgs.vimPlugins; [ + extraPlugins = [ # A plugin without config - plenary-nvim - # Plugins with configs - { - plugin = nvim-treesitter; - config = "let g:treesitter_config = 1"; - } + simplePlugin1 + # Plugin with config { - plugin = nvim-lspconfig; - config = "let g:lspconfig_config = 1"; + plugin = simplePlugin2; + config = "let g:simple_plugin_2 = 1"; } # Optional plugin with config { - plugin = telescope-nvim; + plugin = simplePlugin3; optional = true; - config = "let g:telescope_config = 1"; + config = "let g:simple_plugin_3 = 1"; } ]; extraConfigLuaPost = '' - -- Plugins are loadable - require("plenary") - require("nvim-treesitter") - require("lspconfig") - -- Configs are evaluated - assert(vim.g.treesitter_config == 1, "nvim-treesitter config isn't evaluated") - assert(vim.g.lspconfig_config == 1, "nvim-lspconfig config isn't evaluated") - assert(vim.g.telescope_config == 1, "telescope-nvim config isn't evaluated") + assert(vim.g.simple_plugin_2 == 1, "simplePlugin2's config isn't evaluated") + assert(vim.g.simple_plugin_3 == 1, "simplePlugin3's config isn't evaluated") ''; assertions = [ - { - assertion = pluginCount config.build.nvimPackage config.build.extraFiles "start" == 1; - message = "More than one start plugin is defined in packpathDirs"; - } + (expectOneStartPlugin config) ]; }; @@ -246,68 +344,39 @@ in { config, ... }: { performance.combinePlugins.enable = true; - extraPlugins = with pkgs.vimPlugins; [ - nvim-treesitter - vim-nix + extraPlugins = [ + simplePlugin1 + simplePlugin2 ]; - # Ensure that build.extraFiles is added extraPlugins + # Ensure that build.extraFiles is added to extraPlugins wrapRc = true; # Extra user files colliding with plugins extraFiles = { - "ftplugin/nix.vim".text = "let b:test = 1"; - "queries/nix/highlights.scm".text = '' - ;; extends - (comment) @comment - ''; + "lua/simple-plugin-1/init.lua".text = "return 1"; }; # Another form of user files files = { - "ftdetect/nix.vim" = { - autoCmd = [ - { - event = [ - "BufRead" - "BufNewFile" - ]; - pattern = "*.nix"; - command = "setf nix"; - } - ]; + "lua/simple-plugin-2/init.lua" = { + extraConfigLua = "return 1"; }; }; extraConfigLuaPost = '' - local function get_paths(name) - local paths = vim.api.nvim_get_runtime_file(name, true); - return vim.tbl_filter(function(v) - -- Skip paths from neovim runtime - return not v:find("/nvim/runtime/") - end, paths) - end + for _, file in ipairs({"lua/simple-plugin-1/init.lua", "lua/simple-plugin-2/init.lua"}) do + local paths_found = vim.api.nvim_get_runtime_file(file, true) + local num_found = #paths_found - -- Both plugin and user version are available - assert(#get_paths("ftplugin/nix.vim") == 2, "only one version of ftplugin/nix.vim") - assert(#get_paths("ftdetect/nix.vim") == 2, "only one version of ftdetect/nix.vim") - assert(#get_paths("queries/nix/highlights.scm") == 2, "only one version of queries/nix/highlights.scm") + -- Both plugin and user version are available + assert(num_found == 2, "expected exactly 2 versions of '" .. file .. "', got " .. num_found) - -- First found file is from build.extraFiles - assert( - get_paths("ftplugin/nix.vim")[1]:find("${lib.getName config.build.extraFiles}", 1, true), - "first found ftplugin/nix.vim isn't in build.extraFiles runtime path" - ) - assert( - get_paths("queries/nix/highlights.scm")[1]:find("${lib.getName config.build.extraFiles}", 1, true), - "first found queries/nix/highlights.scm isn't in build.extraFiles runtime path" - ) - assert( - get_paths("queries/nix/highlights.scm")[1]:find("${lib.getName config.build.extraFiles}", 1, true), - "first found queries/nix/highlights.scm isn't in build.extraFiles runtime path" - ) + -- First found file is from build.extraFiles + assert( + paths_found[1]:find("${lib.getName config.build.extraFiles}", 1, true), + "expected first found '" .. file .. "' to be from build.extraFiles, got " .. paths_found[1] + ) + end ''; assertions = [ - { - assertion = pluginCount config.build.nvimPackage config.build.extraFiles "start" == 1; - message = "More than one start plugin is defined in packpathDirs"; - } + (expectOneStartPlugin config) ]; }; @@ -317,65 +386,52 @@ in { performance.combinePlugins = { enable = true; - standalonePlugins = with pkgs.vimPlugins; [ + standalonePlugins = [ # By plugin name - "nvim-treesitter" - # By package itself - nvim-lspconfig - # Its dependency, plenary-nvim, not in this list, so will be combined - telescope-nvim + "simple-plugin-1" + # By package itself. Its dependency, simplePlugin2, not in this list, so will be combined + pluginWithDeps2 # Dependency of other plugin - "nvim-cmp" + "simple-plugin-3" ]; }; - extraPlugins = with pkgs.vimPlugins; [ - nvim-treesitter - nvim-lspconfig - telescope-nvim - # Only its dependency (nvim-cmp) won't be combined, but not the plugin itself - cmp-dictionary - # We have to manually add cmp-dictionary's dependence: nvim-cmp - nvim-cmp - # More plugins - gitsigns-nvim - luasnip + extraPlugins = [ + simplePlugin1 + pluginWithDeps2 + pluginWithDeps3 + pluginWithExtraFiles ]; extraConfigLuaPost = '' - -- Plugins are loadable - require("nvim-treesitter") - require("lspconfig") - require("telescope") - require("plenary") - require("cmp_dictionary") - require("cmp") - require("gitsigns") - require("luasnip") + local tests = { + {"simple-plugin-1", true}, + {"plugin-with-deps-2", true}, + {"simple-plugin-2", false}, + {"plugin-with-deps-3", false}, + {"simple-plugin-3", true}, + {"plugin-with-extra-files", false}, + } + for _, test in ipairs(tests) do + local name = test[1] + local expected_standalone = test[2] - -- Verify if plugin is standalone or combined - local function is_standalone(name, dirname) - local paths = vim.api.nvim_get_runtime_file("lua/" .. name, true); - assert(#paths == 1, "more than one copy of " .. name .. " in runtime") - return paths[1]:match("^(.+)/lua/"):find(dirname or name, 1, true) ~= nil - end + -- Plugin is loadable + require(test[1]) - -- Standalone plugins - assert(is_standalone("nvim-treesitter"), "nvim-treesitter is combined, expected standalone") - assert(is_standalone("lspconfig"), "nvim-lspconfig is combined, expected standalone") - assert(is_standalone("telescope"), "telescope-nvim is combined, expected standalone") - -- Add trailing slash to ensure that it doesn't match cmp_dictionary - assert(is_standalone("cmp/", "nvim-cmp"), "nvim-cmp is combined, expected standalone") - -- Combined plugins - assert(not is_standalone("plenary"), "plenary-nvim is standalone, expected combined") - assert(not is_standalone("cmp_dictionary", "cmp-dictionary"), "cmp-dictionary is standalone, expected combined") - assert(not is_standalone("gitsigns"), "gitsigns-nvim is standalone, expected combined") - assert(not is_standalone("luasnip"), "luasnip is standalone, expected combined") + local paths = vim.api.nvim_get_runtime_file("lua/" .. name, true) + -- Plugins shouldn't be duplicated + assert(#paths == 1, "expected exactly 1 copy of '" .. name .. "' in runtime, got ", #paths) + -- Test if plugin is standalone. This matches directory name before '/lua/'. + local is_standalone = paths[1]:match("^(.+)/lua/"):find(name, 1, true) ~= nil + local expected_text = expected_standalone and "standalone" or "combined" + assert( + is_standalone == expected_standalone, + "expected '" .. name .. "' to be " .. expected_text .. ", found path: " .. paths[1] + ) + end ''; assertions = [ - { - # plugin-pack, nvim-treesitter, nvim-lspconfig, telescope-nvim, nvim-cmp - assertion = pluginCount config.build.nvimPackage config.build.extraFiles "start" == 5; - message = "Wrong number of plugins in packpathDirs"; - } + # plugin-pack, simplePlugin1, pluginWithDeps2, simplePlugin3 + (expectNPlugins config "start" 4) ]; };