packages feed

cabal-gild 1.6.0.4 → 1.7.0.0

raw patch · 8 files changed

+355/−174 lines, 8 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

+ CabalGild.Unstable.Action.AttachComments: addAfterComments :: Name (Position, Comments Position) -> [Comment Position] -> Name (Position, Comments Position)
+ CabalGild.Unstable.Action.AttachComments: attachTrailing :: Int -> Maybe Position -> State [Comment Position] [Comment Position]
+ CabalGild.Unstable.Action.AttachComments: fields :: Maybe Position -> [Field Position] -> State [Comment Position] [Field (Position, Comments Position)]
+ CabalGild.Unstable.Type.Comments: MkComments :: [Comment p] -> [Comment p] -> Comments p
+ CabalGild.Unstable.Type.Comments: [after] :: Comments p -> [Comment p]
+ CabalGild.Unstable.Type.Comments: [before] :: Comments p -> [Comment p]
+ CabalGild.Unstable.Type.Comments: afterLens :: forall p f. Functor f => LensLike f (Comments p) (Comments p) [Comment p] [Comment p]
+ CabalGild.Unstable.Type.Comments: data Comments p
+ CabalGild.Unstable.Type.Comments: empty :: Comments p
+ CabalGild.Unstable.Type.Comments: instance GHC.Classes.Eq p => GHC.Classes.Eq (CabalGild.Unstable.Type.Comments.Comments p)
+ CabalGild.Unstable.Type.Comments: instance GHC.Internal.Base.Monoid (CabalGild.Unstable.Type.Comments.Comments p)
+ CabalGild.Unstable.Type.Comments: instance GHC.Internal.Base.Semigroup (CabalGild.Unstable.Type.Comments.Comments p)
+ CabalGild.Unstable.Type.Comments: instance GHC.Internal.Show.Show p => GHC.Internal.Show.Show (CabalGild.Unstable.Type.Comments.Comments p)
+ CabalGild.Unstable.Type.Comments: toList :: Comments p -> [Comment p]
- CabalGild.Unstable.Action.AttachComments: field :: Ord p => Field p -> State [Comment p] (Field (p, [Comment p]))
+ CabalGild.Unstable.Action.AttachComments: field :: Maybe Position -> Field Position -> State [Comment Position] (Field (Position, Comments Position))
- CabalGild.Unstable.Action.AttachComments: fieldLine :: Ord p => FieldLine p -> State [Comment p] (FieldLine (p, [Comment p]))
+ CabalGild.Unstable.Action.AttachComments: fieldLine :: FieldLine Position -> State [Comment Position] (FieldLine (Position, Comments Position))
- CabalGild.Unstable.Action.AttachComments: name :: Ord p => Name p -> State [Comment p] (Name (p, [Comment p]))
+ CabalGild.Unstable.Action.AttachComments: name :: Name Position -> State [Comment Position] (Name (Position, Comments Position))
- CabalGild.Unstable.Action.AttachComments: run :: (Applicative m, Ord p) => ([Field p], [Comment p]) -> m ([Field (p, [Comment p])], [Comment p])
+ CabalGild.Unstable.Action.AttachComments: run :: Applicative m => ([Field Position], [Comment Position]) -> m ([Field (Position, Comments Position)], [Comment Position])
- CabalGild.Unstable.Action.AttachComments: sectionArg :: Ord p => SectionArg p -> State [Comment p] (SectionArg (p, [Comment p]))
+ CabalGild.Unstable.Action.AttachComments: sectionArg :: SectionArg Position -> State [Comment Position] (SectionArg (Position, Comments Position))
- CabalGild.Unstable.Action.AttachComments: toPosition :: Ord p => p -> State [Comment p] (p, [Comment p])
+ CabalGild.Unstable.Action.AttachComments: toPosition :: Position -> State [Comment Position] (Position, Comments Position)
- CabalGild.Unstable.Action.EvaluatePragmas: discover :: forall (m :: Type -> Type) p c. (MonadThrow m, MonadWalk m) => FilePath -> Name (p, [c]) -> [FieldLine (p, [c])] -> DiscoverTarget -> [String] -> MaybeT m (Field (p, [c]))
+ CabalGild.Unstable.Action.EvaluatePragmas: discover :: forall (m :: Type -> Type) p q. (MonadThrow m, MonadWalk m) => FilePath -> Name (p, Comments q) -> [FieldLine (p, Comments q)] -> DiscoverTarget -> [String] -> MaybeT m (Field (p, Comments q))
- CabalGild.Unstable.Action.EvaluatePragmas: field :: (MonadThrow m, MonadWalk m) => FilePath -> Field (p, [Comment q]) -> m (Field (p, [Comment q]))
+ CabalGild.Unstable.Action.EvaluatePragmas: field :: (MonadThrow m, MonadWalk m) => FilePath -> Field (p, Comments q) -> m (Field (p, Comments q))
- CabalGild.Unstable.Action.EvaluatePragmas: run :: (MonadThrow m, MonadWalk m) => FilePath -> ([Field (p, [Comment q])], cs) -> m ([Field (p, [Comment q])], cs)
+ CabalGild.Unstable.Action.EvaluatePragmas: run :: (MonadThrow m, MonadWalk m) => FilePath -> ([Field (p, Comments q)], cs) -> m ([Field (p, Comments q)], cs)
- CabalGild.Unstable.Action.FormatFields: collectComments :: [FieldLine (p, [c])] -> [c]
+ CabalGild.Unstable.Action.FormatFields: collectComments :: [FieldLine (p, Comments q)] -> Comments q
- CabalGild.Unstable.Action.FormatFields: field :: CabalSpecVersion -> Field (p, [c]) -> Field (p, [c])
+ CabalGild.Unstable.Action.FormatFields: field :: CabalSpecVersion -> Field (p, Comments q) -> Field (p, Comments q)
- CabalGild.Unstable.Action.FormatFields: fieldLines :: CabalSpecVersion -> p -> [FieldLine (p, [c])] -> SomeParsecParser -> [FieldLine (p, [c])]
+ CabalGild.Unstable.Action.FormatFields: fieldLines :: CabalSpecVersion -> p -> [FieldLine (p, Comments q)] -> SomeParsecParser -> [FieldLine (p, Comments q)]
- CabalGild.Unstable.Action.FormatFields: floatComments :: p -> [FieldLine (p, [c])] -> [FieldLine (p, [c])]
+ CabalGild.Unstable.Action.FormatFields: floatComments :: p -> [FieldLine (p, Comments q)] -> [FieldLine (p, Comments q)]
- CabalGild.Unstable.Action.FormatFields: run :: Applicative m => CabalSpecVersion -> ([Field (p, [c])], [c]) -> m ([Field (p, [c])], [c])
+ CabalGild.Unstable.Action.FormatFields: run :: Applicative m => CabalSpecVersion -> ([Field (p, Comments q)], [Comment q]) -> m ([Field (p, Comments q)], [Comment q])
- CabalGild.Unstable.Action.ReflowText: field :: Field (Position, [Comment Position]) -> Field (Position, [Comment Position])
+ CabalGild.Unstable.Action.ReflowText: field :: Field (Position, Comments Position) -> Field (Position, Comments Position)
- CabalGild.Unstable.Action.ReflowText: fieldLineToFirstRow :: FieldLine (Position, [Comment Position]) -> Int
+ CabalGild.Unstable.Action.ReflowText: fieldLineToFirstRow :: FieldLine (Position, Comments Position) -> Int
- CabalGild.Unstable.Action.ReflowText: fieldLines :: Field (Position, [Comment Position]) -> [FieldLine (Position, [Comment Position])] -> [FieldLine (Position, [Comment Position])]
+ CabalGild.Unstable.Action.ReflowText: fieldLines :: Field (Position, Comments Position) -> [FieldLine (Position, Comments Position)] -> [FieldLine (Position, Comments Position)]
- CabalGild.Unstable.Action.ReflowText: fields :: CabalSpecVersion -> [Field (Position, [Comment Position])] -> [Field (Position, [Comment Position])]
+ CabalGild.Unstable.Action.ReflowText: fields :: CabalSpecVersion -> [Field (Position, Comments Position)] -> [Field (Position, Comments Position)]
- CabalGild.Unstable.Action.ReflowText: fixCols :: Field (Position, [Comment Position]) -> [FieldLine (Position, [Comment Position])] -> [FieldLine (Position, [Comment Position])]
+ CabalGild.Unstable.Action.ReflowText: fixCols :: Field (Position, Comments Position) -> [FieldLine (Position, Comments Position)] -> [FieldLine (Position, Comments Position)]
- CabalGild.Unstable.Action.ReflowText: fixRows :: [FieldLine (Position, [Comment Position])] -> [FieldLine (Position, [Comment Position])]
+ CabalGild.Unstable.Action.ReflowText: fixRows :: [FieldLine (Position, Comments Position)] -> [FieldLine (Position, Comments Position)]
- CabalGild.Unstable.Action.ReflowText: rowToFieldLine :: Int -> FieldLine (Position, [c])
+ CabalGild.Unstable.Action.ReflowText: rowToFieldLine :: Int -> FieldLine (Position, Comments Position)
- CabalGild.Unstable.Action.ReflowText: run :: Applicative m => CabalSpecVersion -> ([Field (Position, [Comment Position])], cs) -> m ([Field (Position, [Comment Position])], cs)
+ CabalGild.Unstable.Action.ReflowText: run :: Applicative m => CabalSpecVersion -> ([Field (Position, Comments Position)], cs) -> m ([Field (Position, Comments Position)], cs)
- CabalGild.Unstable.Action.Render: field :: CabalSpecVersion -> Int -> Field (Position, [Comment p]) -> Block
+ CabalGild.Unstable.Action.Render: field :: CabalSpecVersion -> Int -> Field (Position, Comments p) -> Block
- CabalGild.Unstable.Action.Render: fieldLineC :: Int -> FieldLine (p, [Comment q]) -> Block
+ CabalGild.Unstable.Action.Render: fieldLineC :: Int -> FieldLine (p, Comments q) -> Block
- CabalGild.Unstable.Action.Render: fieldLines :: Int -> [FieldLine (p, [Comment q])] -> Block
+ CabalGild.Unstable.Action.Render: fieldLines :: Int -> [FieldLine (p, Comments q)] -> Block
- CabalGild.Unstable.Action.Render: fields :: CabalSpecVersion -> Int -> [Field (Position, [Comment p])] -> Block
+ CabalGild.Unstable.Action.Render: fields :: CabalSpecVersion -> Int -> [Field (Position, Comments p)] -> Block
- CabalGild.Unstable.Action.Render: run :: Applicative m => CabalSpecVersion -> ([Field (Position, [Comment p])], [Comment p]) -> m ByteString
+ CabalGild.Unstable.Action.Render: run :: Applicative m => CabalSpecVersion -> ([Field (Position, Comments p)], [Comment p]) -> m ByteString
- CabalGild.Unstable.Action.Render: toByteString :: CabalSpecVersion -> [Field (Position, [Comment p])] -> [Comment p] -> ByteString
+ CabalGild.Unstable.Action.Render: toByteString :: CabalSpecVersion -> [Field (Position, Comments p)] -> [Comment p] -> ByteString

