nix-lang-0.1.0.0: test/RFCPrint.hs
{-# LANGUAGE EmptyCase #-}
module RFCPrint where
import qualified Data.Text as T
import Nix.Lang.Parser (nixExpr, runNixParser)
import Nix.Lang.RFCPrint (formatExpr, formatExprWithHints)
import Nix.Lang.RFCPrint.LayoutHints
import Nix.Lang.Types
import Nix.Lang.Types.Syn
import System.Exit (ExitCode (..))
import System.Process (readProcessWithExitCode)
import Test.Tasty
import Test.Tasty.HUnit
import Text.Megaparsec (eof, errorBundlePretty)
import Utils (parseExprOrFail, parseFileOrFail)
tests :: TestTree
tests =
testGroup
"rfc print"
[ testGroup
"precedence and parentheses"
[ testCase "formats application argument with required parentheses" applicationArgumentParens,
testCase "formats application chains" applicationChainFormatting,
testCase "formats binary precedence correctly" binaryPrecedence,
testCase "formats right associative concat" concatAssociativity,
testCase "formats right associative updates" updateAssociativity,
testCase "formats right associative implication" implicationAssociativity,
testCase "formats non associative equality with parentheses" equalityParens,
testCase "formats select default without losing precedence" selectDefaultFormatting,
testCase "formats inherit scope with parentheses" inheritScopeParens
],
testGroup
"containers and bindings"
[ testCase "formats empty list" emptyListFormatting,
testCase "formats empty set" emptySetFormatting,
testCase "formats empty recursive set" emptyRecSetFormatting,
testCase "formats empty let" emptyLetFormatting,
testCase "formats long lists multiline" longListFormatting,
testCase "formats multiline inherit bindings" inheritManyFormatting,
testCase "formats multiline inherit-from bindings" inheritFromManyFormatting,
testCase "formats nested set binding values multiline" nestedSetBindingFormatting,
testCase "formats let binding values multiline" letValueBindingFormatting,
testCase "formats empty set-pattern lambdas with spaced braces" emptySetPatternFormatting,
testCase "formats ellipsis-only set-pattern lambdas with spaced braces" ellipsisOnlySetPatternFormatting,
testCase "formats simple set-pattern lambdas multiline with trailing commas" simpleSetPatternFormatting,
testCase "formats set recursively" recursiveSetFormatting,
testCase "formats let expression multiline" letFormatting,
testCase "formats lambda set pattern" lambdaSetPatternFormatting
],
testGroup
"keyword expressions"
[ testCase "formats with expression inline when compact" withFormatting,
testCase "formats with attrset body multiline" withAttrsetFormatting,
testCase "formats assert expression multiline" assertFormatting,
testCase "formats assert attrset body multiline" assertAttrsetFormatting,
testCase "formats if expression inline when compact" ifFormatting,
testCase "formats else-if chains without indentation creep" elseIfFormatting
],
testGroup
"application layout"
[ testCase "formats attrset application arguments multiline" applicationAttrsetFormatting,
testCase "formats let application arguments multiline" applicationLetFormatting
],
testGroup
"strings and reparsing"
[ testCase "formats strings and reparses" stringFormatting
],
testGroup
"nixfmt fixed point"
[ testCase "nixfmt is no-op for fresh Syn output" nixfmtIsNoOp
],
testGroup
"layout hints"
[ testCase "collects multiline list hint from parsed source" collectsMultilineListHint,
testCase "parsed source can preserve inline list layout with hints" preservesInlineListWithHints,
testCase "parsed source can preserve inline let layout with hints" preservesInlineLetWithHints,
testCase "parsed source can preserve inline interpolation list layout with hints" preservesInlineInterpolationListWithHints,
testCase "parsed source can preserve inline path interpolation list layout with hints" preservesInlinePathInterpolationListWithHints,
testCase "parsed source can preserve root leading comments canonically" preservesRootLeadingCommentsWithHints,
testCase "parsed source can preserve root trailing comments canonically" preservesRootTrailingCommentsWithHints,
testCase "parsed source can preserve multiple root comments with blank lines canonically" preservesMultipleRootCommentsWithBlankLinesWithHints,
testCase "parsed source can preserve nested set comments canonically" preservesNestedSetCommentsWithHints,
testCase "parsed source can preserve blank line before nested binding comments canonically" preservesNestedBlankLineCommentsWithHints,
testCase "parsed source can preserve blank line before second binding comment canonically" preservesSecondBindingBlankLineCommentsWithHints,
testCase "parsed source can preserve inherit-binding comments canonically" preservesInheritBindingCommentsWithHints
]
]
assertFormatsTo :: Expr -> String -> Assertion
assertFormatsTo expr expected = formatExpr expr @?= T.pack expected
assertRoundtrips :: Expr -> Assertion
assertRoundtrips expr = do
let rendered = formatExpr expr
case runNixParser (nixExpr <* eof) "<rfc>" rendered of
(Right actual, _) -> show (stripParensExpr (lowerParsedExpr actual)) @?= show (stripParensExpr expr)
(Left err, _) -> assertFailure (errorBundlePretty err)
assertNixfmtFixedPoint :: Expr -> Assertion
assertNixfmtFixedPoint expr = do
let rendered = T.unpack (formatExpr expr) <> "\n"
(exitCode, stdout, stderr) <- readProcessWithExitCode "nixfmt" [] rendered
case exitCode of
ExitSuccess -> stdout @?= rendered
ExitFailure code -> assertFailure $ unlines ["nixfmt failed with exit code " <> show code, stderr]
applicationArgumentParens :: Assertion
applicationArgumentParens = do
let expr = mkApp (mkVar "f") (mkBinApp OpAdd (mkInt 1) (mkInt 2))
assertFormatsTo expr "f (1 + 2)"
assertRoundtrips expr
applicationChainFormatting :: Assertion
applicationChainFormatting = do
let expr = mkApp (mkApp (mkVar "f") (mkVar "x")) (mkVar "y")
assertFormatsTo expr "f x y"
assertRoundtrips expr
binaryPrecedence :: Assertion
binaryPrecedence = do
let expr = mkBinApp OpMul (mkPar (mkBinApp OpAdd (mkInt 1) (mkInt 2))) (mkInt 3)
assertFormatsTo expr "(1 + 2) * 3"
assertRoundtrips expr
concatAssociativity :: Assertion
concatAssociativity = do
let expr = mkBinApp OpConcat (mkVar "a") (mkBinApp OpConcat (mkVar "b") (mkVar "c"))
assertFormatsTo expr "a ++ b ++ c"
assertRoundtrips expr
updateAssociativity :: Assertion
updateAssociativity = do
let expr = mkBinApp OpUpdate (mkVar "a") (mkBinApp OpUpdate (mkVar "b") (mkVar "c"))
assertFormatsTo expr "a // b // c"
assertRoundtrips expr
implicationAssociativity :: Assertion
implicationAssociativity = do
let expr = mkBinApp OpImpl (mkVar "a") (mkBinApp OpImpl (mkVar "b") (mkVar "c"))
assertFormatsTo expr "a -> b -> c"
assertRoundtrips expr
equalityParens :: Assertion
equalityParens = do
let expr = mkBinApp OpEq (mkVar "a") (mkPar (mkBinApp OpEq (mkVar "b") (mkVar "c")))
assertFormatsTo expr "a == (b == c)"
assertRoundtrips expr
inheritScopeParens :: Assertion
inheritScopeParens = do
let expr = mkSet [mkInheritFrom (mkIf (mkVar "cond") (mkVar "pkg") (mkVar "fallback")) ["name"]]
assertFormatsTo expr "{\n inherit (if cond then pkg else fallback) name;\n}"
assertRoundtrips expr
emptyListFormatting :: Assertion
emptyListFormatting = do
let expr = mkList []
assertFormatsTo expr "[ ]"
assertRoundtrips expr
emptySetFormatting :: Assertion
emptySetFormatting = do
let expr = mkSet []
assertFormatsTo expr "{ }"
assertRoundtrips expr
emptyRecSetFormatting :: Assertion
emptyRecSetFormatting = do
let expr = mkRecSet []
assertFormatsTo expr "rec { }"
assertRoundtrips expr
emptyLetFormatting :: Assertion
emptyLetFormatting = do
let expr = mkLet [] (mkVar "x")
assertFormatsTo expr "let\nin\nx"
assertRoundtrips expr
longListFormatting :: Assertion
longListFormatting = do
let expr = mkList [mkInt 1, mkInt 2, mkInt 3, mkInt 4, mkInt 5]
assertFormatsTo expr "[\n 1\n 2\n 3\n 4\n 5\n]"
assertRoundtrips expr
inheritManyFormatting :: Assertion
inheritManyFormatting = do
let keys = map mkAttr ["a", "b", "c", "d"]
expr = mkSet [mkInheritKeys keys]
assertFormatsTo expr "{\n inherit\n a\n b\n c\n d\n ;\n}"
assertRoundtrips expr
inheritFromManyFormatting :: Assertion
inheritFromManyFormatting = do
let keys = map mkAttr ["a", "b", "c", "d"]
expr = mkSet [mkInheritFromKeys (mkVar "pkgs") keys]
assertFormatsTo expr "{\n inherit (pkgs)\n a\n b\n c\n d\n ;\n}"
assertRoundtrips expr
nestedSetBindingFormatting :: Assertion
nestedSetBindingFormatting = do
let expr = mkSet [mkBinding ["x"] (mkSet [mkBinding ["a"] (mkInt 1), mkBinding ["b"] (mkInt 2)])]
assertFormatsTo expr "{\n x = {\n a = 1;\n b = 2;\n };\n}"
assertRoundtrips expr
letValueBindingFormatting :: Assertion
letValueBindingFormatting = do
let expr = mkSet [mkBinding ["x"] (mkLet [mkBinding ["a"] (mkInt 1)] (mkVar "a"))]
assertFormatsTo expr "{\n x =\n let\n a = 1;\n in\n a;\n}"
assertRoundtrips expr
emptySetPatternFormatting :: Assertion
emptySetPatternFormatting = do
let expr = mkLam (mkSetPat NixSetPatNotEllipses Nothing []) (mkVar "body")
assertFormatsTo expr "{ }: body"
assertRoundtrips expr
ellipsisOnlySetPatternFormatting :: Assertion
ellipsisOnlySetPatternFormatting = do
let expr = mkLam (mkSetPat NixSetPatIsEllipses Nothing []) (mkVar "body")
assertFormatsTo expr "{ ... }: body"
assertRoundtrips expr
simpleSetPatternFormatting :: Assertion
simpleSetPatternFormatting = do
let pat = mkSetPat NixSetPatNotEllipses Nothing [mkSetPatBinding "a" Nothing, mkSetPatBinding "b" (Just (mkInt 1))]
expr = mkLam pat (mkVar "body")
assertFormatsTo expr "{\n a,\n b ? 1,\n}:\nbody"
assertRoundtrips expr
recursiveSetFormatting :: Assertion
recursiveSetFormatting = do
let expr = mkRecSet [mkBinding ["a"] (mkInt 1), mkBinding ["b"] (mkList [mkInt 1, mkInt 2])]
assertFormatsTo expr "rec {\n a = 1;\n b = [\n 1\n 2\n ];\n}"
assertRoundtrips expr
letFormatting :: Assertion
letFormatting = do
let expr = mkLet [mkBinding ["a"] (mkInt 1), mkBinding ["b"] (mkVar "a")] (mkVar "b")
assertFormatsTo expr "let\n a = 1;\n b = a;\nin\nb"
assertRoundtrips expr
selectDefaultFormatting :: Assertion
selectDefaultFormatting = do
let expr = mkApp (mkVar "f") (mkSelectOrAttrs (mkVar "cfg") ["a", "b"] (mkIf (mkVar "cond") (mkInt 1) (mkInt 2)))
assertFormatsTo expr "f (cfg.a.b or (if cond then 1 else 2))"
assertRoundtrips expr
stringFormatting :: Assertion
stringFormatting = do
let expr = mkText "a\n${b}\""
assertFormatsTo expr "\"a\\n\\${b}\\\"\""
_ <- parseExprOrFail (formatExpr expr)
pure ()
lambdaSetPatternFormatting :: Assertion
lambdaSetPatternFormatting = do
let pat = mkSetPat NixSetPatIsEllipses (Just (mkSetPatAs NixSetPatAsLeading "args")) [mkSetPatBinding "x" Nothing, mkSetPatBinding "y" (Just (mkInt 1))]
expr = mkLam pat (mkVar "x")
assertFormatsTo expr "args@{\n x,\n y ? 1,\n ...\n}:\nx"
assertRoundtrips expr
applicationAttrsetFormatting :: Assertion
applicationAttrsetFormatting = do
let attrset = mkSet [mkBinding ["a"] (mkInt 1), mkBinding ["b"] (mkInt 2)]
expr = mkApp (mkApp (mkVar "f") attrset) (mkVar "x")
assertFormatsTo expr "f {\n a = 1;\n b = 2;\n} x"
assertRoundtrips expr
applicationLetFormatting :: Assertion
applicationLetFormatting = do
let letExpr = mkLet [mkBinding ["a"] (mkInt 1)] (mkVar "a")
expr = mkApp (mkApp (mkVar "f") letExpr) (mkVar "z")
assertFormatsTo expr "f (\n let\n a = 1;\n in\n a\n) z"
assertRoundtrips expr
withFormatting :: Assertion
withFormatting = do
let expr = mkWith (mkVar "pkgs") (mkApp (mkVar "callPackage") (mkVar "drv"))
assertFormatsTo expr "with pkgs; callPackage drv"
assertRoundtrips expr
withAttrsetFormatting :: Assertion
withAttrsetFormatting = do
let body = mkSet [mkBinding ["a"] (mkInt 1), mkBinding ["b"] (mkInt 2)]
expr = mkWith (mkVar "pkgs") body
assertFormatsTo expr "with pkgs;\n{\n a = 1;\n b = 2;\n}"
assertRoundtrips expr
assertFormatting :: Assertion
assertFormatting = do
let expr = mkAssert (mkVar "cond") (mkApp (mkVar "f") (mkVar "x"))
assertFormatsTo expr "assert cond;\nf x"
assertRoundtrips expr
assertAttrsetFormatting :: Assertion
assertAttrsetFormatting = do
let body = mkSet [mkBinding ["a"] (mkInt 1), mkBinding ["b"] (mkInt 2)]
expr = mkAssert (mkVar "cond") body
assertFormatsTo expr "assert cond;\n{\n a = 1;\n b = 2;\n}"
assertRoundtrips expr
ifFormatting :: Assertion
ifFormatting = do
let expr = mkIf (mkVar "cond") (mkVar "yes") (mkVar "no")
assertFormatsTo expr "if cond then yes else no"
assertRoundtrips expr
elseIfFormatting :: Assertion
elseIfFormatting = do
let expr = mkIf (mkVar "a") (mkVar "b") (mkIf (mkVar "c") (mkVar "d") (mkVar "e"))
assertFormatsTo expr "if a then\n b\nelse if c then\n d\nelse\n e"
assertRoundtrips expr
nixfmtIsNoOp :: Assertion
nixfmtIsNoOp = mapM_ assertNixfmtFixedPoint examples
where
examples =
[ mkInt 1,
mkList [],
mkSet [],
mkRecSet [],
mkList [mkInt 1, mkInt 2, mkInt 3, mkInt 4, mkInt 5],
mkApp (mkVar "f") (mkBinApp OpAdd (mkInt 1) (mkInt 2)),
mkApp (mkApp (mkVar "f") (mkVar "x")) (mkVar "y"),
mkApp (mkApp (mkVar "f") (mkSet [mkBinding ["a"] (mkInt 1), mkBinding ["b"] (mkInt 2)])) (mkVar "x"),
mkApp (mkApp (mkVar "f") (mkLet [mkBinding ["a"] (mkInt 1)] (mkVar "a"))) (mkVar "z"),
mkBinApp OpUpdate (mkVar "a") (mkBinApp OpUpdate (mkVar "b") (mkVar "c")),
mkBinApp OpImpl (mkVar "a") (mkBinApp OpImpl (mkVar "b") (mkVar "c")),
mkSet [mkInheritKeys (map mkAttr ["a", "b", "c", "d"])],
mkSet [mkInheritFromKeys (mkVar "pkgs") (map mkAttr ["a", "b", "c", "d"])],
mkSet [mkBinding ["x"] (mkSet [mkBinding ["a"] (mkInt 1), mkBinding ["b"] (mkInt 2)])],
mkSet [mkBinding ["x"] (mkLet [mkBinding ["a"] (mkInt 1)] (mkVar "a"))],
mkRecSet [mkBinding ["a"] (mkInt 1), mkBinding ["b"] (mkList [mkInt 1, mkInt 2])],
mkLet [] (mkVar "x"),
mkLet [mkBinding ["a"] (mkInt 1), mkBinding ["b"] (mkVar "a")] (mkVar "b"),
mkLam (mkSetPat NixSetPatNotEllipses Nothing []) (mkVar "body"),
mkLam (mkSetPat NixSetPatIsEllipses Nothing []) (mkVar "body"),
mkLam (mkSetPat NixSetPatNotEllipses Nothing [mkSetPatBinding "a" Nothing, mkSetPatBinding "b" (Just (mkInt 1))]) (mkVar "body"),
mkApp (mkVar "f") (mkSelectOrAttrs (mkVar "cfg") ["a", "b"] (mkIf (mkVar "cond") (mkInt 1) (mkInt 2))),
mkLam (mkSetPat NixSetPatIsEllipses (Just (mkSetPatAs NixSetPatAsLeading "args")) [mkSetPatBinding "x" Nothing, mkSetPatBinding "y" (Just (mkInt 1))]) (mkVar "x"),
mkSet [mkInheritFrom (mkIf (mkVar "cond") (mkVar "pkg") (mkVar "fallback")) ["name"]],
mkWith (mkVar "pkgs") (mkApp (mkVar "callPackage") (mkVar "drv")),
mkWith (mkVar "pkgs") (mkSet [mkBinding ["a"] (mkInt 1), mkBinding ["b"] (mkInt 2)]),
mkAssert (mkVar "cond") (mkApp (mkVar "f") (mkVar "x")),
mkAssert (mkVar "cond") (mkSet [mkBinding ["a"] (mkInt 1), mkBinding ["b"] (mkInt 2)]),
mkIf (mkVar "a") (mkVar "b") (mkIf (mkVar "c") (mkVar "d") (mkVar "e"))
]
collectsMultilineListHint :: Assertion
collectsMultilineListHint = do
parsed <- parseExprOrFail "[\n 1\n 2\n]"
let hints = collectLayoutHints parsed
lookupLayoutHint [] hints @?= Just (LayoutHint (Just PreferMultiline) [] [])
preservesInlineListWithHints :: Assertion
preservesInlineListWithHints = do
parsed <- parseExprOrFail "[ 1 2 ]"
let (expr, hints) = fromParsedExpr parsed
formatExprWithHints hints expr @?= "[ 1 2 ]"
preservesInlineLetWithHints :: Assertion
preservesInlineLetWithHints = do
parsed <- parseExprOrFail "let a = 1; b = a; in b"
let (expr, hints) = fromParsedExpr parsed
formatExprWithHints hints expr @?= "let a = 1; b = a; in b"
preservesInlineInterpolationListWithHints :: Assertion
preservesInlineInterpolationListWithHints = do
parsed <- parseExprOrFail "\"${[ 1 2 ]}\""
let (expr, hints) = fromParsedExpr parsed
formatExprWithHints hints expr @?= "\"${[ 1 2 ]}\""
preservesInlinePathInterpolationListWithHints :: Assertion
preservesInlinePathInterpolationListWithHints = do
parsed <- parseExprOrFail "./${[ 1 2 ]}"
let (expr, hints) = fromParsedExpr parsed
formatExprWithHints hints expr @?= "./${[ 1 2 ]}"
preservesRootLeadingCommentsWithHints :: Assertion
preservesRootLeadingCommentsWithHints = do
parsed <- parseFileOrFail "<comments>" "# hello\n1"
let (expr, hints) = fromParsedExpr parsed
formatExprWithHints hints expr @?= "# hello\n1"
preservesRootTrailingCommentsWithHints :: Assertion
preservesRootTrailingCommentsWithHints = do
parsed <- parseFileOrFail "<comments>" "1\n# bye"
let (expr, hints) = fromParsedExpr parsed
formatExprWithHints hints expr @?= "1\n# bye"
preservesMultipleRootCommentsWithBlankLinesWithHints :: Assertion
preservesMultipleRootCommentsWithBlankLinesWithHints = do
parsed <- parseFileOrFail "<comments>" "# first\n\n# second\n1"
let (expr, hints) = fromParsedExpr parsed
lookupLayoutHint [] hints
@?= Just
( LayoutHint
Nothing
[CanonicalLineComment " first", CanonicalBlankLine, CanonicalLineComment " second"]
[]
)
formatExprWithHints hints expr @?= "# first\n\n# second\n1"
preservesNestedSetCommentsWithHints :: Assertion
preservesNestedSetCommentsWithHints = do
parsed <- parseFileOrFail "<comments>" "{\n # before x\n x = 1;\n}"
let (expr, hints) = fromParsedExpr parsed
lookupLayoutHint [0] hints @?= Nothing
lookupLayoutHint [0, 0] hints
@?= Just
( LayoutHint
Nothing
[CanonicalLineComment " before x"]
[]
)
formatExprWithHints hints expr @?= "{\n # before x\n x = 1;\n}"
preservesNestedBlankLineCommentsWithHints :: Assertion
preservesNestedBlankLineCommentsWithHints = do
parsed <- parseFileOrFail "<comments>" "{\n\n # before x\n x = 1;\n}"
let (expr, hints) = fromParsedExpr parsed
lookupLayoutHint [0] hints @?= Nothing
lookupLayoutHint [0, 0] hints
@?= Just
( LayoutHint
Nothing
[CanonicalBlankLine, CanonicalLineComment " before x"]
[]
)
formatExprWithHints hints expr @?= "{\n\n # before x\n x = 1;\n}"
preservesSecondBindingBlankLineCommentsWithHints :: Assertion
preservesSecondBindingBlankLineCommentsWithHints = do
parsed <- parseFileOrFail "<comments>" "{\n x = 1;\n\n # before y\n y = 2;\n}"
let (expr, hints) = fromParsedExpr parsed
lookupLayoutHint [1] hints @?= Nothing
lookupLayoutHint [1, 0] hints
@?= Just
( LayoutHint
Nothing
[CanonicalBlankLine, CanonicalLineComment " before y"]
[]
)
formatExprWithHints hints expr @?= "{\n x = 1;\n\n # before y\n y = 2;\n}"
preservesInheritBindingCommentsWithHints :: Assertion
preservesInheritBindingCommentsWithHints = do
parsed <- parseFileOrFail "<comments>" "{\n # before inherit\n inherit x;\n}"
let (expr, hints) = fromParsedExpr parsed
formatExprWithHints hints expr @?= "{\n # before inherit\n inherit x;\n}"
stripParensExpr :: Expr -> Expr
stripParensExpr = \case
NixVar x name -> NixVar x name
NixLit x lit -> NixLit x lit
NixPar _ expr -> stripParensExpr expr
NixString x str -> NixString x (stripParensString str)
NixPath x path -> NixPath x (stripParensPath path)
NixEnvPath x path -> NixEnvPath x path
NixLam x pat expr -> NixLam x (stripParensFuncPat pat) (stripParensExpr expr)
NixApp x f y -> NixApp x (stripParensExpr f) (stripParensExpr y)
NixBinApp x op l r -> NixBinApp x op (stripParensExpr l) (stripParensExpr r)
NixNotApp x expr -> NixNotApp x (stripParensExpr expr)
NixNegApp x expr -> NixNegApp x (stripParensExpr expr)
NixList x xs -> NixList x (stripParensExpr <$> xs)
NixSet x recFlag bindings -> NixSet x recFlag (stripParensBinding <$> bindings)
NixLet x bindings expr -> NixLet x (stripParensBinding <$> bindings) (stripParensExpr expr)
NixHasAttr x expr path -> NixHasAttr x (stripParensExpr expr) (stripParensAttrPath path)
NixSelect x expr path mDefault -> NixSelect x (stripParensExpr expr) (stripParensAttrPath path) (stripParensExpr <$> mDefault)
NixIf x c t f -> NixIf x (stripParensExpr c) (stripParensExpr t) (stripParensExpr f)
NixWith x scope expr -> NixWith x (stripParensExpr scope) (stripParensExpr expr)
NixAssert x assertion expr -> NixAssert x (stripParensExpr assertion) (stripParensExpr expr)
stripParensString :: NString -> NString
stripParensString = \case
NixDoubleQuotesString x parts -> NixDoubleQuotesString x (stripParensStringPart <$> parts)
NixDoubleSingleQuotesString x parts -> NixDoubleSingleQuotesString x (stripParensStringPart <$> parts)
stripParensPath :: Path -> Path
stripParensPath = \case
NixLiteralPath x path -> NixLiteralPath x path
NixInterpolPath x parts -> NixInterpolPath x (stripParensStringPart <$> parts)
stripParensStringPart :: StringPart -> StringPart
stripParensStringPart = \case
NixStringLiteral x text -> NixStringLiteral x text
NixStringInterpol x expr -> NixStringInterpol x (stripParensExpr expr)
stripParensAttrPath :: AttrPath -> AttrPath
stripParensAttrPath (NixAttrPath x keys) = NixAttrPath x (stripParensAttrKey <$> keys)
stripParensAttrKey :: AttrKey -> AttrKey
stripParensAttrKey = \case
NixStaticAttrKey x name -> NixStaticAttrKey x name
NixDynamicStringAttrKey x parts -> NixDynamicStringAttrKey x (stripParensStringPart <$> parts)
NixDynamicInterpolAttrKey x expr -> NixDynamicInterpolAttrKey x (stripParensExpr expr)
stripParensBinding :: Binding -> Binding
stripParensBinding = \case
NixNormalBinding x path expr -> NixNormalBinding x (stripParensAttrPath path) (stripParensExpr expr)
NixInheritBinding x mScope keys -> NixInheritBinding x (stripParensExpr <$> mScope) (stripParensAttrKey <$> keys)
stripParensFuncPat :: FuncPat -> FuncPat
stripParensFuncPat = \case
NixVarPat x name -> NixVarPat x name
NixSetPat x ellipses mAs bindings -> NixSetPat x ellipses mAs (stripParensSetPatBinding <$> bindings)
stripParensSetPatBinding :: SetPatBinding -> SetPatBinding
stripParensSetPatBinding NixSetPatBinding {..} = NixSetPatBinding nspbAnn nspbVar (stripParensExpr <$> nspbDefault)