Skip to content

Commit

Permalink
Merge pull request #118 from piegamesde/rfc101-style
Browse files Browse the repository at this point in the history
RFC 101/166 style
  • Loading branch information
infinisil authored Mar 14, 2024
2 parents 0c2fb12 + 8d13b59 commit 91b200a
Show file tree
Hide file tree
Showing 108 changed files with 19,689 additions and 626 deletions.
4 changes: 4 additions & 0 deletions .envrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# © 2024 piegames <git@piegames.de>
# SPDX-License-Identifier: MPL-2.0

use_nix
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@
/dist-newstyle
/.ghc.environment.*
/result
/.direnv
4 changes: 4 additions & 0 deletions .reuse/dep5
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ Copyright: 2019 Serokell <hi@serokell.io>
2019 Lars Jellema <lars.jellema@gmail.com>
License: MPL-2.0

Files: test/diff/*
Copyright: 2024 piegames <git@piegames.de>
License: MPL-2.0

Files: test/correct/*
Copyright: 2022 Serokell <hi@serokell.io>
2022 Lars Jellema <lars.jellema@gmail.com>
Expand Down
36 changes: 18 additions & 18 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@
# nixfmt: expand
cabal-install
stylish-haskell
shellcheck
]);
});

Expand Down
6 changes: 3 additions & 3 deletions main/Main.hs
Original file line number Diff line number Diff line change
Expand Up @@ -43,20 +43,20 @@ data Nixfmt = Nixfmt

options :: Nixfmt
options =
let defaultWidth = 80
let defaultWidth = 100
addDefaultHint value message =
message ++ "\n[default: " ++ show value ++ "]"
in Nixfmt
{ files = [] &= args &= typ "FILES"
, width =
defaultWidth &=
help (addDefaultHint defaultWidth "Maximum width in characters")
, check = False &= help "Check whether files are formatted"
, check = False &= help "Check whether files are formatted without modifying them"
, quiet = False &= help "Do not report errors"
, verify =
False &=
help
"Check that the output parses and formats the same as the input"
"Apply sanity checks on the output after formatting"
} &=
summary ("nixfmt v" ++ showVersion version) &=
help "Format Nix source code"
Expand Down
2 changes: 2 additions & 0 deletions nixfmt.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,11 @@ library
build-depends:
base >= 4.12.0 && < 4.19
, megaparsec >= 9.0.1 && < 9.6
, mtl
, parser-combinators >= 1.0.3 && < 1.4
, scientific >= 0.3.0 && < 0.4.0
, text >= 1.2.3 && < 2.2
, transformers
default-language: Haskell2010
ghc-options:
-Wall
Expand Down
44 changes: 37 additions & 7 deletions src/Nixfmt.hs
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,18 @@ module Nixfmt
, formatVerify
) where

import Data.Either (fromRight)
import Data.Bifunctor (bimap, first)
import Data.Text (Text)
import Data.Text (Text, unpack)
import qualified Text.Megaparsec as Megaparsec (parse)
import Text.Megaparsec.Error (errorBundlePretty)

import Nixfmt.Parser (file)
import Nixfmt.Predoc (layout)
import Nixfmt.Pretty ()
import Nixfmt.Types (ParseErrorBundle)
import Nixfmt.Types (ParseErrorBundle, Whole(..), Expression, walkSubprograms)

-- import Debug.Trace (traceShow, traceShowId)

type Width = Int

Expand All @@ -32,17 +35,44 @@ format width filename
= bimap errorBundlePretty (layout width)
. Megaparsec.parse file filename

-- Same functionality as `format`, but add sanity checks to guarantee the following properties of the formatter:
-- - Correctness: The formatted output parses, and the parse tree is identical to the input's
-- - Idempotency: Formatting the output again will not modify it
--
-- If any issues are found, the operation will fail and print an error message. It will contain a diff showcasing
-- the issue on an automatically minimized example based on the input.
formatVerify :: Width -> FilePath -> Text -> Either String Text
formatVerify width path unformatted = do
unformattedParsed <- parse unformatted
unformattedParsed@(Whole unformattedParsed' _) <- parse unformatted
let formattedOnce = layout width unformattedParsed
formattedOnceParsed <- parse formattedOnce
formattedOnceParsed <- flip first (parse formattedOnce) $
(\x -> pleaseReport "Fails to parse after formatting.\n" <> x <> "\n\nAfter Formatting:\n" <> unpack formattedOnce)
let formattedTwice = layout width formattedOnceParsed
if formattedOnceParsed /= unformattedParsed
then pleaseReport "Parses differently after formatting."
then Left $
let
minimized = minimize unformattedParsed' (\e -> parse (layout width e) == Right (Whole e []))
in
pleaseReport "Parses differently after formatting."
<> "\n\nBefore formatting:\n" <> (show minimized)
<> "\n\nAfter formatting:\n" <> (show $ fromRight (error "TODO") $ parse (layout width minimized))
else if formattedOnce /= formattedTwice
then pleaseReport "Nixfmt is not idempotent."
then Left $
let
minimized = minimize unformattedParsed'
(\e -> layout width e == layout width (fromRight (error "TODO") $ parse $ layout width e))
in
pleaseReport "Nixfmt is not idempotent."
<> "\n\nAfter one formatting:\n" <> unpack (layout width minimized)
<> "\n\nAfter two:\n" <> unpack (layout width (fromRight (error "TODO") $ parse $ layout width minimized))
else Right formattedOnce
where
parse = first errorBundlePretty . Megaparsec.parse file path
pleaseReport x = Left $ path <> ": " <> x <> " This is a bug in nixfmt. Please report it at https://github.com/serokell/nixfmt"
pleaseReport x = path <> ": " <> x <> " This is a bug in nixfmt. Please report it at https://github.com/serokell/nixfmt"


minimize :: Expression -> (Expression -> Bool) -> Expression
minimize expr test =
case concatMap (\e -> case test e of { False -> [minimize e test]; True -> [] }) $ walkSubprograms expr of
result:_ -> result
[] -> expr
Loading

0 comments on commit 91b200a

Please sign in to comment.