nix-community.nixvim/plugins/lsp/language-servers/rust-analyzer-config.nix

168 lines
4.6 KiB
Nix
Raw Normal View History

lib: pkgs:
# Future improvements:
# - extra documentation from anyOf types, they can have `enumDescriptions` that are valuable
2024-05-05 19:39:35 +02:00
with lib;
let
packageJson = "${pkgs.rust-analyzer.src}/editors/code/package.json";
2024-05-05 19:39:35 +02:00
options = (trivial.importJSON packageJson).contributes.configuration.properties;
packageJsonTxt = strings.splitString "\n" (builtins.readFile packageJson);
2024-05-05 19:39:35 +02:00
vscodeStart = lists.findFirstIndex (
x: x == " \"configuration\": {"
) (throw "no configuration") packageJsonTxt;
vscodeEnd =
lists.findFirstIndex (strings.hasInfix "generated-start") (throw "no generated start")
2024-05-05 19:39:35 +02:00
packageJsonTxt;
vscodeOptions = lists.sublist vscodeStart (vscodeEnd - vscodeStart) packageJsonTxt;
2024-05-05 19:39:35 +02:00
vscodeOptionNames = builtins.map (
x: strings.removeSuffix "\": {" (strings.removePrefix " \"" x)
) (lists.filter (strings.hasPrefix " \"rust-analyzer.") vscodeOptions);
2024-05-05 19:39:35 +02:00
rustAnalyzerOptions = builtins.removeAttrs options (
vscodeOptionNames
++ [
"\$generated-start"
"\$generated-end"
]
);
nullType = mkOptionType {
name = "nullType";
description = "null";
descriptionClass = "noun";
merge = mergeEqualOption;
check = e: e == null;
};
2024-05-05 19:39:35 +02:00
mkRustAnalyzerType =
opt:
{
type,
enum ? null,
minimum ? null,
maximum ? null,
items ? null,
anyOf ? null,
uniqueItems ? null,
# unused, but for exhaustivness
enumDescriptions ? null,
}@def:
if enum != null then
types.enum enum
else if anyOf != null then
types.oneOf (builtins.map (mkRustAnalyzerType opt) anyOf)
else if builtins.isList type then
if builtins.length type == 2 && builtins.head type == "null" then
types.nullOr (mkRustAnalyzerType opt (def // { type = builtins.elemAt type 1; }))
else
types.oneOf (builtins.map (t: mkRustAnalyzerType opt (def // { type = t; })) type)
else if type == "boolean" then
types.bool
else if type == "object" then
types.attrsOf types.anything
else if type == "string" then
types.str
else if type == "null" then
nullType
else if type == "array" then
types.listOf (
2024-05-05 19:39:35 +02:00
mkRustAnalyzerType "${opt}-items" (
if items == null then throw "null items with array type (in ${opt})" else items
)
)
2024-05-05 19:39:35 +02:00
else if type == "number" then
if minimum != null && maximum != null then
types.numbers.between minimum maximum
else if minimum != null then
types.addCheck types.number (x: x >= minimum)
else if maximum != null then
types.addCheck types.number (x: x <= maximum)
else
types.number
else if type == "integer" then
if minimum != null && maximum != null then
types.ints.between minimum maximum
else if minimum != null then
types.addCheck types.int (x: x >= minimum)
else if maximum != null then
types.addCheck types.int (x: x <= maximum)
else
types.int
else
throw "unhandled type `${builtins.toJSON type}` (in ${opt})";
2024-05-05 19:39:35 +02:00
mkRustAnalyzerOption =
opt:
{
default,
markdownDescription,
type ? null,
anyOf ? null,
# Enum types
enum ? null,
enumDescriptions ? null,
# Int types
minimum ? null,
maximum ? null,
# List types
items ? null,
uniqueItems ? false,
}:
mkOption {
2024-05-05 19:39:35 +02:00
type = types.nullOr (
mkRustAnalyzerType opt {
inherit
type
enum
minimum
maximum
items
anyOf
uniqueItems
;
}
);
default = null;
description =
2024-05-05 19:39:35 +02:00
if enum != null then
let
valueDesc = builtins.map ({ fst, snd }: ''- ${fst}: ${snd}'') (
lists.zipLists enum enumDescriptions
);
in
''
${markdownDescription}
2024-05-05 19:39:35 +02:00
Values:
${builtins.concatStringsSep "\n" valueDesc}
2024-05-05 19:39:35 +02:00
```nix
${generators.toPretty { } default}
```
''
else
''
${markdownDescription}
2024-05-05 19:39:35 +02:00
default:
```nix
${generators.toPretty { } default}
```
'';
};
nixOptions = builtins.mapAttrs mkRustAnalyzerOption rustAnalyzerOptions;
2024-05-05 19:39:35 +02:00
nestOpt =
opt: value:
let
parts = strings.splitString "." opt;
in
builtins.foldl' (current: segment: { ${segment} = current; }) value (lists.reverseList parts);
nestedNixOptions = attrsets.mapAttrsToList nestOpt nixOptions;
in
2024-05-05 19:39:35 +02:00
(builtins.foldl' attrsets.recursiveUpdate { } nestedNixOptions).rust-analyzer