content: {-# LANGUAGE OverloadedStrings   #-}
  {-# LANGUAGE ScopedTypeVariables #-}
  -- |
  -- License: GPL-3.0-or-later
  -- Copyright: Oleg Grenrus
  module CabalFmt.Refactoring (
      CommentsPragmas,
      refactor,
      ) where
  
  import qualified Distribution.Fields as C
  
  import CabalFmt.Monad
  import CabalFmt.Refactoring.ExpandExposedModules
  import CabalFmt.Refactoring.Fragments
  import CabalFmt.Refactoring.GlobFiles
  import CabalFmt.Refactoring.Type
  import CabalFmt.Fields.SourceFiles 
  
  -------------------------------------------------------------------------------
  -- Refactorings
  -------------------------------------------------------------------------------
  
  refactor :: forall m r. MonadCabalFmt r m => [C.Field CommentsPragmas] -> m [C.Field CommentsPragmas]
  refactor = rewriteFields rewrite
    where
      rewrite :: C.Field CommentsPragmas -> m (Maybe (C.Field CommentsPragmas))
      rewrite f@(C.Field (C.Name _ n) _)
          | n == "exposed-modules" || n == "other-modules" = combine
              [ refactoringFragments
              , refactoringExpandExposedModules
              ] f
          | n `elem` fileFields = combine
              [ refactoringFragments
              , refactoringGlobFiles
              ] f
          | otherwise = combine
              [ refactoringFragments
              ] f
  
      rewrite f@(C.Section _ _ _)
          | otherwise = combine
              [ refactoringFragments
              ] f
  
  -- | Try refactorings in turn,
  -- considering it done if one applies.
  combine
      :: Monad m
      => [C.Field CommentsPragmas -> m (Maybe (C.Field CommentsPragmas))]
      -> C.Field CommentsPragmas -> m (Maybe (C.Field CommentsPragmas))
  combine []     _ = return Nothing
  combine (r:rs) f = do
      m <- r f
      case m of
          Nothing -> combine rs f
          Just f' -> return (Just f')
  