nix-community.nixvim/tests/test-sources/modules/performance/combine-plugins.nix

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

426 lines
13 KiB
Nix
Raw Normal View History

{ pkgs, ... }:
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});
# 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 ];
};
in
{
# Test basic functionality
default =
{ config, ... }:
let
extraPlugins = [
simplePlugin1
simplePlugin2
simplePlugin3
];
in
{
performance.combinePlugins.enable = true;
inherit extraPlugins;
extraConfigLuaPost = lib.concatMapStringsSep "\n" (
name:
# lua
''
-- Plugin is loadable
require("${name}")
-- 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("${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.";
}
];
};
# Test disabled option
disabled =
{ config, ... }:
let
extraPlugins = [
simplePlugin1
simplePlugin2
simplePlugin3
];
in
{
performance.combinePlugins.enable = false;
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.";
}
];
};
# Test that plugin dependencies are handled
dependencies =
{ config, ... }:
{
performance.combinePlugins.enable = true;
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 = ''
-- 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.";
}
];
};
# Test that pathsToLink option works
paths-to-link =
{ config, ... }:
{
performance.combinePlugins = {
enable = true;
pathsToLink = [ "/_extra" ];
};
extraPlugins = [ pluginWithExtraFiles ];
extraConfigLuaPost = ''
-- Test file is in runtime
assert(
vim.api.nvim_get_runtime_file("_extra/test", false)[1],
"'_extra/test' file isn't found in runtime, expected to be found"
)
'';
assertions = [
{
assertion = pluginCount config.build.nvimPackage config.build.extraFiles "start" == 1;
message = "More than one plugin is defined in packpathDirs.";
}
];
};
# Test that plugin python3 dependencies are handled
python-dependencies =
{ config, ... }:
{
performance.combinePlugins.enable = true;
extraPlugins = [
# No python3 dependencies
simplePlugin1
# Duplicated python3-pyyaml dependency
pluginWithPyDeps1
pluginWithPyDeps2
# Python3-requests dependency
pluginWithPyDeps3
];
extraConfigLuaPost = ''
-- Python modules are importable
vim.cmd.py3("import yaml")
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.";
}
];
};
# Test that optional plugins are handled
optional-plugins =
{ config, ... }:
{
performance.combinePlugins.enable = true;
extraPlugins = [
# Start plugins
simplePlugin1
simplePlugin2
# Optional plugin
{
plugin = simplePlugin3;
optional = true;
}
# Optional plugin with dependency on simplePlugin1
# Dependencies should not be duplicated
{
plugin = pluginWithDeps1;
optional = true;
}
];
extraConfigLuaPost = ''
-- Start plugins are loadable
require("simple-plugin-1")
require("simple-plugin-2")
-- Opt plugins are not 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("simple-plugin-3")
vim.cmd.packadd("plugin-with-deps-1")
-- Now opt plugins are loadable
require("simple-plugin-3")
require("plugin-with-deps-1")
-- 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";
}
];
};
# Test that plugin configs are handled
configs =
{ config, ... }:
{
performance.combinePlugins.enable = true;
extraPlugins = [
# A plugin without config
simplePlugin1
# Plugin with config
{
plugin = simplePlugin2;
config = "let g:simple_plugin_2 = 1";
}
# Optional plugin with config
{
plugin = simplePlugin3;
optional = true;
config = "let g:simple_plugin_3 = 1";
}
];
extraConfigLuaPost = ''
-- Configs are 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";
}
];
};
# Test that config.build.extraFiles is not combined
files-plugin =
{ config, ... }:
{
performance.combinePlugins.enable = true;
extraPlugins = [
simplePlugin1
simplePlugin2
];
# Ensure that build.extraFiles is added to extraPlugins
wrapRc = true;
# Extra user files colliding with plugins
extraFiles = {
"lua/simple-plugin-1/init.lua".text = "return 1";
};
# Another form of user files
files = {
"lua/simple-plugin-2/init.lua" = {
extraConfigLua = "return 1";
};
};
extraConfigLuaPost = ''
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(num_found == 2, "expected exactly 2 versions of '" .. file .. "', got " .. num_found)
-- 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";
}
];
};
# Test that standalonePlugins option works
standalone-plugins =
{ config, ... }:
{
performance.combinePlugins = {
enable = true;
standalonePlugins = [
# By plugin name
"simple-plugin-1"
# By package itself. Its dependency, simplePlugin2, not in this list, so will be combined
pluginWithDeps2
# Dependency of other plugin
"simple-plugin-3"
];
};
extraPlugins = [
simplePlugin1
pluginWithDeps2
pluginWithDeps3
pluginWithExtraFiles
];
extraConfigLuaPost = ''
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]
-- Plugin is loadable
require(test[1])
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, simplePlugin1, pluginWithDeps2, simplePlugin3
assertion = pluginCount config.build.nvimPackage config.build.extraFiles "start" == 4;
message = "Wrong number of plugins in packpathDirs";
}
];
};
# Test if plenary.filetype is working
plenary-nvim = {
performance.combinePlugins.enable = true;
extraPlugins = [ pkgs.vimPlugins.plenary-nvim ];
extraConfigLuaPost = ''
-- Plenary filetype detection is usable
assert(require("plenary.filetype").detect(".bashrc") == "sh", "plenary.filetype is not working")
'';
};
}