hindent 5.3.4 → 6.0.0
raw patch · 48 files changed
+10183/−5354 lines, 48 filesdep +ghc-lib-parserdep +ghc-lib-parser-exdep +regex-tdfadep −ghc-primdep −haskell-src-extsdep −unix-compatdep ~basedep ~mtlsetup-changedPVP ok
version bump matches the API change (PVP)
Dependencies added: ghc-lib-parser, ghc-lib-parser-ex, regex-tdfa, split, syb, unicode-show
Dependencies removed: ghc-prim, haskell-src-exts, unix-compat
Dependency ranges changed: base, mtl
API changes (from Hackage documentation)
- HIndent: defaultExtensions :: [Extension]
- HIndent: getExtensions :: [Text] -> [Extension]
- HIndent: parseMode :: ParseMode
- HIndent: test :: ByteString -> IO ()
- HIndent: testFile :: FilePath -> IO ()
- HIndent: testFileAst :: FilePath -> IO ()
- HIndent.Pretty: instance GHC.Show.Show l => GHC.Show.Show (HIndent.Pretty.OpChainLink l)
- HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Exts.Syntax.Alt
- HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Exts.Syntax.Asst
- HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Exts.Syntax.BangType
- HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Exts.Syntax.Binds
- HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Exts.Syntax.BooleanFormula
- HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Exts.Syntax.Bracket
- HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Exts.Syntax.CallConv
- HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Exts.Syntax.ClassDecl
- HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Exts.Syntax.ConDecl
- HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Exts.Syntax.Context
- HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Exts.Syntax.DataOrNew
- HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Exts.Syntax.Decl
- HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Exts.Syntax.DeclHead
- HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Exts.Syntax.DerivStrategy
- HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Exts.Syntax.Deriving
- HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Exts.Syntax.Exp
- HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Exts.Syntax.ExportSpec
- HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Exts.Syntax.ExportSpecList
- HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Exts.Syntax.FieldDecl
- HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Exts.Syntax.FieldUpdate
- HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Exts.Syntax.FunDep
- HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Exts.Syntax.GadtDecl
- HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Exts.Syntax.GuardedRhs
- HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Exts.Syntax.IPBind
- HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Exts.Syntax.IPName
- HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Exts.Syntax.ImportDecl
- HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Exts.Syntax.ImportSpec
- HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Exts.Syntax.ImportSpecList
- HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Exts.Syntax.InjectivityInfo
- HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Exts.Syntax.InstDecl
- HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Exts.Syntax.InstHead
- HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Exts.Syntax.InstRule
- HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Exts.Syntax.Kind
- HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Exts.Syntax.Literal
- HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Exts.Syntax.Match
- HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Exts.Syntax.Module
- HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Exts.Syntax.ModuleHead
- HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Exts.Syntax.ModuleName
- HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Exts.Syntax.ModulePragma
- HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Exts.Syntax.Name
- HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Exts.Syntax.Overlap
- HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Exts.Syntax.Pat
- HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Exts.Syntax.PatField
- HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Exts.Syntax.QName
- HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Exts.Syntax.QOp
- HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Exts.Syntax.QualConDecl
- HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Exts.Syntax.QualStmt
- HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Exts.Syntax.ResultSig
- HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Exts.Syntax.Rhs
- HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Exts.Syntax.Safety
- HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Exts.Syntax.Sign
- HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Exts.Syntax.SpecialCon
- HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Exts.Syntax.Splice
- HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Exts.Syntax.Stmt
- HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Exts.Syntax.TyVarBind
- HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Exts.Syntax.Type
- HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Exts.Syntax.TypeEqn
- HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Exts.Syntax.Unpackedness
- HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Exts.Syntax.WarningText
- HIndent.Types: CommentAfterLine :: SrcSpan -> SomeComment -> NodeComment
- HIndent.Types: CommentBeforeLine :: SrcSpan -> SomeComment -> NodeComment
- HIndent.Types: CommentSameLine :: SrcSpan -> SomeComment -> NodeComment
- HIndent.Types: Config :: !Int64 -> !Int64 -> !Bool -> !Bool -> [String] -> [Extension] -> Config
- HIndent.Types: EndOfLine :: String -> SomeComment
- HIndent.Types: MultiLine :: String -> SomeComment
- HIndent.Types: NodeInfo :: !SrcSpanInfo -> ![NodeComment] -> NodeInfo
- HIndent.Types: PrintState :: !Int64 -> !Builder -> !Bool -> !Int64 -> !Int64 -> !Config -> !Bool -> !Bool -> !Bool -> PrintState
- HIndent.Types: Printer :: StateT PrintState (MaybeT Identity) a -> Printer a
- HIndent.Types: [configExtensions] :: Config -> [Extension]
- HIndent.Types: [configIndentSpaces] :: Config -> !Int64
- HIndent.Types: [configLineBreaks] :: Config -> [String]
- HIndent.Types: [configMaxColumns] :: Config -> !Int64
- HIndent.Types: [configSortImports] :: Config -> !Bool
- HIndent.Types: [configTrailingNewline] :: Config -> !Bool
- HIndent.Types: [nodeInfoComments] :: NodeInfo -> ![NodeComment]
- HIndent.Types: [nodeInfoSpan] :: NodeInfo -> !SrcSpanInfo
- HIndent.Types: [psColumn] :: PrintState -> !Int64
- HIndent.Types: [psConfig] :: PrintState -> !Config
- HIndent.Types: [psEolComment] :: PrintState -> !Bool
- HIndent.Types: [psFitOnOneLine] :: PrintState -> !Bool
- HIndent.Types: [psIndentLevel] :: PrintState -> !Int64
- HIndent.Types: [psInsideCase] :: PrintState -> !Bool
- HIndent.Types: [psLine] :: PrintState -> !Int64
- HIndent.Types: [psNewline] :: PrintState -> !Bool
- HIndent.Types: [psOutput] :: PrintState -> !Builder
- HIndent.Types: [runPrinter] :: Printer a -> StateT PrintState (MaybeT Identity) a
- HIndent.Types: data Config
- HIndent.Types: data NodeComment
- HIndent.Types: data NodeInfo
- HIndent.Types: data PrintState
- HIndent.Types: data SomeComment
- HIndent.Types: defaultConfig :: Config
- HIndent.Types: instance Control.Monad.State.Class.MonadState HIndent.Types.PrintState HIndent.Types.Printer
- HIndent.Types: instance Data.Aeson.Types.FromJSON.FromJSON HIndent.Types.Config
- HIndent.Types: instance GHC.Base.Alternative HIndent.Types.Printer
- HIndent.Types: instance GHC.Base.Applicative HIndent.Types.Printer
- HIndent.Types: instance GHC.Base.Functor HIndent.Types.Printer
- HIndent.Types: instance GHC.Base.Monad HIndent.Types.Printer
- HIndent.Types: instance GHC.Base.MonadPlus HIndent.Types.Printer
- HIndent.Types: instance GHC.Classes.Eq HIndent.Types.NodeComment
- HIndent.Types: instance GHC.Classes.Eq HIndent.Types.SomeComment
- HIndent.Types: instance GHC.Classes.Ord HIndent.Types.NodeComment
- HIndent.Types: instance GHC.Classes.Ord HIndent.Types.SomeComment
- HIndent.Types: instance GHC.Show.Show HIndent.Types.NodeComment
- HIndent.Types: instance GHC.Show.Show HIndent.Types.NodeInfo
- HIndent.Types: instance GHC.Show.Show HIndent.Types.SomeComment
- HIndent.Types: newtype Printer a
- HIndent.Types: readExtension :: Monad m => String -> m Extension
+ HIndent.Applicative: whenJust :: Applicative m => Maybe a -> (a -> m ()) -> m ()
+ HIndent.Config: Config :: !Int64 -> !Int64 -> !Bool -> !Bool -> [String] -> [Extension] -> Config
+ HIndent.Config: [configExtensions] :: Config -> [Extension]
+ HIndent.Config: [configIndentSpaces] :: Config -> !Int64
+ HIndent.Config: [configLineBreaks] :: Config -> [String]
+ HIndent.Config: [configMaxColumns] :: Config -> !Int64
+ HIndent.Config: [configSortImports] :: Config -> !Bool
+ HIndent.Config: [configTrailingNewline] :: Config -> !Bool
+ HIndent.Config: data Config
+ HIndent.Config: defaultConfig :: Config
+ HIndent.Config: getConfig :: IO Config
+ HIndent.Config: instance Data.Aeson.Types.FromJSON.FromJSON HIndent.Config.Config
+ HIndent.Language: convertLanguage :: HasCallStack => Language -> Language
+ HIndent.LanguageExtension: allExtensions :: [Extension]
+ HIndent.LanguageExtension: collectLanguageExtensionsFromSource :: String -> [Extension]
+ HIndent.LanguageExtension: defaultExtensions :: [Extension]
+ HIndent.LanguageExtension: extensionImplies :: Extension -> [Extension]
+ HIndent.LanguageExtension: getExtensions :: [Text] -> [Extension]
+ HIndent.LanguageExtension: implicitExtensions :: Language -> [Extension]
+ HIndent.LanguageExtension.Conversion: convertExtension :: KnownExtension -> Maybe Extension
+ HIndent.LanguageExtension.Conversion: fromCabalExtension :: Extension -> Maybe Extension
+ HIndent.LanguageExtension.Conversion: strToExt :: String -> Maybe Extension
+ HIndent.LanguageExtension.Conversion: uniqueExtensions :: [Extension] -> [Extension]
+ HIndent.LanguageExtension.Types: DisableExtension :: Extension -> Extension
+ HIndent.LanguageExtension.Types: EnableExtension :: Extension -> Extension
+ HIndent.LanguageExtension.Types: data Extension
+ HIndent.LanguageExtension.Types: instance GHC.Classes.Eq HIndent.LanguageExtension.Types.Extension
+ HIndent.ModulePreprocessing: modifyASTForPrettyPrinting :: HsModule -> HsModule
+ HIndent.ModulePreprocessing.CommentRelocation: relocateComments :: HsModule -> [LEpaComment] -> HsModule
+ HIndent.Parse: lexCode :: HasCallStack => String -> [Token]
+ HIndent.Parse: parseModule :: Maybe FilePath -> [Extension] -> String -> ParseResult HsModule
+ HIndent.Path.Find: findFileUp :: (MonadIO m, MonadThrow m) => Path Abs Dir -> (Path Abs File -> Bool) -> Maybe (Path Abs Dir) -> m (Maybe (Path Abs File))
+ HIndent.Pragma: extractPragmaNameAndElement :: String -> Maybe (String, String)
+ HIndent.Pragma: extractPragmasFromCode :: String -> [(String, String)]
+ HIndent.Pragma: pragmaRegex :: Regex
+ HIndent.Pretty: instance (HIndent.Pretty.NodeComments.CommentExtraction l, HIndent.Pretty.Pretty e) => HIndent.Pretty.Pretty (GHC.Types.SrcLoc.GenLocated l e)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (GHC.Hs.Doc.WithHsDocIdentifiers GHC.Types.SourceText.StringLiteral GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (GHC.Hs.ImpExp.IE GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (GHC.Hs.ImpExp.IEWrappedName GHC.Types.Name.Reader.RdrName)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (GHC.Hs.ImpExp.ImportDecl GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Binds.FixitySig GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Binds.HsBind GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Binds.HsIPBinds GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Binds.HsLocalBindsLR GHC.Hs.Extension.GhcPs GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Binds.HsPatSynDir GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Binds.HsValBindsLR GHC.Hs.Extension.GhcPs GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Binds.IPBind GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Binds.PatSynBind GHC.Hs.Extension.GhcPs GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Binds.RecordPatSynField GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Binds.Sig GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Decls.AnnDecl GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Decls.ClsInstDecl GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Decls.ConDecl GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Decls.DataFamInstDecl GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Decls.DefaultDecl GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Decls.DerivClauseTys GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Decls.DerivDecl GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Decls.DerivStrategy GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Decls.FamEqn GHC.Hs.Extension.GhcPs (GHC.Types.SrcLoc.GenLocated GHC.Parser.Annotation.SrcSpanAnnA (Language.Haskell.Syntax.Type.HsType GHC.Hs.Extension.GhcPs)))
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Decls.FamEqn GHC.Hs.Extension.GhcPs (Language.Haskell.Syntax.Decls.HsDataDefn GHC.Hs.Extension.GhcPs))
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Decls.FamilyDecl GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Decls.FamilyResultSig GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Decls.ForeignDecl GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Decls.HsDataDefn GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Decls.HsDecl GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Decls.HsDerivingClause GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Decls.InjectivityAnn GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Decls.InstDecl GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Decls.RoleAnnotDecl GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Decls.RuleBndr GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Decls.RuleDecl GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Decls.RuleDecls GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Decls.SpliceDecl GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Decls.StandaloneKindSig GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Decls.TyClDecl GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Decls.TyFamInstDecl GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Decls.WarnDecl GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Decls.WarnDecls GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Expr.ArithSeqInfo GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Expr.DotFieldOcc GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Expr.FieldLabelStrings GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Expr.GRHS GHC.Hs.Extension.GhcPs (GHC.Types.SrcLoc.GenLocated GHC.Parser.Annotation.SrcSpanAnnA (Language.Haskell.Syntax.Expr.HsExpr GHC.Hs.Extension.GhcPs)))
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Expr.GRHSs GHC.Hs.Extension.GhcPs (GHC.Types.SrcLoc.GenLocated GHC.Parser.Annotation.SrcSpanAnnA (Language.Haskell.Syntax.Expr.HsCmd GHC.Hs.Extension.GhcPs)))
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Expr.GRHSs GHC.Hs.Extension.GhcPs (GHC.Types.SrcLoc.GenLocated GHC.Parser.Annotation.SrcSpanAnnA (Language.Haskell.Syntax.Expr.HsExpr GHC.Hs.Extension.GhcPs)))
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Expr.HsCmd GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Expr.HsCmdTop GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Expr.HsExpr GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Expr.HsMatchContext GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Expr.HsPragE GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Expr.HsQuote GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Expr.HsSplice GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Expr.HsTupArg GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Expr.Match GHC.Hs.Extension.GhcPs (GHC.Types.SrcLoc.GenLocated GHC.Parser.Annotation.SrcSpanAnnA (Language.Haskell.Syntax.Expr.HsCmd GHC.Hs.Extension.GhcPs)))
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Expr.Match GHC.Hs.Extension.GhcPs (GHC.Types.SrcLoc.GenLocated GHC.Parser.Annotation.SrcSpanAnnA (Language.Haskell.Syntax.Expr.HsExpr GHC.Hs.Extension.GhcPs)))
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Expr.MatchGroup GHC.Hs.Extension.GhcPs (GHC.Types.SrcLoc.GenLocated GHC.Parser.Annotation.SrcSpanAnnA (Language.Haskell.Syntax.Expr.HsCmd GHC.Hs.Extension.GhcPs)))
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Expr.MatchGroup GHC.Hs.Extension.GhcPs (GHC.Types.SrcLoc.GenLocated GHC.Parser.Annotation.SrcSpanAnnA (Language.Haskell.Syntax.Expr.HsExpr GHC.Hs.Extension.GhcPs)))
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Expr.ParStmtBlock GHC.Hs.Extension.GhcPs GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Expr.StmtLR GHC.Hs.Extension.GhcPs GHC.Hs.Extension.GhcPs (GHC.Types.SrcLoc.GenLocated GHC.Parser.Annotation.SrcSpanAnnA (Language.Haskell.Syntax.Expr.HsCmd GHC.Hs.Extension.GhcPs)))
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Expr.StmtLR GHC.Hs.Extension.GhcPs GHC.Hs.Extension.GhcPs (GHC.Types.SrcLoc.GenLocated GHC.Parser.Annotation.SrcSpanAnnA (Language.Haskell.Syntax.Expr.HsExpr GHC.Hs.Extension.GhcPs)))
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Lit.HsLit GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Lit.HsOverLit GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Pat.HsFieldBind (GHC.Types.SrcLoc.GenLocated (GHC.Parser.Annotation.SrcAnn GHC.Parser.Annotation.NoEpAnns) (Language.Haskell.Syntax.Type.FieldOcc GHC.Hs.Extension.GhcPs)) (GHC.Types.SrcLoc.GenLocated GHC.Parser.Annotation.SrcSpanAnnA (Language.Haskell.Syntax.Expr.HsExpr GHC.Hs.Extension.GhcPs)))
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Pat.HsFieldBind (GHC.Types.SrcLoc.GenLocated (GHC.Parser.Annotation.SrcAnn GHC.Parser.Annotation.NoEpAnns) (Language.Haskell.Syntax.Type.FieldOcc GHC.Hs.Extension.GhcPs)) (GHC.Types.SrcLoc.GenLocated GHC.Parser.Annotation.SrcSpanAnnA (Language.Haskell.Syntax.Pat.Pat GHC.Hs.Extension.GhcPs)))
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Pat.HsRecFields GHC.Hs.Extension.GhcPs (GHC.Types.SrcLoc.GenLocated GHC.Parser.Annotation.SrcSpanAnnA (Language.Haskell.Syntax.Expr.HsExpr GHC.Hs.Extension.GhcPs)))
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Pat.HsRecFields GHC.Hs.Extension.GhcPs (GHC.Types.SrcLoc.GenLocated GHC.Parser.Annotation.SrcSpanAnnA (Language.Haskell.Syntax.Pat.Pat GHC.Hs.Extension.GhcPs)))
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Pat.Pat GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Type.AmbiguousFieldOcc GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Type.ConDeclField GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Type.FieldOcc GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Type.HsArg (GHC.Types.SrcLoc.GenLocated GHC.Parser.Annotation.SrcSpanAnnA (Language.Haskell.Syntax.Type.HsType GHC.Hs.Extension.GhcPs)) (GHC.Types.SrcLoc.GenLocated GHC.Parser.Annotation.SrcSpanAnnA (Language.Haskell.Syntax.Type.HsType GHC.Hs.Extension.GhcPs)))
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Type.HsConDetails Data.Void.Void (GHC.Types.SrcLoc.GenLocated GHC.Parser.Annotation.SrcSpanAnnN GHC.Types.Name.Reader.RdrName) [Language.Haskell.Syntax.Binds.RecordPatSynField GHC.Hs.Extension.GhcPs])
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Type.HsConDetails Data.Void.Void (Language.Haskell.Syntax.Type.HsScaled GHC.Hs.Extension.GhcPs (GHC.Types.SrcLoc.GenLocated GHC.Parser.Annotation.SrcSpanAnnA (Language.Haskell.Syntax.Type.BangType GHC.Hs.Extension.GhcPs))) (GHC.Types.SrcLoc.GenLocated GHC.Parser.Annotation.SrcSpanAnnL [GHC.Types.SrcLoc.GenLocated GHC.Parser.Annotation.SrcSpanAnnA (Language.Haskell.Syntax.Type.ConDeclField GHC.Hs.Extension.GhcPs)]))
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Type.HsForAllTelescope GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Type.HsOuterSigTyVarBndrs GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Type.HsPatSigType GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Type.HsSigType GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Type.HsTyVarBndr a GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Type.HsType GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Type.HsWildCardBndrs GHC.Hs.Extension.GhcPs (GHC.Types.SrcLoc.GenLocated GHC.Parser.Annotation.SrcSpanAnnA (Language.Haskell.Syntax.Type.HsSigType GHC.Hs.Extension.GhcPs)))
+ HIndent.Pretty: instance HIndent.Pretty.Pretty (Language.Haskell.Syntax.Type.HsWildCardBndrs GHC.Hs.Extension.GhcPs (GHC.Types.SrcLoc.GenLocated GHC.Parser.Annotation.SrcSpanAnnA (Language.Haskell.Syntax.Type.HsType GHC.Hs.Extension.GhcPs)))
+ HIndent.Pretty: instance HIndent.Pretty.Pretty GHC.Core.Coercion.Axiom.Role
+ HIndent.Pretty: instance HIndent.Pretty.Pretty GHC.Core.DataCon.HsSrcBang
+ HIndent.Pretty: instance HIndent.Pretty.Pretty GHC.Core.DataCon.SrcStrictness
+ HIndent.Pretty: instance HIndent.Pretty.Pretty GHC.Core.DataCon.SrcUnpackedness
+ HIndent.Pretty: instance HIndent.Pretty.Pretty GHC.Hs.Decls.XViaStrategyPs
+ HIndent.Pretty: instance HIndent.Pretty.Pretty GHC.Hs.HsModule
+ HIndent.Pretty: instance HIndent.Pretty.Pretty GHC.Parser.Annotation.EpaComment
+ HIndent.Pretty: instance HIndent.Pretty.Pretty GHC.Parser.Annotation.EpaCommentTok
+ HIndent.Pretty: instance HIndent.Pretty.Pretty GHC.Types.Basic.InlinePragma
+ HIndent.Pretty: instance HIndent.Pretty.Pretty GHC.Types.Basic.InlineSpec
+ HIndent.Pretty: instance HIndent.Pretty.Pretty GHC.Types.Basic.OverlapMode
+ HIndent.Pretty: instance HIndent.Pretty.Pretty GHC.Types.Fixity.Fixity
+ HIndent.Pretty: instance HIndent.Pretty.Pretty GHC.Types.Fixity.FixityDirection
+ HIndent.Pretty: instance HIndent.Pretty.Pretty GHC.Types.ForeignCall.CCallConv
+ HIndent.Pretty: instance HIndent.Pretty.Pretty GHC.Types.ForeignCall.CExportSpec
+ HIndent.Pretty: instance HIndent.Pretty.Pretty GHC.Types.ForeignCall.Safety
+ HIndent.Pretty: instance HIndent.Pretty.Pretty GHC.Types.Name.Occurrence.OccName
+ HIndent.Pretty: instance HIndent.Pretty.Pretty GHC.Types.Name.Reader.RdrName
+ HIndent.Pretty: instance HIndent.Pretty.Pretty GHC.Types.SourceText.FractionalLit
+ HIndent.Pretty: instance HIndent.Pretty.Pretty GHC.Types.SourceText.IntegralLit
+ HIndent.Pretty: instance HIndent.Pretty.Pretty GHC.Types.SourceText.StringLiteral
+ HIndent.Pretty: instance HIndent.Pretty.Pretty GHC.Unit.Module.Name.ModuleName
+ HIndent.Pretty: instance HIndent.Pretty.Pretty HIndent.Pretty.SigBindFamily.SigBindFamily
+ HIndent.Pretty: instance HIndent.Pretty.Pretty HIndent.Pretty.Types.Context
+ HIndent.Pretty: instance HIndent.Pretty.Pretty HIndent.Pretty.Types.DataFamInstDecl'
+ HIndent.Pretty: instance HIndent.Pretty.Pretty HIndent.Pretty.Types.DeclSig
+ HIndent.Pretty: instance HIndent.Pretty.Pretty HIndent.Pretty.Types.DoExpression
+ HIndent.Pretty: instance HIndent.Pretty.Pretty HIndent.Pretty.Types.FamEqn'
+ HIndent.Pretty: instance HIndent.Pretty.Pretty HIndent.Pretty.Types.GRHSExpr
+ HIndent.Pretty: instance HIndent.Pretty.Pretty HIndent.Pretty.Types.GRHSProc
+ HIndent.Pretty: instance HIndent.Pretty.Pretty HIndent.Pretty.Types.GRHSsExpr
+ HIndent.Pretty: instance HIndent.Pretty.Pretty HIndent.Pretty.Types.HorizontalContext
+ HIndent.Pretty: instance HIndent.Pretty.Pretty HIndent.Pretty.Types.HsSigType'
+ HIndent.Pretty: instance HIndent.Pretty.Pretty HIndent.Pretty.Types.HsType'
+ HIndent.Pretty: instance HIndent.Pretty.Pretty HIndent.Pretty.Types.InfixApp
+ HIndent.Pretty: instance HIndent.Pretty.Pretty HIndent.Pretty.Types.InfixExpr
+ HIndent.Pretty: instance HIndent.Pretty.Pretty HIndent.Pretty.Types.InfixOp
+ HIndent.Pretty: instance HIndent.Pretty.Pretty HIndent.Pretty.Types.LambdaCase
+ HIndent.Pretty: instance HIndent.Pretty.Pretty HIndent.Pretty.Types.LetIn
+ HIndent.Pretty: instance HIndent.Pretty.Pretty HIndent.Pretty.Types.ListComprehension
+ HIndent.Pretty: instance HIndent.Pretty.Pretty HIndent.Pretty.Types.ModuleDeprecatedPragma
+ HIndent.Pretty: instance HIndent.Pretty.Pretty HIndent.Pretty.Types.ModuleNameWithPrefix
+ HIndent.Pretty: instance HIndent.Pretty.Pretty HIndent.Pretty.Types.ParStmtBlockInsideVerticalList
+ HIndent.Pretty: instance HIndent.Pretty.Pretty HIndent.Pretty.Types.PatInsidePatDecl
+ HIndent.Pretty: instance HIndent.Pretty.Pretty HIndent.Pretty.Types.PrefixOp
+ HIndent.Pretty: instance HIndent.Pretty.Pretty HIndent.Pretty.Types.RecConField
+ HIndent.Pretty: instance HIndent.Pretty.Pretty HIndent.Pretty.Types.RecConPat
+ HIndent.Pretty: instance HIndent.Pretty.Pretty HIndent.Pretty.Types.StmtLRInsideVerticalList
+ HIndent.Pretty: instance HIndent.Pretty.Pretty HIndent.Pretty.Types.TopLevelTyFamInstDecl
+ HIndent.Pretty: instance HIndent.Pretty.Pretty HIndent.Pretty.Types.VerticalContext
+ HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Syntax.Decls.ForeignExport
+ HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Syntax.Decls.ForeignImport
+ HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Syntax.Lit.OverLitVal
+ HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Syntax.Type.HsIPName
+ HIndent.Pretty: instance HIndent.Pretty.Pretty Language.Haskell.Syntax.Type.HsTyLit
+ HIndent.Pretty: instance HIndent.Pretty.Pretty a => HIndent.Pretty.Pretty (GHC.Data.BooleanFormula.BooleanFormula a)
+ HIndent.Pretty: instance HIndent.Pretty.Pretty a => HIndent.Pretty.Pretty (Language.Haskell.Syntax.Type.HsScaled GHC.Hs.Extension.GhcPs a)
+ HIndent.Pretty.Combinators.Comment: eolCommentsArePrinted :: Printer ()
+ HIndent.Pretty.Combinators.Getter: printerLength :: Printer a -> Printer Int64
+ HIndent.Pretty.Combinators.Getter: startingColumn :: Printer Int64
+ HIndent.Pretty.Combinators.Indent: (|=>) :: Printer () -> Printer a -> Printer a
+ HIndent.Pretty.Combinators.Indent: getIndentSpaces :: Printer Int64
+ HIndent.Pretty.Combinators.Indent: indentedBlock :: Printer a -> Printer a
+ HIndent.Pretty.Combinators.Indent: indentedWithFixedLevel :: Int64 -> Printer a -> Printer a
+ HIndent.Pretty.Combinators.Indent: indentedWithSpace :: Int64 -> Printer a -> Printer a
+ HIndent.Pretty.Combinators.Indent: infixl 1 |=>
+ HIndent.Pretty.Combinators.Indent: prefixed :: String -> Printer () -> Printer ()
+ HIndent.Pretty.Combinators.Lineup: blanklined :: [Printer ()] -> Printer ()
+ HIndent.Pretty.Combinators.Lineup: hBarSep :: [Printer ()] -> Printer ()
+ HIndent.Pretty.Combinators.Lineup: hCommaSep :: [Printer ()] -> Printer ()
+ HIndent.Pretty.Combinators.Lineup: hDotSep :: [Printer ()] -> Printer ()
+ HIndent.Pretty.Combinators.Lineup: hFields :: [Printer ()] -> Printer ()
+ HIndent.Pretty.Combinators.Lineup: hList :: [Printer ()] -> Printer ()
+ HIndent.Pretty.Combinators.Lineup: hPromotedTuple :: [Printer ()] -> Printer ()
+ HIndent.Pretty.Combinators.Lineup: hTuple :: [Printer ()] -> Printer ()
+ HIndent.Pretty.Combinators.Lineup: hUnboxedTuple :: [Printer ()] -> Printer ()
+ HIndent.Pretty.Combinators.Lineup: hvBarSep :: [Printer ()] -> Printer ()
+ HIndent.Pretty.Combinators.Lineup: hvCommaSep :: [Printer ()] -> Printer ()
+ HIndent.Pretty.Combinators.Lineup: hvFields :: [Printer ()] -> Printer ()
+ HIndent.Pretty.Combinators.Lineup: hvPromotedList :: [Printer ()] -> Printer ()
+ HIndent.Pretty.Combinators.Lineup: hvTuple :: [Printer ()] -> Printer ()
+ HIndent.Pretty.Combinators.Lineup: hvTuple' :: [Printer ()] -> Printer ()
+ HIndent.Pretty.Combinators.Lineup: hvUnboxedSum' :: [Printer ()] -> Printer ()
+ HIndent.Pretty.Combinators.Lineup: hvUnboxedTuple' :: [Printer ()] -> Printer ()
+ HIndent.Pretty.Combinators.Lineup: inter :: Printer () -> [Printer ()] -> Printer ()
+ HIndent.Pretty.Combinators.Lineup: lined :: [Printer ()] -> Printer ()
+ HIndent.Pretty.Combinators.Lineup: newlinePrefixed :: [Printer ()] -> Printer ()
+ HIndent.Pretty.Combinators.Lineup: prefixedLined :: String -> [Printer ()] -> Printer ()
+ HIndent.Pretty.Combinators.Lineup: spacePrefixed :: [Printer ()] -> Printer ()
+ HIndent.Pretty.Combinators.Lineup: spaced :: [Printer ()] -> Printer ()
+ HIndent.Pretty.Combinators.Lineup: vBarSep :: [Printer ()] -> Printer ()
+ HIndent.Pretty.Combinators.Lineup: vCommaSep :: [Printer ()] -> Printer ()
+ HIndent.Pretty.Combinators.Lineup: vFields :: [Printer ()] -> Printer ()
+ HIndent.Pretty.Combinators.Lineup: vFields' :: [Printer ()] -> Printer ()
+ HIndent.Pretty.Combinators.Lineup: vList :: [Printer ()] -> Printer ()
+ HIndent.Pretty.Combinators.Lineup: vTuple :: [Printer ()] -> Printer ()
+ HIndent.Pretty.Combinators.Lineup: vTuple' :: [Printer ()] -> Printer ()
+ HIndent.Pretty.Combinators.Op: unlessSpecialOp :: RdrName -> Printer () -> Printer ()
+ HIndent.Pretty.Combinators.Outputable: output :: (HasCallStack, Outputable a) => a -> Printer ()
+ HIndent.Pretty.Combinators.Outputable: showOutputable :: Outputable a => a -> String
+ HIndent.Pretty.Combinators.RhsSeparator: rhsSeparator :: GRHSExprType -> Printer ()
+ HIndent.Pretty.Combinators.String: blankline :: Printer ()
+ HIndent.Pretty.Combinators.String: comma :: Printer ()
+ HIndent.Pretty.Combinators.String: dot :: Printer ()
+ HIndent.Pretty.Combinators.String: newline :: Printer ()
+ HIndent.Pretty.Combinators.String: space :: Printer ()
+ HIndent.Pretty.Combinators.String: string :: HasCallStack => String -> Printer ()
+ HIndent.Pretty.Combinators.Switch: (<-|>) :: Printer a -> Printer a -> Printer a
+ HIndent.Pretty.Combinators.Wrap: backticks :: Printer a -> Printer a
+ HIndent.Pretty.Combinators.Wrap: backticksIfNotSymbol :: OccName -> Printer a -> Printer a
+ HIndent.Pretty.Combinators.Wrap: bananaBrackets :: Printer a -> Printer a
+ HIndent.Pretty.Combinators.Wrap: braces :: Printer a -> Printer a
+ HIndent.Pretty.Combinators.Wrap: brackets :: Printer a -> Printer a
+ HIndent.Pretty.Combinators.Wrap: doubleQuotes :: Printer a -> Printer a
+ HIndent.Pretty.Combinators.Wrap: parens :: Printer a -> Printer a
+ HIndent.Pretty.Combinators.Wrap: parensIfSymbol :: OccName -> Printer a -> Printer a
+ HIndent.Pretty.Combinators.Wrap: promotedListBrackets :: Printer a -> Printer a
+ HIndent.Pretty.Combinators.Wrap: promotedTupleParens :: Printer a -> Printer a
+ HIndent.Pretty.Combinators.Wrap: typedBrackets :: Printer a -> Printer a
+ HIndent.Pretty.Combinators.Wrap: unboxedParens :: Printer a -> Printer a
+ HIndent.Pretty.Combinators.Wrap: wrapWithBars :: Printer a -> Printer a
+ HIndent.Pretty.Import: extractImports :: HsModule -> [[LImportDecl GhcPs]]
+ HIndent.Pretty.Import: extractImportsSorted :: HsModule -> [[LImportDecl GhcPs]]
+ HIndent.Pretty.Import: groupImports :: [LImportDecl GhcPs] -> [[LImportDecl GhcPs]]
+ HIndent.Pretty.Import: importsExist :: HsModule -> Bool
+ HIndent.Pretty.Import.Sort: instance GHC.Classes.Eq HIndent.Pretty.Import.Sort.LetterType
+ HIndent.Pretty.Import.Sort: instance GHC.Classes.Ord HIndent.Pretty.Import.Sort.LetterType
+ HIndent.Pretty.Import.Sort: sortImportsByLocation :: [LImportDecl GhcPs] -> [LImportDecl GhcPs]
+ HIndent.Pretty.Import.Sort: sortImportsByName :: [LImportDecl GhcPs] -> [LImportDecl GhcPs]
+ HIndent.Pretty.NodeComments: class CommentExtraction a
+ HIndent.Pretty.NodeComments: emptyNodeComments :: NodeComments
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (GHC.Data.BooleanFormula.BooleanFormula a)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (GHC.Hs.Doc.WithHsDocIdentifiers GHC.Types.SourceText.StringLiteral GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (GHC.Hs.ImpExp.IE GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (GHC.Hs.ImpExp.IEWrappedName GHC.Types.Name.Reader.RdrName)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (GHC.Hs.ImpExp.ImportDecl GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (GHC.Parser.Annotation.EpAnn a)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (GHC.Parser.Annotation.SrcAnn a)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Binds.FixitySig GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Binds.HsBind GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Binds.HsIPBinds GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Binds.HsLocalBindsLR GHC.Hs.Extension.GhcPs GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Binds.HsPatSynDir GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Binds.HsValBindsLR GHC.Hs.Extension.GhcPs GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Binds.IPBind GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Binds.PatSynBind GHC.Hs.Extension.GhcPs GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Binds.RecordPatSynField GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Binds.Sig GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Decls.AnnDecl GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Decls.ClsInstDecl GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Decls.ConDecl GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Decls.DataFamInstDecl GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Decls.DefaultDecl GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Decls.DerivClauseTys GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Decls.DerivDecl GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Decls.DerivStrategy GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Decls.FamEqn GHC.Hs.Extension.GhcPs (GHC.Types.SrcLoc.GenLocated GHC.Parser.Annotation.SrcSpanAnnA (Language.Haskell.Syntax.Type.HsType GHC.Hs.Extension.GhcPs)))
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Decls.FamEqn GHC.Hs.Extension.GhcPs (Language.Haskell.Syntax.Decls.HsDataDefn GHC.Hs.Extension.GhcPs))
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Decls.FamilyDecl GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Decls.FamilyResultSig GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Decls.ForeignDecl GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Decls.HsDataDefn GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Decls.HsDecl GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Decls.HsDerivingClause GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Decls.InjectivityAnn GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Decls.InstDecl GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Decls.RoleAnnotDecl GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Decls.RuleBndr GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Decls.RuleDecl GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Decls.RuleDecls GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Decls.SpliceDecl GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Decls.StandaloneKindSig GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Decls.TyClDecl GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Decls.TyFamInstDecl GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Decls.WarnDecl GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Decls.WarnDecls GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Expr.ArithSeqInfo GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Expr.DotFieldOcc GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Expr.FieldLabelStrings GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Expr.GRHS GHC.Hs.Extension.GhcPs (GHC.Types.SrcLoc.GenLocated GHC.Parser.Annotation.SrcSpanAnnA (Language.Haskell.Syntax.Expr.HsExpr GHC.Hs.Extension.GhcPs)))
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Expr.GRHSs GHC.Hs.Extension.GhcPs a)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Expr.HsCmd GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Expr.HsCmdTop GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Expr.HsExpr GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Expr.HsMatchContext GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Expr.HsPragE GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Expr.HsQuote GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Expr.HsSplice GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Expr.HsTupArg GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Expr.Match GHC.Hs.Extension.GhcPs a)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Expr.MatchGroup GHC.Hs.Extension.GhcPs a)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Expr.ParStmtBlock GHC.Hs.Extension.GhcPs GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Expr.StmtLR GHC.Hs.Extension.GhcPs GHC.Hs.Extension.GhcPs (GHC.Types.SrcLoc.GenLocated GHC.Parser.Annotation.SrcSpanAnnA (Language.Haskell.Syntax.Expr.HsCmd GHC.Hs.Extension.GhcPs)))
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Expr.StmtLR GHC.Hs.Extension.GhcPs GHC.Hs.Extension.GhcPs (GHC.Types.SrcLoc.GenLocated GHC.Parser.Annotation.SrcSpanAnnA (Language.Haskell.Syntax.Expr.HsExpr GHC.Hs.Extension.GhcPs)))
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Lit.HsLit GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Lit.HsOverLit GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Pat.HsFieldBind (GHC.Types.SrcLoc.GenLocated (GHC.Parser.Annotation.SrcAnn GHC.Parser.Annotation.NoEpAnns) (Language.Haskell.Syntax.Type.FieldOcc GHC.Hs.Extension.GhcPs)) (GHC.Types.SrcLoc.GenLocated GHC.Parser.Annotation.SrcSpanAnnA (Language.Haskell.Syntax.Expr.HsExpr GHC.Hs.Extension.GhcPs)))
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Pat.HsFieldBind (GHC.Types.SrcLoc.GenLocated (GHC.Parser.Annotation.SrcAnn GHC.Parser.Annotation.NoEpAnns) (Language.Haskell.Syntax.Type.FieldOcc GHC.Hs.Extension.GhcPs)) (GHC.Types.SrcLoc.GenLocated GHC.Parser.Annotation.SrcSpanAnnA (Language.Haskell.Syntax.Pat.Pat GHC.Hs.Extension.GhcPs)))
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Pat.HsRecFields GHC.Hs.Extension.GhcPs (GHC.Types.SrcLoc.GenLocated GHC.Parser.Annotation.SrcSpanAnnA (Language.Haskell.Syntax.Expr.HsExpr GHC.Hs.Extension.GhcPs)))
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Pat.HsRecFields GHC.Hs.Extension.GhcPs (GHC.Types.SrcLoc.GenLocated GHC.Parser.Annotation.SrcSpanAnnA (Language.Haskell.Syntax.Pat.Pat GHC.Hs.Extension.GhcPs)))
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Pat.Pat GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Type.AmbiguousFieldOcc GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Type.ConDeclField GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Type.FieldOcc GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Type.HsArg (GHC.Types.SrcLoc.GenLocated GHC.Parser.Annotation.SrcSpanAnnA (Language.Haskell.Syntax.Type.HsType GHC.Hs.Extension.GhcPs)) (GHC.Types.SrcLoc.GenLocated GHC.Parser.Annotation.SrcSpanAnnA (Language.Haskell.Syntax.Type.HsType GHC.Hs.Extension.GhcPs)))
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Type.HsConDetails Data.Void.Void (GHC.Types.SrcLoc.GenLocated GHC.Parser.Annotation.SrcSpanAnnN GHC.Types.Name.Reader.RdrName) [Language.Haskell.Syntax.Binds.RecordPatSynField GHC.Hs.Extension.GhcPs])
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Type.HsConDetails Data.Void.Void (Language.Haskell.Syntax.Type.HsScaled GHC.Hs.Extension.GhcPs (GHC.Types.SrcLoc.GenLocated GHC.Parser.Annotation.SrcSpanAnnA (Language.Haskell.Syntax.Type.BangType GHC.Hs.Extension.GhcPs))) (GHC.Types.SrcLoc.GenLocated GHC.Parser.Annotation.SrcSpanAnnL [GHC.Types.SrcLoc.GenLocated GHC.Parser.Annotation.SrcSpanAnnA (Language.Haskell.Syntax.Type.ConDeclField GHC.Hs.Extension.GhcPs)]))
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Type.HsForAllTelescope GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Type.HsOuterSigTyVarBndrs GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Type.HsPatSigType GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Type.HsScaled GHC.Hs.Extension.GhcPs a)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Type.HsSigType GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Type.HsTyVarBndr a GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Type.HsType GHC.Hs.Extension.GhcPs)
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Type.HsWildCardBndrs GHC.Hs.Extension.GhcPs (GHC.Types.SrcLoc.GenLocated GHC.Parser.Annotation.SrcSpanAnnA (Language.Haskell.Syntax.Type.HsSigType GHC.Hs.Extension.GhcPs)))
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction (Language.Haskell.Syntax.Type.HsWildCardBndrs GHC.Hs.Extension.GhcPs (GHC.Types.SrcLoc.GenLocated GHC.Parser.Annotation.SrcSpanAnnA (Language.Haskell.Syntax.Type.HsType GHC.Hs.Extension.GhcPs)))
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction GHC.Core.Coercion.Axiom.Role
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction GHC.Core.DataCon.HsSrcBang
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction GHC.Core.DataCon.SrcStrictness
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction GHC.Core.DataCon.SrcUnpackedness
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction GHC.Hs.Decls.XViaStrategyPs
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction GHC.Hs.HsModule
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction GHC.Parser.Annotation.Anchor
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction GHC.Parser.Annotation.EpaComment
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction GHC.Parser.Annotation.EpaCommentTok
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction GHC.Types.Basic.InlinePragma
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction GHC.Types.Basic.InlineSpec
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction GHC.Types.Basic.OverlapMode
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction GHC.Types.Fixity.Fixity
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction GHC.Types.Fixity.FixityDirection
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction GHC.Types.ForeignCall.CCallConv
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction GHC.Types.ForeignCall.CExportSpec
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction GHC.Types.ForeignCall.Safety
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction GHC.Types.Name.Occurrence.OccName
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction GHC.Types.Name.Reader.RdrName
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction GHC.Types.SourceText.FractionalLit
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction GHC.Types.SourceText.IntegralLit
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction GHC.Types.SourceText.StringLiteral
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction GHC.Types.SrcLoc.SrcSpan
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction GHC.Unit.Module.Name.ModuleName
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction HIndent.Pretty.SigBindFamily.SigBindFamily
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction HIndent.Pretty.Types.Context
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction HIndent.Pretty.Types.DataFamInstDecl'
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction HIndent.Pretty.Types.DeclSig
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction HIndent.Pretty.Types.DoExpression
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction HIndent.Pretty.Types.FamEqn'
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction HIndent.Pretty.Types.GRHSExpr
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction HIndent.Pretty.Types.GRHSProc
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction HIndent.Pretty.Types.GRHSsExpr
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction HIndent.Pretty.Types.HorizontalContext
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction HIndent.Pretty.Types.HsSigType'
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction HIndent.Pretty.Types.HsType'
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction HIndent.Pretty.Types.InfixApp
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction HIndent.Pretty.Types.InfixExpr
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction HIndent.Pretty.Types.InfixOp
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction HIndent.Pretty.Types.LambdaCase
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction HIndent.Pretty.Types.LetIn
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction HIndent.Pretty.Types.ListComprehension
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction HIndent.Pretty.Types.ModuleDeprecatedPragma
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction HIndent.Pretty.Types.ModuleNameWithPrefix
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction HIndent.Pretty.Types.ParStmtBlockInsideVerticalList
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction HIndent.Pretty.Types.PatInsidePatDecl
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction HIndent.Pretty.Types.PrefixOp
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction HIndent.Pretty.Types.RecConField
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction HIndent.Pretty.Types.RecConPat
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction HIndent.Pretty.Types.StmtLRInsideVerticalList
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction HIndent.Pretty.Types.TopLevelTyFamInstDecl
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction HIndent.Pretty.Types.VerticalContext
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction Language.Haskell.Syntax.Decls.ForeignExport
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction Language.Haskell.Syntax.Decls.ForeignImport
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction Language.Haskell.Syntax.Lit.OverLitVal
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction Language.Haskell.Syntax.Type.HsIPName
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction Language.Haskell.Syntax.Type.HsTyLit
+ HIndent.Pretty.NodeComments: instance HIndent.Pretty.NodeComments.CommentExtraction l => HIndent.Pretty.NodeComments.CommentExtraction (GHC.Types.SrcLoc.GenLocated l e)
+ HIndent.Pretty.NodeComments: nodeComments :: CommentExtraction a => a -> NodeComments
+ HIndent.Pretty.Pragma: isPragma :: EpaCommentTok -> Bool
+ HIndent.Pretty.Pragma: pragmaExists :: HsModule -> Bool
+ HIndent.Pretty.Pragma: prettyPragmas :: HsModule -> Printer ()
+ HIndent.Pretty.SigBindFamily: Bind :: HsBindLR GhcPs GhcPs -> SigBindFamily
+ HIndent.Pretty.SigBindFamily: DataFamInst :: DataFamInstDecl GhcPs -> SigBindFamily
+ HIndent.Pretty.SigBindFamily: Sig :: Sig GhcPs -> SigBindFamily
+ HIndent.Pretty.SigBindFamily: TyFamInst :: TyFamInstDecl GhcPs -> SigBindFamily
+ HIndent.Pretty.SigBindFamily: TypeFamily :: FamilyDecl GhcPs -> SigBindFamily
+ HIndent.Pretty.SigBindFamily: data SigBindFamily
+ HIndent.Pretty.SigBindFamily: filterLBind :: [LSigBindFamily] -> [LHsBindLR GhcPs GhcPs]
+ HIndent.Pretty.SigBindFamily: filterLSig :: [LSigBindFamily] -> [LSig GhcPs]
+ HIndent.Pretty.SigBindFamily: mkLSigBindFamilyList :: [LSig GhcPs] -> [LHsBindLR GhcPs GhcPs] -> [LFamilyDecl GhcPs] -> [LTyFamInstDecl GhcPs] -> [LDataFamInstDecl GhcPs] -> [LSigBindFamily]
+ HIndent.Pretty.SigBindFamily: mkSortedLSigBindFamilyList :: [LSig GhcPs] -> [LHsBindLR GhcPs GhcPs] -> [LFamilyDecl GhcPs] -> [LTyFamInstDecl GhcPs] -> [LDataFamInstDecl GhcPs] -> [LSigBindFamily]
+ HIndent.Pretty.SigBindFamily: type LSigBindFamily = GenLocated SrcSpanAnnA SigBindFamily
+ HIndent.Pretty.Types: Case :: CaseOrCases
+ HIndent.Pretty.Types: Cases :: CaseOrCases
+ HIndent.Pretty.Types: Context :: LHsContext GhcPs -> Context
+ HIndent.Pretty.Types: DataFamInstDecl' :: DataFamInstDeclFor -> DataFamInstDecl GhcPs -> DataFamInstDecl'
+ HIndent.Pretty.Types: DataFamInstDeclForInsideClassInst :: DataFamInstDeclFor
+ HIndent.Pretty.Types: DataFamInstDeclForTopLevel :: DataFamInstDeclFor
+ HIndent.Pretty.Types: DeclSig :: Sig GhcPs -> DeclSig
+ HIndent.Pretty.Types: Do :: DoOrMdo
+ HIndent.Pretty.Types: DoExpression :: [ExprLStmt GhcPs] -> DoOrMdo -> DoExpression
+ HIndent.Pretty.Types: FamEqn' :: DataFamInstDeclFor -> FamEqn GhcPs (HsDataDefn GhcPs) -> FamEqn'
+ HIndent.Pretty.Types: GRHSExpr :: GRHSExprType -> GRHS GhcPs (LHsExpr GhcPs) -> GRHSExpr
+ HIndent.Pretty.Types: GRHSExprCase :: GRHSExprType
+ HIndent.Pretty.Types: GRHSExprLambda :: GRHSExprType
+ HIndent.Pretty.Types: GRHSExprMultiWayIf :: GRHSExprType
+ HIndent.Pretty.Types: GRHSExprNormal :: GRHSExprType
+ HIndent.Pretty.Types: GRHSProc :: GRHS GhcPs (LHsCmd GhcPs) -> GRHSProc
+ HIndent.Pretty.Types: GRHSProcCase :: GRHSProcType
+ HIndent.Pretty.Types: GRHSProcLambda :: GRHSProcType
+ HIndent.Pretty.Types: GRHSsExpr :: GRHSExprType -> GRHSs GhcPs (LHsExpr GhcPs) -> GRHSsExpr
+ HIndent.Pretty.Types: HorizontalContext :: LHsContext GhcPs -> HorizontalContext
+ HIndent.Pretty.Types: HsSigType' :: HsTypeFor -> HsTypeDir -> HsSigType GhcPs -> HsSigType'
+ HIndent.Pretty.Types: HsType' :: HsTypeFor -> HsTypeDir -> HsType GhcPs -> HsType'
+ HIndent.Pretty.Types: HsTypeForDeclSig :: HsTypeFor
+ HIndent.Pretty.Types: HsTypeForFuncSig :: HsTypeFor
+ HIndent.Pretty.Types: HsTypeForInstDecl :: HsTypeFor
+ HIndent.Pretty.Types: HsTypeForNormalDecl :: HsTypeFor
+ HIndent.Pretty.Types: HsTypeForVerticalAppTy :: HsTypeFor
+ HIndent.Pretty.Types: HsTypeNoDir :: HsTypeDir
+ HIndent.Pretty.Types: HsTypeVertical :: HsTypeDir
+ HIndent.Pretty.Types: InfixApp :: LHsExpr GhcPs -> LHsExpr GhcPs -> LHsExpr GhcPs -> Bool -> InfixApp
+ HIndent.Pretty.Types: InfixExpr :: LHsExpr GhcPs -> InfixExpr
+ HIndent.Pretty.Types: InfixOp :: RdrName -> InfixOp
+ HIndent.Pretty.Types: LambdaCase :: MatchGroup GhcPs (LHsExpr GhcPs) -> CaseOrCases -> LambdaCase
+ HIndent.Pretty.Types: LetIn :: HsLocalBinds GhcPs -> LHsExpr GhcPs -> LetIn
+ HIndent.Pretty.Types: ListComprehension :: ExprLStmt GhcPs -> [ExprLStmt GhcPs] -> ListComprehension
+ HIndent.Pretty.Types: Mdo :: DoOrMdo
+ HIndent.Pretty.Types: ModuleDeprecatedPragma :: WarningTxt GhcPs -> ModuleDeprecatedPragma
+ HIndent.Pretty.Types: ModuleNameWithPrefix :: ModuleName -> ModuleNameWithPrefix
+ HIndent.Pretty.Types: NodeComments :: [LEpaComment] -> [LEpaComment] -> [LEpaComment] -> NodeComments
+ HIndent.Pretty.Types: ParStmtBlockInsideVerticalList :: ParStmtBlock GhcPs GhcPs -> ParStmtBlockInsideVerticalList
+ HIndent.Pretty.Types: PatInsidePatDecl :: Pat GhcPs -> PatInsidePatDecl
+ HIndent.Pretty.Types: PrefixOp :: RdrName -> PrefixOp
+ HIndent.Pretty.Types: RecConField :: HsFieldBind (LFieldOcc GhcPs) (LPat GhcPs) -> RecConField
+ HIndent.Pretty.Types: RecConPat :: HsRecFields GhcPs (LPat GhcPs) -> RecConPat
+ HIndent.Pretty.Types: StmtLRInsideVerticalList :: StmtLR GhcPs GhcPs (LHsExpr GhcPs) -> StmtLRInsideVerticalList
+ HIndent.Pretty.Types: TopLevelTyFamInstDecl :: TyFamInstDecl GhcPs -> TopLevelTyFamInstDecl
+ HIndent.Pretty.Types: VerticalContext :: LHsContext GhcPs -> VerticalContext
+ HIndent.Pretty.Types: [caseOrCases] :: LambdaCase -> CaseOrCases
+ HIndent.Pretty.Types: [commentsAfter] :: NodeComments -> [LEpaComment]
+ HIndent.Pretty.Types: [commentsBefore] :: NodeComments -> [LEpaComment]
+ HIndent.Pretty.Types: [commentsOnSameLine] :: NodeComments -> [LEpaComment]
+ HIndent.Pretty.Types: [dataFamInstDeclFor] :: DataFamInstDecl' -> DataFamInstDeclFor
+ HIndent.Pretty.Types: [dataFamInstDecl] :: DataFamInstDecl' -> DataFamInstDecl GhcPs
+ HIndent.Pretty.Types: [doOrMdo] :: DoExpression -> DoOrMdo
+ HIndent.Pretty.Types: [doStmts] :: DoExpression -> [ExprLStmt GhcPs]
+ HIndent.Pretty.Types: [famEqnFor] :: FamEqn' -> DataFamInstDeclFor
+ HIndent.Pretty.Types: [famEqn] :: FamEqn' -> FamEqn GhcPs (HsDataDefn GhcPs)
+ HIndent.Pretty.Types: [grhsExprType] :: GRHSExpr -> GRHSExprType
+ HIndent.Pretty.Types: [grhsExpr] :: GRHSExpr -> GRHS GhcPs (LHsExpr GhcPs)
+ HIndent.Pretty.Types: [grhssExprType] :: GRHSsExpr -> GRHSExprType
+ HIndent.Pretty.Types: [grhssExpr] :: GRHSsExpr -> GRHSs GhcPs (LHsExpr GhcPs)
+ HIndent.Pretty.Types: [hsSigTypeDir] :: HsSigType' -> HsTypeDir
+ HIndent.Pretty.Types: [hsSigTypeFor] :: HsSigType' -> HsTypeFor
+ HIndent.Pretty.Types: [hsSigType] :: HsSigType' -> HsSigType GhcPs
+ HIndent.Pretty.Types: [hsTypeDir] :: HsType' -> HsTypeDir
+ HIndent.Pretty.Types: [hsTypeFor] :: HsType' -> HsTypeFor
+ HIndent.Pretty.Types: [hsType] :: HsType' -> HsType GhcPs
+ HIndent.Pretty.Types: [immediatelyAfterDo] :: InfixApp -> Bool
+ HIndent.Pretty.Types: [inExpr] :: LetIn -> LHsExpr GhcPs
+ HIndent.Pretty.Types: [lamCaseGroup] :: LambdaCase -> MatchGroup GhcPs (LHsExpr GhcPs)
+ HIndent.Pretty.Types: [letBinds] :: LetIn -> HsLocalBinds GhcPs
+ HIndent.Pretty.Types: [lhs] :: InfixApp -> LHsExpr GhcPs
+ HIndent.Pretty.Types: [listCompLhs] :: ListComprehension -> ExprLStmt GhcPs
+ HIndent.Pretty.Types: [listCompRhs] :: ListComprehension -> [ExprLStmt GhcPs]
+ HIndent.Pretty.Types: [op] :: InfixApp -> LHsExpr GhcPs
+ HIndent.Pretty.Types: [rhs] :: InfixApp -> LHsExpr GhcPs
+ HIndent.Pretty.Types: data CaseOrCases
+ HIndent.Pretty.Types: data DataFamInstDecl'
+ HIndent.Pretty.Types: data DataFamInstDeclFor
+ HIndent.Pretty.Types: data DoExpression
+ HIndent.Pretty.Types: data DoOrMdo
+ HIndent.Pretty.Types: data FamEqn'
+ HIndent.Pretty.Types: data GRHSExpr
+ HIndent.Pretty.Types: data GRHSExprType
+ HIndent.Pretty.Types: data GRHSProcType
+ HIndent.Pretty.Types: data GRHSsExpr
+ HIndent.Pretty.Types: data HsSigType'
+ HIndent.Pretty.Types: data HsType'
+ HIndent.Pretty.Types: data HsTypeDir
+ HIndent.Pretty.Types: data HsTypeFor
+ HIndent.Pretty.Types: data InfixApp
+ HIndent.Pretty.Types: data LambdaCase
+ HIndent.Pretty.Types: data LetIn
+ HIndent.Pretty.Types: data ListComprehension
+ HIndent.Pretty.Types: data NodeComments
+ HIndent.Pretty.Types: instance GHC.Classes.Eq HIndent.Pretty.Types.GRHSExprType
+ HIndent.Pretty.Types: newtype Context
+ HIndent.Pretty.Types: newtype DeclSig
+ HIndent.Pretty.Types: newtype GRHSProc
+ HIndent.Pretty.Types: newtype HorizontalContext
+ HIndent.Pretty.Types: newtype InfixExpr
+ HIndent.Pretty.Types: newtype InfixOp
+ HIndent.Pretty.Types: newtype ModuleDeprecatedPragma
+ HIndent.Pretty.Types: newtype ModuleNameWithPrefix
+ HIndent.Pretty.Types: newtype ParStmtBlockInsideVerticalList
+ HIndent.Pretty.Types: newtype PatInsidePatDecl
+ HIndent.Pretty.Types: newtype PrefixOp
+ HIndent.Pretty.Types: newtype RecConField
+ HIndent.Pretty.Types: newtype RecConPat
+ HIndent.Pretty.Types: newtype StmtLRInsideVerticalList
+ HIndent.Pretty.Types: newtype TopLevelTyFamInstDecl
+ HIndent.Pretty.Types: newtype VerticalContext
+ HIndent.Pretty.Types: pattern DataFamInstDeclInsideClassInst :: DataFamInstDecl GhcPs -> DataFamInstDecl'
+ HIndent.Pretty.Types: pattern DataFamInstDeclTopLevel :: DataFamInstDecl GhcPs -> DataFamInstDecl'
+ HIndent.Pretty.Types: pattern FamEqnInsideClassInst :: FamEqn GhcPs (HsDataDefn GhcPs) -> FamEqn'
+ HIndent.Pretty.Types: pattern FamEqnTopLevel :: FamEqn GhcPs (HsDataDefn GhcPs) -> FamEqn'
+ HIndent.Pretty.Types: pattern HsSigTypeInsideDeclSig :: HsSigType GhcPs -> HsSigType'
+ HIndent.Pretty.Types: pattern HsSigTypeInsideInstDecl :: HsSigType GhcPs -> HsSigType'
+ HIndent.Pretty.Types: pattern HsSigTypeInsideVerticalFuncSig :: HsSigType GhcPs -> HsSigType'
+ HIndent.Pretty.Types: pattern HsTypeInsideDeclSig :: HsType GhcPs -> HsType'
+ HIndent.Pretty.Types: pattern HsTypeInsideInstDecl :: HsType GhcPs -> HsType'
+ HIndent.Pretty.Types: pattern HsTypeInsideVerticalFuncSig :: HsType GhcPs -> HsType'
+ HIndent.Pretty.Types: pattern HsTypeWithVerticalAppTy :: HsType GhcPs -> HsType'
+ HIndent.Printer: PrintState :: !Int64 -> !Builder -> !Bool -> !Int64 -> !Int64 -> !Config -> !Bool -> !Bool -> PrintState
+ HIndent.Printer: Printer :: StateT PrintState (MaybeT Identity) a -> Printer a
+ HIndent.Printer: [psColumn] :: PrintState -> !Int64
+ HIndent.Printer: [psConfig] :: PrintState -> !Config
+ HIndent.Printer: [psEolComment] :: PrintState -> !Bool
+ HIndent.Printer: [psFitOnOneLine] :: PrintState -> !Bool
+ HIndent.Printer: [psIndentLevel] :: PrintState -> !Int64
+ HIndent.Printer: [psLine] :: PrintState -> !Int64
+ HIndent.Printer: [psNewline] :: PrintState -> !Bool
+ HIndent.Printer: [psOutput] :: PrintState -> !Builder
+ HIndent.Printer: [runPrinter] :: Printer a -> StateT PrintState (MaybeT Identity) a
+ HIndent.Printer: data PrintState
+ HIndent.Printer: instance Control.Monad.State.Class.MonadState HIndent.Printer.PrintState HIndent.Printer.Printer
+ HIndent.Printer: instance GHC.Base.Alternative HIndent.Printer.Printer
+ HIndent.Printer: instance GHC.Base.Applicative HIndent.Printer.Printer
+ HIndent.Printer: instance GHC.Base.Functor HIndent.Printer.Printer
+ HIndent.Printer: instance GHC.Base.Monad HIndent.Printer.Printer
+ HIndent.Printer: instance GHC.Base.MonadPlus HIndent.Printer.Printer
+ HIndent.Printer: newtype Printer a
- HIndent: prettyPrint :: Config -> Module SrcSpanInfo -> [Comment] -> Either a Builder
+ HIndent: prettyPrint :: Config -> HsModule -> Builder
- HIndent: testAst :: ByteString -> Either String (Module NodeInfo)
+ HIndent: testAst :: ByteString -> Either String HsModule
- HIndent.Pretty: pretty :: (Pretty ast, Show (ast NodeInfo)) => ast NodeInfo -> Printer ()
+ HIndent.Pretty: pretty :: Pretty a => a -> Printer ()
Files
- CHANGELOG.md +337/−102
- README.md +22/−14
- Setup.hs +1/−0
- TESTS.md +3328/−1807
- app/Main.hs +150/−0
- benchmarks/Main.hs +47/−0
- hindent.cabal +247/−100
- internal/HIndent/Internal/Test/Markdone.hs +133/−0
- src/HIndent.hs +118/−378
- src/HIndent/Applicative.hs +11/−0
- src/HIndent/CabalFile.hs +59/−74
- src/HIndent/CodeBlock.hs +14/−6
- src/HIndent/Config.hs +81/−0
- src/HIndent/Language.hs +23/−0
- src/HIndent/LanguageExtension.hs +121/−0
- src/HIndent/LanguageExtension/Conversion.hs +58/−0
- src/HIndent/LanguageExtension/Types.hs +18/−0
- src/HIndent/ModulePreprocessing.hs +222/−0
- src/HIndent/ModulePreprocessing/CommentRelocation.hs +336/−0
- src/HIndent/Parse.hs +84/−0
- src/HIndent/Path/Find.hs +40/−0
- src/HIndent/Pragma.hs +64/−0
- src/HIndent/Pretty.hs +2239/−2151
- src/HIndent/Pretty/Combinators.hs +24/−0
- src/HIndent/Pretty/Combinators/Comment.hs +12/−0
- src/HIndent/Pretty/Combinators/Getter.hs +31/−0
- src/HIndent/Pretty/Combinators/Indent.hs +67/−0
- src/HIndent/Pretty/Combinators/Lineup.hs +246/−0
- src/HIndent/Pretty/Combinators/Op.hs +24/−0
- src/HIndent/Pretty/Combinators/Outputable.hs +36/−0
- src/HIndent/Pretty/Combinators/RhsSeparator.hs +16/−0
- src/HIndent/Pretty/Combinators/String.hs +78/−0
- src/HIndent/Pretty/Combinators/Switch.hs +25/−0
- src/HIndent/Pretty/Combinators/Wrap.hs +85/−0
- src/HIndent/Pretty/Import.hs +46/−0
- src/HIndent/Pretty/Import/Sort.hs +125/−0
- src/HIndent/Pretty/NodeComments.hs +873/−0
- src/HIndent/Pretty/Pragma.hs +61/−0
- src/HIndent/Pretty/SigBindFamily.hs +73/−0
- src/HIndent/Pretty/Types.hs +336/−0
- src/HIndent/Printer.hs +52/−0
- src/HIndent/Types.hs +0/−143
- src/main/Benchmark.hs +0/−47
- src/main/Main.hs +0/−127
- src/main/Markdone.hs +0/−130
- src/main/Path/Find.hs +0/−98
- src/main/Test.hs +0/−177
- tests/Main.hs +220/−0
CHANGELOG.md view
@@ -1,136 +1,371 @@-5.3.0:- * Handle multiple deriving clauses in a DerivingStrategies scenario- * Ignore non-files in findCabalFiles- * Allow batch processing of multiple files- * Prevent hindent from trying to open non-files when searching for- .cabal files- * Specify default extensions in configuration file- * Fix bad output for [p|Foo|] pattern quasi-quotes- * Parse C preprocessor line continuations- * Fix pretty printing of '(:)- * Add parens around symbols (:|) when required- * Support $p pattern splices- * Fix associated type families- * Non-dependent record constructor formatting+# Changelog -5.2.7:- * Fix -X option bug+## [Unreleased] -5.2.6:- * Switch to optparse-applicative+### Added -5.2.5:+- ... - * Support get extensions from `.cabal` file- * Improve indention with record constructions and updates- * Fix `let ... in` bug- * Fix top-level lambda expressions in TemplateHaskell slices- * Update to haskell-src-exts dependency to version `>= 1.20.0`+### Changed -5.2.4:+- ... - * Pretty print imports- * Fix pretty print for string literals for `DataKinds`- * Support `--validate` option for checking the format without reformatting- * Support parse `#include`, `#error`, `#warning` directives- * Support read `LANGUAGE` pragma and parse the declared extensions from source- * Treat `TypeApplications` extension as 'badExtensions' due to the `@` symbol- * Improve pretty print for unboxed tuples- * Fix many issues related to infix operators, includes TH name quotes,- `INLINE`/`NOINLINE` pragmas, infix type operator and infix constructor- * Fix pretty print for operators in `INLINE`/`NOINLINE` pragmas- * Support for `EmptyCases` extension- * Fix TH name quotes on operator names- * Optimize pretty print for many fundeps- * Fix extra linebreaks after short identifiers+### Fixed -5.2.3:+- ... - * Sort explicit import lists- * Report the `SrcLoc` when there's a parse error- * Improve long type signatures pretty printing- * Support custom line-break operators, add `--line-breaks` argument- * Fix infix data constructor- * Disable `RecursiveDo` and `DoRec` extensions by default- * Add RecStmt support- * Improve GADT records, data declaration records- * Complicated type alias and type signatures pretty printing- * Fix quasi-quoter names+### Removed -5.2.2:+- ... - * Parallel list comprehensions- * Leave do, lambda, lambda-case on previous line of $- * Misc fixes+## [6.0.0] - 2023-02-20 -5.2.1:+### Added - * Fix hanging on large constraints- * Render multi-line comments- * Rename --tab-size to --indent-size- * Don't add a spurious space for comments at the end of the file- * Don't add trailing whitespace on <-- * Disable PatternSynonyms- * Put a newline before the closing bracket on a list+- The getConfig function is exported. -5.2.0:+### Changed - * Default tab-width is now 2- * Supports .hindent.yaml file to specify alt tab-width and max- column- * Put last paren of export list on a new line- * Implement tab-size support in Emacs Lisp+- Switched the parser from [`haskell-src-exts`] to [`ghc-lib-parser`].+ This switch causes changes in the formatting results in some cases.+- Changed how to format a data type with a record constructor to follow+ the [Johan Tibell's Haskell Style Guide]. ([#662]).+- A newline is no longer inserted after a pattern signature ([#663]).+- A type with many type applications are now broken into multiple lines.+ ([#664]).+- A long type-level list is broken into multiple lines. ([#665]).+- Spaces around typed expression brackets are removed ([#666]).+- HIndent no longer breaks short class constraints in function signautres into+ multiple lines ([#669]). -5.1.1:+### Fixed - * Preserve spaces between groups of imports (fixes #200)- * Support shebangs (closes #208)- * Output filename for parse errors (fixes #179)- * Input with newline ends with newline (closes #211)- * Document -X (closes #212)- * Fix explicit forall in instances (closes #218)- * Put last paren of export list on a new line #227+- Fixed the wrong formatting of data family instances inside class instances+ ([#667]).+- Fixed the bug of removing the space before the enclosing parenthesis of a+ record syntax in a signature in a GADT declaration ([#670]).+- Fixed the bug of inserting unnecessary empty lines if a file contains only+ comments ([#672]). -5.1.0:+### Removed - * Rewrote comment association, more reliable- * Added --tab-size flag for indentation spaces- * Fixed some miscellaneous bugs+- Test functions except `testAst`.+- Atom support ([#671]). -5.0.1:+## [5.3.4] - 2022-07-07 - * Re-implement using bytestring instead of text- * Made compatible with GHC 7.8 through to GHC 8.0- * Added test suite and benchmarks in TESTS.md and BENCHMARKS.md+This version is accidentally pushlished, and is the same as 5.3.3. -5.0.0:+## [5.3.3] - 2022-07-07 - * Drop support for styles+### Added -4.6.4+- Support for GHC 9.2.2.+- Test CI with GitHub Actions (WIP). - * Copy/delete file instead of renaming+### Fixed -4.4.6+- Fixed a broken link to Servant by [@mattfbacon] in [#579].+- Fixed a build with Cabal 3.6 by [@uhbif19] in [#584].+- Fixed a compile error for GHC 9.2.2 by [@toku-sa-n] in [#588]. - * Fix whole module printer- * Accept a filename to reformat+## [5.3.2] - 2022-02-02 -4.4.5+### Fixed - * Fix bug in infix patterns+- `MonadFix` issues to support newer GHC versions. -4.4.2+## [5.3.1] - 2019-06-28 - * Bunch of Gibiansky style fixes.- * Support CPP.- * Tibell style fixes.+### Fixed -4.3.8+- Comment relocations in where clauses of top-level function declarations. - * Fixed: bug in printing operators in statements.+## [5.3.0] - 2019-04-29 -4.5.4+### Added - * Improvements to Tibell style.- * 6x speed up on rendering operators.+- Allow batch processing of multiple files.+- You can now specify default extensions in the configuration file.++### Fixed++- Handle multiple deriving clauses in the `DerivingStrategies` scenario.+- Ignore non-files in `findCabalFiles`.+- Prevent HIndent from trying to open non-files when searching for `.cabal` files.+- Fix the bad output for `[p|Foo|]` pattern quasi-quotes.+- Fix pretty-printing of `'(:)`.+- Fix parsing C preprocessor line continuations.+- Add parentheses around symbols `(:|)` when required.+- Support `$p` pattern splices.+- Fix formatting of associated type families.+- Fix formatting of non-dependent record constructors.++## [5.2.7] - 2019-03-16++### Fixed++- A bug in the `-X` option++## [5.2.6] - 2019-03-16++### Changed++- Switched to [`optparse-applicative`].++## [5.2.5] - 2018-01-04++### Added++- Support getting extensions from a `.cabal` file++### Changed++- Improved the indentation with record constructions and updates+- Updated [`haskell-src-exts`] dependency to version `>= 1.20.0`++### Fixed++- Fix the `let ... in` bug+- Fix formatting top-level lambda expressions in `TemplateHaskell` slices++## [5.2.4] - 2017-10-20++### Added++- Improved pretty-printing unboxed tuples.+- Support the `--validate` option for checking the format without reformatting+- Support parsing `#include`, `#error`, and `#warning` directives.+- Support reading `LANGUAGE` pragmas and parse the declared extensions from sources.+- Support the `EmptyCases` extension+- Optimize pretty-printing for many functional dependencies.++### Changed++- The `TypeApplications` extension is now disabled-by-default due to the `@` symbol++### Fixed++- Fixed pretty-printing imports+- Fixed pretty-printing string literals for `DataKinds`+- Fixed many issues related to infix operators including TH name quotes,+ `INLINE`/`NOINLINE` pragmas, infix type operators, and infix constructors.+- Fix extra linebreaks after short identifiers.++## [5.2.3] - 2017-05-07++### Added++- HIndent now reports where a parse happened.+- Added `--line-breaks` parameter to support custom line breaks.+- Added the `RecStmt` support++### Changed++- Explicit import lists are now sorted.+- Improved pretty-printing long type signatures.+- Improved pretty-printing GADT records.+- Improved pretty-printing data declaration records.+- The `RecursiveDo` and `DoRec` extensions are now disabled-by-default.++## Fixed++- Fixed pretty-printing for infix data constructors.+- Fixed pretty-printing of quasi-quoter names.+- Fixed pretty-printing of complicated type aliases.+- Fixed pretty-printing of complicated type signatures.++## [5.2.2] - 2017-01-16++### Changed++- HIndent now leaves `do`, lambda (`\x->`), and lambda-case (`\case->`) on the previous line of `$`.++### Fixed++- Fixed pretty-printing of parallel list comprehensions.+- Miscellaneous fixes.++## [5.2.1] - 2016-09-01++### Changed++- The `--tab-size` option is renamed to `--indent-size`.+- The `PatternSynonyms` extension is now disabled by default.+- HIndent now puts a newline before the closing bracket on a list.++### Fixed++- Fixed handling of paragraph overhang when using large constraints.+- Fixed pretty-printing of multi-line comments.+- Fixed bug resulting in adding a spurious space for comments at the end of a file.+- Fixed bug which results in adding a trailing white space on `<-`++## [5.2.0] - 2016-08-30++### Added++- Support the `.hindent.yaml` file to specify alternative tab width and max+ column numbers.+- Implement the tab-size support in Emacs Lisp.++### Changed++- The default number of spaces for a tab is changed to 2.++## [5.1.1] - 2016-08-29++### Added++- Add shebang support (Fixes [#208]).+- Output the filename for parse errors (Fixes [#179]).+- Added a document of the `-X` option (Fixes [#212]).++### Changed++- HIndent now preserves spaces between groups of imports (Fixes [#200]).+- HIndent now preserves the last newline if the input ends with one (Fixes [#211]).+- HIndent now puts the last parenthesis of an export list on a new line (Fixes [#227]).++### Fixed++- Fixed pretty-printing explicit `forall`s in instances (Fixes [#218]).++## [5.1.0] - 2016-08-25++### Added++- Add `--tab-size` parameter to control indentation spaces.++### Changed++- Rewrote comment association for more reliability.++### Fixed++- Some miscellaneous bugs.++## [5.0.1] - 2016-08-20++### Added++- Made HIndent compatible with GHC 7.8 through GHC 8.0+- Added test suites and benchmarks in [`TESTS.md`] and [`BENCHMARKS.md`]++### Changed++- Re-implement using [`bytestring`] instead of [`text`]++## [5.0.0] - 2016-08-11++### Removed++- Support for styles++## [4.6.4] - 2016-07-15++### Changed++- The formatted file is now created by coping/deleting a file instead of renaming.++## [4.6.3] - 2016-04-18++### Added++- Accept a filename to reformat.++### Fixed++- Fixed the whole module printer.++## [4.5.4] - 2015-06-22++### Added++- Improvements to Tibell style.+- 6x speed up on rendering operators.++## [4.4.5] - 2015-11-10++### Fixed++- Fixed a bug in infix patterns.++## [4.4.2] - 2015-04-05++### Added++- Support for CPP.++### Fixed++- Bunch of Gibiansky style bugs.+- Tibell style bugs.++## [4.3.8] - 2015-02-06++### Fixed++- A bug in printing operators in statements.++[unreleased]: https://github.com/mihaimaruseac/hindent/compare/v6.0.0...HEAD+[6.0.0]: https://github.com/mihaimaruseac/hindent/compare/v5.3.4...v6.0.0+[5.3.4]: https://github.com/mihaimaruseac/hindent/compare/v5.3.3...v5.3.4+[5.3.3]: https://github.com/mihaimaruseac/hindent/compare/v5.3.2...v5.3.3+[5.3.2]: https://github.com/mihaimaruseac/hindent/compare/5.3.1...v5.3.2+[5.3.1]: https://github.com/mihaimaruseac/hindent/compare/5.3.0...5.3.1+[5.3.0]: https://github.com/mihaimaruseac/hindent/compare/5.2.7...5.3.0+[5.2.7]: https://github.com/mihaimaruseac/hindent/compare/5.2.6...5.2.7+[5.2.6]: https://github.com/mihaimaruseac/hindent/compare/5.2.5...5.2.6+[5.2.5]: https://github.com/mihaimaruseac/hindent/compare/5.2.4...5.2.5+[5.2.4]: https://github.com/mihaimaruseac/hindent/compare/5.2.3...5.2.4+[5.2.3]: https://github.com/mihaimaruseac/hindent/compare/5.2.2...5.2.3+[5.2.2]: https://github.com/mihaimaruseac/hindent/compare/5.2.1...5.2.2+[5.2.1]: https://github.com/mihaimaruseac/hindent/compare/5.2.0...5.2.1+[5.2.0]: https://github.com/mihaimaruseac/hindent/compare/5.1.1...5.2.0+[5.1.1]: https://github.com/mihaimaruseac/hindent/compare/5.1.0...5.1.1+[5.1.0]: https://github.com/mihaimaruseac/hindent/compare/5.0.1...5.1.0+[5.0.1]: https://github.com/mihaimaruseac/hindent/compare/5.0.0...5.0.1+[5.0.0]: https://github.com/mihaimaruseac/hindent/compare/4.6.4...5.0.0+[4.6.4]: https://github.com/mihaimaruseac/hindent/compare/4.6.3...4.6.4+[4.6.3]: https://github.com/mihaimaruseac/hindent/compare/4.6.2...4.6.3+[4.5.4]: https://github.com/mihaimaruseac/hindent/compare/4.5.3...4.5.4+[4.4.5]: https://github.com/mihaimaruseac/hindent/compare/4.4.4...4.4.5+[4.4.2]: https://github.com/mihaimaruseac/hindent/compare/4.4.1...4.4.2+[4.3.8]: https://github.com/mihaimaruseac/hindent/compare/4.3.7...4.3.8++[@mattfbacon]: https://github.com/mattfbacon+[@uhbif19]: https://github.com/uhbif19+[@toku-sa-n]: https://github.com/toku-sa-n++[#672]: https://github.com/mihaimaruseac/hindent/pull/672+[#671]: https://github.com/mihaimaruseac/hindent/pull/671+[#670]: https://github.com/mihaimaruseac/hindent/pull/670+[#669]: https://github.com/mihaimaruseac/hindent/pull/669+[#667]: https://github.com/mihaimaruseac/hindent/pull/667+[#666]: https://github.com/mihaimaruseac/hindent/pull/666+[#665]: https://github.com/mihaimaruseac/hindent/pull/665+[#664]: https://github.com/mihaimaruseac/hindent/pull/664+[#663]: https://github.com/mihaimaruseac/hindent/pull/663+[#662]: https://github.com/mihaimaruseac/hindent/pull/662+[#588]: https://github.com/mihaimaruseac/hindent/pull/588+[#584]: https://github.com/mihaimaruseac/hindent/pull/584+[#579]: https://github.com/mihaimaruseac/hindent/pull/579+[#227]: https://github.com/mihaimaruseac/hindent/pull/227+[#218]: https://github.com/mihaimaruseac/hindent/pull/218+[#212]: https://github.com/mihaimaruseac/hindent/pull/212+[#211]: https://github.com/mihaimaruseac/hindent/pull/211+[#208]: https://github.com/mihaimaruseac/hindent/pull/208+[#200]: https://github.com/mihaimaruseac/hindent/pull/200+[#179]: https://github.com/mihaimaruseac/hindent/pull/179++[`haskell-src-exts`]: https://hackage.haskell.org/package/haskell-src-exts+[`ghc-lib-parser`]: https://hackage.haskell.org/package/ghc-lib-parser+[`optparse-applicative`]: https://hackage.haskell.org/package/optparse-applicative+[`bytestring`]: https://hackage.haskell.org/package/bytestring+[`text`]: https://hackage.haskell.org/package/text++[`TESTS.md`]: TESTS.md+[`BENCHMARKS.md`]: BENCHMARKS.md++[Johan Tibell's Haskell Style Guide]: https://github.com/tibbe/haskell-style-guide/blob/master/haskell-style.md
README.md view
@@ -1,5 +1,6 @@-# hindent [](https://hackage.haskell.org/package/hindent) /badge.svg) /badge.svg)+# hindent [](https://hackage.haskell.org/package/hindent) /badge.svg) /badge.svg) [](https://api.securityscorecards.dev/projects/github.com/mihaimaruseac/hindent) + Haskell pretty printer [Examples](https://github.com/mihaimaruseac/hindent/blob/master/TESTS.md)@@ -11,13 +12,26 @@ ## Usage $ hindent --help- hindent --version --help --style STYLE --line-length <...> --indent-size <...> --no-force-newline [-X<...>]* [<FILENAME>]- Version 5.1.1- Default --indent-size is 2. Specify --indent-size 4 if you prefer that.- -X to pass extensions e.g. -XMagicHash etc.- The --style option is now ignored, but preserved for backwards-compatibility.- Johan Tibell is the default and only style.+ hindent - Reformat Haskell source code + Usage: hindent [--version | [--line-length ARG]+ [--indent-size ARG | --tab-size ARG] [--no-force-newline]+ [--sort-imports | --no-sort-imports] [--style STYLE]+ [-X GHCEXT] [--validate] [FILENAMES]]++ Available options:+ --version Print the version+ --line-length ARG Desired length of lines (default: 80)+ --indent-size ARG Indentation size in spaces (default: 2)+ --tab-size ARG Same as --indent-size, for compatibility+ --no-force-newline Don't force a trailing newline+ --sort-imports Sort imports in groups+ --no-sort-imports Don't sort imports+ --style STYLE Style to print with (historical, now ignored)+ -X GHCEXT Language extension+ --validate Check if files are formatted without changing them+ -h,--help Show this help text+ hindent is used in a pipeline style $ cat path/to/sourcefile.hs | hindent@@ -109,16 +123,10 @@ [vim-hindent](https://github.com/alx741/vim-hindent) plugin which runs hindent automatically when a Haskell file is saved. -## Atom--Fortunately, you can use https://atom.io/packages/ide-haskell with the-path to hindent specified instead of that to stylish-haskell. Works-like a charm that way!- ## IntelliJ / other JetBrains IDEs 1. Install the "HaskForce" Haskell plugin (this is so we get the language type recognized in the file watcher) 2. Install the "File Watchers" plugin under "Browse Repositories"-3. Add a File Watcher with +3. Add a File Watcher with 1. File type: Haskell Language 2. Program: `/path/to/hindent` 3. Arguments: `$FilePath$`
Setup.hs view
@@ -1,2 +1,3 @@ import Distribution.Simple+ main = defaultMain
TESTS.md view
@@ -1,1808 +1,3329 @@-# Introduction--This file is a test suite. Each section maps to an HSpec test, and-each line that is followed by a Haskell code fence is tested to make-sure re-formatting that code snippet produces the same result.--You can browse through this document to see what HIndent's style is-like, or contribute additional sections to it, or regression tests.--# Modules--Empty module--``` haskell-```--Double shebangs--``` haskell-#!/usr/bin/env stack-#!/usr/bin/env stack-main = pure ()-```--Extension pragmas--```haskell-{-# LANGUAGE TypeApplications #-}--fun @Int 12-```--Module header--``` haskell-module X where--x = 1-```--Exports--``` haskell-module X- ( x- , y- , Z- , P(x, z)- ) where-```--Exports, indentation 4--``` haskell 4-module X- ( x- , y- , Z- , P(x, z)- ) where-```--# Imports--Import lists--``` haskell-import Data.Text-import Data.Text-import qualified Data.Text as T-import qualified Data.Text (a, b, c)-import Data.Text (a, b, c)-import Data.Text hiding (a, b, c)-```--Sorted--```haskell given-import B-import A-```--```haskell expect-import A-import B-```--Explicit imports - capitals first (typeclasses/types), then operators, then identifiers--```haskell given-import qualified MegaModule as M ((>>>), MonadBaseControl, void, MaybeT(..), join, Maybe(Nothing, Just), liftIO, Either, (<<<), Monad(return, (>>=), (>>)))-```--```haskell expect-import qualified MegaModule as M- ( Either- , Maybe(Just, Nothing)- , MaybeT(..)- , Monad((>>), (>>=), return)- , MonadBaseControl- , (<<<)- , (>>>)- , join- , liftIO- , void- )-```--Pretty import specification--```haskell-import A hiding- ( foobarbazqux- , foobarbazqux- , foobarbazqux- , foobarbazqux- , foobarbazqux- , foobarbazqux- , foobarbazqux- )--import Name hiding ()--import {-# SOURCE #-} safe qualified Module as M hiding (a, b, c, d, e, f)-```--# Declarations--Type declaration--``` haskell-type EventSource a = (AddHandler a, a -> IO ())-```--Type declaration with infix promoted type constructor--```haskell-fun1 :: Def ('[ Ref s (Stored Uint32), IBool] 'T.:-> IBool)-fun1 = undefined--fun2 :: Def ('[ Ref s (Stored Uint32), IBool] ':-> IBool)-fun2 = undefined-```--Instance declaration without decls--``` haskell-instance C a-```--Instance declaration with decls--``` haskell-instance C a where- foobar = do- x y- k p-```--Symbol class constructor in instance declaration--```haskell-instance Bool :?: Bool--instance (:?:) Int Bool-```--GADT declarations--```haskell-data Ty :: (* -> *) where- TCon- :: { field1 :: Int- , field2 :: Bool}- -> Ty Bool- TCon' :: (a :: *) -> a -> Ty a-```--# Expressions--Lazy patterns in a lambda--``` haskell-f = \ ~a -> undefined--- \~a yields parse error on input ‘\~’-```--Bang patterns in a lambda--``` haskell-f = \ !a -> undefined--- \!a yields parse error on input ‘\!’-```--List comprehensions, short--``` haskell-map f xs = [f x | x <- xs]-```--List comprehensions, long--``` haskell-defaultExtensions =- [ e- | EnableExtension {extensionField1 = extensionField1} <-- knownExtensions knownExtensions- , let a = b- -- comment- , let c = d- -- comment- ]-```--List comprehensions with operators--```haskell-defaultExtensions =- [e | e@EnableExtension {} <- knownExtensions] \\- map EnableExtension badExtensions-```--Parallel list comprehension, short--```haskell-zip xs ys = [(x, y) | x <- xs | y <- ys]-```--Parallel list comprehension, long--```haskell-fun xs ys =- [ (alphaBetaGamma, deltaEpsilonZeta)- | x <- xs- , z <- zs- | y <- ys- , cond- , let t = t- ]-```--Record, short--``` haskell-getGitProvider :: EventProvider GitRecord ()-getGitProvider =- EventProvider {getModuleName = "Git", getEvents = getRepoCommits}-```--Record, medium--``` haskell-commitToEvent :: FolderPath -> TimeZone -> Commit -> Event.Event-commitToEvent gitFolderPath timezone commit =- Event.Event- {pluginName = getModuleName getGitProvider, eventIcon = "glyphicon-cog"}-```--Record, long--``` haskell-commitToEvent :: FolderPath -> TimeZone -> Commit -> Event.Event-commitToEvent gitFolderPath timezone commit =- Event.Event- { pluginName = getModuleName getGitProvider- , eventIcon = "glyphicon-cog"- , eventDate = localTimeToUTC timezone (commitDate commit)- }-```--Record with symbol constructor--```haskell-f = (:..?) {}-```--Record with symbol field--```haskell-f x = x {(..?) = wat}--g x = Rec {(..?)}-```--Cases--``` haskell-strToMonth :: String -> Int-strToMonth month =- case month of- "Jan" -> 1- "Feb" -> 2- _ -> error $ "Unknown month " ++ month-```--Operators, bad--``` haskell-x =- Value <$> thing <*> secondThing <*> thirdThing <*> fourthThing <*>- Just thisissolong <*>- Just stilllonger <*>- evenlonger-```--Operators, good--```haskell pending-x =- Value <$> thing <*> secondThing <*> thirdThing <*> fourthThing <*>- Just thisissolong <*> Just stilllonger <*> evenlonger-```--Operator with `do`--```haskell-for xs $ do- left x- right x-```--Operator with lambda--```haskell-for xs $ \x -> do- left x- right x-```--Operator with lambda-case--```haskell-for xs $ \case- Left x -> x-```--Operator in parentheses--```haskell-cat = (++)-```--Symbol data constructor in parentheses--```haskell-cons = (:)--cons' = (:|)-```--n+k patterns--``` haskell-f (n+5) = 0-```--Binary symbol data constructor in pattern--```haskell-f (x :| _) = x--f' ((:|) x _) = x--f'' ((Data.List.NonEmpty.:|) x _) = x--g (x:xs) = x--g' ((:) x _) = x-```--Type application--```haskell-{-# LANGUAGE TypeApplications #-}--fun @Int 12-```--Transform list comprehensions--```haskell-list =- [ (x, y, map the v)- | x <- [1 .. 10]- , y <- [1 .. 10]- , let v = x + y- , then group by v using groupWith- , then take 10- , then group using permutations- , t <- concat v- , then takeWhile by t < 3- ]-```--Type families--```haskell-type family Id a-```--Type family annotations--``` haskell-type family Id a :: *-```--Type family instances--```haskell-type instance Id Int = Int-```--Type family dependencies--```haskell-type family Id a = r | r -> a-```--Binding implicit parameters--```haskell-f =- let ?x = 42- in f-```--Closed type families--```haskell-type family Closed (a :: k) :: Bool where- Closed x = 'True-```--# Template Haskell--Expression brackets--```haskell-add1 x = [|x + 1|]-```--Pattern brackets--```haskell-mkPat = [p|(x, y)|]-```--Type brackets--```haskell-foo :: $([t|Bool|]) -> a-```--Quoted data constructors--```haskell-cons = '(:)-```--Pattern splices--```haskell-f $pat = ()--g =- case x of- $(mkPat y z) -> True- _ -> False-```--# Type signatures--Long argument list should line break--```haskell-longLongFunction ::- ReaderT r (WriterT w (StateT s m)) a- -> StateT s (WriterT w (ReaderT r m)) a-```--Class constraints should leave `::` on same line--``` haskell--- see https://github.com/chrisdone/hindent/pull/266#issuecomment-244182805-fun ::- (Class a, Class b)- => fooooooooooo bar mu zot- -> fooooooooooo bar mu zot- -> c-```--Class constraints--``` haskell-fun :: (Class a, Class b) => a -> b -> c-```--Symbol class constructor in class constraint--```haskell-f :: (a :?: b) => (a, b)-f' :: ((:?:) a b) => (a, b)-```--Tuples--``` haskell-fun :: (a, b, c) -> (a, b)-```--Quasiquotes in types--```haskell-fun :: [a|bc|]-```--Default signatures--```haskell--- https://github.com/chrisdone/hindent/issues/283-class Foo a where- bar :: a -> a -> a- default bar :: Monoid a =>- a -> a -> a- bar = mappend-```--Implicit parameters--```haskell-f :: (?x :: Int) => Int-```--Symbol type constructor--```haskell-f :: a :?: b-f' :: (:?:) a b-```--Promoted list (issue #348)--```haskell-a :: A '[ 'True]-a = undefined---- nested promoted list with multiple elements.-b :: A '[ '[ 'True, 'False], '[ 'False, 'True]]-b = undefined-```--Promoted list with a tuple (issue #348)--```haskell-a :: A '[ '( a, b, c, d)]-a = undefined---- nested promoted tuples.-b :: A '[ '( 'True, 'False, '[], '( 'False, 'True))]-b = undefined-```--Prefix promoted symbol type constructor--```haskell-a :: '(T.:->) 'True 'False-b :: (T.:->) 'True 'False-c :: '(:->) 'True 'False-d :: (:->) 'True 'False-```--# Function declarations--Prefix notation for operators--``` haskell-(+) :: Num a => a -> a -> a-(+) a b = a-```--Where clause--``` haskell-sayHello = do- name <- getLine- putStrLn $ greeting name- where- greeting name = "Hello, " ++ name ++ "!"-```--Guards and pattern guards--``` haskell-f x- | x <- Just x- , x <- Just x =- case x of- Just x -> e- | otherwise = do e- where- x = y-```--Multi-way if--``` haskell-x =- if | x <- Just x,- x <- Just x ->- case x of- Just x -> e- Nothing -> p- | otherwise -> e-```--Case inside a `where` and `do`--``` haskell-g x =- case x of- a -> x- where- foo =- case x of- _ -> do- launchMissiles- where- y = 2-```--Let inside a `where`--``` haskell-g x =- let x = 1- in x- where- foo =- let y = 2- z = 3- in y-```--Lists--``` haskell-exceptions = [InvalidStatusCode, MissingContentHeader, InternalServerError]--exceptions =- [ InvalidStatusCode- , MissingContentHeader- , InternalServerError- , InvalidStatusCode- , MissingContentHeader- , InternalServerError- ]-```--Long line, function application--```haskell-test = do- alphaBetaGamma deltaEpsilonZeta etaThetaIota kappaLambdaMu nuXiOmicron piRh79- alphaBetaGamma deltaEpsilonZeta etaThetaIota kappaLambdaMu nuXiOmicron piRho80- alphaBetaGamma- deltaEpsilonZeta- etaThetaIota- kappaLambdaMu- nuXiOmicron- piRhoS81-```--Long line, tuple--```haskell-test- (alphaBetaGamma, deltaEpsilonZeta, etaThetaIota, kappaLambdaMu, nuXiOmicro79)- (alphaBetaGamma, deltaEpsilonZeta, etaThetaIota, kappaLambdaMu, nuXiOmicron80)- ( alphaBetaGamma- , deltaEpsilonZeta- , etaThetaIota- , kappaLambdaMu- , nuXiOmicronP81)-```--Long line, tuple section--```haskell-test- (, alphaBetaGamma, , deltaEpsilonZeta, , etaThetaIota, kappaLambdaMu, nu79, )- (, alphaBetaGamma, , deltaEpsilonZeta, , etaThetaIota, kappaLambdaMu, , n80, )- (- , alphaBetaGamma- ,- , deltaEpsilonZeta- ,- , etaThetaIota- , kappaLambdaMu- ,- , nu81- ,)-```--# Record syntax--Pattern matching, short--```haskell-fun Rec {alpha = beta, gamma = delta, epsilon = zeta, eta = theta, iota = kappa} = do- beta + delta + zeta + theta + kappa-```--Pattern matching, long--```haskell-fun Rec { alpha = beta- , gamma = delta- , epsilon = zeta- , eta = theta- , iota = kappa- , lambda = mu- } =- beta + delta + zeta + theta + kappa + mu + beta + delta + zeta + theta + kappa-```--Symbol constructor, short--```haskell-fun ((:..?) {}) = undefined-```--Symbol constructor, long--```-fun (:..?) { alpha = beta- , gamma = delta- , epsilon = zeta- , eta = theta- , iota = kappa- , lambda = mu- } =- beta + delta + zeta + theta + kappa + mu + beta + delta + zeta + theta + kappa-```--Symbol field--```haskell-f (X {(..?) = x}) = x-```--Punned symbol field--```haskell-f' (X {(..?)}) = (..?)-```--# Johan Tibell compatibility checks--Basic example from Tibbe's style--``` haskell-sayHello :: IO ()-sayHello = do- name <- getLine- putStrLn $ greeting name- where- greeting name = "Hello, " ++ name ++ "!"--filter :: (a -> Bool) -> [a] -> [a]-filter _ [] = []-filter p (x:xs)- | p x = x : filter p xs- | otherwise = filter p xs-```--Data declarations--``` haskell-data Tree a- = Branch !a !(Tree a) !(Tree a)- | Leaf--data Tree a- = Branch- !a- !(Tree a)- !(Tree a)- !(Tree a)- !(Tree a)- !(Tree a)- !(Tree a)- !(Tree a)- | Leaf--data HttpException- = InvalidStatusCode Int- | MissingContentHeader--data Person =- Person- { firstName :: !String -- ^ First name- , lastName :: !String -- ^ Last name- , age :: !Int -- ^ Age- }--data Expression a- = VariableExpression- { id :: Id Expression- , label :: a- }- | FunctionExpression- { var :: Id Expression- , body :: Expression a- , label :: a- }- | ApplyExpression- { func :: Expression a- , arg :: Expression a- , label :: a- }- | ConstructorExpression- { id :: Id Constructor- , label :: a- }-```--Spaces between deriving classes--``` haskell--- From https://github.com/chrisdone/hindent/issues/167-data Person =- Person- { firstName :: !String -- ^ First name- , lastName :: !String -- ^ Last name- , age :: !Int -- ^ Age- }- deriving (Eq, Show)-```--Hanging lambdas--``` haskell-bar :: IO ()-bar =- forM_ [1, 2, 3] $ \n -> do- putStrLn "Here comes a number!"- print n--foo :: IO ()-foo =- alloca 10 $ \a ->- alloca 20 $ \b ->- cFunction fooo barrr muuu (fooo barrr muuu) (fooo barrr muuu)-```--# Comments--Comments within a declaration--``` haskell-bob -- after bob- =- foo -- next to foo- -- line after foo- (bar- foo -- next to bar foo- bar -- next to bar- ) -- next to the end paren of (bar)- -- line after (bar)- mu -- next to mu- -- line after mu- -- another line after mu- zot -- next to zot- -- line after zot- (case casey -- after casey- of- Just -- after Just- -> do- justice -- after justice- *- foo- (blah * blah + z + 2 / 4 + a - -- before a line break- 2 * -- inside this mess- z /- 2 /- 2 /- aooooo /- aaaaa -- bob comment- ) +- (sdfsdfsd fsdfsdf) -- blah comment- putStrLn "")- [1, 2, 3]- [ 1 -- foo- , ( 2 -- bar- , 2.5 -- mu- )- , 3- ]- -- in the end of the function- where- alpha = alpha- -- between alpha and beta- beta = beta- -- after beta--foo = 1 -- after foo--gamma = do- delta- epsilon- -- in the end of a do-block 1--gamma = do- delta- epsilon- -- the very last block is detected differently-```--Doesn't work yet (wrong comment position detection)--```haskell pending-gamma = do- -- in the beginning of a do-block- delta- where- -- before alpha- alpha = alpha-```--Haddock comments--``` haskell--- | Module comment.-module X where---- | Main doc.-main :: IO ()-main = return ()--data X- = X -- ^ X is for xylophone.- | Y -- ^ Y is for why did I eat that pizza.--data X =- X- { field1 :: Int -- ^ Field1 is the first field.- , field11 :: Char- -- ^ This field comment is on its own line.- , field2 :: Int -- ^ Field2 is the second field.- , field3 :: Char -- ^ This is a long comment which starts next to- -- the field but continues onto the next line, it aligns exactly- -- with the field name.- , field4 :: Char- -- ^ This is a long comment which starts on the following line- -- from from the field, lines continue at the sme column.- }-```--Comments around regular declarations--``` haskell--- This is some random comment.--- | Main entry point.-main = putStrLn "Hello, World!"--- This is another random comment.-```--Multi-line comments--``` haskell-bob {- after bob -}- =- foo {- next to foo -}- {- line after foo -}- (bar- foo {- next to bar foo -}- bar {- next to bar -}- ) {- next to the end paren of (bar) -}- {- line after (bar) -}- mu {- next to mu -}- {- line after mu -}- {- another line after mu -}- zot {- next to zot -}- {- line after zot -}- (case casey {- after casey -}- of- Just {- after Just -}- -> do- justice {- after justice -}- *- foo- (blah * blah + z + 2 / 4 + a - {- before a line break -}- 2 * {- inside this mess -}- z /- 2 /- 2 /- aooooo /- aaaaa {- bob comment -}- ) +- (sdfsdfsd fsdfsdf) {- blah comment -}- putStrLn "")- [1, 2, 3]- [ 1 {- foo -}- , ( 2 {- bar -}- , 2.5 {- mu -}- )- , 3- ]--foo = 1 {- after foo -}-```--Multi-line comments with multi-line contents--``` haskell-{- | This is some random comment.-Here is more docs and such.-Etc.--}-main = putStrLn "Hello, World!"-{- This is another random comment. -}-```--# MINIMAL pragma--Monad example--```haskell-class A where- {-# MINIMAL return, ((>>=) | (join, fmap)) #-}-```--Very long names #310--```haskell-class A where- {-# MINIMAL averylongnamewithnoparticularmeaning- | ananotherverylongnamewithnomoremeaning #-}-```--# Behaviour checks--Unicode--``` haskell-α = γ * "ω"--- υ-```--Empty module--``` haskell-```--Trailing newline is preserved--``` haskell-module X where--foo = 123-```--# Complex input--A complex, slow-to-print decl--``` haskell-quasiQuotes =- [ ( ''[]- , \(typeVariable:_) _automaticPrinter ->- (let presentVar = varE (presentVarName typeVariable)- in lamE- [varP (presentVarName typeVariable)]- [|(let typeString = "[" ++ fst $(presentVar) ++ "]"- in ( typeString- , \xs ->- case fst $(presentVar) of- "GHC.Types.Char" ->- ChoicePresentation- "String"- [ ( "String"- , StringPresentation- "String"- (concatMap- getCh- (map (snd $(presentVar)) xs)))- , ( "List of characters"- , ListPresentation- typeString- (map (snd $(presentVar)) xs))- ]- where getCh (CharPresentation "GHC.Types.Char" ch) =- ch- getCh (ChoicePresentation _ ((_, CharPresentation _ ch):_)) =- ch- getCh _ = ""- _ ->- ListPresentation- typeString- (map (snd $(presentVar)) xs)))|]))- ]-```--Random snippet from hindent itself--``` haskell-exp' (App _ op a) = do- (fits, st) <- fitsOnOneLine (spaced (map pretty (f : args)))- if fits- then put st- else do- pretty f- newline- spaces <- getIndentSpaces- indented spaces (lined (map pretty args))- where- (f, args) = flatten op [a]- flatten :: Exp NodeInfo -> [Exp NodeInfo] -> (Exp NodeInfo, [Exp NodeInfo])- flatten (App _ f' a') b = flatten f' (a' : b)- flatten f' as = (f', as)-```--Quasi quotes--```haskell-exp = [name|exp|]--f [qq|pattern|] = ()-```--# C preprocessor--Conditionals (`#if`)--```haskell-isDebug :: Bool-#if DEBUG-isDebug = True-#else-isDebug = False-#endif-```--Macro definitions (`#define`)--```haskell-#define STRINGIFY(x) #x-f = STRINGIFY (y)-```--Escaped newlines--```haskell-#define LONG_MACRO_DEFINITION \- data Pair a b = Pair \- { first :: a \- , second :: b \- }-#define SHORT_MACRO_DEFINITION \- x-```--# Regression tests--jml Adds trailing whitespace when wrapping #221--``` haskell-x = do- config <- execParser options- comments <-- case config of- Diff False args -> commentsFromDiff args- Diff True args -> commentsFromDiff ("--cached" : args)- Files args -> commentsFromFiles args- mapM_ (putStrLn . Fixme.formatTodo) (concatMap Fixme.getTodos comments)-```--meditans hindent freezes when trying to format this code #222--``` haskell-c :: forall new.- ( Settable "pitch" Pitch (Map.AsMap (new Map.:\ "pitch")) new- , Default (Book' (Map.AsMap (new Map.:\ "pitch")))- )- => Book' new-c = set #pitch C (def :: Book' (Map.AsMap (new Map.:\ "pitch")))--foo ::- ( Foooooooooooooooooooooooooooooooooooooooooo- , Foooooooooooooooooooooooooooooooooooooooooo- )- => A-```--bitemyapp wonky multiline comment handling #231--``` haskell-module Woo where--hi = "hello"-{--test comment--}--- blah blah--- blah blah--- blah blah-```--cocreature removed from declaration issue #186--``` haskell--- https://github.com/chrisdone/hindent/issues/186-trans One e n =- M.singleton- (Query Unmarked (Mark NonExistent)) -- The goal of this is to fail always- (emptyImage {notPresent = S.singleton (TransitionResult Two (Just A) n)})-```--sheyll explicit forall in instances #218--``` haskell--- https://github.com/chrisdone/hindent/issues/218-instance forall x. C--instance forall x. Show x => C x-```--tfausak support shebangs #208--``` haskell given-#!/usr/bin/env stack--- stack runghc-main =- pure ()--- https://github.com/chrisdone/hindent/issues/208-```--``` haskell expect-#!/usr/bin/env stack--- stack runghc-main = pure ()--- https://github.com/chrisdone/hindent/issues/208-```--joe9 preserve newlines between import groups--``` haskell--- https://github.com/chrisdone/hindent/issues/200-import Data.List-import Data.Maybe--import FooBar-import MyProject--import GHC.Monad---- blah-import Hello--import CommentAfter -- Comment here shouldn't affect newlines-import HelloWorld--import CommentAfter -- Comment here shouldn't affect newlines--import HelloWorld---- Comment here shouldn't affect newlines-import CommentAfter--import HelloWorld-```--Wrapped import list shouldn't add newline--```haskell given-import ATooLongList- (alpha, beta, gamma, delta, epsilon, zeta, eta, theta)-import B-```--```haskell expect-import ATooLongList (alpha, beta, delta, epsilon, eta, gamma, theta, zeta)-import B-```--radupopescu `deriving` keyword not aligned with pipe symbol for type declarations--``` haskell-data Stuffs- = Things- | This- | That- deriving (Show)--data Simple =- Simple- deriving (Show)-```--sgraf812 top-level pragmas should not add an additional newline #255--``` haskell--- https://github.com/chrisdone/hindent/issues/255-{-# INLINE f #-}-f :: Int -> Int-f n = n-```--ivan-timokhin breaks code with type operators #277--```haskell--- https://github.com/chrisdone/hindent/issues/277-{-# LANGUAGE TypeOperators #-}-{-# LANGUAGE MultiParamTypeClasses #-}--type m ~> n = ()--class (a :< b) c-```--ivan-timokhin variables swapped around in constraints #278--```haskell--- https://github.com/chrisdone/hindent/issues/278-data Link c1 c2 a c =- forall b. (c1 a b, c2 b c) =>- Link (Proxy b)-```--ttuegel qualified infix sections get mangled #273--```haskell--- https://github.com/chrisdone/hindent/issues/273-import qualified Data.Vector as V--main :: IO ()-main = do- let _ = foldr1 (V.++) [V.empty, V.empty]- pure ()---- more corner cases.-xs = V.empty V.++ V.empty--ys = (++) [] []--cons :: V.Vector a -> V.Vector a -> V.Vector a-cons = (V.++)-```--ivan-timokhin breaks operators type signatures #301--```haskell--- https://github.com/chrisdone/hindent/issues/301-(+) :: ()-```--cdepillabout Long deriving clauses are not reformatted #289--```haskell-newtype Foo =- Foo Proxy- deriving ( Functor- , Applicative- , Monad- , Semigroup- , Monoid- , Alternative- , MonadPlus- , Foldable- , Traversable- )-```--ivan-timokhin Breaks instances with type operators #342--```haskell--- https://github.com/chrisdone/hindent/issues/342-instance Foo (->)--instance Foo (^>)--instance Foo (T.<^)-```--Indents record constructions and updates #358-```haskell-foo =- assert- sanityCheck- BomSnapshotAggr- { snapshot = Just bs- , previousId = M.bomSnapshotHistoryPreviousId . entityVal <$> bsp- , nextId = M.bomSnapshotHistoryNextId . entityVal <$> bsn- , bomEx = bx''- , orderSubstitutes =- S.fromList . map OrderSubstituteAggrByCreatedAtAsc $ subs- , snapshotSubstitute = msub- }-```--paraseba Deriving strategies with multiple deriving clauses-```haskell--- https://github.com/commercialhaskell/hindent/issues/503-{-# LANGUAGE DerivingStrategies #-}-{-# LANGUAGE DeriveAnyClass #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}--module Foo where--import Data.Typeable-import GHC.Generics--newtype Number a =- Number a- deriving (Generic)- deriving newtype (Show, Eq)- deriving anyclass (Typeable)-```--neongreen "{" is lost when formatting "Foo{}" #366--```haskell--- https://github.com/chrisdone/hindent/issues/366-foo = Nothing {}-```--jparoz Trailing space in list comprehension #357--```haskell--- https://github.com/chrisdone/hindent/issues/357-foo =- [ (x, y)- | x <- [1 .. 10]- , y <- [11 .. 20]- , even x- , even x- , even x- , even x- , even x- , odd y- ]-```--ttuegel Record formatting applied to expressions with RecordWildCards #274--```haskell--- https://github.com/chrisdone/hindent/issues/274-foo (Bar {..}) = Bar {..}-```--RecursiveDo `rec` and `mdo` keyword #328--```haskell-rec = undefined--mdo = undefined-```--sophie-h Record syntax change in 5.2.2 #393--```haskell--- https://github.com/commercialhaskell/hindent/issues/393-data X- = X- { x :: Int- }- | X'--data X =- X- { x :: Int- , x' :: Int- }--data X- = X- { x :: Int- , x' :: Int- }- | X'-```--k-bx Infix data constructor gets reformatted into a parse error #328--```haskell--- https://github.com/commercialhaskell/hindent/issues/328-data Expect =- String :--> String- deriving (Show)-```--tfausak Class constraints cause too many newlines #244--```haskell--- https://github.com/commercialhaskell/hindent/issues/244-x :: Num a => a-x = undefined---- instance-instance Num a => C a---- long instance-instance Nuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuum a =>- C a where- f = undefined-```--expipiplus1 Always break before `::` on overlong signatures #390--```haskell--- https://github.com/commercialhaskell/hindent/issues/390-fun :: Is => Short-fun = undefined--someFunctionSignature ::- Wiiiiiiiiiiiiiiiiith- -> Enough- -> (Arguments -> To ())- -> Overflow (The Line Limit)-```--duog Long Type Constraint Synonyms are not reformatted #290--```haskell--- https://github.com/commercialhaskell/hindent/issues/290-type MyContext m- = ( MonadState Int m- , MonadReader Int m- , MonadError Text m- , MonadMask m- , Monoid m- , Functor m)-```--ocharles Type application differs from function application (leading to long lines) #359--```haskell--- https://github.com/commercialhaskell/hindent/issues/359-thing ::- ( ResB.BomEx- , Maybe [( Entity BomSnapshot- , ( [ResBS.OrderSubstituteAggr]- , ( Maybe (Entity BomSnapshotHistory)- , Maybe (Entity BomSnapshotHistory))))])- -> [(ResB.BomEx, Maybe ResBS.BomSnapshotAggr)]-```--NorfairKing Do as left-hand side of an infix operation #296--```haskell--- https://github.com/commercialhaskell/hindent/issues/296-block =- do ds <- inBraces $ inWhiteSpace declarations- return $ Block ds- <?> "block"-```--NorfairKing Hindent linebreaks after very short names if the total line length goes over 80 #405--```haskell--- https://github.com/commercialhaskell/hindent/issues/405-t =- f "this is a very loooooooooooooooooooooooooooong string that goes over the line length"- argx- argy- argz--t =- function- "this is a very loooooooooooooooooooooooooooong string that goes over the line length"- argx- argy- argz-```--ivan-timokhin No linebreaks for long functional dependency declarations #323--```haskell--- https://github.com/commercialhaskell/hindent/issues/323-class Foo a b | a -> b where- f :: a -> b--class Foo a b c d e f- | a b c d e -> f- , a b c d f -> e- , a b c e f -> d- , a b d e f -> c- , a c d e f -> b- , b c d e f -> a- where- foo :: a -> b -> c -> d -> e -> f-```--utdemir Hindent breaks TH name captures of operators #412--```haskell--- https://github.com/commercialhaskell/hindent/issues/412-data T =- (-)--q = '(-)--data (-)--q = ''(-)-```--utdemir Hindent can not parse empty case statements #414--```haskell--- https://github.com/commercialhaskell/hindent/issues/414-{-# LANGUAGE EmptyCase #-}-{-# LANGUAGE LambdaCase #-}--f1 = case () of {}--f2 = \case {}-```--TimoFreiberg INLINE (and other) pragmas for operators are reformatted without parens #415--```haskell--- https://github.com/commercialhaskell/hindent/issues/415-{-# NOINLINE (<>) #-}-```--NorfairKing Hindent breaks servant API's #417--```haskell--- https://github.com/commercialhaskell/hindent/issues/417-type API = api1 :<|> api2-```--andersk Cannot parse @: operator #421--```haskell--- https://github.com/commercialhaskell/hindent/issues/421-a @: b = a + b--main = print (2 @: 2)-```--andersk Corrupts parenthesized type operators #422--```haskell--- https://github.com/commercialhaskell/hindent/issues/422-data T a =- a :@ a--test = (:@)-```--NorfairKing Infix constructor pattern is broken #424--```haskell--- https://github.com/commercialhaskell/hindent/issues/424-from $ \(author `InnerJoin` post) -> pure ()-```--NorfairKing Hindent can no longer parse type applications code #426--```haskell--- https://github.com/commercialhaskell/hindent/issues/426-{-# LANGUAGE TypeApplications #-}--f :: Num a => a-f = id--x = f @Int 12-```--michalrus Multiline `GHC.TypeLits.Symbol`s are being broken #451--```haskell--- https://github.com/commercialhaskell/hindent/issues/451-import GHC.TypeLits (Symbol)--data X (sym :: Symbol)- deriving (Typeable)--type Y = X "abc\n\n\ndef"-```--DavidEichmann Existential Quantification reordered #443--```haskell--- https://github.com/commercialhaskell/hindent/issues/443-{-# LANGUAGE ExistentialQuantification #-}--data D =- forall a b c. D a b c-```--sophie-h Regression: Breaks basic type class code by inserting "|" #459--```haskell--- https://github.com/commercialhaskell/hindent/issues/459-class Class1 a =>- Class2 a- where- f :: a -> Int--class (Eq a, Show a) =>- Num a- where- (+), (-), (*) :: a -> a -> a- negate :: a -> a- abs, signum :: a -> a- fromInteger :: Integer -> a-```--michalrus `let … in …` inside of `do` breaks compilation #467--```haskell--- https://github.com/commercialhaskell/hindent/issues/467-main :: IO ()-main = do- let x = 5- in when (x > 0) (return ())-```--sophie-h Breaking valid top-level template haskell #473--```haskell--- https://github.com/commercialhaskell/hindent/issues/473-template $- haskell- [ ''SomeVeryLongName- , ''AnotherLongNameEvenLongToBreakTheLine- , ''LastLongNameInList- ]-```--schroffl Hindent produces invalid Syntax from FFI exports #479--```haskell--- https://github.com/commercialhaskell/hindent/issues/479-foreign export ccall "test" test :: IO ()--foreign import ccall "test" test :: IO ()--foreign import ccall safe "test" test :: IO ()--foreign import ccall unsafe "test" test :: IO ()-```--ptek Reformatting of the {-# OVERLAPPING #-} pragma #386--```haskell--- https://github.com/commercialhaskell/hindent/issues/386-instance {-# OVERLAPPING #-} Arbitrary (Set Int) where- arbitrary = undefined-```--cdsmith Quotes are dropped from package imports #480--```haskell--- https://github.com/commercialhaskell/hindent/issues/480-{-# LANGUAGE PackageImports #-}--import qualified "base" Prelude as P-```--alexwl Hindent breaks associated type families annotated with injectivity information #528--```haskell--- https://github.com/commercialhaskell/hindent/issues/528-class C a where- type F a = b | b -> a-```--sophie-h Fails to create required indentation for infix #238--```haskell--- https://github.com/commercialhaskell/hindent/issues/238-{-# LANGUAGE ScopedTypeVariables #-}--import Control.Exception--x :: IO Int-x =- do putStrLn "ok"- error "ok"- `catch` (\(_ :: IOException) -> pure 1) `catch`- (\(_ :: ErrorCall) -> pure 2)--```--lippirk Comments on functions in where clause not quite right #540--```haskell--- https://github.com/chrisdone/hindent/issues/540-topLevelFunc1 = f- where- -- comment on func in where clause- -- stays in the where clause- f = undefined--topLevelFunc2 = f . g- where- {- multi- line- comment -}- f = undefined- -- single line comment- g = undefined+# HIndent test codes++This file is a test suite. Each section maps to an HSpec test, and+each line that is followed by a Haskell code fence is tested to make+sure re-formatting that code snippet produces the same result.++You can browse through this document to see what HIndent's style is+like, or contribute additional sections to it, or regression tests.++## Shebangs++No newlines after a shebang++```haskell given+#!/usr/bin/env stack++-- stack runghc+main =+ pure ()+-- https://github.com/mihaimaruseac/hindent/issues/208+```++```haskell expect+#!/usr/bin/env stack+-- stack runghc+main = pure ()+-- https://github.com/mihaimaruseac/hindent/issues/208+```++Double shebangs++```haskell+#!/usr/bin/env stack+#!/usr/bin/env stack+main = pure ()+```++## Modules++Empty module++```haskell+```++### Module headers++Without an export list++```haskell+module X where++x = 1+```++With an export list++```haskell+module X+ ( x+ , y+ , Z+ , P(x, z)+ , module Foo+ ) where+```++With an export list; indentation 4++```haskell 4+module X+ ( x+ , y+ , Z+ , P(x, z)+ ) where+```++### Module-level pragmas++A `WARNING` for a module without an export list.++```haskell+module Foo {-# WARNING "Debug purpose only." #-} where+```++A `DEPRECATED` for a module with an export list.++```haskell+module Foo {-# DEPRECATED "Use Bar." #-}+ ( x+ , y+ , z+ ) where+```++A pragma's name is converted to the SHOUT_CASE.++```haskell given+{-# lAnGuAgE CPP #-}+```++```haskell expect+{-# LANGUAGE CPP #-}+```++Pragmas, GHC options, and haddock options.++```haskell+{-# LANGUAGE CPP #-}+{-# LANGUAGE NoRebindableSyntax #-}+{-# OPTIONS_GHC -fno-warn-missing-import-lists #-}+{-# OPTIONS_GHC -w #-}+{-# OPTIONS_HADDOCK show-extensions #-}++module Foo where+```++Accept pragmas via `OPTIONS -XFOO`++```haskell+{-# OPTIONS -XPatternSynonyms #-}++import Foo (pattern Bar)+```++Accept pragmas via `OPTIONS_GHC -XFOO`++```haskell+{-# OPTIONS_GHC -XPatternSynonyms #-}++import Foo (pattern Bar)+```++A pragma's length is adjusted automatically++```haskell given+{-# LANGUAGE OverloadedStrings #-}+```++```haskell expect+{-# LANGUAGE OverloadedStrings #-}+```++Collect multiple extensions correctly++```haskell+{-# LANGUAGE DerivingStrategies #-}+{-# LANGUAGE PatternSynonyms #-}++import Language.C.Types (pattern TypeName)+```++Collect multiple extensions separated by commas correctly++```haskell given+{-# LANGUAGE TypeApplications,+ PatternSynonyms #-}++import Foo (pattern Bar)++foo = bar @Int 3+```++```haskell expect+{-# LANGUAGE TypeApplications, PatternSynonyms #-}++import Foo (pattern Bar)++foo = bar @Int 3+```++Do not collect pragma-like comments++```haskell+-- {-# LANGUAGE StaticPointers #-}+{-++{-# LANGUAGE StaticPointers #-}++-}+-- @static@ is no longer a valid identifier+-- once `StaticPointers` is enabled.+static = 3+```++## Imports, foreign imports, and foreign exports++Import lists++```haskell+import Control.Lens (_2, _Just)+import Data.Text+import Data.Text+import qualified Data.Text as T+import qualified Data.Text (a, b, c)+import Data.Text (a, b, c)+import Data.Text hiding (a, b, c)+```++Shorter identifiers come first++```haskell+import Foo ((!), (!!))+```++Import with `ExplicitNamespaces`.++```haskell+{-# LANGUAGE ExplicitNamespaces #-}++import Prlude (type FilePath)+```++Import a pattern++```haskell+{-# LANGUAGE PatternSynonyms #-}++import Foo (pattern Bar)+```++Sorted++```haskell given+import B+import A+```++```haskell expect+import A+import B+```++Explicit imports - capitals first (typeclasses/types), then operators, then identifiers++```haskell given+import qualified MegaModule as M ((>>>), MonadBaseControl, void, MaybeT(..), join, Maybe(Nothing, Just), liftIO, Either, (<<<), Monad(return, (>>=), (>>)))+```++```haskell expect+import qualified MegaModule as M+ ( Either+ , Maybe(Just, Nothing)+ , MaybeT(..)+ , Monad((>>), (>>=), return)+ , MonadBaseControl+ , (<<<)+ , (>>>)+ , join+ , liftIO+ , void+ )+```++Pretty import specification++```haskell+import A hiding+ ( foobarbazqux+ , foobarbazqux+ , foobarbazqux+ , foobarbazqux+ , foobarbazqux+ , foobarbazqux+ , foobarbazqux+ )++import Name hiding ()++import {-# SOURCE #-} safe qualified Module as M hiding (a, b, c, d, e, f)+```++An import declaration importing lots of data constructors++```haskell+import Direction+ ( Direction(East, North, NorthEast, NorthWest, South, SouthEast,+ SouthWest, West)+ , allDirections+ )+```++Preserve newlines between import groups++```haskell+-- https://github.com/mihaimaruseac/hindent/issues/200+import GHC.Monad++import CommentAfter -- Comment here shouldn't affect newlines+import HelloWorld++import CommentAfter -- Comment here shouldn't affect newlines++-- Comment here shouldn't affect newlines+import CommentAfter+```++`PackageImports`++```haskell+-- https://github.com/mihaimaruseac/hindent/issues/480+{-# LANGUAGE PackageImports #-}++import qualified "base" Prelude as P+```++Importing a `#`++```haskell+-- https://github.com/mihaimaruseac/hindent/issues/547+import Diagrams.Prelude ((#))+```++### Foreign imports and exports++A `ccall` foreign export++```haskell+{-# LANGUAGE ForeignFunctionInterface #-}++foreign export ccall "test" test :: IO ()+```++A `ccall` unsafe foreign import++```haskell+{-# LANGUAGE ForeignFunctionInterface #-}++foreign import ccall unsafe "test" test :: IO ()+```++A `capi` foreign import++```haskell+{-# LANGUAGE CApiFFI #-}+{-# LANGUAGE ForeignFunctionInterface #-}++foreign import capi safe "foo" test :: IO Int+```++A `stdcall` foreign import++```haskell+{-# LANGUAGE ForeignFunctionInterface #-}++foreign import stdcall safe "test" bar :: IO ()+```++A `prim` foreign import++```haskell+{-# LANGUAGE ForeignFunctionInterface #-}++foreign import prim safe "test" test :: IO ()+```++A `javascript` foreign import++```haskell+{-# LANGUAGE ForeignFunctionInterface #-}++foreign import javascript safe "test" test :: IO ()+```++## Declarations++Data family++```haskell+data family Foo a+```++`StandaloneKindSignatures`++```haskell+{-# LANGUAGE StandaloneKindSignatures #-}++type Foo :: Type -> Type -> Type+```++Default declaration++```haskell+default (Integer, Double)+```++### `ANN` pragmas++Value annotation.++```haskell+{-# ANN foo "annotation" #-}+```++Type annotation.++```haskell+{-# ANN type Foo "annotation" #-}+```++Module annotation.++```haskell+{-# ANN module "annotation" #-}+```++### Class declarations++Default signatures++```haskell+-- https://github.com/chrisdone/hindent/issues/283+class Foo a where+ bar :: a -> a -> a+ default bar :: Monoid a => a -> a -> a+ bar = mappend+```++`TypeOperators` and `MultiParamTypeClasses`++```haskell+-- https://github.com/chrisdone/hindent/issues/277+{-# LANGUAGE TypeOperators #-}+{-# LANGUAGE MultiParamTypeClasses #-}++class (a :< b) c+```++#### Class constraints++Empty++```haskell+class () =>+ Foo a+```++Long++```haskell+class ( Foo a+ , Bar a+ , Baz a+ , Hoge a+ , Fuga a+ , Piyo a+ , Hogera a+ , Hogehoge a+ , Spam a+ , Ham a+ ) =>+ Quux a+```++#### Class methods++With class constraints++```haskell+class Foo f where+ myEq :: (Eq a) => f a -> f a -> Bool+```++Long signatures++```haskell+class Foo a where+ fooBarBazQuuxHogeFuga ::+ a -> a -> a -> a -> a -> a -> a -> a -> a -> a -> a -> a -> a+```++#### Associated type synonyms++Associated type synonyms++```haskell+class Foo a where+ type Bar b+```++Associated type synonyms annotated with injectivity information++```haskell+-- https://github.com/commercialhaskell/hindent/issues/528+class C a where+ type F a = b | b -> a+```++### Class instance declarations++Without methods++```haskell+instance C a+```++With methods++```haskell+instance C a where+ foobar = do+ x y+ k p+```++With type operators++```haskell+-- https://github.com/mihaimaruseac/hindent/issues/342+instance Foo (->)++instance Foo (^>)++instance Foo (T.<^)+```++With a type alias++```haskell+instance Foo a where+ type Bar a = Int+```++A `where` clause between instance functions++```haskell+instance Pretty HsModule where+ pretty' = undefined+ where+ a = b+ commentsBefore = Nothing+```++With a `SPECIALISE` pragma++```haskell+instance (Show a) => Show (Foo a) where+ {-# SPECIALISE instance Show (Foo String) #-}+ show = undefined+```++With associated data types++```haskell+-- https://github.com/mihaimaruseac/hindent/issues/493+instance GM 'Practice where+ data MatchConfig 'Practice = MatchConfig'Practice+ { teamSize :: Int+ , ladder :: Ladder+ }+```++#### With overlapping pragmas++`OVERLAPPING`++```haskell+-- https://github.com/mihaimaruseac/hindent/issues/386+instance {-# OVERLAPPING #-} Arbitrary (Set Int) where+ arbitrary = undefined+```++`OVERLAPPABLE`++```haskell+instance {-# OVERLAPPABLE #-} Arbitrary Int where+ arbitrary = undefined+```++`OVERLAPS`++```haskell+instance {-# OVERLAPS #-} Arbitrary String where+ arbitrary = undefined+```++`INCOHERENT`++```haskell+instance {-# INCOHERENT #-} Arbitrary String where+ arbitrary = undefined+```++#### With class constraints++Short name++```haskell+-- https://github.com/mihaimaruseac/hindent/issues/244+instance Num a => C a+```++Long name++```haskell+-- https://github.com/mihaimaruseac/hindent/issues/244+instance Nuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuum a =>+ C a where+ f = undefined+```++#### Explicit foralls++Without class constraints++```haskell+-- https://github.com/mihaimaruseac/hindent/issues/218+instance forall x. C+```++With class constraints++```haskell+-- https://github.com/mihaimaruseac/hindent/issues/218+instance forall x. Show x => C x+```++#### Symbol class constructor++Infix++```haskell+instance Bool :?: Bool+```++Prefix++```haskell+instance (:?:) Int Bool+```++### Data declarations++Data declaration with underscore++```haskell+data Stanza = MkStanza+ { _stanzaBuildInfo :: BuildInfo+ , stanzaIsSourceFilePath :: FilePath -> Bool+ }+```++A data declaration with typeclass constraints++```haskell+data Ord a =>+ Foo =+ Foo a+```++Multiple constructors at once++```haskell+data Foo = Foo+ { foo, bar, baz, qux, quux :: Int+ }+```++No fields++```haskell+data Foo+```++Single field++```haskell+data Foo =+ Foo+```++Multiple unnamed fields++```haskell+data HttpException+ = InvalidStatusCode Int+ | MissingContentHeader+```++A lot of unnamed fields in a constructor++```haskell+data Foo =+ Foo+ String+ String+ String+ String+ String+ String+ String+ String+ String+ String+ String+```++A banged field++```haskell+data Foo =+ Foo !Int+```++A record constructor with a field++```haskell+data Foo = Foo+ { foo :: Int+ }+```++Multiple constructors with fields++```haskell+data Expression a+ = VariableExpression+ { id :: Id Expression+ , label :: a+ }+ | FunctionExpression+ { var :: Id Expression+ , body :: Expression a+ , label :: a+ }+ | ApplyExpression+ { func :: Expression a+ , arg :: Expression a+ , label :: a+ }+ | ConstructorExpression+ { id :: Id Constructor+ , label :: a+ }+```++A mixture of constructors with unnamed fields and record constructors++```haskell+-- https://github.com/mihaimaruseac/hindent/issues/393+data X+ = X+ { x :: Int+ , x' :: Int+ }+ | X'+```++An infix data constructor++```haskell+data Foo =+ Int :--> Int+```++An `UNPACK`ed field.++```haskell+data Foo = Foo+ { x :: {-# UNPACK #-} Int+ }+```++An `NOUNPACK`ed field.++```haskell+data Foo = Foo+ { x :: {-# NOUNPACK #-} !Int+ }+```++A lazy field.++```haskell+data Foo = Foo+ { x :: ~Int+ }+```++#### Fields with `forall` constraints++Single++```haskell+-- https://github.com/mihaimaruseac/hindent/issues/278+data Link c1 c2 a c =+ forall b. (c1 a b, c2 b c) =>+ Link (Proxy b)+```++Multiple++```haskell+-- https://github.com/mihaimaruseac/hindent/issues/443+{-# LANGUAGE ExistentialQuantification #-}++data D =+ forall a b c. D a b c+```++#### Derivings++With a single constructor++```haskell+data Simple =+ Simple+ deriving (Show)+```++With multiple constructors++```haskell+data Stuffs+ = Things+ | This+ | That+ deriving (Show)+```++With a record constructor++```haskell+-- From https://github.com/mihaimaruseac/hindent/issues/167+data Person = Person+ { firstName :: !String -- ^ First name+ , lastName :: !String -- ^ Last name+ , age :: !Int -- ^ Age+ } deriving (Eq, Show)+```++Multiple derivings++```haskell+-- https://github.com/mihaimaruseac/hindent/issues/289+newtype Foo =+ Foo Proxy+ deriving ( Functor+ , Applicative+ , Monad+ , Semigroup+ , Monoid+ , Alternative+ , MonadPlus+ , Foldable+ , Traversable+ )+```++Various deriving strategies++```haskell+-- https://github.com/mihaimaruseac/hindent/issues/503+{-# LANGUAGE DerivingStrategies #-}+{-# LANGUAGE DeriveAnyClass #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE DeriveVia #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}++module Foo where++import Data.Typeable+import GHC.Generics++newtype Number a =+ Number a+ deriving (Generic)+ deriving stock (Ord)+ deriving newtype (Eq)+ deriving anyclass (Typeable)+ deriving (Show) via a+```++`StandaloneDeriving`++```haskell+{-# LANGUAGE DerivingVia #-}+{-# LANGUAGE StandaloneDeriving #-}++data Foo =+ Foo++deriving instance Eq Foo++deriving stock instance Ord Foo++deriving via (Foo a) instance Show (Bar a)+```++#### GADT declarations++With a kind signature++```haskell+data Ty :: (* -> *) where+ TCon+ :: { field1 :: Int+ , field2 :: Bool}+ -> Ty Bool+ TCon' :: (a :: *) -> a -> Ty a+```++Without a kind signature++```haskell+data Foo where+ Foo+ :: forall v. Ord v+ => v+ -> v+ -> Foo+```++With a `forall` but no contexts++```haskell+data Foo where+ Foo :: forall v. v -> v -> Foo+```++With a context but no `forall`s++```haskell+data Foo where+ Foo :: (Ord v) => v -> v -> Foo+```++With methods with record signatures++```haskell+-- https://github.com/mihaimaruseac/hindent/issues/581+data Test where+ Test :: Eq a => { test :: a } -> Test+```++### Data instance declarations++Without type applications++```haskell+data instance Foo Int =+ FInt+```++With type applications++```haskell+data instance Foo @k a =+ FString+```++### Function declarations++Case inside `do` and lambda++```haskell+foo =+ \x -> do+ case x of+ Just _ -> 1+ Nothing -> 2+```++A `case` inside a `let`.++```haskell+f = do+ let (x, xs) =+ case gs of+ [] -> undefined+ (x':xs') -> (x', xs')+ undefined+```++A `do` inside a lambda.++```haskell+printCommentsAfter =+ case commentsAfter p of+ xs -> do+ forM_ xs $ \(L loc c) -> do+ eolCommentsArePrinted+```++Case with natural pattern (See NPat of https://hackage.haskell.org/package/ghc-lib-parser-9.2.3.20220527/docs/Language-Haskell-Syntax-Pat.html#t:Pat)++```haskell+foo =+ case x of+ 0 -> pure ()+ _ -> undefined+```++```haskell+s8_stripPrefix bs1@(S.PS _ _ l1) bs2+ | bs1 `S.isPrefixOf` bs2 = Just (S.unsafeDrop l1 bs2)+ | otherwise = Nothing+```++A `do` inside a guard arm++```haskell+f+ | x == 1 = do+ a+ b+```++`if` having a long condition++```haskell+foo =+ if fooooooo ||+ baaaaaaaaaaaaaaaaaaaaa || apsdgiuhasdpfgiuahdfpgiuah || bazzzzzzzzzzzzz+ then a+ else b+```++A long signature inside a where clause++```haskell+cppSplitBlocks :: ByteString -> [CodeBlock]+cppSplitBlocks inp = undefined+ where+ spanCPPLines ::+ [(Int, ByteString)] -> ([(Int, ByteString)], [(Int, ByteString)])+ spanCPPLines = undefined+```++A `forall` type inside a where clause++```haskell+replaceAllNotUsedAnns :: HsModule -> HsModule+replaceAllNotUsedAnns = everywhere app+ where+ app ::+ forall a. Data a+ => (a -> a)+ app = undefined++f :: a+f = undefined+ where+ ggg ::+ forall a. Typeable a+ => a+ -> a+ ggg = undefined+```++Prefix notation for operators++```haskell+(+) a b = a+```++Guards and pattern guards++```haskell+f x+ | x <- Just x+ , x <- Just x =+ case x of+ Just x -> e+ | otherwise = do e+ where+ x = y+```++Where clause++```haskell+sayHello = do+ name <- getLine+ putStrLn $ greeting name+ where+ greeting name = "Hello, " ++ name ++ "!"+```++An empty line is inserted after an empty `where`++```haskell given+f = evalState+ -- A comment+ where+```++```haskell expect+f = evalState+ -- A comment+ where++```++Multiple function declarations with an empty `where`++```haskell+f = undefined+ where+++g = undefined+```++Let inside a `where`++```haskell+g x =+ let x = 1+ in x+ where+ foo =+ let y = 2+ z = 3+ in y+```++The indent after a top-level `where` has always 2 spaces.++```haskell 4+f = undefined+ where+ g = undefined+```++The indent after a `where` inside a `case` depends on the indent space setting++```haskell 4+f =+ case x of+ x -> undefined+ where y = undefined+```++#### Pattern matchings++View pattern++```haskell+foo (f -> Just x) = print x+foo _ = Nothing+```++Match against a list++```haskell+head [] = undefined+head [x] = x+head xs = head $ init xs++foo [Coord _ _, Coord _ _] = undefined+```++Multiple matchings++```haskell+head' [] = Nothing+head' (x:_) = Just x+```++n+k patterns++```haskell+f (n+5) = 0+```++Binary symbol data constructor in pattern++```haskell+f (x :| _) = x++f' ((:|) x _) = x++f'' ((Data.List.NonEmpty.:|) x _) = x++g (x:xs) = x++g' ((:) x _) = x+```++Infix constructor pattern++```haskell+-- https://github.com/mihaimaruseac/hindent/issues/424+from $ \(author `InnerJoin` post) -> pure ()+```++Unboxed sum pattern matching.++```haskell+{-# LANGUAGE UnboxedSums #-}++f (# (# n, _ #) | #) = (# n | #)+f (# | b #) = (# | b #)+```++Pattern matching against a infix constructor with a module name prefix++```haskell+foo (a FOO.:@: b) = undefined+```++##### Pattern matchings against record++Short++```haskell+fun Rec {alpha = beta, gamma = delta, epsilon = zeta, eta = theta, iota = kappa} = do+ beta + delta + zeta + theta + kappa+```++Long++```haskell+fun Rec { alpha = beta+ , gamma = delta+ , epsilon = zeta+ , eta = theta+ , iota = kappa+ , lambda = mu+ } =+ beta + delta + zeta + theta + kappa + mu + beta + delta + zeta + theta + kappa+```++Another long one++```haskell+resetModuleStartLine m@HsModule { hsmodAnn = epa@EpAnn {..}+ , hsmodName = Just (L (SrcSpanAnn _ (RealSrcSpan sp _)) _)+ } = undefined+```++Symbol constructor, short++```haskell+fun ((:..?) {}) = undefined+```++Symbol constructor, long++```haskell+fun (:..?) { alpha = beta+ , gamma = delta+ , epsilon = zeta+ , eta = theta+ , iota = kappa+ , lambda = mu+ } =+ beta + delta + zeta + theta + kappa + mu + beta + delta + zeta + theta + kappa+```++Symbol field++```haskell+f (X {(..?) = x}) = x+```++Punned symbol field++```haskell+f' (X {(..?)}) = (..?)+```++`RecordWileCards`++```haskell+-- https://github.com/mihaimaruseac/hindent/issues/274+foo (bar@Bar {..}) = Bar {..}++resetModuleNameColumn m@HsModule {hsmodName = Just (L (SrcSpanAnn epa@EpAnn {..} sp) name)} =+ m++bar Bar {baz = before, ..} = Bar {baz = after, ..}+```++As pattern++```haskell+f all@(x:xs) = all+```++### Infix declarations++infixl++```haskell+infixl 1 ^-^+```++infixr++```haskell+infixr 1 ^-^+```++infix++```haskell+infix 1 ^-^+```++### Pattern synonym declarations++Unidirectional with a pattern type signature++```haskell+{-# LANGUAGE PatternSynonyms #-}++pattern Foo :: Int -> Int -> [Int]+pattern Foo x y <- [x, y]+```++Bidirectional record pattern++```haskell+{-# LANGUAGE PatternSynonyms #-}++pattern Pair {x, y} = (x, y)+```++#### Explicit bidirectional++With a prefix constructor++```haskell+{-# LANGUAGE PatternSynonyms #-}++pattern Fst x <- (x, x)+ where Fst x = (x, 0)+```++With an infix constructor++```haskell+{-# LANGUAGE PatternSynonyms #-}++pattern x :| xs <- x : xs+ where a :| b = a : b+```++### Pragma declarations++`INLINE`++```haskell+-- https://github.com/mihaimaruseac/hindent/issues/255+{-# INLINE f #-}+f :: Int -> Int+f n = n+```++`NOINLINE` with an operator enclosed by parentheses++```haskell+-- https://github.com/mihaimaruseac/hindent/issues/415+{-# NOINLINE (<>) #-}+```++`INLINABLE`++```haskell+{-# INLINABLE f #-}+f :: a+f = undefined+```++`OPAQUE`++```haskell since 9.4.0+{-# OPAQUE f #-}+f :: a+f = undefined+```++`INLINE` with levels++```haskell+{-# INLINE [0] f #-}+{-# INLINE [~1] g #-}+```++A `DEPRECATED`.++```haskell+{-# DEPRECATED+giveUp "Never give up."+ #-}++giveUp = undefined+```++A `WARNING`.++```haskell+{-# WARNING+debugCode "The use of 'debugCode'"+ #-}+```++A `COMPLETE`++```haskell+{-# COMPLETE Single, Anylist #-}+```++Top-level `SPECIALISE`++```haskell+{-# SPECIALISE lookup :: [(Int, Int)] -> Int -> Maybe Int #-}+```++A `SCC`++```haskell+{-# SCC bar #-}+```++#### Rule declarations++Without `forall`s++```haskell+{-# RULES+"foo/bar" foo = bar+ #-}+```++With `forall` but no type signatures++```haskell+{-# RULES+"piyo/pochi" forall a. piyo a = pochi a a+ #-}+```++With `forall` and type signatures++```haskell+{-# RULES+"hoge/fuga" forall (a :: Int). hoge a = fuga a a+ #-}+```++### Role annotation declarations++`normal`++```haskell+{-# LANGUAGE RoleAnnotations #-}++type role Foo nominal+```++`representational`++```haskell+{-# LANGUAGE RoleAnnotations #-}++type role Bar representational+```++`phantom`++```haskell+{-# LANGUAGE RoleAnnotations #-}++type role Baz phantom+```++### Type family declarations++Without annotations++```haskell+type family Id a+```++With annotations++```haskell+type family Id a :: *+```++With injectivity annotations++```haskell+type family Id a = r | r -> a+```++Closed type families++```haskell+type family Closed (a :: k) :: Bool where+ Closed (x @Int) = 'Int+ Closed x = 'True+```++### Type family instance declarations++Without holes++```haskell+type instance Id Int = Int+```++With a hole++```haskell+type instance Id _ = String+```++### Type signature declarations++Multiple function signatures at once++```haskell+a, b, c :: Int+```++Type using a numeric value++```haskell+f :: Foo 0+```++Type using a character value++```haskell+f :: Foo 'a'+```++Type using a unicode string value++```haskell+f :: Foo "あ"+```++A dot not enclosed by spaces is printed correctly if `OverloadedRecordDot` is not enabled.++```haskell given+f :: forall a.(Data a, Typeable a) => a+```++```haskell expect+f :: forall a. (Data a, Typeable a)+ => a+```++Short++```haskell+-- https://github.com/mihaimaruseac/hindent/issues/390+fun :: Short+fun = undefined+```++Always break after `::` on overlong signatures++```haskell+-- https://github.com/mihaimaruseac/hindent/issues/390+someFunctionSignature ::+ Wiiiiiiiiiiiiiiiiith+ -> Enough+ -> (Arguments -> To ())+ -> Overflow (The Line Limit)+```++A long type is broken into lines++```haskell+-- https://github.com/mihaimaruseac/hindent/issues/359+thing ::+ ( ResB.BomEx+ , Maybe+ [( Entity BomSnapshot+ , ( [ResBS.OrderSubstituteAggr]+ , ( Maybe (Entity BomSnapshotHistory)+ , Maybe (Entity BomSnapshotHistory))))])+ -> [(ResB.BomEx, Maybe ResBS.BomSnapshotAggr)]+```++Long parameter list with a `forall`++```haskell+fooooooooo ::+ forall a.+ Fooooooooooooooo a+ -> Fooooooooooooooo a+ -> Fooooooooooooooo a+ -> Fooooooooooooooo a+```++Implicit parameters++```haskell+f :: (?x :: Int) => Int+```++Quasiquotes in types++```haskell+fun :: [a|bc|]+```++Implicit parameters++```haskell+f :: (?x :: Int) => Int+```++Tuples++```haskell+fun :: (a, b, c) -> (a, b)+```++Infix operator++```haskell+-- https://github.com/mihaimaruseac/hindent/issues/301+(+) :: ()+```++With a record++```haskell+url :: r {url :: String} => r -> Integer+```++`forall` type++```haskell+f :: (forall a. Data a => a -> a) -> (forall a b. Data a => a -> b)+g :: forall a b. a -> b+```+++An infix operator containing `#`++```haskell+(#!) :: Int -> Int -> Int+```++Multiple line function signature inside a `where`++```haskell 4+foo = undefined+ where+ go :: Fooooooooooooooooooooooo+ -> Fooooooooooooooooooooooo+ -> Fooooooooooooooooooooooo+ -> Fooooooooooooooooooooooo+ go = undefined+```++Types with many type applications++```haskell+foo ::+ Foo+ LongLongType+ LongLongType+ LongLongType+ LongLongType+ LongLongType+ LongLongType+ -> Int+```++#### Promoted types++Class constraints should leave `::` on same line++``` haskell+-- see https://github.com/chrisdone/hindent/pull/266#issuecomment-244182805+fun ::+ (Class a, Class b)+ => fooooooooooo bar mu zot+ -> fooooooooooo bar mu zot+ -> c+```++An infix operator containing `#`++```haskell+(#!) :: Int -> Int -> Int+```++Prefix promoted symbol type constructor++```haskell+a :: '(T.:->) 'True 'False+b :: (T.:->) 'True 'False+c :: '(:->) 'True 'False+d :: (:->) 'True 'False+```++##### Promoted lists++Short++```haskell+fun1 :: Def ('[ Ref s (Stored Uint32), IBool] T.:-> IBool)+fun1 = undefined++fun2 :: Def ('[ Ref s (Stored Uint32), IBool] :-> IBool)+fun2 = undefined+```++Long++```haskell+-- https://github.com/mihaimaruseac/hindent/issues/522+type OurContext+ = '[ AuthHandler W.Request (ExtendedPayloadWrapper UserSession)+ , BasicAuthCheck GameInstanceId+ , BasicAuthCheck (RegionId, RegionName)+ , BasicAuthCheck Alert.SourceId+ , M.MultipartOptions M.Tmp+ ]+```++Nested++```haskell+-- https://github.com/mihaimaruseac/hindent/issues/348+a :: A '[ 'True]+-- nested promoted list with multiple elements.+b :: A '[ '[ 'True, 'False], '[ 'False, 'True]]+```++#### Symbol type constructors++Infix++```haskell+f :: a :?: b+```++Prefix++```haskell+f' :: (:?:) a b+```++#### Type signature with class constraints++Single++```haskell+-- https://github.com/mihaimaruseac/hindent/issues/244+x :: Num a => a+x = undefined+```++Multiple++```haskell+fun :: (Class a, Class b) => a -> b -> c+```++Multiple without parentheses++```haskell+-- https://github.com/mihaimaruseac/hindent/issues/554+g :: Semigroup a => Monoid a => Maybe a -> a+```++Long constraints++```haskell+-- https://github.com/mihaimaruseac/hindent/issues/222+foo ::+ ( Foooooooooooooooooooooooooooooooooooooooooo+ , Foooooooooooooooooooooooooooooooooooooooooo+ )+ => A+```++Class constraints should leave `::` on same line++```haskell+-- see https://github.com/mihaimaruseac/hindent/pull/266#issuecomment-244182805+fun ::+ (Class a, Class b)+ => fooooooooooo bar mu zot+ -> fooooooooooo bar mu zot+ -> c+```++Symbol class constructor in class constraint++```haskell+f :: (a :?: b) => (a, b)+f' :: ((:?:) a b) => (a, b)+```++#### Unboxed types++Short unboxed sums++```haskell+{-# LANGUAGE UnboxedSums #-}++f :: (# (# Int, String #) | String #) -> (# Int | String #)+```++Long unboxed sums++```haskell+{-# LANGUAGE UnboxedSums #-}++f' ::+ (# (# Int, String #)+ | Either Bool Int+ | Either Bool Int+ | Either Bool Int+ | Either Bool Int+ | Either Bool Int+ | String #)+ -> (# Int | String #)+```++Large unboxed tuples++```haskell+{-# LANGUAGE UnboxedTuples #-}++f :: (# Looooooooooooooooooooooooooooooooooooooooooooong+ , Looooooooooooooooooooooooooooooooooooooooooooong+ , Looooooooooooooooooooooooooooooooooooooooooooong #)+```++### Type synonym declarations++Short++```haskell+type EventSource a = (AddHandler a, a -> IO ())+```++Long++```haskell+-- https://github.com/mihaimaruseac/hindent/issues/290+type MyContext m+ = ( MonadState Int m+ , MonadReader Int m+ , MonadError Text m+ , MonadMask m+ , Monoid m+ , Functor m)+```++Very higher-kinded type++```haskell+-- https://github.com/mihaimaruseac/hindent/issues/534+type SomeTypeSynonym+ = RecordWithManyFields+ FieldNumber1+ FieldNumber2+ FieldNumber3+ FieldNumber4+ FieldNumber5+ FieldNumber6+ FieldNumber7+ FieldNumber8+ FieldNumber9+ FieldNumber10+ FieldNumber11+ FieldNumber12+ FieldNumber13+ FieldNumber14+ FieldNumber15+```++Infix type constructor++```haskell+-- https://github.com/mihaimaruseac/hindent/issues/417+type API = api1 :<|> api2+```++Type with a string++```haskell+-- https://github.com/mihaimaruseac/hindent/issues/451+type Y = X "abc\n\n\ndef"+```++`TypeOperators`++```haskell+-- https://github.com/mihaimaruseac/hindent/issues/277+{-# LANGUAGE TypeOperators #-}++type m ~> n = ()+```++#### Functional dependencies++Short++```haskell+-- https://github.com/commercialhaskell/hindent/issues/323+class Foo a b | a -> b where+ f :: a -> b+```++Long++```haskell+-- https://github.com/commercialhaskell/hindent/issues/323+class Foo a b c d e f+ | a b c d e -> f+ , a b c d f -> e+ , a b c e f -> d+ , a b d e f -> c+ , a c d e f -> b+ , b c d e f -> a+ where+ foo :: a -> b -> c -> d -> e -> f+```++#### With class constraints++Single++```haskell+-- https://github.com/commercialhaskell/hindent/issues/459+class Class1 a =>+ Class2 a+ where+ f :: a -> Int+```++Multiple++```haskell+-- https://github.com/commercialhaskell/hindent/issues/459+class (Eq a, Show a) =>+ Num a+ where+ (+), (-), (*) :: a -> a -> a+ negate :: a -> a+ abs, signum :: a -> a+ fromInteger :: Integer -> a+```++#### MINIMAL pragmas++Monad example++```haskell+class A where+ {-# MINIMAL return, ((>>=) | (join, fmap)) #-}+```++Very long names #310++```haskell+class A where+ {-# MINIMAL averylongnamewithnoparticularmeaning+ | ananotherverylongnamewithnomoremeaning #-}+```++## Expressions++A minus sign++```haskell+f = -(3 + 5)+```++Lists++```haskell+exceptions = [InvalidStatusCode, MissingContentHeader, InternalServerError]++exceptions =+ [ InvalidStatusCode+ , MissingContentHeader+ , InternalServerError+ , InvalidStatusCode+ , MissingContentHeader+ , InternalServerError+ ]+```++Multi-way if++```haskell+x =+ if | x <- Just x+ , x <- Just x ->+ case x of+ Just x -> e+ Nothing -> p+ | otherwise -> e+```++Type application++```haskell+{-# LANGUAGE TypeApplications #-}++fun @Int 12+```++An expression with a SCC pragma++```haskell+foo = {-# SCC foo #-} undefined+```++A hole++```haskell+foo = 3 + _+```++Implicit value++```haskell+foo = ?undefined+```++`UnboxedSums`++```haskell+{-# LANGUAGE UnboxedSums #-}++f = (# | Bool #)+```++`StaticPointers`++```haskell+{-# LANGUAGE StaticPointers #-}++f = static 1+```++`OverloadedLabels`++```haskell+{-# LANGUAGE OverloadedLabels #-}++f = #foo+```++### Arrows++`-<`++```haskell+{-# LANGUAGE Arrows #-}++f =+ proc foo -> do+ bar -< baz+ aaa >- bbb+```++`-<<`++```haskell+{-# LANGUAGE Arrows #-}++f =+ proc foo -> do+ g bar -<< baz+ aaaaa >>- h bbb+```++`(| ... |)`++```haskell+{-# LANGUAGE Arrows #-}++f = proc g -> (|foo (bar -< g) (baz -< g)|) zz+```++Lambda equation.++```haskell+{-# LANGUAGE Arrows #-}++f = proc g -> \x -> x -< g+```++Case expression.++```haskell+{-# LANGUAGE Arrows #-}++f =+ proc g ->+ case h of+ [] -> i -< ()+ (_:_) -> j -< ()+```++Lambda case++```haskell+{-# LANGUAGE Arrows #-}+{-# LANGUAGE LambdaCase #-}++f =+ proc g ->+ \case+ _ -> h -< ()+```++`if ... then ... else`++```haskell+{-# LANGUAGE Arrows #-}++f =+ proc g ->+ if x+ then h -< g+ else t -< g+```++`let ... in`++```haskell+{-# LANGUAGE Arrows #-}++f =+ proc g ->+ let x = undefined+ y = undefined+ in returnA -< g+```++### Case expressions++Normal case++```haskell+strToMonth :: String -> Int+strToMonth month =+ case month of+ "Jan" -> 1+ "Feb" -> 2+ _ -> error $ "Unknown month " ++ month+```++Inside a `where` and `do`++```haskell+g x =+ case x of+ a -> x+ where+ foo =+ case x of+ _ -> do+ launchMissiles+ where+ y = 2+```++Empty case++```haskell+-- https://github.com/mihaimaruseac/hindent/issues/414+{-# LANGUAGE EmptyCase #-}++f1 = case () of {}+```++Empty lambda case++```haskell+-- https://github.com/mihaimaruseac/hindent/issues/414+{-# LANGUAGE EmptyCase #-}+{-# LANGUAGE LambdaCase #-}++f2 = \case {}+```++A guard in a case++```haskell+f =+ case g of+ []+ | even h -> Nothing+ _ -> undefined+```++cases++```haskell since 9.4.1+foo =+ \cases+ 1 1 -> 1+ _ _ -> 2+```++### `do` expressions++Long function applications++```haskell+test = do+ alphaBetaGamma deltaEpsilonZeta etaThetaIota kappaLambdaMu nuXiOmicron piRh79+ alphaBetaGamma deltaEpsilonZeta etaThetaIota kappaLambdaMu nuXiOmicron piRho80+ alphaBetaGamma+ deltaEpsilonZeta+ etaThetaIota+ kappaLambdaMu+ nuXiOmicron+ piRhoS81+```++Do as a left-hand side of an infix operation++```haskell+-- https://github.com/mihaimaruseac/hindent/issues/238+-- https://github.com/mihaimaruseac/hindent/issues/296+block =+ do ds <- inBraces $ inWhiteSpace declarations+ return $ Block ds+ <?> "block"+```++#### Bindings++Short++```haskell+foo = do+ mcp <- findCabalFiles (takeDirectory abssrcpath) (takeFileName abssrcpath)+ print mcp+```++Large++```haskell+-- https://github.com/mihaimaruseac/hindent/issues/221+x = do+ config <- execParser options+ comments <-+ case config of+ Diff False args -> commentsFromDiff args+ Diff True args -> commentsFromDiff ("--cached" : args)+ Files args -> commentsFromFiles args+ mapM_ (putStrLn . Fixme.formatTodo) (concatMap Fixme.getTodos comments)+```++#### `let` bindings++With type signatures but no class constraints++```haskell+f = do+ let g :: Int+ g = 3+ print g+```++With both type signatures and class constraints++```haskell+f = do+ let try :: Typeable b => b+ try = undefined+ undefined+```++#### `RecursiveDo`++`rec`++```haskell+{-# LANGUAGE RecursiveDo #-}++f = do+ a <- foo+ rec b <- a c+ c <- a b+ return $ b + c+```++`mdo`++```haskell+{-# LANGUAGE RecursiveDo #-}++g = mdo+ foo+ bar+```++### Function applications++Long line, tuple++```haskell+test+ (alphaBetaGamma, deltaEpsilonZeta, etaThetaIota, kappaLambdaMu, nuXiOmicro79)+ (alphaBetaGamma, deltaEpsilonZeta, etaThetaIota, kappaLambdaMu, nuXiOmicron80)+ ( alphaBetaGamma+ , deltaEpsilonZeta+ , etaThetaIota+ , kappaLambdaMu+ , nuXiOmicronP81)+```++Long line, tuple section++```haskell+test+ (, alphaBetaGamma, , deltaEpsilonZeta, , etaThetaIota, kappaLambdaMu, nu79, )+ (, alphaBetaGamma, , deltaEpsilonZeta, , etaThetaIota, kappaLambdaMu, , n80, )+ (+ , alphaBetaGamma+ ,+ , deltaEpsilonZeta+ ,+ , etaThetaIota+ , kappaLambdaMu+ ,+ , nu81+ ,)+```++Linebreaks after very short names if the total line length goes over the limit++```haskell+-- https://github.com/mihaimaruseac/hindent/issues/405+t =+ f "this is a very loooooooooooooooooooooooooooong string that goes over the line length"+ argx+ argy+ argz++t =+ function+ "this is a very loooooooooooooooooooooooooooong string that goes over the line length"+ argx+ argy+ argz+```++### Lambda expressions++Lazy patterns++```haskell+f = \ ~a -> undefined+-- \~a yields parse error on input ‘\~’+```++Bang patterns++```haskell+f = \ !a -> undefined+-- \!a yields parse error on input ‘\!’+```++An infix operator with a lambda expression++```haskell+for xs $ \x -> do+ left x+ right x+```++Nested lambdas++```haskell+foo :: IO ()+foo =+ alloca 10 $ \a ->+ alloca 20 $ \b ->+ cFunction fooo barrr muuu (fooo barrr muuu) (fooo barrr muuu)+```++In a `case`++```haskell+f x =+ case filter (\y -> isHappy y x) of+ [] -> Nothing+ (z:_) -> Just (\a b -> makeSmile z a b)+```++### Let ... in expressions++With bang parameters++```haskell+f =+ let !x = 3+ in x+```++With implicit parameters++```haskell+f =+ let ?x = 42+ in f+```++inside a `do`++```haskell+-- https://github.com/mihaimaruseac/hindent/issues/467+main :: IO ()+main = do+ let x = 5+ in when (x > 0) (return ())+```++### List comprehensions++Short++```haskell+map f xs = [f x | x <- xs]+```++Long++```haskell+defaultExtensions =+ [ e+ | EnableExtension {extensionField1 = extensionField1} <-+ knownExtensions knownExtensions+ , let a = b+ -- comment+ , let c = d+ -- comment+ ]+```++Another long one++```haskell+-- https://github.com/mihaimaruseac/hindent/issues/357+foo =+ [ (x, y)+ | x <- [1 .. 10]+ , y <- [11 .. 20]+ , even x+ , even x+ , even x+ , even x+ , even x+ , odd y+ ]+```++With operators++```haskell+defaultExtensions =+ [e | e@EnableExtension {} <- knownExtensions] \\+ map EnableExtension badExtensions+```++Transform list comprehensions++```haskell+list =+ [ (x, y, map the v)+ | x <- [1 .. 10]+ , y <- [1 .. 10]+ , let v = x + y+ , then group by v using groupWith+ , then take 10+ , then group using permutations+ , t <- concat v+ , then takeWhile by t < 3+ ]+```++#### Parallel list comprehensions++Short++```haskell+zip xs ys = [(x, y) | x <- xs | y <- ys]+```++Long++```haskell+fun xs ys =+ [ (alphaBetaGamma, deltaEpsilonZeta)+ | x <- xs+ , z <- zs+ | y <- ys+ , cond+ , let t = t+ ]+```++### Operators++Bad++```haskell+x =+ Value <$> thing <*> secondThing <*> thirdThing <*> fourthThing <*>+ Just thisissolong <*>+ Just stilllonger <*>+ evenlonger+```++Good++```haskell pending+x =+ Value <$> thing <*> secondThing <*> thirdThing <*> fourthThing <*>+ Just thisissolong <*> Just stilllonger <*> evenlonger+```++With `do`++```haskell+for xs $ do+ left x+ right x+```++With lambda-case++```haskell+for xs $ \case+ Left x -> x+```++`$` chain++```haskell+f =+ Right $+ S.lazyByteStrings $ addPrefix prefix $ S.toLazyByteString $ prettyPrint m+```++Qualified operator as an argument++```haskell+-- https://github.com/mihaimaruseac/hindent/issues/273+foo = foldr1 (V.++) [V.empty, V.empty]+```++Apply an infix operator in prefix style++```haskell+-- https://github.com/mihaimaruseac/hindent/issues/273+ys = (++) [] []+```++Qualified operator++```haskell+-- https://github.com/mihaimaruseac/hindent/issues/273+xs = V.empty V.++ V.empty+```++In parentheses++```haskell+cat = (++)+```++Qualified operator in parentheses++```haskell+-- https://github.com/mihaimaruseac/hindent/issues/273+cons = (V.++)+```++A list constructor enclosed by parentheses++```haskell+cons = (:)+```++A data constructor enclosed by parentheses++```haskell+-- https://github.com/mihaimaruseac/hindent/issues/422+data T a =+ a :@ a++test = (:@)+```++Force indent and print RHS in a top-level expression++```haskell+-- https://github.com/mihaimaruseac/hindent/issues/473+template $+ haskell+ [ SomeVeryLongName+ , AnotherLongNameEvenLongToBreakTheLine+ , LastLongNameInList+ ]+```++### Primitive type values++`Char`++```haskell+a = 'a'+```++`\n` as a `Char`++```haskell+a = '\n'+```++`String` with a `\n`++```haskell+a = "bcd\nefgh"+```++Multiple line string++```haskell+foo =+ "hoge \+ \ fuga"+ where+ bar =+ "foo \+ \ bar"+```++Hex integers++```haskell+a = 0xa5+```++Unboxed integers++```haskell+a = 0#+```++Unboxed floating point numbers++```haskell+a = 3.3#+```++Unboxed `Char`++```haskell+a = 'c'#+```++Unboxed `String`++```haskell+a = "Foo"#+```++`NumericUnderscores`++```haskell+-- https://github.com/mihaimaruseac/hindent/issues/542+{-# LANGUAGE NumericUnderscores #-}++foo = 10_000+```++### Quasi-quotes++Body has multiple lines.++```haskell+{-# LANGUAGE QuasiQuotes #-}++f =+ [s|First line+Second line|]+```++Body has a top-level declaration.++```haskell+{-# LANGUAGE QuasiQuotes #-}++f =+ [d| f :: Int -> Int+ f = undefined |]+```++Typed quote.++```haskell+f = [||a||]+```++Preserve the trailing newline.++```haskell+{-# LANGUAGE QuasiQuotes #-}++f =+ [s|foo+|]+```+### Ranges++from++```haskell+a = [1 ..]+```++from to++```haskell+a = [1 .. 9]+```++from then++```haskell+b = [1,3 ..]+```++from then to++```haskell+c = [1,3 .. 9]+```++### Records++No fields++```haskell+-- https://github.com/mihaimaruseac/hindent/issues/366+foo = Nothing {}+```++Short++```haskell+getGitProvider :: EventProvider GitRecord ()+getGitProvider =+ EventProvider {getModuleName = "Git", getEvents = getRepoCommits}+```++Medium++```haskell+commitToEvent :: FolderPath -> TimeZone -> Commit -> Event.Event+commitToEvent gitFolderPath timezone commit =+ Event.Event+ {pluginName = getModuleName getGitProvider, eventIcon = "glyphicon-cog"}+```++Long++```haskell+commitToEvent :: FolderPath -> TimeZone -> Commit -> Event.Event+commitToEvent gitFolderPath timezone commit =+ Event.Event+ { pluginName = getModuleName getGitProvider+ , eventIcon = "glyphicon-cog"+ , eventDate = localTimeToUTC timezone (commitDate commit)+ }+```++Another long one++```haskell+-- https://github.com/mihaimaruseac/hindent/issues/358+foo =+ assert+ sanityCheck+ BomSnapshotAggr+ { snapshot = Just bs+ , previousId = M.bomSnapshotHistoryPreviousId . entityVal <$> bsp+ , nextId = M.bomSnapshotHistoryNextId . entityVal <$> bsn+ , bomEx = bx''+ , orderSubstitutes =+ S.fromList . map OrderSubstituteAggrByCreatedAtAsc $ subs+ , snapshotSubstitute = msub+ }+```++Record body may be in one line even if a new line is inserted after the variable name.++```haskell+addCommentsToNode mkNodeComment newComments nodeInfo@(NodeInfo (SrcSpanInfo _ _) existingComments) =+ nodeInfo+ {nodeInfoComments = existingComments <> map mkBeforeNodeComment newComments}+```++Symbol constructor++```haskell+f = (:..?) {}+```++Symbol field++```haskell+f x = x {(..?) = wat}++g x = Rec {(..?)}+```++A field updater in a `do` inside a `let ... in`.++```haskell+f = undefined+ where+ g h =+ let x = undefined+ in do foo+ pure+ h+ { grhssLocalBinds =+ HsValBinds x (ValBinds (newSigs newSigMethods))+ }+```++`OverloadedRecordDot`++```haskell since 9.2.2+{-# LANGUAGE OverloadedRecordDot #-}++data Rectangle = Rectangle+ { width :: Int+ , height :: Int+ }++area :: Rectangle -> Int+area r = r.width * r.height++foo = (.x.y)+```++`OverloadedRecordUpdate`++```haskell since 9.2.0+{-# LANGUAGE OverloadedRecordDot #-}+{-# LANGUAGE OverloadedRecordUpdate #-}++foo = bar {baz.qux = 1}+```++### Sections++With a LHS++```haskell+double = (2 *)+```++With a RHS++```haskell+halve = (/ 2)+```++With a large RHS++```haskell+foo =+ (`elem` concat+ [ [20, 68, 92, 112, 28, 124, 116, 80]+ , [21, 84, 87, 221, 127, 255, 241, 17]+ ])+```++## Template Haskell++Expression brackets++```haskell+add1 x = [|x + 1|]+```++Pattern brackets++```haskell+mkPat = [p|(x, y)|]+```++Type brackets++```haskell+foo :: $([t|Bool|]) -> a+```++A quoted TH name from a type name++```haskell+-- https://github.com/mihaimaruseac/hindent/issues/412+data (-)++q = ''(-)+```++Quoted list constructors++```haskell+cons = '(:)+```++Pattern splices++```haskell+f $pat = ()++g =+ case x of+ $(mkPat y z) -> True+ _ -> False+```++Typed splice++```haskell+foo = $$bar+```++## Comments++Only comments++```haskell+-- foo+```++Double comments in a line++```haskell+f = undefined {- Comment 1 -} {- Comment 2 -} -- Comment 3+```++Comments within a declaration++```haskell+bob -- after bob+ =+ foo -- next to foo+ -- line after foo+ (bar+ foo -- next to bar foo+ bar -- next to bar+ ) -- next to the end paren of (bar)+ -- line after (bar)+ mu -- next to mu+ -- line after mu+ -- another line after mu+ zot -- next to zot+ -- line after zot+ (case casey -- after casey+ of+ Just -- after Just+ -> do+ justice -- after justice+ *+ foo+ (blah * blah + z + 2 / 4 + a - -- before a line break+ 2 * -- inside this mess+ z /+ 2 /+ 2 /+ aooooo /+ aaaaa -- bob comment+ ) ++ (sdfsdfsd fsdfsdf) -- blah comment+ putStrLn "")+ [1, 2, 3]+ [ 1 -- foo+ , ( 2 -- bar+ , 2.5 -- mu+ )+ , 3+ ]+ -- in the end of the function+ where+ alpha = alpha+ -- between alpha and beta+ beta = beta+ -- after beta++foo = 1 -- after foo++gamma = do+ delta+ epsilon+ -- in the end of a do-block 1++gamma = do+ delta+ epsilon+ -- the very last block is detected differently+```++Doesn't work yet (wrong comment position detection)++```haskell pending+gamma = do+ -- in the beginning of a do-block+ delta+ where+ -- before alpha+ alpha = alpha+```++Comments in a class declaration++```haskell+class Foo a+ -- A comment+ where+ foo :: a -> Int+```++Comments in a class instance++```haskell+instance Pretty MatchForCase+ -- TODO: Do not forget to handle comments!+ where+ pretty' = undefined+```++Haddock comments++```haskell+-- | Module comment.+module X where++-- | Main doc.+main :: IO ()+main = return ()++data X+ = X -- ^ X is for xylophone.+ | Y -- ^ Y is for why did I eat that pizza.++data X = X+ { field1 :: Int -- ^ Field1 is the first field.+ , field11 :: Char+ -- ^ This field comment is on its own line.+ , field2 :: Int -- ^ Field2 is the second field.+ , field3 :: Char -- ^ This is a long comment which starts next to+ -- the field but continues onto the next line, it aligns exactly+ -- with the field name.+ , field4 :: Char+ -- ^ This is a long comment which starts on the following line+ -- from from the field, lines continue at the sme column.+ }++foo ::+ String -- ^ Reason for eating pizza.+ -> Int -- ^ How many did you eat pizza?+ -> String -- ^ The report.+foo = undefined+```++Module header with haddock comments++```haskell+-- | A module+module HIndent -- Foo+ ( -- * Formatting functions.+ reformat+ , -- * Testing+ test+ ) where+```++Comments around regular declarations++```haskell+-- This is some random comment.+-- | Main entry point.+main = putStrLn "Hello, World!"+-- This is another random comment.+```++Multi-line comments++```haskell+bob {- after bob -}+ =+ foo {- next to foo -}+ {- line after foo -}+ (bar+ foo {- next to bar foo -}+ bar {- next to bar -}+ ) {- next to the end paren of (bar) -}+ {- line after (bar) -}+ mu {- next to mu -}+ {- line after mu -}+ {- another line after mu -}+ zot {- next to zot -}+ {- line after zot -}+ (case casey {- after casey -}+ of+ Just {- after Just -}+ -> do+ justice {- after justice -}+ *+ foo+ (blah * blah + z + 2 / 4 + a - {- before a line break -}+ 2 * {- inside this mess -}+ z /+ 2 /+ 2 /+ aooooo /+ aaaaa {- bob comment -}+ ) ++ (sdfsdfsd fsdfsdf) {- blah comment -}+ putStrLn "")+ [1, 2, 3]+ [ 1 {- foo -}+ , ( 2 {- bar -}+ , 2.5 {- mu -}+ )+ , 3+ ]++foo = 1 {- after foo -}+```++Multi-line comments with multi-line contents++```haskell+{- | This is some random comment.+Here is more docs and such.+Etc.+-}+main = putStrLn "Hello, World!"+{- This is another random comment. -}+```++Comments on functions in where clause++```haskell+-- https://github.com/mihaimaruseac/hindent/issues/540+topLevelFunc1 = f+ where+ -- comment on func in where clause+ -- stays in the where clause+ f = undefined++topLevelFunc2 = f . g+ -- Another comment+ where+ {- multi+ line+ comment -}+ f = undefined -- single line comment+ -- single line comment+ -- Different size of indent+ g :: a+ g = undefined+```++Comments in a 'where' clause++```haskell+foo = undefined+ where+ bar+ -- A comment+ = undefined+ where+ a = b+ baz = undefined+```++Haddocks around data constructors++```haskell+data Foo+ -- | A haddock comment for 'Bar'.+ = Bar+ -- | A haddock comment for 'Baz'.+ | Baz+ -- | A haddock comment for 'Quuz'.+ | Quuz+```++## Identifiers++Unicode++```haskell+α = γ * "ω"+-- υ+```++`rec` and `mdo` are valid identifiers unless `RecursiveDo` is enabled++```haskell+-- https://github.com/mihaimaruseac/hindent/issues/328+rec = undefined++mdo = undefined+```++The first character of an infix operator can be `@` unless `TypeApplications` is enabled.++```haskell+-- https://github.com/mihaimaruseac/hindent/issues/421+a @: b = a + b++main = print (2 @: 2)+```++## Complex input++A complex, slow-to-print decl++```haskell+quasiQuotes =+ [ ( ''[]+ , \(typeVariable:_) _automaticPrinter ->+ (let presentVar = varE (presentVarName typeVariable)+ in lamE+ [varP (presentVarName typeVariable)]+ [|(let typeString = "[" ++ fst $(presentVar) ++ "]"+ in ( typeString+ , \xs ->+ case fst $(presentVar) of+ "GHC.Types.Char" ->+ ChoicePresentation+ "String"+ [ ( "String"+ , StringPresentation+ "String"+ (concatMap+ getCh+ (map (snd $(presentVar)) xs)))+ , ( "List of characters"+ , ListPresentation+ typeString+ (map (snd $(presentVar)) xs))+ ]+ where getCh (CharPresentation "GHC.Types.Char" ch) =+ ch+ getCh (ChoicePresentation _ ((_, CharPresentation _ ch):_)) =+ ch+ getCh _ = ""+ _ ->+ ListPresentation+ typeString+ (map (snd $(presentVar)) xs)))|]))+ ]+```++Random snippet from hindent itself++```haskell+exp' (App _ op a) = do+ (fits, st) <- fitsOnOneLine (spaced (map pretty (f : args)))+ if fits+ then put st+ else do+ pretty f+ newline+ spaces <- getIndentSpaces+ indented spaces (lined (map pretty args))+ where+ (f, args) = flatten op [a]+ flatten :: Exp NodeInfo -> [Exp NodeInfo] -> (Exp NodeInfo, [Exp NodeInfo])+ flatten (App _ f' a') b = flatten f' (a' : b)+ flatten f' as = (f', as)+```++Quasi quotes++```haskell+exp = [name|exp|]++f [qq|pattern|] = ()+```++## C preprocessor++Conditionals (`#if`)++```haskell+isDebug :: Bool+#if DEBUG+isDebug = True+#else+isDebug = False+#endif+```++Macro definitions (`#define`)++```haskell+#define STRINGIFY(x) #x+f = STRINGIFY (y)+```++Escaped newlines++```haskell+#define LONG_MACRO_DEFINITION \+ data Pair a b = Pair \+ { first :: a \+ , second :: b \+ }+#define SHORT_MACRO_DEFINITION \+ x ```
+ app/Main.hs view
@@ -0,0 +1,150 @@+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE Unsafe #-}++-- | Main entry point to hindent.+--+-- hindent+module Main+ ( main+ ) where++import Control.Applicative+import Control.Exception+import Control.Monad+import qualified Data.ByteString as S+import qualified Data.ByteString.Builder as S+import qualified Data.ByteString.Lazy.Char8 as L8+import Data.Maybe+import qualified Data.Text as T+import Data.Version (showVersion)+import Foreign.C.Error+import GHC.IO.Exception+import HIndent+import HIndent.CabalFile+import HIndent.Config+import HIndent.LanguageExtension+import HIndent.LanguageExtension.Types+import Options.Applicative hiding (action, style)+import Paths_hindent (version)+import qualified System.Directory as IO+import System.Exit (exitWith)+import qualified System.IO as IO++data Action+ = Validate+ | Reformat++data RunMode+ = ShowVersion+ | Run Config [Extension] Action [FilePath]++-- | Main entry point.+main :: IO ()+main = do+ config <- getConfig+ runMode <-+ execParser+ (info+ (options config <**> helper)+ (header "hindent - Reformat Haskell source code"))+ case runMode of+ ShowVersion -> putStrLn ("hindent " ++ showVersion version)+ Run style exts action paths ->+ if null paths+ then L8.interact+ (either error S.toLazyByteString .+ reformat style (Just exts) Nothing . L8.toStrict)+ else forM_ paths $ \filepath -> do+ cabalexts <- getCabalExtensionsForSourcePath filepath+ text <- S.readFile filepath+ case reformat+ style+ (Just $ cabalexts ++ exts)+ (Just filepath)+ text of+ Left e -> error e+ Right out ->+ unless (L8.fromStrict text == S.toLazyByteString out) $+ case action of+ Validate -> do+ IO.putStrLn $ filepath ++ " is not formatted"+ exitWith (ExitFailure 1)+ Reformat -> do+ tmpDir <- IO.getTemporaryDirectory+ (fp, h) <- IO.openTempFile tmpDir "hindent.hs"+ L8.hPutStr h (S.toLazyByteString out)+ IO.hFlush h+ IO.hClose h+ let exdev e =+ if ioe_errno e == Just ((\(Errno a) -> a) eXDEV)+ then IO.copyFile fp filepath >> IO.removeFile fp+ else throw e+ IO.copyPermissions filepath fp+ IO.renameFile fp filepath `catch` exdev++-- | Program options.+options :: Config -> Parser RunMode+options config =+ flag' ShowVersion (long "version" <> help "Print the version") <|>+ (Run <$> style <*> exts <*> action <*> files)+ where+ style =+ (makeStyle config <$> lineLen <*> indentSpaces <*> trailingNewline <*>+ sortImports) <*+ optional+ (strOption+ (long "style" <>+ help "Style to print with (historical, now ignored)" <>+ metavar "STYLE") :: Parser String)+ exts =+ fmap+ getExtensions+ (many+ (T.pack <$>+ strOption+ (short 'X' <> help "Language extension" <> metavar "GHCEXT")))+ indentSpaces =+ option+ auto+ (long "indent-size" <>+ help "Indentation size in spaces" <>+ value (configIndentSpaces config) <> showDefault) <|>+ option+ auto+ (long "tab-size" <> help "Same as --indent-size, for compatibility")+ lineLen =+ option+ auto+ (long "line-length" <>+ help "Desired length of lines" <>+ value (configMaxColumns config) <> showDefault)+ trailingNewline =+ not <$>+ flag+ (not (configTrailingNewline config))+ (configTrailingNewline config)+ (long "no-force-newline" <>+ help "Don't force a trailing newline" <> showDefault)+ sortImports =+ flag+ Nothing+ (Just True)+ (long "sort-imports" <> help "Sort imports in groups" <> showDefault) <|>+ flag+ Nothing+ (Just False)+ (long "no-sort-imports" <> help "Don't sort imports")+ action =+ flag+ Reformat+ Validate+ (long "validate" <>+ help "Check if files are formatted without changing them")+ makeStyle s mlen tabs trailing imports =+ s+ { configMaxColumns = mlen+ , configIndentSpaces = tabs+ , configTrailingNewline = trailing+ , configSortImports = fromMaybe (configSortImports s) imports+ }+ files = many (strArgument (metavar "FILENAMES"))
+ benchmarks/Main.hs view
@@ -0,0 +1,47 @@+{-# LANGUAGE BangPatterns #-}+{-# LANGUAGE OverloadedStrings #-}++-- | Benchmark the pretty printer.+module Main where++import Control.DeepSeq+import Criterion+import Criterion.Main+import qualified Data.ByteString as S+import qualified Data.ByteString.Builder as S+import qualified Data.ByteString.Char8 as S8+import qualified Data.ByteString.UTF8 as UTF8+import HIndent+import HIndent.Config+import HIndent.Internal.Test.Markdone+import HIndent.LanguageExtension++-- | Main benchmarks.+main :: IO ()+main = do+ bytes <- S.readFile "BENCHMARKS.md"+ !forest <- fmap force (parse (tokenize bytes))+ defaultMain (toCriterion forest)++-- | Convert the Markdone document to Criterion benchmarks.+toCriterion :: [Markdone] -> [Benchmark]+toCriterion = go+ where+ go (Section name children:next) =+ bgroup (S8.unpack name) (go children) : go next+ go (PlainText desc:CodeFence lang code:next) =+ if lang == "haskell"+ then (bench+ (UTF8.toString desc)+ (nf+ (either error S.toLazyByteString .+ reformat+ HIndent.Config.defaultConfig+ (Just defaultExtensions)+ Nothing)+ code)) :+ go next+ else go next+ go (PlainText {}:next) = go next+ go (CodeFence {}:next) = go next+ go [] = []
hindent.cabal view
@@ -1,113 +1,260 @@-name: hindent-version: 5.3.4-synopsis: Extensible Haskell pretty printer-description: Extensible Haskell pretty printer. Both a library and an executable.- .- See the Github page for usage\/explanation: <https://github.com/mihaimaruseac/hindent>-license: BSD3-stability: Unstable-license-file: LICENSE.md-author: Mihai Maruseac, Chris Done, Andrew Gibiansky, Tobias Pflug, Pierre Radermecker-maintainer: Mihai Maruseac-copyright: 2014 Chris Done, 2015 Andrew Gibiansky, 2021 Mihai Maruseac-category: Development-build-type: Simple-cabal-version: >=1.10-homepage: https://github.com/mihaimaruseac/hindent-bug-reports: https://github.com/mihaimaruseac/hindent/issues-data-files: elisp/hindent.el+cabal-version: 2.0++-- This file has been generated from package.yaml by hpack version 0.34.4.+--+-- see: https://github.com/sol/hpack++name: hindent+version: 6.0.0+synopsis: Extensible Haskell pretty printer+description: Extensible Haskell pretty printer. Both a library and an executable. See the GitHub page for usage/explanation: <https://github.com/mihaimaruseac/hindent>+category: Development+stability: Unstable+homepage: https://github.com/mihaimaruseac/hindent+bug-reports: https://github.com/mihaimaruseac/hindent/issues+author: Mihai Maruseac, Chris Done, Andrew Gibiansky, Tobias Pflug, Pierre Radermecker+maintainer: Mihai Maruseac+copyright: 2014 Chris Done, 2015 Andrew Gibiansky, 2021 Mihai Maruseac+license: BSD3+license-file: LICENSE.md+build-type: Simple extra-source-files:- README.md- CHANGELOG.md- BENCHMARKS.md- TESTS.md+ README.md+ CHANGELOG.md+ BENCHMARKS.md+ TESTS.md+data-files:+ elisp/hindent.el source-repository head- type: git- location: https://github.com/mihaimaruseac/hindent+ type: git+ location: https://github.com/mihaimaruseac/hindent library- hs-source-dirs: src/- ghc-options: -Wall -O2- default-language: Haskell2010- exposed-modules: HIndent- HIndent.Types- HIndent.Pretty- HIndent.CabalFile- HIndent.CodeBlock- build-depends: base >= 4.7 && <5- , containers- , Cabal- , filepath- , directory- , haskell-src-exts >= 1.20- , monad-loops- , mtl- , bytestring- , utf8-string- , transformers- , exceptions- , text- , yaml+ exposed-modules:+ HIndent+ HIndent.Applicative+ HIndent.CabalFile+ HIndent.CodeBlock+ HIndent.Config+ HIndent.Language+ HIndent.LanguageExtension+ HIndent.LanguageExtension.Conversion+ HIndent.LanguageExtension.Types+ HIndent.ModulePreprocessing+ HIndent.ModulePreprocessing.CommentRelocation+ HIndent.Parse+ HIndent.Path.Find+ HIndent.Pragma+ HIndent.Pretty+ HIndent.Pretty.Combinators+ HIndent.Pretty.Combinators.Comment+ HIndent.Pretty.Combinators.Getter+ HIndent.Pretty.Combinators.Indent+ HIndent.Pretty.Combinators.Lineup+ HIndent.Pretty.Combinators.Op+ HIndent.Pretty.Combinators.Outputable+ HIndent.Pretty.Combinators.RhsSeparator+ HIndent.Pretty.Combinators.String+ HIndent.Pretty.Combinators.Switch+ HIndent.Pretty.Combinators.Wrap+ HIndent.Pretty.Import+ HIndent.Pretty.Import.Sort+ HIndent.Pretty.NodeComments+ HIndent.Pretty.Pragma+ HIndent.Pretty.SigBindFamily+ HIndent.Pretty.Types+ HIndent.Printer+ other-modules:+ Paths_hindent+ hs-source-dirs:+ src+ ghc-options: -Wall -O2+ build-depends:+ Cabal+ , base >=4.7 && <5+ , bytestring+ , containers+ , directory+ , exceptions+ , filepath+ , ghc-lib-parser-ex+ , monad-loops+ , mtl+ , path+ , path-io+ , regex-tdfa+ , split+ , syb+ , text+ , transformers+ , unicode-show+ , utf8-string+ , yaml+ if impl(ghc >= 9.4.1)+ build-depends:+ ghc-lib-parser >=9.4.1.20220807 && <9.5+ else+ build-depends:+ ghc-lib-parser >=9.2.3.20220527 && <9.3+ default-language: Haskell2010 +library hindent-internal+ exposed-modules:+ HIndent.Internal.Test.Markdone+ other-modules:+ Paths_hindent+ hs-source-dirs:+ internal+ ghc-options: -Wall -O2+ build-depends:+ Cabal+ , base >=4.7 && <5+ , bytestring+ , containers+ , deepseq+ , directory+ , exceptions+ , filepath+ , ghc-lib-parser-ex+ , monad-loops+ , mtl+ , path+ , path-io+ , regex-tdfa+ , split+ , syb+ , text+ , transformers+ , unicode-show+ , utf8-string+ , yaml+ if impl(ghc >= 9.4.1)+ build-depends:+ ghc-lib-parser >=9.4.1.20220807 && <9.5+ else+ build-depends:+ ghc-lib-parser >=9.2.3.20220527 && <9.3+ default-language: Haskell2010+ executable hindent- hs-source-dirs: src/main- ghc-options: -Wall -O2- default-language: Haskell2010- main-is: Main.hs- other-modules: Path.Find- build-depends: base >= 4 && < 5- , hindent- , bytestring- , utf8-string- , haskell-src-exts- , ghc-prim- , directory- , text- , yaml- , unix-compat- , deepseq- , path- , path-io- , transformers- , exceptions- , optparse-applicative+ main-is: Main.hs+ other-modules:+ Paths_hindent+ autogen-modules:+ Paths_hindent+ hs-source-dirs:+ app+ ghc-options: -Wall -O2+ build-depends:+ Cabal+ , base >=4.7 && <5+ , bytestring+ , containers+ , directory+ , exceptions+ , filepath+ , ghc-lib-parser-ex+ , hindent+ , monad-loops+ , mtl+ , optparse-applicative+ , path+ , path-io+ , regex-tdfa+ , split+ , syb+ , text+ , transformers+ , unicode-show+ , utf8-string+ , yaml+ if impl(ghc >= 9.4.1)+ build-depends:+ ghc-lib-parser >=9.4.1.20220807 && <9.5+ else+ build-depends:+ ghc-lib-parser >=9.2.3.20220527 && <9.3+ default-language: Haskell2010 test-suite hindent-test type: exitcode-stdio-1.0- hs-source-dirs: src/main/- default-language: Haskell2010- main-is: Test.hs- other-modules: Markdone- build-depends: base >= 4 && <5- , hindent- , haskell-src-exts- , monad-loops- , mtl- , bytestring- , utf8-string- , hspec- , directory- , deepseq- , exceptions- , utf8-string- , Diff+ main-is: Main.hs+ other-modules:+ Paths_hindent+ hs-source-dirs:+ tests+ ghc-options: -Wall -O2+ build-depends:+ Cabal+ , Diff+ , base >=4.7 && <5+ , bytestring+ , containers+ , directory+ , exceptions+ , filepath+ , ghc-lib-parser-ex+ , hindent+ , hindent-internal+ , hspec+ , monad-loops+ , mtl+ , path+ , path-io+ , regex-tdfa+ , split+ , syb+ , text+ , transformers+ , unicode-show+ , utf8-string+ , yaml+ if impl(ghc >= 9.4.1)+ build-depends:+ ghc-lib-parser >=9.4.1.20220807 && <9.5+ else+ build-depends:+ ghc-lib-parser >=9.2.3.20220527 && <9.3+ default-language: Haskell2010 benchmark hindent-bench type: exitcode-stdio-1.0- hs-source-dirs: src/main- default-language: Haskell2010- ghc-options: -Wall -O2 -rtsopts- main-is: Benchmark.hs- other-modules: Markdone- build-depends: base >= 4 && < 5- , hindent- , bytestring- , utf8-string- , haskell-src-exts- , ghc-prim- , directory- , criterion- , deepseq- , exceptions- , mtl+ main-is: Main.hs+ other-modules:+ Paths_hindent+ hs-source-dirs:+ benchmarks+ ghc-options: -Wall -O2+ build-depends:+ Cabal+ , base >=4.7 && <5+ , bytestring+ , containers+ , criterion+ , deepseq+ , directory+ , exceptions+ , filepath+ , ghc-lib-parser-ex+ , hindent+ , hindent-internal+ , monad-loops+ , mtl+ , path+ , path-io+ , regex-tdfa+ , split+ , syb+ , text+ , transformers+ , unicode-show+ , utf8-string+ , yaml+ if impl(ghc >= 9.4.1)+ build-depends:+ ghc-lib-parser >=9.4.1.20220807 && <9.5+ else+ build-depends:+ ghc-lib-parser >=9.2.3.20220527 && <9.3+ default-language: Haskell2010
+ internal/HIndent/Internal/Test/Markdone.hs view
@@ -0,0 +1,133 @@+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DeriveGeneric #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedStrings #-}++-- | A subset of markdown that only supports @#headings@ and code+-- fences.+--+-- All content must be in section headings with proper hierarchy,+-- anything else is rejected.+module HIndent.Internal.Test.Markdone+ ( Token(..)+ , Markdone(..)+ , tokenize+ , parse+ ) where++import Control.DeepSeq+import Control.Monad.Catch+import Control.Monad.State.Strict (State, evalState, get, put)+import Data.ByteString (ByteString)+import qualified Data.ByteString.Char8 as S8+import Data.Char+import Data.Typeable+import GHC.Generics++-- | A markdone token.+data Token+ = Heading !Int !ByteString+ | PlainLine !ByteString+ | BeginFence !ByteString+ | EndFence+ deriving (Eq, Show)++-- | A markdone document.+data Markdone+ = Section !ByteString ![Markdone]+ | CodeFence !ByteString !ByteString+ | PlainText !ByteString+ deriving (Eq, Show, Generic)++instance NFData Markdone++-- | Parse error.+data MarkdownError+ = NoFenceEnd+ | ExpectedSection+ deriving (Typeable, Show)++instance Exception MarkdownError++data TokenizerMode+ = Normal+ | Fenced++-- | Tokenize the bytestring.+tokenize :: ByteString -> [Token]+tokenize input =+ evalState (mapM token (S8.filter (/= '\r') <$> S8.lines input)) Normal+ where+ token :: ByteString -> State TokenizerMode Token+ token line = do+ mode <- get+ case mode of+ Normal ->+ if S8.isPrefixOf "#" line+ then let (hashes, title) = S8.span (== '#') line+ in return $+ Heading (S8.length hashes) (S8.dropWhile isSpace title)+ else if S8.isPrefixOf "```" line+ then do+ put Fenced+ return $+ BeginFence+ (S8.dropWhile (\c -> c == '`' || c == ' ') line)+ else return $ PlainLine line+ Fenced ->+ if line == "```"+ then do+ put Normal+ return EndFence+ else return $ PlainLine line++-- | Parse into a forest.+parse :: (Functor m, MonadThrow m) => [Token] -> m [Markdone]+parse = go (0 :: Int)+ where+ go level =+ \case+ (Heading n label:rest) ->+ let (children, rest') =+ span+ (\case+ Heading nextN _ -> nextN > n+ _ -> True)+ rest+ in do childs <- go (level + 1) children+ siblings <- go level rest'+ return (Section label childs : siblings)+ (BeginFence label:rest)+ | level > 0 ->+ let (content, rest') =+ span+ (\case+ PlainLine {} -> True+ _ -> False)+ rest+ in case rest' of+ (EndFence:rest'') ->+ fmap+ (CodeFence+ label+ (S8.intercalate "\n" (map getPlain content)) :)+ (go level rest'')+ _ -> throwM NoFenceEnd+ PlainLine p:rest+ | level > 0 ->+ let (content, rest') =+ span+ (\case+ PlainLine {} -> True+ _ -> False)+ (PlainLine p : rest)+ in fmap+ (PlainText+ (S8.intercalate+ "\n"+ (filter (not . S8.null) (map getPlain content))) :)+ (go level rest')+ [] -> return []+ _ -> throwM ExpectedSection+ getPlain (PlainLine x) = x+ getPlain _ = ""
src/HIndent.hs view
@@ -1,29 +1,22 @@-{-# OPTIONS_GHC -fno-warn-name-shadowing #-}+{-# LANGUAGE CPP #-}+{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RankNTypes #-}-{-# LANGUAGE OverloadedStrings, ScopedTypeVariables, PatternGuards #-}+{-# LANGUAGE ScopedTypeVariables #-} -- | Haskell indenter.- module HIndent- (-- * Formatting functions.- reformat- ,prettyPrint- ,parseMode- -- * Testing- ,test- ,testFile- ,testAst- ,testFileAst- ,defaultExtensions- ,getExtensions- )- where+ ( -- * Formatting functions.+ reformat+ , prettyPrint+ , -- * Testing+ testAst+ ) where -import Control.Monad.State.Strict-import Control.Monad.Trans.Maybe-import Data.ByteString (ByteString)+import Control.Monad.State.Strict+import Control.Monad.Trans.Maybe+import Data.ByteString (ByteString) import qualified Data.ByteString as S-import Data.ByteString.Builder (Builder)+import Data.ByteString.Builder (Builder) import qualified Data.ByteString.Builder as S import qualified Data.ByteString.Char8 as S8 import qualified Data.ByteString.Internal as S@@ -31,135 +24,128 @@ import qualified Data.ByteString.Lazy.Char8 as L8 import qualified Data.ByteString.UTF8 as UTF8 import qualified Data.ByteString.Unsafe as S-import Data.Char-import Data.Foldable (foldr')-import Data.Either-import Data.Function-import Data.Functor.Identity-import Data.List-import Data.Maybe-import Data.Monoid-import Data.Text (Text)-import qualified Data.Text as T-import Data.Traversable hiding (mapM)-import HIndent.CodeBlock-import HIndent.Pretty-import HIndent.Types-import qualified Language.Haskell.Exts as Exts-import Language.Haskell.Exts hiding (Style, prettyPrint, Pretty, style, parse)-import Prelude+import Data.Char+import Data.Either+import Data.Function+import Data.Functor.Identity+import Data.List hiding (stripPrefix)+import Data.Maybe+import Data.Monoid+import GHC.Hs+import GHC.Parser.Lexer hiding (buffer)+import GHC.Types.SrcLoc+import HIndent.CodeBlock+import HIndent.Config+import HIndent.LanguageExtension+import qualified HIndent.LanguageExtension.Conversion as CE+import HIndent.LanguageExtension.Types+import HIndent.ModulePreprocessing+import HIndent.Parse+import HIndent.Pretty+import HIndent.Printer+import Prelude -- | Format the given source.-reformat :: Config -> Maybe [Extension] -> Maybe FilePath -> ByteString -> Either String Builder+reformat ::+ Config+ -> Maybe [Extension]+ -> Maybe FilePath+ -> ByteString+ -> Either String Builder reformat config mexts mfilepath =- preserveTrailingNewline- (fmap (mconcat . intersperse "\n") . mapM processBlock . cppSplitBlocks)+ preserveTrailingNewline+ (fmap (mconcat . intersperse "\n") . mapM processBlock . cppSplitBlocks) where processBlock :: CodeBlock -> Either String Builder processBlock (Shebang text) = Right $ S.byteString text processBlock (CPPDirectives text) = Right $ S.byteString text- processBlock (HaskellSource line text) =- let ls = S8.lines text- prefix = findPrefix ls- code = unlines' (map (stripPrefix prefix) ls)- exts = readExtensions (UTF8.toString code)- mode'' = case exts of- Nothing -> mode'- Just (Nothing, exts') ->- mode' { extensions =- exts'- ++ configExtensions config- ++ extensions mode' }- Just (Just lang, exts') ->- mode' { baseLanguage = lang- , extensions =- exts'- ++ configExtensions config- ++ extensions mode' }- in case parseModuleWithComments mode'' (UTF8.toString code) of- ParseOk (m, comments) ->- fmap- (S.lazyByteString . addPrefix prefix . S.toLazyByteString)- (prettyPrint config m comments)- ParseFailed loc e ->- Left (Exts.prettyPrint (loc {srcLine = srcLine loc + line}) ++ ": " ++ e)+ processBlock (HaskellSource yPos text) =+ let ls = S8.lines text+ prefix = findPrefix ls+ code = unlines' (map (stripPrefix prefix) ls)+ allExts =+ fromMaybe allExtensions mexts +++ configExtensions config +++ collectLanguageExtensionsFromSource (UTF8.toString code)+ exts = CE.uniqueExtensions allExts+ in case parseModule mfilepath exts (UTF8.toString code) of+ POk _ m ->+ Right $+ S.lazyByteString $+ addPrefix prefix $ S.toLazyByteString $ prettyPrint config m+ PFailed st ->+ let rawErrLoc = psRealLoc $ loc st+ adjustedLoc =+ (srcLocLine rawErrLoc + yPos, srcLocCol rawErrLoc)+ in Left $ "Parse failed near " ++ show adjustedLoc unlines' = S.concat . intersperse "\n" unlines'' = L.concat . intersperse "\n" addPrefix :: ByteString -> L8.ByteString -> L8.ByteString addPrefix prefix = unlines'' . map (L8.fromStrict prefix <>) . L8.lines stripPrefix :: ByteString -> ByteString -> ByteString stripPrefix prefix line =- if S.null (S8.dropWhile (== '\n') line)- then line- else fromMaybe (error "Missing expected prefix") . s8_stripPrefix prefix $- line+ if S.null (S8.dropWhile (== '\n') line)+ then line+ else fromMaybe (error "Missing expected prefix") . s8_stripPrefix prefix $+ line findPrefix :: [ByteString] -> ByteString findPrefix = takePrefix False . findSmallestPrefix . dropNewlines dropNewlines :: [ByteString] -> [ByteString] dropNewlines = filter (not . S.null . S8.dropWhile (== '\n')) takePrefix :: Bool -> ByteString -> ByteString takePrefix bracketUsed txt =- case S8.uncons txt of- Nothing -> ""- Just ('>', txt') ->- if not bracketUsed- then S8.cons '>' (takePrefix True txt')- else ""- Just (c, txt') ->- if c == ' ' || c == '\t'- then S8.cons c (takePrefix bracketUsed txt')- else ""+ case S8.uncons txt of+ Nothing -> ""+ Just ('>', txt') ->+ if not bracketUsed+ then S8.cons '>' (takePrefix True txt')+ else ""+ Just (c, txt') ->+ if c == ' ' || c == '\t'+ then S8.cons c (takePrefix bracketUsed txt')+ else "" findSmallestPrefix :: [ByteString] -> ByteString findSmallestPrefix [] = "" findSmallestPrefix ("":_) = "" findSmallestPrefix (p:ps) =- let first = S8.head p- startsWithChar c x = S8.length x > 0 && S8.head x == c- in if all (startsWithChar first) ps- then S8.cons- first- (findSmallestPrefix (S.tail p : map S.tail ps))- else ""- mode' =- let m = case mexts of- Just exts ->- parseMode- { extensions = exts- }- Nothing -> parseMode- in m { parseFilename = fromMaybe "<interactive>" mfilepath }- preserveTrailingNewline f x =- if S8.null x || S8.all isSpace x- then return mempty- else if hasTrailingLine x || configTrailingNewline config- then fmap- (\x' ->- if hasTrailingLine- (L.toStrict (S.toLazyByteString x'))- then x'- else x' <> "\n")- (f x)- else f x+ let first = S8.head p+ startsWithChar c x = S8.length x > 0 && S8.head x == c+ in if all (startsWithChar first) ps+ then S8.cons first (findSmallestPrefix (S.tail p : map S.tail ps))+ else ""+ preserveTrailingNewline f x+ | S8.null x || S8.all isSpace x = return mempty+ | hasTrailingLine x || configTrailingNewline config =+ fmap+ (\x' ->+ if hasTrailingLine (L.toStrict (S.toLazyByteString x'))+ then x'+ else x' <> "\n")+ (f x)+ | otherwise = f x +-- | Generate an AST from the given module for debugging.+testAst :: ByteString -> Either String HsModule+testAst x =+ case parseModule Nothing exts (UTF8.toString x) of+ POk _ m -> Right $ modifyASTForPrettyPrinting m+ PFailed st ->+ Left $+ "Parse failed near " +++ show ((,) <$> srcLocLine <*> srcLocCol $ psRealLoc $ loc st)+ where+ exts =+ CE.uniqueExtensions $+ collectLanguageExtensionsFromSource $ UTF8.toString x+ -- | Does the strict bytestring have a trailing newline? hasTrailingLine :: ByteString -> Bool-hasTrailingLine xs =- if S8.null xs- then False- else S8.last xs == '\n'+hasTrailingLine xs = not (S8.null xs) && S8.last xs == '\n' -- | Print the module.-prettyPrint :: Config- -> Module SrcSpanInfo- -> [Comment]- -> Either a Builder-prettyPrint config m comments =- let ast =- evalState- (collectAllComments- (fromMaybe m (applyFixities baseFixities m)))- comments- in Right (runPrinterStyle config (pretty ast))+prettyPrint :: Config -> HsModule -> Builder+prettyPrint config m =+ runPrinterStyle config (pretty $ modifyASTForPrettyPrinting m) -- | Pretty print the given printable thing. runPrinterStyle :: Config -> Printer () -> Builder@@ -172,263 +158,17 @@ (execStateT (runPrinter m) (PrintState- { psIndentLevel = 0- , psOutput = mempty- , psNewline = False- , psColumn = 0- , psLine = 1- , psConfig = config- , psInsideCase = False- , psFitOnOneLine = False- , psEolComment = False- }))))---- | Parse mode, includes all extensions, doesn't assume any fixities.-parseMode :: ParseMode-parseMode =- defaultParseMode {extensions = allExtensions- ,fixities = Nothing}- where allExtensions =- filter isDisabledExtension knownExtensions- isDisabledExtension (DisableExtension _) = False- isDisabledExtension _ = True---- | Test the given file.-testFile :: FilePath -> IO ()-testFile fp = S.readFile fp >>= test---- | Test the given file.-testFileAst :: FilePath -> IO ()-testFileAst fp = S.readFile fp >>= print . testAst---- | Test with the given style, prints to stdout.-test :: ByteString -> IO ()-test =- either error (L8.putStrLn . S.toLazyByteString) .- reformat defaultConfig Nothing Nothing---- | Parse the source and annotate it with comments, yielding the resulting AST.-testAst :: ByteString -> Either String (Module NodeInfo)-testAst x =- case parseModuleWithComments parseMode (UTF8.toString x) of- ParseOk (m,comments) ->- Right- (let ast =- evalState- (collectAllComments- (fromMaybe m (applyFixities baseFixities m)))- comments- in ast)- ParseFailed _ e -> Left e---- | Default extensions.-defaultExtensions :: [Extension]-defaultExtensions =- [ e- | e@EnableExtension {} <- knownExtensions ] \\- map EnableExtension badExtensions---- | Extensions which steal too much syntax.-badExtensions :: [KnownExtension]-badExtensions =- [Arrows -- steals proc- ,TransformListComp -- steals the group keyword- ,XmlSyntax, RegularPatterns -- steals a-b- ,UnboxedTuples -- breaks (#) lens operator- -- ,QuasiQuotes -- breaks [x| ...], making whitespace free list comps break- ,PatternSynonyms -- steals the pattern keyword- ,RecursiveDo -- steals the rec keyword- ,DoRec -- same- ,TypeApplications -- since GHC 8 and haskell-src-exts-1.19- ]-+ { psIndentLevel = 0+ , psOutput = mempty+ , psNewline = False+ , psColumn = 0+ , psLine = 1+ , psConfig = config+ , psFitOnOneLine = False+ , psEolComment = False+ })))) s8_stripPrefix :: ByteString -> ByteString -> Maybe ByteString s8_stripPrefix bs1@(S.PS _ _ l1) bs2- | bs1 `S.isPrefixOf` bs2 = Just (S.unsafeDrop l1 bs2)- | otherwise = Nothing------------------------------------------------------------------------------------- Extensions stuff stolen from hlint---- | Consume an extensions list from arguments.-getExtensions :: [Text] -> [Extension]-getExtensions = foldl f defaultExtensions . map T.unpack- where f _ "Haskell98" = []- f a ('N':'o':x)- | Just x' <- readExtension x =- delete x' a- f a x- | Just x' <- readExtension x =- x' :- delete x' a- f _ x = error $ "Unknown extension: " ++ x------------------------------------------------------------------------------------- Comments---- | Traverse the structure backwards.-traverseInOrder- :: (Monad m, Traversable t, Functor m)- => (b -> b -> Ordering) -> (b -> m b) -> t b -> m (t b)-traverseInOrder cmp f ast = do- indexed <-- fmap (zip [0 :: Integer ..] . reverse) (execStateT (traverse (modify . (:)) ast) [])- let sorted = sortBy (\(_,x) (_,y) -> cmp x y) indexed- results <-- mapM- (\(i,m) -> do- v <- f m- return (i, v))- sorted- evalStateT- (traverse- (const- (do i <- gets head- modify tail- case lookup i results of- Nothing -> error "traverseInOrder"- Just x -> return x))- ast)- [0 ..]---- | Collect all comments in the module by traversing the tree. Read--- this from bottom to top.-collectAllComments :: Module SrcSpanInfo -> State [Comment] (Module NodeInfo)-collectAllComments =- shortCircuit- (traverseBackwards- -- Finally, collect backwards comments which come after each node.- (collectCommentsBy- CommentAfterLine- (\nodeSpan commentSpan ->- fst (srcSpanStart commentSpan) >= fst (srcSpanEnd nodeSpan)))) <=<- shortCircuit addCommentsToTopLevelWhereClauses <=<- shortCircuit- (traverse- -- Collect forwards comments which start at the end line of a- -- node: Does the start line of the comment match the end-line- -- of the node?- (collectCommentsBy- CommentSameLine- (\nodeSpan commentSpan ->- fst (srcSpanStart commentSpan) == fst (srcSpanEnd nodeSpan)))) <=<- shortCircuit- (traverseBackwards- -- Collect backwards comments which are on the same line as a- -- node: Does the start line & end line of the comment match- -- that of the node?- (collectCommentsBy- CommentSameLine- (\nodeSpan commentSpan ->- fst (srcSpanStart commentSpan) == fst (srcSpanStart nodeSpan) &&- fst (srcSpanStart commentSpan) == fst (srcSpanEnd nodeSpan)))) <=<- shortCircuit- (traverse- -- First, collect forwards comments for declarations which both- -- start on column 1 and occur before the declaration.- (collectCommentsBy- CommentBeforeLine- (\nodeSpan commentSpan ->- (snd (srcSpanStart nodeSpan) == 1 &&- snd (srcSpanStart commentSpan) == 1) &&- fst (srcSpanStart commentSpan) < fst (srcSpanStart nodeSpan)))) .- fmap nodify- where- nodify s = NodeInfo s mempty- -- Sort the comments by their end position.- traverseBackwards =- traverseInOrder- (\x y -> on (flip compare) (srcSpanEnd . srcInfoSpan . nodeInfoSpan) x y)- -- Stop traversing if all comments have been consumed.- shortCircuit m v = do- comments <- get- if null comments- then return v- else m v---- | Collect comments by satisfying the given predicate, to collect a--- comment means to remove it from the pool of available comments in--- the State. This allows for a multiple pass approach.-collectCommentsBy- :: (SrcSpan -> SomeComment -> NodeComment)- -> (SrcSpan -> SrcSpan -> Bool)- -> NodeInfo- -> State [Comment] NodeInfo-collectCommentsBy cons predicate nodeInfo@(NodeInfo (SrcSpanInfo nodeSpan _) _) = do- comments <- get- let (others, mine) =- partitionEithers- (map- (\comment@(Comment _ commentSpan _) ->- if predicate nodeSpan commentSpan- then Right comment- else Left comment)- comments)- put others- return $ addCommentsToNode cons mine nodeInfo---- | Reintroduce comments which were immediately above declarations in where clauses.--- Affects where clauses of top level declarations only.-addCommentsToTopLevelWhereClauses ::- Module NodeInfo -> State [Comment] (Module NodeInfo)-addCommentsToTopLevelWhereClauses (Module x x' x'' x''' topLevelDecls) =- Module x x' x'' x''' <$>- traverse addCommentsToWhereClauses topLevelDecls- where- addCommentsToWhereClauses ::- Decl NodeInfo -> State [Comment] (Decl NodeInfo)- addCommentsToWhereClauses (PatBind x x' x'' (Just (BDecls x''' whereDecls))) = do- newWhereDecls <- traverse addCommentsToPatBind whereDecls- return $ PatBind x x' x'' (Just (BDecls x''' newWhereDecls))- addCommentsToWhereClauses other = return other- addCommentsToPatBind :: Decl NodeInfo -> State [Comment] (Decl NodeInfo)- addCommentsToPatBind (PatBind bindInfo (PVar x (Ident declNodeInfo declString)) x' x'') = do- bindInfoWithComments <- addCommentsBeforeNode bindInfo- return $- PatBind- bindInfoWithComments- (PVar x (Ident declNodeInfo declString))- x'- x''- addCommentsToPatBind other = return other- addCommentsBeforeNode :: NodeInfo -> State [Comment] NodeInfo- addCommentsBeforeNode nodeInfo = do- comments <- get- let (notAbove, above) = partitionAboveNotAbove comments nodeInfo- put notAbove- return $ addCommentsToNode CommentBeforeLine above nodeInfo- partitionAboveNotAbove :: [Comment] -> NodeInfo -> ([Comment], [Comment])- partitionAboveNotAbove cs (NodeInfo (SrcSpanInfo nodeSpan _) _) =- fst $- foldr'- (\comment@(Comment _ commentSpan _) ((ls, rs), lastSpan) ->- if comment `isAbove` lastSpan- then ((ls, comment : rs), commentSpan)- else ((comment : ls, rs), lastSpan))- (([], []), nodeSpan)- cs- isAbove :: Comment -> SrcSpan -> Bool- isAbove (Comment _ commentSpan _) span =- let (_, commentColStart) = srcSpanStart commentSpan- (commentLnEnd, _) = srcSpanEnd commentSpan- (lnStart, colStart) = srcSpanStart span- in commentColStart == colStart && commentLnEnd + 1 == lnStart-addCommentsToTopLevelWhereClauses other = return other--addCommentsToNode :: (SrcSpan -> SomeComment -> NodeComment)- -> [Comment]- -> NodeInfo- -> NodeInfo-addCommentsToNode mkNodeComment newComments nodeInfo@(NodeInfo (SrcSpanInfo _ _) existingComments) =- nodeInfo- {nodeInfoComments = existingComments <> map mkBeforeNodeComment newComments}- where- mkBeforeNodeComment :: Comment -> NodeComment- mkBeforeNodeComment (Comment multiLine commentSpan commentString) =- mkNodeComment- commentSpan- ((if multiLine- then MultiLine- else EndOfLine)- commentString)+ | bs1 `S.isPrefixOf` bs2 = Just (S.unsafeDrop l1 bs2)+ | otherwise = Nothing
+ src/HIndent/Applicative.hs view
@@ -0,0 +1,11 @@+-- | Helper functions to handle 'Applicative's+module HIndent.Applicative+ ( whenJust+ ) where++-- | If the first argument is a 'Just' value, this function applies its+-- internal value to the function passed as the second argument. Otherwise,+-- this function returne a 'pure ()'.+whenJust :: (Applicative m) => Maybe a -> (a -> m ()) -> m ()+whenJust Nothing _ = pure ()+whenJust (Just x) f = f x
src/HIndent/CabalFile.hs view
@@ -20,11 +20,13 @@ #else import Distribution.PackageDescription.Parse #endif-import Language.Haskell.Extension-import qualified Language.Haskell.Exts.Extension as HSE+import HIndent.Language+import HIndent.LanguageExtension hiding (defaultExtensions)+import HIndent.LanguageExtension.Conversion+import HIndent.LanguageExtension.Types+import Language.Haskell.Extension hiding (Extension) import System.Directory import System.FilePath-import Text.Read data Stanza = MkStanza { _stanzaBuildInfo :: BuildInfo@@ -33,60 +35,60 @@ -- | Find the relative path of a child path in a parent, if it is a child toRelative :: FilePath -> FilePath -> Maybe FilePath-toRelative parent child = let- rel = makeRelative parent child- in if rel == child- then Nothing- else Just rel+toRelative parent child =+ let rel = makeRelative parent child+ in if rel == child+ then Nothing+ else Just rel -- | Create a Stanza from `BuildInfo` and names of modules and paths mkStanza :: BuildInfo -> [ModuleName] -> [FilePath] -> Stanza mkStanza bi mnames fpaths =- MkStanza bi $ \path -> let- modpaths = fmap toFilePath $ otherModules bi ++ mnames- inDir dir =- case toRelative dir path of- Nothing -> False- Just relpath ->- any (equalFilePath $ dropExtension relpath) modpaths ||- any (equalFilePath relpath) fpaths- in any inDir $ hsSourceDirs' bi- where+ MkStanza bi $ \path ->+ let modpaths = fmap toFilePath $ otherModules bi ++ mnames+ inDir dir =+ case toRelative dir path of+ Nothing -> False+ Just relpath ->+ any (equalFilePath $ dropExtension relpath) modpaths ||+ any (equalFilePath relpath) fpaths+ in any inDir $ hsSourceDirs' bi+ where+ #if MIN_VERSION_Cabal(3, 6, 0)- hsSourceDirs' = (map getSymbolicPath) . hsSourceDirs+ hsSourceDirs' = (map getSymbolicPath) . hsSourceDirs #else hsSourceDirs' = hsSourceDirs #endif- -- | Extract `Stanza`s from a package packageStanzas :: PackageDescription -> [Stanza]-packageStanzas pd = let- libStanza :: Library -> Stanza- libStanza lib = mkStanza (libBuildInfo lib) (exposedModules lib) []- exeStanza :: Executable -> Stanza- exeStanza exe = mkStanza (buildInfo exe) [] [modulePath exe]- testStanza :: TestSuite -> Stanza- testStanza ts =- mkStanza- (testBuildInfo ts)- (case testInterface ts of- TestSuiteLibV09 _ mname -> [mname]- _ -> [])- (case testInterface ts of- TestSuiteExeV10 _ path -> [path]- _ -> [])- benchStanza :: Benchmark -> Stanza- benchStanza bn =- mkStanza (benchmarkBuildInfo bn) [] $- case benchmarkInterface bn of- BenchmarkExeV10 _ path -> [path]- _ -> []- in mconcat- [ maybeToList $ fmap libStanza $ library pd- , fmap exeStanza $ executables pd- , fmap testStanza $ testSuites pd- , fmap benchStanza $ benchmarks pd- ]+packageStanzas pd =+ let libStanza :: Library -> Stanza+ libStanza lib = mkStanza (libBuildInfo lib) (exposedModules lib) []+ exeStanza :: Executable -> Stanza+ exeStanza exe = mkStanza (buildInfo exe) [] [modulePath exe]+ testStanza :: TestSuite -> Stanza+ testStanza ts =+ mkStanza+ (testBuildInfo ts)+ (case testInterface ts of+ TestSuiteLibV09 _ mname -> [mname]+ _ -> [])+ (case testInterface ts of+ TestSuiteExeV10 _ path -> [path]+ _ -> [])+ benchStanza :: Benchmark -> Stanza+ benchStanza bn =+ mkStanza (benchmarkBuildInfo bn) [] $+ case benchmarkInterface bn of+ BenchmarkExeV10 _ path -> [path]+ _ -> []+ in mconcat+ [ maybeToList $ fmap libStanza $ library pd+ , fmap exeStanza $ executables pd+ , fmap testStanza $ testSuites pd+ , fmap benchStanza $ benchmarks pd+ ] -- | Find cabal files that are "above" the source path findCabalFiles :: FilePath -> FilePath -> IO (Maybe ([FilePath], FilePath))@@ -103,16 +105,15 @@ getGenericPackageDescription :: FilePath -> IO (Maybe GenericPackageDescription) #if MIN_VERSION_Cabal(2, 2, 0) getGenericPackageDescription cabalPath = do- cabaltext <- BS.readFile cabalPath- return $ parseGenericPackageDescriptionMaybe cabaltext+ cabaltext <- BS.readFile cabalPath+ return $ parseGenericPackageDescriptionMaybe cabaltext #else getGenericPackageDescription cabalPath = do cabaltext <- readFile cabalPath case parsePackageDescription cabaltext of ParseOk _ gpd -> return $ Just gpd- _ -> return Nothing+ _ -> return Nothing #endif- -- | Find the `Stanza` that refers to this source path getCabalStanza :: FilePath -> IO (Maybe Stanza) getCabalStanza srcpath = do@@ -134,36 +135,20 @@ (stanza:_) -> Just stanza -- just pick the first one Nothing -> return Nothing --- | Get (Cabal package) language and extensions from the cabal file for this source path+-- | Get language and extensions from the cabal file for this source path getCabalExtensions :: FilePath -> IO (Language, [Extension]) getCabalExtensions srcpath = do mstanza <- getCabalStanza srcpath return $ case mstanza of Nothing -> (Haskell98, [])- Just (MkStanza bi _) -> do- (fromMaybe Haskell98 $ defaultLanguage bi, defaultExtensions bi)--convertLanguage :: Language -> HSE.Language-convertLanguage lang = read $ show lang--convertKnownExtension :: KnownExtension -> Maybe HSE.KnownExtension-convertKnownExtension ext =- case readEither $ show ext of- Left _ -> Nothing- Right hext -> Just hext--convertExtension :: Extension -> Maybe HSE.Extension-convertExtension (EnableExtension ke) =- fmap HSE.EnableExtension $ convertKnownExtension ke-convertExtension (DisableExtension ke) =- fmap HSE.DisableExtension $ convertKnownExtension ke-convertExtension (UnknownExtension s) = Just $ HSE.UnknownExtension s+ Just (MkStanza bi _) ->+ ( fromMaybe Haskell98 $ defaultLanguage bi+ , mapMaybe fromCabalExtension $ defaultExtensions bi) -- | Get extensions from the cabal file for this source path-getCabalExtensionsForSourcePath :: FilePath -> IO [HSE.Extension]+getCabalExtensionsForSourcePath :: FilePath -> IO [Extension] getCabalExtensionsForSourcePath srcpath = do (lang, exts) <- getCabalExtensions srcpath- return $- fmap HSE.EnableExtension $- HSE.toExtensionList (convertLanguage lang) $ mapMaybe convertExtension exts+ let allExts = exts ++ implicitExtensions (convertLanguage lang)+ return $ concatMap extensionImplies allExts
src/HIndent/CodeBlock.hs view
@@ -7,15 +7,14 @@ import Data.ByteString (ByteString) import qualified Data.ByteString.Char8 as S8-import Data.Monoid -- | A block of code. data CodeBlock- = Shebang ByteString- | HaskellSource Int ByteString+ = Shebang ByteString+ | HaskellSource Int ByteString -- ^ Includes the starting line (indexed from 0) for error reporting- | CPPDirectives ByteString- deriving (Show, Eq)+ | CPPDirectives ByteString+ deriving (Show, Eq) -- | Break a Haskell code string into chunks, using CPP as a delimiter. -- Lines that start with '#if', '#end', or '#else' are their own chunks, and@@ -57,7 +56,16 @@ cppLine src = any (`S8.isPrefixOf` src)- ["#if", "#end", "#else", "#define", "#undef", "#elif", "#include", "#error", "#warning"]+ [ "#if"+ , "#end"+ , "#else"+ , "#define"+ , "#undef"+ , "#elif"+ , "#include"+ , "#error"+ , "#warning"+ ] -- Note: #ifdef and #ifndef are handled by #if hasEscapedTrailingNewline :: ByteString -> Bool hasEscapedTrailingNewline src = "\\" `S8.isSuffixOf` src
+ src/HIndent/Config.hs view
@@ -0,0 +1,81 @@+{-# LANGUAGE OverloadedStrings #-}++-- | Things related to HIndent configuration.+module HIndent.Config+ ( Config(..)+ , defaultConfig+ , getConfig+ ) where++import Control.Applicative+import Data.Int+import Data.Maybe+import Data.Yaml+import qualified Data.Yaml as Y+import HIndent.LanguageExtension.Conversion+import HIndent.LanguageExtension.Types+import qualified HIndent.Path.Find as Path+import Path+import qualified Path.IO as Path++-- | Configurations shared among the different styles. Styles may pay+-- attention to or completely disregard this configuration.+data Config = Config+ { configMaxColumns :: !Int64 -- ^ Maximum columns to fit code into ideally.+ , configIndentSpaces :: !Int64 -- ^ How many spaces to indent?+ , configTrailingNewline :: !Bool -- ^ End with a newline.+ , configSortImports :: !Bool -- ^ Sort imports in groups.+ , configLineBreaks :: [String] -- ^ Break line when meets these operators.+ , configExtensions :: [Extension]+ -- ^ Extra language extensions enabled by default.+ }++instance FromJSON Config where+ parseJSON (Y.Object v) =+ Config <$>+ fmap (fromMaybe (configMaxColumns defaultConfig)) (v Y..:? "line-length") <*>+ fmap+ (fromMaybe (configIndentSpaces defaultConfig))+ (v Y..:? "indent-size" <|> v Y..:? "tab-size") <*>+ fmap+ (fromMaybe (configTrailingNewline defaultConfig))+ (v Y..:? "force-trailing-newline") <*>+ fmap (fromMaybe (configSortImports defaultConfig)) (v Y..:? "sort-imports") <*>+ fmap (fromMaybe (configLineBreaks defaultConfig)) (v Y..:? "line-breaks") <*>+ (traverse convertExt . fromMaybe [] =<< v Y..:? "extensions")+ where+ convertExt x =+ case strToExt x of+ Just x' -> pure x'+ Nothing -> error $ "Unknow extension: " ++ show x+ parseJSON _ = fail "Expected Object for Config value"++-- | Default style configuration.+defaultConfig :: Config+defaultConfig =+ Config+ { configMaxColumns = 80+ , configIndentSpaces = 2+ , configTrailingNewline = True+ , configSortImports = True+ , configLineBreaks = []+ , configExtensions = []+ }++-- | Read config from a config file, or return 'defaultConfig'.+getConfig :: IO Config+getConfig = do+ cur <- Path.getCurrentDir+ homeDir <- Path.getHomeDir+ mfile <-+ Path.findFileUp+ cur+ ((== ".hindent.yaml") . toFilePath . filename)+ (Just homeDir)+ case mfile of+ Nothing -> return defaultConfig+ Just file -> do+ result <- Y.decodeFileEither (toFilePath file)+ case result of+ Left e -> error (show e)+ Right config -> return config
+ src/HIndent/Language.hs view
@@ -0,0 +1,23 @@+{-# LANGUAGE CPP #-}++-- | Operations for handling languages (e.g., Haskell2010).+module HIndent.Language+ ( convertLanguage+ ) where++import qualified GHC.Driver.Session as GLP+import GHC.Stack+import qualified Language.Haskell.Extension as Cabal++-- | This function converts a value of 'Language' defined in the 'Cabal'+-- package to the same value of 'Language' defined in the 'ghc-lib-parser'+-- package.+--+-- This function raises an error if a 'UnknownLanguage' value is passed.+convertLanguage :: HasCallStack => Cabal.Language -> GLP.Language+convertLanguage Cabal.Haskell98 = GLP.Haskell98+convertLanguage Cabal.Haskell2010 = GLP.Haskell2010+#if MIN_VERSION_Cabal(3,6,0)+convertLanguage Cabal.GHC2021 = GLP.GHC2021+#endif+convertLanguage (Cabal.UnknownLanguage s) = error $ "Unknown language: " ++ s
+ src/HIndent/LanguageExtension.hs view
@@ -0,0 +1,121 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE ScopedTypeVariables #-}++-- | Operations related to language extensions.+module HIndent.LanguageExtension+ ( implicitExtensions+ , extensionImplies+ , collectLanguageExtensionsFromSource+ , defaultExtensions+ , allExtensions+ , getExtensions+ ) where++import Data.Char+import Data.List+import Data.List.Split+import Data.Maybe+import qualified Data.Text as T+import qualified GHC.Driver.Session as GLP+import qualified GHC.LanguageExtensions as GLP+import HIndent.LanguageExtension.Conversion+import HIndent.LanguageExtension.Types+import HIndent.Pragma+import Text.Regex.TDFA++-- | This function returns a list of extensions that the passed language+-- (e.g., GHC2021) enables.+implicitExtensions :: GLP.Language -> [Extension]+implicitExtensions = fmap EnableExtension . GLP.languageExtensions . Just++-- | This function returns a list of extensions that the passed extension+-- enables and disables.+--+-- For example, @GADTs@ enables @GADTSyntax@ and @RebindableSyntax@+-- disables @ImplicitPrelude@.+extensionImplies :: Extension -> [Extension]+extensionImplies (EnableExtension e) =+ toExtension <$> filter (\(a, _, _) -> e == a) GLP.impliedXFlags+ where+ toExtension (_, True, e') = EnableExtension e'+ toExtension (_, False, e') = DisableExtension e'+extensionImplies _ = []++-- | Collect pragmas specified in the source code.+collectLanguageExtensionsFromSource :: String -> [Extension]+collectLanguageExtensionsFromSource =+ (++) <$> collectLanguageExtensionsSpecifiedViaLanguagePragma <*>+ collectLanguageExtensionsFromSourceViaOptionsPragma++-- | Consume an extensions list from arguments.+getExtensions :: [T.Text] -> [Extension]+getExtensions = foldr (f . T.unpack) defaultExtensions+ where+ f "Haskell98" _ = []+ f x a =+ case strToExt x of+ Just x'@EnableExtension {} -> x' : delete x' a+ Just (DisableExtension x') -> delete (EnableExtension x') a+ _ -> error $ "Unknown extension: " ++ x++-- | Collects language extensions enabled or disabled by @{-# LANGUAGE FOO+-- #-}@.+--+-- This function ignores language extensions not supported by Cabal.+collectLanguageExtensionsSpecifiedViaLanguagePragma :: String -> [Extension]+collectLanguageExtensionsSpecifiedViaLanguagePragma =+ mapMaybe (strToExt . stripSpaces) .+ concatMap (splitOn ",") .+ fmap snd . filter ((== "LANGUAGE") . fst) . extractPragmasFromCode++-- | Extracts the language extensions specified by @-XFOO@ from @OPTIONS@+-- or @OPTIONS_GHC@ pragmas+collectLanguageExtensionsFromSourceViaOptionsPragma :: String -> [Extension]+collectLanguageExtensionsFromSourceViaOptionsPragma =+ mapMaybe (strToExt . stripSpaces) .+ concatMap extractLanguageExtensionsFromOptions .+ fmap snd .+ filter ((`elem` ["OPTIONS", "OPTIONS_GHC"]) . fst) . extractPragmasFromCode++-- | Extracts the language extensions specified in the '-XFOO' format from+-- the given string+extractLanguageExtensionsFromOptions :: String -> [String]+extractLanguageExtensionsFromOptions options =+ fmap+ trimXOption+ (getAllTextMatches (options =~ "-X[^,[:space:]]+") :: [String])+ where+ trimXOption ('-':'X':xs) = xs+ trimXOption _ = error "Unreachable: the option must have the `-X` prefix."++-- | Removes spaces before and after the string.+stripSpaces :: String -> String+stripSpaces = reverse . dropWhile isSpace . reverse . dropWhile isSpace++-- | Default extensions.+defaultExtensions :: [Extension]+defaultExtensions = fmap EnableExtension $ [minBound ..] \\ badExtensions++-- | All extensions supported by Cabal.+allExtensions :: [Extension]+allExtensions = fmap EnableExtension [minBound ..]++-- | Extensions which steal too much syntax.+badExtensions :: [GLP.Extension]+badExtensions =+ [ GLP.Arrows -- steals proc+ , GLP.TransformListComp -- steals the group keyword+ , GLP.UnboxedTuples -- breaks (#) lens operator+ , GLP.UnboxedSums -- Same as 'UnboxedTuples'+ -- ,QuasiQuotes -- breaks [x| ...], making whitespace free list comps break+ , GLP.PatternSynonyms -- steals the pattern keyword+ , GLP.RecursiveDo -- steals the rec keyword+ , GLP.TypeApplications -- Steals `@`+ , GLP.StaticPointers -- Steals the `static` keyword+ , GLP.AlternativeLayoutRule -- Breaks a few tests+ , GLP.AlternativeLayoutRuleTransitional -- Same as `AlternativeLayoutRule`+ , GLP.LexicalNegation -- Cannot handle minus signs in some cases+ , GLP.OverloadedRecordDot -- Breaks 'a.b'+ , GLP.OverloadedRecordUpdate -- Cannot handle symbol members starting+ -- with a dot in a record well+ ]
+ src/HIndent/LanguageExtension/Conversion.hs view
@@ -0,0 +1,58 @@+{-# LANGUAGE CPP #-}++-- | Operations for converting extensions types.+module HIndent.LanguageExtension.Conversion+ ( fromCabalExtension+ , uniqueExtensions+ , convertExtension+ , strToExt+ ) where++import qualified GHC.LanguageExtensions as GLP+import HIndent.LanguageExtension.Types+import qualified Language.Haskell.Extension as Cabal+import qualified Language.Haskell.GhclibParserEx.GHC.Driver.Session as GLP++-- | Converts from an `Extension` defined in the `Cabal` package to an+-- `Extension` defined in HIndent.+--+-- Note that this function returns `Nothing` if `UnknownExtension` is+-- passed or if an extension is not supported by GHC.+fromCabalExtension :: Cabal.Extension -> Maybe Extension+fromCabalExtension (Cabal.EnableExtension x) =+ EnableExtension <$> convertExtension x+fromCabalExtension (Cabal.DisableExtension x) =+ DisableExtension <$> convertExtension x+fromCabalExtension Cabal.UnknownExtension {} = Nothing++-- | This function converts each value of the type 'Extension' defined in+-- 'HIndent.LanguageExtension.Types' in the list to the same value of the+-- type 'Extension' defined in the package 'ghc-lib-parser'.+--+-- If the extension has the 'No' suffix, the extension is removed from the+-- result. If both extensions having and not having the suffix exist in the+-- list, only the most backward one has the effect.+--+-- If converting an extension fails due to neither GHC nor 'ghc-lib-parser'+-- not supporting, or deprecation or removal, the extension is ignored.+uniqueExtensions :: [Extension] -> [GLP.Extension]+uniqueExtensions [] = []+uniqueExtensions ((EnableExtension e):xs) = e : uniqueExtensions xs+uniqueExtensions ((DisableExtension e):xs) =+ uniqueExtensions $ filter (/= EnableExtension e) xs++-- | This function converts a value of 'KnownExtension' defined in the+-- 'Cabal' package to the same value of 'Extension' defined in+-- 'ghc-lib-parser'.+--+-- This function returns a 'Just' value if it succeeds in converting.+-- Otherwise (e.g., 'ghc-lib-parser' does not the passed extension, or it+-- is deprecated or removed), it returns a 'Nothing'.+convertExtension :: Cabal.KnownExtension -> Maybe GLP.Extension+convertExtension = GLP.readExtension . show++-- | Converts the given string to an extension, or returns a 'Nothing' on+-- fail.+strToExt :: String -> Maybe Extension+strToExt ('N':'o':s) = DisableExtension <$> GLP.readExtension s+strToExt s = EnableExtension <$> GLP.readExtension s
+ src/HIndent/LanguageExtension/Types.hs view
@@ -0,0 +1,18 @@+-- | Types related to language extensions+module HIndent.LanguageExtension.Types+ ( Extension(..)+ ) where++import qualified GHC.LanguageExtensions as GLP++-- | Language Extension. Either enabled or disabled.+--+-- The `Cabal` package also has an `Extension` type that can be used to+-- indicate whether an extension is enabled or disabled, but Cabal's one+-- should be avoided as much as possible. The `KnownExtension` of `Cabal`+-- may not have the latest extensions, and if such extensions are used,+-- there will be cases where GHC can build, but HIndent cannot format.+data Extension+ = EnableExtension GLP.Extension+ | DisableExtension GLP.Extension+ deriving (Eq)
+ src/HIndent/ModulePreprocessing.hs view
@@ -0,0 +1,222 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE ImpredicativeTypes #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}++-- | Module preprocessing before pretty-printing.+module HIndent.ModulePreprocessing+ ( modifyASTForPrettyPrinting+ ) where++import Control.Applicative+import Data.Function+import Data.List+import Data.Maybe+import GHC.Hs+import GHC.Types.SrcLoc+import Generics.SYB hiding (GT, typeOf, typeRep)+import HIndent.ModulePreprocessing.CommentRelocation+import Language.Haskell.GhclibParserEx.Fixity+import Type.Reflection++-- | This function modifies the given module AST for pretty-printing.+--+-- Pretty-printing a module without calling this function for it before may+-- raise an error or not print it correctly.+modifyASTForPrettyPrinting :: HsModule -> HsModule+modifyASTForPrettyPrinting m = relocateComments (beforeRelocation m) allComments+ where+ beforeRelocation =+ resetLGRHSEndPositionInModule .+ removeAllDocDs .+ closeEpAnnOfHsFunTy .+ closeEpAnnOfMatchMExt .+ closePlaceHolderEpAnns .+ closeEpAnnOfFunBindFunId .+ resetModuleNameColumn .+ replaceAllNotUsedAnns . removeComments . sortExprLStmt . fixFixities+ allComments = listify (not . isEofComment . ac_tok . unLoc) m+ isEofComment EpaEofComment = True+ isEofComment _ = False++-- | This function modifies the given module AST to apply fixities of infix+-- operators defined in the 'base' package.+fixFixities :: HsModule -> HsModule+fixFixities = applyFixities baseFixities++-- | This function sets an 'LGRHS's end position to the end position of the+-- last RHS in the 'grhssGRHSs'.+--+-- The source span of an 'L?GRHS' contains the 'where' keyword, which+-- locates comments in the wrong position in the process of comment+-- relocation. This function prevents it by fixing the 'L?GRHS''s source+-- span.+resetLGRHSEndPositionInModule :: HsModule -> HsModule+resetLGRHSEndPositionInModule = everywhere (mkT resetLGRHSEndPosition)++-- | This function sorts lists of statements in order their positions.+--+-- For example, the last element of 'HsDo' of 'HsExpr' is the element+-- before a bar, and the elements are not sorted by their locations. This+-- function fixes the orderings.+sortExprLStmt :: HsModule -> HsModule+sortExprLStmt m@HsModule {hsmodDecls = xs} = m {hsmodDecls = sorted}+ where+ sorted = everywhere (mkT sortByLoc) xs+ sortByLoc :: [ExprLStmt GhcPs] -> [ExprLStmt GhcPs]+ sortByLoc = sortBy (compare `on` srcSpanToRealSrcSpan . locA . getLoc)++-- | This function removes all comments from the given module not to+-- duplicate them on comment relocation.+removeComments :: HsModule -> HsModule+removeComments = everywhere (mkT $ const emptyComments)++-- | This function replaces all 'EpAnnNotUsed's in 'SrcSpanAnn''s with+-- 'EpAnn's to make it possible to locate comments on them.+replaceAllNotUsedAnns :: HsModule -> HsModule+replaceAllNotUsedAnns = everywhere app+ where+ app ::+ forall a. Data a+ => (a -> a)+ app sp+ | App g (App y z) <- typeRep @a+ , Just HRefl <- eqTypeRep g (typeRep @SrcSpanAnn')+ , Just HRefl <- eqTypeRep y (typeRep @EpAnn) =+ fromMaybe sp $ do+ let try :: Typeable b => b -> Maybe a+ try ann = do+ HRefl <- eqTypeRep (typeOf ann) z+ pure sp {ann = EpAnn (spanAsAnchor $ locA sp) ann emptyComments}+ try emptyListItem <|> try emptyList <|> try emptyPragma <|>+ try emptyContext <|>+ try emptyNameAnn <|>+ try NoEpAnns+ app x = x+ emptyListItem = AnnListItem []+ emptyList = AnnList Nothing Nothing Nothing [] []+ emptyPragma = AnnPragma emptyAddEpAnn emptyAddEpAnn []+ emptyContext = AnnContext Nothing [] []+ emptyNameAnn = NameAnnTrailing []+ emptyAddEpAnn = AddEpAnn AnnAnyclass emptyEpaLocation+ emptyEpaLocation = EpaDelta (SameLine 0) []++-- | This function sets the start column of 'hsmodName' of the given+-- 'HsModule' to 1 to correctly locate comments above the module name.+resetModuleNameColumn :: HsModule -> HsModule+resetModuleNameColumn m@HsModule {hsmodName = Just (L (SrcSpanAnn epa@EpAnn {..} sp) name)} =+ m {hsmodName = Just (L (SrcSpanAnn newAnn sp) name)}+ where+ newAnn = epa {entry = realSpanAsAnchor newSpan}+ newSpan =+ mkRealSrcSpan+ (mkRealSrcLoc (srcSpanFile anc) (srcSpanStartLine anc) 1)+ (realSrcSpanEnd anc)+ anc = anchor entry+resetModuleNameColumn m = m++-- | This function replaces the 'EpAnn' of 'fun_id' in 'FunBind' with+-- 'EpAnnNotUsed'.+--+-- The 'fun_id' contains the function's name. However, 'FunRhs' of 'Match'+-- also contains the name, and we use the latter one. This function+-- prevents comments from being located in 'fun_id'.+closeEpAnnOfFunBindFunId :: HsModule -> HsModule+closeEpAnnOfFunBindFunId = everywhere (mkT closeEpAnn)+ where+ closeEpAnn :: HsBind GhcPs -> HsBind GhcPs+ closeEpAnn bind@FunBind {fun_id = (L (SrcSpanAnn _ l) name)} =+ bind {fun_id = L (SrcSpanAnn EpAnnNotUsed l) name}+ closeEpAnn x = x++-- | This function replaces the 'EpAnn' of 'm_ext' in 'Match' with+-- 'EpAnnNotUsed.+--+-- The field contains the annotation of the match LHS. However, the same+-- information is also stored inside the 'Match'. This function removes the+-- duplication not to locate comments on a wrong point.+closeEpAnnOfMatchMExt :: HsModule -> HsModule+closeEpAnnOfMatchMExt = everywhere closeEpAnn+ where+ closeEpAnn ::+ forall a. Typeable a+ => a+ -> a+ closeEpAnn x+ | App (App g h) _ <- typeRep @a+ , Just HRefl <- eqTypeRep g (typeRep @Match)+ , Just HRefl <- eqTypeRep h (typeRep @GhcPs) = x {m_ext = EpAnnNotUsed}+ | otherwise = x++-- | This function replaces the 'EpAnn' of the first argument of 'HsFunTy'+-- of 'HsType'.+--+-- 'HsFunTy' should not have any comments. Instead, its LHS and RHS should+-- have them.+closeEpAnnOfHsFunTy :: HsModule -> HsModule+closeEpAnnOfHsFunTy = everywhere (mkT closeEpAnn)+ where+ closeEpAnn :: HsType GhcPs -> HsType GhcPs+ closeEpAnn (HsFunTy _ p l r) = HsFunTy EpAnnNotUsed p l r+ closeEpAnn x = x++-- | This function replaces all 'EpAnn's that contain placeholder anchors+-- to locate comments correctly. A placeholder anchor is an anchor pointing+-- on (-1, -1).+closePlaceHolderEpAnns :: HsModule -> HsModule+closePlaceHolderEpAnns = everywhere closeEpAnn+ where+ closeEpAnn ::+ forall a. Typeable a+ => a+ -> a+ closeEpAnn x+ | App g _ <- typeRep @a+ , Just HRefl <- eqTypeRep g (typeRep @EpAnn)+ , (EpAnn (Anchor sp _) _ _) <- x+ , srcSpanEndLine sp == -1 && srcSpanEndCol sp == -1 = EpAnnNotUsed+ | otherwise = x++-- | This function removes all 'DocD's from the given module. They have+-- haddocks, but the same information is stored in 'EpaCommentTok's. Thus,+-- we need to remove the duplication.+removeAllDocDs :: HsModule -> HsModule+removeAllDocDs x@HsModule {hsmodDecls = decls} =+ x {hsmodDecls = filter (not . isDocD . unLoc) decls}+ where+ isDocD DocD {} = True+ isDocD _ = False++-- | This function sets the position of the given 'LGRHS' to the end+-- position of the last RHS in it.+--+-- See the documentation of 'resetLGRHSEndPositionInModule' for the reason.+resetLGRHSEndPosition ::+ LGRHS GhcPs (LHsExpr GhcPs) -> LGRHS GhcPs (LHsExpr GhcPs)+#if MIN_VERSION_ghc_lib_parser(9,4,1)+resetLGRHSEndPosition (L (SrcSpanAnn locAnn@EpAnn {} sp) (GRHS ext@EpAnn {..} stmt body)) =+ let lastPosition =+ maximum $ realSrcSpanEnd . anchor <$> listify collectAnchor body+ newSpan = mkRealSrcSpan (realSrcSpanStart $ anchor entry) lastPosition+ newLocAnn = locAnn {entry = realSpanAsAnchor newSpan}+ newAnn = ext {entry = realSpanAsAnchor newSpan}+ in L (SrcSpanAnn newLocAnn sp) (GRHS newAnn stmt body)+ where+ collectAnchor :: Anchor -> Bool+ collectAnchor _ = True+#else+resetLGRHSEndPosition (L _ (GRHS ext@EpAnn {..} stmt body)) =+ let lastPosition =+ maximum $ realSrcSpanEnd . anchor <$> listify collectAnchor body+ newSpan = mkRealSrcSpan (realSrcSpanStart $ anchor entry) lastPosition+ newLoc = RealSrcSpan newSpan Nothing+ newAnn = ext {entry = realSpanAsAnchor newSpan}+ in L newLoc (GRHS newAnn stmt body)+ where+ collectAnchor :: Anchor -> Bool+ collectAnchor _ = True+#endif+resetLGRHSEndPosition x = x
+ src/HIndent/ModulePreprocessing/CommentRelocation.hs view
@@ -0,0 +1,336 @@+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeApplications #-}++-- | Comment relocation for pretty-printing comments correctly.+--+-- HIndent gathers all comments above a function, an import, a module+-- declaration, etc. For example, HIndent formats the following code+--+-- > f :: Int+-- > f = 1+-- >+-- > -- A comment between f and g+-- >+-- > -- Another comment between f and g+-- >+-- > g :: Int+-- > g = 2+--+-- to+--+-- > f :: Int+-- > f = 1+-- >+-- > -- A comment between f and g+-- > -- Another comment between f and g+-- > g :: Int+-- > g = 2+--+-- AST nodes must have the information of which comments are above, on the+-- same line, and below. However, AST nodes generated by a parser of+-- 'ghc-lib-parser' only contain comments after them. 'relocateComments' is+-- defined to solve the problem.+module HIndent.ModulePreprocessing.CommentRelocation+ ( relocateComments+ ) where++import Control.Exception+import Control.Monad.State+import Data.Foldable+import Data.Function+import Data.List+import GHC.Data.Bag+import GHC.Hs+import GHC.Types.SrcLoc+import Generics.SYB hiding (GT, typeOf, typeRep)+import HIndent.Pretty.Pragma+import HIndent.Pretty.SigBindFamily+import Type.Reflection++-- | A wrapper type used in everywhereMEpAnnsBackwards' to collect all+-- 'EpAnn's to apply a function with them in order their positions.+data Wrapper =+ forall a. Typeable (EpAnn a) =>+ Wrapper (EpAnn a)++-- | 'State' with comments.+type WithComments = State [LEpaComment]++-- | This function collects all comments from the passed 'HsModule', and+-- modifies all 'EpAnn's so that all 'EpAnn's have 'EpaCommentsBalanced's.+relocateComments :: HsModule -> [LEpaComment] -> HsModule+relocateComments = evalState . relocate+ where+ relocate =+ relocatePragmas >=>+ relocateCommentsBeforePragmas >=>+ relocateCommentsInExportList >=>+ relocateCommentsBeforeTopLevelDecls >=>+ relocateCommentsSameLine >=>+ relocateCommentsTopLevelWhereClause >=>+ relocateCommentsAfter >=> assertAllCommentsAreConsumed+ assertAllCommentsAreConsumed x = do+ cs <- get+ assert (null cs) (pure x)++-- | This function locates pragmas to the module's EPA.+relocatePragmas :: HsModule -> WithComments HsModule+relocatePragmas m@HsModule {hsmodAnn = epa@EpAnn {}} = do+ newAnn <- insertComments (isPragma . ac_tok . unLoc) insertPriorComments epa+ return m {hsmodAnn = newAnn}+relocatePragmas m = pure m++-- | This function locates comments that are located before pragmas to the+-- module's EPA.+relocateCommentsBeforePragmas :: HsModule -> WithComments HsModule+relocateCommentsBeforePragmas m@HsModule {hsmodAnn = ann}+ | pragmaExists m = do+ newAnn <- insertCommentsByPos (< startPosOfPragmas) insertPriorComments ann+ pure m {hsmodAnn = newAnn}+ | otherwise = pure m+ where+ startPosOfPragmas = anchor $ getLoc $ head $ priorComments $ comments ann++-- | This function locates comments that are located before each element of+-- an export list.+relocateCommentsInExportList :: HsModule -> WithComments HsModule+relocateCommentsInExportList m@HsModule {hsmodExports = Just (L listSp@SrcSpanAnn {ann = EpAnn {entry = listAnn}} xs)} = do+ newExports <- mapM insertCommentsBeforeElement xs+ pure m {hsmodExports = Just (L listSp newExports)}+ where+ insertCommentsBeforeElement (L sp@SrcSpanAnn {ann = entryAnn@EpAnn {}} x) = do+ newEpa <-+ insertCommentsByPos+ (isBefore $ anchor $ entry entryAnn)+ insertPriorComments+ entryAnn+ pure $ L sp {ann = newEpa} x+ insertCommentsBeforeElement x = pure x+ isBefore anc comAnc =+ srcSpanStartLine comAnc < srcSpanStartLine anc &&+ realSrcSpanStart (anchor listAnn) < realSrcSpanStart comAnc+relocateCommentsInExportList x = pure x++-- | This function locates comments located before top-level declarations.+relocateCommentsBeforeTopLevelDecls :: HsModule -> WithComments HsModule+relocateCommentsBeforeTopLevelDecls = everywhereM (applyM f)+ where+ f epa@EpAnn {..} =+ insertCommentsByPos (isBefore $ anchor entry) insertPriorComments epa+ f EpAnnNotUsed = pure EpAnnNotUsed+ isBefore anc comAnc =+ srcSpanStartCol anc == 1 &&+ srcSpanStartCol comAnc == 1 &&+ srcSpanStartLine comAnc < srcSpanStartLine anc++-- | This function scans the given AST from bottom to top and locates+-- comments that are on the same line as the node. Comments are stored in+-- the 'followingComments' of 'EpaCommentsBalanced'.+relocateCommentsSameLine :: HsModule -> WithComments HsModule+relocateCommentsSameLine = everywhereMEpAnnsBackwards f+ where+ f epa@EpAnn {..} =+ insertCommentsByPos+ (isOnSameLine $ anchor entry)+ insertFollowingComments+ epa+ f EpAnnNotUsed = pure EpAnnNotUsed+ isOnSameLine anc comAnc =+ srcSpanStartLine comAnc == srcSpanStartLine anc &&+ srcSpanStartLine comAnc == srcSpanEndLine anc++-- | This function locates comments above the top-level declarations in+-- a 'where' clause in the topmost declaration.+relocateCommentsTopLevelWhereClause :: HsModule -> WithComments HsModule+relocateCommentsTopLevelWhereClause m@HsModule {..} = do+ hsmodDecls' <- mapM relocateCommentsDeclWhereClause hsmodDecls+ pure m {hsmodDecls = hsmodDecls'}+ where+ relocateCommentsDeclWhereClause (L l (ValD ext fb@(FunBind {fun_matches = MG {..}}))) = do+ mg_alts' <- mapM (mapM relocateCommentsMatch) mg_alts+ pure $ L l (ValD ext fb {fun_matches = MG {mg_alts = mg_alts', ..}})+ relocateCommentsDeclWhereClause x = pure x+ relocateCommentsMatch (L l match@Match {m_grhss = gs@GRHSs {grhssLocalBinds = (HsValBinds ext (ValBinds ext' binds sigs))}}) = do+ (binds', sigs') <- relocateCommentsBindsSigs binds sigs+ let localBinds = HsValBinds ext (ValBinds ext' binds' sigs')+ pure $ L l match {m_grhss = gs {grhssLocalBinds = localBinds}}+ relocateCommentsMatch x = pure x+ relocateCommentsBindsSigs ::+ LHsBindsLR GhcPs GhcPs+ -> [LSig GhcPs]+ -> WithComments (LHsBindsLR GhcPs GhcPs, [LSig GhcPs])+ relocateCommentsBindsSigs binds sigs = do+ bindsSigs' <- mapM addCommentsBeforeEpAnn bindsSigs+ pure (listToBag $ filterLBind bindsSigs', filterLSig bindsSigs')+ where+ bindsSigs = mkSortedLSigBindFamilyList sigs (bagToList binds) [] [] []+ addCommentsBeforeEpAnn (L (SrcSpanAnn epa@EpAnn {..} sp) x) = do+ cs <- get+ let (notAbove, above) =+ partitionAboveNotAbove (sortCommentsByLocation cs) entry+ epa' = epa {comments = insertPriorComments comments above}+ put notAbove+ pure $ L (SrcSpanAnn epa' sp) x+ addCommentsBeforeEpAnn x = pure x+ partitionAboveNotAbove cs sp =+ fst $+ foldr'+ (\c@(L l _) ((ls, rs), lastSpan) ->+ if anchor l `isAbove` anchor lastSpan+ then ((ls, c : rs), l)+ else ((c : ls, rs), lastSpan))+ (([], []), sp)+ cs+ isAbove comAnc anc =+ srcSpanStartCol comAnc == srcSpanStartCol anc &&+ srcSpanEndLine comAnc + 1 == srcSpanStartLine anc++-- | This function scans the given AST from bottom to top and locates+-- comments in the comment pool after each node on it.+relocateCommentsAfter :: HsModule -> WithComments HsModule+relocateCommentsAfter = everywhereMEpAnnsBackwards f+ where+ f epa@EpAnn {..} =+ insertCommentsByPos (isAfter $ anchor entry) insertFollowingComments epa+ f EpAnnNotUsed = pure EpAnnNotUsed+ isAfter anc comAnc = srcSpanEndLine anc <= srcSpanStartLine comAnc++-- | This function applies the given function to all 'EpAnn's.+applyM ::+ forall a. Typeable a+ => (forall b. EpAnn b -> WithComments (EpAnn b))+ -> (a -> WithComments a)+applyM f+ | App g _ <- typeRep @a+ , Just HRefl <- eqTypeRep g (typeRep @EpAnn) = f+ | otherwise = pure++-- | This function drains comments whose positions satisfy the given+-- predicate and inserts them to the given node using the given inserter.+insertCommentsByPos ::+ (RealSrcSpan -> Bool)+ -> (EpAnnComments -> [LEpaComment] -> EpAnnComments)+ -> EpAnn a+ -> WithComments (EpAnn a)+insertCommentsByPos cond = insertComments (cond . anchor . getLoc)++-- | This function drains comments that satisfy the given predicate and+-- inserts them to the given node using the given inserter.+insertComments ::+ (LEpaComment -> Bool)+ -> (EpAnnComments -> [LEpaComment] -> EpAnnComments)+ -> EpAnn a+ -> WithComments (EpAnn a)+insertComments cond inserter epa@EpAnn {..} = do+ coms <- drainComments cond+ pure $ epa {comments = inserter comments coms}+insertComments _ _ EpAnnNotUsed = pure EpAnnNotUsed++-- | This function inserts comments to `priorComments`.+insertPriorComments :: EpAnnComments -> [LEpaComment] -> EpAnnComments+insertPriorComments (EpaComments prior) cs =+ EpaComments (sortCommentsByLocation $ prior ++ cs)+insertPriorComments (EpaCommentsBalanced prior following) cs =+ EpaCommentsBalanced (sortCommentsByLocation $ prior ++ cs) following++-- | This function inserts comments to `followingComments`.+insertFollowingComments :: EpAnnComments -> [LEpaComment] -> EpAnnComments+insertFollowingComments (EpaComments prior) cs = EpaCommentsBalanced prior cs+insertFollowingComments (EpaCommentsBalanced prior following) cs =+ EpaCommentsBalanced prior (sortCommentsByLocation $ following ++ cs)++-- | This function drains comments that satisfy the given predicate.+drainComments :: (LEpaComment -> Bool) -> WithComments [LEpaComment]+drainComments cond = do+ coms <- get+ let (xs, others) = partition cond coms+ put others+ return xs++-- | 'everywhereM' but applies the given function to EPAs in order their+-- positions from backwards.+everywhereMEpAnnsBackwards ::+ Data a+ => (forall b. EpAnn b -> WithComments (EpAnn b))+ -> a+ -> WithComments a+everywhereMEpAnnsBackwards =+ everywhereMEpAnnsInOrder (flip compareEpaByEndPosition)++-- | 'everywhereM' but applies the given function to EPAs in order+-- specified by the given ordering function.+everywhereMEpAnnsInOrder ::+ Data a+ => (forall b c. EpAnn b -> EpAnn c -> Ordering)+ -> (forall b. EpAnn b -> WithComments (EpAnn b))+ -> a+ -> WithComments a+everywhereMEpAnnsInOrder cmp f hm =+ collectEpAnnsInOrderEverywhereMTraverses >>=+ applyFunctionInOrderEpAnnEndPositions >>=+ putModifiedEpAnnsToModule+ where+ collectEpAnnsInOrderEverywhereMTraverses+ -- This function uses 'everywhereM' to collect 'EpAnn's because they+ -- should be collected in the same order as 'putModifiedEpAnnsToModule'+ -- puts them to the AST.+ = reverse <$> execStateT (everywhereM collectEpAnnsST hm) []+ where+ collectEpAnnsST x = do+ modify $ collectEpAnns x+ pure x+ collectEpAnns ::+ forall a. Typeable a+ => a+ -> ([Wrapper] -> [Wrapper])+ collectEpAnns x+ -- If 'a' is 'EpAnn b' ('b' can be any type), wrap 'x' with a 'Wrapper'.+ | App g _ <- typeRep @a+ , Just HRefl <- eqTypeRep g (typeRep @EpAnn) = (Wrapper x :)+ | otherwise = id+ applyFunctionInOrderEpAnnEndPositions ::+ [Wrapper]+ -> WithComments [(Int, Wrapper)] -- ^ The first element of the tuple+ -- indicates how many 'Wrapper's were there before 'everywhereM'+ -- accessed the second element.+ applyFunctionInOrderEpAnnEndPositions anns =+ forM sorted $ \(i, Wrapper x) -> do+ x' <- f x+ pure (i, Wrapper x')+ where+ indexed = zip [0 :: Int ..] anns+ sorted = sortBy (\(_, Wrapper a) (_, Wrapper b) -> cmp a b) indexed+ putModifiedEpAnnsToModule anns = evalStateT (everywhereM setEpAnn hm) [0 ..]+ where+ setEpAnn ::+ forall a. Typeable a+ => a+ -> StateT [Int] WithComments a+ setEpAnn x+ -- This guard arm checks if 'a' is 'EpAnn b' ('b' can be any type).+ | App g g' <- typeRep @a+ , Just HRefl <- eqTypeRep g (typeRep @EpAnn) = do+ i <- gets head+ modify tail+ case lookup i anns of+ Just (Wrapper y)+ | App _ h <- typeOf y+ , Just HRefl <- eqTypeRep g' h -> pure y+ _ -> error "Unmatches"+ | otherwise = pure x++-- | This function sorts comments by its location.+sortCommentsByLocation :: [LEpaComment] -> [LEpaComment]+sortCommentsByLocation = sortBy (compare `on` anchor . getLoc)++-- | This function compares given EPAs by their end positions.+compareEpaByEndPosition :: EpAnn a -> EpAnn b -> Ordering+compareEpaByEndPosition (EpAnn a _ _) (EpAnn b _ _) =+ on compare (realSrcSpanEnd . anchor) a b+compareEpaByEndPosition EpAnnNotUsed EpAnnNotUsed = EQ+compareEpaByEndPosition _ EpAnnNotUsed = GT+compareEpaByEndPosition EpAnnNotUsed _ = LT
+ src/HIndent/Parse.hs view
@@ -0,0 +1,84 @@+{-# LANGUAGE CPP #-}++-- | Parsing and lexical analysis functions.+module HIndent.Parse+ ( parseModule+ , lexCode+ ) where++import Data.Maybe+import qualified GHC.Data.EnumSet as ES+import GHC.Data.FastString+import GHC.Data.StringBuffer+import GHC.Hs+import qualified GHC.LanguageExtensions as GLP+import qualified GHC.Parser as GLP+import GHC.Parser.Lexer hiding (buffer)+import GHC.Stack+import GHC.Types.SrcLoc+#if MIN_VERSION_ghc_lib_parser(9,4,1)+import GHC.Utils.Error+import GHC.Utils.Outputable hiding ((<>), empty, text)+#endif+-- | This function parses the given Haskell source code with the given file+-- path (if any) and parse options.+parseModule ::+ Maybe FilePath -> [GLP.Extension] -> String -> ParseResult HsModule+parseModule filepath exts src =+ case unP GLP.parseModule initState of+ POk s m -> POk s $ unLoc m+ PFailed s -> PFailed s+ where+ initState = initParserState (parserOptsFromExtensions exts) buffer location+ location =+ mkRealSrcLoc (mkFastString $ fromMaybe "<interactive>" filepath) 1 1+ buffer = stringToStringBuffer src++-- | Lexically analyze the given code.+lexCode :: HasCallStack => String -> [Token]+lexCode code+ | POk _ tokens <-+ lexTokenStream+ (parserOptsFromExtensions [])+ (stringToStringBuffer code)+ (mkRealSrcLoc (mkFastString "<interactive>") 1 1) = fmap unLoc tokens+ | otherwise = error "Failed to lex the code."++-- | This function generates a 'ParserOpts' from te given extension.+--+-- The 'StarIsType' extension is always enabled to compile a code using+-- kinds like '* -> *'.+parserOptsFromExtensions :: [GLP.Extension] -> ParserOpts+#if MIN_VERSION_ghc_lib_parser(9,4,1)+parserOptsFromExtensions opts =+ mkParserOpts+ opts'+ diagOpts+ [] -- There are no supported languages and extensions (this list is used only in error messages)+ False -- Safe imports are off.+ False -- Haddock comments are treated as normal comments.+ True -- Comments are kept in an AST.+ False -- Do not update the internal position of a comment.+ where+ opts' = ES.fromList $ GLP.StarIsType : opts+ diagOpts =+ DiagOpts+ { diag_warning_flags = ES.empty+ , diag_fatal_warning_flags = ES.empty+ , diag_warn_is_error = False+ , diag_reverse_errors = False+ , diag_max_errors = Nothing+ , diag_ppr_ctx = defaultSDocContext+ }+#else+parserOptsFromExtensions opts =+ mkParserOpts+ ES.empty -- No compiler warnings are enabled.+ opts'+ False -- Safe imports are off.+ False -- Haddock comments are treated as normal comments.+ True -- Comments are kept in an AST.+ False -- Do not update the internal position of a comment.+ where+ opts' = ES.fromList $ GLP.StarIsType : opts+#endif
+ src/HIndent/Path/Find.hs view
@@ -0,0 +1,40 @@+{-# LANGUAGE DataKinds #-}++-- | Finding files.+-- Lifted from Stack.+module HIndent.Path.Find+ ( findFileUp+ ) where++import Control.Monad.Catch+import Control.Monad.IO.Class+import Data.List+import Path+import Path.IO hiding (findFiles)++-- | Find the location of a file matching the given predicate.+findFileUp ::+ (MonadIO m, MonadThrow m)+ => Path Abs Dir -- ^ Start here.+ -> (Path Abs File -> Bool) -- ^ Predicate to match the file.+ -> Maybe (Path Abs Dir) -- ^ Do not ascend above this directory.+ -> m (Maybe (Path Abs File)) -- ^ Absolute file path.+findFileUp = findPathUp snd++-- | Find the location of a path matching the given predicate.+findPathUp ::+ (MonadIO m, MonadThrow m)+ => (([Path Abs Dir], [Path Abs File]) -> [Path Abs t])+ -- ^ Choose path type from pair.+ -> Path Abs Dir -- ^ Start here.+ -> (Path Abs t -> Bool) -- ^ Predicate to match the path.+ -> Maybe (Path Abs Dir) -- ^ Do not ascend above this directory.+ -> m (Maybe (Path Abs t)) -- ^ Absolute path.+findPathUp pathType dir p upperBound = do+ entries <- listDir dir+ case find p (pathType entries) of+ Just path -> return (Just path)+ Nothing+ | Just dir == upperBound -> return Nothing+ | parent dir == dir -> return Nothing+ | otherwise -> findPathUp pathType (parent dir) p upperBound
+ src/HIndent/Pragma.hs view
@@ -0,0 +1,64 @@+{-# LANGUAGE CPP #-}++-- | Pragma-related functions.+module HIndent.Pragma+ ( extractPragmasFromCode+ , extractPragmaNameAndElement+ , pragmaRegex+ ) where++import Data.Maybe+import GHC.Parser.Lexer+import HIndent.Parse+import Text.Regex.TDFA hiding (empty)++-- | Extracts all pragmas from the given source code.+--+-- FIXME: The function is slow because it lexicographically analyzes the+-- given source code. An alternative way is to use regular expressions.+-- However, this method cannot determine if what appears to be a pragma is+-- really a pragma, or requires complex regular expressions. For example,+-- @{-\n\n{-# LANGUAGE CPP #-}\n\n-}@ is not a pragma, but is likely to be+-- recognized as such.+extractPragmasFromCode :: String -> [(String, String)] -- ^ [(Pragma's name (e.g., @"LANGUAGE"@), Pragma's element (e.g., @"CPP, DerivingVia"@))]+extractPragmasFromCode =+ mapMaybe extractPragmaNameAndElement . mapMaybe extractBlockComment . lexCode+ where+ extractBlockComment (ITblockComment c _) = Just c+ extractBlockComment _ = Nothing++-- | Extracts the pragma's name and its element from the given pragma.+--+-- This function returns a 'Nothing' if it fails to extract them.+extractPragmaNameAndElement :: String -> Maybe (String, String) -- ^ [(Pragma's name (e.g., @"LANGUAGE"@), Pragma's element (e.g., @"CPP, DerivingVia"@))]+extractPragmaNameAndElement l+ | (_, _, _, [name, element]) <-+ match pragmaRegex l :: (String, String, String, [String]) =+ Just (name, element)+extractPragmaNameAndElement _ = Nothing++-- | A regex to match against a pragma.+pragmaRegex :: Regex+pragmaRegex =+ makeRegexOpts+ compOption+ execOption+ "^{-#[[:space:]]*([^[:space:]]+)[[:space:]]+([^#]+)#-}"++-- | The option for matching against a pragma.+execOption :: ExecOption+execOption = ExecOption {captureGroups = True}++-- | The option for matching against a pragma.+--+-- 'multiline' is set to 'False' to match against multiline pragmas, e.g.,+-- @{-# LANGUAGE CPP\nOverloadedStrings #-}@.+compOption :: CompOption+compOption =+ CompOption+ { caseSensitive = True+ , multiline = False+ , rightAssoc = True+ , newSyntax = True+ , lastStarGreedy = True+ }
src/HIndent/Pretty.hs view
@@ -1,2151 +1,2239 @@-{-# LANGUAGE ScopedTypeVariables #-}-{-# LANGUAGE LambdaCase #-}-{-# LANGUAGE TupleSections #-}-{-# LANGUAGE FlexibleInstances #-}-{-# LANGUAGE TypeSynonymInstances #-}-{-# LANGUAGE FlexibleContexts #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE CPP #-}---- | Pretty printing.--module HIndent.Pretty- (pretty)- where--import Control.Applicative-import Control.Monad.State.Strict hiding (state)-import qualified Data.ByteString.Builder as S-import Data.Foldable (for_, forM_, traverse_)-import Data.Int-import Data.List-import Data.Maybe-import Data.Monoid ((<>))-import Data.Typeable-import HIndent.Types-import qualified Language.Haskell.Exts as P-import Language.Haskell.Exts.SrcLoc-import Language.Haskell.Exts.Syntax-import Prelude hiding (exp)------------------------------------------------------------------------------------- * Pretty printing class---- | Pretty printing class.-class (Annotated ast,Typeable ast) => Pretty ast where- prettyInternal :: ast NodeInfo -> Printer ()---- | Pretty print including comments.-pretty :: (Pretty ast,Show (ast NodeInfo))- => ast NodeInfo -> Printer ()-pretty a = do- mapM_- (\c' -> do- case c' of- CommentBeforeLine _ c -> do- case c of- EndOfLine s -> write ("--" ++ s)- MultiLine s -> write ("{-" ++ s ++ "-}")- newline- _ -> return ())- comments- prettyInternal a- mapM_- (\(i, c') -> do- case c' of- CommentSameLine spn c -> do- col <- gets psColumn- if col == 0- then do- -- write comment keeping original indentation- let col' = fromIntegral $ srcSpanStartColumn spn - 1- column col' $ writeComment c- else do- space- writeComment c- CommentAfterLine spn c -> do- when (i == 0) newline- -- write comment keeping original indentation- let col = fromIntegral $ srcSpanStartColumn spn - 1- column col $ writeComment c- _ -> return ())- (zip [0 :: Int ..] comments)- where- comments = nodeInfoComments (ann a)- writeComment =- \case- EndOfLine cs -> do- write ("--" ++ cs)- modify- (\s ->- s- { psEolComment = True- })- MultiLine cs -> do- write ("{-" ++ cs ++ "-}")- modify- (\s ->- s- { psEolComment = True- })---- | Pretty print using HSE's own printer. The 'P.Pretty' class here--- is HSE's.-pretty' :: (Pretty ast,P.Pretty (ast SrcSpanInfo))- => ast NodeInfo -> Printer ()-pretty' = write . P.prettyPrint . fmap nodeInfoSpan------------------------------------------------------------------------------------- * Combinators---- | Increase indentation level by n spaces for the given printer.-indented :: Int64 -> Printer a -> Printer a-indented i p =- do level <- gets psIndentLevel- modify (\s -> s {psIndentLevel = level + i})- m <- p- modify (\s -> s {psIndentLevel = level})- return m--indentedBlock :: Printer a -> Printer a-indentedBlock p =- do indentSpaces <- getIndentSpaces- indented indentSpaces p---- | Print all the printers separated by spaces.-spaced :: [Printer ()] -> Printer ()-spaced = inter space---- | Print all the printers separated by commas.-commas :: [Printer ()] -> Printer ()-commas = inter (write ", ")---- | Print all the printers separated by sep.-inter :: Printer () -> [Printer ()] -> Printer ()-inter sep ps =- foldr- (\(i,p) next ->- depend- (do p- if i < length ps- then sep- else return ())- next)- (return ())- (zip [1 ..] ps)---- | Print all the printers separated by newlines.-lined :: [Printer ()] -> Printer ()-lined ps = sequence_ (intersperse newline ps)---- | Print all the printers separated newlines and optionally a line--- prefix.-prefixedLined :: String -> [Printer ()] -> Printer ()-prefixedLined pref ps' =- case ps' of- [] -> return ()- (p:ps) ->- do p- indented (fromIntegral- (length pref *- (-1)))- (mapM_ (\p' ->- do newline- depend (write pref) p')- ps)---- | Set the (newline-) indent level to the given column for the given--- printer.-column :: Int64 -> Printer a -> Printer a-column i p =- do level <- gets psIndentLevel- modify (\s -> s {psIndentLevel = i})- m <- p- modify (\s -> s {psIndentLevel = level})- return m---- | Output a newline.-newline :: Printer ()-newline =- do write "\n"- modify (\s -> s {psNewline = True})---- | Set the context to a case context, where RHS is printed with -> .-withCaseContext :: Bool -> Printer a -> Printer a-withCaseContext bool pr =- do original <- gets psInsideCase- modify (\s -> s {psInsideCase = bool})- result <- pr- modify (\s -> s {psInsideCase = original})- return result---- | Get the current RHS separator, either = or -> .-rhsSeparator :: Printer ()-rhsSeparator =- do inCase <- gets psInsideCase- if inCase- then write "->"- else write "="---- | Make the latter's indentation depend upon the end column of the--- former.-depend :: Printer () -> Printer b -> Printer b-depend maker dependent =- do state' <- get- maker- st <- get- col <- gets psColumn- if psLine state' /= psLine st || psColumn state' /= psColumn st- then column col dependent- else dependent---- | Wrap.-wrap :: String -> String -> Printer a -> Printer a-wrap open close p = depend (write open) $ p <* write close---- | Wrap in parens.-parens :: Printer a -> Printer a-parens = wrap "(" ")"---- | Wrap in braces.-braces :: Printer a -> Printer a-braces = wrap "{" "}"---- | Wrap in brackets.-brackets :: Printer a -> Printer a-brackets = wrap "[" "]"---- | Write a space.-space :: Printer ()-space = write " "---- | Write a comma.-comma :: Printer ()-comma = write ","---- | Write an integral.-int :: Integer -> Printer ()-int = write . show---- | Write out a string, updating the current position information.-write :: String -> Printer ()-write x =- do eol <- gets psEolComment- hardFail <- gets psFitOnOneLine- let addingNewline = eol && x /= "\n"- when addingNewline newline- state <- get- let writingNewline = x == "\n"- out :: String- out =- if psNewline state && not writingNewline- then (replicate (fromIntegral (psIndentLevel state))- ' ') <>- x- else x- psColumn' =- if additionalLines > 0- then fromIntegral (length (concat (take 1 (reverse srclines))))- else psColumn state + fromIntegral (length out)- when- hardFail- (guard- (additionalLines == 0 &&- (psColumn' <= configMaxColumns (psConfig state))))- modify (\s ->- s {psOutput = psOutput state <> S.stringUtf8 out- ,psNewline = False- ,psLine = psLine state + fromIntegral additionalLines- ,psEolComment= False- ,psColumn = psColumn'})- where srclines = lines x- additionalLines =- length (filter (== '\n') x)---- | Write a string.-string :: String -> Printer ()-string = write---- | Indent spaces, e.g. 2.-getIndentSpaces :: Printer Int64-getIndentSpaces =- gets (configIndentSpaces . psConfig)---- | Play with a printer and then restore the state to what it was--- before.-sandbox :: Printer a -> Printer (a,PrintState)-sandbox p =- do orig <- get- a <- p- new <- get- put orig- return (a,new)---- | Render a type with a context, or not.-withCtx :: (Pretty ast,Show (ast NodeInfo))- => Maybe (ast NodeInfo) -> Printer b -> Printer b-withCtx Nothing m = m-withCtx (Just ctx) m =- do pretty ctx- write " =>"- newline- m---- | Maybe render an overlap definition.-maybeOverlap :: Maybe (Overlap NodeInfo) -> Printer ()-maybeOverlap =- maybe (return ())- (\p ->- pretty p >>- space)---- | Swing the second printer below and indented with respect to the first.-swing :: Printer () -> Printer b -> Printer ()-swing a b =- do orig <- gets psIndentLevel- a- mst <- fitsOnOneLine (do space- b)- case mst of- Just st -> put st- Nothing -> do newline- indentSpaces <- getIndentSpaces- _ <- column (orig + indentSpaces) b- return ()---- | Swing the second printer below and indented with respect to the first by--- the specified amount.-swingBy :: Int64 -> Printer() -> Printer b -> Printer b-swingBy i a b =- do orig <- gets psIndentLevel- a- newline- column (orig + i) b------------------------------------------------------------------------------------- * Instances--instance Pretty Context where- prettyInternal ctx@(CxTuple _ asserts) = do- mst <- fitsOnOneLine (parens (inter (comma >> space) (map pretty asserts)))- case mst of- Nothing -> context ctx- Just st -> put st- prettyInternal ctx = context ctx--instance Pretty Pat where- prettyInternal x =- case x of- PLit _ sign l -> pretty sign >> pretty l- PNPlusK _ n k ->- depend (do pretty n- write "+")- (int k)- PInfixApp _ a op b ->- case op of- Special{} ->- depend (pretty a)- (depend (prettyInfixOp op)- (pretty b))- _ ->- depend (do pretty a- space)- (depend (do prettyInfixOp op- space)- (pretty b))- PApp _ f args ->- depend (do pretty f- unless (null args) space)- (spaced (map pretty args))- PTuple _ boxed pats ->- depend (write (case boxed of- Unboxed -> "(# "- Boxed -> "("))- (do commas (map pretty pats)- write (case boxed of- Unboxed -> " #)"- Boxed -> ")"))- PList _ ps ->- brackets (commas (map pretty ps))- PParen _ e -> parens (pretty e)- PRec _ qname fields -> do- let horVariant = do- pretty qname- space- braces $ commas $ map pretty fields- verVariant =- depend (pretty qname >> space) $ do- case fields of- [] -> write "{}"- [field] -> braces $ pretty field- _ -> do- depend (write "{") $- prefixedLined "," $ map (depend space . pretty) fields- newline- write "}"- horVariant `ifFitsOnOneLineOrElse` verVariant- PAsPat _ n p ->- depend (do pretty n- write "@")- (pretty p)- PWildCard _ -> write "_"- PIrrPat _ p ->- depend (write "~")- (pretty p)- PatTypeSig _ p ty ->- depend (do pretty p- write " :: ")- (pretty ty)- PViewPat _ e p ->- depend (do pretty e- write " -> ")- (pretty p)- PQuasiQuote _ name str -> quotation name (string str)- PBangPat _ p ->- depend (write "!")- (pretty p)- PRPat{} -> pretty' x- PXTag{} -> pretty' x- PXETag{} -> pretty' x- PXPcdata{} -> pretty' x- PXPatTag{} -> pretty' x- PXRPats{} -> pretty' x- PVar{} -> pretty' x- PSplice _ s -> pretty s---- | Pretty infix application of a name (identifier or symbol).-prettyInfixName :: Name NodeInfo -> Printer ()-prettyInfixName (Ident _ n) = do write "`"; string n; write "`";-prettyInfixName (Symbol _ s) = string s---- | Pretty print a name for being an infix operator.-prettyInfixOp :: QName NodeInfo -> Printer ()-prettyInfixOp x =- case x of- Qual _ mn n ->- case n of- Ident _ i -> do write "`"; pretty mn; write "."; string i; write "`";- Symbol _ s -> do pretty mn; write "."; string s;- UnQual _ n -> prettyInfixName n- Special _ s -> pretty s--prettyQuoteName :: Name NodeInfo -> Printer ()-prettyQuoteName x =- case x of- Ident _ i -> string i- Symbol _ s -> string ("(" ++ s ++ ")")--instance Pretty Type where- prettyInternal = typ--instance Pretty Exp where- prettyInternal = exp---- | Render an expression.-exp :: Exp NodeInfo -> Printer ()--- | Do after lambda should swing.-exp (Lambda _ pats (Do l stmts)) =- do- mst <-- fitsOnOneLine- (do write "\\"- spaced (map pretty pats)- write " -> "- pretty (Do l stmts))- case mst of- Nothing -> swing (do write "\\"- spaced (map pretty pats)- write " -> do")- (lined (map pretty stmts))- Just st -> put st--- | Space out tuples.-exp (Tuple _ boxed exps) = do- let horVariant = parensHorB boxed $ inter (write ", ") (map pretty exps)- verVariant = parensVerB boxed $ prefixedLined "," (map (depend space . pretty) exps)- mst <- fitsOnOneLine horVariant- case mst of- Nothing -> verVariant- Just st -> put st- where- parensHorB Boxed = parens- parensHorB Unboxed = wrap "(# " " #)"- parensVerB Boxed = parens- parensVerB Unboxed = wrap "(#" "#)"--- | Space out tuples.-exp (TupleSection _ boxed mexps) = do- let horVariant = parensHorB boxed $ inter (write ", ") (map (maybe (return ()) pretty) mexps)- verVariant =- parensVerB boxed $ prefixedLined "," (map (maybe (return ()) (depend space . pretty)) mexps)- mst <- fitsOnOneLine horVariant- case mst of- Nothing -> verVariant- Just st -> put st- where- parensHorB Boxed = parens- parensHorB Unboxed = wrap "(# " " #)"- parensVerB Boxed = parens- parensVerB Unboxed = wrap "(#" "#)"-exp (UnboxedSum{}) = error "FIXME: No implementation for UnboxedSum."--- | Infix apps, same algorithm as ChrisDone at the moment.-exp e@(InfixApp _ a op b) =- infixApp e a op b Nothing--- | If bodies are indented 4 spaces. Handle also do-notation.-exp (If _ if' then' else') =- do depend (write "if ")- (pretty if')- newline- indentSpaces <- getIndentSpaces- indented indentSpaces- (do branch "then " then'- newline- branch "else " else')- -- Special handling for do.- where branch str e =- case e of- Do _ stmts ->- do write str- write "do"- newline- indentSpaces <- getIndentSpaces- indented indentSpaces (lined (map pretty stmts))- _ ->- depend (write str)- (pretty e)--- | Render on one line, or otherwise render the op with the arguments--- listed line by line.-exp (App _ op arg) = do- let flattened = flatten op ++ [arg]- mst <- fitsOnOneLine (spaced (map pretty flattened))- case mst of- Nothing -> do- let (f:args) = flattened- col <- gets psColumn- spaces <- getIndentSpaces- pretty f- col' <- gets psColumn- let diff = col' - col - if col == 0 then spaces else 0- if diff + 1 <= spaces- then space- else newline- spaces' <- getIndentSpaces- indented spaces' (lined (map pretty args))- Just st -> put st- where- flatten (App label' op' arg') = flatten op' ++ [amap (addComments label') arg']- flatten x = [x]- addComments n1 n2 =- n2- { nodeInfoComments = nub (nodeInfoComments n2 ++ nodeInfoComments n1)- }--- | Space out commas in list.-exp (List _ es) =- do mst <- fitsOnOneLine p- case mst of- Nothing -> do- depend- (write "[")- (prefixedLined "," (map (depend space . pretty) es))- newline- write "]"- Just st -> put st- where p =- brackets (inter (write ", ")- (map pretty es))-exp (RecUpdate _ exp' updates) = recUpdateExpr (pretty exp') updates-exp (RecConstr _ qname updates) = recUpdateExpr (pretty qname) updates-exp (Let _ binds e) =- depend (write "let ")- (do pretty binds- newline- indented (-3) (depend (write "in ")- (pretty e)))-exp (ListComp _ e qstmt) = do- let horVariant = brackets $ do- pretty e- write " | "- commas $ map pretty qstmt- verVariant = do- write "[ "- pretty e- newline- depend (write "| ") $ prefixedLined ", " $ map pretty qstmt- newline- write "]"- horVariant `ifFitsOnOneLineOrElse` verVariant--exp (ParComp _ e qstmts) = do- let horVariant = brackets $ do- pretty e- for_ qstmts $ \qstmt -> do- write " | "- commas $ map pretty qstmt- verVariant = do- depend (write "[ ") $ pretty e- newline- for_ qstmts $ \qstmt -> do- depend (write "| ") $ prefixedLined ", " $ map pretty qstmt- newline- write "]"- horVariant `ifFitsOnOneLineOrElse` verVariant--exp (TypeApp _ t) = do- write "@"- pretty t-exp (NegApp _ e) =- depend (write "-")- (pretty e)-exp (Lambda _ ps e) = do- write "\\"- spaced [ do case (i, x) of- (0, PIrrPat {}) -> space- (0, PBangPat {}) -> space- _ -> return ()- pretty x- | (i, x) <- zip [0 :: Int ..] ps- ]- swing (write " ->") $ pretty e-exp (Paren _ e) = parens (pretty e)-exp (Case _ e alts) =- do depend (write "case ")- (do pretty e- write " of")- if null alts- then write " {}"- else do newline- indentedBlock (lined (map (withCaseContext True . pretty) alts))-exp (Do _ stmts) =- depend (write "do ")- (lined (map pretty stmts))-exp (MDo _ stmts) =- depend (write "mdo ")- (lined (map pretty stmts))-exp (LeftSection _ e op) =- parens (depend (do pretty e- space)- (pretty op))-exp (RightSection _ e op) =- parens (depend (do pretty e- space)- (pretty op))-exp (EnumFrom _ e) =- brackets (do pretty e- write " ..")-exp (EnumFromTo _ e f) =- brackets (depend (do pretty e- write " .. ")- (pretty f))-exp (EnumFromThen _ e t) =- brackets (depend (do pretty e- write ",")- (do pretty t- write " .."))-exp (EnumFromThenTo _ e t f) =- brackets (depend (do pretty e- write ",")- (depend (do pretty t- write " .. ")- (pretty f)))-exp (ExpTypeSig _ e t) =- depend (do pretty e- write " :: ")- (pretty t)-exp (VarQuote _ x) =- depend (write "'")- (pretty x)-exp (TypQuote _ x) =- depend (write "''")- (pretty x)-exp (BracketExp _ b) = pretty b-exp (SpliceExp _ s) = pretty s-exp (QuasiQuote _ n s) = quotation n (string s)-exp (LCase _ alts) =- do write "\\case"- if null alts- then write " {}"- else do newline- indentedBlock (lined (map (withCaseContext True . pretty) alts))-exp (MultiIf _ alts) =- withCaseContext- True- (depend- (write "if ")- (lined- (map- (\p -> do- write "| "- prettyG p)- alts)))- where- prettyG (GuardedRhs _ stmts e) = do- indented- 1- (do (lined (map- (\(i,p) -> do- unless (i == 1)- space- pretty p- unless (i == length stmts)- (write ","))- (zip [1..] stmts))))- swing (write " " >> rhsSeparator) (pretty e)-exp (Lit _ lit) = prettyInternal lit-exp (Var _ q) = pretty q-exp (IPVar _ q) = pretty q-exp (Con _ q) = pretty q--exp x@XTag{} = pretty' x-exp x@XETag{} = pretty' x-exp x@XPcdata{} = pretty' x-exp x@XExpTag{} = pretty' x-exp x@XChildTag{} = pretty' x-exp x@CorePragma{} = pretty' x-exp x@SCCPragma{} = pretty' x-exp x@GenPragma{} = pretty' x-exp x@Proc{} = pretty' x-exp x@LeftArrApp{} = pretty' x-exp x@RightArrApp{} = pretty' x-exp x@LeftArrHighApp{} = pretty' x-exp x@RightArrHighApp{} = pretty' x-exp x@ParArray{} = pretty' x-exp x@ParArrayFromTo{} = pretty' x-exp x@ParArrayFromThenTo{} = pretty' x-exp x@ParArrayComp{} = pretty' x-exp (OverloadedLabel _ label) = string ('#' : label)--instance Pretty IPName where- prettyInternal = pretty'--instance Pretty Stmt where- prettyInternal =- stmt--instance Pretty QualStmt where- prettyInternal x =- case x of- QualStmt _ s -> pretty s- ThenTrans _ s -> do- write "then "- pretty s- ThenBy _ s t -> do- write "then "- pretty s- write " by "- pretty t- GroupBy _ s -> do- write "then group by "- pretty s- GroupUsing _ s -> do- write "then group using "- pretty s- GroupByUsing _ s t -> do- write "then group by "- pretty s- write " using "- pretty t--instance Pretty Decl where- prettyInternal = decl'---- | Render a declaration.-decl :: Decl NodeInfo -> Printer ()-decl (InstDecl _ moverlap dhead decls) =- do depend (write "instance ")- (depend (maybeOverlap moverlap)- (depend (pretty dhead)- (unless (null (fromMaybe [] decls))- (write " where"))))- unless (null (fromMaybe [] decls))- (do newline- indentedBlock (lined (map pretty (fromMaybe [] decls))))-decl (SpliceDecl _ e) = pretty e-decl (TypeSig _ names ty) =- depend (do inter (write ", ")- (map pretty names)- write " :: ")- (pretty ty)-decl (FunBind _ matches) =- lined (map pretty matches)-decl (ClassDecl _ ctx dhead fundeps decls) =- do classHead ctx dhead fundeps decls- unless (null (fromMaybe [] decls))- (do newline- indentedBlock (lined (map pretty (fromMaybe [] decls))))-decl (TypeDecl _ typehead typ') = do- write "type "- pretty typehead- ifFitsOnOneLineOrElse- (depend (write " = ") (pretty typ'))- (do newline- indentedBlock (depend (write " = ") (pretty typ')))-decl (TypeFamDecl _ declhead result injectivity) = do- write "type family "- pretty declhead- case result of- Just r -> do- space- let sep = case r of- KindSig _ _ -> "::"- TyVarSig _ _ -> "="- write sep- space- pretty r- Nothing -> return ()- case injectivity of- Just i -> do- space- pretty i- Nothing -> return ()-decl (ClosedTypeFamDecl _ declhead result injectivity instances) = do- write "type family "- pretty declhead- for_ result $ \r -> do- space- let sep = case r of- KindSig _ _ -> "::"- TyVarSig _ _ -> "="- write sep- space- pretty r- for_ injectivity $ \i -> do- space- pretty i- space- write "where"- newline- indentedBlock (lined (map pretty instances))-decl (DataDecl _ dataornew ctx dhead condecls mderivs) =- do depend (do pretty dataornew- space)- (withCtx ctx- (do pretty dhead- case condecls of- [] -> return ()- [x] -> singleCons x- xs -> multiCons xs))- indentSpaces <- getIndentSpaces- forM_ mderivs $ \deriv -> newline >> column indentSpaces (pretty deriv)- where singleCons x =- do write " ="- indentSpaces <- getIndentSpaces- column indentSpaces- (do newline- pretty x)- multiCons xs =- do newline- indentSpaces <- getIndentSpaces- column indentSpaces- (depend (write "=")- (prefixedLined "|"- (map (depend space . pretty) xs)))--decl (GDataDecl _ dataornew ctx dhead mkind condecls mderivs) =- do depend (pretty dataornew >> space)- (withCtx ctx- (do pretty dhead- case mkind of- Nothing -> return ()- Just kind -> do write " :: "- pretty kind- write " where"))- indentedBlock $ do- case condecls of- [] -> return ()- _ -> do- newline- lined (map pretty condecls)- forM_ mderivs $ \deriv -> newline >> pretty deriv--decl (InlineSig _ inline active name) = do- write "{-# "-- unless inline $ write "NO"- write "INLINE "- case active of- Nothing -> return ()- Just (ActiveFrom _ x) -> write ("[" ++ show x ++ "] ")- Just (ActiveUntil _ x) -> write ("[~" ++ show x ++ "] ")- pretty name-- write " #-}"-decl (MinimalPragma _ (Just formula)) =- wrap "{-# " " #-}" $ do- depend (write "MINIMAL ") $ pretty formula-decl (ForImp _ callconv maybeSafety maybeName name ty) = do- string "foreign import "- pretty' callconv >> space- case maybeSafety of- Just safety -> pretty' safety >> space- Nothing -> return ()- case maybeName of- Just namestr -> string (show namestr) >> space- Nothing -> return ()- pretty' name- tyline <- fitsOnOneLine $ do string " :: "- pretty' ty- case tyline of- Just line -> put line- Nothing -> do newline- indentedBlock $ do string ":: "- pretty' ty-decl (ForExp _ callconv maybeName name ty) = do- string "foreign export "- pretty' callconv >> space- case maybeName of- Just namestr -> string (show namestr) >> space- Nothing -> return ()- pretty' name- tyline <- fitsOnOneLine $ do string " :: "- pretty' ty- case tyline of- Just line -> put line- Nothing -> do newline- indentedBlock $ do string ":: "- pretty' ty-decl x' = pretty' x'--classHead- :: Maybe (Context NodeInfo)- -> DeclHead NodeInfo- -> [FunDep NodeInfo]- -> Maybe [ClassDecl NodeInfo]- -> Printer ()-classHead ctx dhead fundeps decls = shortHead `ifFitsOnOneLineOrElse` longHead- where- shortHead =- depend- (write "class ")- (withCtx ctx $- depend- (pretty dhead)- (depend (unless (null fundeps) (write " | " >> commas (map pretty fundeps)))- (unless (null (fromMaybe [] decls)) (write " where"))))- longHead = do- depend (write "class ") (withCtx ctx $ pretty dhead)- newline- indentedBlock $ do- unless (null fundeps) $ do- depend (write "| ") (prefixedLined ", " $ map pretty fundeps)- newline- unless (null (fromMaybe [] decls)) (write "where")--instance Pretty TypeEqn where- prettyInternal (TypeEqn _ in_ out_) = do- pretty in_- write " = "- pretty out_--instance Pretty Deriving where- prettyInternal (Deriving _ strategy heads) =- depend (write "deriving" >> space >> writeStrategy) $ do- let heads' =- if length heads == 1- then map stripParens heads- else heads- maybeDerives <- fitsOnOneLine $ parens (commas (map pretty heads'))- case maybeDerives of- Nothing -> formatMultiLine heads'- Just derives -> put derives- where- writeStrategy = case strategy of- Nothing -> return ()- Just st -> pretty st >> space- stripParens (IParen _ iRule) = stripParens iRule- stripParens x = x- formatMultiLine derives = do- depend (write "( ") $ prefixedLined ", " (map pretty derives)- newline- write ")"--instance Pretty DerivStrategy where- prettyInternal x =- case x of- DerivStock _ -> return ()- DerivAnyclass _ -> write "anyclass"- DerivNewtype _ -> write "newtype"--instance Pretty Alt where- prettyInternal x =- case x of- Alt _ p galts mbinds ->- do pretty p- pretty galts- case mbinds of- Nothing -> return ()- Just binds ->- do newline- indentedBlock (depend (write "where ")- (pretty binds))--instance Pretty Asst where- prettyInternal x =- case x of- IParam _ name ty -> do- pretty name- write " :: "- pretty ty- ParenA _ asst -> parens (pretty asst)-#if MIN_VERSION_haskell_src_exts(1,21,0)- TypeA _ ty -> pretty ty-#else- ClassA _ name types -> spaced (pretty name : map pretty types)- i@InfixA {} -> pretty' i- EqualP _ a b -> do- pretty a- write " ~ "- pretty b- AppA _ name tys ->- spaced (pretty name : map pretty tys)- WildCardA _ name ->- case name of- Nothing -> write "_"- Just n -> do- write "_"- pretty n-#endif--instance Pretty BangType where- prettyInternal x =- case x of- BangedTy _ -> write "!"- LazyTy _ -> write "~"- NoStrictAnnot _ -> return ()--instance Pretty Unpackedness where- prettyInternal (Unpack _) = write "{-# UNPACK #-}"- prettyInternal (NoUnpack _) = write "{-# NOUNPACK #-}"- prettyInternal (NoUnpackPragma _) = return ()--instance Pretty Binds where- prettyInternal x =- case x of- BDecls _ ds -> lined (map pretty ds)- IPBinds _ i -> lined (map pretty i)--instance Pretty ClassDecl where- prettyInternal x =- case x of- ClsDecl _ d -> pretty d- ClsDataFam _ ctx h mkind ->- depend- (write "data ")- (withCtx- ctx- (do pretty h- (case mkind of- Nothing -> return ()- Just kind -> do- write " :: "- pretty kind)))- ClsTyFam _ h msig minj ->- depend- (write "type ")- (depend- (pretty h)- (depend- (traverse_- (\case- KindSig _ kind -> write " :: " >> pretty kind- TyVarSig _ tyVarBind -> write " = " >> pretty tyVarBind)- msig)- (traverse_ (\inj -> space >> pretty inj) minj)))- ClsTyDef _ (TypeEqn _ this that) -> do- write "type "- pretty this- write " = "- pretty that- ClsDefSig _ name ty -> do- write "default "- pretty name- write " :: "- pretty ty--instance Pretty ConDecl where- prettyInternal x =- conDecl x--instance Pretty FieldDecl where- prettyInternal (FieldDecl _ names ty) =- depend (do commas (map pretty names)- write " :: ")- (pretty ty)--instance Pretty FieldUpdate where- prettyInternal x =- case x of- FieldUpdate _ n e ->- swing (do pretty n- write " =")- (pretty e)- FieldPun _ n -> pretty n- FieldWildcard _ -> write ".."--instance Pretty GuardedRhs where- prettyInternal =- guardedRhs--instance Pretty InjectivityInfo where- prettyInternal x = pretty' x--instance Pretty InstDecl where- prettyInternal i =- case i of- InsDecl _ d -> pretty d- InsType _ name ty ->- depend (do write "type "- pretty name- write " = ")- (pretty ty)- _ -> pretty' i--instance Pretty Match where- prettyInternal = match- {-case x of- Match _ name pats rhs' mbinds ->- do depend (do pretty name- space)- (spaced (map pretty pats))- withCaseContext False (pretty rhs')- case mbinds of- Nothing -> return ()- Just binds ->- do newline- indentedBlock (depend (write "where ")- (pretty binds))- InfixMatch _ pat1 name pats rhs' mbinds ->- do depend (do pretty pat1- space- prettyInfixName name)- (do space- spaced (map pretty pats))- withCaseContext False (pretty rhs')- case mbinds of- Nothing -> return ()- Just binds ->- do newline- indentedBlock (depend (write "where ")- (pretty binds))-}--instance Pretty PatField where- prettyInternal x =- case x of- PFieldPat _ n p ->- depend (do pretty n- write " = ")- (pretty p)- PFieldPun _ n -> pretty n- PFieldWildcard _ -> write ".."--instance Pretty QualConDecl where- prettyInternal x =- case x of- QualConDecl _ tyvars ctx d ->- depend (unless (null (fromMaybe [] tyvars))- (do write "forall "- spaced (map pretty (reverse (fromMaybe [] tyvars)))- write ". "))- (withCtx ctx- (pretty d))--instance Pretty GadtDecl where-#if MIN_VERSION_haskell_src_exts(1,21,0)- prettyInternal (GadtDecl _ name _ _ fields t) =-#else- prettyInternal (GadtDecl _ name fields t) =-#endif- horVar `ifFitsOnOneLineOrElse` verVar- where- fields' p =- case fromMaybe [] fields of- [] -> return ()- fs -> do- depend (write "{") $ do- prefixedLined "," (map (depend space . pretty) fs)- write "}"- p- horVar =- depend (pretty name >> write " :: ") $ do- fields' (write " -> ")- declTy t- verVar = do- pretty name- newline- indentedBlock $- depend (write ":: ") $ do- fields' $ do- newline- indented (-3) (write "-> ")- declTy t--instance Pretty Rhs where- prettyInternal =- rhs--instance Pretty Splice where- prettyInternal x =- case x of- IdSplice _ str ->- do write "$"- string str- ParenSplice _ e ->- depend (write "$")- (parens (pretty e))--instance Pretty InstRule where- prettyInternal (IParen _ rule) = parens $ pretty rule- prettyInternal (IRule _ mvarbinds mctx ihead) =- do case mvarbinds of- Nothing -> return ()- Just xs -> do write "forall "- spaced (map pretty xs)- write ". "- case mctx of- Nothing -> pretty ihead- Just ctx -> do- mst <- fitsOnOneLine (do pretty ctx- write " => "- pretty ihead- write " where")- case mst of- Nothing -> withCtx mctx (pretty ihead)- Just {} -> do- pretty ctx- write " => "- pretty ihead--instance Pretty InstHead where- prettyInternal x =- case x of- -- Base cases- IHCon _ name -> pretty name- IHInfix _ typ' name ->- depend (pretty typ')- (do space- prettyInfixOp name)- -- Recursive application- IHApp _ ihead typ' ->- depend (pretty ihead)- (do space- pretty typ')- -- Wrapping in parens- IHParen _ h -> parens (pretty h)--instance Pretty DeclHead where- prettyInternal x =- case x of- DHead _ name -> prettyQuoteName name- DHParen _ h -> parens (pretty h)- DHInfix _ var name ->- do pretty var- space- prettyInfixName name- DHApp _ dhead var ->- depend (pretty dhead)- (do space- pretty var)--instance Pretty Overlap where- prettyInternal (Overlap _) = write "{-# OVERLAP #-}"- prettyInternal (Overlapping _) = write "{-# OVERLAPPING #-}"- prettyInternal (Overlaps _) = write "{-# OVERLAPS #-}"- prettyInternal (Overlappable _) = write "{-# OVERLAPPABLE #-}"- prettyInternal (NoOverlap _) = write "{-# NO_OVERLAP #-}"- prettyInternal (Incoherent _) = write "{-# INCOHERENT #-}"--instance Pretty Sign where- prettyInternal (Signless _) = return ()- prettyInternal (Negative _) = write "-"--instance Pretty CallConv where- prettyInternal = pretty'--instance Pretty Safety where- prettyInternal = pretty'------------------------------------------------------------------------------------- * Unimplemented or incomplete printers--instance Pretty Module where- prettyInternal x =- case x of- Module _ mayModHead pragmas imps decls ->- do inter (do newline- newline)- (mapMaybe (\(isNull,r) ->- if isNull- then Nothing- else Just r)- [(null pragmas,inter newline (map pretty pragmas))- ,(case mayModHead of- Nothing -> (True,return ())- Just modHead -> (False,pretty modHead))- ,(null imps,formatImports imps)- ,(null decls- ,interOf newline- (map (\case- r@TypeSig{} -> (1,pretty r)- r@InlineSig{} -> (1, pretty r)- r -> (2,pretty r))- decls))])- newline- where interOf i ((c,p):ps) =- case ps of- [] -> p- _ ->- do p- replicateM_ c i- interOf i ps- interOf _ [] = return ()- XmlPage{} -> error "FIXME: No implementation for XmlPage."- XmlHybrid{} -> error "FIXME: No implementation for XmlHybrid."---- | Format imports, preserving empty newlines between groups.-formatImports :: [ImportDecl NodeInfo] -> Printer ()-formatImports =- sequence_ .- intersperse (newline >> newline) .- map formatImportGroup . groupAdjacentBy atNextLine- where- atNextLine import1 import2 =- let end1 = srcSpanEndLine (srcInfoSpan (nodeInfoSpan (ann import1)))- start2 = srcSpanStartLine (srcInfoSpan (nodeInfoSpan (ann import2)))- in start2 - end1 <= 1- formatImportGroup imps = do- shouldSortImports <- gets $ configSortImports . psConfig- let imps1 =- if shouldSortImports- then sortImports imps- else imps- sequence_ . intersperse newline $ map formatImport imps1- moduleVisibleName idecl =- let ModuleName _ name = importModule idecl- in name- formatImport = pretty- sortImports imps = sortOn moduleVisibleName . map sortImportSpecsOnImport $ imps- sortImportSpecsOnImport imp = imp { importSpecs = fmap sortImportSpecs (importSpecs imp) }- sortImportSpecs (ImportSpecList l hiding specs) = ImportSpecList l hiding sortedSpecs- where- sortedSpecs = sortBy importSpecCompare . map sortCNames $ specs-- sortCNames (IThingWith l2 name cNames) = IThingWith l2 name . sortBy cNameCompare $ cNames- sortCNames is = is--groupAdjacentBy :: (a -> a -> Bool) -> [a] -> [[a]]-groupAdjacentBy _ [] = []-groupAdjacentBy adj items = xs : groupAdjacentBy adj rest- where- (xs, rest) = spanAdjacentBy adj items--spanAdjacentBy :: (a -> a -> Bool) -> [a] -> ([a], [a])-spanAdjacentBy _ [] = ([], [])-spanAdjacentBy _ [x] = ([x], [])-spanAdjacentBy adj (x:xs@(y:_))- | adj x y =- let (xs', rest') = spanAdjacentBy adj xs- in (x : xs', rest')- | otherwise = ([x], xs)--importSpecCompare :: ImportSpec l -> ImportSpec l -> Ordering-importSpecCompare (IAbs _ _ (Ident _ s1)) (IAbs _ _ (Ident _ s2)) = compare s1 s2-importSpecCompare (IAbs _ _ (Ident _ _)) (IAbs _ _ (Symbol _ _)) = GT-importSpecCompare (IAbs _ _ (Ident _ s1)) (IThingAll _ (Ident _ s2)) = compare s1 s2-importSpecCompare (IAbs _ _ (Ident _ _)) (IThingAll _ (Symbol _ _)) = GT-importSpecCompare (IAbs _ _ (Ident _ s1)) (IThingWith _ (Ident _ s2) _) = compare s1 s2-importSpecCompare (IAbs _ _ (Ident _ _)) (IThingWith _ (Symbol _ _) _) = GT-importSpecCompare (IAbs _ _ (Symbol _ _)) (IAbs _ _ (Ident _ _)) = LT-importSpecCompare (IAbs _ _ (Symbol _ s1)) (IAbs _ _ (Symbol _ s2)) = compare s1 s2-importSpecCompare (IAbs _ _ (Symbol _ _)) (IThingAll _ (Ident _ _)) = LT-importSpecCompare (IAbs _ _ (Symbol _ s1)) (IThingAll _ (Symbol _ s2)) = compare s1 s2-importSpecCompare (IAbs _ _ (Symbol _ _)) (IThingWith _ (Ident _ _) _) = LT-importSpecCompare (IAbs _ _ (Symbol _ s1)) (IThingWith _ (Symbol _ s2) _) = compare s1 s2-importSpecCompare (IAbs _ _ _) (IVar _ _) = LT-importSpecCompare (IThingAll _ (Ident _ s1)) (IAbs _ _ (Ident _ s2)) = compare s1 s2-importSpecCompare (IThingAll _ (Ident _ _)) (IAbs _ _ (Symbol _ _)) = GT-importSpecCompare (IThingAll _ (Ident _ s1)) (IThingAll _ (Ident _ s2)) = compare s1 s2-importSpecCompare (IThingAll _ (Ident _ _)) (IThingAll _ (Symbol _ _)) = GT-importSpecCompare (IThingAll _ (Ident _ s1)) (IThingWith _ (Ident _ s2) _) = compare s1 s2-importSpecCompare (IThingAll _ (Ident _ _)) (IThingWith _ (Symbol _ _) _) = GT-importSpecCompare (IThingAll _ (Symbol _ _)) (IAbs _ _ (Ident _ _)) = LT-importSpecCompare (IThingAll _ (Symbol _ s1)) (IAbs _ _ (Symbol _ s2)) = compare s1 s2-importSpecCompare (IThingAll _ (Symbol _ _)) (IThingAll _ (Ident _ _)) = LT-importSpecCompare (IThingAll _ (Symbol _ s1)) (IThingAll _ (Symbol _ s2)) = compare s1 s2-importSpecCompare (IThingAll _ (Symbol _ _)) (IThingWith _ (Ident _ _) _) = LT-importSpecCompare (IThingAll _ (Symbol _ s1)) (IThingWith _ (Symbol _ s2) _) = compare s1 s2-importSpecCompare (IThingAll _ _) (IVar _ _) = LT-importSpecCompare (IThingWith _ (Ident _ s1) _) (IAbs _ _ (Ident _ s2)) = compare s1 s2-importSpecCompare (IThingWith _ (Ident _ _) _) (IAbs _ _ (Symbol _ _)) = GT-importSpecCompare (IThingWith _ (Ident _ s1) _) (IThingAll _ (Ident _ s2)) = compare s1 s2-importSpecCompare (IThingWith _ (Ident _ _) _) (IThingAll _ (Symbol _ _)) = GT-importSpecCompare (IThingWith _ (Ident _ s1) _) (IThingWith _ (Ident _ s2) _) = compare s1 s2-importSpecCompare (IThingWith _ (Ident _ _) _) (IThingWith _ (Symbol _ _) _) = GT-importSpecCompare (IThingWith _ (Symbol _ _) _) (IAbs _ _ (Ident _ _)) = LT-importSpecCompare (IThingWith _ (Symbol _ s1) _) (IAbs _ _ (Symbol _ s2)) = compare s1 s2-importSpecCompare (IThingWith _ (Symbol _ _) _) (IThingAll _ (Ident _ _)) = LT-importSpecCompare (IThingWith _ (Symbol _ s1) _) (IThingAll _ (Symbol _ s2)) = compare s1 s2-importSpecCompare (IThingWith _ (Symbol _ _) _) (IThingWith _ (Ident _ _) _) = LT-importSpecCompare (IThingWith _ (Symbol _ s1) _) (IThingWith _ (Symbol _ s2) _) = compare s1 s2-importSpecCompare (IThingWith _ _ _) (IVar _ _) = LT-importSpecCompare (IVar _ (Ident _ s1)) (IVar _ (Ident _ s2)) = compare s1 s2-importSpecCompare (IVar _ (Ident _ _)) (IVar _ (Symbol _ _)) = GT-importSpecCompare (IVar _ (Symbol _ _)) (IVar _ (Ident _ _)) = LT-importSpecCompare (IVar _ (Symbol _ s1)) (IVar _ (Symbol _ s2)) = compare s1 s2-importSpecCompare (IVar _ _) _ = GT--cNameCompare :: CName l -> CName l -> Ordering-cNameCompare (VarName _ (Ident _ s1)) (VarName _ (Ident _ s2)) = compare s1 s2-cNameCompare (VarName _ (Ident _ _)) (VarName _ (Symbol _ _)) = GT-cNameCompare (VarName _ (Ident _ s1)) (ConName _ (Ident _ s2)) = compare s1 s2-cNameCompare (VarName _ (Ident _ _)) (ConName _ (Symbol _ _)) = GT-cNameCompare (VarName _ (Symbol _ _)) (VarName _ (Ident _ _)) = LT-cNameCompare (VarName _ (Symbol _ s1)) (VarName _ (Symbol _ s2)) = compare s1 s2-cNameCompare (VarName _ (Symbol _ _)) (ConName _ (Ident _ _)) = LT-cNameCompare (VarName _ (Symbol _ s1)) (ConName _ (Symbol _ s2)) = compare s1 s2-cNameCompare (ConName _ (Ident _ s1)) (VarName _ (Ident _ s2)) = compare s1 s2-cNameCompare (ConName _ (Ident _ _)) (VarName _ (Symbol _ _)) = GT-cNameCompare (ConName _ (Ident _ s1)) (ConName _ (Ident _ s2)) = compare s1 s2-cNameCompare (ConName _ (Ident _ _)) (ConName _ (Symbol _ _)) = GT-cNameCompare (ConName _ (Symbol _ _)) (VarName _ (Ident _ _)) = LT-cNameCompare (ConName _ (Symbol _ s1)) (VarName _ (Symbol _ s2)) = compare s1 s2-cNameCompare (ConName _ (Symbol _ _)) (ConName _ (Ident _ _)) = LT-cNameCompare (ConName _ (Symbol _ s1)) (ConName _ (Symbol _ s2)) = compare s1 s2--instance Pretty Bracket where- prettyInternal x =- case x of- ExpBracket _ p -> quotation "" (pretty p)- PatBracket _ p -> quotation "p" (pretty p)- TypeBracket _ ty -> quotation "t" (pretty ty)- d@(DeclBracket _ _) -> pretty' d--instance Pretty IPBind where- prettyInternal x =- case x of- IPBind _ name expr -> do- pretty name- space- write "="- space- pretty expr--instance Pretty BooleanFormula where- prettyInternal (VarFormula _ i@(Ident _ _)) = pretty' i- prettyInternal (VarFormula _ (Symbol _ s)) = write "(" >> string s >> write ")"- prettyInternal (AndFormula _ fs) = do- maybeFormulas <- fitsOnOneLine $ inter (write ", ") $ map pretty fs- case maybeFormulas of- Nothing -> prefixedLined ", " (map pretty fs)- Just formulas -> put formulas- prettyInternal (OrFormula _ fs) = do- maybeFormulas <- fitsOnOneLine $ inter (write " | ") $ map pretty fs- case maybeFormulas of- Nothing -> prefixedLined "| " (map pretty fs)- Just formulas -> put formulas- prettyInternal (ParenFormula _ f) = parens $ pretty f------------------------------------------------------------------------------------- * Fallback printers--instance Pretty DataOrNew where- prettyInternal = pretty'--instance Pretty FunDep where- prettyInternal = pretty'--#if !MIN_VERSION_haskell_src_exts(1,21,0)-instance Pretty Kind where- prettyInternal = pretty'-#endif--instance Pretty ResultSig where- prettyInternal (KindSig _ kind) = pretty kind- prettyInternal (TyVarSig _ tyVarBind) = pretty tyVarBind--instance Pretty Literal where- prettyInternal (String _ _ rep) = do- write "\""- string rep- write "\""- prettyInternal (Char _ _ rep) = do- write "'"- string rep- write "'"- prettyInternal (PrimString _ _ rep) = do- write "\""- string rep- write "\"#"- prettyInternal (PrimChar _ _ rep) = do- write "'"- string rep- write "'#"- -- We print the original notation (because HSE doesn't track Hex- -- vs binary vs decimal notation).- prettyInternal (Int _l _i originalString) =- string originalString- prettyInternal (Frac _l _r originalString) =- string originalString- prettyInternal x = pretty' x--instance Pretty Name where- prettyInternal x = case x of- Ident _ _ -> pretty' x -- Identifiers.- Symbol _ s -> string s -- Symbols--instance Pretty QName where- prettyInternal =- \case- Qual _ mn n ->- case n of- Ident _ i -> do pretty mn; write "."; string i;- Symbol _ s -> do write "("; pretty mn; write "."; string s; write ")";- UnQual _ n ->- case n of- Ident _ i -> string i- Symbol _ s -> do write "("; string s; write ")";- Special _ s@Cons{} -> parens (pretty s)- Special _ s@FunCon{} -> parens (pretty s)- Special _ s -> pretty s---instance Pretty SpecialCon where- prettyInternal s =- case s of- UnitCon _ -> write "()"- ListCon _ -> write "[]"- FunCon _ -> write "->"- TupleCon _ Boxed i ->- string ("(" ++- replicate (i - 1) ',' ++- ")")- TupleCon _ Unboxed i ->- string ("(# " ++- replicate (i - 1) ',' ++- " #)")- Cons _ -> write ":"- UnboxedSingleCon _ -> write "(##)"- ExprHole _ -> write "_"--instance Pretty QOp where- prettyInternal = pretty'--instance Pretty TyVarBind where- prettyInternal = pretty'--instance Pretty ModuleHead where- prettyInternal (ModuleHead _ name mwarnings mexports) =- do write "module "- pretty name- maybe (return ()) pretty mwarnings- maybe (return ())- (\exports ->- do newline- indentSpaces <- getIndentSpaces- indented indentSpaces (pretty exports))- mexports- write " where"--instance Pretty ModulePragma where- prettyInternal = pretty'--instance Pretty ImportDecl where- prettyInternal (ImportDecl _ name qualified source safe mpkg mas mspec) = do- write "import"- when source $ write " {-# SOURCE #-}"- when safe $ write " safe"- when qualified $ write " qualified"- case mpkg of- Nothing -> return ()- Just pkg -> space >> write ("\"" ++ pkg ++ "\"")- space- pretty name- case mas of- Nothing -> return ()- Just asName -> do- space- write "as "- pretty asName- case mspec of- Nothing -> return ()- Just spec -> pretty spec--instance Pretty ModuleName where- prettyInternal (ModuleName _ name) =- write name--instance Pretty ImportSpecList where- prettyInternal (ImportSpecList _ hiding spec) = do- when hiding $ write " hiding"- let verVar = do- space- parens (commas (map pretty spec))- let horVar = do- newline- indentedBlock- (do depend (write "( ") (prefixedLined ", " (map pretty spec))- newline- write ")")- verVar `ifFitsOnOneLineOrElse` horVar--instance Pretty ImportSpec where- prettyInternal = pretty'--instance Pretty WarningText where- prettyInternal (DeprText _ s) =- write "{-# DEPRECATED " >> string s >> write " #-}"- prettyInternal (WarnText _ s) =- write "{-# WARNING " >> string s >> write " #-}"--instance Pretty ExportSpecList where- prettyInternal (ExportSpecList _ es) = do- depend (write "(")- (prefixedLined "," (map pretty es))- newline- write ")"--instance Pretty ExportSpec where- prettyInternal x = string " " >> pretty' x---- Do statements need to handle infix expression indentation specially because--- do x *--- y--- is two invalid statements, not one valid infix op.-stmt :: Stmt NodeInfo -> Printer ()-stmt (Qualifier _ e@(InfixApp _ a op b)) =- do col <- fmap (psColumn . snd)- (sandbox (write ""))- infixApp e a op b (Just col)-stmt (Generator _ p e) =- do indentSpaces <- getIndentSpaces- pretty p- indented indentSpaces- (dependOrNewline- (write " <-")- space- e- pretty)-stmt x = case x of- Generator _ p e ->- depend (do pretty p- write " <- ")- (pretty e)- Qualifier _ e -> pretty e- LetStmt _ binds ->- depend (write "let ")- (pretty binds)- RecStmt _ es ->- depend (write "rec ")- (lined (map pretty es))---- | Make the right hand side dependent if it fits on one line,--- otherwise send it to the next line.-dependOrNewline- :: Printer ()- -> Printer ()- -> Exp NodeInfo- -> (Exp NodeInfo -> Printer ())- -> Printer ()-dependOrNewline left prefix right f =- do msg <- fitsOnOneLine renderDependent- case msg of- Nothing -> do left- newline- (f right)- Just st -> put st- where renderDependent = depend left (do prefix; f right)---- | Handle do and case specially and also space out guards more.-rhs :: Rhs NodeInfo -> Printer ()-rhs (UnGuardedRhs _ (Do _ dos)) =- do inCase <- gets psInsideCase- write (if inCase then " -> " else " = ")- indentSpaces <- getIndentSpaces- let indentation | inCase = indentSpaces- | otherwise = max 2 indentSpaces- swingBy indentation- (write "do")- (lined (map pretty dos))-rhs (UnGuardedRhs _ e) = do- msg <-- fitsOnOneLine- (do write " "- rhsSeparator- write " "- pretty e)- case msg of- Nothing -> swing (write " " >> rhsSeparator) (pretty e)- Just st -> put st-rhs (GuardedRhss _ gas) =- do newline- n <- getIndentSpaces- indented n- (lined (map (\p ->- do write "|"- pretty p)- gas))---- | Implement dangling right-hand-sides.-guardedRhs :: GuardedRhs NodeInfo -> Printer ()--- | Handle do specially.--guardedRhs (GuardedRhs _ stmts (Do _ dos)) =- do indented 1- (do prefixedLined- ","- (map (\p ->- do space- pretty p)- stmts))- inCase <- gets psInsideCase- write (if inCase then " -> " else " = ")- swing (write "do")- (lined (map pretty dos))-guardedRhs (GuardedRhs _ stmts e) = do- mst <- fitsOnOneLine printStmts- case mst of- Just st -> do- put st- mst' <-- fitsOnOneLine- (do write " "- rhsSeparator- write " "- pretty e)- case mst' of- Just st' -> put st'- Nothing -> swingIt- Nothing -> do- printStmts- swingIt- where- printStmts =- indented- 1- (do prefixedLined- ","- (map- (\p -> do- space- pretty p)- stmts))- swingIt = swing (write " " >> rhsSeparator) (pretty e)--match :: Match NodeInfo -> Printer ()-match (Match _ name pats rhs' mbinds) =- do depend (do case name of- Ident _ _ ->- pretty name- Symbol _ _ ->- do write "("- pretty name- write ")"- space)- (spaced (map pretty pats))- withCaseContext False (pretty rhs')- for_ mbinds bindingGroup-match (InfixMatch _ pat1 name pats rhs' mbinds) =- do depend (do pretty pat1- space- prettyInfixName name)- (do space- spaced (map pretty pats))- withCaseContext False (pretty rhs')- for_ mbinds bindingGroup---- | Format contexts with spaces and commas between class constraints.-context :: Context NodeInfo -> Printer ()-context ctx =- case ctx of- CxSingle _ a -> pretty a- CxTuple _ as -> do- depend (write "( ") $ prefixedLined ", " (map pretty as)- newline- write ")"- CxEmpty _ -> parens (return ())--typ :: Type NodeInfo -> Printer ()-typ (TyTuple _ Boxed types) = do- let horVar = parens $ inter (write ", ") (map pretty types)- let verVar = parens $ prefixedLined "," (map (depend space . pretty) types)- horVar `ifFitsOnOneLineOrElse` verVar-typ (TyTuple _ Unboxed types) = do- let horVar = wrap "(# " " #)" $ inter (write ", ") (map pretty types)- let verVar = wrap "(#" " #)" $ prefixedLined "," (map (depend space . pretty) types)- horVar `ifFitsOnOneLineOrElse` verVar-typ (TyForall _ mbinds ctx ty) =- depend (case mbinds of- Nothing -> return ()- Just ts ->- do write "forall "- spaced (map pretty ts)- write ". ")- (do indentSpaces <- getIndentSpaces- withCtx ctx (indented indentSpaces (pretty ty)))-typ (TyFun _ a b) =- depend (do pretty a- write " -> ")- (pretty b)-typ (TyList _ t) = brackets (pretty t)-typ (TyParArray _ t) =- brackets (do write ":"- pretty t- write ":")-typ (TyApp _ f a) = spaced [pretty f, pretty a]-typ (TyVar _ n) = pretty n-typ (TyCon _ p) = pretty p-typ (TyParen _ e) = parens (pretty e)-typ (TyInfix _ a promotedop b) = do- -- Apply special rules to line-break operators.- let isLineBreak' op =- case op of- PromotedName _ op' -> isLineBreak op'- UnpromotedName _ op' -> isLineBreak op'- prettyInfixOp' op =- case op of- PromotedName _ op' -> write "'" >> prettyInfixOp op'- UnpromotedName _ op' -> prettyInfixOp op'- linebreak <- isLineBreak' promotedop- if linebreak- then do pretty a- newline- prettyInfixOp' promotedop- space- pretty b- else do pretty a- space- prettyInfixOp' promotedop- space- pretty b-typ (TyKind _ ty k) =- parens (do pretty ty- write " :: "- pretty k)-typ (TyBang _ bangty unpackty right) =- do pretty unpackty- pretty bangty- pretty right-typ (TyEquals _ left right) =- do pretty left- write " ~ "- pretty right-typ (TyPromoted _ (PromotedList _ _ ts)) =- do write "'["- unless (null ts) $ write " "- commas (map pretty ts)- write "]"-typ (TyPromoted _ (PromotedTuple _ ts)) =- do write "'("- unless (null ts) $ write " "- commas (map pretty ts)- write ")"-typ (TyPromoted _ (PromotedCon _ _ tname)) =- do write "'"- pretty tname-typ (TyPromoted _ (PromotedString _ _ raw)) = do- do write "\""- string raw- write "\""-typ ty@TyPromoted{} = pretty' ty-typ (TySplice _ splice) = pretty splice-typ (TyWildCard _ name) =- case name of- Nothing -> write "_"- Just n ->- do write "_"- pretty n-typ (TyQuasiQuote _ n s) = quotation n (string s)-typ (TyUnboxedSum{}) = error "FIXME: No implementation for TyUnboxedSum."-#if MIN_VERSION_haskell_src_exts(1,21,0)-typ (TyStar _) = write "*"-#endif--prettyTopName :: Name NodeInfo -> Printer ()-prettyTopName x@Ident{} = pretty x-prettyTopName x@Symbol{} = parens $ pretty x---- | Specially format records. Indent where clauses only 2 spaces.-decl' :: Decl NodeInfo -> Printer ()--- | Pretty print type signatures like------ foo :: (Show x, Read x)--- => (Foo -> Bar)--- -> Maybe Int--- -> (Char -> X -> Y)--- -> IO ()----decl' (TypeSig _ names ty') = do- mst <- fitsOnOneLine (depend (do commas (map prettyTopName names)- write " :: ")- (declTy ty'))- case mst of- Nothing -> do- commas (map prettyTopName names)- indentSpaces <- getIndentSpaces- if allNamesLength >= indentSpaces- then do write " ::"- newline- indented indentSpaces (depend (write " ") (declTy ty'))- else (depend (write " :: ") (declTy ty'))- Just st -> put st- where- nameLength (Ident _ s) = length s- nameLength (Symbol _ s) = length s + 2- allNamesLength = fromIntegral $ sum (map nameLength names) + 2 * (length names - 1)--decl' (PatBind _ pat rhs' mbinds) =- withCaseContext False $- do pretty pat- pretty rhs'- for_ mbinds bindingGroup---- | Handle records specially for a prettier display (see guide).-decl' e = decl e--declTy :: Type NodeInfo -> Printer ()-declTy dty =- case dty of- TyForall _ mbinds mctx ty ->- case mbinds of- Nothing -> do- case mctx of- Nothing -> prettyTy False ty- Just ctx -> do- mst <- fitsOnOneLine (do pretty ctx- depend (write " => ") (prettyTy False ty))- case mst of- Nothing -> do- pretty ctx- newline- indented (-3) (depend (write "=> ") (prettyTy True ty))- Just st -> put st- Just ts -> do- write "forall "- spaced (map pretty ts)- write "."- case mctx of- Nothing -> do- mst <- fitsOnOneLine (space >> prettyTy False ty)- case mst of- Nothing -> do- newline- prettyTy True ty- Just st -> put st- Just ctx -> do- mst <- fitsOnOneLine (space >> pretty ctx)- case mst of- Nothing -> do- newline- pretty ctx- newline- indented (-3) (depend (write "=> ") (prettyTy True ty))- Just st -> do- put st- newline- indented (-3) (depend (write "=> ") (prettyTy True ty))- _ -> prettyTy False dty- where- collapseFaps (TyFun _ arg result) = arg : collapseFaps result- collapseFaps e = [e]- prettyTy breakLine ty = do- if breakLine- then- case collapseFaps ty of- [] -> pretty ty- tys -> prefixedLined "-> " (map pretty tys)- else do- mst <- fitsOnOneLine (pretty ty)- case mst of- Nothing ->- case collapseFaps ty of- [] -> pretty ty- tys -> prefixedLined "-> " (map pretty tys)- Just st -> put st---- | Use special record display, used by 'dataDecl' in a record scenario.-qualConDecl :: QualConDecl NodeInfo -> Printer ()-qualConDecl (QualConDecl _ tyvars ctx d) =- depend (unless (null (fromMaybe [] tyvars))- (do write "forall "- spaced (map pretty (fromMaybe [] tyvars))- write ". "))- (withCtx ctx (recDecl d))---- | Fields are preceded with a space.-conDecl :: ConDecl NodeInfo -> Printer ()-conDecl (RecDecl _ name fields) = do- pretty name- newline- indentedBlock- (do depend (write "{")- (prefixedLined ","- (map (depend space . pretty) fields))- newline- write "}"- )-conDecl (ConDecl _ name bangty) = do- prettyQuoteName name- unless- (null bangty)- (ifFitsOnOneLineOrElse- (do space- spaced (map pretty bangty))- (do newline- indentedBlock (lined (map pretty bangty))))-conDecl (InfixConDecl _ a f b) =- inter space [pretty a, pretty f, pretty b]---- | Record decls are formatted like: Foo--- { bar :: X--- }-recDecl :: ConDecl NodeInfo -> Printer ()-recDecl (RecDecl _ name fields) =- do pretty name- indentSpaces <- getIndentSpaces- newline- column indentSpaces- (do depend (write "{!")- (prefixedLined ","- (map (depend space . pretty) fields))- newline- write "}")-recDecl r = prettyInternal r--recUpdateExpr :: Printer () -> [FieldUpdate NodeInfo] -> Printer ()-recUpdateExpr expWriter updates = do- ifFitsOnOneLineOrElse hor $ do- expWriter- newline- indentedBlock (updatesHor `ifFitsOnOneLineOrElse` updatesVer)- where- hor = do- expWriter- space- updatesHor- updatesHor = braces $ commas $ map pretty updates- updatesVer = do- depend (write "{ ") $ prefixedLined ", " $ map pretty updates- newline- write "}"------------------------------------------------------------------------------------- Predicates---- | Is the decl a record?-isRecord :: QualConDecl t -> Bool-isRecord (QualConDecl _ _ _ RecDecl{}) = True-isRecord _ = False---- | If the given operator is an element of line breaks in configuration.-isLineBreak :: QName NodeInfo -> Printer Bool-isLineBreak (UnQual _ (Symbol _ s)) = do- breaks <- gets (configLineBreaks . psConfig)- return $ s `elem` breaks-isLineBreak _ = return False---- | Does printing the given thing overflow column limit? (e.g. 80)-fitsOnOneLine :: Printer a -> Printer (Maybe PrintState)-fitsOnOneLine p =- do st <- get- put st { psFitOnOneLine = True}- ok <- fmap (const True) p <|> return False- st' <- get- put st- guard $ ok || not (psFitOnOneLine st)- return (if ok- then Just st' { psFitOnOneLine = psFitOnOneLine st }- else Nothing)---- | If first printer fits, use it, else use the second one.-ifFitsOnOneLineOrElse :: Printer a -> Printer a -> Printer a-ifFitsOnOneLineOrElse a b = do- stOrig <- get- put stOrig{psFitOnOneLine = True}- res <- fmap Just a <|> return Nothing- case res of- Just r -> do- modify $ \st -> st{psFitOnOneLine = psFitOnOneLine stOrig}- return r- Nothing -> do- put stOrig- guard $ not (psFitOnOneLine stOrig)- b--bindingGroup :: Binds NodeInfo -> Printer ()-bindingGroup binds =- do newline- indented 2- (do write "where"- newline- indented 2 (pretty binds))--infixApp :: Exp NodeInfo- -> Exp NodeInfo- -> QOp NodeInfo- -> Exp NodeInfo- -> Maybe Int64- -> Printer ()-infixApp e a op b indent =- hor `ifFitsOnOneLineOrElse` ver- where- hor =- spaced- [ case link of- OpChainExp e' -> pretty e'- OpChainLink qop -> pretty qop- | link <- flattenOpChain e- ]- ver = do- prettyWithIndent a- beforeRhs <- case a of- Do _ _ -> do- indentSpaces <- getIndentSpaces- column (fromMaybe 0 indent + indentSpaces + 3) (newline >> pretty op) -- 3 = "do "- return space- _ -> space >> pretty op >> return newline- case b of- Lambda{} -> space >> pretty b- LCase{} -> space >> pretty b- Do _ stmts -> swing (write " do") $ lined (map pretty stmts)- _ -> do- beforeRhs- case indent of- Nothing -> do- col <- fmap (psColumn . snd)- (sandbox (write ""))- -- force indent for top-level template haskell expressions, #473.- if col == 0- then do indentSpaces <- getIndentSpaces- column indentSpaces (prettyWithIndent b)- else prettyWithIndent b- Just col -> do- indentSpaces <- getIndentSpaces- column (col + indentSpaces) (prettyWithIndent b)- prettyWithIndent e' =- case e' of- InfixApp _ a' op' b' -> infixApp e' a' op' b' indent- _ -> pretty e'---- | A link in a chain of operator applications.-data OpChainLink l- = OpChainExp (Exp l)- | OpChainLink (QOp l)- deriving (Show)---- | Flatten a tree of InfixApp expressions into a chain of operator--- links.-flattenOpChain :: Exp l -> [OpChainLink l]-flattenOpChain (InfixApp _ left op right) =- flattenOpChain left <>- [OpChainLink op] <>- flattenOpChain right-flattenOpChain e = [OpChainExp e]---- | Write a Template Haskell quotation or a quasi-quotation.------ >>> quotation "t" (string "Foo")--- > [t|Foo|]-quotation :: String -> Printer () -> Printer ()-quotation quoter body =- brackets- (depend- (do string quoter- write "|")- (do body- write "|"))+{-# LANGUAGE CPP #-}+{-# LANGUAGE ExistentialQuantification #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE RecordWildCards #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE ViewPatterns #-}++-- | Pretty printing.+--+-- Some instances define top-level functions to handle CPP.+--+-- Some value constructors never appear in an AST. GHC has three stages for+-- using an AST: parsing, renaming, and type checking, and GHC uses these+-- constructors only in remaining and type checking.+module HIndent.Pretty+ ( pretty+ ) where++import Control.Monad+import Control.Monad.RWS+import Data.Maybe+import Data.Void+import GHC.Core.Coercion+import GHC.Core.InstEnv+import GHC.Data.Bag+import GHC.Data.BooleanFormula+import GHC.Data.FastString+import GHC.Hs+import GHC.Stack+import GHC.Types.Basic+import GHC.Types.Fixity+import GHC.Types.ForeignCall+import GHC.Types.Name+import GHC.Types.Name.Reader+import GHC.Types.SourceText+import GHC.Types.SrcLoc+import GHC.Unit+import GHC.Unit.Module.Warnings+import HIndent.Applicative+import HIndent.Config+import HIndent.Pretty.Combinators+import HIndent.Pretty.Import+import HIndent.Pretty.NodeComments+import HIndent.Pretty.Pragma+import HIndent.Pretty.SigBindFamily+import HIndent.Pretty.Types+import HIndent.Printer+import Text.Show.Unicode+#if MIN_VERSION_ghc_lib_parser(9,4,1)+import GHC.Types.PkgQual+#endif+-- | This function pretty-prints the given AST node with comments.+pretty :: Pretty a => a -> Printer ()+pretty p = do+ printCommentsBefore p+ pretty' p+ printCommentOnSameLine p+ printCommentsAfter p++-- | Prints comments included in the location information and then the+-- AST node body.+printCommentsAnd ::+ (CommentExtraction l) => GenLocated l e -> (e -> Printer ()) -> Printer ()+printCommentsAnd (L l e) f = do+ printCommentsBefore l+ f e+ printCommentOnSameLine l+ printCommentsAfter l++-- | Prints comments that are before the given AST node.+printCommentsBefore :: CommentExtraction a => a -> Printer ()+printCommentsBefore p =+ forM_ (commentsBefore $ nodeComments p) $ \(L loc c) -> do+ let col = fromIntegral $ srcSpanStartCol (anchor loc) - 1+ indentedWithFixedLevel col $ pretty c+ newline++-- | Prints comments that are on the same line as the given AST node.+printCommentOnSameLine :: CommentExtraction a => a -> Printer ()+printCommentOnSameLine (commentsOnSameLine . nodeComments -> (c:cs)) = do+ col <- gets psColumn+ if col == 0+ then indentedWithFixedLevel+ (fromIntegral $ srcSpanStartCol $ anchor $ getLoc c) $+ spaced $ fmap pretty $ c : cs+ else spacePrefixed $ fmap pretty $ c : cs+ eolCommentsArePrinted+printCommentOnSameLine _ = return ()++-- | Prints comments that are after the given AST node.+printCommentsAfter :: CommentExtraction a => a -> Printer ()+printCommentsAfter p =+ case commentsAfter $ nodeComments p of+ [] -> return ()+ xs -> do+ isThereCommentsOnSameLine <- gets psEolComment+ unless isThereCommentsOnSameLine newline+ forM_ xs $ \(L loc c) -> do+ let col = fromIntegral $ srcSpanStartCol (anchor loc) - 1+ indentedWithFixedLevel col $ pretty c+ eolCommentsArePrinted++-- | Pretty print including comments.+--+-- 'FastString' does not implement this class because it may contain @\n@s+-- and each type that may contain a 'FastString' value needs their own+-- handlings.+class CommentExtraction a =>+ Pretty a+ where+ pretty' :: a -> Printer ()++-- Do nothing if there are no pragmas, module headers, imports, or+-- declarations. Otherwise, extra blank lines will be inserted if only+-- comments are present in the source code. See+-- https://github.com/mihaimaruseac/hindent/issues/586#issuecomment-1374992624.+instance Pretty HsModule where+ pretty' m@HsModule {hsmodName = Nothing, hsmodImports = [], hsmodDecls = []}+ | not (pragmaExists m) = pure ()+ pretty' m = blanklined printers >> newline+ where+ printers = snd <$> filter fst pairs+ pairs =+ [ (pragmaExists m, prettyPragmas m)+ , (moduleDeclExists m, prettyModuleDecl m)+ , (importsExist m, prettyImports)+ , (declsExist m, prettyDecls)+ ]+ prettyModuleDecl HsModule {hsmodName = Nothing} =+ error "The module declaration does not exist."+ prettyModuleDecl HsModule { hsmodName = Just name+ , hsmodExports = Nothing+ , ..+ } = do+ pretty $ fmap ModuleNameWithPrefix name+ whenJust hsmodDeprecMessage $ \x -> do+ space+ pretty $ fmap ModuleDeprecatedPragma x+ string " where"+ prettyModuleDecl HsModule { hsmodName = Just name+ , hsmodExports = Just exports+ , ..+ } = do+ pretty $ fmap ModuleNameWithPrefix name+ whenJust hsmodDeprecMessage $ \x -> do+ space+ pretty $ fmap ModuleDeprecatedPragma x+ newline+ indentedBlock $ do+ printCommentsAnd exports (vTuple . fmap pretty)+ string " where"+ moduleDeclExists HsModule {hsmodName = Nothing} = False+ moduleDeclExists _ = True+ prettyDecls =+ mapM_ (\(x, sp) -> pretty x >> fromMaybe (return ()) sp) $+ addDeclSeparator $ hsmodDecls m+ addDeclSeparator [] = []+ addDeclSeparator [x] = [(x, Nothing)]+ addDeclSeparator (x:xs) =+ (x, Just $ declSeparator $ unLoc x) : addDeclSeparator xs+ declSeparator (SigD _ TypeSig {}) = newline+ declSeparator (SigD _ InlineSig {}) = newline+ declSeparator (SigD _ PatSynSig {}) = newline+ declSeparator _ = blankline+ declsExist = not . null . hsmodDecls+ prettyImports = importDecls >>= blanklined . fmap outputImportGroup+ outputImportGroup = lined . fmap pretty+ importDecls =+ gets (configSortImports . psConfig) >>= \case+ True -> pure $ extractImportsSorted m+ False -> pure $ extractImports m++instance (CommentExtraction l, Pretty e) => Pretty (GenLocated l e) where+ pretty' (L _ e) = pretty e++instance Pretty (HsDecl GhcPs) where+ pretty' (TyClD _ d) = pretty d+ pretty' (InstD _ inst) = pretty inst+ pretty' (DerivD _ x) = pretty x+ pretty' (ValD _ bind) = pretty bind+ pretty' (SigD _ s) = pretty $ DeclSig s+ pretty' (KindSigD _ x) = pretty x+ pretty' (DefD _ x) = pretty x+ pretty' (ForD _ x) = pretty x+ pretty' (WarningD _ x) = pretty x+ pretty' (AnnD _ x) = pretty x+ pretty' (RuleD _ x) = pretty x+ pretty' (SpliceD _ sp) = pretty sp+ pretty' DocD {} = docNode+ pretty' (RoleAnnotD _ x) = pretty x++instance Pretty (TyClDecl GhcPs) where+ pretty' = prettyTyClDecl++prettyTyClDecl :: TyClDecl GhcPs -> Printer ()+prettyTyClDecl (FamDecl _ x) = pretty x+prettyTyClDecl SynDecl {..} = do+ string "type "+ case tcdFixity of+ Prefix -> spaced $ pretty tcdLName : fmap pretty (hsq_explicit tcdTyVars)+ Infix ->+ case hsq_explicit tcdTyVars of+ (l:r:xs) -> do+ spaced [pretty l, pretty $ fmap InfixOp tcdLName, pretty r]+ forM_ xs $ \x -> do+ space+ pretty x+ _ -> error "Not enough parameters are given."+ hor <-|> ver+ where+ hor = string " = " >> pretty tcdRhs+ ver = newline >> indentedBlock (string "= " |=> pretty tcdRhs)+#if MIN_VERSION_ghc_lib_parser(9,4,1)+prettyTyClDecl DataDecl {..} = do+ printDataNewtype |=> do+ whenJust (dd_ctxt tcdDataDefn) $ \x -> do+ pretty $ Context x+ string " =>"+ newline+ pretty tcdLName+ spacePrefixed $ pretty <$> hsq_explicit tcdTyVars+ pretty tcdDataDefn+ where+ printDataNewtype =+ case dd_ND tcdDataDefn of+ DataType -> string "data "+ NewType -> string "newtype "+#else+prettyTyClDecl DataDecl {..} = do+ printDataNewtype |=> do+ whenJust (dd_ctxt tcdDataDefn) $ \_ -> do+ pretty $ Context $ dd_ctxt tcdDataDefn+ string " =>"+ newline+ pretty tcdLName+ spacePrefixed $ pretty <$> hsq_explicit tcdTyVars+ pretty tcdDataDefn+ where+ printDataNewtype =+ case dd_ND tcdDataDefn of+ DataType -> string "data "+ NewType -> string "newtype "+#endif+prettyTyClDecl ClassDecl {..} = do+ if isJust tcdCtxt+ then verHead+ else horHead <-|> verHead+ indentedBlock $ newlinePrefixed $ fmap pretty sigsMethodsFamilies+ where+ horHead = do+ string "class "+ printNameAndTypeVariables+ unless (null tcdFDs) $ do+ string " | "+ forM_ tcdFDs $ \x@(L _ FunDep {}) ->+ printCommentsAnd x $ \(FunDep _ from to) ->+ spaced $ fmap pretty from ++ [string "->"] ++ fmap pretty to+ unless (null sigsMethodsFamilies) $ string " where"+ verHead = do+ string "class " |=> do+ whenJust tcdCtxt $ \ctx -> do+ printCommentsAnd ctx $ \case+ [] -> string "()"+ [x] -> pretty x+ xs -> hvTuple $ fmap pretty xs+ string " =>"+ newline+ printNameAndTypeVariables+ unless (null tcdFDs) $ do+ newline+ indentedBlock $+ string "| " |=>+ vCommaSep+ (flip fmap tcdFDs $ \x@(L _ FunDep {}) ->+ printCommentsAnd x $ \(FunDep _ from to) ->+ spaced $ fmap pretty from ++ [string "->"] ++ fmap pretty to)+ unless (null sigsMethodsFamilies) $ do+ newline+ indentedBlock $ string "where"+ printNameAndTypeVariables =+ case tcdFixity of+ Prefix ->+ spaced $ pretty tcdLName : fmap pretty (hsq_explicit tcdTyVars)+ Infix ->+ case hsq_explicit tcdTyVars of+ (l:r:xs) -> do+ parens $+ spaced [pretty l, pretty $ fmap InfixOp tcdLName, pretty r]+ spacePrefixed $ fmap pretty xs+ _ -> error "Not enough parameters are given."+ sigsMethodsFamilies =+ mkSortedLSigBindFamilyList tcdSigs (bagToList tcdMeths) tcdATs [] []++instance Pretty (InstDecl GhcPs) where+ pretty' ClsInstD {..} = pretty cid_inst+ pretty' DataFamInstD {..} = pretty dfid_inst+ pretty' TyFamInstD {..} = pretty $ TopLevelTyFamInstDecl tfid_inst++instance Pretty (HsBind GhcPs) where+ pretty' = prettyHsBind++prettyHsBind :: HsBind GhcPs -> Printer ()+prettyHsBind FunBind {..} = pretty fun_matches+prettyHsBind PatBind {..} = pretty pat_lhs >> pretty pat_rhs+prettyHsBind VarBind {} = notGeneratedByParser+#if !MIN_VERSION_ghc_lib_parser(9,4,1)+prettyHsBind AbsBinds {} = notGeneratedByParser+#endif+prettyHsBind (PatSynBind _ x) = pretty x++instance Pretty (Sig GhcPs) where+ pretty' (TypeSig _ funName params) = do+ printFunName+ string " ::"+ horizontal <-|> vertical+ where+ horizontal = space >> pretty (hswc_body params)+ vertical = do+ headLen <- printerLength printFunName+ indentSpaces <- getIndentSpaces+ if headLen < indentSpaces+ then space+ else newline+ indentedBlock $+ indentedWithSpace 3 $+ pretty $ HsSigTypeInsideVerticalFuncSig <$> hswc_body params+ printFunName = pretty $ head funName+ pretty' (PatSynSig _ names sig) =+ spaced+ [string "pattern", hCommaSep $ fmap pretty names, string "::", pretty sig]+ pretty' (ClassOpSig _ True funNames params) =+ spaced+ [ string "default"+ , hCommaSep $ fmap pretty funNames+ , string "::"+ , printCommentsAnd params pretty+ ]+ pretty' (ClassOpSig _ False funNames params) = do+ hCommaSep $ fmap pretty funNames+ string " ::"+ hor <-|> ver+ where+ hor = space >> printCommentsAnd params (pretty . HsSigTypeInsideDeclSig)+ ver = do+ newline+ indentedBlock $+ indentedWithSpace 3 $+ printCommentsAnd params (pretty . HsSigTypeInsideDeclSig)+ pretty' IdSig {} = notGeneratedByParser+ pretty' (FixSig _ x) = pretty x+ pretty' (InlineSig _ name detail) =+ spaced [string "{-#", pretty detail, pretty name, string "#-}"]+ pretty' (SpecSig _ name sig _) =+ spaced+ [ string "{-# SPECIALISE"+ , pretty name+ , string "::"+ , pretty $ head sig+ , string "#-}"+ ]+ pretty' (SpecInstSig _ _ sig) =+ spaced [string "{-# SPECIALISE instance", pretty sig, string "#-}"]+ pretty' (MinimalSig _ _ xs) =+ string "{-# MINIMAL " |=> do+ pretty xs+ string " #-}"+ pretty' (SCCFunSig _ _ name _) =+ spaced [string "{-# SCC", pretty name, string "#-}"]+ pretty' (CompleteMatchSig _ _ names _) =+ spaced+ [ string "{-# COMPLETE"+ , printCommentsAnd names (hCommaSep . fmap pretty)+ , string "#-}"+ ]++instance Pretty DeclSig where+ pretty' (DeclSig (TypeSig _ funName params)) = do+ printFunName+ string " ::"+ horizontal <-|> vertical+ where+ horizontal = do+ space+ pretty $ HsSigTypeInsideDeclSig <$> hswc_body params+ vertical = do+ headLen <- printerLength printFunName+ indentSpaces <- getIndentSpaces+ if headLen < indentSpaces+ then space |=> pretty (HsSigTypeInsideDeclSig <$> hswc_body params)+ else do+ newline+ indentedBlock $+ indentedWithSpace 3 $+ pretty $ HsSigTypeInsideDeclSig <$> hswc_body params+ printFunName = hCommaSep $ fmap pretty funName+ pretty' (DeclSig x) = pretty x++instance Pretty (HsDataDefn GhcPs) where+ pretty' HsDataDefn {..} =+ if isGADT+ then do+ whenJust dd_kindSig $ \x -> do+ string " :: "+ pretty x+ string " where"+ indentedBlock $ newlinePrefixed $ fmap pretty dd_cons+ else do+ case dd_cons of+ [] -> indentedBlock derivingsAfterNewline+ [x@(L _ ConDeclH98 {con_args = RecCon {}})] -> do+ string " = "+ pretty x+ unless (null dd_derivs) $ space |=> printDerivings+ [x] -> do+ string " ="+ newline+ indentedBlock $ do+ pretty x+ derivingsAfterNewline+ _ ->+ indentedBlock $ do+ newline+ string "= " |=> vBarSep (fmap pretty dd_cons)+ derivingsAfterNewline+ where+ isGADT =+ case dd_cons of+ (L _ ConDeclGADT {}:_) -> True+ _ -> False+ derivingsAfterNewline =+ unless (null dd_derivs) $ newline >> printDerivings+ printDerivings = lined $ fmap pretty dd_derivs++instance Pretty (ClsInstDecl GhcPs) where+ pretty' ClsInstDecl {..} = do+ string "instance " |=> do+ whenJust cid_overlap_mode $ \x -> do+ pretty x+ space+ pretty (fmap HsSigTypeInsideInstDecl cid_poly_ty) |=>+ unless (null sigsAndMethods) (string " where")+ unless (null sigsAndMethods) $ do+ newline+ indentedBlock $ lined $ fmap pretty sigsAndMethods+ where+ sigsAndMethods =+ mkSortedLSigBindFamilyList+ cid_sigs+ (bagToList cid_binds)+ []+ cid_tyfam_insts+ cid_datafam_insts++instance Pretty (MatchGroup GhcPs (GenLocated SrcSpanAnnA (HsExpr GhcPs))) where+ pretty' MG {..} = printCommentsAnd mg_alts (lined . fmap pretty)++instance Pretty (MatchGroup GhcPs (GenLocated SrcSpanAnnA (HsCmd GhcPs))) where+ pretty' MG {..} = printCommentsAnd mg_alts (lined . fmap pretty)++instance Pretty (HsExpr GhcPs) where+ pretty' = prettyHsExpr++prettyHsExpr :: HsExpr GhcPs -> Printer ()+prettyHsExpr (HsVar _ bind) = pretty $ fmap PrefixOp bind+prettyHsExpr (HsUnboundVar _ x) = pretty x+prettyHsExpr (HsOverLabel _ l) = string "#" >> string (unpackFS l)+prettyHsExpr (HsIPVar _ var) = string "?" >> pretty var+prettyHsExpr (HsOverLit _ x) = pretty x+prettyHsExpr (HsLit _ l) = pretty l+prettyHsExpr (HsLam _ body) = pretty body+#if MIN_VERSION_ghc_lib_parser(9,4,1)+prettyHsExpr (HsLamCase _ LamCase matches) = pretty $ LambdaCase matches Case+prettyHsExpr (HsLamCase _ LamCases matches) = pretty $ LambdaCase matches Cases+#else+prettyHsExpr (HsLamCase _ matches) = pretty $ LambdaCase matches Case+#endif+prettyHsExpr (HsApp _ l r) = horizontal <-|> vertical+ where+ horizontal = spaced [pretty l, pretty r]+ vertical = do+ let (f, args) =+ case flatten l ++ [r] of+ [] -> error "Invalid function application."+ (f':args') -> (f', args')+ col <- gets psColumn+ spaces <- getIndentSpaces+ pretty f+ col' <- gets psColumn+ let diff =+ col' - col -+ if col == 0+ then spaces+ else 0+ if diff + 1 <= spaces+ then space+ else newline+ spaces' <- getIndentSpaces+ indentedWithSpace spaces' $ lined $ fmap pretty args+ flatten :: LHsExpr GhcPs -> [LHsExpr GhcPs]+ flatten (L (SrcSpanAnn (EpAnn _ _ cs) _) (HsApp _ l' r')) =+ flatten l' ++ [insertComments cs r']+ flatten x = [x]+ insertComments :: EpAnnComments -> LHsExpr GhcPs -> LHsExpr GhcPs+ insertComments cs (L s@SrcSpanAnn {ann = e@EpAnn {comments = cs'}} r') =+ L (s {ann = e {comments = cs <> cs'}}) r'+ insertComments _ x = x+prettyHsExpr (HsAppType _ l r) = do+ pretty l+ string " @"+ pretty r+prettyHsExpr (OpApp _ l o r) = pretty (InfixApp l o r False)+prettyHsExpr (NegApp _ x _) = string "-" >> pretty x+#if MIN_VERSION_ghc_lib_parser(9,4,1)+prettyHsExpr (HsPar _ _ expr _) = parens $ pretty expr+#else+prettyHsExpr (HsPar _ expr) = parens $ pretty expr+#endif+prettyHsExpr (SectionL _ l o) = spaced [pretty l, pretty (InfixExpr o)]+prettyHsExpr (SectionR _ o r) = (pretty (InfixExpr o) >> space) |=> pretty r+prettyHsExpr (ExplicitTuple _ full _) = horizontal <-|> vertical+ where+ horizontal = hTuple $ fmap pretty full+ vertical =+ parens $+ prefixedLined "," $+ fmap (\e -> unless (isMissing e) (space |=> pretty e)) full+ isMissing Missing {} = True+ isMissing _ = False+prettyHsExpr (ExplicitSum _ position numElem expr) = do+ string "(#"+ forM_ [1 .. numElem] $ \idx -> do+ if idx == position+ then string " " >> pretty expr >> string " "+ else string " "+ when (idx < numElem) $ string "|"+ string "#)"+prettyHsExpr (HsCase _ cond arms) = do+ string "case " |=> do+ pretty cond+ string " of"+ if null $ unLoc $ mg_alts arms+ then string " {}"+ else do+ newline+ indentedBlock $ pretty arms+prettyHsExpr (HsIf _ cond t f) = do+ string "if " |=> pretty cond+ indentedBlock $ newlinePrefixed [branch "then " t, branch "else " f]+ where+ branch :: String -> LHsExpr GhcPs -> Printer ()+ branch str e =+ case e of+ (L _ (HsDo _ DoExpr {} xs)) -> doStmt "do" xs+ (L _ (HsDo _ MDoExpr {} xs)) -> doStmt "mdo" xs+ _ -> string str |=> pretty e+ where+ doStmt pref stmts = do+ string $ str ++ pref+ newline+ indentedBlock $ printCommentsAnd stmts (lined . fmap pretty)+prettyHsExpr (HsMultiIf _ guards) =+ string "if " |=>+ lined (fmap (pretty . fmap (GRHSExpr GRHSExprMultiWayIf)) guards)+#if MIN_VERSION_ghc_lib_parser(9,4,1)+prettyHsExpr (HsLet _ _ binds _ exprs) = pretty $ LetIn binds exprs+#else+prettyHsExpr (HsLet _ binds exprs) = pretty $ LetIn binds exprs+#endif+prettyHsExpr (HsDo _ ListComp {} (L _ [])) =+ error "Not enough arguments are passed to pretty-print a list comprehension."+prettyHsExpr (HsDo _ ListComp {} (L l (lhs:rhs))) =+ pretty $ L l $ ListComprehension lhs rhs+-- While the name contains 'Monad', 'MonadComp' is for list comprehensions.+prettyHsExpr (HsDo _ MonadComp {} (L _ [])) =+ error "Not enough arguments are passed to pretty-print a list comprehension."+prettyHsExpr (HsDo _ MonadComp {} (L l (lhs:rhs))) =+ pretty $ L l $ ListComprehension lhs rhs+prettyHsExpr (HsDo _ DoExpr {} (L l xs)) = pretty $ L l $ DoExpression xs Do+prettyHsExpr (HsDo _ MDoExpr {} (L l xs)) = pretty $ L l $ DoExpression xs Mdo+prettyHsExpr (HsDo _ GhciStmtCtxt {} _) = error "We're not using GHCi, are we?"+prettyHsExpr (ExplicitList _ xs) = horizontal <-|> vertical+ where+ horizontal = brackets $ hCommaSep $ fmap pretty xs+ vertical = vList $ fmap pretty xs+prettyHsExpr (RecordCon _ name fields) = horizontal <-|> vertical+ where+ horizontal = spaced [pretty name, pretty fields]+ vertical = do+ pretty name+ (space >> pretty fields) <-|> (newline >> indentedBlock (pretty fields))+#if MIN_VERSION_ghc_lib_parser(9,4,1)+prettyHsExpr (RecordUpd _ name fields) = hor <-|> ver+ where+ hor = spaced [pretty name, either printHorFields printHorFields fields]+ ver = do+ pretty name+ newline+ indentedBlock $+ either printHorFields printHorFields fields <-|>+ either printVerFields printVerFields fields+ printHorFields ::+ (Pretty a, Pretty b, CommentExtraction l)+ => [GenLocated l (HsFieldBind a b)]+ -> Printer ()+ printHorFields = hFields . fmap (`printCommentsAnd` horField)+ printVerFields ::+ (Pretty a, Pretty b, CommentExtraction l)+ => [GenLocated l (HsFieldBind a b)]+ -> Printer ()+ printVerFields = vFields . fmap printField+ printField x = printCommentsAnd x $ (<-|>) <$> horField <*> verField+ horField HsFieldBind {..} = do+ pretty hfbLHS+ string " = "+ pretty hfbRHS+ verField HsFieldBind {..} = do+ pretty hfbLHS+ string " ="+ newline+ indentedBlock $ pretty hfbRHS+#else+prettyHsExpr (RecordUpd _ name fields) = hor <-|> ver+ where+ hor = spaced [pretty name, either printHorFields printHorFields fields]+ ver = do+ pretty name+ newline+ indentedBlock $+ either printHorFields printHorFields fields <-|>+ either printVerFields printVerFields fields+ printHorFields ::+ (Pretty a, Pretty b, CommentExtraction l)+ => [GenLocated l (HsRecField' a b)]+ -> Printer ()+ printHorFields = hFields . fmap (`printCommentsAnd` horField)+ printVerFields ::+ (Pretty a, Pretty b, CommentExtraction l)+ => [GenLocated l (HsRecField' a b)]+ -> Printer ()+ printVerFields = vFields . fmap printField+ printField x = printCommentsAnd x $ (<-|>) <$> horField <*> verField+ horField HsRecField {..} = do+ pretty hsRecFieldLbl+ string " = "+ pretty hsRecFieldArg+ verField HsRecField {..} = do+ pretty hsRecFieldLbl+ string " ="+ newline+ indentedBlock $ pretty hsRecFieldArg+#endif+prettyHsExpr (HsGetField _ e f) = do+ pretty e+ dot+ pretty f+prettyHsExpr HsProjection {..} =+ parens $+ forM_ proj_flds $ \x -> do+ string "."+ pretty x+prettyHsExpr (ExprWithTySig _ e sig) = do+ pretty e+ string " :: "+ pretty $ hswc_body sig+prettyHsExpr (ArithSeq _ _ x) = pretty x+prettyHsExpr (HsSpliceE _ x) = pretty x+prettyHsExpr (HsProc _ pat x@(L _ (HsCmdTop _ (L _ (HsCmdDo _ xs))))) = do+ spaced [string "proc", pretty pat, string "-> do"]+ newline+ indentedBlock $+ printCommentsAnd x (const (printCommentsAnd xs (lined . fmap pretty)))+prettyHsExpr (HsProc _ pat body) = hor <-|> ver+ where+ hor = spaced [string "proc", pretty pat, string "->", pretty body]+ ver = do+ spaced [string "proc", pretty pat, string "->"]+ newline+ indentedBlock (pretty body)+prettyHsExpr (HsStatic _ x) = spaced [string "static", pretty x]+prettyHsExpr (HsPragE _ p x) = spaced [pretty p, pretty x]+#if MIN_VERSION_ghc_lib_parser(9,4,1)+prettyHsExpr HsRecSel {} = notGeneratedByParser+prettyHsExpr (HsTypedBracket _ inner) = typedBrackets $ pretty inner+prettyHsExpr (HsUntypedBracket _ inner) = pretty inner+#else+prettyHsExpr HsConLikeOut {} = notGeneratedByParser+prettyHsExpr HsRecFld {} = notGeneratedByParser+prettyHsExpr (HsDo _ ArrowExpr {} _) = notGeneratedByParser+prettyHsExpr (HsDo _ PatGuard {} _) = notGeneratedByParser+prettyHsExpr (HsDo _ ParStmtCtxt {} _) = notGeneratedByParser+prettyHsExpr (HsDo _ TransStmtCtxt {} _) = notGeneratedByParser+prettyHsExpr HsTick {} = forHpc+prettyHsExpr HsBinTick {} = forHpc+prettyHsExpr (HsBracket _ inner) = pretty inner+prettyHsExpr HsRnBracketOut {} = notGeneratedByParser+prettyHsExpr HsTcBracketOut {} = notGeneratedByParser+#endif+instance Pretty LambdaCase where+ pretty' (LambdaCase matches caseOrCases) = do+ case caseOrCases of+ Case -> string "\\case"+ Cases -> string "\\cases"+ if null $ unLoc $ mg_alts matches+ then string " {}"+ else do+ newline+ indentedBlock $ pretty matches++instance Pretty (HsSigType GhcPs) where+ pretty' = pretty' . HsSigType' HsTypeForNormalDecl HsTypeNoDir++instance Pretty HsSigType' where+ pretty' (HsSigTypeInsideDeclSig HsSig {..}) =+ case sig_bndrs of+ HsOuterExplicit _ xs -> do+ string "forall "+ spaced $ fmap pretty xs+ dot+ case unLoc sig_body of+ HsQualTy {..} ->+ printCommentsAnd sig_body $ \_ ->+ let hor = do+ space+ pretty $ HorizontalContext hst_ctxt+ ver = do+ newline+ pretty $ VerticalContext hst_ctxt+ in do hor <-|> ver+ newline+ prefixed "=> " $+ prefixedLined "-> " $ pretty <$> flatten hst_body+ _ ->+ let hor = space >> pretty (fmap HsTypeInsideDeclSig sig_body)+ ver =+ newline >> prefixedLined "-> " (pretty <$> flatten sig_body)+ in hor <-|> ver+ _ -> pretty $ fmap HsTypeInsideDeclSig sig_body+ where+ flatten :: LHsType GhcPs -> [LHsType GhcPs]+ flatten (L _ (HsFunTy _ _ l r)) = flatten l ++ flatten r+ flatten x = [x]+ pretty' (HsSigTypeInsideVerticalFuncSig HsSig {..}) =+ case sig_bndrs of+ HsOuterExplicit _ xs -> do+ string "forall "+ spaced $ fmap pretty xs+ dot+ printCommentsAnd sig_body $ \case+ HsQualTy {..} -> do+ (space >> pretty (HorizontalContext hst_ctxt)) <-|>+ (newline >> pretty (VerticalContext hst_ctxt))+ newline+ prefixed "=> " $ pretty hst_body+ x -> pretty $ HsTypeInsideDeclSig x+ _ -> pretty $ fmap HsTypeInsideDeclSig sig_body+ pretty' (HsSigType' for dir HsSig {..}) = do+ case sig_bndrs of+ HsOuterExplicit _ xs -> do+ string "forall "+ spaced $ fmap pretty xs+ dot+ space+ _ -> return ()+ pretty $ HsType' for dir <$> sig_body++instance Pretty (ConDecl GhcPs) where+ pretty' = prettyConDecl++prettyConDecl :: ConDecl GhcPs -> Printer ()+prettyConDecl ConDeclGADT {..} = do+ hCommaSep $ fmap pretty con_names+ hor <-|> ver+ where+ hor = string " :: " |=> body+ ver = do+ newline+ indentedBlock (string ":: " |=> body)+ body =+ case (forallNeeded, con_mb_cxt) of+ (True, Just ctx) -> withForallCtx ctx+ (True, Nothing) -> withForallOnly+ (False, Just ctx) -> withCtxOnly ctx+ (False, Nothing) -> noForallCtx+ withForallOnly = do+ pretty con_bndrs+ (space >> horArgs) <-|> (newline >> verArgs)+ noForallCtx = horArgs <-|> verArgs+#if MIN_VERSION_ghc_lib_parser(9,4,1)+ withForallCtx ctx = do+ pretty con_bndrs+ (space >> pretty (Context ctx)) <-|> (newline >> pretty (Context ctx))+ newline+ prefixed "=> " verArgs+ + withCtxOnly ctx =+ (pretty (Context ctx) >> string " => " >> horArgs) <-|>+ (pretty (Context ctx) >> prefixed "=> " verArgs)+ + horArgs =+ case con_g_args of+ PrefixConGADT xs ->+ inter (string " -> ") $+ fmap (\(HsScaled _ x) -> pretty x) xs ++ [pretty con_res_ty]+ RecConGADT xs _ -> inter (string " -> ") [recArg xs, pretty con_res_ty]+ + verArgs =+ case con_g_args of+ PrefixConGADT xs ->+ prefixedLined "-> " $+ fmap (\(HsScaled _ x) -> pretty x) xs ++ [pretty con_res_ty]+ RecConGADT xs _ -> prefixedLined "-> " [recArg xs, pretty con_res_ty]+#else+ withForallCtx _ = do+ pretty con_bndrs+ (space >> pretty (Context con_mb_cxt)) <-|>+ (newline >> pretty (Context con_mb_cxt))+ newline+ prefixed "=> " verArgs+ + withCtxOnly _ =+ (pretty (Context con_mb_cxt) >> string " => " >> horArgs) <-|>+ (pretty (Context con_mb_cxt) >> prefixed "=> " verArgs)+ + horArgs =+ case con_g_args of+ PrefixConGADT xs ->+ inter (string " -> ") $+ fmap (\(HsScaled _ x) -> pretty x) xs ++ [pretty con_res_ty]+ RecConGADT xs -> inter (string " -> ") [recArg xs, pretty con_res_ty]+ + verArgs =+ case con_g_args of+ PrefixConGADT xs ->+ prefixedLined "-> " $+ fmap (\(HsScaled _ x) -> pretty x) xs ++ [pretty con_res_ty]+ RecConGADT xs -> prefixedLined "-> " [recArg xs, pretty con_res_ty]+#endif+ recArg xs = printCommentsAnd xs $ \xs' -> vFields' $ fmap pretty xs'+ + forallNeeded =+ case unLoc con_bndrs of+ HsOuterImplicit {} -> False+ HsOuterExplicit {} -> True+#if MIN_VERSION_ghc_lib_parser(9,4,1)+prettyConDecl ConDeclH98 {con_forall = True, ..} =+ (do string "forall "+ spaced $ fmap pretty con_ex_tvs+ string ". ") |=>+ (do whenJust con_mb_cxt $ \c -> do+ pretty $ Context c+ string " =>"+ newline+ pretty con_name+ pretty con_args)+#else+prettyConDecl ConDeclH98 {con_forall = True, ..} =+ (do string "forall "+ spaced $ fmap pretty con_ex_tvs+ string ". ") |=>+ (do whenJust con_mb_cxt $ \_ -> do+ pretty $ Context con_mb_cxt+ string " =>"+ newline+ pretty con_name+ pretty con_args)+#endif+prettyConDecl ConDeclH98 {con_forall = False, ..} =+ case con_args of+ (InfixCon l r) ->+ spaced [pretty l, pretty $ fmap InfixOp con_name, pretty r]+ _ -> do+ pretty con_name+ pretty con_args++instance Pretty (Match GhcPs (GenLocated SrcSpanAnnA (HsExpr GhcPs))) where+ pretty' = prettyMatchExpr++prettyMatchExpr :: Match GhcPs (LHsExpr GhcPs) -> Printer ()+prettyMatchExpr Match {m_ctxt = LambdaExpr, ..} = do+ string "\\"+ unless (null m_pats) $+ case unLoc $ head m_pats of+ LazyPat {} -> space+ BangPat {} -> space+ _ -> return ()+ spaced $ fmap pretty m_pats+ pretty $ GRHSsExpr GRHSExprLambda m_grhss+prettyMatchExpr Match {m_ctxt = CaseAlt, ..} = do+ mapM_ pretty m_pats+ pretty $ GRHSsExpr GRHSExprCase m_grhss+#if MIN_VERSION_ghc_lib_parser(9,4,1)+prettyMatchExpr Match {m_ctxt = LamCaseAlt {}, ..} = do+ spaced $ fmap pretty m_pats+ pretty $ GRHSsExpr GRHSExprCase m_grhss+#endif+prettyMatchExpr Match {..} =+ case mc_fixity m_ctxt of+ Prefix -> do+ pretty m_ctxt+ spacePrefixed $ fmap pretty m_pats+ pretty m_grhss+ Infix -> do+ case (m_pats, m_ctxt) of+ (l:r:xs, FunRhs {..}) -> do+ spaced $+ [pretty l, pretty $ fmap InfixOp mc_fun, pretty r] ++ fmap pretty xs+ pretty m_grhss+ _ -> error "Not enough parameters are passed."++instance Pretty (Match GhcPs (GenLocated SrcSpanAnnA (HsCmd GhcPs))) where+ pretty' = prettyMatchProc++prettyMatchProc :: Match GhcPs (LHsCmd GhcPs) -> Printer ()+prettyMatchProc Match {m_ctxt = LambdaExpr, ..} = do+ string "\\"+ unless (null m_pats) $+ case unLoc $ head m_pats of+ LazyPat {} -> space+ BangPat {} -> space+ _ -> return ()+ spaced $ fmap pretty m_pats ++ [pretty m_grhss]+prettyMatchProc Match {m_ctxt = CaseAlt, ..} =+ spaced [mapM_ pretty m_pats, pretty m_grhss]+#if MIN_VERSION_ghc_lib_parser(9,4,1)+prettyMatchProc Match {m_ctxt = LamCaseAlt {}, ..} = do+ spaced [mapM_ pretty m_pats, pretty m_grhss]+#endif+prettyMatchProc _ = notGeneratedByParser++instance Pretty (StmtLR GhcPs GhcPs (GenLocated SrcSpanAnnA (HsExpr GhcPs))) where+ pretty' (LastStmt _ x _ _) = pretty x+ pretty' (BindStmt _ pat body) = do+ pretty pat+ string " <-"+ hor <-|> ver+ where+ hor = space >> pretty body+ ver = newline >> indentedBlock (pretty body)+ pretty' ApplicativeStmt {} = notGeneratedByParser+ pretty' (BodyStmt _ (L loc (OpApp _ l o r)) _ _) =+ pretty (L loc (InfixApp l o r True))+ pretty' (BodyStmt _ body _ _) = pretty body+ pretty' (LetStmt _ l) = string "let " |=> pretty l+ pretty' (ParStmt _ xs _ _) = hvBarSep $ fmap pretty xs+ pretty' TransStmt {..} =+ vCommaSep $ fmap pretty trS_stmts ++ [string "then " >> pretty trS_using]+ pretty' RecStmt {..} =+ string "rec " |=> printCommentsAnd recS_stmts (lined . fmap pretty)++instance Pretty (StmtLR GhcPs GhcPs (GenLocated SrcSpanAnnA (HsCmd GhcPs))) where+ pretty' (LastStmt _ x _ _) = pretty x+ pretty' (BindStmt _ pat body) = hor <-|> ver+ where+ hor = spaced [pretty pat, string "<-", pretty body]+ ver = do+ pretty pat+ string " <-"+ newline+ indentedBlock $ pretty body+ pretty' ApplicativeStmt {} = notGeneratedByParser+ pretty' (BodyStmt _ body _ _) = pretty body+ pretty' (LetStmt _ l) = string "let " |=> pretty l+ pretty' (ParStmt _ xs _ _) = hvBarSep $ fmap pretty xs+ pretty' TransStmt {..} =+ vCommaSep $ fmap pretty trS_stmts ++ [string "then " >> pretty trS_using]+ pretty' RecStmt {..} =+ string "rec " |=> printCommentsAnd recS_stmts (lined . fmap pretty)++instance Pretty StmtLRInsideVerticalList where+ pretty' (StmtLRInsideVerticalList (ParStmt _ xs _ _)) =+ vBarSep $ fmap (pretty . ParStmtBlockInsideVerticalList) xs+ pretty' (StmtLRInsideVerticalList x) = pretty x++-- | For pattern matching.+instance Pretty (HsRecFields GhcPs (GenLocated SrcSpanAnnA (Pat GhcPs))) where+ pretty' HsRecFields {..} = horizontal <-|> vertical+ where+ horizontal =+ case rec_dotdot of+ Just _ -> braces $ string ".."+ Nothing -> hFields $ fmap pretty rec_flds+ vertical = vFields $ fmap pretty rec_flds++-- | For record updates+instance Pretty (HsRecFields GhcPs (GenLocated SrcSpanAnnA (HsExpr GhcPs))) where+ pretty' HsRecFields {..} = hvFields fieldPrinters+ where+ fieldPrinters =+ fmap pretty rec_flds +++ maybeToList (fmap (const (string "..")) rec_dotdot)++instance Pretty (HsType GhcPs) where+ pretty' = pretty' . HsType' HsTypeForNormalDecl HsTypeNoDir++instance Pretty HsType' where+ pretty' (HsTypeInsideVerticalFuncSig (HsFunTy _ _ a b)) = do+ pretty $ HsTypeInsideVerticalFuncSig <$> a+ newline+ prefixed "-> " $ pretty $ HsTypeInsideVerticalFuncSig <$> b+ pretty' (HsTypeInsideDeclSig HsQualTy {..}) = hor <-|> ver+ where+ hor = spaced [pretty $ Context hst_ctxt, string "=>", pretty hst_body]+ ver = do+ pretty $ Context hst_ctxt+ newline+ prefixed "=> " $ pretty $ fmap HsTypeInsideVerticalFuncSig hst_body+ pretty' (HsTypeInsideDeclSig (HsFunTy _ _ a b)) = hor <-|> ver+ where+ hor = spaced [pretty a, string "->", pretty b]+ ver = do+ pretty $ fmap HsTypeInsideVerticalFuncSig a+ newline+ prefixed "-> " $ pretty $ fmap HsTypeInsideVerticalFuncSig b+ pretty' (HsTypeInsideInstDecl HsQualTy {..}) = hor <-|> ver+ where+ hor = spaced [pretty (Context hst_ctxt), string "=>", pretty hst_body]+ ver = do+ pretty (Context hst_ctxt)+ string " =>"+ newline+ pretty hst_body+ pretty' (HsTypeWithVerticalAppTy (HsAppTy _ l r)) = do+ pretty $ fmap HsTypeWithVerticalAppTy l+ newline+ indentedBlock $ pretty $ fmap HsTypeWithVerticalAppTy r+ pretty' (HsType' _ _ x) = prettyHsType x++prettyHsType :: HsType GhcPs -> Printer ()+prettyHsType (HsForAllTy _ tele body) = (pretty tele >> space) |=> pretty body+prettyHsType HsQualTy {..} = hor <-|> ver+ where+ hor = spaced [pretty $ Context hst_ctxt, string "=>", pretty hst_body]+ ver = do+ pretty $ Context hst_ctxt+ lined [string " =>", indentedBlock $ pretty hst_body]+prettyHsType (HsTyVar _ NotPromoted x) = pretty x+prettyHsType (HsTyVar _ IsPromoted x) = string "'" >> pretty x+prettyHsType x@(HsAppTy _ l r) = hor <-|> ver+ where+ hor = spaced $ fmap pretty [l, r]+ ver = pretty $ HsTypeWithVerticalAppTy x+prettyHsType (HsAppKindTy _ l r) = pretty l >> string " @" >> pretty r+prettyHsType (HsFunTy _ _ a b) = (pretty a >> string " -> ") |=> pretty b+prettyHsType (HsListTy _ xs) = brackets $ pretty xs+prettyHsType (HsTupleTy _ HsUnboxedTuple []) = string "(# #)"+prettyHsType (HsTupleTy _ HsBoxedOrConstraintTuple []) = string "()"+prettyHsType (HsTupleTy _ HsUnboxedTuple xs) = hvUnboxedTuple' $ fmap pretty xs+prettyHsType (HsTupleTy _ HsBoxedOrConstraintTuple xs) =+ hvTuple' $ fmap pretty xs+prettyHsType (HsSumTy _ xs) = hvUnboxedSum' $ fmap pretty xs+ -- For `HsOpTy`, we do not need a single quote for the infix operator. An+ -- explicit promotion is necessary if there is a data constructor and+ -- a type with the same name. However, infix data constructors never+ -- share their names with types because types cannot contain symbols.+ -- Thus there is no ambiguity.+#if MIN_VERSION_ghc_lib_parser(9,4,1)+prettyHsType (HsOpTy _ _ l op r) = do+ lineBreak <- gets (configLineBreaks . psConfig)+ if showOutputable op `elem` lineBreak+ then do+ pretty l+ newline+ pretty $ fmap InfixOp op+ space+ pretty r+ else spaced [pretty l, pretty $ fmap InfixOp op, pretty r]+#else+prettyHsType (HsOpTy _ l op r) = do+ lineBreak <- gets (configLineBreaks . psConfig)+ if showOutputable op `elem` lineBreak+ then do+ pretty l+ newline+ pretty $ fmap InfixOp op+ space+ pretty r+ else spaced [pretty l, pretty $ fmap InfixOp op, pretty r]+#endif+prettyHsType (HsParTy _ inside) = parens $ pretty inside+prettyHsType (HsIParamTy _ x ty) =+ spaced [string "?" >> pretty x, string "::", pretty ty]+prettyHsType HsStarTy {} = string "*"+prettyHsType (HsKindSig _ t k) = spaced [pretty t, string "::", pretty k]+prettyHsType (HsSpliceTy _ sp) = pretty sp+prettyHsType HsDocTy {} = docNode+prettyHsType (HsBangTy _ pack x) = pretty pack >> pretty x+prettyHsType (HsRecTy _ xs) = hvFields $ fmap pretty xs+prettyHsType (HsExplicitListTy _ _ xs) =+ case xs of+ [] -> string "'[]"+ _ -> hvPromotedList $ fmap pretty xs+prettyHsType (HsExplicitTupleTy _ xs) = hPromotedTuple $ fmap pretty xs+prettyHsType (HsTyLit _ x) = pretty x+prettyHsType HsWildCardTy {} = string "_"+prettyHsType XHsType {} = notGeneratedByParser++instance Pretty (GRHSs GhcPs (GenLocated SrcSpanAnnA (HsExpr GhcPs))) where+ pretty' = pretty' . GRHSsExpr GRHSExprNormal++instance Pretty GRHSsExpr where+ pretty' (GRHSsExpr {grhssExpr = GRHSs {..}, ..}) = do+ mapM_ (pretty . fmap (GRHSExpr grhssExprType)) grhssGRHSs+ case (grhssLocalBinds, grhssExprType) of+ (HsValBinds {}, GRHSExprCase) ->+ indentedBlock $ do+ newline+ string "where " |=> pretty grhssLocalBinds+ (HsValBinds epa lr, _) ->+ indentedWithSpace 2 $+ newlinePrefixed+ [ string "where"+ , printCommentsAnd (L epa lr) (indentedWithSpace 2 . pretty)+ ]+ _ -> return ()++instance Pretty (GRHSs GhcPs (GenLocated SrcSpanAnnA (HsCmd GhcPs))) where+ pretty' GRHSs {..} = do+ mapM_ (pretty . fmap GRHSProc) grhssGRHSs+ case grhssLocalBinds of+ (HsValBinds epa lr) ->+ indentedWithSpace 2 $+ newlinePrefixed+ [ string "where"+ , printCommentsAnd (L epa lr) (indentedWithSpace 2 . pretty)+ ]+ _ -> return ()++instance Pretty (HsMatchContext GhcPs) where+ pretty' = prettyHsMatchContext++prettyHsMatchContext :: HsMatchContext GhcPs -> Printer ()+prettyHsMatchContext FunRhs {..} = pretty mc_strictness >> pretty mc_fun+prettyHsMatchContext LambdaExpr = return ()+prettyHsMatchContext CaseAlt = return ()+prettyHsMatchContext IfAlt {} = notGeneratedByParser+prettyHsMatchContext ArrowMatchCtxt {} = notGeneratedByParser+prettyHsMatchContext PatBindRhs {} = notGeneratedByParser+prettyHsMatchContext PatBindGuards {} = notGeneratedByParser+prettyHsMatchContext RecUpd {} = notGeneratedByParser+prettyHsMatchContext StmtCtxt {} = notGeneratedByParser+prettyHsMatchContext ThPatSplice {} = notGeneratedByParser+prettyHsMatchContext ThPatQuote {} = notGeneratedByParser+prettyHsMatchContext PatSyn {} = notGeneratedByParser+#if MIN_VERSION_ghc_lib_parser(9,4,1)+prettyHsMatchContext LamCaseAlt {} = notUsedInParsedStage+#endif+instance Pretty (ParStmtBlock GhcPs GhcPs) where+ pretty' (ParStmtBlock _ xs _ _) = hvCommaSep $ fmap pretty xs++instance Pretty ParStmtBlockInsideVerticalList where+ pretty' (ParStmtBlockInsideVerticalList (ParStmtBlock _ xs _ _)) =+ vCommaSep $ fmap pretty xs++instance Pretty RdrName where+ pretty' = pretty . PrefixOp++instance Pretty (GRHS GhcPs (GenLocated SrcSpanAnnA (HsExpr GhcPs))) where+ pretty' = pretty' . GRHSExpr GRHSExprNormal++instance Pretty GRHSExpr where+ pretty' (GRHSExpr {grhsExpr = (GRHS _ [] body), ..}) = do+ space+ rhsSeparator grhsExprType+ case unLoc body of+ HsDo _ DoExpr {} stmts ->+ printCommentsAnd body (const (doExpr "do" stmts))+ HsDo _ MDoExpr {} stmts ->+ printCommentsAnd body (const (doExpr "mdo" stmts))+ _ ->+ let hor = space >> pretty body+ ver = newline >> indentedBlock (pretty body)+ in hor <-|> ver+ where+ doExpr pref stmts = do+ space+ string pref+ newline+ indentedBlock $ printCommentsAnd stmts (lined . fmap pretty)+ pretty' (GRHSExpr {grhsExpr = (GRHS _ guards body), ..}) = do+ unless (grhsExprType == GRHSExprMultiWayIf) newline+ (if grhsExprType == GRHSExprMultiWayIf+ then id+ else indentedBlock) $ do+ string "| " |=> vCommaSep (fmap pretty guards)+ space+ rhsSeparator grhsExprType+ printCommentsAnd body $ \case+ HsDo _ DoExpr {} stmts -> doExpr "do" stmts+ HsDo _ MDoExpr {} stmts -> doExpr "mdo" stmts+ x ->+ let hor = space >> pretty x+ ver = newline >> indentedBlock (pretty x)+ in hor <-|> ver+ where+ doExpr pref stmts = do+ space+ string pref+ let hor = space >> printCommentsAnd stmts (lined . fmap pretty)+ ver = do+ newline+ indentedBlock (printCommentsAnd stmts (lined . fmap pretty))+ hor <-|> ver++instance Pretty GRHSProc where+ pretty' (GRHSProc (GRHS _ guards body)) =+ if null guards+ then bodyPrinter+ else do+ newline+ indentedBlock $ do+ string "| " |=> vCommaSep (fmap pretty guards)+ space+ bodyPrinter+ where+ bodyPrinter = do+ string "->"+ printCommentsAnd body $ \case+ HsCmdDo _ stmts ->+ let hor = space >> printCommentsAnd stmts (lined . fmap pretty)+ ver = do+ newline+ indentedBlock $ printCommentsAnd stmts (lined . fmap pretty)+ in hor <-|> ver+ x ->+ let hor = space >> pretty x+ ver = newline >> indentedBlock (pretty x)+ in hor <-|> ver++instance Pretty EpaCommentTok where+ pretty' (EpaLineComment c) = string c+ pretty' (EpaBlockComment c) =+ case lines c of+ [] -> pure ()+ [x] -> string x+ (x:xs) -> do+ string x+ newline+ -- 'indentedWithFixedLevel 0' is used because an 'EpaBlockComment'+ -- contains indent spaces for all lines except the first one.+ indentedWithFixedLevel 0 $ lined $ fmap string xs+ pretty' _ = docNode++instance Pretty (SpliceDecl GhcPs) where+ pretty' (SpliceDecl _ sp _) = pretty sp++instance Pretty (HsSplice GhcPs) where+ pretty' (HsTypedSplice _ _ _ body) = string "$$" >> pretty body+ pretty' (HsUntypedSplice _ DollarSplice _ body) = string "$" >> pretty body+ pretty' (HsUntypedSplice _ BareSplice _ body) = pretty body+ -- The body of a quasi-quote must not be changed by a formatter.+ -- Changing it will modify the actual behavior of the code.+ pretty' (HsQuasiQuote _ _ l _ r) =+ brackets $ do+ pretty l+ wrapWithBars $+ indentedWithFixedLevel 0 $ sequence_ $ printers [] "" $ unpackFS r+ where+ printers ps s [] = reverse (string (reverse s) : ps)+ printers ps s ('\n':xs) =+ printers (newline : string (reverse s) : ps) "" xs+ printers ps s (x:xs) = printers ps (x : s) xs+ pretty' HsSpliced {} = notGeneratedByParser++instance Pretty (Pat GhcPs) where+ pretty' = prettyPat++instance Pretty PatInsidePatDecl where+ pretty' (PatInsidePatDecl (ConPat {pat_args = (InfixCon l r), ..})) =+ spaced [pretty l, pretty $ fmap InfixOp pat_con, pretty r]+ pretty' (PatInsidePatDecl x) = pretty x++prettyPat :: Pat GhcPs -> Printer ()+prettyPat WildPat {} = string "_"+prettyPat (VarPat _ x) = pretty x+prettyPat (LazyPat _ x) = string "~" >> pretty x+prettyPat (AsPat _ a b) = pretty a >> string "@" >> pretty b+#if MIN_VERSION_ghc_lib_parser(9,4,1)+prettyPat (ParPat _ _ inner _) = parens $ pretty inner+#else+prettyPat (ParPat _ inner) = parens $ pretty inner+#endif+prettyPat (BangPat _ x) = string "!" >> pretty x+prettyPat (ListPat _ xs) = hList $ fmap pretty xs+prettyPat (TuplePat _ pats Boxed) = hTuple $ fmap pretty pats+prettyPat (TuplePat _ pats Unboxed) = hUnboxedTuple $ fmap pretty pats+prettyPat (SumPat _ x position numElem) = do+ string "(#"+ forM_ [1 .. numElem] $ \idx -> do+ if idx == position+ then string " " >> pretty x >> string " "+ else string " "+ when (idx < numElem) $ string "|"+ string "#)"+prettyPat ConPat {..} =+ case pat_args of+ PrefixCon _ as -> do+ pretty $ fmap PrefixOp pat_con+ spacePrefixed $ fmap pretty as+ RecCon rec -> (pretty pat_con >> space) |=> pretty (RecConPat rec)+ InfixCon a b -> do+ pretty a+ unlessSpecialOp (unLoc pat_con) space+ pretty $ fmap InfixOp pat_con+ unlessSpecialOp (unLoc pat_con) space+ pretty b+prettyPat (ViewPat _ l r) = spaced [pretty l, string "->", pretty r]+prettyPat (SplicePat _ x) = pretty x+prettyPat (LitPat _ x) = pretty x+prettyPat (NPat _ x _ _) = pretty x+prettyPat (NPlusKPat _ n k _ _ _) = pretty n >> string "+" >> pretty k+prettyPat (SigPat _ l r) = spaced [pretty l, string "::", pretty r]++instance Pretty RecConPat where+ pretty' (RecConPat HsRecFields {..}) =+ case fieldPrinters of+ [] -> string "{}"+ [x] -> braces x+ xs -> hvFields xs+ where+ fieldPrinters =+ fmap (pretty . fmap RecConField) rec_flds +++ maybeToList (fmap (const (string "..")) rec_dotdot)+#if !MIN_VERSION_ghc_lib_parser(9,4,1)+instance Pretty (HsBracket GhcPs) where+ pretty' (ExpBr _ expr) = brackets $ wrapWithBars $ pretty expr+ pretty' (PatBr _ expr) = brackets $ string "p" >> wrapWithBars (pretty expr)+ pretty' (DecBrL _ decls) =+ brackets $ string "d| " |=> lined (fmap pretty decls) >> string " |"+ pretty' DecBrG {} = notGeneratedByParser+ pretty' (TypBr _ expr) = brackets $ string "t" >> wrapWithBars (pretty expr)+ pretty' (VarBr _ True var) = string "'" >> pretty var+ pretty' (VarBr _ False var) = string "''" >> pretty var+ pretty' (TExpBr _ x) = typedBrackets $ pretty x+#endif+instance Pretty SigBindFamily where+ pretty' (Sig x) = pretty $ DeclSig x+ pretty' (Bind x) = pretty x+ pretty' (TypeFamily x) = pretty x+ pretty' (TyFamInst x) = pretty x+ pretty' (DataFamInst x) = pretty $ DataFamInstDeclInsideClassInst x++instance Pretty EpaComment where+ pretty' EpaComment {..} = pretty ac_tok++instance Pretty (HsLocalBindsLR GhcPs GhcPs) where+ pretty' (HsValBinds _ lr) = pretty lr+ pretty' (HsIPBinds _ x) = pretty x+ pretty' EmptyLocalBinds {} =+ error+ "This branch indicates that the bind is empty, but since calling this code means that let or where has already been output, it cannot be handled here. It should be handled higher up in the AST."++instance Pretty (HsValBindsLR GhcPs GhcPs) where+ pretty' (ValBinds _ methods sigs) = lined $ fmap pretty sigsAndMethods+ where+ sigsAndMethods =+ mkSortedLSigBindFamilyList sigs (bagToList methods) [] [] []+ pretty' XValBindsLR {} = notUsedInParsedStage++instance Pretty (HsTupArg GhcPs) where+ pretty' (Present _ e) = pretty e+ pretty' Missing {} = pure () -- This appears in a tuple section.+#if MIN_VERSION_ghc_lib_parser(9,4,1)+instance Pretty RecConField where+ pretty' (RecConField HsFieldBind {..}) = do+ pretty hfbLHS+ unless hfbPun $ do+ string " = "+ pretty hfbRHS+#else+-- | For pattern matching against a record.+instance Pretty+ (HsRecField' (FieldOcc GhcPs) (GenLocated SrcSpanAnnA (Pat GhcPs))) where+ pretty' HsRecField {..} =+ (pretty hsRecFieldLbl >> string " = ") |=> pretty hsRecFieldArg++-- | For record updates.+instance Pretty+ (HsRecField' (FieldOcc GhcPs) (GenLocated SrcSpanAnnA (HsExpr GhcPs))) where+ pretty' HsRecField {..} = do+ pretty hsRecFieldLbl+ unless hsRecPun $ do+ string " ="+ horizontal <-|> vertical+ where+ horizontal = space >> pretty hsRecFieldArg+ vertical = newline >> indentedBlock (pretty hsRecFieldArg)+#endif+#if MIN_VERSION_ghc_lib_parser(9,4,1)+-- | For pattern matchings against records.+instance Pretty+ (HsFieldBind+ (GenLocated (SrcAnn NoEpAnns) (FieldOcc GhcPs))+ (GenLocated SrcSpanAnnA (Pat GhcPs))) where+ pretty' HsFieldBind {..} = (pretty hfbLHS >> string " = ") |=> pretty hfbRHS++-- | For record updates.+instance Pretty+ (HsFieldBind+ (GenLocated (SrcAnn NoEpAnns) (FieldOcc GhcPs))+ (GenLocated SrcSpanAnnA (HsExpr GhcPs))) where+ pretty' HsFieldBind {..} = do+ pretty hfbLHS+ unless hfbPun $ do+ string " ="+ horizontal <-|> vertical+ where+ horizontal = space >> pretty hfbRHS+ vertical = newline >> indentedBlock (pretty hfbRHS)+#else+instance Pretty RecConField where+ pretty' (RecConField HsRecField {..}) = do+ pretty hsRecFieldLbl+ unless hsRecPun $ do+ string " = "+ pretty hsRecFieldArg+#endif+#if MIN_VERSION_ghc_lib_parser(9,4,1)+instance Pretty (FieldOcc GhcPs) where+ pretty' FieldOcc {..} = pretty foLabel+#else+instance Pretty (FieldOcc GhcPs) where+ pretty' FieldOcc {..} = pretty rdrNameFieldOcc+#endif+-- HsConDeclH98Details+instance Pretty+ (HsConDetails+ Void+ (HsScaled GhcPs (GenLocated SrcSpanAnnA (BangType GhcPs)))+ (GenLocated+ SrcSpanAnnL+ [GenLocated SrcSpanAnnA (ConDeclField GhcPs)])) where+ pretty' (PrefixCon _ xs) = horizontal <-|> vertical+ where+ horizontal = spacePrefixed $ fmap pretty xs+ vertical = indentedBlock $ newlinePrefixed $ fmap pretty xs+ pretty' (RecCon x) =+ printCommentsAnd x $ \rec -> do+ newline+ indentedBlock $ vFields $ fmap pretty rec+ pretty' InfixCon {} =+ error+ "Cannot handle here because 'InfixCon' does not have the information of its constructor."++instance Pretty a => Pretty (HsScaled GhcPs a) where+ pretty' (HsScaled _ x) = pretty x++instance Pretty (ConDeclField GhcPs) where+ pretty' ConDeclField {..}+ -- Here, we *ignore* the 'cd_fld_doc' field because doc strings are+ -- also stored as comments, and printing both results in duplicated+ -- comments.+ = do+ hCommaSep $ fmap pretty cd_fld_names+ string " :: "+ pretty cd_fld_type++instance Pretty InfixExpr where+ pretty' (InfixExpr (L _ (HsVar _ bind))) = pretty $ fmap InfixOp bind+ pretty' (InfixExpr x) = pretty' x++instance Pretty InfixApp where+ pretty' InfixApp {..} = horizontal <-|> vertical+ where+ horizontal = spaced [pretty lhs, pretty (InfixExpr op), pretty rhs]+ vertical = do+ lhsVer+ beforeRhs <-+ case unLoc lhs of+ (HsDo _ DoExpr {} _) -> do+ indentedWithSpace 3 (newline >> pretty (InfixExpr op)) -- 3 for "do "+ return space+ (HsDo _ MDoExpr {} _) -> do+ indentedWithSpace 4 (newline >> pretty (InfixExpr op)) -- 4 for "mdo "+ return space+ _ -> do+ space+ pretty (InfixExpr op)+ return newline+ case unLoc rhs of+ (HsDo _ (DoExpr _) xs) -> do+ string " do"+ newline+ indentedBlock $ printCommentsAnd xs (lined . fmap pretty)+ (HsDo _ (MDoExpr _) xs) -> do+ string " mdo"+ newline+ indentedBlock $ printCommentsAnd xs (lined . fmap pretty)+ HsLam {} -> do+ space+ pretty rhs+ HsLamCase {} -> do+ space+ pretty rhs+ _ ->+ (if immediatelyAfterDo+ then indentedBlock+ else id) $ do+ beforeRhs+ col <- startingColumn+ (if col == 0+ then indentedBlock+ else id) $+ pretty rhs+ lhsVer =+ case lhs of+ (L loc (OpApp _ l o r)) ->+ pretty (L loc (InfixApp l o r immediatelyAfterDo))+ _ -> pretty lhs++instance Pretty a => Pretty (BooleanFormula a) where+ pretty' (Var x) = pretty x+ pretty' (And xs) = hvCommaSep $ fmap pretty xs+ pretty' (Or xs) = hvBarSep $ fmap pretty xs+ pretty' (Parens x) = parens $ pretty x++instance Pretty (FieldLabelStrings GhcPs) where+ pretty' (FieldLabelStrings xs) = hDotSep $ fmap pretty xs++instance Pretty (AmbiguousFieldOcc GhcPs) where+ pretty' (Unambiguous _ name) = pretty name+ pretty' (Ambiguous _ name) = pretty name++instance Pretty (ImportDecl GhcPs) where+ pretty' decl@ImportDecl {..} = do+ string "import "+ when (ideclSource == IsBoot) $ string "{-# SOURCE #-} "+ when ideclSafe $ string "safe "+ unless (ideclQualified == NotQualified) $ string "qualified "+ whenJust (packageName decl) $ \x -> do+ pretty x+ space+ pretty ideclName+ whenJust ideclAs $ \x -> do+ string " as "+ pretty x+ whenJust ideclHiding $ \(x, ps) -> do+ when x (string " hiding")+ (string " " >> printCommentsAnd ps (hTuple . fmap pretty)) <-|>+ (newline >> indentedBlock (printCommentsAnd ps (vTuple . fmap pretty)))++packageName :: ImportDecl GhcPs -> Maybe StringLiteral+#if MIN_VERSION_ghc_lib_parser(9,4,1)+packageName (ideclPkgQual -> RawPkgQual name) = Just name+packageName _ = Nothing+#else+packageName = ideclPkgQual+#endif+instance Pretty (HsDerivingClause GhcPs) where+ pretty' HsDerivingClause { deriv_clause_strategy = Just strategy@(L _ ViaStrategy {})+ , ..+ } =+ spaced [string "deriving", pretty deriv_clause_tys, pretty strategy]+ pretty' HsDerivingClause {..} = do+ string "deriving "+ whenJust deriv_clause_strategy $ \x -> do+ pretty x+ space+ pretty deriv_clause_tys++instance Pretty (DerivClauseTys GhcPs) where+ pretty' (DctSingle _ ty) = parens $ pretty ty+ pretty' (DctMulti _ ts) = hvTuple $ fmap pretty ts++instance Pretty OverlapMode where+ pretty' NoOverlap {} = notUsedInParsedStage+ pretty' Overlappable {} = string "{-# OVERLAPPABLE #-}"+ pretty' Overlapping {} = string "{-# OVERLAPPING #-}"+ pretty' Overlaps {} = string "{-# OVERLAPS #-}"+ pretty' Incoherent {} = string "{-# INCOHERENT #-}"++instance Pretty StringLiteral where+ pretty' = output++-- | This instance is for type family declarations inside a class declaration.+instance Pretty (FamilyDecl GhcPs) where+ pretty' FamilyDecl {..} = do+ string $+ case fdInfo of+ DataFamily -> "data"+ OpenTypeFamily -> "type"+ ClosedTypeFamily {} -> "type"+ case fdTopLevel of+ TopLevel -> string " family "+ NotTopLevel -> space+ pretty fdLName+ spacePrefixed $ pretty <$> hsq_explicit fdTyVars+ case unLoc fdResultSig of+ NoSig {} -> pure ()+ TyVarSig {} -> do+ string " = "+ pretty fdResultSig+ _ -> do+ space+ pretty fdResultSig+ whenJust fdInjectivityAnn $ \x -> do+ string " | "+ pretty x+ case fdInfo of+ ClosedTypeFamily (Just xs) -> do+ string " where"+ newline+ indentedBlock $ lined $ fmap pretty xs+ _ -> pure ()++instance Pretty (FamilyResultSig GhcPs) where+ pretty' NoSig {} = pure ()+ pretty' (KindSig _ x) = string ":: " >> pretty x+ pretty' (TyVarSig _ x) = pretty x++instance Pretty (HsTyVarBndr a GhcPs) where+ pretty' (UserTyVar _ _ x) = pretty x+ pretty' (KindedTyVar _ _ name ty) =+ parens $ spaced [pretty name, string "::", pretty ty]++instance Pretty (InjectivityAnn GhcPs) where+ pretty' (InjectivityAnn _ from to) =+ spaced $ pretty from : string "->" : fmap pretty to++instance Pretty (ArithSeqInfo GhcPs) where+ pretty' (From from) = brackets $ spaced [pretty from, string ".."]+ pretty' (FromThen from next) =+ brackets $ spaced [pretty from >> comma >> pretty next, string ".."]+ pretty' (FromTo from to) =+ brackets $ spaced [pretty from, string "..", pretty to]+ pretty' (FromThenTo from next to) =+ brackets $+ spaced [pretty from >> comma >> pretty next, string "..", pretty to]++instance Pretty (HsForAllTelescope GhcPs) where+ pretty' HsForAllVis {..} = do+ string "forall "+ spaced $ fmap pretty hsf_vis_bndrs+ dot+ pretty' HsForAllInvis {..} = do+ string "forall "+ spaced $ fmap pretty hsf_invis_bndrs+ dot++instance Pretty InfixOp where+ pretty' (InfixOp (Unqual name)) = backticksIfNotSymbol name $ pretty name+ pretty' (InfixOp (Qual modName name)) =+ backticksIfNotSymbol name $ do+ pretty modName+ string "."+ pretty name+ pretty' (InfixOp Orig {}) = notUsedInParsedStage+ pretty' (InfixOp (Exact name)) = backticksIfNotSymbol occ $ pretty occ+ where+ occ = occName name++instance Pretty PrefixOp where+ pretty' (PrefixOp (Unqual name)) = parensIfSymbol name $ pretty name+ pretty' (PrefixOp (Qual modName name)) =+ parensIfSymbol name $ do+ pretty modName+ string "."+ pretty name+ pretty' (PrefixOp Orig {}) = notUsedInParsedStage+ pretty' (PrefixOp (Exact name)) = parensIfSymbol occ $ pretty occ+ where+ occ = occName name++instance Pretty Context where+ pretty' (Context xs) =+ pretty (HorizontalContext xs) <-|> pretty (VerticalContext xs)+#if MIN_VERSION_ghc_lib_parser(9,4,1)+instance Pretty HorizontalContext where+ pretty' (HorizontalContext xs) =+ constraintsParens $ printCommentsAnd xs (hCommaSep . fmap pretty)+ where+ constraintsParens =+ case xs of+ (L _ []) -> parens+ (L _ [_]) -> id+ _ -> parens++instance Pretty VerticalContext where+ pretty' (VerticalContext full@(L _ [])) =+ printCommentsAnd full (const $ string "()")+ pretty' (VerticalContext full@(L _ [x])) =+ printCommentsAnd full (const $ pretty x)+ pretty' (VerticalContext xs) = printCommentsAnd xs (vTuple . fmap pretty)+#else+instance Pretty HorizontalContext where+ pretty' (HorizontalContext xs) =+ constraintsParens $ mapM_ (`printCommentsAnd` (hCommaSep . fmap pretty)) xs+ where+ constraintsParens =+ case xs of+ Nothing -> id+ Just (L _ []) -> parens+ Just (L _ [_]) -> id+ Just _ -> parens++instance Pretty VerticalContext where+ pretty' (VerticalContext Nothing) = pure ()+ pretty' (VerticalContext (Just (L _ []))) = string "()"+ pretty' (VerticalContext (Just full@(L _ [x]))) =+ printCommentsAnd full (const $ pretty x)+ pretty' (VerticalContext (Just xs)) =+ printCommentsAnd xs (vTuple . fmap pretty)+#endif+-- Wrap a value of this type with 'ModulenameWithPrefix' to print it with+-- the "module " prefix.+instance Pretty ModuleName where+ pretty' = output++instance Pretty ModuleNameWithPrefix where+ pretty' (ModuleNameWithPrefix name) = spaced [string "module", pretty name]++instance Pretty (IE GhcPs) where+ pretty' (IEVar _ name) = pretty name+ pretty' (IEThingAbs _ name) = pretty name+ pretty' (IEThingAll _ name) = do+ pretty name+ string "(..)"+ -- FIXME: Currently, pretty-printing a 'IEThingWith' uses+ -- 'ghc-lib-parser''s pretty-printer. However, we should avoid it because+ -- 'ghc-lib-parser' may suddenly change how it prints, resulting in+ -- unexpected test failures.+ pretty' x@IEThingWith {} =+ case lines $ showOutputable x of+ [] -> pure ()+ [x'] -> string x'+ xs -> do+ string $ head xs+ indentedWithFixedLevel 0 $ newlinePrefixed $ string <$> tail xs+ pretty' (IEModuleContents _ name) = pretty $ fmap ModuleNameWithPrefix name+ pretty' IEGroup {} = docNode+ pretty' IEDoc {} = docNode+ pretty' IEDocNamed {} = docNode++instance Pretty (FamEqn GhcPs (GenLocated SrcSpanAnnA (HsType GhcPs))) where+ pretty' FamEqn {..} = do+ pretty feqn_tycon+ spacePrefixed $ fmap pretty feqn_pats+ string " = "+ pretty feqn_rhs++-- | Pretty-print a data instance.+instance Pretty (FamEqn GhcPs (HsDataDefn GhcPs)) where+ pretty' = pretty' . FamEqnTopLevel++instance Pretty FamEqn' where+ pretty' FamEqn' {famEqn = FamEqn {..}, ..} = do+ spaced $ string prefix : pretty feqn_tycon : fmap pretty feqn_pats+ pretty feqn_rhs+ where+ prefix =+ case famEqnFor of+ DataFamInstDeclForTopLevel -> "data instance"+ DataFamInstDeclForInsideClassInst -> "data"++-- | HsArg (LHsType GhcPs) (LHsType GhcPs)+instance Pretty+ (HsArg+ (GenLocated SrcSpanAnnA (HsType GhcPs))+ (GenLocated SrcSpanAnnA (HsType GhcPs))) where+ pretty' (HsValArg x) = pretty x+ pretty' (HsTypeArg _ x) = string "@" >> pretty x+ pretty' HsArgPar {} = notUsedInParsedStage+#if MIN_VERSION_ghc_lib_parser(9,4,1)+instance Pretty (HsQuote GhcPs) where+ pretty' (ExpBr _ x) = brackets $ wrapWithBars $ pretty x+ pretty' (PatBr _ x) = brackets $ string "p" >> wrapWithBars (pretty x)+ pretty' (DecBrL _ decls) =+ brackets $ string "d| " |=> lined (fmap pretty decls) >> string " |"+ pretty' DecBrG {} = notUsedInParsedStage+ pretty' (TypBr _ x) = brackets $ string "t" >> wrapWithBars (pretty x)+ pretty' (VarBr _ True x) = string "'" >> pretty x+ pretty' (VarBr _ False x) = string "''" >> pretty x+#endif+instance Pretty (WarnDecls GhcPs) where+ pretty' (Warnings _ _ x) = lined $ fmap pretty x++instance Pretty (WarnDecl GhcPs) where+ pretty' (Warning _ names deprecatedOrWarning) =+ case deprecatedOrWarning of+ DeprecatedTxt _ reasons -> prettyWithTitleReasons "DEPRECATED" reasons+ WarningTxt _ reasons -> prettyWithTitleReasons "WARNING" reasons+ where+ prettyWithTitleReasons title reasons =+ lined+ [ string $ "{-# " ++ title+ , spaced+ [hCommaSep $ fmap pretty names, hCommaSep $ fmap pretty reasons]+ , string " #-}"+ ]+#if MIN_VERSION_ghc_lib_parser(9,4,1)+instance Pretty (WithHsDocIdentifiers StringLiteral GhcPs) where+ pretty' WithHsDocIdentifiers {..} = pretty hsDocString+#endif+-- | 'Pretty' for 'LIEWrappedName (IdP GhcPs)'+instance Pretty (IEWrappedName RdrName) where+ pretty' (IEName name) = pretty name+ pretty' (IEPattern _ name) = spaced [string "pattern", pretty name]+ pretty' (IEType _ name) = string "type " >> pretty name+#if MIN_VERSION_ghc_lib_parser(9,4,1)+instance Pretty (DotFieldOcc GhcPs) where+ pretty' DotFieldOcc {..} = printCommentsAnd dfoLabel (string . unpackFS)+#else+instance Pretty (HsFieldLabel GhcPs) where+ pretty' HsFieldLabel {..} = printCommentsAnd hflLabel (string . unpackFS)+#endif+instance Pretty (RuleDecls GhcPs) where+ pretty' HsRules {..} =+ lined $ string "{-# RULES" : fmap pretty rds_rules ++ [string " #-}"]++instance Pretty (RuleDecl GhcPs) where+ pretty' HsRule {..} =+ spaced+ [ printCommentsAnd rd_name (doubleQuotes . string . unpackFS . snd)+ , lhs+ , string "="+ , pretty rd_rhs+ ]+ where+ lhs =+ if null rd_tmvs+ then pretty rd_lhs+ else do+ string "forall "+ spaced $ fmap pretty rd_tmvs+ dot+ space+ pretty rd_lhs++instance Pretty OccName where+ pretty' = output++instance Pretty (DerivDecl GhcPs) where+ pretty' DerivDecl { deriv_strategy = (Just deriv_strategy@(L _ ViaStrategy {}))+ , ..+ } =+ spaced+ [ string "deriving"+ , pretty deriv_strategy+ , string "instance"+ , pretty deriv_type+ ]+ pretty' DerivDecl {..} = do+ string "deriving "+ whenJust deriv_strategy $ \x -> do+ pretty x+ space+ string "instance "+ pretty deriv_type++-- | 'Pretty' for 'LHsSigWcType GhcPs'.+instance Pretty+ (HsWildCardBndrs GhcPs (GenLocated SrcSpanAnnA (HsSigType GhcPs))) where+ pretty' HsWC {..} = pretty hswc_body++-- | 'Pretty' for 'LHsWcType'+instance Pretty (HsWildCardBndrs GhcPs (GenLocated SrcSpanAnnA (HsType GhcPs))) where+ pretty' HsWC {..} = pretty hswc_body++instance Pretty (StandaloneKindSig GhcPs) where+ pretty' (StandaloneKindSig _ name kind) =+ spaced [string "type", pretty name, string "::", pretty kind]++instance Pretty (DefaultDecl GhcPs) where+ pretty' (DefaultDecl _ xs) =+ spaced [string "default", hTuple $ fmap pretty xs]++instance Pretty (ForeignDecl GhcPs) where+ pretty' ForeignImport {..} =+ spaced+ [ string "foreign import"+ , pretty fd_fi+ , pretty fd_name+ , string "::"+ , pretty fd_sig_ty+ ]+ pretty' ForeignExport {..} =+ spaced+ [ string "foreign export"+ , pretty fd_fe+ , pretty fd_name+ , string "::"+ , pretty fd_sig_ty+ ]++instance Pretty ForeignImport where+ pretty' (CImport conv safety _ _ (L _ (SourceText s))) =+ spaced [pretty conv, pretty safety, string s]+ pretty' (CImport conv safety _ _ _) = spaced [pretty conv, pretty safety]++instance Pretty ForeignExport where+ pretty' (CExport conv (L _ (SourceText s))) = spaced [pretty conv, string s]+ pretty' (CExport conv _) = pretty conv++instance Pretty CExportSpec where+ pretty' (CExportStatic _ _ x) = pretty x++instance Pretty Safety where+ pretty' PlaySafe = string "safe"+ pretty' PlayInterruptible = string "interruptible"+ pretty' PlayRisky = string "unsafe"++instance Pretty (AnnDecl GhcPs) where+ pretty' (HsAnnotation _ _ (ValueAnnProvenance name) expr) =+ spaced [string "{-# ANN", pretty name, pretty expr, string "#-}"]+ pretty' (HsAnnotation _ _ (TypeAnnProvenance name) expr) =+ spaced [string "{-# ANN type", pretty name, pretty expr, string "#-}"]+ pretty' (HsAnnotation _ _ ModuleAnnProvenance expr) =+ spaced [string "{-# ANN module", pretty expr, string "#-}"]++instance Pretty (RoleAnnotDecl GhcPs) where+ pretty' (RoleAnnotDecl _ name roles) =+ spaced $+ [string "type role", pretty name] +++ fmap (maybe (string "_") pretty . unLoc) roles++instance Pretty Role where+ pretty' Nominal = string "nominal"+ pretty' Representational = string "representational"+ pretty' Phantom = string "phantom"++instance Pretty (TyFamInstDecl GhcPs) where+ pretty' TyFamInstDecl {..} = string "type " >> pretty tfid_eqn++instance Pretty TopLevelTyFamInstDecl where+ pretty' (TopLevelTyFamInstDecl TyFamInstDecl {..}) =+ string "type instance " >> pretty tfid_eqn++instance Pretty (DataFamInstDecl GhcPs) where+ pretty' = pretty' . DataFamInstDeclTopLevel++instance Pretty DataFamInstDecl' where+ pretty' DataFamInstDecl' {dataFamInstDecl = DataFamInstDecl {..}, ..} =+ pretty $ FamEqn' dataFamInstDeclFor dfid_eqn++instance Pretty (PatSynBind GhcPs GhcPs) where+ pretty' PSB {..} = do+ string "pattern "+ case psb_args of+ InfixCon l r -> spaced [pretty l, pretty $ fmap InfixOp psb_id, pretty r]+ PrefixCon _ [] -> pretty psb_id+ _ -> spaced [pretty psb_id, pretty psb_args]+ spacePrefixed [pretty psb_dir, pretty $ fmap PatInsidePatDecl psb_def]+ case psb_dir of+ ExplicitBidirectional matches -> do+ newline+ indentedBlock $ string "where " |=> pretty matches+ _ -> pure ()++-- | 'Pretty' for 'HsPatSynDetails'.+instance Pretty+ (HsConDetails+ Void+ (GenLocated SrcSpanAnnN RdrName)+ [RecordPatSynField GhcPs]) where+ pretty' (PrefixCon _ xs) = spaced $ fmap pretty xs+ pretty' (RecCon rec) = hFields $ fmap pretty rec+ pretty' InfixCon {} =+ error+ "Cannot handle here because `InfixCon` does not have the information of the constructor."++instance Pretty (FixitySig GhcPs) where+ pretty' (FixitySig _ names fixity) =+ spaced [pretty fixity, hCommaSep $ fmap (pretty . fmap InfixOp) names]++instance Pretty Fixity where+ pretty' (Fixity _ level dir) = spaced [pretty dir, string $ show level]++instance Pretty FixityDirection where+ pretty' InfixL = string "infixl"+ pretty' InfixR = string "infixr"+ pretty' InfixN = string "infix"++instance Pretty InlinePragma where+ pretty' InlinePragma {..} = do+ pretty inl_inline+ case inl_act of+ ActiveBefore _ x -> space >> brackets (string $ "~" ++ show x)+ ActiveAfter _ x -> space >> brackets (string $ show x)+ _ -> pure ()++instance Pretty InlineSpec where+ pretty' = prettyInlineSpec++prettyInlineSpec :: InlineSpec -> Printer ()+prettyInlineSpec Inline {} = string "INLINE"+prettyInlineSpec Inlinable {} = string "INLINABLE"+prettyInlineSpec NoInline {} = string "NOINLINE"+prettyInlineSpec NoUserInlinePrag =+ error+ "This branch is executed if the inline pragma is not written, but executing this branch means that the pragma is already about to be output, which indicates something goes wrong."+#if MIN_VERSION_ghc_lib_parser(9,4,1)+prettyInlineSpec Opaque {} = string "OPAQUE"+#endif+instance Pretty (HsPatSynDir GhcPs) where+ pretty' Unidirectional = string "<-"+ pretty' ImplicitBidirectional = string "="+ pretty' ExplicitBidirectional {} = string "<-"++instance Pretty (HsOverLit GhcPs) where+ pretty' OverLit {..} = pretty ol_val++instance Pretty OverLitVal where+ pretty' (HsIntegral x) = pretty x+ pretty' (HsFractional x) = pretty x+ pretty' (HsIsString _ x) = string $ unpackFS x++instance Pretty IntegralLit where+ pretty' IL {il_text = SourceText s} = string s+ pretty' IL {..} = string $ show il_value++instance Pretty FractionalLit where+ pretty' = output++instance Pretty (HsLit GhcPs) where+ pretty' x@(HsChar _ _) = output x+ pretty' x@HsCharPrim {} = output x+ pretty' HsInt {} = notUsedInParsedStage+ pretty' (HsIntPrim _ x) = string $ show x ++ "#"+ pretty' HsWordPrim {} = notUsedInParsedStage+ pretty' HsInt64Prim {} = notUsedInParsedStage+ pretty' HsWord64Prim {} = notUsedInParsedStage+ pretty' HsInteger {} = notUsedInParsedStage+ pretty' HsRat {} = notUsedInParsedStage+ pretty' (HsFloatPrim _ x) = pretty x >> string "#"+ pretty' HsDoublePrim {} = notUsedInParsedStage+ pretty' x =+ case x of+ HsString {} -> prettyString+ HsStringPrim {} -> prettyString+ where+ prettyString =+ case lines $ showOutputable x of+ [] -> pure ()+ [l] -> string l+ (s:ss) ->+ string "" |=> do+ string s+ newline+ indentedWithSpace (-1) $+ lined $ fmap (string . dropWhile (/= '\\')) ss++instance Pretty (HsPragE GhcPs) where+ pretty' (HsPragSCC _ _ x) = spaced [string "{-# SCC", pretty x, string "#-}"]++instance Pretty HsIPName where+ pretty' (HsIPName x) = string $ unpackFS x++instance Pretty HsTyLit where+ pretty' (HsNumTy _ x) = string $ show x+ pretty' (HsStrTy _ x) = string $ ushow x+ pretty' (HsCharTy _ x) = string $ show x++instance Pretty (HsPatSigType GhcPs) where+ pretty' HsPS {..} = pretty hsps_body++instance Pretty (HsIPBinds GhcPs) where+ pretty' (IPBinds _ xs) = lined $ fmap pretty xs++instance Pretty (IPBind GhcPs) where+ pretty' = prettyIPBind++prettyIPBind :: IPBind GhcPs -> Printer ()+#if MIN_VERSION_ghc_lib_parser(9,4,1)+prettyIPBind (IPBind _ l r) =+ spaced [string "?" >> pretty l, string "=", pretty r]+#else+prettyIPBind (IPBind _ (Right _) _) = notUsedInParsedStage+prettyIPBind (IPBind _ (Left l) r) =+ spaced [string "?" >> pretty l, string "=", pretty r]+#endif+instance Pretty (DerivStrategy GhcPs) where+ pretty' StockStrategy {} = string "stock"+ pretty' AnyclassStrategy {} = string "anyclass"+ pretty' NewtypeStrategy {} = string "newtype"+ pretty' (ViaStrategy x) = string "via " >> pretty x++instance Pretty XViaStrategyPs where+ pretty' (XViaStrategyPs _ ty) = pretty ty++instance Pretty (RecordPatSynField GhcPs) where+ pretty' RecordPatSynField {..} = pretty recordPatSynField++instance Pretty (HsCmdTop GhcPs) where+ pretty' (HsCmdTop _ cmd) = pretty cmd++instance Pretty (HsCmd GhcPs) where+ pretty' = prettyHsCmd++prettyHsCmd :: HsCmd GhcPs -> Printer ()+prettyHsCmd (HsCmdArrApp _ f arg HsHigherOrderApp True) =+ spaced [pretty f, string "-<<", pretty arg]+prettyHsCmd (HsCmdArrApp _ f arg HsHigherOrderApp False) =+ spaced [pretty arg, string ">>-", pretty f]+prettyHsCmd (HsCmdArrApp _ f arg HsFirstOrderApp True) =+ spaced [pretty f, string "-<", pretty arg]+prettyHsCmd (HsCmdArrApp _ f arg HsFirstOrderApp False) =+ spaced [pretty arg, string ">-", pretty f]+prettyHsCmd (HsCmdArrForm _ f _ _ args) =+ bananaBrackets $ spaced $ pretty f : fmap pretty args+prettyHsCmd (HsCmdApp _ f arg) = spaced [pretty f, pretty arg]+prettyHsCmd (HsCmdLam _ x) = pretty x+#if MIN_VERSION_ghc_lib_parser(9,4,1)+prettyHsCmd (HsCmdPar _ _ x _) = parens $ pretty x+#else+prettyHsCmd (HsCmdPar _ x) = parens $ pretty x+#endif+prettyHsCmd (HsCmdCase _ cond arms) = do+ spaced [string "case", pretty cond, string "of"]+ newline+ indentedBlock $ pretty arms+#if MIN_VERSION_ghc_lib_parser(9,4,1)+prettyHsCmd (HsCmdLamCase _ _ arms) = do+ string "\\case"+ newline+ indentedBlock $ pretty arms+#else+prettyHsCmd (HsCmdLamCase _ arms) = do+ string "\\case"+ newline+ indentedBlock $ pretty arms+#endif+prettyHsCmd (HsCmdIf _ _ cond t f) = do+ string "if "+ pretty cond+ newline+ indentedBlock $ lined [string "then " >> pretty t, string "else " >> pretty f]+#if MIN_VERSION_ghc_lib_parser(9,4,1)+prettyHsCmd (HsCmdLet _ _ binds _ expr) =+ lined [string "let " |=> pretty binds, string " in " |=> pretty expr]+#else+prettyHsCmd (HsCmdLet _ binds expr) =+ lined [string "let " |=> pretty binds, string " in " |=> pretty expr]+#endif+prettyHsCmd (HsCmdDo _ stmts) = do+ string "do"+ newline+ indentedBlock $ printCommentsAnd stmts (lined . fmap pretty)++instance Pretty ListComprehension where+ pretty' ListComprehension {..} = horizontal <-|> vertical+ where+ horizontal =+ brackets $+ spaced+ [pretty listCompLhs, string "|", hCommaSep $ fmap pretty listCompRhs]+ vertical = do+ string "[ "+ pretty $ fmap StmtLRInsideVerticalList listCompLhs+ newline+ forM_ (stmtsAndPrefixes listCompRhs) $ \(p, x) -> do+ string p |=> pretty (fmap StmtLRInsideVerticalList x)+ newline+ string "]"+ stmtsAndPrefixes l = ("| ", head l) : fmap (", ", ) (tail l)++instance Pretty DoExpression where+ pretty' DoExpression {..} =+ (string pref >> space) |=> lined (fmap pretty doStmts)+ where+ pref =+ case doOrMdo of+ Do -> "do"+ Mdo -> "mdo"++instance Pretty LetIn where+ pretty' LetIn {..} =+ lined [string "let " |=> pretty letBinds, string " in " |=> pretty inExpr]++instance Pretty (RuleBndr GhcPs) where+ pretty' (RuleBndr _ name) = pretty name+ pretty' (RuleBndrSig _ name sig) =+ parens $ spaced [pretty name, string "::", pretty sig]++instance Pretty CCallConv where+ pretty' CCallConv = string "ccall"+ pretty' CApiConv = string "capi"+ pretty' StdCallConv = string "stdcall"+ pretty' PrimCallConv = string "prim"+ pretty' JavaScriptCallConv = string "javascript"++instance Pretty ModuleDeprecatedPragma where+ pretty' (ModuleDeprecatedPragma (WarningTxt _ xs)) =+ spaced [string "{-# WARNING", spaced $ fmap pretty xs, string "#-}"]+ pretty' (ModuleDeprecatedPragma (DeprecatedTxt _ xs)) =+ spaced [string "{-# DEPRECATED", spaced $ fmap pretty xs, string "#-}"]++instance Pretty HsSrcBang where+ pretty' (HsSrcBang _ unpack strictness) = do+ pretty unpack+ unless (unpack == NoSrcUnpack) space+ pretty strictness++instance Pretty SrcUnpackedness where+ pretty' SrcUnpack = string "{-# UNPACK #-}"+ pretty' SrcNoUnpack = string "{-# NOUNPACK #-}"+ pretty' NoSrcUnpack = pure ()++instance Pretty SrcStrictness where+ pretty' SrcLazy = string "~"+ pretty' SrcStrict = string "!"+ pretty' NoSrcStrict = pure ()++instance Pretty (HsOuterSigTyVarBndrs GhcPs) where+ pretty' HsOuterImplicit {} = pure ()+ pretty' HsOuterExplicit {..} = do+ string "forall"+ spacePrefixed $ fmap pretty hso_bndrs+ dot++-- | Marks an AST node as never appearing in an AST.+--+-- Some AST node types are only defined in `ghc-lib-parser` and not+-- generated by it.+notGeneratedByParser :: HasCallStack => a+notGeneratedByParser = error "`ghc-lib-parser` never generates this AST node."++-- | Marks an AST node as related to Haddock comments.+--+-- The parser parses haddock comments as normal ones, meaning AST nodes+-- related to haddock never appear in an AST.+docNode :: HasCallStack => a+docNode =+ error+ "This AST node is related to Haddocks, but haddock comments are treated as normal ones, and this node should never appear in an AST."++-- | Marks an AST node as never appearing in the AST.+--+-- Some AST node types are only used in the renaming or type-checking phase.+notUsedInParsedStage :: HasCallStack => a+notUsedInParsedStage =+ error+ "This AST should never appears in an AST. It only appears in the renaming or type checked stages."+#if !MIN_VERSION_ghc_lib_parser(9,4,1)+-- | Marks an AST node as it is used only for Haskell Program Coverage.+forHpc :: HasCallStack => a+forHpc = error "This AST type is for the use of Haskell Program Coverage."+#endif
+ src/HIndent/Pretty/Combinators.hs view
@@ -0,0 +1,24 @@+-- | A module to import all @HIndent.Pretty.Combinators.*@s.+module HIndent.Pretty.Combinators+ ( module HIndent.Pretty.Combinators.Comment+ , module HIndent.Pretty.Combinators.Getter+ , module HIndent.Pretty.Combinators.Indent+ , module HIndent.Pretty.Combinators.Lineup+ , module HIndent.Pretty.Combinators.Op+ , module HIndent.Pretty.Combinators.Outputable+ , module HIndent.Pretty.Combinators.RhsSeparator+ , module HIndent.Pretty.Combinators.String+ , module HIndent.Pretty.Combinators.Switch+ , module HIndent.Pretty.Combinators.Wrap+ ) where++import HIndent.Pretty.Combinators.Comment+import HIndent.Pretty.Combinators.Getter+import HIndent.Pretty.Combinators.Indent+import HIndent.Pretty.Combinators.Lineup+import HIndent.Pretty.Combinators.Op+import HIndent.Pretty.Combinators.Outputable+import HIndent.Pretty.Combinators.RhsSeparator+import HIndent.Pretty.Combinators.String+import HIndent.Pretty.Combinators.Switch+import HIndent.Pretty.Combinators.Wrap
+ src/HIndent/Pretty/Combinators/Comment.hs view
@@ -0,0 +1,12 @@+-- | Printer combinators for handling comments.+module HIndent.Pretty.Combinators.Comment+ ( eolCommentsArePrinted+ ) where++import Control.Monad.State+import HIndent.Printer++-- | Claims that comments were printed. Next time calling 'string' will+-- print a newline before printing a text.+eolCommentsArePrinted :: Printer ()+eolCommentsArePrinted = modify (\s -> s {psEolComment = True})
+ src/HIndent/Pretty/Combinators/Getter.hs view
@@ -0,0 +1,31 @@+-- | Getters to fetch current status and printer information.+module HIndent.Pretty.Combinators.Getter+ ( startingColumn+ , printerLength+ ) where++import Control.Monad.RWS hiding (state)+import Data.Int+import HIndent.Pretty.Combinators.String+import HIndent.Printer++-- | Returns the column from which a new string is printed. It may be+-- different from 'psColumn' immediately after printing a comment.+startingColumn :: Printer Int64+startingColumn = do+ before <- get+ string ""+ after <- get+ put before+ return $ psColumn after++-- Returns how many characters the printer moved the cursor horizontally.+-- The returned value maybe negative if the printer prints multiple lines+-- and the column of the last position is less than before.+printerLength :: Printer a -> Printer Int64+printerLength p = do+ before <- get+ _ <- p+ after <- get+ put before+ pure $ psColumn after - psColumn before
+ src/HIndent/Pretty/Combinators/Indent.hs view
@@ -0,0 +1,67 @@+-- | Printer combinators related to indent.+module HIndent.Pretty.Combinators.Indent+ ( indentedBlock+ , indentedWithSpace+ , (|=>)+ , indentedWithFixedLevel+ , prefixed+ , getIndentSpaces+ ) where++import Control.Monad.State+import Data.Int+import HIndent.Config+import HIndent.Pretty.Combinators.String+import HIndent.Printer++-- | This function runs the given printer with an additional indent. The+-- indent has 'configIndentSpaces' spaces.+indentedBlock :: Printer a -> Printer a+indentedBlock p = do+ indentSpaces <- getIndentSpaces+ indentedWithSpace indentSpaces p++-- | This function runs the given printer with an additional indent. The+-- indent has the specified number of spaces.+indentedWithSpace :: Int64 -> Printer a -> Printer a+indentedWithSpace i p = do+ level <- gets psIndentLevel+ indentedWithFixedLevel (level + i) p++-- | This function runs the first printer, fixes the indent, and then runs+-- the second one.+--+-- For example,+--+-- > string "foo " |=> lined [string "bar", "baz"]+--+-- will print texts as below.+-- foo bar+-- baz+(|=>) :: Printer () -> Printer a -> Printer a+hd |=> p = do+ hd+ col <- gets psColumn+ indentedWithFixedLevel col p++infixl 1 |=>++-- | This function runs the given printer with the passed indent level.+indentedWithFixedLevel :: Int64 -> Printer a -> Printer a+indentedWithFixedLevel i p = do+ l <- gets psIndentLevel+ modify (\s -> s {psIndentLevel = i})+ m <- p+ modify (\s -> s {psIndentLevel = l})+ return m++-- | Prints the text passed as the first argument before the current+-- position and then the second argument.+prefixed :: String -> Printer () -> Printer ()+prefixed s p = do+ indentedWithSpace (-(fromIntegral $ length s)) $ string s+ p++-- | This function returns the current indent level.+getIndentSpaces :: Printer Int64+getIndentSpaces = gets (configIndentSpaces . psConfig)
+ src/HIndent/Pretty/Combinators/Lineup.hs view
@@ -0,0 +1,246 @@+-- | Printer combinators for lining up multiple elements.+module HIndent.Pretty.Combinators.Lineup+ ( -- * Tuples+ hvTuple+ , hvTuple'+ , hTuple+ , vTuple+ , vTuple'+ , hPromotedTuple+ , -- * Unboxed tuples+ hvUnboxedTuple'+ , hUnboxedTuple+ , -- * Unboxed sums+ hvUnboxedSum'+ , -- * Records+ hvFields+ , hFields+ , vFields+ , vFields'+ , -- * Lists+ hList+ , vList+ , hvPromotedList+ , -- * Bars+ hvBarSep+ , hBarSep+ , vBarSep+ , -- * Commas+ hvCommaSep+ , hCommaSep+ , vCommaSep+ , -- * Others+ spaced+ , lined+ , blanklined+ , hDotSep+ , spacePrefixed+ , newlinePrefixed+ , prefixedLined+ , inter+ ) where++import Control.Monad+import Data.List+import HIndent.Pretty.Combinators.Indent+import HIndent.Pretty.Combinators.String+import HIndent.Pretty.Combinators.Switch+import HIndent.Pretty.Combinators.Wrap+import HIndent.Printer++-- | Applies 'hTuple' if the result fits in a line or 'vTuple' otherwise.+hvTuple :: [Printer ()] -> Printer ()+hvTuple = (<-|>) <$> hTuple <*> vTuple++-- | Applies 'hTuple'' if the result fits in a line or 'vTuple'' otherwise.+hvTuple' :: [Printer ()] -> Printer ()+hvTuple' = (<-|>) <$> hTuple <*> vTuple'++-- | Runs printers to construct a tuple in a line.+hTuple :: [Printer ()] -> Printer ()+hTuple = parens . hCommaSep++-- | Runs printers to construct a tuple where elements are aligned+-- vertically.+vTuple :: [Printer ()] -> Printer ()+vTuple = vCommaSepWrapped ("(", ")")++-- | Similar to 'vTuple', but the closing parenthesis is in the last+-- element.+vTuple' :: [Printer ()] -> Printer ()+vTuple' = vCommaSepWrapped' ("(", ")")++-- | Runs printers to construct a promoted tuple in a line.+hPromotedTuple :: [Printer ()] -> Printer ()+hPromotedTuple = promotedTupleParens . hCommaSep++-- | Runs printers to construct an unboxed tuple. The elements are aligned+-- either in a line or vertically.+hvUnboxedTuple' :: [Printer ()] -> Printer ()+hvUnboxedTuple' = (<-|>) <$> hUnboxedTuple <*> vUnboxedTuple'++-- | Runs printers to construct an unboxed tuple in a line.+hUnboxedTuple :: [Printer ()] -> Printer ()+hUnboxedTuple = unboxedParens . hCommaSep++-- | Runs printers to construct an unboxed tuple where the elements are+-- aligned vertically.+vUnboxedTuple' :: [Printer ()] -> Printer ()+vUnboxedTuple' = vCommaSepWrapped' ("(#", " #)")++-- | Runs printers to construct an unboxed sum. The elements are aligned+-- either in a line or vertically.+--+-- The enclosing parenthesis will be printed on the same line as the last+-- element.+hvUnboxedSum' :: [Printer ()] -> Printer ()+hvUnboxedSum' = (<-|>) <$> hUnboxedSum <*> vUnboxedSum'++-- | Runs printers to construct an unboxed sum in a line.+hUnboxedSum :: [Printer ()] -> Printer ()+hUnboxedSum = unboxedParens . hBarSep++-- | Runs printers to construct an unboxed sum where the elements are+-- aligned vertically.+--+-- The enclosing parenthesis will be printed on the same line as the last+-- element.+vUnboxedSum' :: [Printer ()] -> Printer ()+vUnboxedSum' = vWrappedLineup' '|' ("(#", " #)")++-- | Applies 'hFields' if the result fits in a line or 'vFields' otherwise.+hvFields :: [Printer ()] -> Printer ()+hvFields = (<-|>) <$> hFields <*> vFields++-- | Runs printers to construct a record in a line.+hFields :: [Printer ()] -> Printer ()+hFields = braces . hCommaSep++-- | Runs printers to construct a record where elements are aligned+-- vertically.+vFields :: [Printer ()] -> Printer ()+vFields = vCommaSepWrapped ("{", "}")++-- | Similar to 'vFields', but the closing brace is in the same line as the+-- last element.+vFields' :: [Printer ()] -> Printer ()+vFields' = vCommaSepWrapped' ("{", "}")++-- | Runs printers to construct a list in a line.+hList :: [Printer ()] -> Printer ()+hList = brackets . hCommaSep++-- | Runs printers to construct a list where elements are aligned+-- vertically.+vList :: [Printer ()] -> Printer ()+vList = vCommaSepWrapped ("[", "]")++-- | Runs printers to construct a promoted list where elements are aligned+-- in a line or vertically.+hvPromotedList :: [Printer ()] -> Printer ()+hvPromotedList = (<-|>) <$> hPromotedList <*> vPromotedList++-- | Runs printers to construct a promoted list in a line.+hPromotedList :: [Printer ()] -> Printer ()+hPromotedList = promotedListBrackets . hCommaSep++-- | Runs printers to construct a promoted list where elements are aligned+-- vertically.+vPromotedList :: [Printer ()] -> Printer ()+vPromotedList = vCommaSepWrapped ("'[", " ]")++-- | Runs printers in a line with a space as the separator.+spaced :: [Printer ()] -> Printer ()+spaced = inter space++-- | Runs printers line by line.+lined :: [Printer ()] -> Printer ()+lined = inter newline++-- | Runs printers with a blank line as the separator.+blanklined :: [Printer ()] -> Printer ()+blanklined = inter blankline++-- | Applies 'hBarSep' if the result fits in a line or 'vBarSep' otherwise.+hvBarSep :: [Printer ()] -> Printer ()+hvBarSep = (<-|>) <$> hBarSep <*> vBarSep++-- | Runs printers in a line with a bar as the separator.+hBarSep :: [Printer ()] -> Printer ()+hBarSep = inter (string " | ")++-- | Runs printers where each line except the first one has @| @ as+-- a prefix.+vBarSep :: [Printer ()] -> Printer ()+vBarSep = prefixedLined "| "++-- | Applies 'hCommaSep' if the result fits in a line or 'vCommaSep'+-- otherwise.+hvCommaSep :: [Printer ()] -> Printer ()+hvCommaSep = (<-|>) <$> hCommaSep <*> vCommaSep++-- | Runs printers in a line with a comma as the separator.+hCommaSep :: [Printer ()] -> Printer ()+hCommaSep = inter (string ", ")++-- | Runs printers with each line except the first one has @, @ as+-- a prefix.+vCommaSep :: [Printer ()] -> Printer ()+vCommaSep = prefixedLined ", "++-- | Prints elements separated by comma in vertical with the given prefix+-- and suffix.+vCommaSepWrapped :: (String, String) -> [Printer ()] -> Printer ()+vCommaSepWrapped = vWrappedLineup ','++-- | Similar to 'vCommaSepWrapped' but the suffix is in the same line as the last+-- element.+vCommaSepWrapped' :: (String, String) -> [Printer ()] -> Printer ()+vCommaSepWrapped' = vWrappedLineup' ','++-- | Runs printers with a dot as the separator.+hDotSep :: [Printer ()] -> Printer ()+hDotSep = inter (string ".")++-- | Prints each element after a space like.+spacePrefixed :: [Printer ()] -> Printer ()+spacePrefixed = mapM_ (space >>)++-- | Prints each element after a new line.+newlinePrefixed :: [Printer ()] -> Printer ()+newlinePrefixed = mapM_ (newline >>)++-- | Runs printers with a prefix. The prefix is printed before the indent.+prefixedLined :: String -> [Printer ()] -> Printer ()+prefixedLined _ [] = return ()+prefixedLined pref (x:xs) = do+ x+ forM_ xs $ \p -> do+ newline+ prefixed pref p++-- | Prints elements in vertical with the given prefix, suffix, and+-- separator.+vWrappedLineup :: Char -> (String, String) -> [Printer ()] -> Printer ()+vWrappedLineup sep (prefix, suffix) ps =+ string prefix >>+ space |=> do+ prefixedLined [sep, ' '] ps+ newline+ indentedWithSpace (-(fromIntegral (length prefix) + 1)) $ string suffix++-- | Similar to 'vWrappedLineup' but the suffix is in the same line as the+-- last element.+vWrappedLineup' :: Char -> (String, String) -> [Printer ()] -> Printer ()+vWrappedLineup' _ (prefix, suffix) [x] =+ spaced [string prefix, x, string suffix]+vWrappedLineup' sep (prefix, suffix) ps =+ string prefix >>+ space |=> do+ prefixedLined [sep, ' '] ps+ string suffix++-- Inserts the first printer between each element of the list passed as the+-- second argument and runs them.+inter :: Printer () -> [Printer ()] -> Printer ()+inter separator = sequence_ . intersperse separator
+ src/HIndent/Pretty/Combinators/Op.hs view
@@ -0,0 +1,24 @@+-- | Printer combinators related to operators.+module HIndent.Pretty.Combinators.Op+ ( unlessSpecialOp+ ) where++import Control.Monad+import GHC.Types.Name+import GHC.Types.Name.Reader+import HIndent.Printer++-- | Runs the printer unless HIndent needs to treat the operator specially.+unlessSpecialOp :: RdrName -> Printer () -> Printer ()+unlessSpecialOp name = unless (isSpecialOp name)++-- | Returns if HIndent needs special treatment for the operator.+isSpecialOp :: RdrName -> Bool+isSpecialOp (Unqual name) = isSpecialOpString $ occNameString name+isSpecialOp Qual {} = False+isSpecialOp Orig {} = error "This node is never used in the parsed stage."+isSpecialOp (Exact name) = isSpecialOpString $ occNameString $ nameOccName name++-- | Returns if HIndent needs special treatment for the operator.+isSpecialOpString :: String -> Bool+isSpecialOpString name = name `elem` ["()", "[]", "->", ":"]
+ src/HIndent/Pretty/Combinators/Outputable.hs view
@@ -0,0 +1,36 @@+-- | Printer combinators for printing values of types implementing+-- 'Outputable'.+module HIndent.Pretty.Combinators.Outputable+ ( output+ , showOutputable+ ) where++import GHC.Driver.Ppr+import GHC.Driver.Session+import GHC.Stack+import GHC.Utils.Outputable+import HIndent.Pretty.Combinators.String+import HIndent.Printer+import Language.Haskell.GhclibParserEx.GHC.Settings.Config++-- | Prints the given value using the type's 'Outputable' implementation.+--+-- The use of this function should be avoided for these reasons:+--+-- * It may raise an error due to 'showPpr' returning a 'String' containing+-- @\n@s. Use 'newline' to print @\n@s.+--+-- * ghc-lib-parser may change a type's implementation of 'Outputable',+-- causing a sudden test failure. It becomes a maintaince burden.+--+-- * All comments of the node's children are ignored.+output :: (HasCallStack, Outputable a) => a -> Printer ()+output = string . showOutputable++-- | Converts the given value to a 'String'.+showOutputable :: Outputable a => a -> String+showOutputable = showPpr dynFlags++-- | 'DynFlags' for calling 'showPpr'+dynFlags :: DynFlags+dynFlags = defaultDynFlags fakeSettings fakeLlvmConfig
+ src/HIndent/Pretty/Combinators/RhsSeparator.hs view
@@ -0,0 +1,16 @@+-- | Separator-related things (e.g., '=' and '->').+module HIndent.Pretty.Combinators.RhsSeparator+ ( rhsSeparator+ ) where++import HIndent.Pretty.Combinators.String+import HIndent.Pretty.Types+import HIndent.Printer++-- | Returns a separator between a LHS and a RHS according to the type of+-- the RHS.+rhsSeparator :: GRHSExprType -> Printer ()+rhsSeparator GRHSExprNormal = string "="+rhsSeparator GRHSExprCase = string "->"+rhsSeparator GRHSExprMultiWayIf = string "->"+rhsSeparator GRHSExprLambda = string "->"
+ src/HIndent/Pretty/Combinators/String.hs view
@@ -0,0 +1,78 @@+-- | Printer combinators related to print strings.+module HIndent.Pretty.Combinators.String+ ( string+ , space+ , newline+ , blankline+ , comma+ , dot+ ) where++import Control.Monad.RWS+import qualified Data.ByteString.Builder as S+import GHC.Stack+import HIndent.Config+import HIndent.Printer++-- | This function prints the given string.+--+-- The string must not include '\n's. Use 'newline' to print them.+string :: HasCallStack => String -> Printer ()+string x+ | '\n' `elem` x =+ error $+ "You tried to print " ++ show x ++ ". Use `newline` to print '\\n's."+ | otherwise = do+ eol <- gets psEolComment+ hardFail <- gets psFitOnOneLine+ when eol newline+ st <- get+ let indentSpaces =+ if psNewline st+ then replicate (fromIntegral $ psIndentLevel st) ' '+ else ""+ out = indentSpaces <> x+ psColumn' = psColumn st + fromIntegral (length out)+ columnFits = psColumn' <= configMaxColumns (psConfig st)+ when hardFail $ guard columnFits+ modify+ (\s ->+ s+ { psOutput = psOutput st <> S.stringUtf8 out+ , psNewline = False+ , psEolComment = False+ , psColumn = psColumn'+ })++-- | Equivalent to 'string " "'.+space :: Printer ()+space = string " "++-- | Equivalent to 'string ","'.+comma :: Printer ()+comma = string ","++-- | Equivalent to 'string "."'.+dot :: Printer ()+dot = string "."++-- | This function prints a '\n'.+--+-- Always call this function to print it because printing it requires+-- special treatment. Do not call 'string' instead.+newline :: Printer ()+newline = do+ gets psFitOnOneLine >>= guard . not+ modify+ (\s ->+ s+ { psOutput = psOutput s <> S.stringUtf8 "\n"+ , psNewline = True+ , psLine = psLine s + 1+ , psEolComment = False+ , psColumn = 0+ })++-- | Equivalent to 'newline >> newline'.+blankline :: Printer ()+blankline = newline >> newline
+ src/HIndent/Pretty/Combinators/Switch.hs view
@@ -0,0 +1,25 @@+{-# LANGUAGE LambdaCase #-}++-- | Printer combinators for switching printers depending on situations.+module HIndent.Pretty.Combinators.Switch+ ( (<-|>)+ ) where++import Control.Applicative+import Control.Monad.State+import HIndent.Printer++-- | This function runs the first printer if the result of running it fits+-- in a single line. Otherwise, it runs the second printer.+(<-|>) :: Printer a -> Printer a -> Printer a+fit <-|> notFit = do+ before <- get+ put before {psFitOnOneLine = True}+ fmap Just fit <|> return Nothing >>= \case+ Just r -> do+ modify $ \st -> st {psFitOnOneLine = psFitOnOneLine before}+ return r+ Nothing -> do+ put before+ guard $ not $ psFitOnOneLine before+ notFit
+ src/HIndent/Pretty/Combinators/Wrap.hs view
@@ -0,0 +1,85 @@+-- | Printer operators for wrapping texts with a prefix and a suffix.+module HIndent.Pretty.Combinators.Wrap+ ( parens+ , parensIfSymbol+ , bananaBrackets+ , braces+ , doubleQuotes+ , brackets+ , typedBrackets+ , backticks+ , backticksIfNotSymbol+ , wrapWithBars+ , promotedListBrackets+ , promotedTupleParens+ , unboxedParens+ ) where++import GHC.Types.Name+import HIndent.Pretty.Combinators.Indent+import HIndent.Pretty.Combinators.String+import HIndent.Printer++-- | This function wraps the printer with parentheses.+parens :: Printer a -> Printer a+parens = wrap "(" ")"++-- | This function wraps the printer with parentheses if the identifier+-- contains only symbols.+parensIfSymbol :: OccName -> Printer a -> Printer a+parensIfSymbol name+ | isSymOcc name = parens+ | otherwise = id++-- | Wraps with "(|" and "|)"+bananaBrackets :: Printer a -> Printer a+bananaBrackets = wrap "(|" "|)"++-- | This function wraps the printer with braces.+braces :: Printer a -> Printer a+braces = wrap "{" "}"++-- | This function wraps the printer with brackets.+brackets :: Printer a -> Printer a+brackets = wrap "[" "]"++-- | Wraps with @[||@ and @||]@.+typedBrackets :: Printer a -> Printer a+typedBrackets = wrap "[||" "||]"++-- | Wraps with double quotes.+doubleQuotes :: Printer a -> Printer a+doubleQuotes = wrap "\"" "\""++-- | This function wraps the printer with backticks.+backticks :: Printer a -> Printer a+backticks = wrap "`" "`"++-- | This function wraps the printer with backticks if the identifier+-- contains at least one non-symbol character.+backticksIfNotSymbol :: OccName -> Printer a -> Printer a+backticksIfNotSymbol name+ | isSymOcc name = id+ | otherwise = backticks++-- | This function wraps the printer with bars (|).+wrapWithBars :: Printer a -> Printer a+wrapWithBars = wrap "|" "|"++-- | This function wraps the printer with @'[ @ and @]@ for a promoted+-- list.+promotedListBrackets :: Printer a -> Printer a+promotedListBrackets = wrap "'[ " "]"++-- | This function wraps the printer with @'( @ and @)@ for a promoted+-- tuple.+promotedTupleParens :: Printer a -> Printer a+promotedTupleParens = wrap "'( " ")"++-- | Wraps with @(# @ and @ #)@.+unboxedParens :: Printer a -> Printer a+unboxedParens = wrap "(# " " #)"++-- | This function wraps the printer with the prefix and the suffix.+wrap :: String -> String -> Printer a -> Printer a+wrap open close p = string open |=> p <* string close
+ src/HIndent/Pretty/Import.hs view
@@ -0,0 +1,46 @@+-- | Helper functions for dealing with import declarations.+module HIndent.Pretty.Import+ ( importsExist+ , extractImports+ , extractImportsSorted+ , groupImports+ ) where++import GHC.Hs+import GHC.Types.SrcLoc+import HIndent.Pretty.Import.Sort++-- | Returns if the module has import declarations.+importsExist :: HsModule -> Bool+importsExist = not . null . hsmodImports++-- | Extracts import declarations from the given module. Adjacent import+-- declarations are grouped as a single list.+extractImports :: HsModule -> [[LImportDecl GhcPs]]+extractImports = groupImports . sortImportsByLocation . hsmodImports++-- | Extracts import declarations from the given module and sorts them by+-- their names. Adjacent import declarations are grouped as a single list.+extractImportsSorted :: HsModule -> [[LImportDecl GhcPs]]+extractImportsSorted = fmap sortImportsByName . extractImports++-- | Combines adjacent import declarations into a single list.+groupImports :: [LImportDecl GhcPs] -> [[LImportDecl GhcPs]]+groupImports = groupImports' []+ where+ groupImports' ::+ [[LImportDecl GhcPs]] -> [LImportDecl GhcPs] -> [[LImportDecl GhcPs]]+ groupImports' xs [] = xs+ groupImports' [] (x:xs) = groupImports' [[x]] xs+ groupImports' [[]] (x:xs) = groupImports' [[x]] xs+ groupImports' ([]:x:xs) (y:ys) = groupImports' ([y] : x : xs) ys+ groupImports' ((z:zs):xs) (y:ys)+ | z `isAdjacentTo` y = groupImports' ((y : z : zs) : xs) ys+ | otherwise = groupImports' ([y] : (z : zs) : xs) ys+ a `isAdjacentTo` b =+ srcSpanEndLine (sp a) + 1 == srcSpanStartLine (sp b) ||+ srcSpanEndLine (sp b) + 1 == srcSpanStartLine (sp a)+ sp x =+ case locA $ getLoc x of+ RealSrcSpan x' _ -> x'+ _ -> error "Src span unavailable."
+ src/HIndent/Pretty/Import/Sort.hs view
@@ -0,0 +1,125 @@+-- | Import declaration sorting for pretty-printing.+module HIndent.Pretty.Import.Sort+ ( sortImportsByName+ , sortImportsByLocation+ ) where++import Data.Char+import Data.Function+import Data.List+import Data.Maybe+import GHC.Hs+import GHC.Stack+import GHC.Types.SrcLoc+import HIndent.Pretty.Combinators.Outputable++-- | The letter type of a 'Char'.+--+-- The order of constructors is important. HIndent sorts explicit imports+-- from ones starting from a capital letter (e.g., data constructors),+-- symbol identifiers, and functions.+data LetterType+ = Capital+ | Symbol+ | Lower+ deriving (Eq, Ord)++-- | This function sorts import declarations and explicit imports in them+-- by their names.+sortImportsByName :: [LImportDecl GhcPs] -> [LImportDecl GhcPs]+sortImportsByName = fmap sortExplicitImportsInDecl . sortByModuleName++-- | This function sorts imports by their start line numbers.+sortImportsByLocation :: [LImportDecl GhcPs] -> [LImportDecl GhcPs]+sortImportsByLocation = sortBy (flip compare `on` lineIdx)+ where+ lineIdx = startLine . locA . getLoc++-- | This function sorts import declarations by their module names.+sortByModuleName :: [LImportDecl GhcPs] -> [LImportDecl GhcPs]+sortByModuleName = sortBy (compare `on` unLoc . ideclName . unLoc)++-- | This function sorts explicit imports in the given import declaration+-- by their names.+sortExplicitImportsInDecl :: LImportDecl GhcPs -> LImportDecl GhcPs+sortExplicitImportsInDecl (L l d@ImportDecl {ideclHiding = Just (x, imports)}) =+ L l d {ideclHiding = Just (x, sorted)}+ where+ sorted = fmap (fmap sortVariants . sortExplicitImports) imports+sortExplicitImportsInDecl x = x++-- | This function sorts the given explicit imports by their names.+sortExplicitImports :: [LIE GhcPs] -> [LIE GhcPs]+sortExplicitImports = sortBy compareImportEntities++-- | This function sorts variants (e.g., data constructors and class+-- methods) in the given explicit import by their names.+sortVariants :: LIE GhcPs -> LIE GhcPs+sortVariants (L l (IEThingWith x x' x'' xs)) =+ L l $ IEThingWith x x' x'' (sortWrappedNames xs)+ where+ sortWrappedNames = sortBy (compare `on` showOutputable)+sortVariants x = x++-- | This function compares two import declarations by their module names.+compareImportEntities :: LIE GhcPs -> LIE GhcPs -> Ordering+compareImportEntities (L _ a) (L _ b) =+ fromMaybe LT $ compareIdentifier <$> moduleName a <*> moduleName b++-- | This function returns a 'Just' value with the module name extracted+-- from the import declaration. Otherwise, it returns a 'Nothing'.+moduleName :: IE GhcPs -> Maybe String+moduleName (IEVar _ wrapped) = Just $ showOutputable wrapped+moduleName (IEThingAbs _ wrapped) = Just $ showOutputable wrapped+moduleName (IEThingAll _ wrapped) = Just $ showOutputable wrapped+moduleName (IEThingWith _ wrapped _ _) = Just $ showOutputable wrapped+moduleName _ = Nothing++-- | This function compares two identifiers in order of capitals, symbols,+-- and lowers.+compareIdentifier :: String -> String -> Ordering+compareIdentifier as@(a:_) bs@(b:_) =+ case compareChar a b of+ EQ -> compareSameIdentifierType as bs+ x -> x+compareIdentifier _ _ = error "Either identifier is an empty string."++-- | Almost similar to 'compare' but ignores parentheses for symbol+-- identifiers as they are enclosed by parentheses.+compareSameIdentifierType :: String -> String -> Ordering+compareSameIdentifierType "" "" = EQ+compareSameIdentifierType "" _ = LT+compareSameIdentifierType _ "" = GT+compareSameIdentifierType ('(':as) bs = compareSameIdentifierType as bs+compareSameIdentifierType (')':as) bs = compareSameIdentifierType as bs+compareSameIdentifierType as ('(':bs) = compareSameIdentifierType as bs+compareSameIdentifierType as (')':bs) = compareSameIdentifierType as bs+compareSameIdentifierType (a:as) (b:bs) =+ case compare a b of+ EQ -> compareSameIdentifierType as bs+ x -> x++-- | This function compares two characters by their types (capital, symbol,+-- and lower). If both are the same type, then it compares them by the+-- usual ordering.+compareChar :: Char -> Char -> Ordering+compareChar a b =+ case compare at bt of+ EQ -> compare a b+ x -> x+ where+ at = charToLetterType a+ bt = charToLetterType b++-- | This function returns a 'LetterType' based on the given character.+charToLetterType :: Char -> LetterType+charToLetterType c+ | isLower c = Lower+ | isUpper c = Capital+ | otherwise = Symbol++-- | This function returns the start line of the given 'SrcSpan'. If it is+-- not available, it raises an error.+startLine :: HasCallStack => SrcSpan -> Int+startLine (RealSrcSpan x _) = srcSpanStartLine x+startLine (UnhelpfulSpan _) = error "The src span is unavailable."
+ src/HIndent/Pretty/NodeComments.hs view
@@ -0,0 +1,873 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE RecordWildCards #-}++-- | Comment handling around an AST node+module HIndent.Pretty.NodeComments+ ( CommentExtraction(..)+ , emptyNodeComments+ ) where++import Data.Void+import GHC.Core.Coercion+import GHC.Data.BooleanFormula+import GHC.Hs+import GHC.Stack+import GHC.Types.Basic+import GHC.Types.Fixity+import GHC.Types.ForeignCall+import GHC.Types.Name+import GHC.Types.Name.Reader+import GHC.Types.SourceText+import GHC.Types.SrcLoc+import GHC.Unit+import HIndent.Pretty.Pragma+import HIndent.Pretty.SigBindFamily+import HIndent.Pretty.Types++-- | An interface to extract comments from an AST node.+class CommentExtraction a where+ nodeComments :: a -> NodeComments++instance CommentExtraction HsModule where+ nodeComments = nodeComments . filterOutEofAndPragmasFromAnn . hsmodAnn+ where+ filterOutEofAndPragmasFromAnn EpAnn {..} =+ EpAnn {comments = filterOutEofAndPragmasFromComments comments, ..}+ filterOutEofAndPragmasFromAnn EpAnnNotUsed = EpAnnNotUsed+ filterOutEofAndPragmasFromComments comments =+ EpaCommentsBalanced+ { priorComments = filterOutEofAndPragmas $ priorComments comments+ , followingComments =+ filterOutEofAndPragmas $ getFollowingComments comments+ }+ filterOutEofAndPragmas = filter isNeitherEofNorPragmaComment+ isNeitherEofNorPragmaComment (L _ (EpaComment EpaEofComment _)) = False+ isNeitherEofNorPragmaComment (L _ (EpaComment tok _)) = not $ isPragma tok++instance CommentExtraction l => CommentExtraction (GenLocated l e) where+ nodeComments (L l _) = nodeComments l++instance CommentExtraction (HsDecl GhcPs) where+ nodeComments TyClD {} = emptyNodeComments+ nodeComments InstD {} = emptyNodeComments+ nodeComments DerivD {} = emptyNodeComments+ nodeComments ValD {} = emptyNodeComments+ nodeComments SigD {} = emptyNodeComments+ nodeComments KindSigD {} = emptyNodeComments+ nodeComments DefD {} = emptyNodeComments+ nodeComments ForD {} = emptyNodeComments+ nodeComments WarningD {} = emptyNodeComments+ nodeComments AnnD {} = emptyNodeComments+ nodeComments RuleD {} = emptyNodeComments+ nodeComments SpliceD {} = emptyNodeComments+ nodeComments DocD {} =+ error "Document comments should be treated as normal ones."+ nodeComments RoleAnnotD {} = emptyNodeComments++instance CommentExtraction (TyClDecl GhcPs) where+ nodeComments FamDecl {} = emptyNodeComments+ nodeComments SynDecl {..} = nodeComments tcdSExt+ nodeComments DataDecl {..} = nodeComments tcdDExt+ nodeComments ClassDecl {tcdCExt = (x, _, _)} = nodeComments x++instance CommentExtraction (InstDecl GhcPs) where+ nodeComments = nodeCommentsInstDecl++nodeCommentsInstDecl :: InstDecl GhcPs -> NodeComments+nodeCommentsInstDecl ClsInstD {} = emptyNodeComments+#if MIN_VERSION_ghc_lib_parser(9,4,1)+nodeCommentsInstDecl DataFamInstD {} = emptyNodeComments+#else+nodeCommentsInstDecl DataFamInstD {..} = nodeComments dfid_ext+#endif+nodeCommentsInstDecl TyFamInstD {} = emptyNodeComments++instance CommentExtraction (HsBind GhcPs) where+ nodeComments = nodeCommentsHsBind++nodeCommentsHsBind :: HsBind GhcPs -> NodeComments+nodeCommentsHsBind FunBind {..} = nodeComments fun_id+nodeCommentsHsBind PatBind {..} = nodeComments pat_ext+nodeCommentsHsBind VarBind {} = emptyNodeComments+#if !MIN_VERSION_ghc_lib_parser(9,4,1)+nodeCommentsHsBind AbsBinds {} = emptyNodeComments+#endif+nodeCommentsHsBind PatSynBind {} = emptyNodeComments++instance CommentExtraction (Sig GhcPs) where+ nodeComments (TypeSig x _ _) = nodeComments x+ nodeComments (PatSynSig x _ _) = nodeComments x+ nodeComments (ClassOpSig x _ _ _) = nodeComments x+ nodeComments IdSig {} = emptyNodeComments+ nodeComments (FixSig x _) = nodeComments x+ nodeComments (InlineSig x _ _) = nodeComments x+ nodeComments (SpecSig x _ _ _) = nodeComments x+ nodeComments (SpecInstSig x _ _) = nodeComments x+ nodeComments (MinimalSig x _ _) = nodeComments x+ nodeComments (SCCFunSig x _ _ _) = nodeComments x+ nodeComments (CompleteMatchSig x _ _ _) = nodeComments x++instance CommentExtraction DeclSig where+ nodeComments (DeclSig x) = nodeComments x++instance CommentExtraction (HsDataDefn GhcPs) where+ nodeComments HsDataDefn {} = emptyNodeComments++instance CommentExtraction (ClsInstDecl GhcPs) where+ nodeComments ClsInstDecl {cid_ext = (x, _)} = nodeComments x++instance CommentExtraction (MatchGroup GhcPs a) where+ nodeComments MG {} = emptyNodeComments++instance CommentExtraction (HsExpr GhcPs) where+ nodeComments = nodeCommentsHsExpr++instance CommentExtraction LambdaCase where+ nodeComments (LambdaCase x _) = nodeComments x++nodeCommentsHsExpr :: HsExpr GhcPs -> NodeComments+nodeCommentsHsExpr HsVar {} = emptyNodeComments+nodeCommentsHsExpr (HsUnboundVar x _) = nodeComments x+#if !MIN_VERSION_ghc_lib_parser(9,4,1)+nodeCommentsHsExpr HsConLikeOut {} = emptyNodeComments+nodeCommentsHsExpr HsRecFld {} = emptyNodeComments+#endif+nodeCommentsHsExpr (HsOverLabel x _) = nodeComments x+nodeCommentsHsExpr (HsIPVar x _) = nodeComments x+nodeCommentsHsExpr (HsOverLit x _) = nodeComments x+nodeCommentsHsExpr (HsLit x _) = nodeComments x+nodeCommentsHsExpr HsLam {} = emptyNodeComments+#if MIN_VERSION_ghc_lib_parser(9,4,1)+nodeCommentsHsExpr (HsLamCase x _ _) = nodeComments x+#else+nodeCommentsHsExpr (HsLamCase x _) = nodeComments x+#endif+nodeCommentsHsExpr (HsApp x _ _) = nodeComments x+nodeCommentsHsExpr HsAppType {} = emptyNodeComments+nodeCommentsHsExpr (OpApp x _ _ _) = nodeComments x+nodeCommentsHsExpr (NegApp x _ _) = nodeComments x+#if MIN_VERSION_ghc_lib_parser(9,4,1)+nodeCommentsHsExpr (HsPar x _ _ _) = nodeComments x+#else+nodeCommentsHsExpr (HsPar x _) = nodeComments x+#endif+nodeCommentsHsExpr (SectionL x _ _) = nodeComments x+nodeCommentsHsExpr (SectionR x _ _) = nodeComments x+nodeCommentsHsExpr (ExplicitTuple x _ _) = nodeComments x+nodeCommentsHsExpr (ExplicitSum x _ _ _) = nodeComments x+nodeCommentsHsExpr (HsCase x _ _) = nodeComments x+nodeCommentsHsExpr (HsIf x _ _ _) = nodeComments x+nodeCommentsHsExpr (HsMultiIf x _) = nodeComments x+#if MIN_VERSION_ghc_lib_parser(9,4,1)+nodeCommentsHsExpr (HsLet x _ _ _ _) = nodeComments x+#else+nodeCommentsHsExpr (HsLet x _ _) = nodeComments x+#endif+nodeCommentsHsExpr (HsDo x _ _) = nodeComments x+nodeCommentsHsExpr (ExplicitList x _) = nodeComments x+nodeCommentsHsExpr RecordCon {..} = nodeComments rcon_ext+nodeCommentsHsExpr RecordUpd {..} = nodeComments rupd_ext+nodeCommentsHsExpr HsGetField {..} = nodeComments gf_ext+nodeCommentsHsExpr HsProjection {..} = nodeComments proj_ext+nodeCommentsHsExpr (ExprWithTySig x _ _) = nodeComments x+nodeCommentsHsExpr (ArithSeq x _ _) = nodeComments x+#if !MIN_VERSION_ghc_lib_parser(9,4,1)+nodeCommentsHsExpr (HsBracket x _) = nodeComments x+nodeCommentsHsExpr HsRnBracketOut {} = notUsedInParsedStage+nodeCommentsHsExpr HsTcBracketOut {} = notUsedInParsedStage+#endif+nodeCommentsHsExpr (HsSpliceE x _) = nodeComments x+nodeCommentsHsExpr (HsProc x _ _) = nodeComments x+nodeCommentsHsExpr (HsStatic x _) = nodeComments x+#if !MIN_VERSION_ghc_lib_parser(9,4,1)+nodeCommentsHsExpr HsTick {} = emptyNodeComments+nodeCommentsHsExpr HsBinTick {} = emptyNodeComments+#endif+nodeCommentsHsExpr HsPragE {} = emptyNodeComments+#if MIN_VERSION_ghc_lib_parser(9,4,1)+nodeCommentsHsExpr HsRecSel {} = emptyNodeComments+nodeCommentsHsExpr (HsTypedBracket x _) = nodeComments x+nodeCommentsHsExpr (HsUntypedBracket x _) = nodeComments x+#endif+instance CommentExtraction (HsSigType GhcPs) where+ nodeComments HsSig {} = emptyNodeComments++instance CommentExtraction HsSigType' where+ nodeComments (HsSigType' _ _ HsSig {}) = emptyNodeComments++instance CommentExtraction (ConDecl GhcPs) where+ nodeComments ConDeclGADT {..} = nodeComments con_g_ext+ nodeComments ConDeclH98 {..} = nodeComments con_ext++instance CommentExtraction (Match GhcPs a) where+ nodeComments Match {..} = nodeComments m_ext++instance CommentExtraction+ (StmtLR GhcPs GhcPs (GenLocated SrcSpanAnnA (HsExpr GhcPs))) where+ nodeComments LastStmt {} = emptyNodeComments+ nodeComments (BindStmt x _ _) = nodeComments x+ nodeComments ApplicativeStmt {} = emptyNodeComments+ nodeComments BodyStmt {} = emptyNodeComments+ nodeComments (LetStmt x _) = nodeComments x+ nodeComments ParStmt {} = emptyNodeComments+ nodeComments TransStmt {..} = nodeComments trS_ext+ nodeComments RecStmt {..} = nodeComments recS_ext++instance CommentExtraction+ (StmtLR GhcPs GhcPs (GenLocated SrcSpanAnnA (HsCmd GhcPs))) where+ nodeComments LastStmt {} = emptyNodeComments+ nodeComments (BindStmt x _ _) = nodeComments x+ nodeComments ApplicativeStmt {} = emptyNodeComments+ nodeComments BodyStmt {} = emptyNodeComments+ nodeComments (LetStmt x _) = nodeComments x+ nodeComments ParStmt {} = emptyNodeComments+ nodeComments TransStmt {..} = nodeComments trS_ext+ nodeComments RecStmt {..} = nodeComments recS_ext++instance CommentExtraction StmtLRInsideVerticalList where+ nodeComments (StmtLRInsideVerticalList x) = nodeComments x++-- | For pattern matching.+instance CommentExtraction+ (HsRecFields GhcPs (GenLocated SrcSpanAnnA (Pat GhcPs))) where+ nodeComments HsRecFields {} = emptyNodeComments++-- | For record updates+instance CommentExtraction+ (HsRecFields GhcPs (GenLocated SrcSpanAnnA (HsExpr GhcPs))) where+ nodeComments HsRecFields {} = emptyNodeComments++instance CommentExtraction (HsType GhcPs) where+ nodeComments = nodeComments . HsType' HsTypeForNormalDecl HsTypeNoDir++instance CommentExtraction HsType' where+ nodeComments (HsType' _ _ HsForAllTy {}) = emptyNodeComments+ nodeComments (HsType' _ _ HsQualTy {}) = emptyNodeComments+ nodeComments (HsType' _ _ (HsTyVar x _ _)) = nodeComments x+ nodeComments (HsType' _ _ HsAppTy {}) = emptyNodeComments+ nodeComments (HsType' _ _ HsAppKindTy {}) = emptyNodeComments+ nodeComments (HsType' _ _ (HsFunTy x _ _ _)) = nodeComments x+ nodeComments (HsType' _ _ (HsListTy x _)) = nodeComments x+ nodeComments (HsType' _ _ (HsTupleTy x _ _)) = nodeComments x+ nodeComments (HsType' _ _ (HsSumTy x _)) = nodeComments x+ nodeComments (HsType' _ _ HsOpTy {}) = emptyNodeComments+ nodeComments (HsType' _ _ (HsParTy x _)) = nodeComments x+ nodeComments (HsType' _ _ (HsIParamTy x _ _)) = nodeComments x+ nodeComments (HsType' _ _ HsStarTy {}) = emptyNodeComments+ nodeComments (HsType' _ _ (HsKindSig x _ _)) = nodeComments x+ nodeComments (HsType' _ _ HsSpliceTy {}) = emptyNodeComments+ nodeComments (HsType' _ _ (HsDocTy x _ _)) = nodeComments x+ nodeComments (HsType' _ _ (HsBangTy x _ _)) = nodeComments x+ nodeComments (HsType' _ _ (HsRecTy x _)) = nodeComments x+ nodeComments (HsType' _ _ (HsExplicitListTy x _ _)) = nodeComments x+ nodeComments (HsType' _ _ (HsExplicitTupleTy x _)) = nodeComments x+ nodeComments (HsType' _ _ HsTyLit {}) = emptyNodeComments+ nodeComments (HsType' _ _ HsWildCardTy {}) = emptyNodeComments+ nodeComments (HsType' _ _ XHsType {}) = emptyNodeComments++instance CommentExtraction (GRHSs GhcPs a) where+ nodeComments GRHSs {..} = NodeComments {..}+ where+ commentsBefore = priorComments grhssExt+ commentsOnSameLine = []+ commentsAfter = getFollowingComments grhssExt++instance CommentExtraction GRHSsExpr where+ nodeComments (GRHSsExpr {..}) = nodeComments grhssExpr++instance CommentExtraction (HsMatchContext GhcPs) where+ nodeComments = nodeCommentsMatchContext++nodeCommentsMatchContext :: HsMatchContext GhcPs -> NodeComments+nodeCommentsMatchContext FunRhs {} = emptyNodeComments+nodeCommentsMatchContext LambdaExpr {} = emptyNodeComments+nodeCommentsMatchContext CaseAlt {} = emptyNodeComments+nodeCommentsMatchContext IfAlt {} = emptyNodeComments+nodeCommentsMatchContext ArrowMatchCtxt {} = emptyNodeComments+nodeCommentsMatchContext PatBindRhs {} = emptyNodeComments+nodeCommentsMatchContext PatBindGuards {} = emptyNodeComments+nodeCommentsMatchContext RecUpd {} = emptyNodeComments+nodeCommentsMatchContext StmtCtxt {} = emptyNodeComments+nodeCommentsMatchContext ThPatSplice {} = emptyNodeComments+nodeCommentsMatchContext ThPatQuote {} = emptyNodeComments+nodeCommentsMatchContext PatSyn {} = emptyNodeComments+#if MIN_VERSION_ghc_lib_parser(9,4,1)+nodeCommentsMatchContext LamCaseAlt {} = emptyNodeComments+#endif+instance CommentExtraction (ParStmtBlock GhcPs GhcPs) where+ nodeComments ParStmtBlock {} = emptyNodeComments++instance CommentExtraction ParStmtBlockInsideVerticalList where+ nodeComments (ParStmtBlockInsideVerticalList x) = nodeComments x++instance CommentExtraction RdrName where+ nodeComments Unqual {} = emptyNodeComments+ nodeComments Qual {} = emptyNodeComments+ nodeComments Orig {} = emptyNodeComments+ nodeComments Exact {} = emptyNodeComments++instance CommentExtraction (GRHS GhcPs (GenLocated SrcSpanAnnA (HsExpr GhcPs))) where+ nodeComments = nodeComments . GRHSExpr GRHSExprNormal++instance CommentExtraction GRHSExpr where+ nodeComments (GRHSExpr {grhsExpr = (GRHS x _ _)}) = nodeComments x++instance CommentExtraction GRHSProc where+ nodeComments (GRHSProc (GRHS x _ _)) = nodeComments x++instance CommentExtraction EpaCommentTok where+ nodeComments = const emptyNodeComments++instance CommentExtraction (SpliceDecl GhcPs) where+ nodeComments SpliceDecl {} = emptyNodeComments++instance CommentExtraction (HsSplice GhcPs) where+ nodeComments (HsTypedSplice x _ _ _) = nodeComments x+ nodeComments (HsUntypedSplice x _ _ _) = nodeComments x+ nodeComments HsQuasiQuote {} = emptyNodeComments+ nodeComments HsSpliced {} = emptyNodeComments++instance CommentExtraction (Pat GhcPs) where+ nodeComments = nodeCommentsPat++instance CommentExtraction PatInsidePatDecl where+ nodeComments (PatInsidePatDecl x) = nodeComments x++nodeCommentsPat :: Pat GhcPs -> NodeComments+nodeCommentsPat WildPat {} = emptyNodeComments+nodeCommentsPat VarPat {} = emptyNodeComments+nodeCommentsPat (LazyPat x _) = nodeComments x+nodeCommentsPat (AsPat x _ _) = nodeComments x+#if MIN_VERSION_ghc_lib_parser(9,4,1)+nodeCommentsPat (ParPat x _ _ _) = nodeComments x+#else+nodeCommentsPat (ParPat x _) = nodeComments x+#endif+nodeCommentsPat (BangPat x _) = nodeComments x+nodeCommentsPat (ListPat x _) = nodeComments x+nodeCommentsPat (TuplePat x _ _) = nodeComments x+nodeCommentsPat (SumPat x _ _ _) = nodeComments x+nodeCommentsPat ConPat {..} = nodeComments pat_con_ext+nodeCommentsPat (ViewPat x _ _) = nodeComments x+nodeCommentsPat SplicePat {} = emptyNodeComments+nodeCommentsPat LitPat {} = emptyNodeComments+nodeCommentsPat (NPat x _ _ _) = nodeComments x+nodeCommentsPat (NPlusKPat x _ _ _ _ _) = nodeComments x+nodeCommentsPat (SigPat x _ _) = nodeComments x++instance CommentExtraction RecConPat where+ nodeComments (RecConPat x) = nodeComments x+#if !MIN_VERSION_ghc_lib_parser(9,4,1)+instance CommentExtraction (HsBracket GhcPs) where+ nodeComments ExpBr {} = emptyNodeComments+ nodeComments PatBr {} = emptyNodeComments+ nodeComments DecBrL {} = emptyNodeComments+ nodeComments DecBrG {} = emptyNodeComments+ nodeComments TypBr {} = emptyNodeComments+ nodeComments VarBr {} = emptyNodeComments+ nodeComments TExpBr {} = emptyNodeComments+#endif+instance CommentExtraction SigBindFamily where+ nodeComments (Sig x) = nodeComments x+ nodeComments (Bind x) = nodeComments x+ nodeComments (TypeFamily x) = nodeComments x+ nodeComments (TyFamInst x) = nodeComments x+ nodeComments (DataFamInst x) = nodeComments x++instance CommentExtraction EpaComment where+ nodeComments EpaComment {} = emptyNodeComments++instance CommentExtraction Anchor where+ nodeComments Anchor {} = emptyNodeComments++instance CommentExtraction (SrcAnn a) where+ nodeComments (SrcSpanAnn ep _) = nodeComments ep++instance CommentExtraction SrcSpan where+ nodeComments RealSrcSpan {} = emptyNodeComments+ nodeComments UnhelpfulSpan {} = emptyNodeComments++instance CommentExtraction (EpAnn a) where+ nodeComments (EpAnn ann _ cs) = NodeComments {..}+ where+ commentsBefore = priorComments cs+ commentsOnSameLine = filter isCommentOnSameLine $ getFollowingComments cs+ commentsAfter =+ filter (not . isCommentOnSameLine) $ getFollowingComments cs+ isCommentOnSameLine (L comAnn _) =+ srcSpanEndLine (anchor ann) == srcSpanStartLine (anchor comAnn)+ nodeComments EpAnnNotUsed = emptyNodeComments++instance CommentExtraction (HsLocalBindsLR GhcPs GhcPs) where+ nodeComments (HsValBinds x _) = nodeComments x+ nodeComments (HsIPBinds x _) = nodeComments x+ nodeComments EmptyLocalBinds {} = emptyNodeComments++instance CommentExtraction (HsValBindsLR GhcPs GhcPs) where+ nodeComments ValBinds {} = emptyNodeComments+ nodeComments XValBindsLR {} = notUsedInParsedStage++instance CommentExtraction (HsTupArg GhcPs) where+ nodeComments (Present x _) = nodeComments x+ nodeComments (Missing x) = nodeComments x+#if MIN_VERSION_ghc_lib_parser(9,4,1)+instance CommentExtraction RecConField where+ nodeComments (RecConField x) = nodeComments x+#else+-- | For pattern matching against a record.+instance CommentExtraction+ (HsRecField' (FieldOcc GhcPs) (GenLocated SrcSpanAnnA (Pat GhcPs))) where+ nodeComments HsRecField {..} = nodeComments hsRecFieldAnn++-- | For record updates.+instance CommentExtraction+ (HsRecField' (FieldOcc GhcPs) (GenLocated SrcSpanAnnA (HsExpr GhcPs))) where+ nodeComments HsRecField {..} = nodeComments hsRecFieldAnn+#endif+#if MIN_VERSION_ghc_lib_parser(9,4,1)+-- | For pattern matchings against records.+instance CommentExtraction+ (HsFieldBind+ (GenLocated (SrcAnn NoEpAnns) (FieldOcc GhcPs))+ (GenLocated SrcSpanAnnA (Pat GhcPs))) where+ nodeComments HsFieldBind {..} = nodeComments hfbAnn++-- | For record updates.+instance CommentExtraction+ (HsFieldBind+ (GenLocated (SrcAnn NoEpAnns) (FieldOcc GhcPs))+ (GenLocated SrcSpanAnnA (HsExpr GhcPs))) where+ nodeComments HsFieldBind {..} = nodeComments hfbAnn+#else+instance CommentExtraction RecConField where+ nodeComments (RecConField x) = nodeComments x+#endif+#if MIN_VERSION_ghc_lib_parser(9,4,1)+instance CommentExtraction (FieldOcc GhcPs) where+ nodeComments FieldOcc {} = emptyNodeComments+#else+instance CommentExtraction (FieldOcc GhcPs) where+ nodeComments FieldOcc {} = emptyNodeComments+#endif+-- HsConDeclH98Details+instance CommentExtraction+ (HsConDetails+ Void+ (HsScaled GhcPs (GenLocated SrcSpanAnnA (BangType GhcPs)))+ (GenLocated+ SrcSpanAnnL+ [GenLocated SrcSpanAnnA (ConDeclField GhcPs)])) where+ nodeComments PrefixCon {} = emptyNodeComments+ nodeComments RecCon {} = emptyNodeComments+ nodeComments InfixCon {} = emptyNodeComments++instance CommentExtraction (HsScaled GhcPs a) where+ nodeComments HsScaled {} = emptyNodeComments++instance CommentExtraction (ConDeclField GhcPs) where+ nodeComments ConDeclField {..} = nodeComments cd_fld_ext++instance CommentExtraction InfixExpr where+ nodeComments (InfixExpr x) = nodeComments x++instance CommentExtraction InfixApp where+ nodeComments InfixApp {} = emptyNodeComments++instance CommentExtraction (BooleanFormula a) where+ nodeComments Var {} = emptyNodeComments+ nodeComments And {} = emptyNodeComments+ nodeComments Or {} = emptyNodeComments+ nodeComments Parens {} = emptyNodeComments++instance CommentExtraction (FieldLabelStrings GhcPs) where+ nodeComments FieldLabelStrings {} = emptyNodeComments++instance CommentExtraction (AmbiguousFieldOcc GhcPs) where+ nodeComments Unambiguous {} = emptyNodeComments+ nodeComments Ambiguous {} = emptyNodeComments++instance CommentExtraction (ImportDecl GhcPs) where+ nodeComments ImportDecl {..} = nodeComments ideclExt++instance CommentExtraction (HsDerivingClause GhcPs) where+ nodeComments HsDerivingClause {..} = nodeComments deriv_clause_ext++instance CommentExtraction (DerivClauseTys GhcPs) where+ nodeComments DctSingle {} = emptyNodeComments+ nodeComments DctMulti {} = emptyNodeComments++instance CommentExtraction OverlapMode where+ nodeComments NoOverlap {} = emptyNodeComments+ nodeComments Overlappable {} = emptyNodeComments+ nodeComments Overlapping {} = emptyNodeComments+ nodeComments Overlaps {} = emptyNodeComments+ nodeComments Incoherent {} = emptyNodeComments++instance CommentExtraction StringLiteral where+ nodeComments StringLiteral {} = emptyNodeComments++-- | This instance is for type family declarations inside a class declaration.+instance CommentExtraction (FamilyDecl GhcPs) where+ nodeComments FamilyDecl {..} = nodeComments fdExt++instance CommentExtraction (FamilyResultSig GhcPs) where+ nodeComments NoSig {} = emptyNodeComments+ nodeComments KindSig {} = emptyNodeComments+ nodeComments TyVarSig {} = emptyNodeComments++instance CommentExtraction (HsTyVarBndr a GhcPs) where+ nodeComments (UserTyVar x _ _) = nodeComments x+ nodeComments (KindedTyVar x _ _ _) = nodeComments x++instance CommentExtraction (InjectivityAnn GhcPs) where+ nodeComments (InjectivityAnn x _ _) = nodeComments x++instance CommentExtraction (ArithSeqInfo GhcPs) where+ nodeComments From {} = emptyNodeComments+ nodeComments FromThen {} = emptyNodeComments+ nodeComments FromTo {} = emptyNodeComments+ nodeComments FromThenTo {} = emptyNodeComments++instance CommentExtraction (HsForAllTelescope GhcPs) where+ nodeComments HsForAllVis {..} = nodeComments hsf_xvis+ nodeComments HsForAllInvis {..} = nodeComments hsf_xinvis++instance CommentExtraction InfixOp where+ nodeComments (InfixOp x) = nodeComments x++instance CommentExtraction PrefixOp where+ nodeComments (PrefixOp x) = nodeComments x++instance CommentExtraction Context where+ nodeComments Context {} = emptyNodeComments+#if MIN_VERSION_ghc_lib_parser(9,4,1)+instance CommentExtraction HorizontalContext where+ nodeComments HorizontalContext {} = emptyNodeComments++instance CommentExtraction VerticalContext where+ nodeComments VerticalContext {} = emptyNodeComments+#else+instance CommentExtraction HorizontalContext where+ nodeComments HorizontalContext {} = emptyNodeComments++instance CommentExtraction VerticalContext where+ nodeComments VerticalContext {} = emptyNodeComments+#endif+-- Wrap a value of this type with 'ModulenameWithPrefix' to print it with+-- the "module " prefix.+instance CommentExtraction ModuleName where+ nodeComments = const emptyNodeComments++instance CommentExtraction ModuleNameWithPrefix where+ nodeComments ModuleNameWithPrefix {} = emptyNodeComments++instance CommentExtraction (IE GhcPs) where+ nodeComments IEVar {} = emptyNodeComments+ nodeComments (IEThingAbs x _) = nodeComments x+ nodeComments (IEThingAll x _) = nodeComments x+ nodeComments (IEThingWith x _ _ _) = nodeComments x+ nodeComments (IEModuleContents x _) = nodeComments x+ nodeComments IEGroup {} = emptyNodeComments+ nodeComments IEDoc {} = emptyNodeComments+ nodeComments IEDocNamed {} = emptyNodeComments++instance CommentExtraction+ (FamEqn GhcPs (GenLocated SrcSpanAnnA (HsType GhcPs))) where+ nodeComments FamEqn {..} = nodeComments feqn_ext++instance CommentExtraction FamEqn' where+ nodeComments FamEqn' {..} = nodeComments famEqn++-- | Pretty-print a data instance.+instance CommentExtraction (FamEqn GhcPs (HsDataDefn GhcPs)) where+ nodeComments FamEqn {..} = nodeComments feqn_ext++-- | HsArg (LHsType GhcPs) (LHsType GhcPs)+instance CommentExtraction+ (HsArg+ (GenLocated SrcSpanAnnA (HsType GhcPs))+ (GenLocated SrcSpanAnnA (HsType GhcPs))) where+ nodeComments HsValArg {} = emptyNodeComments+ nodeComments HsTypeArg {} = emptyNodeComments+ nodeComments HsArgPar {} = emptyNodeComments+#if MIN_VERSION_ghc_lib_parser(9,4,1)+instance CommentExtraction (HsQuote GhcPs) where+ nodeComments ExpBr {} = emptyNodeComments+ nodeComments PatBr {} = emptyNodeComments+ nodeComments DecBrL {} = emptyNodeComments+ nodeComments DecBrG {} = emptyNodeComments+ nodeComments TypBr {} = emptyNodeComments+ nodeComments VarBr {} = emptyNodeComments+#endif+instance CommentExtraction (WarnDecls GhcPs) where+ nodeComments Warnings {..} = nodeComments wd_ext++instance CommentExtraction (WarnDecl GhcPs) where+ nodeComments (Warning x _ _) = nodeComments x+#if MIN_VERSION_ghc_lib_parser(9,4,1)+instance CommentExtraction (WithHsDocIdentifiers StringLiteral GhcPs) where+ nodeComments WithHsDocIdentifiers {} = emptyNodeComments+#endif+-- | 'Pretty' for 'LIEWrappedName (IdP GhcPs)'+instance CommentExtraction (IEWrappedName RdrName) where+ nodeComments IEName {} = emptyNodeComments+ nodeComments IEPattern {} = emptyNodeComments+ nodeComments IEType {} = emptyNodeComments+#if MIN_VERSION_ghc_lib_parser(9,4,1)+instance CommentExtraction (DotFieldOcc GhcPs) where+ nodeComments DotFieldOcc {..} = nodeComments dfoExt+#else+instance CommentExtraction (HsFieldLabel GhcPs) where+ nodeComments HsFieldLabel {..} = nodeComments hflExt+#endif+instance CommentExtraction (RuleDecls GhcPs) where+ nodeComments HsRules {..} = nodeComments rds_ext++instance CommentExtraction (RuleDecl GhcPs) where+ nodeComments HsRule {..} = nodeComments rd_ext++instance CommentExtraction OccName where+ nodeComments = const emptyNodeComments++instance CommentExtraction (DerivDecl GhcPs) where+ nodeComments DerivDecl {..} = nodeComments deriv_ext++-- | 'Pretty' for 'LHsSigWcType GhcPs'.+instance CommentExtraction+ (HsWildCardBndrs GhcPs (GenLocated SrcSpanAnnA (HsSigType GhcPs))) where+ nodeComments HsWC {} = emptyNodeComments++-- | 'Pretty' for 'LHsWcType'+instance CommentExtraction+ (HsWildCardBndrs GhcPs (GenLocated SrcSpanAnnA (HsType GhcPs))) where+ nodeComments HsWC {} = emptyNodeComments++instance CommentExtraction (StandaloneKindSig GhcPs) where+ nodeComments (StandaloneKindSig x _ _) = nodeComments x++instance CommentExtraction (DefaultDecl GhcPs) where+ nodeComments (DefaultDecl x _) = nodeComments x++instance CommentExtraction (ForeignDecl GhcPs) where+ nodeComments ForeignImport {..} = nodeComments fd_i_ext+ nodeComments ForeignExport {..} = nodeComments fd_e_ext++instance CommentExtraction ForeignImport where+ nodeComments CImport {} = emptyNodeComments++instance CommentExtraction ForeignExport where+ nodeComments CExport {} = emptyNodeComments++instance CommentExtraction CExportSpec where+ nodeComments CExportStatic {} = emptyNodeComments++instance CommentExtraction Safety where+ nodeComments PlaySafe = emptyNodeComments+ nodeComments PlayInterruptible = emptyNodeComments+ nodeComments PlayRisky = emptyNodeComments++instance CommentExtraction (AnnDecl GhcPs) where+ nodeComments (HsAnnotation x _ _ _) = nodeComments x++instance CommentExtraction (RoleAnnotDecl GhcPs) where+ nodeComments (RoleAnnotDecl x _ _) = nodeComments x++instance CommentExtraction Role where+ nodeComments Nominal = emptyNodeComments+ nodeComments Representational = emptyNodeComments+ nodeComments Phantom = emptyNodeComments++instance CommentExtraction (TyFamInstDecl GhcPs) where+ nodeComments TyFamInstDecl {..} = nodeComments tfid_xtn++instance CommentExtraction TopLevelTyFamInstDecl where+ nodeComments (TopLevelTyFamInstDecl x) = nodeComments x++instance CommentExtraction (DataFamInstDecl GhcPs) where+ nodeComments DataFamInstDecl {} = emptyNodeComments++instance CommentExtraction DataFamInstDecl' where+ nodeComments DataFamInstDecl' {..} = nodeComments dataFamInstDecl++instance CommentExtraction (PatSynBind GhcPs GhcPs) where+ nodeComments PSB {..} = nodeComments psb_ext++-- | 'Pretty' for 'HsPatSynDetails'.+instance CommentExtraction+ (HsConDetails+ Void+ (GenLocated SrcSpanAnnN RdrName)+ [RecordPatSynField GhcPs]) where+ nodeComments PrefixCon {} = emptyNodeComments+ nodeComments RecCon {} = emptyNodeComments+ nodeComments InfixCon {} = emptyNodeComments++instance CommentExtraction (FixitySig GhcPs) where+ nodeComments FixitySig {} = emptyNodeComments++instance CommentExtraction Fixity where+ nodeComments Fixity {} = emptyNodeComments++instance CommentExtraction FixityDirection where+ nodeComments InfixL {} = emptyNodeComments+ nodeComments InfixR {} = emptyNodeComments+ nodeComments InfixN {} = emptyNodeComments++instance CommentExtraction InlinePragma where+ nodeComments InlinePragma {} = emptyNodeComments++instance CommentExtraction InlineSpec where+ nodeComments = nodeCommentsInlineSpec++nodeCommentsInlineSpec :: InlineSpec -> NodeComments+nodeCommentsInlineSpec Inline {} = emptyNodeComments+nodeCommentsInlineSpec Inlinable {} = emptyNodeComments+nodeCommentsInlineSpec NoInline {} = emptyNodeComments+nodeCommentsInlineSpec NoUserInlinePrag {} = emptyNodeComments+#if MIN_VERSION_ghc_lib_parser(9,4,1)+nodeCommentsInlineSpec Opaque {} = emptyNodeComments+#endif+instance CommentExtraction (HsPatSynDir GhcPs) where+ nodeComments Unidirectional = emptyNodeComments+ nodeComments ImplicitBidirectional = emptyNodeComments+ nodeComments ExplicitBidirectional {} = emptyNodeComments++instance CommentExtraction (HsOverLit GhcPs) where+ nodeComments OverLit {} = emptyNodeComments++instance CommentExtraction OverLitVal where+ nodeComments HsIntegral {} = emptyNodeComments+ nodeComments HsFractional {} = emptyNodeComments+ nodeComments HsIsString {} = emptyNodeComments++instance CommentExtraction IntegralLit where+ nodeComments IL {} = emptyNodeComments++instance CommentExtraction FractionalLit where+ nodeComments FL {} = emptyNodeComments++instance CommentExtraction (HsLit GhcPs) where+ nodeComments HsChar {} = emptyNodeComments+ nodeComments HsCharPrim {} = emptyNodeComments+ nodeComments HsString {} = emptyNodeComments+ nodeComments HsStringPrim {} = emptyNodeComments+ nodeComments HsInt {} = emptyNodeComments+ nodeComments HsIntPrim {} = emptyNodeComments+ nodeComments HsWordPrim {} = emptyNodeComments+ nodeComments HsInt64Prim {} = emptyNodeComments+ nodeComments HsWord64Prim {} = emptyNodeComments+ nodeComments HsInteger {} = emptyNodeComments+ nodeComments HsRat {} = emptyNodeComments+ nodeComments HsFloatPrim {} = emptyNodeComments+ nodeComments HsDoublePrim {} = emptyNodeComments++instance CommentExtraction (HsPragE GhcPs) where+ nodeComments (HsPragSCC x _ _) = nodeComments x++instance CommentExtraction HsIPName where+ nodeComments HsIPName {} = emptyNodeComments++instance CommentExtraction HsTyLit where+ nodeComments HsNumTy {} = emptyNodeComments+ nodeComments HsStrTy {} = emptyNodeComments+ nodeComments HsCharTy {} = emptyNodeComments++instance CommentExtraction (HsPatSigType GhcPs) where+ nodeComments HsPS {..} = nodeComments hsps_ext++instance CommentExtraction (HsIPBinds GhcPs) where+ nodeComments IPBinds {} = emptyNodeComments++instance CommentExtraction (IPBind GhcPs) where+ nodeComments (IPBind x _ _) = nodeComments x++instance CommentExtraction (DerivStrategy GhcPs) where+ nodeComments (StockStrategy x) = nodeComments x+ nodeComments (AnyclassStrategy x) = nodeComments x+ nodeComments (NewtypeStrategy x) = nodeComments x+ nodeComments (ViaStrategy x) = nodeComments x++instance CommentExtraction XViaStrategyPs where+ nodeComments (XViaStrategyPs x _) = nodeComments x++instance CommentExtraction (RecordPatSynField GhcPs) where+ nodeComments RecordPatSynField {} = emptyNodeComments++instance CommentExtraction (HsCmdTop GhcPs) where+ nodeComments HsCmdTop {} = emptyNodeComments++instance CommentExtraction (HsCmd GhcPs) where+ nodeComments = nodeCommentsHsCmd++nodeCommentsHsCmd :: HsCmd GhcPs -> NodeComments+nodeCommentsHsCmd (HsCmdArrApp x _ _ _ _) = nodeComments x+nodeCommentsHsCmd (HsCmdArrForm x _ _ _ _) = nodeComments x+nodeCommentsHsCmd (HsCmdApp x _ _) = nodeComments x+nodeCommentsHsCmd HsCmdLam {} = emptyNodeComments+#if MIN_VERSION_ghc_lib_parser(9,4,1)+nodeCommentsHsCmd (HsCmdPar x _ _ _) = nodeComments x+#else+nodeCommentsHsCmd (HsCmdPar x _) = nodeComments x+#endif+nodeCommentsHsCmd (HsCmdCase x _ _) = nodeComments x+#if MIN_VERSION_ghc_lib_parser(9,4,1)+nodeCommentsHsCmd (HsCmdLamCase x _ _) = nodeComments x+#else+nodeCommentsHsCmd (HsCmdLamCase x _) = nodeComments x+#endif+nodeCommentsHsCmd (HsCmdIf x _ _ _ _) = nodeComments x+#if MIN_VERSION_ghc_lib_parser(9,4,1)+nodeCommentsHsCmd (HsCmdLet x _ _ _ _) = nodeComments x+#else+nodeCommentsHsCmd (HsCmdLet x _ _) = nodeComments x+#endif+nodeCommentsHsCmd (HsCmdDo x _) = nodeComments x++instance CommentExtraction ListComprehension where+ nodeComments ListComprehension {} = emptyNodeComments++instance CommentExtraction DoExpression where+ nodeComments DoExpression {} = emptyNodeComments++instance CommentExtraction LetIn where+ nodeComments LetIn {} = emptyNodeComments++instance CommentExtraction (RuleBndr GhcPs) where+ nodeComments (RuleBndr x _) = nodeComments x+ nodeComments (RuleBndrSig x _ _) = nodeComments x++instance CommentExtraction CCallConv where+ nodeComments = const emptyNodeComments++instance CommentExtraction ModuleDeprecatedPragma where+ nodeComments ModuleDeprecatedPragma {} = emptyNodeComments++instance CommentExtraction HsSrcBang where+ nodeComments HsSrcBang {} = emptyNodeComments++instance CommentExtraction SrcUnpackedness where+ nodeComments SrcUnpack = emptyNodeComments+ nodeComments SrcNoUnpack = emptyNodeComments+ nodeComments NoSrcUnpack = emptyNodeComments++instance CommentExtraction SrcStrictness where+ nodeComments SrcLazy = emptyNodeComments+ nodeComments SrcStrict = emptyNodeComments+ nodeComments NoSrcStrict = emptyNodeComments++instance CommentExtraction (HsOuterSigTyVarBndrs GhcPs) where+ nodeComments HsOuterImplicit {} = emptyNodeComments+ nodeComments HsOuterExplicit {..} = nodeComments hso_xexplicit++-- | Marks an AST node as never appearing in the AST.+--+-- Some AST node types are only used in the renaming or type-checking phase.+notUsedInParsedStage :: HasCallStack => a+notUsedInParsedStage =+ error+ "This AST should never appears in an AST. It only appears in the renaming or type checked stages."++-- | A 'NodeComment' with no comments.+emptyNodeComments :: NodeComments+emptyNodeComments = NodeComments [] [] []
+ src/HIndent/Pretty/Pragma.hs view
@@ -0,0 +1,61 @@+-- | Pretty-printing pragmas+module HIndent.Pretty.Pragma+ ( prettyPragmas+ , pragmaExists+ , isPragma+ ) where++import Data.Bifunctor+import Data.Char+import Data.Generics.Schemes+import Data.List+import Data.List.Split+import Data.Maybe+import GHC.Hs+import HIndent.Pragma+import HIndent.Pretty.Combinators.Lineup+import HIndent.Pretty.Combinators.String+import HIndent.Printer+import Text.Regex.TDFA++-- | This function pretty-prints the module's pragmas+prettyPragmas :: HsModule -> Printer ()+prettyPragmas = lined . fmap string . collectPragmas++-- | This function returns a 'True' if the module has pragmas.+-- Otherwise, it returns a 'False'.+pragmaExists :: HsModule -> Bool+pragmaExists = not . null . collectPragmas++-- | This function collects pragma comments from the+-- given module and modifies them into 'String's.+--+-- A pragma's name is converted to the @SHOUT_CASE@ (e.g., @lAnGuAgE@ ->+-- @LANGUAGE@).+collectPragmas :: HsModule -> [String]+collectPragmas =+ fmap (uncurry constructPragma) .+ mapMaybe extractPragma . listify matchToComment . hsmodAnn+ where+ matchToComment :: EpaCommentTok -> Bool+ matchToComment EpaBlockComment {} = True+ matchToComment _ = False+ constructPragma optionOrPragma xs =+ "{-# " +++ fmap toUpper optionOrPragma ++ " " ++ intercalate ", " xs ++ " #-}"++-- | This function returns a 'Just' value with the pragma+-- extracted from the passed 'EpaCommentTok' if it has one. Otherwise, it+-- returns a 'Nothing'.+extractPragma :: EpaCommentTok -> Maybe (String, [String])+extractPragma (EpaBlockComment c) =+ second (fmap strip . splitOn ",") <$> extractPragmaNameAndElement c+ where+ strip = reverse . dropWhile isSpace . reverse . dropWhile isSpace+extractPragma _ = Nothing++-- | This function returns a 'True' if the passed 'EpaCommentTok' is+-- a pragma. Otherwise, it returns a 'False'.+isPragma :: EpaCommentTok -> Bool+isPragma (EpaBlockComment c) = match pragmaRegex c+isPragma _ = False
+ src/HIndent/Pretty/SigBindFamily.hs view
@@ -0,0 +1,73 @@+{-# LANGUAGE LambdaCase #-}++-- | A module defining 'SigBindFamily' and other related types and+-- functions.+module HIndent.Pretty.SigBindFamily+ ( SigBindFamily(..)+ , LSigBindFamily+ , mkSortedLSigBindFamilyList+ , mkLSigBindFamilyList+ , filterLSig+ , filterLBind+ ) where++import Data.Function+import Data.List+import Data.Maybe+import GHC.Hs+import GHC.Types.SrcLoc++-- | A sum type containing one of those: function signature, function+-- binding, type family, type family instance, and data family instance.+data SigBindFamily+ = Sig (Sig GhcPs)+ | Bind (HsBindLR GhcPs GhcPs)+ | TypeFamily (FamilyDecl GhcPs)+ | TyFamInst (TyFamInstDecl GhcPs)+ | DataFamInst (DataFamInstDecl GhcPs)++-- | 'SigBindFamily' with the location information.+type LSigBindFamily = GenLocated SrcSpanAnnA SigBindFamily++-- | Creates a list of 'LSigBindFamily' from arguments. The list is sorted+-- by its elements' locations.+mkSortedLSigBindFamilyList ::+ [LSig GhcPs]+ -> [LHsBindLR GhcPs GhcPs]+ -> [LFamilyDecl GhcPs]+ -> [LTyFamInstDecl GhcPs]+ -> [LDataFamInstDecl GhcPs]+ -> [LSigBindFamily]+mkSortedLSigBindFamilyList sigs binds fams datafams =+ sortBy (compare `on` realSrcSpan . locA . getLoc) .+ mkLSigBindFamilyList sigs binds fams datafams++-- | Creates a list of 'LSigBindFamily' from arguments.+mkLSigBindFamilyList ::+ [LSig GhcPs]+ -> [LHsBindLR GhcPs GhcPs]+ -> [LFamilyDecl GhcPs]+ -> [LTyFamInstDecl GhcPs]+ -> [LDataFamInstDecl GhcPs]+ -> [LSigBindFamily]+mkLSigBindFamilyList sigs binds fams insts datafams =+ fmap (fmap Sig) sigs +++ fmap (fmap Bind) binds +++ fmap (fmap TypeFamily) fams +++ fmap (fmap TyFamInst) insts ++ fmap (fmap DataFamInst) datafams++-- | Filters out 'Sig's and extract the wrapped values.+filterLSig :: [LSigBindFamily] -> [LSig GhcPs]+filterLSig =+ mapMaybe+ (\case+ (L l (Sig x)) -> Just $ L l x+ _ -> Nothing)++-- | Filters out 'Bind's and extract the wrapped values.+filterLBind :: [LSigBindFamily] -> [LHsBindLR GhcPs GhcPs]+filterLBind =+ mapMaybe+ (\case+ (L l (Bind x)) -> Just $ L l x+ _ -> Nothing)
+ src/HIndent/Pretty/Types.hs view
@@ -0,0 +1,336 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE PatternSynonyms #-}++-- | Types to pretty-print certain parts of Haskell codes.+--+-- We define new types to pretty-print AST nodes rather than define+-- functions to print comments easily using the 'Pretty' implementation of+-- 'GenLocated'.+module HIndent.Pretty.Types+ ( InfixExpr(..)+ , InfixOp(..)+ , PrefixOp(..)+ , InfixApp(..)+ , GRHSsExpr(..)+ , GRHSExpr(..)+ , GRHSProc(..)+ , RecConPat(..)+ , RecConField(..)+ , HsSigType'(..)+ , pattern HsSigTypeInsideInstDecl+ , pattern HsSigTypeInsideVerticalFuncSig+ , pattern HsSigTypeInsideDeclSig+ , HsType'(..)+ , pattern HsTypeInsideVerticalFuncSig+ , pattern HsTypeInsideDeclSig+ , pattern HsTypeInsideInstDecl+ , pattern HsTypeWithVerticalAppTy+ , DataFamInstDecl'(..)+ , pattern DataFamInstDeclTopLevel+ , pattern DataFamInstDeclInsideClassInst+ , FamEqn'(..)+ , pattern FamEqnTopLevel+ , pattern FamEqnInsideClassInst+ , StmtLRInsideVerticalList(..)+ , ParStmtBlockInsideVerticalList(..)+ , DeclSig(..)+ , TopLevelTyFamInstDecl(..)+ , Context(..)+ , HorizontalContext(..)+ , VerticalContext(..)+ , ModuleNameWithPrefix(..)+ , PatInsidePatDecl(..)+ , LambdaCase(..)+ , ModuleDeprecatedPragma(..)+ , ListComprehension(..)+ , DoExpression(..)+ , DoOrMdo(..)+ , LetIn(..)+ , NodeComments(..)+ , GRHSExprType(..)+ , GRHSProcType(..)+ , HsTypeFor(..)+ , HsTypeDir(..)+ , CaseOrCases(..)+ , DataFamInstDeclFor(..)+ ) where++import GHC.Hs+import GHC.Types.Name.Reader+import GHC.Unit+import GHC.Unit.Module.Warnings++-- | `LHsExpr` used as a infix operator+newtype InfixExpr =+ InfixExpr (LHsExpr GhcPs)++newtype InfixOp =+ InfixOp RdrName++-- | A wrapper type for printing an identifier as a prefix operator.+--+-- Printing a `PrefixOp` value containing a symbol operator wraps it with+-- parentheses.+newtype PrefixOp =+ PrefixOp RdrName++-- | An infix operator application.+--+-- `immediatelyAfterDo` is `True` if an application is next to a `do`+-- keyword. It needs an extra indent in such cases because+--+-- > do a+-- > * b+--+-- is not a valid Haskell code.+data InfixApp = InfixApp+ { lhs :: LHsExpr GhcPs+ , op :: LHsExpr GhcPs+ , rhs :: LHsExpr GhcPs+ , immediatelyAfterDo :: Bool+ }++-- | `GRHSs` with a label indicating in which context the RHS is located+-- in.+data GRHSsExpr = GRHSsExpr+ { grhssExprType :: GRHSExprType+ , grhssExpr :: GRHSs GhcPs (LHsExpr GhcPs)+ }++-- | 'GRHS' for a normal binding.+data GRHSExpr = GRHSExpr+ { grhsExprType :: GRHSExprType+ , grhsExpr :: GRHS GhcPs (LHsExpr GhcPs)+ }++-- | 'GRHS' for a @proc@ binding.+newtype GRHSProc =+ GRHSProc (GRHS GhcPs (LHsCmd GhcPs))++-- | A pattern match against a record.+newtype RecConPat =+ RecConPat (HsRecFields GhcPs (LPat GhcPs))+#if MIN_VERSION_ghc_lib_parser(9,4,1)+-- | A record field in a pattern match.+newtype RecConField =+ RecConField (HsFieldBind (LFieldOcc GhcPs) (LPat GhcPs))+#else+-- | A record field in a pattern match.+newtype RecConField =+ RecConField (HsRecField' (FieldOcc GhcPs) (LPat GhcPs))+#endif+-- | A wrapper for `HsSigType`.+data HsSigType' = HsSigType'+ { hsSigTypeFor :: HsTypeFor -- ^ In which context a `HsSigType` is located in.+ , hsSigTypeDir :: HsTypeDir -- ^ How a `HsSigType` should be printed;+ -- either horizontally or vertically.+ , hsSigType :: HsSigType GhcPs -- ^ The actual signature.+ }++-- | `HsSigType'` for instance declarations.+pattern HsSigTypeInsideInstDecl :: HsSigType GhcPs -> HsSigType'+pattern HsSigTypeInsideInstDecl x = HsSigType' HsTypeForInstDecl HsTypeNoDir x++-- | `HsSigType'` for function declarations; printed horizontally.+pattern HsSigTypeInsideVerticalFuncSig :: HsSigType GhcPs -> HsSigType'+pattern HsSigTypeInsideVerticalFuncSig x = HsSigType' HsTypeForFuncSig HsTypeVertical x++-- | `HsSigType'` for a top-level function signature.+pattern HsSigTypeInsideDeclSig :: HsSigType GhcPs -> HsSigType'+pattern HsSigTypeInsideDeclSig x = HsSigType' HsTypeForDeclSig HsTypeNoDir x++-- | A wrapper for `HsType`.+data HsType' = HsType'+ { hsTypeFor :: HsTypeFor -- ^ In which context a `HsType` is located in.+ , hsTypeDir :: HsTypeDir -- ^ How a function signature is printed;+ -- either horizontally or vertically.+ , hsType :: HsType GhcPs -- ^ The actual type.+ }++-- | `HsType'` inside a function signature declaration; printed horizontally.+pattern HsTypeInsideVerticalFuncSig :: HsType GhcPs -> HsType'+pattern HsTypeInsideVerticalFuncSig x = HsType' HsTypeForFuncSig HsTypeVertical x++-- | `HsType'` inside a top-level function signature declaration.+pattern HsTypeInsideDeclSig :: HsType GhcPs -> HsType'+pattern HsTypeInsideDeclSig x = HsType' HsTypeForDeclSig HsTypeNoDir x++-- | `HsType'` inside a instance signature declaration.+pattern HsTypeInsideInstDecl :: HsType GhcPs -> HsType'+pattern HsTypeInsideInstDecl x = HsType' HsTypeForInstDecl HsTypeNoDir x++-- | `HsType'` to pretty-print a `HsAppTy` vertically.+pattern HsTypeWithVerticalAppTy :: HsType GhcPs -> HsType'+pattern HsTypeWithVerticalAppTy x = HsType' HsTypeForVerticalAppTy HsTypeVertical x++-- | A wrapper of `DataFamInstDecl`.+data DataFamInstDecl' = DataFamInstDecl'+ { dataFamInstDeclFor :: DataFamInstDeclFor -- ^ Where a data family instance is declared.+ , dataFamInstDecl :: DataFamInstDecl GhcPs -- ^ The actual value.+ }++-- | `DataFamInstDecl'` wrapping a `DataFamInstDecl` representing+-- a top-level data family instance.+pattern DataFamInstDeclTopLevel :: DataFamInstDecl GhcPs -> DataFamInstDecl'+pattern DataFamInstDeclTopLevel x = DataFamInstDecl' DataFamInstDeclForTopLevel x++-- | `DataFamInstDecl'` wrapping a `DataFamInstDecl` representing a data+-- family instance inside a class instance.+pattern DataFamInstDeclInsideClassInst :: DataFamInstDecl GhcPs -> DataFamInstDecl'+pattern DataFamInstDeclInsideClassInst x = DataFamInstDecl' DataFamInstDeclForInsideClassInst x++-- | A wrapper for `FamEqn`.+data FamEqn' = FamEqn'+ { famEqnFor :: DataFamInstDeclFor -- ^ Where a data family instance is declared.+ , famEqn :: FamEqn GhcPs (HsDataDefn GhcPs)+ }++-- | `FamEqn'` wrapping a `FamEqn` representing a top-level data family+-- instance.+pattern FamEqnTopLevel :: FamEqn GhcPs (HsDataDefn GhcPs) -> FamEqn'+pattern FamEqnTopLevel x = FamEqn' DataFamInstDeclForTopLevel x++-- | `FamEqn'` wrapping a `FamEqn` representing a data family instance+-- inside a class instance.+pattern FamEqnInsideClassInst :: FamEqn GhcPs (HsDataDefn GhcPs) -> FamEqn'+pattern FamEqnInsideClassInst x = FamEqn' DataFamInstDeclForInsideClassInst x++-- | `StmtLR` inside a vertically printed list.+newtype StmtLRInsideVerticalList =+ StmtLRInsideVerticalList (StmtLR GhcPs GhcPs (LHsExpr GhcPs))++-- | `ParStmtBlock` inside a vertically printed list.+newtype ParStmtBlockInsideVerticalList =+ ParStmtBlockInsideVerticalList (ParStmtBlock GhcPs GhcPs)++-- | A top-level function signature.+newtype DeclSig =+ DeclSig (Sig GhcPs)++-- | A top-level type family instance declaration.+newtype TopLevelTyFamInstDecl =+ TopLevelTyFamInstDecl (TyFamInstDecl GhcPs)+#if MIN_VERSION_ghc_lib_parser(9,4,1)+-- | A wrapper type for type class constraints; e.g., (Eq a, Ord a) of (Eq+-- a, Ord a) => [a] -> [a]. Either 'HorizontalContext' or 'VerticalContext'+-- is used internally.+newtype Context =+ Context (LHsContext GhcPs)++-- | A wrapper type for printing a context horizontally.+newtype HorizontalContext =+ HorizontalContext (LHsContext GhcPs)++-- | A wrapper type for printing a context vertically.+newtype VerticalContext =+ VerticalContext (LHsContext GhcPs)+#else+-- | A wrapper type for type class constraints; e.g., (Eq a, Ord a) of (Eq+-- a, Ord a) => [a] -> [a]. Either 'HorizontalContext' or 'VerticalContext'+-- is used internally.+newtype Context =+ Context (Maybe (LHsContext GhcPs))++-- | A wrapper type for printing a context horizontally.+newtype HorizontalContext =+ HorizontalContext (Maybe (LHsContext GhcPs))++-- | A wrapper type for printing a context vertically.+newtype VerticalContext =+ VerticalContext (Maybe (LHsContext GhcPs))+#endif+-- | A wrapper type for pretty-printing a value of @ModuleName@ with the+-- @module @ prefix.+--+-- Pretty-printing it via @(string "module " >> pretty (name ::+-- ModuleName))@ locates comments before @name@ in the same line as @module+-- @ and the name will be in the next line. This type is to avoid the+-- problem.+newtype ModuleNameWithPrefix =+ ModuleNameWithPrefix ModuleName++-- | A wrapper for 'LPat' inside a pattern declaration. Here, all infix+-- patterns have extra spaces around the operators, like x : xs.+newtype PatInsidePatDecl =+ PatInsidePatDecl (Pat GhcPs)++-- | Lambda case.+data LambdaCase = LambdaCase+ { lamCaseGroup :: MatchGroup GhcPs (LHsExpr GhcPs)+ , caseOrCases :: CaseOrCases+ }+#if MIN_VERSION_ghc_lib_parser(9,4,1)+-- | A deprecation pragma for a module.+newtype ModuleDeprecatedPragma =+ ModuleDeprecatedPragma (WarningTxt GhcPs)+#else+-- | A deprecation pragma for a module.+newtype ModuleDeprecatedPragma =+ ModuleDeprecatedPragma WarningTxt+#endif+-- | Use this type to pretty-print a list comprehension.+data ListComprehension = ListComprehension+ { listCompLhs :: ExprLStmt GhcPs -- ^ @f x@ of @[f x| x <- xs]@.+ , listCompRhs :: [ExprLStmt GhcPs] -- ^ @x <- xs@ of @[f x| x <- xs]@.+ }++-- | Use this type to pretty-print a do expression.+data DoExpression = DoExpression+ { doStmts :: [ExprLStmt GhcPs]+ , doOrMdo :: DoOrMdo+ }++-- | Use this type to pretty-print a @let ... in ...@ expression.+data LetIn = LetIn+ { letBinds :: HsLocalBinds GhcPs+ , inExpr :: LHsExpr GhcPs+ }++-- | Comments belonging to an AST node.+data NodeComments = NodeComments+ { commentsBefore :: [LEpaComment]+ , commentsOnSameLine :: [LEpaComment]+ , commentsAfter :: [LEpaComment]+ }++-- | Values indicating whether `do` or `mdo` is used.+data DoOrMdo+ = Do+ | Mdo++-- | Values indicating in which context a RHS is located.+data GRHSExprType+ = GRHSExprNormal+ | GRHSExprCase+ | GRHSExprMultiWayIf+ | GRHSExprLambda+ deriving (Eq)++-- | Values indicating in which context a RHS in a proc expression is located.+data GRHSProcType+ = GRHSProcCase+ | GRHSProcLambda++-- | Values indicating in which context a `HsType` is located.+data HsTypeFor+ = HsTypeForNormalDecl+ | HsTypeForInstDecl+ | HsTypeForFuncSig+ | HsTypeForDeclSig+ | HsTypeForVerticalAppTy++-- | Values indicating how a node should be printed; either horizontally or+-- vertically.+data HsTypeDir+ = HsTypeNoDir+ | HsTypeVertical++-- | Values indicating whether `case` or `cases` is used.+data CaseOrCases+ = Case+ | Cases++-- | Values indicating where a data family instance is declared.+data DataFamInstDeclFor+ = DataFamInstDeclForTopLevel+ | DataFamInstDeclForInsideClassInst
+ src/HIndent/Printer.hs view
@@ -0,0 +1,52 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE GADTs #-}+{-# LANGUAGE GeneralizedNewtypeDeriving #-}+{-# LANGUAGE RankNTypes #-}++-- | Printer types.+module HIndent.Printer+ ( Printer(..)+ , PrintState(..)+ ) where++import Control.Applicative+import Control.Monad+import Control.Monad.State.Strict (MonadState(..), StateT)+import Control.Monad.Trans.Maybe+import Data.ByteString.Builder+import Data.Functor.Identity+import Data.Int (Int64)+import HIndent.Config++-- | A pretty printing monad.+newtype Printer a = Printer+ { runPrinter :: StateT PrintState (MaybeT Identity) a+ } deriving ( Applicative+ , Monad+ , Functor+ , MonadState PrintState+ , MonadPlus+ , Alternative+ )++-- | The state of the pretty printer.+data PrintState = PrintState+ { psIndentLevel :: !Int64+ -- ^ Current indentation level, i.e. every time there's a+ -- new-line, output this many spaces.+ , psOutput :: !Builder+ -- ^ The current output bytestring builder.+ , psNewline :: !Bool+ -- ^ Just outputted a newline?+ , psColumn :: !Int64+ -- ^ Current column.+ , psLine :: !Int64+ -- ^ Current line number.+ , psConfig :: !Config+ -- ^ Configuration of max colums and indentation style.+ , psFitOnOneLine :: !Bool+ -- ^ Bail out if we need to print beyond the current line or+ -- the maximum column.+ , psEolComment :: !Bool+ }
− src/HIndent/Types.hs
@@ -1,143 +0,0 @@-{-# OPTIONS_GHC -cpp #-}-{-# LANGUAGE RankNTypes #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE GADTs #-}-{-# LANGUAGE NamedFieldPuns #-}-{-# LANGUAGE GeneralizedNewtypeDeriving #-}-{-# LANGUAGE FlexibleContexts #-}---- | All types.--module HIndent.Types- (Printer(..)- ,PrintState(..)- ,Config(..)- ,readExtension- ,defaultConfig- ,NodeInfo(..)- ,NodeComment(..)- ,SomeComment(..)- ) where--import Control.Applicative-import Control.Monad-import Control.Monad.State.Strict (MonadState(..),StateT)-import Control.Monad.Trans.Maybe-import Data.ByteString.Builder-import Data.Functor.Identity-import Data.Int (Int64)-import Data.Maybe-import Data.Yaml (FromJSON(..))-import qualified Data.Yaml as Y-import Language.Haskell.Exts hiding (Style, prettyPrint, Pretty, style, parse)---- | A pretty printing monad.-newtype Printer a =- Printer {runPrinter :: StateT PrintState (MaybeT Identity) a}- deriving (Applicative,Monad,Functor,MonadState PrintState,MonadPlus,Alternative)---- | The state of the pretty printer.-data PrintState = PrintState- { psIndentLevel :: !Int64- -- ^ Current indentation level, i.e. every time there's a- -- new-line, output this many spaces.- , psOutput :: !Builder- -- ^ The current output bytestring builder.- , psNewline :: !Bool- -- ^ Just outputted a newline?- , psColumn :: !Int64- -- ^ Current column.- , psLine :: !Int64- -- ^ Current line number.- , psConfig :: !Config- -- ^ Configuration of max colums and indentation style.- , psInsideCase :: !Bool- -- ^ Whether we're in a case statement, used for Rhs printing.- , psFitOnOneLine :: !Bool- -- ^ Bail out if we need to print beyond the current line or- -- the maximum column.- , psEolComment :: !Bool- }---- | Configurations shared among the different styles. Styles may pay--- attention to or completely disregard this configuration.-data Config = Config- { configMaxColumns :: !Int64 -- ^ Maximum columns to fit code into ideally.- , configIndentSpaces :: !Int64 -- ^ How many spaces to indent?- , configTrailingNewline :: !Bool -- ^ End with a newline.- , configSortImports :: !Bool -- ^ Sort imports in groups.- , configLineBreaks :: [String] -- ^ Break line when meets these operators.- , configExtensions :: [Extension]- -- ^ Extra language extensions enabled by default.- }---- | Parse an extension.--#if __GLASGOW_HASKELL__ >= 808-readExtension :: (Monad m, MonadFail m) => String -> m Extension-#else-readExtension :: Monad m => String -> m Extension-#endif-readExtension x =- case classifyExtension x -- Foo- of- UnknownExtension _ -> fail ("Unknown extension: " ++ x)- x' -> return x'--instance FromJSON Config where- parseJSON (Y.Object v) =- Config <$>- fmap- (fromMaybe (configMaxColumns defaultConfig))- (v Y..:? "line-length") <*>- fmap- (fromMaybe (configIndentSpaces defaultConfig))- (v Y..:? "indent-size" <|> v Y..:? "tab-size") <*>- fmap- (fromMaybe (configTrailingNewline defaultConfig))- (v Y..:? "force-trailing-newline") <*>- fmap- (fromMaybe (configSortImports defaultConfig))- (v Y..:? "sort-imports") <*>- fmap- (fromMaybe (configLineBreaks defaultConfig))- (v Y..:? "line-breaks") <*>- (traverse readExtension- =<< fmap (fromMaybe []) (v Y..:? "extensions"))- parseJSON _ = fail "Expected Object for Config value"---- | Default style configuration.-defaultConfig :: Config-defaultConfig =- Config- { configMaxColumns = 80- , configIndentSpaces = 2- , configTrailingNewline = True- , configSortImports = True- , configLineBreaks = []- , configExtensions = []- }---- | Some comment to print.-data SomeComment- = EndOfLine String- | MultiLine String- deriving (Show, Ord, Eq)---- | Comment associated with a node.--- 'SrcSpan' is the original source span of the comment.-data NodeComment- = CommentSameLine SrcSpan SomeComment- | CommentAfterLine SrcSpan SomeComment- | CommentBeforeLine SrcSpan SomeComment- deriving (Show, Ord, Eq)---- | Information for each node in the AST.-data NodeInfo = NodeInfo- { nodeInfoSpan :: !SrcSpanInfo -- ^ Location info from the parser.- , nodeInfoComments :: ![NodeComment] -- ^ Comments attached to this node.- }-instance Show NodeInfo where- show (NodeInfo _ []) = ""- show (NodeInfo _ s) =- "{- " ++ show s ++ " -}"
− src/main/Benchmark.hs
@@ -1,47 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE BangPatterns #-}---- | Benchmark the pretty printer.--module Main where--import Control.DeepSeq-import Criterion-import Criterion.Main-import qualified Data.ByteString as S-import qualified Data.ByteString.Builder as S-import qualified Data.ByteString.Char8 as S8-import qualified Data.ByteString.UTF8 as UTF8-import HIndent-import HIndent.Types-import Markdone---- | Main benchmarks.-main :: IO ()-main = do- bytes <- S.readFile "BENCHMARKS.md"- !forest <- fmap force (parse (tokenize bytes))- defaultMain (toCriterion forest)---- | Convert the Markdone document to Criterion benchmarks.-toCriterion :: [Markdone] -> [Benchmark]-toCriterion = go- where- go (Section name children:next) =- bgroup (S8.unpack name) (go children) : go next- go (PlainText desc:CodeFence lang code:next) =- if lang == "haskell"- then (bench- (UTF8.toString desc)- (nf- (either error S.toLazyByteString .- reformat- HIndent.Types.defaultConfig- (Just defaultExtensions)- Nothing)- code)) :- go next- else go next- go (PlainText {}:next) = go next- go (CodeFence {}:next) = go next- go [] = []
− src/main/Main.hs
@@ -1,127 +0,0 @@-{-# LANGUAGE Unsafe #-}-{-# LANGUAGE OverloadedStrings #-}---- | Main entry point to hindent.------ hindent-module Main (main) where--import Control.Applicative-import Control.Exception-import Control.Monad-import qualified Data.ByteString as S-import qualified Data.ByteString.Builder as S-import qualified Data.ByteString.Lazy.Char8 as L8-import Data.Maybe-import Data.Version (showVersion)-import qualified Data.Yaml as Y-import Foreign.C.Error-import GHC.IO.Exception-import HIndent-import HIndent.CabalFile-import HIndent.Types-import Language.Haskell.Exts hiding (Style, style)-import Path-import qualified Path.Find as Path-import qualified Path.IO as Path-import Paths_hindent (version)-import qualified System.Directory as IO-import System.Exit (exitWith)-import qualified System.IO as IO-import Options.Applicative hiding (action, style)-import Data.Monoid ((<>))-import qualified Data.Text as T--data Action = Validate | Reformat--data RunMode = ShowVersion | Run Config [Extension] Action [FilePath]---- | Main entry point.-main :: IO ()-main = do- config <- getConfig- runMode <- execParser (info (options config <**> helper) (header "hindent - Reformat Haskell source code"))- case runMode of- ShowVersion ->- putStrLn ("hindent " ++ showVersion version)- Run style exts action paths ->- if null paths then- L8.interact- (either error S.toLazyByteString . reformat style (Just exts) Nothing . L8.toStrict)- else- forM_ paths $ \filepath -> do- cabalexts <- getCabalExtensionsForSourcePath filepath- text <- S.readFile filepath- case reformat style (Just $ cabalexts ++ exts) (Just filepath) text of- Left e -> error e- Right out ->- unless (L8.fromStrict text == S.toLazyByteString out) $- case action of- Validate -> do- IO.putStrLn $ filepath ++ " is not formatted"- exitWith (ExitFailure 1)- Reformat -> do- tmpDir <- IO.getTemporaryDirectory- (fp, h) <- IO.openTempFile tmpDir "hindent.hs"- L8.hPutStr h (S.toLazyByteString out)- IO.hFlush h- IO.hClose h- let exdev e =- if ioe_errno e == Just ((\(Errno a) -> a) eXDEV)- then IO.copyFile fp filepath >> IO.removeFile fp- else throw e- IO.copyPermissions filepath fp- IO.renameFile fp filepath `catch` exdev---- | Read config from a config file, or return 'defaultConfig'.-getConfig :: IO Config-getConfig = do- cur <- Path.getCurrentDir- homeDir <- Path.getHomeDir- mfile <-- Path.findFileUp cur ((== ".hindent.yaml") . toFilePath . filename) (Just homeDir)- case mfile of- Nothing -> return defaultConfig- Just file -> do- result <- Y.decodeFileEither (toFilePath file)- case result of- Left e -> error (show e)- Right config -> return config---- | Program options.-options ::- Config -> Parser RunMode-options config =- flag' ShowVersion ( long "version" <> help "Print the version") <|>- (Run <$> style <*> exts <*> action <*> files)- where- style =- (makeStyle config <$>- lineLen <*>- indentSpaces <*>- trailingNewline <*>- sortImports- ) <*- optional (strOption- (long "style" <> help "Style to print with (historical, now ignored)" <> metavar "STYLE") :: Parser String)- exts = fmap getExtensions (many (T.pack <$> strOption (short 'X' <> help "Language extension" <> metavar "GHCEXT")))- indentSpaces =- option auto- (long "indent-size" <> help "Indentation size in spaces" <> value (configIndentSpaces config) <> showDefault) <|>- option auto (long "tab-size" <> help "Same as --indent-size, for compatibility")- lineLen =- option auto (long "line-length" <> help "Desired length of lines" <> value (configMaxColumns config) <> showDefault )- trailingNewline = not <$>- flag (not (configTrailingNewline config)) (configTrailingNewline config) (long "no-force-newline" <> help "Don't force a trailing newline" <> showDefault)- sortImports =- flag Nothing (Just True) (long "sort-imports" <> help "Sort imports in groups" <> showDefault) <|>- flag Nothing (Just False) (long "no-sort-imports" <> help "Don't sort imports")- action = flag Reformat Validate (long "validate" <> help "Check if files are formatted without changing them")- makeStyle s mlen tabs trailing imports =- s- { configMaxColumns = mlen- , configIndentSpaces = tabs- , configTrailingNewline = trailing- , configSortImports = fromMaybe (configSortImports s) imports- }- files = many (strArgument (metavar "FILENAMES"))
− src/main/Markdone.hs
@@ -1,130 +0,0 @@-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE DeriveGeneric #-}-{-# LANGUAGE OverloadedStrings #-}-{-# LANGUAGE LambdaCase #-}---- | A subset of markdown that only supports @#headings@ and code--- fences.------ All content must be in section headings with proper hierarchy,--- anything else is rejected.--module Markdone where--import Control.DeepSeq-import Control.Monad.Catch-import Control.Monad.State.Strict (State, evalState, get, put)-import Data.ByteString (ByteString)-import qualified Data.ByteString.Char8 as S8-import Data.Char-import Data.Typeable-import GHC.Generics---- | A markdone token.-data Token- = Heading !Int- !ByteString- | PlainLine !ByteString- | BeginFence !ByteString- | EndFence- deriving (Eq, Show)---- | A markdone document.-data Markdone- = Section !ByteString- ![Markdone]- | CodeFence !ByteString- !ByteString- | PlainText !ByteString- deriving (Eq,Show,Generic)-instance NFData Markdone---- | Parse error.-data MarkdownError = NoFenceEnd | ExpectedSection- deriving (Typeable,Show)-instance Exception MarkdownError--data TokenizerMode- = Normal- | Fenced---- | Tokenize the bytestring.-tokenize :: ByteString -> [Token]-tokenize input = evalState (mapM token (S8.lines input)) Normal- where- token :: ByteString -> State TokenizerMode Token- token line = do- mode <- get- case mode of- Normal ->- if S8.isPrefixOf "#" line- then let (hashes,title) = S8.span (== '#') line- in return $- Heading (S8.length hashes) (S8.dropWhile isSpace title)- else if S8.isPrefixOf "```" line- then do- put Fenced- return $- BeginFence- (S8.dropWhile- (\c ->- c == '`' || c == ' ')- line)- else return $ PlainLine line- Fenced ->- if line == "```"- then do- put Normal- return EndFence- else return $ PlainLine line---- | Parse into a forest.-parse :: (Functor m,MonadThrow m) => [Token] -> m [Markdone]-parse = go (0 :: Int)- where- go level =- \case- (Heading n label:rest) ->- let (children,rest') =- span- (\case- Heading nextN _ -> nextN > n- _ -> True)- rest- in do childs <- go (level + 1) children- siblings <- go level rest'- return (Section label childs : siblings)- (BeginFence label:rest)- | level > 0 ->- let (content,rest') =- (span- (\case- PlainLine {} -> True- _ -> False)- rest)- in case rest' of- (EndFence:rest'') ->- fmap- (CodeFence- label- (S8.intercalate "\n" (map getPlain content)) :)- (go level rest'')- _ -> throwM NoFenceEnd- PlainLine p:rest- | level > 0 ->- let (content,rest') =- (span- (\case- PlainLine {} -> True- _ -> False)- (PlainLine p : rest))- in fmap- (PlainText- (S8.intercalate- "\n"- (filter (not . S8.null) (map getPlain content))) :)- (go level rest')- [] -> return []- _ -> throwM ExpectedSection- getPlain (PlainLine x) = x- getPlain _ = ""
− src/main/Path/Find.hs
@@ -1,98 +0,0 @@-{-# LANGUAGE DataKinds #-}---- | Finding files.---- Lifted from Stack.--module Path.Find- (findFileUp- ,findDirUp- ,findFiles- ,findInParents)- where--import Control.Exception (evaluate)-import Control.DeepSeq (force)-import Control.Monad-import Control.Monad.Catch-import Control.Monad.IO.Class-import System.IO.Error (isPermissionError)-import Data.List-import Path-import Path.IO hiding (findFiles)-import System.PosixCompat.Files (getSymbolicLinkStatus, isSymbolicLink)---- | Find the location of a file matching the given predicate.-findFileUp :: (MonadIO m,MonadThrow m)- => Path Abs Dir -- ^ Start here.- -> (Path Abs File -> Bool) -- ^ Predicate to match the file.- -> Maybe (Path Abs Dir) -- ^ Do not ascend above this directory.- -> m (Maybe (Path Abs File)) -- ^ Absolute file path.-findFileUp = findPathUp snd---- | Find the location of a directory matching the given predicate.-findDirUp :: (MonadIO m,MonadThrow m)- => Path Abs Dir -- ^ Start here.- -> (Path Abs Dir -> Bool) -- ^ Predicate to match the directory.- -> Maybe (Path Abs Dir) -- ^ Do not ascend above this directory.- -> m (Maybe (Path Abs Dir)) -- ^ Absolute directory path.-findDirUp = findPathUp fst---- | Find the location of a path matching the given predicate.-findPathUp :: (MonadIO m,MonadThrow m)- => (([Path Abs Dir],[Path Abs File]) -> [Path Abs t])- -- ^ Choose path type from pair.- -> Path Abs Dir -- ^ Start here.- -> (Path Abs t -> Bool) -- ^ Predicate to match the path.- -> Maybe (Path Abs Dir) -- ^ Do not ascend above this directory.- -> m (Maybe (Path Abs t)) -- ^ Absolute path.-findPathUp pathType dir p upperBound =- do entries <- listDir dir- case find p (pathType entries) of- Just path -> return (Just path)- Nothing | Just dir == upperBound -> return Nothing- | parent dir == dir -> return Nothing- | otherwise -> findPathUp pathType (parent dir) p upperBound---- | Find files matching predicate below a root directory.------ NOTE: this skips symbolic directory links, to avoid loops. This may--- not make sense for all uses of file finding.------ TODO: write one of these that traverses symbolic links but--- efficiently ignores loops.-findFiles :: Path Abs Dir -- ^ Root directory to begin with.- -> (Path Abs File -> Bool) -- ^ Predicate to match files.- -> (Path Abs Dir -> Bool) -- ^ Predicate for which directories to traverse.- -> IO [Path Abs File] -- ^ List of matching files.-findFiles dir p traversep =- do (dirs,files) <- catchJust (\ e -> if isPermissionError e- then Just ()- else Nothing)- (listDir dir)- (\ _ -> return ([], []))- filteredFiles <- evaluate $ force (filter p files)- filteredDirs <- filterM (fmap not . isSymLink) dirs- subResults <-- forM filteredDirs- (\entry ->- if traversep entry- then findFiles entry p traversep- else return [])- return (concat (filteredFiles : subResults))--isSymLink :: Path Abs t -> IO Bool-isSymLink = fmap isSymbolicLink . getSymbolicLinkStatus . toFilePath---- | @findInParents f path@ applies @f@ to @path@ and its 'parent's until--- it finds a 'Just' or reaches the root directory.-findInParents :: MonadIO m => (Path Abs Dir -> m (Maybe a)) -> Path Abs Dir -> m (Maybe a)-findInParents f path = do- mres <- f path- case mres of- Just res -> return (Just res)- Nothing -> do- let next = parent path- if next == path- then return Nothing- else findInParents f next
− src/main/Test.hs
@@ -1,177 +0,0 @@-{-# LANGUAGE OverloadedStrings #-}---- | Test the pretty printer.-module Main where--import Data.Algorithm.Diff-import Data.Algorithm.DiffOutput-import qualified Data.ByteString as S-import qualified Data.ByteString.Builder as S-import Data.ByteString.Lazy (ByteString)-import qualified Data.ByteString.Lazy as L-import qualified Data.ByteString.Lazy.Char8 as L8-import qualified Data.ByteString.Lazy.UTF8 as LUTF8-import qualified Data.ByteString.UTF8 as UTF8-import Data.Function-import Data.Monoid-import qualified HIndent-import HIndent.CodeBlock-import HIndent.Types-import Markdone-import Test.Hspec---- | Main benchmarks.-main :: IO ()-main = do- bytes <- S.readFile "TESTS.md"- forest <- parse (tokenize bytes)- hspec $ do- codeBlocksSpec- markdoneSpec- toSpec forest--reformat :: Config -> S.ByteString -> ByteString-reformat cfg code =- either (("-- " <>) . L8.pack) S.toLazyByteString $- HIndent.reformat cfg (Just HIndent.defaultExtensions) Nothing code---- | Convert the Markdone document to Spec benchmarks.-toSpec :: [Markdone] -> Spec-toSpec = go- where- cfg = HIndent.Types.defaultConfig {configTrailingNewline = False}- go (Section name children:next) = do- describe (UTF8.toString name) (go children)- go next- go (PlainText desc:CodeFence lang code:next) =- case lang of- "haskell" -> do- it (UTF8.toString desc) $- shouldBeReadable (reformat cfg code) (L.fromStrict code)- go next- "haskell 4" -> do- let cfg' = cfg {configIndentSpaces = 4}- it (UTF8.toString desc) $- shouldBeReadable (reformat cfg' code) (L.fromStrict code)- go next- "haskell given" ->- case skipEmptyLines next of- CodeFence "haskell expect" codeExpect:next' -> do- it (UTF8.toString desc) $- shouldBeReadable (reformat cfg code) (L.fromStrict codeExpect)- go next'- _ ->- error- "'haskell given' block must be followed by a 'haskell expect' block"- "haskell pending" -> do- it (UTF8.toString desc) pending- go next- _ -> go next- go (PlainText {}:next) = go next- go (CodeFence {}:next) = go next- go [] = return ()---- | Version of 'shouldBe' that prints strings in a readable way,--- better for our use-case.-shouldBeReadable :: ByteString -> ByteString -> Expectation-shouldBeReadable x y =- shouldBe (Readable x (Just (diff y x))) (Readable y Nothing)---- | Prints a string without quoting and escaping.-data Readable = Readable- { readableString :: ByteString- , readableDiff :: Maybe String- }--instance Eq Readable where- (==) = on (==) readableString--instance Show Readable where- show (Readable x d') =- "\n" ++- LUTF8.toString x ++- (case d' of- Just d -> "\nThe diff:\n" ++ d- Nothing -> "")---- | A diff display.-diff :: ByteString -> ByteString -> String-diff x y = ppDiff (on getGroupedDiff (lines . LUTF8.toString) x y)--skipEmptyLines :: [Markdone] -> [Markdone]-skipEmptyLines (PlainText "":rest) = rest-skipEmptyLines other = other--codeBlocksSpec :: Spec-codeBlocksSpec =- describe "splitting source into code blocks" $ do- it "should put just Haskell code in its own block" $ do- let input = "this is totally haskell code\n\nit deserves its own block!\n"- cppSplitBlocks input `shouldBe` [HaskellSource 0 input]- it "should put #if/#endif and Haskell code into separate blocks" $ do- cppSplitBlocks- "haskell code\n#if DEBUG\ndebug code\n#endif\nmore haskell code\n" `shouldBe`- [ HaskellSource 0 "haskell code"- , CPPDirectives "#if DEBUG"- , HaskellSource 2 "debug code"- , CPPDirectives "#endif"- , HaskellSource 4 "more haskell code\n"- ]- it "should put the shebang line into its own block" $ do- cppSplitBlocks- "#!/usr/bin/env runhaskell\n{-# LANGUAGE OverloadedStrings #-}\n" `shouldBe`- [ Shebang "#!/usr/bin/env runhaskell"- , HaskellSource 1 "{-# LANGUAGE OverloadedStrings #-}\n"- ]- it "should put a multi-line #define into its own block" $ do- let input = "#define A \\\n macro contents \\\n go here\nhaskell code\n"- cppSplitBlocks input `shouldBe`- [ CPPDirectives "#define A \\\n macro contents \\\n go here"- , HaskellSource 3 "haskell code\n"- ]- it "should put an unterminated multi-line #define into its own block" $ do- cppSplitBlocks "#define A \\" `shouldBe` [CPPDirectives "#define A \\"]- cppSplitBlocks "#define A \\\n" `shouldBe` [CPPDirectives "#define A \\"]- cppSplitBlocks "#define A \\\n.\\" `shouldBe`- [CPPDirectives "#define A \\\n.\\"]--markdoneSpec :: Spec-markdoneSpec = do- describe "markdown tokenizer" $ do- it "should tokenize plain text" $ do- let input =- "this is a line\nthis is another line\n\nthis is a new paragraph\n"- tokenize input `shouldBe`- [ PlainLine "this is a line"- , PlainLine "this is another line"- , PlainLine ""- , PlainLine "this is a new paragraph"- ]- it "should tokenize headings" $ do- tokenize "# Heading" `shouldBe` [Heading 1 "Heading"]- it "should tokenize code fence beginnings with labels" $ do- tokenize "``` haskell\n" `shouldBe` [BeginFence "haskell"]- tokenize "```haskell expect\n" `shouldBe` [BeginFence "haskell expect"]- tokenize "before\n```code\nafter\n" `shouldBe`- [PlainLine "before", BeginFence "code", PlainLine "after"]- it "should tokenize full code fences" $ do- tokenize "```haskell\ncode goes here\n```" `shouldBe`- [BeginFence "haskell", PlainLine "code goes here", EndFence]- it "should tokenize lines inside code fences as plain text" $ do- tokenize "```haskell\n#!/usr/bin/env stack\n```" `shouldBe`- [BeginFence "haskell", PlainLine "#!/usr/bin/env stack", EndFence]- tokenize "```haskell\n# not a heading\n```" `shouldBe`- [BeginFence "haskell", PlainLine "# not a heading", EndFence]- describe "markdown parser" $ do- it "should parse a heading followed by text as a section" $ do- let input =- [ Heading 1 "This is a heading"- , PlainLine "This is plain text"- , PlainLine "split across two lines."- ]- output <- parse input- output `shouldBe`- [ Section- "This is a heading"- [PlainText "This is plain text\nsplit across two lines."]- ]
+ tests/Main.hs view
@@ -0,0 +1,220 @@+{-# LANGUAGE CPP #-}+{-# LANGUAGE OverloadedStrings #-}++-- | Test the pretty printer.+module Main where++import Data.Algorithm.Diff+import Data.Algorithm.DiffOutput+import qualified Data.ByteString as S+import qualified Data.ByteString.Builder as S+import Data.ByteString.Lazy (ByteString)+import qualified Data.ByteString.Lazy as L+import qualified Data.ByteString.Lazy.Char8 as L8+import qualified Data.ByteString.Lazy.UTF8 as LUTF8+import qualified Data.ByteString.UTF8 as UTF8+import Data.Function+import Data.Version+import qualified HIndent+import HIndent.CodeBlock+import HIndent.Config+import HIndent.Internal.Test.Markdone+import qualified HIndent.LanguageExtension as HIndent+import qualified System.Info+import Test.Hspec+import Text.Read+import Text.Regex.TDFA++-- | Main benchmarks.+main :: IO ()+main = do+ bytes <- S.readFile "TESTS.md"+ forest <- parse (tokenize bytes)+ hspec $ do+ codeBlocksSpec+ markdoneSpec+ toSpec forest++reformat :: Config -> S.ByteString -> ByteString+reformat cfg code =+ either (("-- " <>) . L8.pack) S.toLazyByteString $+ HIndent.reformat cfg (Just HIndent.defaultExtensions) Nothing code++-- | Convert the Markdone document to Spec benchmarks.+toSpec :: [Markdone] -> Spec+toSpec = go+ where+ cfg = HIndent.Config.defaultConfig {configTrailingNewline = False}+ go (Section name children:next) = do+ describe (UTF8.toString name) (go children)+ go next+ go (PlainText desc:CodeFence lang code:next) =+ case lang of+ "haskell" -> do+ it (UTF8.toString desc) $+ shouldBeReadable (reformat cfg code) (L.fromStrict code)+ go next+ "haskell 4" -> do+ let cfg' = cfg {configIndentSpaces = 4}+ it (UTF8.toString desc) $+ shouldBeReadable (reformat cfg' code) (L.fromStrict code)+ go next+ "haskell given" ->+ case skipEmptyLines next of+ CodeFence "haskell expect" codeExpect:next' -> do+ it (UTF8.toString desc) $+ shouldBeReadable (reformat cfg code) (L.fromStrict codeExpect)+ go next'+ _ ->+ error+ "'haskell given' block must be followed by a 'haskell expect' block"+ "haskell pending" -> do+ it (UTF8.toString desc) pending+ go next+ s+ | Just from <- fromVersion $ UTF8.toString s ->+ if compilerVersion >= from+ then do+ it (UTF8.toString desc) $+ shouldBeReadable (reformat cfg code) (L.fromStrict code)+ go next+ else do+ it+ (UTF8.toString desc)+ (pendingWith $ pendingForVersionMsg from)+ go next+ _ -> go next+ go (PlainText {}:next) = go next+ go (CodeFence {}:next) = go next+ go [] = return ()+ pendingForVersionMsg from =+ "The test is for GHC versions since " +++ showVersion from +++ " but you are using GHC version " ++ showVersion compilerVersion ++ "."+ fromVersion :: String -> Maybe Version+ fromVersion s+ | (_, _, _, [x, y, z]) <-+ s =~ fromRegex :: (String, String, String, [String])+ , (Just x', Just y', Just z') <- (readMaybe x, readMaybe y, readMaybe z) =+ Just $ Version [x', y', z'] []+ fromVersion _ = Nothing+ fromRegex :: String+ fromRegex = "haskell since ([0-9]+)\\.([0-9]+)\\.([0-9]+)"++-- | Version of 'shouldBe' that prints strings in a readable way,+-- better for our use-case.+shouldBeReadable :: ByteString -> ByteString -> Expectation+shouldBeReadable x y =+ shouldBe (Readable x (Just (diff y x))) (Readable y Nothing)++-- | Prints a string without quoting and escaping.+data Readable = Readable+ { readableString :: ByteString+ , readableDiff :: Maybe String+ }++instance Eq Readable where+ (==) = on (==) readableString++instance Show Readable where+ show (Readable x d') =+ "\n" +++ LUTF8.toString x +++ (case d' of+ Just d -> "\nThe diff:\n" ++ d+ Nothing -> "")++-- | A diff display.+diff :: ByteString -> ByteString -> String+diff x y = ppDiff (on getGroupedDiff (lines . LUTF8.toString) x y)++skipEmptyLines :: [Markdone] -> [Markdone]+skipEmptyLines (PlainText "":rest) = rest+skipEmptyLines other = other++codeBlocksSpec :: Spec+codeBlocksSpec =+ describe "splitting source into code blocks" $ do+ it "should put just Haskell code in its own block" $ do+ let input = "this is totally haskell code\n\nit deserves its own block!\n"+ cppSplitBlocks input `shouldBe` [HaskellSource 0 input]+ it "should put #if/#endif and Haskell code into separate blocks" $ do+ cppSplitBlocks+ "haskell code\n#if DEBUG\ndebug code\n#endif\nmore haskell code\n" `shouldBe`+ [ HaskellSource 0 "haskell code"+ , CPPDirectives "#if DEBUG"+ , HaskellSource 2 "debug code"+ , CPPDirectives "#endif"+ , HaskellSource 4 "more haskell code\n"+ ]+ it "should put the shebang line into its own block" $ do+ cppSplitBlocks+ "#!/usr/bin/env runhaskell\n{-# LANGUAGE OverloadedStrings #-}\n" `shouldBe`+ [ Shebang "#!/usr/bin/env runhaskell"+ , HaskellSource 1 "{-# LANGUAGE OverloadedStrings #-}\n"+ ]+ it "should put a multi-line #define into its own block" $ do+ let input = "#define A \\\n macro contents \\\n go here\nhaskell code\n"+ cppSplitBlocks input `shouldBe`+ [ CPPDirectives "#define A \\\n macro contents \\\n go here"+ , HaskellSource 3 "haskell code\n"+ ]+ it "should put an unterminated multi-line #define into its own block" $ do+ cppSplitBlocks "#define A \\" `shouldBe` [CPPDirectives "#define A \\"]+ cppSplitBlocks "#define A \\\n" `shouldBe` [CPPDirectives "#define A \\"]+ cppSplitBlocks "#define A \\\n.\\" `shouldBe`+ [CPPDirectives "#define A \\\n.\\"]++markdoneSpec :: Spec+markdoneSpec = do+ describe "markdown tokenizer" $ do+ it "should tokenize plain text" $ do+ let input =+ "this is a line\nthis is another line\n\nthis is a new paragraph\n"+ tokenize input `shouldBe`+ [ PlainLine "this is a line"+ , PlainLine "this is another line"+ , PlainLine ""+ , PlainLine "this is a new paragraph"+ ]+ it "should tokenize headings" $ do+ tokenize "# Heading" `shouldBe` [Heading 1 "Heading"]+ it "should tokenize code fence beginnings with labels" $ do+ tokenize "``` haskell\n" `shouldBe` [BeginFence "haskell"]+ tokenize "```haskell expect\n" `shouldBe` [BeginFence "haskell expect"]+ tokenize "before\n```code\nafter\n" `shouldBe`+ [PlainLine "before", BeginFence "code", PlainLine "after"]+ it "should tokenize full code fences" $ do+ tokenize "```haskell\ncode goes here\n```" `shouldBe`+ [BeginFence "haskell", PlainLine "code goes here", EndFence]+ it "should tokenize lines inside code fences as plain text" $ do+ tokenize "```haskell\n#!/usr/bin/env stack\n```" `shouldBe`+ [BeginFence "haskell", PlainLine "#!/usr/bin/env stack", EndFence]+ tokenize "```haskell\n# not a heading\n```" `shouldBe`+ [BeginFence "haskell", PlainLine "# not a heading", EndFence]+ describe "markdown parser" $ do+ it "should parse a heading followed by text as a section" $ do+ let input =+ [ Heading 1 "This is a heading"+ , PlainLine "This is plain text"+ , PlainLine "split across two lines."+ ]+ output <- parse input+ output `shouldBe`+ [ Section+ "This is a heading"+ [PlainText "This is plain text\nsplit across two lines."]+ ]++-- | Returns the version of the compiler used to build this program.+--+-- This function is a wrapper for `compilerVersion` and+-- `fullCompilerVersion` defined in `System.info`. If the `base` package+-- 4.15.0.0 or later is used, the latter function is defined and hence the+-- value is returned, otherwise the former value is returned.+compilerVersion :: Version+#if MIN_VERSION_base(4,15,0)+compilerVersion = System.Info.fullCompilerVersion+#else+compilerVersion = System.Info.compilerVersion+#endif