plugin/none-ls: Implement all builtins (#1169)

* plugins/none-ls: Use upstream builtins.json to list sources

This avoids the need to define sources in nixvim. We only need to define
a mapping from source names to packages.

This commit does not yet introduce sources for the newly available builtins

* plugin/none-ls: Enable all known sources in tests

* plugins/none-ls: Add all missing sources
This commit is contained in:
traxys 2024-03-01 13:24:14 +01:00 committed by GitHub
parent 8c0bdb17e9
commit f9280a6865
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 504 additions and 410 deletions

View file

@ -1,64 +0,0 @@
{
mkServer = {
name,
sourceType,
description ? "${name} built-in source for none-ls",
package ? null,
extraPackages ? [],
...
}:
# returns a module
{
pkgs,
config,
lib,
helpers,
...
}:
with lib; let
cfg = config.plugins.none-ls.sources.${sourceType}.${name};
# does this evaluate package?
packageOption =
if package == null
then {}
else {
package = mkOption {
type = types.package;
default = package;
description = "Package to use for ${name} by none-ls.";
};
};
in {
options.plugins.none-ls.sources.${sourceType}.${name} =
{
enable = mkEnableOption description;
# TODO: withArgs can exist outside of the module in a generalized manner
withArgs = mkOption {
default = null;
type = with types; nullOr str;
description = ''Raw Lua code passed as an argument to the source's `with` method.'';
# Not sure that it makes sense to have the same example for all servers
# example = ''
# '\'{ extra_args = { "--no-semi", "--single-quote", "--jsx-single-quote" } }'\'
# '';
};
}
// packageOption;
config = mkIf cfg.enable {
# Does this evaluate package?
extraPackages = extraPackages ++ optional (package != null) cfg.package;
# Add source to list of sources
plugins.none-ls.sourcesItems = let
sourceItem = "${sourceType}.${name}";
withArgs =
if (cfg.withArgs == null)
then sourceItem
else "${sourceItem}.with ${cfg.withArgs}";
finalString = ''require("null-ls").builtins.${withArgs}'';
in [(helpers.mkRaw finalString)];
};
};
}

View file

@ -2,277 +2,400 @@
pkgs,
config,
lib,
helpers,
...
}:
with lib; let
cmpHelpers = import ./helpers.nix;
serverData = {
code_actions = {
eslint = {
package = pkgs.nodePackages.eslint;
};
eslint_d = {
package = pkgs.nodePackages.eslint_d;
};
gitsigns = {};
ltrs = {
package = pkgs.languagetool-rust;
};
shellcheck = {
package = pkgs.shellcheck;
};
statix = {
package = pkgs.statix;
};
};
completion = {};
diagnostics = {
alex = {
package = pkgs.nodePackages.alex;
};
ansiblelint = {
package = pkgs.ansible-lint;
};
bandit = {
package = pkgs.python3Packages.bandit;
};
checkstyle = {
package = pkgs.checkstyle;
};
cppcheck = {
package = pkgs.cppcheck;
};
deadnix = {
package = pkgs.deadnix;
};
eslint = {
package = pkgs.nodePackages.eslint;
};
eslint_d = {
package = pkgs.nodePackages.eslint_d;
};
flake8 = {
package = pkgs.python3Packages.flake8;
};
gitlint = {
package = pkgs.gitlint;
};
golangci_lint = {
package = pkgs.golangci-lint;
};
hadolint = {
package = pkgs.hadolint;
};
ktlint = {
package = pkgs.ktlint;
};
luacheck = {
package = pkgs.luaPackages.luacheck;
};
ltrs = {
package = pkgs.languagetool-rust;
};
markdownlint = {
package = pkgs.nodePackages.markdownlint-cli;
};
mypy = {
package = pkgs.mypy;
};
protolint = {
package = pkgs.protolint;
};
pylint = {
package = pkgs.pylint;
};
revive = {
pacakge = pkgs.revive;
};
ruff = {
package = pkgs.ruff;
};
shellcheck = {
package = pkgs.shellcheck;
};
staticcheck = {
pacakge = pkgs.go-tools;
};
statix = {
package = pkgs.statix;
};
stylelint = {
package = pkgs.stylelint;
};
typos = {
package = pkgs.typos;
};
vale = {
package = pkgs.vale;
};
vulture = {
package = pkgs.python3Packages.vulture;
};
write_good = {
package = pkgs.write-good;
};
yamllint = {
package = pkgs.yamllint;
};
};
formatting = {
alejandra = {
package = pkgs.alejandra;
};
asmfmt = {
package = pkgs.asmfmt;
};
astyle = {
package = pkgs.astyle;
};
bean_format = {
package = pkgs.beancount;
};
beautysh = {
package = pkgs.beautysh;
};
black = {
package = pkgs.python3Packages.black;
};
cbfmt = {
package = pkgs.cbfmt;
};
eslint = {
package = pkgs.nodePackages.eslint;
};
eslint_d = {
package = pkgs.nodePackages.eslint_d;
};
fantomas = {
package = pkgs.fantomas;
};
fnlfmt = {
package = pkgs.fnlfmt;
};
fourmolu = {
package = pkgs.haskellPackages.fourmolu;
};
gofmt = {
package = pkgs.go;
};
gofumpt = {
package = pkgs.gofumpt;
};
goimports = {
package = pkgs.gotools;
};
goimports_reviser = {
package = pkgs.goimports-reviser;
};
golines = {
package = pkgs.golines;
};
google_java_format = {
package = pkgs.google-java-format;
};
isort = {
package = pkgs.isort;
};
jq = {
package = pkgs.jq;
};
ktlint = {
package = pkgs.ktlint;
};
markdownlint = {
package = pkgs.nodePackages.markdownlint-cli;
};
nixfmt = {
package = pkgs.nixfmt;
};
nixpkgs_fmt = {
package = pkgs.nixpkgs-fmt;
};
pint = {};
phpcbf = {
package = pkgs.phpPackages.php-codesniffer;
};
prettier = {
package = pkgs.nodePackages.prettier;
};
prettierd = {
package = pkgs.prettierd;
};
protolint = {
package = pkgs.protolint;
};
ruff = {
package = pkgs.ruff;
};
ruff_format = {
package = pkgs.ruff;
};
rustfmt = {
package = pkgs.rustfmt;
};
shfmt = {
package = pkgs.shfmt;
};
sqlfluff = {
package = pkgs.sqlfluff;
};
stylelint = {
package = pkgs.stylelint;
};
stylua = {
package = pkgs.stylua;
};
taplo = {
package = pkgs.taplo;
};
trim_newlines = {};
trim_whitespace = {};
};
noneLsBuiltins = builtins.fromJSON (
builtins.readFile "${pkgs.vimPlugins.none-ls-nvim.src}/doc/builtins.json"
);
# Can contain either:
# - a package
# - null if the source is not present in nixpkgs
# - false if this source does not need a package
builtinPackages = {
inherit
(pkgs)
actionlint
alejandra
asmfmt
astyle
autoflake
beancount
beautysh
bibclean
biome
buf
cbfmt
checkmake
checkstyle
clazy
codespell
commitlint
cppcheck
cpplint
csharpier
deadnix
dfmt
djhtml
djlint
dprint
erlfmt
fantomas
fish
fnlfmt
fprettify
gitlint
gofumpt
golines
hadolint
hclfmt
isort
joker
jq
just
ktlint
leptosfmt
mdformat
mdl
mypy
nixfmt
php
pmd
prettierd
proselint
protolint
pylint
revive
rstcheck
rubocop
rubyfmt
ruff
rufo
rustfmt
rustywind
scalafmt
selene
semgrep
shellcheck
shellharden
shfmt
smlfmt
sqlfluff
statix
stylelint
stylua
taplo
templ
tfsec
topiary
treefmt
trivy
typos
typstfmt
uncrustify
usort
vale
verilator
xmlformat
xq
yamlfmt
yamllint
yapf
yq
zprint
zsh
;
inherit
(pkgs.nodePackages)
alex
eslint
eslint_d
prettier
;
inherit
(pkgs.python3.pkgs)
autopep8
bandit
black
docformatter
flake8
pycodestyle
pydocstyle
pylama
vulture
;
inherit
(pkgs.luaPackages)
luacheck
;
inherit
(pkgs.haskellPackages)
fourmolu
;
inherit
(pkgs.phpPackages)
phpmd
phpstan
psalm
;
inherit
(pkgs.rubyPackages)
htmlbeautifier
;
inherit
(pkgs.ocamlPackages)
ocamlformat
;
ansiblelint = pkgs.ansible-lint;
bean_format = pkgs.beancount;
blackd = pkgs.black;
buildifier = pkgs.bazel-buildtools;
cabal_fmt = pkgs.haskellPackages.cabal-fmt;
cfn_lint = pkgs.python3.pkgs.cfn-lint;
chktex = pkgs.texliveMedium;
clang_check = pkgs.clang-tools;
clang_format = pkgs.clang-tools;
clj_kondo = pkgs.clj-kondo;
cmake_format = pkgs.cmake-format;
cmake_lint = pkgs.cmake-format;
credo = pkgs.elixir;
crystal_format = pkgs.crystal;
cue_fmt = pkgs.cue;
d2_fmt = pkgs.d2;
dart_format = pkgs.dart;
deno_fmt = pkgs.deno;
deno_lint = pkgs.deno;
dictionary = pkgs.curl;
dotenv_linter = pkgs.dotenv-linter;
editorconfig_checker = pkgs.editorconfig-checker;
elm_format = pkgs.elmPackages.elm-format;
emacs_scheme_mode = pkgs.emacs;
emacs_vhdl_mode = pkgs.emacs;
erb_format = pkgs.rubyPackages.erb-formatter;
fish_indent = pkgs.fish;
format_r = pkgs.R;
gdformat = pkgs.gdtoolkit;
gdlint = pkgs.gdtoolkit;
gitsigns = pkgs.git;
glslc = pkgs.shaderc;
gn_format = pkgs.gn;
gofmt = pkgs.go;
goimports = pkgs.gotools;
goimports_reviser = pkgs.goimports-reviser;
golangci_lint = pkgs.golangci-lint;
google_java_format = pkgs.google-java-format;
haml_lint = pkgs.mastodon;
haxe_formatter = pkgs.haxe;
isortd = pkgs.isort;
jsonnetfmt = pkgs.jsonnet;
json_tool = pkgs.python3;
latexindent = pkgs.texliveMedium;
ltrs = pkgs.languagetool-rust;
lua_format = pkgs.luaformatter;
markdownlint_cli2 = pkgs.markdownlint-cli2;
markdownlint = pkgs.nodePackages.markdownlint-cli;
mix = pkgs.elixir;
nimpretty = pkgs.nim;
nixpkgs_fmt = pkgs.nixpkgs-fmt;
opacheck = pkgs.open-policy-agent;
perltidy = pkgs.perlPackages.PerlTidy;
pg_format = pkgs.pgformatter;
phpcbf = pkgs.phpPackages.php-codesniffer;
phpcsfixer = pkgs.phpPackages.php-cs-fixer;
phpcs = pkgs.phpPackages.php-codesniffer;
prismaFmt = pkgs.nodePackages.prisma;
protoc_gen_lint = pkgs.protobuf;
ptop = pkgs.fpc;
puppet_lint = pkgs.puppet-lint;
qmlformat = pkgs.qt6.qtdeclarative;
qmllint = pkgs.qt6.qtdeclarative;
racket_fixw = pkgs.racket;
raco_fmt = pkgs.racket;
rego = pkgs.open-policy-agent;
reorder_python_imports = pkgs.python3.pkgs.reorder-python-imports;
rpmspec = pkgs.rpm;
ruff_format = pkgs.ruff;
sqlformat = pkgs.python3.pkgs.sqlparse;
staticcheck = pkgs.go-tools;
stylish_haskell = pkgs.stylish-haskell;
surface = pkgs.elixir;
swift_format = pkgs.swift-format;
teal = pkgs.luaPackages.tl;
terraform_fmt = pkgs.terraform;
terraform_validate = pkgs.terraform;
tidy = pkgs.html-tidy;
trim_newlines = pkgs.gawk;
trim_whitespace = pkgs.gawk;
tsc = pkgs.typescript;
verible_verilog_format = pkgs.verible;
vfmt = pkgs.vlang;
vint = pkgs.vim-vint;
write_good = pkgs.write-good;
xmllint = pkgs.libxml2.bin;
zigfmt = pkgs.zig;
# Sources not present in nixpkgs
blade_formatter = null;
blue = null;
brittany = null;
bsfmt = null;
bslint = null;
cljstyle = null;
cueimports = null;
curlylint = null;
dtsfmt = null;
erb_lint = null;
fixjson = null;
forge_fmt = null;
gccdiag = null;
gersemi = null;
gospel = null;
jshint = null;
jsonlint = null;
markdown_toc = null;
markuplint = null;
misspell = null;
mlint = null;
nginx_beautifier = null;
npm_groovy_lint = null;
ocdc = null;
packer = null;
perlimports = null;
pint = null;
pretty_php = null;
puglint = null;
purs_tidy = null;
pyflyby = null;
pyink = null;
pyproject_flake8 = null;
reek = null;
regal = null;
remark = null;
rescript = null;
saltlint = null;
semistandardjs = null;
solhint = null;
spectral = null;
sqlfmt = null;
sql_formatter = null;
standardjs = null;
standardrb = null;
standardts = null;
styler = null;
stylint = null;
swiftformat = null;
swiftlint = null;
terrafmt = null;
textidote = null;
textlint = null;
twigcs = null;
vacuum = null;
xo = null;
yamlfix = null;
# Sources without packages
gitrebase = false;
# TODO: Requires the go tree-sitter parser
gomodifytags = false;
# TODO: Requires the go tree-sitter parser
impl = false;
luasnip = false;
printenv = false;
refactoring = false;
spell = false;
tags = false;
todo_comments = false;
trail_space = false;
ts_node_action = false;
vsnip = false;
};
# Format the servers to be an array of attrs like the following example
# [{
# name = "prettier";
# sourceType = "formatting";
# packages = [...];
# }]
serverDataFormatted =
mapAttrsToList
(
sourceType:
mapAttrsToList
(
name: attrs:
attrs
// {
inherit sourceType name;
}
)
)
serverData;
dataFlattened = flatten serverDataFormatted;
# Check if the package is set to `false` or not
hasBuiltinPackage = source:
if builtins.hasAttr source builtinPackages
then !(builtins.isBool builtinPackages.${source})
else true;
builtinPackage = source: builtinPackages.${source} or null;
in {
imports =
(map cmpHelpers.mkServer dataFlattened)
++ [
./prettier.nix
# Introduced January 22 2024.
# TODO remove in early March 2024.
(
mkRemovedOptionModule
["plugins" "none-ls" "sources" "formatting" "prettier_d_slim"]
"`prettier_d_slim` is no longer maintained for >3 years. Please migrate to `prettierd`"
)
];
imports = [
./prettier.nix
];
options.plugins.none-ls.sources =
builtins.mapAttrs (
sourceType: sources:
builtins.mapAttrs
(source: _:
{
enable = mkEnableOption "the ${source} ${sourceType} source for none-ls";
withArgs = helpers.mkNullOrLua ''
Raw Lua code passed as an argument to the source's `with` method.
'';
}
// lib.optionalAttrs (hasBuiltinPackage source) {
package = let
pkg = builtinPackage source;
in
mkOption ({
type = types.nullOr types.package;
description =
"Package to use for ${source} by none-ls. "
+ (
lib.optionalString (pkg == null) ''
Not handled in nixvim, either install externally and set to null or set the option with a derivation.
''
);
}
// optionalAttrs (pkg != null) {
default = pkg;
});
})
sources
)
noneLsBuiltins;
config = let
cfg = config.plugins.none-ls;
gitsignsEnabled = cfg.sources.code_actions.gitsigns.enable;
flattenedSources = lib.flatten (
lib.mapAttrsToList (
sourceType: sources: (lib.mapAttrsToList (sourceName: source:
source
// {
inherit sourceType sourceName;
})
sources)
)
cfg.sources
);
enabledSources = builtins.filter (source: source.enable) flattenedSources;
in
mkIf cfg.enable {
plugins.none-ls.sourcesItems =
builtins.map (
source: let
sourceItem = "${source.sourceType}.${source.sourceName}";
withArgs =
if source.withArgs == null
then sourceItem
else "${sourceItem}.with(${source.withArgs}})";
in
helpers.mkRaw ''
require("null-ls").builtins.${withArgs}
''
)
enabledSources;
plugins.gitsigns.enable = mkIf gitsignsEnabled true;
extraPackages = optional gitsignsEnabled pkgs.git;
extraPackages = builtins.filter (p: p != null) (
builtins.map (
source: source.package or null
)
enabledSources
);
};
}