Files

cabal-gild.cabal view
@@ -11,7 +11,7 @@ maintainer: Taylor Fausak name: cabal-gild synopsis: Formats package descriptions.-version: 1.6.0.4+version: 1.7.0.0  source-repository head   type: git@@ -107,6 +107,7 @@     CabalGild.Unstable.Type.Block     CabalGild.Unstable.Type.Chunk     CabalGild.Unstable.Type.Comment+    CabalGild.Unstable.Type.Comments     CabalGild.Unstable.Type.Condition     CabalGild.Unstable.Type.Config     CabalGild.Unstable.Type.Context
source/library/CabalGild/Unstable/Action/AttachComments.hs view
@@ -1,43 +1,70 @@ module CabalGild.Unstable.Action.AttachComments where +import qualified CabalGild.Unstable.Extra.Field as Field+import qualified CabalGild.Unstable.Extra.Name as Name import qualified CabalGild.Unstable.Type.Comment as Comment+import qualified CabalGild.Unstable.Type.Comments as Comments import qualified Control.Monad.Trans.State as StateT+import qualified Data.Maybe as Maybe+import qualified Distribution.Compat.Lens as Lens import qualified Distribution.Fields as Fields+import qualified Distribution.Parsec.Position as Position --- | High level wrapper around 'field' that makes this action easier to compose+-- | High level wrapper around 'fields' that makes this action easier to compose -- with other actions. run ::-  (Applicative m, Ord p) =>-  ([Fields.Field p], [Comment.Comment p]) ->-  m ([Fields.Field (p, [Comment.Comment p])], [Comment.Comment p])-run (fs, cs) = pure $ StateT.runState (traverse field fs) cs+  (Applicative m) =>+  ([Fields.Field Position.Position], [Comment.Comment Position.Position]) ->+  m ([Fields.Field (Position.Position, Comments.Comments Position.Position)], [Comment.Comment Position.Position])+run (fs, cs) = pure $ StateT.runState (fields Nothing fs) cs +-- | Attaches comments to a list of fields, with awareness of sibling positions.+-- The first argument is the boundary position (e.g., from a parent's next sibling).+fields ::+  Maybe Position.Position ->+  [Fields.Field Position.Position] ->+  StateT.State [Comment.Comment Position.Position] [Fields.Field (Position.Position, Comments.Comments Position.Position)]+fields p fs = case fs of+  [] -> pure []+  f : gs -> do+    let q = maybe p (Just . Name.annotation . Field.name) $ Maybe.listToMaybe gs+    (:)+      <$> field q f+      <*> fields p gs+ -- | Attaches comments to a single field. It is assumed that both the fields--- and comments are already sorted by their position @p@. This precondition is+-- and comments are already sorted by their position. This precondition is -- not checked. Note that comments actually end up attached to the field's -- name. That's because the 'Field.Field' type doesn't have any annotations -- directly on it.+--+-- Comments that are indented beyond the field's starting column are attached+-- as trailing comments (in 'Comments.after'), but only if they appear before+-- the next sibling's position. field ::-  (Ord p) =>-  Fields.Field p ->-  StateT.State [Comment.Comment p] (Fields.Field (p, [Comment.Comment p]))-field f = case f of-  Fields.Field n fls ->-    Fields.Field-      <$> name n-      <*> traverse fieldLine fls-  Fields.Section n sas fs ->-    Fields.Section-      <$> name n-      <*> traverse sectionArg sas-      <*> traverse field fs+  Maybe Position.Position ->+  Fields.Field Position.Position ->+  StateT.State [Comment.Comment Position.Position] (Fields.Field (Position.Position, Comments.Comments Position.Position))+field p f = case f of+  Fields.Field n1 fls1 -> do+    let col = Position.positionCol $ Name.annotation n1+    n2 <- name n1+    fls2 <- traverse fieldLine fls1+    cs <- attachTrailing col p+    pure $ Fields.Field (addAfterComments n2 cs) fls2+  Fields.Section n1 sas1 fs1 -> do+    let col = Position.positionCol $ Name.annotation n1+    n2 <- name n1+    sas2 <- traverse sectionArg sas1+    fs2 <- fields p fs1+    cs <- attachTrailing col p+    pure $ Fields.Section (addAfterComments n2 cs) sas2 fs2  -- | Attaches comments to a name. Note that this could be a field name or a -- section name. name ::-  (Ord p) =>-  Fields.Name p ->-  StateT.State [Comment.Comment p] (Fields.Name (p, [Comment.Comment p]))+  Fields.Name Position.Position ->+  StateT.State [Comment.Comment Position.Position] (Fields.Name (Position.Position, Comments.Comments Position.Position)) name (Fields.Name p fn) =   Fields.Name     <$> toPosition p@@ -45,9 +72,8 @@  -- | Attach comments to a field line. fieldLine ::-  (Ord p) =>-  Fields.FieldLine p ->-  StateT.State [Comment.Comment p] (Fields.FieldLine (p, [Comment.Comment p]))+  Fields.FieldLine Position.Position ->+  StateT.State [Comment.Comment Position.Position] (Fields.FieldLine (Position.Position, Comments.Comments Position.Position)) fieldLine (Fields.FieldLine p bs) =   Fields.FieldLine     <$> toPosition p@@ -58,9 +84,8 @@ -- must be on the same line as the section name, so all comments will end up -- attached to the name. sectionArg ::-  (Ord p) =>-  Fields.SectionArg p ->-  StateT.State [Comment.Comment p] (Fields.SectionArg (p, [Comment.Comment p]))+  Fields.SectionArg Position.Position ->+  StateT.State [Comment.Comment Position.Position] (Fields.SectionArg (Position.Position, Comments.Comments Position.Position)) sectionArg sa = case sa of   Fields.SecArgName p bs ->     Fields.SecArgName@@ -79,11 +104,33 @@ -- Comments are attached when their position is less than or equal to the given -- position. The comments are removed from the state as they are attached. toPosition ::-  (Ord p) =>-  p ->-  StateT.State [Comment.Comment p] (p, [Comment.Comment p])+  Position.Position ->+  StateT.State [Comment.Comment Position.Position] (Position.Position, Comments.Comments Position.Position) toPosition p = do   cs <- StateT.get   let (xs, ys) = span ((<= p) . Comment.annotation) cs   StateT.put ys-  pure (p, xs)+  pure (p, Comments.MkComments {Comments.before = xs, Comments.after = []})++-- | Attaches trailing comments based on column indentation. Comments that are+-- indented beyond the given column are considered trailing, but only up to+-- the boundary position (if specified). Comments are removed from the state.+attachTrailing ::+  Int ->+  Maybe Position.Position ->+  StateT.State [Comment.Comment Position.Position] [Comment.Comment Position.Position]+attachTrailing col boundary = do+  cs <- StateT.get+  let isTrailing c =+        let p = Comment.annotation c+         in Position.positionCol p > col && maybe True (p <) boundary+      (xs, ys) = span isTrailing cs+  StateT.put ys+  pure xs++-- | Adds trailing comments to the 'after' field of a Name's Comments.+addAfterComments ::+  Fields.Name (Position.Position, Comments.Comments Position.Position) ->+  [Comment.Comment Position.Position] ->+  Fields.Name (Position.Position, Comments.Comments Position.Position)+addAfterComments n cs = Lens.over (Name.annotationLens . Lens._2 . Comments.afterLens) (<> cs) n
source/library/CabalGild/Unstable/Action/EvaluatePragmas.hs view
@@ -9,6 +9,7 @@ import qualified CabalGild.Unstable.Extra.Name as Name import qualified CabalGild.Unstable.Extra.String as String import qualified CabalGild.Unstable.Type.Comment as Comment+import qualified CabalGild.Unstable.Type.Comments as Comments import qualified CabalGild.Unstable.Type.DiscoverTarget as DiscoverTarget import qualified CabalGild.Unstable.Type.Pragma as Pragma import qualified Control.Applicative as Applicative@@ -33,8 +34,8 @@ run ::   (Exception.MonadThrow m, MonadWalk.MonadWalk m) =>   FilePath ->-  ([Fields.Field (p, [Comment.Comment q])], cs) ->-  m ([Fields.Field (p, [Comment.Comment q])], cs)+  ([Fields.Field (p, Comments.Comments q)], cs) ->+  m ([Fields.Field (p, Comments.Comments q)], cs) run p (fs, cs) = (,) <$> traverse (field p) fs <*> pure cs  -- | Evaluates pragmas within the given field. Or, if the field is a section,@@ -42,14 +43,14 @@ field ::   (Exception.MonadThrow m, MonadWalk.MonadWalk m) =>   FilePath ->-  Fields.Field (p, [Comment.Comment q]) ->-  m (Fields.Field (p, [Comment.Comment q]))+  Fields.Field (p, Comments.Comments q) ->+  m (Fields.Field (p, Comments.Comments q)) field p f = case f of   Fields.Field n fls -> fmap (Maybe.fromMaybe f) . MaybeT.runMaybeT $ do     dt <-       maybe Applicative.empty pure $         Map.lookup (Name.value n) relevantFieldNames-    comment <- hoistMaybe . Utils.safeLast . snd $ Name.annotation n+    comment <- hoistMaybe . Utils.safeLast . Comments.toList . snd $ Name.annotation n     pragma <- hoistMaybe . Parsec.simpleParsecBS $ Comment.value comment     case pragma of       Pragma.Discover ds -> discover p n fls dt ds@@ -60,11 +61,11 @@ discover ::   (Exception.MonadThrow m, MonadWalk.MonadWalk m) =>   FilePath ->-  Fields.Name (p, [c]) ->-  [Fields.FieldLine (p, [c])] ->+  Fields.Name (p, Comments.Comments q) ->+  [Fields.FieldLine (p, Comments.Comments q)] ->   DiscoverTarget.DiscoverTarget ->   [String] ->-  MaybeT.MaybeT m (Fields.Field (p, [c]))+  MaybeT.MaybeT m (Fields.Field (p, Comments.Comments q)) discover p n fls dt ds = do   let (flgs, args, opts, errs) =         GetOpt.getOpt'@@ -87,19 +88,19 @@           . fmap clean           $ if null incs then fmap (`FilePath.combine` "**") directories else incs   files <- Trans.lift $ MonadWalk.walk root inclusions exclusions-  let comments = concatMap (snd . FieldLine.annotation) fls+  let comments = foldMap (snd . FieldLine.annotation) fls       position =         maybe (fst $ Name.annotation n) (fst . FieldLine.annotation) $           Maybe.listToMaybe fls       fieldLines = case dt of         DiscoverTarget.Modules ->-          zipWith ModuleName.toFieldLine ((,) position <$> comments : repeat [])+          zipWith ModuleName.toFieldLine ((,) position <$> comments : repeat Comments.empty)             . Maybe.mapMaybe (toModuleName directories)             $ Maybe.mapMaybe (stripAnyExtension extensions . clean) files         DiscoverTarget.Files ->           zipWith             (\a -> Fields.FieldLine a . String.toUtf8)-            ((,) position <$> comments : repeat [])+            ((,) position <$> comments : repeat Comments.empty)             files       -- This isn't great, but the comments have to go /somewhere/.       name =
source/library/CabalGild/Unstable/Action/FormatFields.hs view
@@ -6,6 +6,8 @@ import qualified CabalGild.Unstable.Extra.Name as Name import qualified CabalGild.Unstable.Extra.SectionArg as SectionArg import qualified CabalGild.Unstable.Extra.String as String+import qualified CabalGild.Unstable.Type.Comment as Comment+import qualified CabalGild.Unstable.Type.Comments as Comments import qualified CabalGild.Unstable.Type.Condition as Condition import qualified CabalGild.Unstable.Type.Dependency as Dependency import qualified CabalGild.Unstable.Type.Extension as Extension@@ -35,8 +37,8 @@ run ::   (Applicative m) =>   CabalSpecVersion.CabalSpecVersion ->-  ([Fields.Field (p, [c])], [c]) ->-  m ([Fields.Field (p, [c])], [c])+  ([Fields.Field (p, Comments.Comments q)], [Comment.Comment q]) ->+  m ([Fields.Field (p, Comments.Comments q)], [Comment.Comment q]) run csv (fs, cs) = pure (fmap (field csv) fs, cs)  -- | Formats the given field, if applicable. Otherwise returns the field as is.@@ -44,8 +46,8 @@ -- formatted. field ::   CabalSpecVersion.CabalSpecVersion ->-  Fields.Field (p, [c]) ->-  Fields.Field (p, [c])+  Fields.Field (p, Comments.Comments q) ->+  Fields.Field (p, Comments.Comments q) field csv f = case f of   Fields.Field n fls ->     let position =@@ -70,7 +72,7 @@               Left _ -> sas               Right c ->                 pure-                  . Fields.SecArgName (position, [])+                  . Fields.SecArgName (position, Comments.empty)                   . String.toUtf8                   . PrettyPrint.renderStyle style                   $ Condition.prettyCondition Variable.prettyVariable c@@ -90,15 +92,15 @@ fieldLines ::   CabalSpecVersion.CabalSpecVersion ->   p ->-  [Fields.FieldLine (p, [c])] ->+  [Fields.FieldLine (p, Comments.Comments q)] ->   SPP.SomeParsecParser ->-  [Fields.FieldLine (p, [c])]+  [Fields.FieldLine (p, Comments.Comments q)] fieldLines csv position fls SPP.SomeParsecParser {SPP.parsec = parsec, SPP.pretty = pretty} =   case Parsec.runParsecParser' csv parsec "" $ FieldLine.toFieldLineStream fls of     Left _ -> floatComments position fls     Right r ->       zipWith-        (\b l -> Fields.FieldLine (position, if b then collectComments fls else []) $ String.toUtf8 l)+        (\b l -> Fields.FieldLine (position, if b then collectComments fls else Comments.empty) $ String.toUtf8 l)         (True : repeat False)         . lines         . PrettyPrint.renderStyle style@@ -108,18 +110,18 @@ -- attaches them all to the first one. floatComments ::   p ->-  [Fields.FieldLine (p, [c])] ->-  [Fields.FieldLine (p, [c])]+  [Fields.FieldLine (p, Comments.Comments q)] ->+  [Fields.FieldLine (p, Comments.Comments q)] floatComments p fls =   zipWith-    (\b -> Fields.FieldLine (p, if b then collectComments fls else []) . FieldLine.value)+    (\b -> Fields.FieldLine (p, if b then collectComments fls else Comments.empty) . FieldLine.value)     (True : repeat False)     fls  -- | Collects all comments from the given field lines. Their relative order -- will be maintained.-collectComments :: [Fields.FieldLine (p, [c])] -> [c]-collectComments = concatMap (snd . FieldLine.annotation)+collectComments :: [Fields.FieldLine (p, Comments.Comments q)] -> Comments.Comments q+collectComments = foldMap (snd . FieldLine.annotation)  -- | This style attempts to force everything to be on its own line. style :: PrettyPrint.Style
source/library/CabalGild/Unstable/Action/ReflowText.hs view
@@ -6,6 +6,7 @@ import qualified CabalGild.Unstable.Extra.Name as Name import qualified CabalGild.Unstable.Extra.String as String import qualified CabalGild.Unstable.Type.Comment as Comment+import qualified CabalGild.Unstable.Type.Comments as Comments import qualified Data.ByteString as ByteString import qualified Data.Set as Set import qualified Distribution.CabalSpecVersion as CabalSpecVersion@@ -16,8 +17,8 @@ run ::   (Applicative m) =>   CabalSpecVersion.CabalSpecVersion ->-  ([Fields.Field (Position.Position, [Comment.Comment Position.Position])], cs) ->-  m ([Fields.Field (Position.Position, [Comment.Comment Position.Position])], cs)+  ([Fields.Field (Position.Position, Comments.Comments Position.Position)], cs) ->+  m ([Fields.Field (Position.Position, Comments.Comments Position.Position)], cs) run csv (fs, cs) = pure (fields csv fs, cs)  -- | Reflows the free text field values if the Cabal spec version is recent@@ -28,8 +29,8 @@ -- insert. fields ::   CabalSpecVersion.CabalSpecVersion ->-  [Fields.Field (Position.Position, [Comment.Comment Position.Position])] ->-  [Fields.Field (Position.Position, [Comment.Comment Position.Position])]+  [Fields.Field (Position.Position, Comments.Comments Position.Position)] ->+  [Fields.Field (Position.Position, Comments.Comments Position.Position)] fields csv fs =   if csv >= CabalSpecVersion.CabalSpecV3_0     then fmap field fs@@ -39,8 +40,8 @@ -- field as is. If the field is a section, the fields within the section will -- be recursively reflowed. field ::-  Fields.Field (Position.Position, [Comment.Comment Position.Position]) ->-  Fields.Field (Position.Position, [Comment.Comment Position.Position])+  Fields.Field (Position.Position, Comments.Comments Position.Position) ->+  Fields.Field (Position.Position, Comments.Comments Position.Position) field f = case f of   Fields.Field n fls ->     if Set.member (Name.value n) relevantFieldNames && List.compareLength fls 1 == GT@@ -60,15 +61,15 @@ -- | Reflows the field lines for the given field. This is just a wrapper around -- 'fixRows' and 'fixCols'. fieldLines ::-  Fields.Field (Position.Position, [Comment.Comment Position.Position]) ->-  [Fields.FieldLine (Position.Position, [Comment.Comment Position.Position])] ->-  [Fields.FieldLine (Position.Position, [Comment.Comment Position.Position])]+  Fields.Field (Position.Position, Comments.Comments Position.Position) ->+  [Fields.FieldLine (Position.Position, Comments.Comments Position.Position)] ->+  [Fields.FieldLine (Position.Position, Comments.Comments Position.Position)] fieldLines f = fixRows . fixCols f  -- | Inserts blank lines between field lines if necessary. fixRows ::-  [Fields.FieldLine (Position.Position, [Comment.Comment Position.Position])] ->-  [Fields.FieldLine (Position.Position, [Comment.Comment Position.Position])]+  [Fields.FieldLine (Position.Position, Comments.Comments Position.Position)] ->+  [Fields.FieldLine (Position.Position, Comments.Comments Position.Position)] fixRows fls = case fls of   x : y : zs ->     x@@ -80,9 +81,9 @@ -- other lines relative to that one. Note that if the first field line is on -- the same line as the field itself, it will never be reindented. fixCols ::-  Fields.Field (Position.Position, [Comment.Comment Position.Position]) ->-  [Fields.FieldLine (Position.Position, [Comment.Comment Position.Position])] ->-  [Fields.FieldLine (Position.Position, [Comment.Comment Position.Position])]+  Fields.Field (Position.Position, Comments.Comments Position.Position) ->+  [Fields.FieldLine (Position.Position, Comments.Comments Position.Position)] ->+  [Fields.FieldLine (Position.Position, Comments.Comments Position.Position)] fixCols f fls = case fls of   [] -> fls   x : xs ->@@ -98,11 +99,11 @@ -- | Extracts the /first/ row number from a field line, which might belong to -- one of its comments. fieldLineToFirstRow ::-  Fields.FieldLine (Position.Position, [Comment.Comment Position.Position]) ->+  Fields.FieldLine (Position.Position, Comments.Comments Position.Position) ->   Int fieldLineToFirstRow =   Position.positionRow-    . uncurry (foldr (min . Comment.annotation))+    . (\(p, cs) -> foldr (min . Comment.annotation) p $ Comments.toList cs)     . FieldLine.annotation  -- | Extracts the /last/ row number from a field line, which will not belong to@@ -125,5 +126,5 @@ -- | Creates a blank field line at the given row number. rowToFieldLine ::   Int ->-  Fields.FieldLine (Position.Position, [c])-rowToFieldLine r = Fields.FieldLine (Position.Position r 1, []) ByteString.empty+  Fields.FieldLine (Position.Position, Comments.Comments Position.Position)+rowToFieldLine r = Fields.FieldLine (Position.Position r 1, Comments.empty) ByteString.empty
source/library/CabalGild/Unstable/Action/Render.hs view
@@ -6,6 +6,7 @@ import qualified CabalGild.Unstable.Type.Block as Block import qualified CabalGild.Unstable.Type.Chunk as Chunk import qualified CabalGild.Unstable.Type.Comment as Comment+import qualified CabalGild.Unstable.Type.Comments as Comments import qualified CabalGild.Unstable.Type.Line as Line import qualified Data.ByteString as ByteString import qualified Data.Function as Function@@ -19,14 +20,14 @@ run ::   (Applicative m) =>   CabalSpecVersion.CabalSpecVersion ->-  ([Fields.Field (Position.Position, [Comment.Comment p])], [Comment.Comment p]) ->+  ([Fields.Field (Position.Position, Comments.Comments p)], [Comment.Comment p]) ->   m ByteString.ByteString run csv = pure . uncurry (toByteString csv)  -- | Renders the given fields and comments to a byte string. toByteString ::   CabalSpecVersion.CabalSpecVersion ->-  [Fields.Field (Position.Position, [Comment.Comment p])] ->+  [Fields.Field (Position.Position, Comments.Comments p)] ->   [Comment.Comment p] ->   ByteString.ByteString toByteString csv fs cs =@@ -37,44 +38,48 @@         $ fields csv i fs <> comments i cs  -- | Renders the given fields to a block at the given indentation level.-fields :: CabalSpecVersion.CabalSpecVersion -> Int -> [Fields.Field (Position.Position, [Comment.Comment p])] -> Block.Block+fields :: CabalSpecVersion.CabalSpecVersion -> Int -> [Fields.Field (Position.Position, Comments.Comments p)] -> Block.Block fields csv = foldMap . field csv  -- | Renders the given field to a block at the given indentation level. -- -- If a field only has one line and no comments, then it can be rendered all on -- one line.-field :: CabalSpecVersion.CabalSpecVersion -> Int -> Fields.Field (Position.Position, [Comment.Comment p]) -> Block.Block+field :: CabalSpecVersion.CabalSpecVersion -> Int -> Fields.Field (Position.Position, Comments.Comments p) -> Block.Block field csv i f = case f of   Fields.Field n fls -> case fls of     [fl]-      | null . snd $ FieldLine.annotation fl,+      | null . Comments.after . snd $ Name.annotation n,+        null . Comments.toList . snd $ FieldLine.annotation fl,         sameRow (Name.annotation n) (FieldLine.annotation fl) ->-          comments i (snd $ Name.annotation n)+          comments i (Comments.before . snd $ Name.annotation n)             <> ( Block.fromLine                    . Lens.over Line.chunkLens (mappend $ name n <> Chunk.colon)                    $ fieldLine i fl                )     _ ->       Lens.set Block.lineAfterLens (not $ null fls) $-        comments i (snd $ Name.annotation n)+        comments i (Comments.before . snd $ Name.annotation n)           <> Block.fromLine             Line.Line               { Line.indent = i,                 Line.chunk = name n <> Chunk.colon               }           <> fieldLines (i + 1) fls+          <> comments (i + 1) (Comments.after . snd $ Name.annotation n)   Fields.Section n sas fs ->     Lens.set Block.lineBeforeLens (not $ Name.isElif csv n || Name.isElse n)       . Lens.set Block.lineAfterLens (not $ Name.isIf n || Name.isElif csv n)-      $ comments i (snd $ Name.annotation n)-        <> comments i (concatMap (snd . SectionArg.annotation) sas)+      $ comments i (Comments.before . snd $ Name.annotation n)+        <> comments i (Comments.before $ foldMap (snd . SectionArg.annotation) sas)         <> Block.fromLine           Line.Line             { Line.indent = i,               Line.chunk = Lens.set Chunk.spaceAfterLens True (name n) <> sectionArgs sas             }         <> Lens.set Block.lineBeforeLens False (fields csv (i + 1) fs)+        <> comments (i + 1) (Comments.after . snd $ Name.annotation n)+        <> comments (i + 1) (Comments.after $ foldMap (snd . SectionArg.annotation) sas)  -- | Returns true if the two positions are on the same row. sameRow :: (Position.Position, cs) -> (Position.Position, cs) -> Bool@@ -85,15 +90,16 @@ name = Chunk.fromByteString . Name.value  -- | Renders the given field lines to a block at the given indentation level.-fieldLines :: Int -> [Fields.FieldLine (p, [Comment.Comment q])] -> Block.Block+fieldLines :: Int -> [Fields.FieldLine (p, Comments.Comments q)] -> Block.Block fieldLines = foldMap . fieldLineC  -- | Renders the given field line and its comments to a block at the given -- indentation level.-fieldLineC :: Int -> Fields.FieldLine (p, [Comment.Comment q]) -> Block.Block+fieldLineC :: Int -> Fields.FieldLine (p, Comments.Comments q) -> Block.Block fieldLineC i fl =-  comments i (snd $ FieldLine.annotation fl)+  comments i (Comments.before . snd $ FieldLine.annotation fl)     <> Block.fromLine (fieldLine i fl)+    <> comments (i + 1) (Comments.after . snd $ FieldLine.annotation fl)  -- | Renders the given field line to a line at the given indentation level. fieldLine :: Int -> Fields.FieldLine a -> Line.Line
+ source/library/CabalGild/Unstable/Type/Comments.hs view
@@ -0,0 +1,30 @@+-- | This module defines the 'Comments' newtype wrapper.+module CabalGild.Unstable.Type.Comments where++import qualified CabalGild.Unstable.Type.Comment as Comment+import qualified Distribution.Compat.Lens as Lens++data Comments p = MkComments+  { before :: [Comment.Comment p],+    after :: [Comment.Comment p]+  }+  deriving (Eq, Show)++instance Semigroup (Comments p) where+  xs <> ys =+    MkComments+      { before = before xs <> before ys,+        after = after ys <> after xs+      }++instance Monoid (Comments p) where+  mempty = empty++toList :: Comments p -> [Comment.Comment p]+toList x = before x <> after x++empty :: Comments p+empty = MkComments {before = [], after = []}++afterLens :: Lens.Lens' (Comments p) [Comment.Comment p]+afterLens f s = fmap (\x -> s {after = x}) . f $ after s
source/test-suite/Main.hs view
@@ -286,46 +286,194 @@       "\t\r\n \r\n"       "" -  Hspec.it "formats a comment" $ do-    expectGilded-      "-- c"-      "-- c\n"+  Hspec.describe "comments" $ do+    Hspec.it "formats a comment" $ do+      expectGilded+        "-- c"+        "-- c\n" -  Hspec.it "keeps a blank comment" $ do-    expectGilded-      "--"-      "--\n"+    Hspec.it "keeps a blank comment" $ do+      expectGilded+        "--"+        "--\n" -  Hspec.it "formats multiple comments" $ do-    expectGilded-      "-- c\n-- d"-      "-- c\n-- d\n"+    Hspec.it "formats multiple comments" $ do+      expectGilded+        "-- c\n-- d"+        "-- c\n-- d\n" -  Hspec.it "removes blank lines between comments" $ do-    expectGilded-      "-- c\n\n-- d"-      "-- c\n-- d\n"+    Hspec.it "removes blank lines between comments" $ do+      expectGilded+        "-- c\n\n-- d"+        "-- c\n-- d\n" -  Hspec.it "does not require a space after the comment start" $ do-    expectGilded-      "--c"-      "--c\n"+    Hspec.it "does not require a space after the comment start" $ do+      expectGilded+        "--c"+        "--c\n" -  Hspec.it "leaves leading blank space in comments" $ do-    expectGilded-      "--\t c"-      "--\t c\n"+    Hspec.it "leaves leading blank space in comments" $ do+      expectGilded+        "--\t c"+        "--\t c\n" -  Hspec.it "trims trailing blank space from comments" $ do-    expectGilded-      "-- c\t \n"-      "-- c\n"+    Hspec.it "trims trailing blank space from comments" $ do+      expectGilded+        "-- c\t \n"+        "-- c\n" -  Hspec.it "normalizes Windows line endings in comments" $ do-    expectGilded-      "-- c\r\n"-      "-- c\n"+    Hspec.it "normalizes Windows line endings in comments" $ do+      expectGilded+        "-- c\r\n"+        "-- c\n" +    Hspec.it "formats a comment before a field" $ do+      expectGilded+        "-- c\nf: 1"+        "-- c\nf: 1\n"++    Hspec.it "formats a comment after a field" $ do+      expectGilded+        "f: 1\n-- c"+        "f: 1\n-- c\n"++    Hspec.it "formats a comment before a field's value" $ do+      expectGilded+        "f:\n -- c\n 1"+        "f:\n  -- c\n  1\n"++    Hspec.it "formats a comment in a field's value" $ do+      expectGilded+        "f:\n 1\n -- c\n 2"+        "f:\n  -- c\n  1\n  2\n"++    Hspec.it "formats a comment trailing an inline field's value" $ do+      -- This comment is indented beyond the beginning of the field, so it+      -- belongs to the field. That forces the field value into block mode,+      -- even though the input was inline.+      expectGilded+        "f: 1\n -- c"+        "f:\n  1\n  -- c\n"++    Hspec.it "formats a comment trailing an inline field's value with an extra blank line" $ do+      -- Even though there's an extra blank line separating the field from the+      -- comment, the comment is still indented past the field.+      expectGilded+        "f: 1\n\n -- c"+        "f:\n  1\n  -- c\n"++    Hspec.it "formats a comment after an inline field's value" $ do+      expectGilded+        "f: 1\n-- c"+        "f: 1\n-- c\n"++    Hspec.it "formats a comment trailing a block field's value" $ do+      expectGilded+        "f:\n 1\n -- c"+        "f:\n  1\n  -- c\n"++    Hspec.it "formats a comment trailing a block field's value with an extra blank line" $ do+      -- Same as above, but there's an extra blank line.+      expectGilded+        "f:\n 1\n\n -- c"+        "f:\n  1\n  -- c\n"++    Hspec.it "formats a comment after a block field's value" $ do+      expectGilded+        "f:\n 1\n-- c"+        "f:\n  1\n\n-- c\n"++    Hspec.it "formats a comment trailing a field with multiple values" $ do+      expectGilded+        "f: 1\n 2\n -- c"+        "f:\n  1\n  2\n  -- c\n"++    Hspec.it "formats a comment trailing a field with multiple values with an extra blank line" $ do+      -- Same as above, but there's an extra blank line.+      expectGilded+        "f: 1\n 2\n\n -- c"+        "f:\n  1\n  2\n  -- c\n"++    Hspec.it "formats a comment after a field with multiple values" $ do+      expectGilded+        "f: 1\n 2\n-- c"+        "f:\n  1\n  2\n\n-- c\n"++    Hspec.it "formats a comment before a section" $ do+      expectGilded+        "-- c\ns"+        "-- c\ns\n"++    Hspec.it "formats a comment trailing a section" $ do+      -- This comment is indented beyond the beginning of the section, so it+      -- belongs to the section.+      expectGilded+        "s\n -- c"+        "s\n  -- c\n"++    Hspec.it "formats a comment trailing a section with extra blank line" $ do+      -- Same as above, but there's an extra blank line.+      expectGilded+        "s\n\n -- c"+        "s\n  -- c\n"++    Hspec.it "formats a comment after a section's value" $ do+      -- This is a minimal reproduction of the issue reported here:+      -- <https://github.com/tfausak/cabal-gild/issues/122>.+      expectGilded+        "s\n f: 1\n -- c"+        "s\n  f: 1\n  -- c\n"++    Hspec.it "formats a comment after a section" $ do+      expectGilded+        "s\n-- c"+        "s\n\n-- c\n"++    Hspec.it "correctly indents a comment in a section" $ do+      expectGilded+        "s\n -- c\n f: 1"+        "s\n  -- c\n  f: 1\n"++    Hspec.it "floats comments on unknown fields" $ do+      expectGilded+        "unknown-field:\n the\n -- some comment\n value"+        "unknown-field:\n  -- some comment\n  the\n  value\n"++    Hspec.it "floats comments when parsing field fails" $ do+      expectGilded+        "build-depends:\n >> no\n -- comment\n parse"+        "build-depends:\n  -- comment\n  >> no\n  parse\n"++    Hspec.it "does not move an indented comment inside a field" $ do+      -- Even though the comment is indented beyond the beginning of the field,+      -- it does not belong to the field because it comes before the field.+      expectGilded+        " -- c\nf: 1"+        "-- c\nf: 1\n"++    Hspec.it "does not move an indented comment inside a section" $ do+      -- Even though the comment is indented beyond the beginning of the+      -- section, it does not belong to the section because it comes before the+      -- section.+      expectGilded+        " -- c\ns"+        "-- c\ns\n"++    Hspec.it "sorts inline field comments correctly" $ do+      expectGilded+        "-- a\n-- b\nf: 1\n -- c\n -- d"+        "-- a\n-- b\nf:\n  1\n  -- c\n  -- d\n"++    Hspec.it "sorts block field comments correctly" $ do+      expectGilded+        "-- a\n-- b\nf:\n -- c\n -- d\n 1\n -- e\n -- f\n 2\n -- g\n -- h"+        "-- a\n-- b\nf:\n  -- c\n  -- d\n  -- e\n  -- f\n  1\n  2\n  -- g\n  -- h\n"++    Hspec.it "sorts section comments correctly" $ do+      expectGilded+        "-- a\n-- b\ns\n -- c\n -- d"+        "-- a\n-- b\ns\n  -- c\n  -- d\n"+   Hspec.it "formats a field without a value" $ do     expectGilded       "f:"@@ -453,51 +601,6 @@       "s\n f:\n  1\n  2"       "s\n  f:\n    1\n    2\n" -  Hspec.it "formats a comment before a field" $ do-    expectGilded-      "-- c\nf: 1"-      "-- c\nf: 1\n"--  Hspec.it "formats a comment after a field" $ do-    expectGilded-      "f: 1\n-- c"-      "f: 1\n-- c\n"--  Hspec.it "formats a comment before a field's value" $ do-    expectGilded-      "f:\n -- c\n 1"-      "f:\n  -- c\n  1\n"--  Hspec.it "formats a comment in a field's value" $ do-    expectGilded-      "f:\n 1\n -- c\n 2"-      "f:\n  -- c\n  1\n  2\n"--  Hspec.it "formats a comment after a field's value" $ do-    expectGilded-      "f:\n 1\n -- c"-      "f:\n  1\n\n-- c\n"--  Hspec.it "formats a comment after a field with multiple values" $ do-    expectGilded-      "f: 1\n 2\n-- c"-      "f:\n  1\n  2\n\n-- c\n"--  Hspec.it "formats a comment before a section" $ do-    expectGilded-      "-- c\ns"-      "-- c\ns\n"--  Hspec.it "formats a comment after a section" $ do-    expectGilded-      "s\n-- c"-      "s\n\n-- c\n"--  Hspec.it "correctly indents a comment in a section" $ do-    expectGilded-      "s\n -- c\n f: 1"-      "s\n  -- c\n  f: 1\n"-   Hspec.describe "description" $ do     -- These tests apply to other "free text" fields as well. The description     -- field is just a representative example.@@ -1582,16 +1685,6 @@       (".", [["example.txt"]])       "-- cabal-gild: discover\nlicense-files:"       "-- cabal-gild: discover\nlicense-files: example.txt\n"--  Hspec.it "floats comments on unknown fields" $ do-    expectGilded-      "unknown-field:\n the\n -- some comment\n value"-      "unknown-field:\n  -- some comment\n  the\n  value\n"--  Hspec.it "floats comments when parsing field fails" $ do-    expectGilded-      "build-depends:\n >> no\n -- comment\n parse"-      "build-depends:\n  -- comment\n  >> no\n  parse\n"    Hspec.it "only discovers modules in given directories" $ do     expectDiscover