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, pkgs,
config, config,
lib, lib,
helpers,
... ...
}: }:
with lib; let with lib; let
cmpHelpers = import ./helpers.nix; noneLsBuiltins = builtins.fromJSON (
serverData = { builtins.readFile "${pkgs.vimPlugins.none-ls-nvim.src}/doc/builtins.json"
code_actions = { );
eslint = {
package = pkgs.nodePackages.eslint; # Can contain either:
}; # - a package
eslint_d = { # - null if the source is not present in nixpkgs
package = pkgs.nodePackages.eslint_d; # - false if this source does not need a package
}; builtinPackages = {
gitsigns = {}; inherit
ltrs = { (pkgs)
package = pkgs.languagetool-rust; actionlint
}; alejandra
shellcheck = { asmfmt
package = pkgs.shellcheck; astyle
}; autoflake
statix = { beancount
package = pkgs.statix; beautysh
}; bibclean
}; biome
completion = {}; buf
diagnostics = { cbfmt
alex = { checkmake
package = pkgs.nodePackages.alex; checkstyle
}; clazy
ansiblelint = { codespell
package = pkgs.ansible-lint; commitlint
}; cppcheck
bandit = { cpplint
package = pkgs.python3Packages.bandit; csharpier
}; deadnix
checkstyle = { dfmt
package = pkgs.checkstyle; djhtml
}; djlint
cppcheck = { dprint
package = pkgs.cppcheck; erlfmt
}; fantomas
deadnix = { fish
package = pkgs.deadnix; fnlfmt
}; fprettify
eslint = { gitlint
package = pkgs.nodePackages.eslint; gofumpt
}; golines
eslint_d = { hadolint
package = pkgs.nodePackages.eslint_d; hclfmt
}; isort
flake8 = { joker
package = pkgs.python3Packages.flake8; jq
}; just
gitlint = { ktlint
package = pkgs.gitlint; leptosfmt
}; mdformat
golangci_lint = { mdl
package = pkgs.golangci-lint; mypy
}; nixfmt
hadolint = { php
package = pkgs.hadolint; pmd
}; prettierd
ktlint = { proselint
package = pkgs.ktlint; protolint
}; pylint
luacheck = { revive
package = pkgs.luaPackages.luacheck; rstcheck
}; rubocop
ltrs = { rubyfmt
package = pkgs.languagetool-rust; ruff
}; rufo
markdownlint = { rustfmt
package = pkgs.nodePackages.markdownlint-cli; rustywind
}; scalafmt
mypy = { selene
package = pkgs.mypy; semgrep
}; shellcheck
protolint = { shellharden
package = pkgs.protolint; shfmt
}; smlfmt
pylint = { sqlfluff
package = pkgs.pylint; statix
}; stylelint
revive = { stylua
pacakge = pkgs.revive; taplo
}; templ
ruff = { tfsec
package = pkgs.ruff; topiary
}; treefmt
shellcheck = { trivy
package = pkgs.shellcheck; typos
}; typstfmt
staticcheck = { uncrustify
pacakge = pkgs.go-tools; usort
}; vale
statix = { verilator
package = pkgs.statix; xmlformat
}; xq
stylelint = { yamlfmt
package = pkgs.stylelint; yamllint
}; yapf
typos = { yq
package = pkgs.typos; zprint
}; zsh
vale = { ;
package = pkgs.vale; inherit
}; (pkgs.nodePackages)
vulture = { alex
package = pkgs.python3Packages.vulture; eslint
}; eslint_d
write_good = { prettier
package = pkgs.write-good; ;
}; inherit
yamllint = { (pkgs.python3.pkgs)
package = pkgs.yamllint; autopep8
}; bandit
}; black
formatting = { docformatter
alejandra = { flake8
package = pkgs.alejandra; pycodestyle
}; pydocstyle
asmfmt = { pylama
package = pkgs.asmfmt; vulture
}; ;
astyle = { inherit
package = pkgs.astyle; (pkgs.luaPackages)
}; luacheck
bean_format = { ;
package = pkgs.beancount; inherit
}; (pkgs.haskellPackages)
beautysh = { fourmolu
package = pkgs.beautysh; ;
}; inherit
black = { (pkgs.phpPackages)
package = pkgs.python3Packages.black; phpmd
}; phpstan
cbfmt = { psalm
package = pkgs.cbfmt; ;
}; inherit
eslint = { (pkgs.rubyPackages)
package = pkgs.nodePackages.eslint; htmlbeautifier
}; ;
eslint_d = { inherit
package = pkgs.nodePackages.eslint_d; (pkgs.ocamlPackages)
}; ocamlformat
fantomas = { ;
package = pkgs.fantomas; ansiblelint = pkgs.ansible-lint;
}; bean_format = pkgs.beancount;
fnlfmt = { blackd = pkgs.black;
package = pkgs.fnlfmt; buildifier = pkgs.bazel-buildtools;
}; cabal_fmt = pkgs.haskellPackages.cabal-fmt;
fourmolu = { cfn_lint = pkgs.python3.pkgs.cfn-lint;
package = pkgs.haskellPackages.fourmolu; chktex = pkgs.texliveMedium;
}; clang_check = pkgs.clang-tools;
gofmt = { clang_format = pkgs.clang-tools;
package = pkgs.go; clj_kondo = pkgs.clj-kondo;
}; cmake_format = pkgs.cmake-format;
gofumpt = { cmake_lint = pkgs.cmake-format;
package = pkgs.gofumpt; credo = pkgs.elixir;
}; crystal_format = pkgs.crystal;
goimports = { cue_fmt = pkgs.cue;
package = pkgs.gotools; d2_fmt = pkgs.d2;
}; dart_format = pkgs.dart;
goimports_reviser = { deno_fmt = pkgs.deno;
package = pkgs.goimports-reviser; deno_lint = pkgs.deno;
}; dictionary = pkgs.curl;
golines = { dotenv_linter = pkgs.dotenv-linter;
package = pkgs.golines; editorconfig_checker = pkgs.editorconfig-checker;
}; elm_format = pkgs.elmPackages.elm-format;
google_java_format = { emacs_scheme_mode = pkgs.emacs;
package = pkgs.google-java-format; emacs_vhdl_mode = pkgs.emacs;
}; erb_format = pkgs.rubyPackages.erb-formatter;
isort = { fish_indent = pkgs.fish;
package = pkgs.isort; format_r = pkgs.R;
}; gdformat = pkgs.gdtoolkit;
jq = { gdlint = pkgs.gdtoolkit;
package = pkgs.jq; gitsigns = pkgs.git;
}; glslc = pkgs.shaderc;
ktlint = { gn_format = pkgs.gn;
package = pkgs.ktlint; gofmt = pkgs.go;
}; goimports = pkgs.gotools;
markdownlint = { goimports_reviser = pkgs.goimports-reviser;
package = pkgs.nodePackages.markdownlint-cli; golangci_lint = pkgs.golangci-lint;
}; google_java_format = pkgs.google-java-format;
nixfmt = { haml_lint = pkgs.mastodon;
package = pkgs.nixfmt; haxe_formatter = pkgs.haxe;
}; isortd = pkgs.isort;
nixpkgs_fmt = { jsonnetfmt = pkgs.jsonnet;
package = pkgs.nixpkgs-fmt; json_tool = pkgs.python3;
}; latexindent = pkgs.texliveMedium;
pint = {}; ltrs = pkgs.languagetool-rust;
phpcbf = { lua_format = pkgs.luaformatter;
package = pkgs.phpPackages.php-codesniffer; markdownlint_cli2 = pkgs.markdownlint-cli2;
}; markdownlint = pkgs.nodePackages.markdownlint-cli;
prettier = { mix = pkgs.elixir;
package = pkgs.nodePackages.prettier; nimpretty = pkgs.nim;
}; nixpkgs_fmt = pkgs.nixpkgs-fmt;
prettierd = { opacheck = pkgs.open-policy-agent;
package = pkgs.prettierd; perltidy = pkgs.perlPackages.PerlTidy;
}; pg_format = pkgs.pgformatter;
protolint = { phpcbf = pkgs.phpPackages.php-codesniffer;
package = pkgs.protolint; phpcsfixer = pkgs.phpPackages.php-cs-fixer;
}; phpcs = pkgs.phpPackages.php-codesniffer;
ruff = { prismaFmt = pkgs.nodePackages.prisma;
package = pkgs.ruff; protoc_gen_lint = pkgs.protobuf;
}; ptop = pkgs.fpc;
ruff_format = { puppet_lint = pkgs.puppet-lint;
package = pkgs.ruff; qmlformat = pkgs.qt6.qtdeclarative;
}; qmllint = pkgs.qt6.qtdeclarative;
rustfmt = { racket_fixw = pkgs.racket;
package = pkgs.rustfmt; raco_fmt = pkgs.racket;
}; rego = pkgs.open-policy-agent;
shfmt = { reorder_python_imports = pkgs.python3.pkgs.reorder-python-imports;
package = pkgs.shfmt; rpmspec = pkgs.rpm;
}; ruff_format = pkgs.ruff;
sqlfluff = { sqlformat = pkgs.python3.pkgs.sqlparse;
package = pkgs.sqlfluff; staticcheck = pkgs.go-tools;
}; stylish_haskell = pkgs.stylish-haskell;
stylelint = { surface = pkgs.elixir;
package = pkgs.stylelint; swift_format = pkgs.swift-format;
}; teal = pkgs.luaPackages.tl;
stylua = { terraform_fmt = pkgs.terraform;
package = pkgs.stylua; terraform_validate = pkgs.terraform;
}; tidy = pkgs.html-tidy;
taplo = { trim_newlines = pkgs.gawk;
package = pkgs.taplo; trim_whitespace = pkgs.gawk;
}; tsc = pkgs.typescript;
trim_newlines = {}; verible_verilog_format = pkgs.verible;
trim_whitespace = {}; vfmt = pkgs.vlang;
}; vint = pkgs.vim-vint;
}; write_good = pkgs.write-good;
# Format the servers to be an array of attrs like the following example xmllint = pkgs.libxml2.bin;
# [{ zigfmt = pkgs.zig;
# name = "prettier";
# sourceType = "formatting"; # Sources not present in nixpkgs
# packages = [...]; blade_formatter = null;
# }] blue = null;
serverDataFormatted = brittany = null;
mapAttrsToList bsfmt = null;
( bslint = null;
sourceType: cljstyle = null;
mapAttrsToList cueimports = null;
( curlylint = null;
name: attrs: dtsfmt = null;
attrs erb_lint = null;
// { fixjson = null;
inherit sourceType name; forge_fmt = null;
} gccdiag = null;
) gersemi = null;
) gospel = null;
serverData; jshint = null;
dataFlattened = flatten serverDataFormatted; 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;
};
# 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 { in {
imports = imports = [
(map cmpHelpers.mkServer dataFlattened)
++ [
./prettier.nix ./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`"
)
]; ];
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 config = let
cfg = config.plugins.none-ls; cfg = config.plugins.none-ls;
gitsignsEnabled = cfg.sources.code_actions.gitsigns.enable; 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 in
mkIf cfg.enable { 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; 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; inherit pkgs lib helpers;
config = {}; config = {};
}; };
nonels-sources-options = import ../plugins/none-ls/servers.nix {
inherit pkgs lib helpers;
config = {};
};
}; };
inherit namespace; inherit namespace;
}) })

View file

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