View file

@ -50,6 +50,10 @@
inherit pkgs lib helpers;
config = {};
};
nonels-sources-options = import ../plugins/none-ls/servers.nix {
inherit pkgs lib helpers;
config = {};
};
};
inherit namespace;
})

View file

@ -1,4 +1,8 @@
{pkgs, ...}: {
{
pkgs,
nonels-sources-options,
...
}: {
# Empty configuration
empty = {
plugins.none-ls.enable = true;
@ -27,7 +31,8 @@
default = {
plugins.none-ls = {
enable = true;
# sandbox-exec: pattern serialization length 159032 exceeds maximum (65535)
enable = !pkgs.stdenv.isDarwin;
enableLspFormat = false;
border = null;
@ -47,90 +52,116 @@
shouldAttach = null;
tempDir = null;
updateInInsert = false;
sources = {
code_actions = {
eslint.enable = true;
eslint_d.enable = true;
gitsigns.enable = true;
ltrs.enable = true;
shellcheck.enable = true;
statix.enable = true;
};
diagnostics = {
ansiblelint.enable = true;
bandit.enable = true;
checkstyle.enable = true;
cppcheck.enable = true;
deadnix.enable = true;
eslint.enable = true;
eslint_d.enable = true;
flake8.enable = true;
gitlint.enable = true;
golangci_lint.enable = true;
ktlint.enable = true;
ltrs.enable = true;
markdownlint.enable = true;
ruff.enable = true;
shellcheck.enable = true;
statix.enable = true;
staticcheck.enable = true;
typos.enable = true;
vale.enable = true;
vulture.enable = true;
alex.enable = true;
protolint.enable = true;
revive.enable = true;
hadolint.enable = true;
luacheck.enable = true;
mypy.enable = true;
pylint.enable = true;
write_good.enable = true;
yamllint.enable = true;
stylelint.enable = true;
};
formatting = {
alejandra.enable = true;
asmfmt.enable = true;
astyle.enable = true;
bean_format.enable = true;
black.enable = true;
# As of 2024-01-04, cbfmt is broken on darwin
# TODO: re-enable this test when fixed
cbfmt.enable = !pkgs.stdenv.isDarwin;
eslint.enable = true;
eslint_d.enable = true;
fantomas.enable = true;
fnlfmt.enable = true;
fourmolu.enable = true;
gofmt.enable = true;
gofumpt.enable = true;
goimports.enable = true;
goimports_reviser.enable = true;
golines.enable = true;
google_java_format.enable = true;
ktlint.enable = true;
nixfmt.enable = true;
nixpkgs_fmt.enable = true;
phpcbf.enable = true;
prettier.enable = true;
prettierd.enable = true;
shfmt.enable = true;
stylua.enable = true;
stylelint.enable = true;
taplo.enable = true;
isort.enable = true;
jq.enable = true;
markdownlint.enable = true;
pint.enable = true;
protolint.enable = true;
ruff.enable = true;
ruff_format.enable = true;
rustfmt.enable = true;
sqlfluff.enable = true;
trim_newlines.enable = true;
trim_whitespace.enable = true;
};
};
sources = let
options = nonels-sources-options.options.plugins.none-ls.sources;
unpackaged =
[
"blade_formatter"
"blue"
"brittany"
"bsfmt"
"bslint"
"cljstyle"
"cueimports"
"curlylint"
"dtsfmt"
"erb_lint"
"fixjson"
"forge_fmt"
"gccdiag"
"gersemi"
"gospel"
"jshint"
"jsonlint"
"markdown_toc"
"markuplint"
"misspell"
"mlint"
"nginx_beautifier"
"npm_groovy_lint"
"ocdc"
"packer"
"perlimports"
"pint"
"pretty_php"
"puglint"
"purs_tidy"
"pyflyby"
"pyink"
"pyproject_flake8"
"reek"
"regal"
"remark"
"rescript"
"saltlint"
"semistandardjs"
"solhint"
"spectral"
"sqlfmt"
"sql_formatter"
"standardjs"
"standardrb"
"standardts"
"styler"
"stylint"
"swiftformat"
"swiftlint"
"terrafmt"
"textidote"
"textlint"
"twigcs"
"vacuum"
"xo"
"yamlfix"
]
++ (
pkgs.lib.optionals
(pkgs.stdenv.isDarwin && pkgs.stdenv.isx86_64)
[
"rubyfmt"
# Currently broken
"lua_format"
# Currently broken
"zigfmt"
]
)
++ (
pkgs.lib.optionals
pkgs.stdenv.isDarwin
[
"rpmspec"
"clazy"
"gdformat"
"gdlint"
"haml_lint"
"verilator"
"verible_verilog_format"
# Broken due to a dependency
"jsonnetfmt"
]
)
++ (
pkgs.lib.optionals
pkgs.stdenv.isAarch64
[
"semgrep"
"smlfmt"
]
);
sources = pkgs.lib.mapAttrs (_: sources:
pkgs.lib.mapAttrs (source: _:
{
enable = true;
}
// pkgs.lib.optionalAttrs (builtins.elem source unpackaged) {
package = null;
})
sources)
options;
in
sources;
};
};
}