feat(nix): indentation queries

This commit is contained in:
Riley Bruins 2024-03-31 09:20:18 -07:00 committed by Christian Clason
parent ee29084ce6
commit 55a13862cd
4 changed files with 379 additions and 0 deletions

75
queries/nix/indents.scm Normal file
View file

@ -0,0 +1,75 @@
[
(list_expression)
(indented_string_expression)
(let_expression)
(if_expression)
(binding)
(parenthesized_expression)
] @indent.begin
((attrset_expression) @indent.begin
(#not-has-parent? @indent.begin if_expression))
((rec_attrset_expression) @indent.begin
(#not-has-parent? @indent.begin if_expression))
((binding
"=" @indent.begin)
(#set! indent.immediate 1))
(binding
";" @indent.end)
(parenthesized_expression
")" @indent.branch @indent.end)
(attrset_expression
"}" @indent.branch @indent.end)
(rec_attrset_expression
"}" @indent.branch @indent.end)
(list_expression
"]" @indent.branch @indent.dedent)
(indented_string_expression
"''" @indent.branch @indent.end .)
[
"else"
"in"
] @indent.branch
(let_expression
body: (_) @indent.end @indent.dedent)
(string_fragment) @indent.ignore @indent.auto
(if_expression
condition: (_) @indent.auto)
alternative: (if_expression) @indent.dedent
(interpolation) @indent.begin @indent.dedent
(interpolation
"}" @indent.end @indent.branch)
(ERROR
"then" @indent.begin)
(ERROR
"then"
.
(formals) @indent.begin)
(ERROR
"then"
.
(formals
"}" @indent.branch @indent.end))
(ERROR
"let") @indent.begin
(comment) @indent.ignore

134
tests/indent/nix/conds.nix Normal file
View file

@ -0,0 +1,134 @@
{ lib }:
with lib.lists;
with lib.types;
with lib.attrsets;
with lib.strings; {
doubleFromSystem = { cpu, kernel, abi, ... }:
if abi == abis.cygnus then
"${cpu.name}-cygwin"
else if kernel.families ? darwin then
"${cpu.name}-darwin"
else
"${cpu.name}-${kernelName kernel}";
tripleFromSystem = { cpu, vendor, kernel, abi, ... }@sys:
assert isSystem sys;
let
optExecFormat = lib.optionalString (kernel.name == "netbsd"
&& gnuNetBSDDefaultExecFormat cpu != kernel.execFormat)
kernel.execFormat.name;
optAbi = lib.optionalString (abi != abis.unknown) "-${abi.name}";
in "${cpu.name}-${vendor.name}-${
kernelName kernel
}${optExecFormat}${optAbi}";
mkSystemFromSkeleton = { cpu,
# Optional, but fallback too complex for here.
# Inferred below instead.
vendor ? assert false; null, kernel,
# Also inferred below
abi ? assert false; null, }@args:
let
getCpu = name: cpuTypes.${name} or (throw "Unknown CPU type: ${name}");
getVendor = name: vendors.${name} or (throw "Unknown vendor: ${name}");
getKernel = name: kernels.${name} or (throw "Unknown kernel: ${name}");
getAbi = name: abis.${name} or (throw "Unknown ABI: ${name}");
parsed = {
cpu = getCpu args.cpu;
vendor = if args ? vendor then
getVendor args.vendor
else if isDarwin parsed then
vendors.apple
else if isWindows parsed then
vendors.pc
else
vendors.unknown;
kernel = if hasPrefix "darwin" args.kernel then
getKernel "darwin"
else if hasPrefix "netbsd" args.kernel then
getKernel "netbsd"
else
getKernel args.kernel;
abi = if args ? abi then
getAbi args.abi
else if isLinux parsed || isWindows parsed then
if isAarch32 parsed then
if lib.versionAtLeast (parsed.cpu.version or "0") "6" then
abis.gnueabihf
else
abis.gnueabi
else if isPower64 parsed && isBigEndian parsed then
abis.gnuabielfv2
else
abis.gnu
else
abis.unknown;
};
in mkSystem parsed;
mkSkeletonFromList = l:
{
"1" = if elemAt l 0 == "avr" then {
cpu = elemAt l 0;
kernel = "none";
abi = "unknown";
} else
throw "Target specification with 1 components is ambiguous";
"2" = # We only do 2-part hacks for things Nix already supports
if elemAt l 1 == "cygwin" then {
cpu = elemAt l 0;
kernel = "windows";
abi = "cygnus";
} else if elemAt l 1 == "windows" then {
cpu = elemAt l 0;
kernel = "windows";
abi = "msvc";
} else if (elemAt l 1) == "elf" then {
cpu = elemAt l 0;
vendor = "unknown";
kernel = "none";
abi = elemAt l 1;
} else {
cpu = elemAt l 0;
kernel = elemAt l 1;
};
"3" =
# cpu-kernel-environment
if elemAt l 1 == "linux"
|| elem (elemAt l 2) [ "eabi" "eabihf" "elf" "gnu" ] then {
cpu = elemAt l 0;
kernel = elemAt l 1;
abi = elemAt l 2;
vendor = "unknown";
} else if elemAt l 1 == "apple"
|| elem (elemAt l 2) [ "wasi" "redox" "mmixware" "ghcjs" "mingw32" ]
|| hasPrefix "freebsd" (elemAt l 2) || hasPrefix "netbsd" (elemAt l 2)
|| hasPrefix "genode" (elemAt l 2) then {
cpu = elemAt l 0;
vendor = elemAt l 1;
kernel = if elemAt l 2 == "mingw32" then
"windows" # autotools breaks on -gnu for window
else
elemAt l 2;
} else
throw "Target specification with 3 components is ambiguous";
"4" = {
cpu = elemAt l 0;
vendor = elemAt l 1;
kernel = elemAt l 2;
abi = elemAt l 3;
};
}.${toString (length l)} or (throw
"system string has invalid number of hyphen-separated components");
# GNU build systems assume that older NetBSD architectures are using a.out.
gnuNetBSDDefaultExecFormat = cpu:
if (cpu.family == "arm" && cpu.bits == 32)
|| (cpu.family == "sparc" && cpu.bits == 32)
|| (cpu.family == "m68k" && cpu.bits == 32)
|| (cpu.family == "x86" && cpu.bits == 32) then
execFormats.aout
else
execFormats.elf;
}

View file

@ -0,0 +1,130 @@
{ lib }:
with lib.lists;
with lib.types;
with lib.attrsets;
with lib.strings;
with (import ./inspect.nix { inherit lib; }).predicates;
let
inherit (lib.options) mergeOneOption;
setTypes = type:
mapAttrs (name: value:
assert type.check value;
setType type.name ({ inherit name; } // value));
in rec {
################################################################################
types.openSignificantByte = mkOptionType {
name = "significant-byte";
description = "Endianness";
merge = mergeOneOption;
};
types.significantByte = enum (attrValues significantBytes);
significantBytes = setTypes types.openSignificantByte {
bigEndian = { };
littleEndian = { };
};
################################################################################
# Reasonable power of 2
types.bitWidth = enum [ 8 16 32 64 128 ];
################################################################################
types.openCpuType = mkOptionType {
name = "cpu-type";
description = "instruction set architecture name and information";
merge = mergeOneOption;
check = x:
types.bitWidth.check x.bits && (if 8 < x.bits then
types.significantByte.check x.significantByte
else
!(x ? significantByte));
};
types.cpuType = enum (attrValues cpuTypes);
cpuTypes = with significantBytes;
setTypes types.openCpuType {
arm = {
bits = 32;
significantByte = littleEndian;
family = "arm";
};
armv5tel = {
bits = 32;
significantByte = littleEndian;
family = "arm";
version = "5";
arch = "armv5t";
};
};
isCompatible = a: b:
with cpuTypes;
lib.any lib.id [
# x86
(b == i386 && isCompatible a i486)
(b == i486 && isCompatible a i586)
(b == i586 && isCompatible a i686)
# ARMv6
(b == armv6l && isCompatible a armv6m)
(b == armv6m && isCompatible a armv7l)
];
################################################################################
types.openVendor = mkOptionType {
name = "vendor";
description = "vendor for the platform";
merge = mergeOneOption;
};
abis = setTypes types.openAbi {
cygnus = { };
msvc = { };
# Other architectures should use ELF in embedded situations.
elf = { };
androideabi = { };
android = {
assertions = [{
assertion = platform: !platform.isAarch32;
message = ''
The "android" ABI is not for 32-bit ARM. Use "androideabi" instead.
'';
}];
};
};
################################################################################
types.parsedPlatform = mkOptionType {
name = "system";
description =
"fully parsed representation of llvm- or nix-style platform tuple";
merge = mergeOneOption;
check = { cpu, vendor, kernel, abi, }:
types.cpuType.check cpu && types.vendor.check vendor
&& types.kernel.check kernel && types.abi.check abi;
};
isSystem = isType "system";
mkSystem = components:
assert types.parsedPlatform.check components;
setType "system" components;
mkSystemFromString = s:
mkSystemFromSkeleton (mkSkeletonFromList (lib.splitString "-" s));
################################################################################
}

40
tests/indent/nix_spec.lua Normal file
View file

@ -0,0 +1,40 @@
local Runner = require("tests.indent.common").Runner
local runner = Runner:new(it, "tests/indent/nix", {
tabstop = 2,
shiftwidth = 2,
softtabstop = 2,
expandtab = true,
})
describe("indent Nix:", function()
describe("whole file:", function()
runner:whole_file(".", {
expected_failures = {},
})
end)
describe("new line:", function()
for _, info in ipairs {
{ 14, 2 },
{ 16, 2 },
{ 48, 4 },
{ 112, 6 },
} do
runner:new_line("general.nix", { on_line = info[1], text = "x = 1;", indent = info[2] })
end
for _, info in ipairs {
{ 115, 6 },
{ 113, 10 },
{ 6, 4 },
{ 12, 2 },
{ 16, 6 },
{ 35, 6 },
{ 23, 2 },
{ 21, 6 },
} do
runner:new_line("conds.nix", { on_line = info[1], text = "x = 1;", indent = info[2] })
end
end)
end)