packages feed

retrie 1.2.3 → 2.0.0

raw patch · 104 files changed

+1891/−1071 lines, 104 filesdep −tasty-hunitdep ~ansi-terminaldep ~basedep ~containerssetup-changedPVP ok

version bump matches the API change (PVP)

Dependencies removed: tasty-hunit

Dependency ranges changed: ansi-terminal, base, containers, data-default, ghc, ghc-exactprint, haskell-src-exts

API changes (from Hackage documentation)

- Retrie.ExactPrint: d1 :: EpaLocation
- Retrie.ExactPrint: m1 :: AnchorOperation
- Retrie.ExactPrint: mn :: Int -> AnchorOperation
- Retrie.ExactPrint: rs :: SrcSpan -> RealSrcSpan
- Retrie.ExactPrint: transferAnchor :: LocatedA a -> LocatedA b -> LocatedA b
- Retrie.ExactPrint: transferEntryDPT :: (HasCallStack, Data a, Data b, Monad m) => Located a -> Located b -> TransformT m ()
- Retrie.ExactPrint.Annotated: instance Data.Default.Class.Default ast => Data.Default.Class.Default (Retrie.ExactPrint.Annotated.Annotated ast)
- Retrie.SYB: data () => Generic' (c :: Type -> Type)
- Retrie.SYB: ext2 :: (Data a, Typeable t) => c a -> (forall d1 d2. (Data d1, Data d2) => c (t d1 d2)) -> c a
- Retrie.SYB: type Strategy m = forall a. Monad m => (a -> m a) -> (a -> m a) -> a -> m a
- Retrie.Types: IsHsAppsTy :: ParentPrec
+ Retrie: [jobs] :: Options_ rewrites imports -> Maybe Int
+ Retrie.ExactPrint: origDelta :: RealSrcSpan -> RealSrcSpan -> DeltaPos
+ Retrie.ExactPrint: setEntryDP :: Default t => LocatedAn t a -> DeltaPos -> LocatedAn t a
+ Retrie.ExactPrint: setTrailingAnns :: [TrailingAnn] -> LocatedA a -> LocatedA a
+ Retrie.ExactPrint: stripOuterAnns :: LocatedA a -> LocatedA a
+ Retrie.ExactPrint: trailingAnns :: LocatedA a -> [TrailingAnn]
+ Retrie.ExactPrint: transferEntryDP :: forall (m :: Type -> Type) t2 t1 a b. (Monad m, Monoid t2, Typeable t1, Typeable t2) => LocatedAn t1 a -> LocatedAn t2 b -> TransformT m (LocatedAn t2 b)
+ Retrie.ExactPrint: tweakDelta :: DeltaPos -> DeltaPos
+ Retrie.ExactPrint.Annotated: instance Data.Default.Internal.Default ast => Data.Default.Internal.Default (Retrie.ExactPrint.Annotated.Annotated ast)
+ Retrie.Expr: mkParen :: forall (m :: Type -> Type). Monad m => LHsExpr GhcPs -> TransformT m (LHsExpr GhcPs)
+ Retrie.GHC: AbstractTypeFlavour :: TyConFlavour tc
+ Retrie.GHC: BuiltInTypeFlavour :: TyConFlavour tc
+ Retrie.GHC: ClassFlavour :: TyConFlavour tc
+ Retrie.GHC: ClosedTypeFamilyFlavour :: TyConFlavour tc
+ Retrie.GHC: DataTypeFlavour :: TyConFlavour tc
+ Retrie.GHC: DoPmc :: DoPmc
+ Retrie.GHC: IAmData :: TypeOrData
+ Retrie.GHC: IAmType :: TypeOrData
+ Retrie.GHC: NewtypeFlavour :: TyConFlavour tc
+ Retrie.GHC: NonCanonical :: SourceText -> OverlapMode
+ Retrie.GHC: OpenFamilyFlavour :: TypeOrData -> Maybe tc -> TyConFlavour tc
+ Retrie.GHC: PromotedDataConFlavour :: TyConFlavour tc
+ Retrie.GHC: SkipPmc :: DoPmc
+ Retrie.GHC: SumFlavour :: TyConFlavour tc
+ Retrie.GHC: TupleFlavour :: Boxity -> TyConFlavour tc
+ Retrie.GHC: TypeSynonymFlavour :: TyConFlavour tc
+ Retrie.GHC: data DoPmc
+ Retrie.GHC: data TyConFlavour tc
+ Retrie.GHC: data TypeOrData
+ Retrie.GHC: dropInvisPats :: [LPat GhcPs] -> [LPat GhcPs]
+ Retrie.GHC: getMatchPats :: Match GhcPs (LHsExpr GhcPs) -> [LPat GhcPs]
+ Retrie.GHC: grhssList :: GRHSs GhcPs body -> [LGRHS GhcPs body]
+ Retrie.GHC: hasNonCanonicalFlag :: OverlapMode -> Bool
+ Retrie.GHC: requiresPMC :: Origin -> Bool
+ Retrie.GHC: tyConFlavourAssoc_maybe :: TyConFlavour tc -> Maybe tc
+ Retrie.Options: [jobs] :: Options_ rewrites imports -> Maybe Int
+ Retrie.SYB: GenericB' :: GenericB -> GenericB'
+ Retrie.SYB: GenericR' :: GenericR m -> GenericR' (m :: Type -> Type)
+ Retrie.SYB: [unGenericB'] :: GenericB' -> GenericB
+ Retrie.SYB: [unGenericR'] :: GenericR' (m :: Type -> Type) -> GenericR m
+ Retrie.SYB: decT :: forall {k} (a :: k) (b :: k). (Typeable a, Typeable b) => Either ((a :~: b) -> Void) (a :~: b)
+ Retrie.SYB: gshowsF :: Data b => (forall a. Data a => a -> ShowS) -> b -> ShowS
+ Retrie.SYB: hdecT :: forall {k1} {k2} (a :: k1) (b :: k2). (Typeable a, Typeable b) => Either ((a :~~: b) -> Void) (a :~~: b)
+ Retrie.SYB: newtype Generic' (c :: Type -> Type)
+ Retrie.SYB: newtype GenericB'
+ Retrie.SYB: newtype GenericR' (m :: Type -> Type)
- Retrie: Options :: imports -> ColoriseFun -> rewrites -> ExecutionMode -> [FilePath] -> FixityEnv -> Int -> Bool -> Bool -> rewrites -> [RoundTrip] -> Bool -> FilePath -> [FilePath] -> Verbosity -> Options_ rewrites imports
+ Retrie: Options :: imports -> ColoriseFun -> rewrites -> ExecutionMode -> [FilePath] -> FixityEnv -> Int -> Maybe Int -> Bool -> Bool -> rewrites -> [RoundTrip] -> Bool -> FilePath -> [FilePath] -> Verbosity -> Options_ rewrites imports
- Retrie: bottomUp :: Strategy m
+ Retrie: bottomUp :: Monad m => (a -> m a) -> (a -> m a) -> a -> m a
- Retrie: graftA :: (Data ast, Monad m) => Annotated ast -> TransformT m ast
+ Retrie: graftA :: forall ast (m :: Type -> Type). (Data ast, Monad m) => Annotated ast -> TransformT m ast
- Retrie: pruneA :: (Data ast, Monad m) => ast -> TransformT m (Annotated ast)
+ Retrie: pruneA :: forall ast (m :: Type -> Type). (Data ast, Monad m) => ast -> TransformT m (Annotated ast)
- Retrie: subst :: (MonadIO m, Data ast) => Substitution -> Context -> ast -> TransformT m ast
+ Retrie: subst :: forall (m :: Type -> Type) ast. (MonadIO m, Data ast) => Substitution -> Context -> ast -> TransformT m ast
- Retrie: topDown :: Strategy m
+ Retrie: topDown :: Monad m => (a -> m a) -> (a -> m a) -> a -> m a
- Retrie: topDownPrune :: Monad m => Strategy (TransformT (WriterT Change m))
+ Retrie: topDownPrune :: forall (m :: Type -> Type). Monad m => Strategy (TransformT (WriterT Change m))
- Retrie: type AnnotatedHsDecl = Annotated (LHsDecl GhcPs)
+ Retrie: type AnnotatedHsDecl = Annotated LHsDecl GhcPs
- Retrie: type AnnotatedHsExpr = Annotated (LHsExpr GhcPs)
+ Retrie: type AnnotatedHsExpr = Annotated LHsExpr GhcPs
- Retrie: type AnnotatedHsType = Annotated (LHsType GhcPs)
+ Retrie: type AnnotatedHsType = Annotated LHsType GhcPs
- Retrie: type AnnotatedModule = Annotated (Located (HsModule GhcPs))
+ Retrie: type AnnotatedModule = Annotated Located HsModule GhcPs
- Retrie: type AnnotatedPat = Annotated (LPat GhcPs)
+ Retrie: type AnnotatedPat = Annotated LPat GhcPs
- Retrie: type AnnotatedStmt = Annotated (LStmt GhcPs (LHsExpr GhcPs))
+ Retrie: type AnnotatedStmt = Annotated LStmt GhcPs LHsExpr GhcPs
- Retrie: type ContextUpdater = forall m. MonadIO m => GenericCU (TransformT m) Context
+ Retrie: type ContextUpdater = forall (m :: Type -> Type). MonadIO m => GenericCU TransformT m Context
- Retrie: type MatchResultTransformer = Context -> MatchResult Universe -> IO (MatchResult Universe)
+ Retrie: type MatchResultTransformer = Context -> MatchResult Universe -> IO MatchResult Universe
- Retrie: updateContext :: forall m. MonadIO m => GenericCU (TransformT m) Context
+ Retrie: updateContext :: forall (m :: Type -> Type). MonadIO m => GenericCU (TransformT m) Context
- Retrie.Context: type ContextUpdater = forall m. MonadIO m => GenericCU (TransformT m) Context
+ Retrie.Context: type ContextUpdater = forall (m :: Type -> Type). MonadIO m => GenericCU TransformT m Context
- Retrie.Context: updateContext :: forall m. MonadIO m => GenericCU (TransformT m) Context
+ Retrie.Context: updateContext :: forall (m :: Type -> Type). MonadIO m => GenericCU (TransformT m) Context
- Retrie.ExactPrint: addAllAnnsT :: (HasCallStack, Monoid an, Data a, Data b, MonadIO m, Typeable an) => LocatedAn an a -> LocatedAn an b -> TransformT m (LocatedAn an b)
+ Retrie.ExactPrint: addAllAnnsT :: forall an a b (m :: Type -> Type). (HasCallStack, Monoid an, Data a, Data b, MonadIO m, Typeable an) => LocatedAn an a -> LocatedAn an b -> TransformT m (LocatedAn an b)
- Retrie.ExactPrint: data () => BlankEpAnnotations
+ Retrie.ExactPrint: data BlankEpAnnotations
- Retrie.ExactPrint: data () => BlankSrcSpan
+ Retrie.ExactPrint: data BlankSrcSpan
- Retrie.ExactPrint: data () => Comment
+ Retrie.ExactPrint: data Comment
- Retrie.ExactPrint: data () => WithWhere
+ Retrie.ExactPrint: data WithWhere
- Retrie.ExactPrint: fix :: (Data ast, MonadIO m) => FixityEnv -> ast -> TransformT m ast
+ Retrie.ExactPrint: fix :: forall ast (m :: Type -> Type). (Data ast, MonadIO m) => FixityEnv -> ast -> TransformT m ast
- Retrie.ExactPrint: newtype () => TransformT (m :: Type -> Type) a
+ Retrie.ExactPrint: newtype TransformT (m :: Type -> Type) a
- Retrie.ExactPrint: swapEntryDPT :: (Data a, Data b, Monad m, Monoid a1, Monoid a2, Typeable a1, Typeable a2) => LocatedAn a1 a -> LocatedAn a2 b -> TransformT m (LocatedAn a1 a, LocatedAn a2 b)
+ Retrie.ExactPrint: swapEntryDPT :: forall a b (m :: Type -> Type) a1 a2. (Data a, Data b, Monad m, Monoid a1, Monoid a2, Typeable a1, Typeable a2) => LocatedAn a1 a -> LocatedAn a2 b -> TransformT m (LocatedAn a1 a, LocatedAn a2 b)
- Retrie.ExactPrint: transferAnnsT :: (Data a, Data b, Monad m) => (TrailingAnn -> Bool) -> LocatedA a -> LocatedA b -> TransformT m (LocatedA b)
+ Retrie.ExactPrint: transferAnnsT :: forall a b (m :: Type -> Type). (Data a, Data b, Monad m) => (TrailingAnn -> Bool) -> LocatedA a -> LocatedA b -> TransformT m (LocatedA b)
- Retrie.ExactPrint: transferEntryAnnsT :: (HasCallStack, Data a, Data b, Monad m) => (TrailingAnn -> Bool) -> LocatedA a -> LocatedA b -> TransformT m (LocatedA b)
+ Retrie.ExactPrint: transferEntryAnnsT :: forall a b (m :: Type -> Type). (HasCallStack, Data a, Data b, Monad m) => LocatedA a -> LocatedA b -> TransformT m (LocatedA b)
- Retrie.ExactPrint.Annotated: graftA :: (Data ast, Monad m) => Annotated ast -> TransformT m ast
+ Retrie.ExactPrint.Annotated: graftA :: forall ast (m :: Type -> Type). (Data ast, Monad m) => Annotated ast -> TransformT m ast
- Retrie.ExactPrint.Annotated: pruneA :: (Data ast, Monad m) => ast -> TransformT m (Annotated ast)
+ Retrie.ExactPrint.Annotated: pruneA :: forall ast (m :: Type -> Type). (Data ast, Monad m) => ast -> TransformT m (Annotated ast)
- Retrie.ExactPrint.Annotated: type AnnotatedHsDecl = Annotated (LHsDecl GhcPs)
+ Retrie.ExactPrint.Annotated: type AnnotatedHsDecl = Annotated LHsDecl GhcPs
- Retrie.ExactPrint.Annotated: type AnnotatedHsExpr = Annotated (LHsExpr GhcPs)
+ Retrie.ExactPrint.Annotated: type AnnotatedHsExpr = Annotated LHsExpr GhcPs
- Retrie.ExactPrint.Annotated: type AnnotatedHsType = Annotated (LHsType GhcPs)
+ Retrie.ExactPrint.Annotated: type AnnotatedHsType = Annotated LHsType GhcPs
- Retrie.ExactPrint.Annotated: type AnnotatedImport = Annotated (LImportDecl GhcPs)
+ Retrie.ExactPrint.Annotated: type AnnotatedImport = Annotated LImportDecl GhcPs
- Retrie.ExactPrint.Annotated: type AnnotatedModule = Annotated (Located (HsModule GhcPs))
+ Retrie.ExactPrint.Annotated: type AnnotatedModule = Annotated Located HsModule GhcPs
- Retrie.ExactPrint.Annotated: type AnnotatedPat = Annotated (LPat GhcPs)
+ Retrie.ExactPrint.Annotated: type AnnotatedPat = Annotated LPat GhcPs
- Retrie.ExactPrint.Annotated: type AnnotatedStmt = Annotated (LStmt GhcPs (LHsExpr GhcPs))
+ Retrie.ExactPrint.Annotated: type AnnotatedStmt = Annotated LStmt GhcPs LHsExpr GhcPs
- Retrie.Expr: mkApps :: MonadIO m => LHsExpr GhcPs -> [LHsExpr GhcPs] -> TransformT m (LHsExpr GhcPs)
+ Retrie.Expr: mkApps :: forall (m :: Type -> Type). MonadIO m => LHsExpr GhcPs -> [LHsExpr GhcPs] -> TransformT m (LHsExpr GhcPs)
- Retrie.Expr: mkConPatIn :: Monad m => LocatedN RdrName -> HsConPatDetails GhcPs -> TransformT m (LPat GhcPs)
+ Retrie.Expr: mkConPatIn :: forall (m :: Type -> Type). Monad m => LocatedN RdrName -> HsConPatDetails GhcPs -> TransformT m (LPat GhcPs)
- Retrie.Expr: mkEpAnn :: Monad m => DeltaPos -> an -> TransformT m (EpAnn an)
+ Retrie.Expr: mkEpAnn :: forall (m :: Type -> Type) an. Monad m => DeltaPos -> an -> TransformT m (EpAnn an)
- Retrie.Expr: mkHsAppsTy :: Monad m => [LHsType GhcPs] -> TransformT m (LHsType GhcPs)
+ Retrie.Expr: mkHsAppsTy :: forall (m :: Type -> Type). Monad m => [LHsType GhcPs] -> TransformT m (LHsType GhcPs)
- Retrie.Expr: mkLet :: Monad m => HsLocalBinds GhcPs -> LHsExpr GhcPs -> TransformT m (LHsExpr GhcPs)
+ Retrie.Expr: mkLet :: forall (m :: Type -> Type). Monad m => HsLocalBinds GhcPs -> LHsExpr GhcPs -> TransformT m (LHsExpr GhcPs)
- Retrie.Expr: mkLoc :: (Data e, Monad m) => e -> TransformT m (Located e)
+ Retrie.Expr: mkLoc :: forall e (m :: Type -> Type). (Data e, Monad m) => e -> TransformT m (Located e)
- Retrie.Expr: mkLocA :: (Data e, Monad m, Monoid an) => DeltaPos -> e -> TransformT m (LocatedAn an e)
+ Retrie.Expr: mkLocA :: forall e (m :: Type -> Type) an. (Data e, Monad m, Monoid an) => DeltaPos -> e -> TransformT m (LocatedAn an e)
- Retrie.Expr: mkLocatedHsVar :: Monad m => LocatedN RdrName -> TransformT m (LHsExpr GhcPs)
+ Retrie.Expr: mkLocatedHsVar :: forall (m :: Type -> Type). Monad m => LocatedN RdrName -> TransformT m (LHsExpr GhcPs)
- Retrie.Expr: mkTyVar :: Monad m => LocatedN RdrName -> TransformT m (LHsType GhcPs)
+ Retrie.Expr: mkTyVar :: forall (m :: Type -> Type). Monad m => LocatedN RdrName -> TransformT m (LHsType GhcPs)
- Retrie.Expr: mkVarPat :: Monad m => LocatedN RdrName -> TransformT m (LPat GhcPs)
+ Retrie.Expr: mkVarPat :: forall (m :: Type -> Type). Monad m => LocatedN RdrName -> TransformT m (LPat GhcPs)
- Retrie.Expr: parenify :: Monad m => Context -> LHsExpr GhcPs -> TransformT m (LHsExpr GhcPs)
+ Retrie.Expr: parenify :: forall (m :: Type -> Type). Monad m => Context -> LHsExpr GhcPs -> TransformT m (LHsExpr GhcPs)
- Retrie.Expr: parenifyP :: Monad m => Context -> LPat GhcPs -> TransformT m (LPat GhcPs)
+ Retrie.Expr: parenifyP :: forall (m :: Type -> Type). Monad m => Context -> LPat GhcPs -> TransformT m (LPat GhcPs)
- Retrie.Expr: parenifyT :: Monad m => Context -> LHsType GhcPs -> TransformT m (LHsType GhcPs)
+ Retrie.Expr: parenifyT :: forall (m :: Type -> Type). Monad m => Context -> LHsType GhcPs -> TransformT m (LHsType GhcPs)
- Retrie.Expr: patToExpr :: MonadIO m => LPat GhcPs -> PatQ m (LHsExpr GhcPs)
+ Retrie.Expr: patToExpr :: forall (m :: Type -> Type). MonadIO m => LPat GhcPs -> PatQ m (LHsExpr GhcPs)
- Retrie.Fixity: data () => Fixity
+ Retrie.Fixity: data Fixity
- Retrie.Fixity: data () => FixityDirection
+ Retrie.Fixity: data FixityDirection
- Retrie.GHC: Generated :: Origin
+ Retrie.GHC: Generated :: DoPmc -> Origin
- Retrie.GHC: cLPat :: LPat (GhcPass p) -> LPat (GhcPass p)
+ Retrie.GHC: cLPat :: forall (p :: Pass). LPat (GhcPass p) -> LPat (GhcPass p)
- Retrie.GHC: class () => Outputable a
+ Retrie.GHC: class Outputable a
- Retrie.GHC: dLPat :: LPat (GhcPass p) -> Maybe (LPat (GhcPass p))
+ Retrie.GHC: dLPat :: forall (p :: Pass). LPat (GhcPass p) -> Maybe (LPat (GhcPass p))
- Retrie.GHC: dLPatUnsafe :: LPat (GhcPass p) -> LPat (GhcPass p)
+ Retrie.GHC: dLPatUnsafe :: forall (p :: Pass). LPat (GhcPass p) -> LPat (GhcPass p)
- Retrie.GHC: data () => Activation
+ Retrie.GHC: data Activation
- Retrie.GHC: data () => Alignment
+ Retrie.GHC: data Alignment
- Retrie.GHC: data () => Boxity
+ Retrie.GHC: data Boxity
- Retrie.GHC: data () => CbvMark
+ Retrie.GHC: data CbvMark
- Retrie.GHC: data () => CompilerPhase
+ Retrie.GHC: data CompilerPhase
- Retrie.GHC: data () => DefMethSpec ty
+ Retrie.GHC: data DefMethSpec ty
- Retrie.GHC: data () => DefaultingStrategy
+ Retrie.GHC: data DefaultingStrategy
- Retrie.GHC: data () => ForeignSrcLang
+ Retrie.GHC: data ForeignSrcLang
- Retrie.GHC: data () => FunctionOrData
+ Retrie.GHC: data FunctionOrData
- Retrie.GHC: data () => InlinePragma
+ Retrie.GHC: data InlinePragma
- Retrie.GHC: data () => InlineSpec
+ Retrie.GHC: data InlineSpec
- Retrie.GHC: data () => InsideLam
+ Retrie.GHC: data InsideLam
- Retrie.GHC: data () => IntWithInf
+ Retrie.GHC: data IntWithInf
- Retrie.GHC: data () => InterestingCxt
+ Retrie.GHC: data InterestingCxt
- Retrie.GHC: data () => LeftOrRight
+ Retrie.GHC: data LeftOrRight
- Retrie.GHC: data () => Levity
+ Retrie.GHC: data Levity
- Retrie.GHC: data () => NonStandardDefaultingStrategy
+ Retrie.GHC: data NonStandardDefaultingStrategy
- Retrie.GHC: data () => OccInfo
+ Retrie.GHC: data OccInfo
- Retrie.GHC: data () => OneShotInfo
+ Retrie.GHC: data OneShotInfo
- Retrie.GHC: data () => Origin
+ Retrie.GHC: data Origin
- Retrie.GHC: data () => OverlapFlag
+ Retrie.GHC: data OverlapFlag
- Retrie.GHC: data () => OverlapMode
+ Retrie.GHC: data OverlapMode
- Retrie.GHC: data () => PromotionFlag
+ Retrie.GHC: data PromotionFlag
- Retrie.GHC: data () => RecFlag
+ Retrie.GHC: data RecFlag
- Retrie.GHC: data () => RuleMatchInfo
+ Retrie.GHC: data RuleMatchInfo
- Retrie.GHC: data () => SuccessFlag
+ Retrie.GHC: data SuccessFlag
- Retrie.GHC: data () => SwapFlag
+ Retrie.GHC: data SwapFlag
- Retrie.GHC: data () => TailCallInfo
+ Retrie.GHC: data TailCallInfo
- Retrie.GHC: data () => TopLevelFlag
+ Retrie.GHC: data TopLevelFlag
- Retrie.GHC: data () => TupleSort
+ Retrie.GHC: data TupleSort
- Retrie.GHC: data () => TypeOrConstraint
+ Retrie.GHC: data TypeOrConstraint
- Retrie.GHC: data () => TypeOrKind
+ Retrie.GHC: data TypeOrKind
- Retrie.GHC: data () => UnboxedTupleOrSum
+ Retrie.GHC: data UnboxedTupleOrSum
- Retrie.GHC: data () => UnfoldingSource
+ Retrie.GHC: data UnfoldingSource
- Retrie.GHC: newtype () => PprPrec
+ Retrie.GHC: newtype PprPrec
- Retrie.Monad: topDownPrune :: Monad m => Strategy (TransformT (WriterT Change m))
+ Retrie.Monad: topDownPrune :: forall (m :: Type -> Type). Monad m => Strategy (TransformT (WriterT Change m))
- Retrie.Options: Options :: imports -> ColoriseFun -> rewrites -> ExecutionMode -> [FilePath] -> FixityEnv -> Int -> Bool -> Bool -> rewrites -> [RoundTrip] -> Bool -> FilePath -> [FilePath] -> Verbosity -> Options_ rewrites imports
+ Retrie.Options: Options :: imports -> ColoriseFun -> rewrites -> ExecutionMode -> [FilePath] -> FixityEnv -> Int -> Maybe Int -> Bool -> Bool -> rewrites -> [RoundTrip] -> Bool -> FilePath -> [FilePath] -> Verbosity -> Options_ rewrites imports
- Retrie.PatternMap.Class: ListMap :: MaybeMap a -> m (ListMap m a) -> ListMap m a
+ Retrie.PatternMap.Class: ListMap :: MaybeMap a -> m (ListMap m a) -> ListMap (m :: Type -> Type) a
- Retrie.PatternMap.Class: ME :: AlphaEnv -> (forall a. a -> Annotated a) -> MatchEnv
+ Retrie.PatternMap.Class: ME :: AlphaEnv -> (forall a. () => a -> Annotated a) -> MatchEnv
- Retrie.PatternMap.Class: [lmCons] :: ListMap m a -> m (ListMap m a)
+ Retrie.PatternMap.Class: [lmCons] :: ListMap (m :: Type -> Type) a -> m (ListMap m a)
- Retrie.PatternMap.Class: [lmNil] :: ListMap m a -> MaybeMap a
+ Retrie.PatternMap.Class: [lmNil] :: ListMap (m :: Type -> Type) a -> MaybeMap a
- Retrie.PatternMap.Class: [mePruneA] :: MatchEnv -> forall a. a -> Annotated a
+ Retrie.PatternMap.Class: [mePruneA] :: MatchEnv -> forall a. () => a -> Annotated a
- Retrie.PatternMap.Class: class PatternMap m where {
+ Retrie.PatternMap.Class: class PatternMap (m :: Type -> Type) where {
- Retrie.PatternMap.Class: data ListMap m a
+ Retrie.PatternMap.Class: data ListMap (m :: Type -> Type) a
- Retrie.PatternMap.Class: type Key m :: Type;
+ Retrie.PatternMap.Class: type Key (m :: Type -> Type);
- Retrie.PatternMap.Instances: fieldsToRdrNamesUpd :: Either [LHsRecUpdField GhcPs] [LHsRecUpdProj GhcPs] -> [LHsRecField GhcPs (LHsExpr GhcPs)]
+ Retrie.PatternMap.Instances: fieldsToRdrNamesUpd :: LHsRecUpdFields GhcPs -> [LHsRecField GhcPs (LHsExpr GhcPs)]
- Retrie.Replace: replace :: (Data a, MonadIO m) => Context -> a -> TransformT (WriterT Change m) a
+ Retrie.Replace: replace :: forall a (m :: Type -> Type). (Data a, MonadIO m) => Context -> a -> TransformT (WriterT Change m) a
- Retrie.Rewrites.Types: mkTypeRewrite :: Direction -> (LocatedN RdrName, [LHsTyVarBndr () GhcPs], LHsType GhcPs) -> TransformT IO (Rewrite (LHsType GhcPs))
+ Retrie.Rewrites.Types: mkTypeRewrite :: Direction -> (LocatedN RdrName, [LHsTyVarBndr (HsBndrVis GhcPs) GhcPs], LHsType GhcPs) -> TransformT IO (Rewrite (LHsType GhcPs))
- Retrie.SYB: bottomUp :: Strategy m
+ Retrie.SYB: bottomUp :: Monad m => (a -> m a) -> (a -> m a) -> a -> m a
- Retrie.SYB: class () => Typeable (a :: k)
+ Retrie.SYB: class Typeable (a :: k)
- Retrie.SYB: data () => (a :: k) :~: (b :: k)
+ Retrie.SYB: data (a :: k) :~: (b :: k)
- Retrie.SYB: data () => Constr
+ Retrie.SYB: data Constr
- Retrie.SYB: data () => ConstrRep
+ Retrie.SYB: data ConstrRep
- Retrie.SYB: data () => DataRep
+ Retrie.SYB: data DataRep
- Retrie.SYB: data () => DataType
+ Retrie.SYB: data DataType
- Retrie.SYB: data () => Proxy (t :: k)
+ Retrie.SYB: data Proxy (t :: k)
- Retrie.SYB: data () => TyCon
+ Retrie.SYB: data TyCon
- Retrie.SYB: everythingMWithContextBut :: forall m c r. (Monad m, Monoid r) => GenericQ Bool -> GenericCU m c -> GenericMCQ m c r -> GenericMCQ m c r
+ Retrie.SYB: everythingMWithContextBut :: forall (m :: Type -> Type) c r. (Monad m, Monoid r) => GenericQ Bool -> GenericCU m c -> GenericMCQ m c r -> GenericMCQ m c r
- Retrie.SYB: everywhereMWithContextBut :: forall m c. Monad m => Strategy m -> GenericQ Bool -> GenericCU m c -> GenericMC m c -> GenericMC m c
+ Retrie.SYB: everywhereMWithContextBut :: forall (m :: Type -> Type) c. Monad m => Strategy m -> GenericQ Bool -> GenericCU m c -> GenericMC m c -> GenericMC m c
- Retrie.SYB: newtype () => GenericM' (m :: Type -> Type)
+ Retrie.SYB: newtype GenericM' (m :: Type -> Type)
- Retrie.SYB: newtype () => GenericQ' r
+ Retrie.SYB: newtype GenericQ' r
- Retrie.SYB: newtype () => GenericT'
+ Retrie.SYB: newtype GenericT'
- Retrie.SYB: topDown :: Strategy m
+ Retrie.SYB: topDown :: Monad m => (a -> m a) -> (a -> m a) -> a -> m a
- Retrie.SYB: type GenericMCQ m c r = forall a. Data a => c -> a -> m r
+ Retrie.SYB: type GenericMCQ (m :: Type -> Type) c r = forall a. Data a => c -> a -> m r
- Retrie.Subst: subst :: (MonadIO m, Data ast) => Substitution -> Context -> ast -> TransformT m ast
+ Retrie.Subst: subst :: forall (m :: Type -> Type) ast. (MonadIO m, Data ast) => Substitution -> Context -> ast -> TransformT m ast
- Retrie.Types: runMatcher :: (Matchable ast, MonadIO m) => Context -> Matcher v -> ast -> TransformT m [(Substitution, v)]
+ Retrie.Types: runMatcher :: forall ast (m :: Type -> Type) v. (Matchable ast, MonadIO m) => Context -> Matcher v -> ast -> TransformT m [(Substitution, v)]
- Retrie.Types: runRewriter :: forall ast m. (Matchable ast, MonadIO m) => (RewriterResult Universe -> RewriterResult Universe) -> Context -> Rewriter -> ast -> TransformT m (MatchResult ast)
+ Retrie.Types: runRewriter :: forall ast (m :: Type -> Type). (Matchable ast, MonadIO m) => (RewriterResult Universe -> RewriterResult Universe) -> Context -> Rewriter -> ast -> TransformT m (MatchResult ast)
- Retrie.Types: type MatchResultTransformer = Context -> MatchResult Universe -> IO (MatchResult Universe)
+ Retrie.Types: type MatchResultTransformer = Context -> MatchResult Universe -> IO MatchResult Universe
- Retrie.Types: type Rewriter = Matcher (RewriterResult Universe)
+ Retrie.Types: type Rewriter = Matcher RewriterResult Universe

Files

CHANGELOG.md view
@@ -1,38 +1,111 @@-1.2.3.0 (January, 2024)+2.0.0 (October 4, 2026) -* Support for GHC 9.8.1 and 9.6.3 (Pranay Sashank)+* Project home moved from facebookincubator/retrie to xich/retrie. Report+  issues and send PRs to https://github.com/xich/retrie+* Support for GHC 9.14 (#13, @simonhorlick)+* Support for GHC 9.12 (#9, @pe200012)+* Dropped support for GHC < 9.6 (supported: 9.6, 9.8, 9.12, 9.14) (#3, @xich)+* Added -j/--jobs flag to bound the number of files rewritten concurrently.+  Defaults to the number of RTS capabilities, so peak memory use no longer+  grows with the number of target files. Fixes #10 (#18, @xich)+* Build the executables with the threaded RTS, so -j (or +RTS -N) actually+  rewrites files concurrently (#18, @xich)+* Require ghc-exactprint >= 1.12.1 (GHC 9.12) and >= 1.14.2 (GHC 9.14), which+  fix a space leak that caused high memory use on large files (#20, @xich)+* Split long grep/VCS invocations into chunks under the system argument limit,+  fixing failures with tens of thousands of target files+  (facebookincubator/retrie#63, @watashi)+* Fix missing parentheses in rewritten expressions and redundant parentheses+  in rewritten types (facebookincubator/retrie#69, @watashi)+* Don't strip the parentheses around sections, which produced malformed+  output (facebookincubator/retrie#70, @watashi)+* Add parentheses where needed when substituting into sections, record+  updates, record-dot projections and negation (#23, @simonhorlick)+* Backtick (infix) rewrites now work for functions of arity greater than two;+  previously these produced code that didn't compile (#14, @simonhorlick)+* Fix many exact-printing bugs in rewritten code: duplicated or misplaced+  trailing commas (e.g. "[succ 4,, ...]" or "(succ 1,)"), lost comments and+  syntax errors when a template has comments before a hole, stray spaces like+  "( Just x)", and lost annotations when reassociating infix operators and+  constructor patterns (#21, #26, @simonhorlick)+* Fix rewrites of expressions and patterns that were reassociated by fixity,+  which could replace the wrong source span (#21, @simonhorlick)+* Fix broken layout in CPP modules when a multi-line replacement lands+  somewhere other than column 1: continuation lines are now indented relative+  to where the replacement starts. Fixes #24 (#29, @xich)+* Preserve comments and layout when unfolding definitions with where clauses+  (#19, @simonhorlick)+* Unfolding works for constructor patterns with type applications+  (type arguments are ignored) (#13, @simonhorlick)+* Report unsupported type-variable binder syntax with the usual "missing+  syntax" error instead of crashing (#9, @pe200012) -1.2.0.0 (December 12, 2021)+1.2.3 (January 15, 2024) +* Support for GHC 9.8 (facebookincubator/retrie#61, @pranaysashank)+* Allow mtl 2.3 and transformers 0.6, as shipped with GHC 9.6+  (facebookincubator/retrie#56, @wz1000)++1.2.2 (March 24, 2023)++* Support for GHC 9.6 (facebookincubator/retrie#54, @wz1000)+* Allow optparse-applicative 0.17 (facebookincubator/retrie#53, @pepeiborra)++1.2.1.1 (November 17, 2022)++* Simplified build-depends: single ghc and ghc-exactprint bounds instead of+  per-GHC conditionals (facebookincubator/retrie#52, @pepeiborra)++1.2.1 (November 13, 2022)++* Support for GHC 9.4 (facebookincubator/retrie#49, @9999years)+* Escape single quotes in patterns passed to grep+  (facebookincubator/retrie#43, @nrnrnr)+* Support text 2.0 (facebookincubator/retrie#44, facebookincubator/retrie#45,+  @pepeiborra)+* Allow ghc-exactprint 1.5 (facebookincubator/retrie#47, @pepeiborra)++1.2.0.1 (January 3, 2022)++* Upgrade to ghc-exactprint 1.4 (facebookincubator/retrie#40, @pepeiborra)++1.2.0.0 (December 14, 2021)+ * Early support for GHC 9.2.1 (thanks to Alan Zimmerman) * Dropped support for GHC <9.2 (might readd it later)  1.1.0.0 (November 13, 2021)-* Remove dependency on xargs (#31)+* Remove dependency on xargs (facebookincubator/retrie#31) * Allow rewrite elaboration  1.0.0.0 (April 9, 2021) -* Added --adhoc-type flag (#13)-* Added --adhoc-pattern, --pattern-forward, --pattern-backward (#15)+* Added --adhoc-type flag (facebookincubator/retrie#13)+* Added --adhoc-pattern, --pattern-forward, --pattern-backward+  (facebookincubator/retrie#15) * Speed up file search when large number of files match. * Removed support for GHC 8.4 and 8.8 * Added support for GHC 9.0.1  0.1.1.1 (June 1, 2020) -* Remove dependency on haskell-src-exts from library (#9)-* Support additional pattern syntax when generating fold/unfold rewrites (#8)-* Limit partial-application rewrite variants to irrefutible patterns (#7)-* Fix handling of qualified names during substitution (#5)-* Fix self-recursion check for do-syntax binds (#5)-* Fix bug in grep invocation for relative target paths (#5)+* Remove dependency on haskell-src-exts from library+  (facebookincubator/retrie#9)+* Support additional pattern syntax when generating fold/unfold rewrites+  (facebookincubator/retrie#8)+* Limit partial-application rewrite variants to irrefutible patterns+  (facebookincubator/retrie#7)+* Fix handling of qualified names during substitution+  (facebookincubator/retrie#5)+* Fix self-recursion check for do-syntax binds (facebookincubator/retrie#5)+* Fix bug in grep invocation for relative target paths+  (facebookincubator/retrie#5)  0.1.1.0 (May 8, 2020)  * Support GHC 8.10.1 -0.1.0.1 (April 1, 2020)+0.1.0.1 (March 31, 2020)  * Don't fail if 'git' or 'hg' commands cannot be found. * Better error message when syntax support needs to be extended.
− CODE_OF_CONDUCT.md
@@ -1,76 +0,0 @@-# Code of Conduct--## Our Pledge--In the interest of fostering an open and welcoming environment, we as-contributors and maintainers pledge to make participation in our project and-our community a harassment-free experience for everyone, regardless of age, body-size, disability, ethnicity, sex characteristics, gender identity and expression,-level of experience, education, socio-economic status, nationality, personal-appearance, race, religion, or sexual identity and orientation.--## Our Standards--Examples of behavior that contributes to creating a positive environment-include:--* Using welcoming and inclusive language-* Being respectful of differing viewpoints and experiences-* Gracefully accepting constructive criticism-* Focusing on what is best for the community-* Showing empathy towards other community members--Examples of unacceptable behavior by participants include:--* The use of sexualized language or imagery and unwelcome sexual attention or-  advances-* Trolling, insulting/derogatory comments, and personal or political attacks-* Public or private harassment-* Publishing others' private information, such as a physical or electronic-  address, without explicit permission-* Other conduct which could reasonably be considered inappropriate in a-  professional setting--## Our Responsibilities--Project maintainers are responsible for clarifying the standards of acceptable-behavior and are expected to take appropriate and fair corrective action in-response to any instances of unacceptable behavior.--Project maintainers have the right and responsibility to remove, edit, or-reject comments, commits, code, wiki edits, issues, and other contributions-that are not aligned to this Code of Conduct, or to ban temporarily or-permanently any contributor for other behaviors that they deem inappropriate,-threatening, offensive, or harmful.--## Scope--This Code of Conduct applies within all project spaces, and it also applies when-an individual is representing the project or its community in public spaces.-Examples of representing a project or community include using an official-project e-mail address, posting via an official social media account, or acting-as an appointed representative at an online or offline event. Representation of-a project may be further defined and clarified by project maintainers.--## Enforcement--Instances of abusive, harassing, or otherwise unacceptable behavior may be-reported by contacting the project team at <opensource-conduct@fb.com>. All-complaints will be reviewed and investigated and will result in a response that-is deemed necessary and appropriate to the circumstances. The project team is-obligated to maintain confidentiality with regard to the reporter of an incident.-Further details of specific enforcement policies may be posted separately.--Project maintainers who do not follow or enforce the Code of Conduct in good-faith may face temporary or permanent repercussions as determined by other-members of the project's leadership.--## Attribution--This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,-available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html--[homepage]: https://www.contributor-covenant.org--For answers to common questions about this code of conduct, see-https://www.contributor-covenant.org/faq
CONTRIBUTING.md view
@@ -2,11 +2,6 @@ We want to make contributing to this project as easy and transparent as possible. -## Our Development Process-retrie is developed internally at Facebook and then exported to GitHub by an -automated tool. Pull requests will first be imported to our internal -repository, then synced back to GitHub.- ## Pull Requests We actively welcome your pull requests. @@ -14,21 +9,12 @@ 2. If you've added code that should be tested, add tests. 3. If you've changed APIs, update the documentation. 4. Ensure the test suite passes.-5. If you haven't already, complete the Contributor License Agreement ("CLA").--## Contributor License Agreement ("CLA")-In order to accept your pull request, we need you to submit a CLA. You only need-to do this once to work on any of Facebook's open source projects.--Complete your CLA here: <https://code.facebook.com/cla>+5. Please add a line to the 'Unreleased' section of `CHANGELOG.md` as part of your pull request.  ## Issues-We use GitHub issues to track public bugs. Please ensure your description is+We use GitHub issues to track bugs. Please ensure your description is clear and has sufficient instructions to be able to reproduce the issue.--Facebook has a [bounty program](https://www.facebook.com/whitehat/) for the safe-disclosure of security bugs. In those cases, please go through the process-outlined on that page and do not file a public issue.+Ideally, add a failing test.  ## Coding Style   * 2 spaces for indentation rather than tabs
LICENSE view
@@ -1,6 +1,7 @@ MIT License -Copyright (c) Facebook, Inc. and its affiliates.+Copyright (c) 2025 Andrew Farmer+Copyright (c) 2020-2024 Facebook, Inc. and its affiliates.  Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal
README.md view
@@ -296,8 +296,6 @@  To report other bugs, please create a GitHub issue. -[![Build Status](https://travis-ci.com/facebookincubator/retrie.svg?branch=master)](https://travis-ci.com/facebookincubator/retrie)- # License  Retrie is MIT licensed, as found in the [LICENSE](LICENSE) file.
Retrie.hs view
@@ -1,4 +1,5 @@--- Copyright (c) Facebook, Inc. and its affiliates.+-- Copyright (c) 2025 Andrew Farmer+-- Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. -- -- This source code is licensed under the MIT license found in the -- LICENSE file in the root directory of this source tree.
Retrie/AlphaEnv.hs view
@@ -1,4 +1,5 @@--- Copyright (c) Facebook, Inc. and its affiliates.+-- Copyright (c) 2025 Andrew Farmer+-- Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. -- -- This source code is licensed under the MIT license found in the -- LICENSE file in the root directory of this source tree.
Retrie/CPP.hs view
@@ -1,9 +1,9 @@--- Copyright (c) Facebook, Inc. and its affiliates.+-- Copyright (c) 2025 Andrew Farmer+-- Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. -- -- This source code is licensed under the MIT license found in the -- LICENSE file in the root directory of this source tree. ---{-# LANGUAGE CPP #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-} module Retrie.CPP@@ -27,10 +27,7 @@ import Retrie.ExactPrint import Retrie.GHC import Retrie.Replace-#if __GLASGOW_HASKELL__ < 904-#else import GHC.Types.PkgQual-#endif  -- Note [CPP] -- We can't just run the pre-processor on files and then rewrite them, because@@ -108,7 +105,8 @@ printCPP :: [Replacement] -> CPP AnnotatedModule -> String printCPP _ (NoCPP m) = printA m -- printCPP _ (NoCPP m) = error $ "printCPP:m=" ++ showAstA m-printCPP repls (CPP orig is ms) = Text.unpack $ Text.unlines $+printCPP _ (CPP _ _ []) = error $ "printCPP: empty list of modules!"+printCPP repls (CPP orig is (m1:_)) = Text.unpack $ Text.unlines $   case is of     [] -> splice "" 1 1 sorted origLines     _ ->@@ -126,7 +124,7 @@       ]      origLines = Text.lines orig-    mbName = unLoc <$> hsmodName (unLoc $ astA $ head ms)+    mbName = unLoc <$> hsmodName (unLoc $ astA m1)     importLines = runIdentity $ fmap astA $ transformA (filterAndFlatten mbName is) $       mapM $ fmap (Text.pack . dropWhile isSpace . printA) . pruneA @@ -325,13 +323,8 @@ insertImports   :: Monad m   => [AnnotatedImports]   -- ^ imports and their annotations-#if __GLASGOW_HASKELL__ < 906-  -> Located HsModule     -- ^ target module-  -> TransformT m (Located HsModule)-#else   -> Located (HsModule GhcPs)     -- ^ target module   -> TransformT m (Located (HsModule GhcPs))-#endif insertImports is (L l m) = do   imps <- graftA $ filterAndFlatten (unLoc <$> hsmodName m) is   let@@ -351,25 +344,14 @@   ((==) `on` unLoc . ideclName) x y   && ((==) `on` ideclQualified) x y   && ((==) `on` ideclAs) x y-#if __GLASGOW_HASKELL__ <= 904-  && ((==) `on` ideclHiding) x y-#else   && ((==) `on` ideclImportList) x y-#endif-#if __GLASGOW_HASKELL__ < 904-  && ((==) `on` ideclPkgQual) x y-#else   && (eqRawPkgQual `on` ideclPkgQual) x y-#endif   && ((==) `on` ideclSource) x y   && ((==) `on` ideclSafe) x y   -- intentionally leave out ideclImplicit and ideclSourceSrc   -- former doesn't matter for this check, latter is prone to whitespace issues-#if __GLASGOW_HASKELL__ < 904-#else   where     eqRawPkgQual NoRawPkgQual NoRawPkgQual = True     eqRawPkgQual NoRawPkgQual (RawPkgQual _) = False     eqRawPkgQual (RawPkgQual _) NoRawPkgQual = False     eqRawPkgQual (RawPkgQual s) (RawPkgQual s') = s == s'-#endif
Retrie/Context.hs view
@@ -1,9 +1,11 @@--- Copyright (c) Facebook, Inc. and its affiliates.+-- Copyright (c) 2025 Andrew Farmer+-- Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. -- -- This source code is licensed under the MIT license found in the -- LICENSE file in the root directory of this source tree. -- {-# LANGUAGE CPP #-}+{-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE ScopedTypeVariables #-}@@ -17,7 +19,9 @@ import Data.Char (isDigit) import Data.Either (partitionEithers) import Data.Generics hiding (Fixity)+#if __GLASGOW_HASKELL__ < 912 import Data.List+#endif import Data.Maybe  import Retrie.AlphaEnv@@ -54,43 +58,68 @@   where     neverParen = c { ctxtParentPrec = NeverParen } +    withOpPrec :: LHsExpr GhcPs -> Context     updExp :: HsExpr GhcPs -> Context-    updExp HsApp{} =-#if __GLASGOW_HASKELL__ < 908-      c { ctxtParentPrec = HasPrec $ Fixity (SourceText "HsApp") (10 + i - firstChild) InfixL }+    updType :: HsType GhcPs -> Context++    updType HsTupleTy{} = neverParen+    updType HsListTy{} = neverParen+    updType HsParTy{} = neverParen+#if __GLASGOW_HASKELL__ < 912+    updType HsAppTy{} = withPrec c (SourceText "HsAppTy") (getPrec appPrec) InfixL i+    updType HsFunTy{} = withPrec c (SourceText "HsFunTy") (getPrec funPrec) InfixR (i - 1)+    updType _ = withPrec c (SourceText "HsType") (getPrec appPrec) InfixN i++    withOpPrec op+      | Fixity source prec dir <- lookupOp op $ ctxtFixityEnv c =+        withPrec c source prec dir i++    updExp HsApp{} = withPrec c (SourceText "HsApp") 10 InfixL i+    updExp RecordUpd{}+      | i == firstChild = withPrec c (SourceText "RecordUpd") 11 InfixN i+    updExp HsGetField{}+      | i == firstChild = withPrec c (SourceText "HsGetField") 11 InfixN i+    updExp NegApp{} = withPrec c (SourceText "NegApp") 6 InfixN i+    updExp (HsLet _ _ lbs _ _) = addInScope neverParen $ collectLocalBinders CollNoDictBinders lbs #else-      c { ctxtParentPrec = HasPrec $ Fixity (SourceText (fsLit "HsApp")) (10 + i - firstChild) InfixL }-#endif-    -- Reason for 10 + i: (i is index of child, 0 = left, 1 = right)-    -- In left child, prec is 10, so HsApp child will NOT get paren'd-    -- In right child, prec is 11, so every child gets paren'd (unless atomic)-    updExp (OpApp _ _ op _) = c { ctxtParentPrec = HasPrec $ lookupOp op (ctxtFixityEnv c) }-#if __GLASGOW_HASKELL__ < 904+    updType HsAppTy{} = withPrec c (getPrec appPrec) InfixL i+    updType HsFunTy{} = withPrec c (getPrec funPrec) InfixR (i - 1)+    updType _ = withPrec c (getPrec appPrec) InfixN i++    withOpPrec op+      | Fixity prec dir <- lookupOp op $ ctxtFixityEnv c =+        withPrec c prec dir i++    updExp HsApp{} = withPrec c 10 InfixL i+    updExp RecordUpd{}+      | i == firstChild = withPrec c 11 InfixN i+    updExp HsGetField{}+      | i == firstChild = withPrec c 11 InfixN i+    updExp NegApp{} = withPrec c 6 InfixN i     updExp (HsLet _ lbs _) = addInScope neverParen $ collectLocalBinders CollNoDictBinders lbs-#else-    updExp (HsLet _ _ lbs _ _) = addInScope neverParen $ collectLocalBinders CollNoDictBinders lbs #endif+    updExp (OpApp _ _ op _) = withOpPrec op+    updExp (SectionL _ _ op) = withOpPrec op+    updExp (SectionR _ op _) = withOpPrec op     updExp _ = neverParen -    updType :: HsType GhcPs -> Context-    updType HsAppTy{}-      | i > firstChild = c { ctxtParentPrec = IsHsAppsTy }-    updType _ = neverParen-     updMatch :: Match GhcPs (LHsExpr GhcPs) -> Context     updMatch       | i == 2  -- m_pats field+#if __GLASGOW_HASKELL__ < 912       = addInScope c{ctxtParentPrec = IsLhs} . collectPatsBinders CollNoDictBinders . m_pats       | otherwise = addInScope neverParen . collectPatsBinders CollNoDictBinders . m_pats+#else+      = addInScope c{ctxtParentPrec = IsLhs} . collectPatsBinders CollNoDictBinders . unLoc . m_pats+      | otherwise+      = addInScope neverParen . collectPatsBinders CollNoDictBinders . unLoc . m_pats+#endif       where      updGRHSs :: GRHSs GhcPs (LHsExpr GhcPs) -> Context     updGRHSs = addInScope neverParen . collectLocalBinders CollNoDictBinders . grhssLocalBinds      updGRHS :: GRHS GhcPs (LHsExpr GhcPs) -> Context-#if __GLASGOW_HASKELL__ < 900-    updGRHS XGRHS{} = neverParen-#endif     updGRHS (GRHS _ gs _)         -- binders are in scope over the body (right child) only       | i > firstChild = addInScope neverParen bs@@ -128,6 +157,29 @@     updPat :: Pat GhcPs -> Context     updPat _ = neverParen +getPrec :: PprPrec -> Int+getPrec (PprPrec prec) = prec++#if __GLASGOW_HASKELL__ < 912+withPrec :: Context -> SourceText -> Int -> FixityDirection -> Int -> Context+withPrec c source prec dir i = c{ ctxtParentPrec = HasPrec fixity }+  where+    fixity = Fixity source prec d+#else+withPrec :: Context -> Int -> FixityDirection -> Int -> Context+withPrec c prec dir i = c{ ctxtParentPrec = HasPrec fixity }+  where+    fixity = Fixity prec d+#endif+    d = case dir of+      InfixL+        | i == firstChild -> InfixL+        | otherwise -> InfixN+      InfixR+        | i == firstChild -> InfixN+        | otherwise -> InfixR+      InfixN -> InfixN+ -- | Create an empty 'Context' with given 'FixityEnv', rewriter, and dependent -- rewrite generator. emptyContext :: FixityEnv -> Rewriter -> Rewriter -> Context@@ -219,7 +271,7 @@ -- Only works on unqualified RdrNames. This is fine, as we only use this to -- rename local binders. renameBinder :: RdrName -> FreeVars -> RdrName-renameBinder rdr fvs = head+renameBinder rdr fvs = headNoWarn   [ rdr'   | i <- [n..]   , let rdr' = mkVarUnqual $ mkFastString $ baseName ++ show i@@ -229,6 +281,12 @@     (ds, rest) = span isDigit $ reverse $ occNameString $ occName rdr      baseName = reverse rest++    -- We build with -Wall -Werror, and there is a warning about how `head` is+    -- partial. Using `head` is safe here because the list is infinite, so the+    -- nil case is impossible. Define our own to avoid the warning.+    headNoWarn (x:_) = x+    headNoWarn _ = error "headNoWarn: impossible!"      n :: Int     n | null ds = 1
Retrie/Debug.hs view
@@ -1,4 +1,5 @@--- Copyright (c) Facebook, Inc. and its affiliates.+-- Copyright (c) 2025 Andrew Farmer+-- Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. -- -- This source code is licensed under the MIT license found in the -- LICENSE file in the root directory of this source tree.
Retrie/Elaborate.hs view
@@ -1,4 +1,5 @@--- Copyright (c) Facebook, Inc. and its affiliates.+-- Copyright (c) 2025 Andrew Farmer+-- Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. -- -- This source code is licensed under the MIT license found in the -- LICENSE file in the root directory of this source tree.@@ -86,7 +87,7 @@       -- substitute for quantifiers in grafted template       r <- subst sub ctxt t'       -- copy appropriate annotations from old expression to template-      r0 <- addAllAnnsT e r+      r0 <- transferEntryAnnsT e r       -- add parens to template if needed       (mkM (parenify ctxt) `extM` parenifyT ctxt `extM` parenifyP ctxt) r0 
Retrie/ExactPrint.hs view
@@ -1,4 +1,5 @@--- Copyright (c) Facebook, Inc. and its affiliates.+-- Copyright (c) 2025 Andrew Farmer+-- Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. -- -- This source code is licensed under the MIT license found in the -- LICENSE file in the root directory of this source tree.@@ -8,6 +9,10 @@ {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE ViewPatterns #-}+#if __GLASGOW_HASKELL__ < 912+#else+{-# OPTIONS_GHC -Wno-orphans #-}+#endif -- | Provides consistent interface with ghc-exactprint. module Retrie.ExactPrint   ( -- * Fixity re-association@@ -29,20 +34,18 @@   , swapEntryDPT   , transferAnnsT   , transferEntryAnnsT-  , transferEntryDPT-  -- , tryTransferEntryDPT-  , transferAnchor+  , setTrailingAnns+  , trailingAnns+  , stripOuterAnns     -- * Utils   , debugDump   , debugParse-  , debug   , hasComments   , isComma     -- * Annotated AST   , module Retrie.ExactPrint.Annotated     -- * ghc-exactprint re-exports   , module Language.Haskell.GHC.ExactPrint-  -- , module Language.Haskell.GHC.ExactPrint.Annotate   , module Language.Haskell.GHC.ExactPrint.Types   , module Language.Haskell.GHC.ExactPrint.Utils   , module Language.Haskell.GHC.ExactPrint.Transform@@ -50,38 +53,73 @@  import Control.Exception import Control.Monad-import Control.Monad.State.Lazy hiding (fix)--- import Data.Function (on)+import Control.Monad.State.Lazy import Data.List (transpose)--- import Data.Maybe--- import qualified Data.Map as M import Text.Printf  import Language.Haskell.GHC.ExactPrint hiding-  (-   setEntryDP+  ( d1+#if __GLASGOW_HASKELL__ < 912+  , m1+  , mn+#endif+  , setEntryDP   , transferEntryDP   )--- import Language.Haskell.GHC.ExactPrint.ExactPrint (ExactPrint)-import Language.Haskell.GHC.ExactPrint.Utils hiding (debug)+import Language.Haskell.GHC.ExactPrint.Utils hiding+  ( rs+  ) import qualified Language.Haskell.GHC.ExactPrint.Parsers as Parsers import Language.Haskell.GHC.ExactPrint.Types   ( showGhc   )-import Language.Haskell.GHC.ExactPrint.Transform+import Language.Haskell.GHC.ExactPrint.Transform hiding+  ( d1+#if __GLASGOW_HASKELL__ < 912+  , m1+  , mn+#endif+  )  import Retrie.ExactPrint.Annotated import Retrie.Fixity import Retrie.GHC import Retrie.SYB hiding (ext1)-import Retrie.Util  import GHC.Stack-import Debug.Trace -debug :: c -> String -> c-debug c s = trace s c+#if __GLASGOW_HASKELL__ < 912+#else+import Data.Default+import Control.Applicative +instance Monoid AnnListItem where+  mempty = AnnListItem []++instance Default AnnListItem where+  def = AnnListItem []++instance Monoid (EpToken s) where+  mempty = NoEpTok+  mappend = (<>)++instance Semigroup (EpToken s) where+  _ <> _ = NoEpTok++instance Semigroup NameAnn where+  _ <> b = b -- Right biased for now++instance Monoid NameAnn where+  mempty = NameAnnTrailing []++instance (Monoid a) => Monoid (AnnList a) where+  mempty = AnnList Nothing ListNone [] mempty []++instance (Semigroup a) => Semigroup (AnnList a) where+  (AnnList a1 b1 s1 r1 t1) <> (AnnList a2 b2 s2 r2 t2) =+    AnnList (a1 <|> a2) (if b1 == ListNone then b2 else b1) (s1 <> s2) (r1 <> r2) (t1 <> t2)+#endif+ -- Fixity traversal -----------------------------------------------------------  -- | Re-associate AST using given 'FixityEnv'. (The GHC parser has no knowledge@@ -95,7 +133,11 @@  -- Should (x op1 y) op2 z be reassociated as x op1 (y op2 z)? associatesRight :: Fixity -> Fixity -> Bool+#if __GLASGOW_HASKELL__ < 912 associatesRight (Fixity _ p1 a1) (Fixity _ p2 _a2) =+#else+associatesRight (Fixity p1 a1) (Fixity p2 _a2) =+#endif   p2 > p1 || p1 == p2 && a1 == InfixR  -- We know GHC produces left-associated chains, so 'z' is never an@@ -106,33 +148,30 @@   => FixityEnv   -> LHsExpr GhcPs   -> TransformT m (LHsExpr GhcPs)-fixOneExpr env (L l2 (OpApp x2 ap1@(L l1 (OpApp x1 x op1 y)) op2 z))+fixOneExpr env (L l2 (OpApp x2 (L _ (OpApp x1 x op1 y)) op2 z))   | associatesRight (lookupOp op1 env) (lookupOp op2 env) = do-    -- lift $ liftIO $ debugPrint Loud "fixOneExpr:(l1,l2)="  [showAst (l1,l2)]-    let ap2' = L (stripComments l2) $ OpApp x2 y op2 z-    (ap1_0, ap2'_0) <- swapEntryDPT ap1 ap2'-    ap1_1 <- transferAnnsT isComma ap2'_0 ap1_0-    -- lift $ liftIO $ debugPrint Loud "fixOneExpr:recursing"  []-    rhs <- fixOneExpr env ap2'_0-    -- lift $ liftIO $ debugPrint Loud "fixOneExpr:returning"  [showAst (L l2 $ OpApp x1 x op1 rhs)]-    -- return $ L l1 $ OpApp x1 x op1 rhs+    let sp = combineSrcSpans (getLocA y) (getLocA z)+        ap2' = L (freshAnn sp) $ OpApp x2 y op2 z+    rhs <- fixOneExpr env ap2'     return $ L l2 $ OpApp x1 x op1 rhs fixOneExpr _ e = return e  fixOnePat :: Monad m => FixityEnv -> LPat GhcPs -> TransformT m (LPat GhcPs)-fixOnePat env (dLPat -> Just (L l2 (ConPat ext2 op2 (InfixCon (dLPat -> Just ap1@(L l1 (ConPat ext1 op1 (InfixCon x y)))) z))))+fixOnePat env (dLPat -> Just (L l2 (ConPat ext2 op2 (InfixCon (dLPat -> Just (L _ (ConPat ext1 op1 (InfixCon x y)))) z))))   | associatesRight (lookupOpRdrName op1 env) (lookupOpRdrName op2 env) = do-    let ap2' = L l2 (ConPat ext2 op2 (InfixCon y z))-    (ap1_0, ap2'_0) <- swapEntryDPT ap1 ap2'-    ap1_1 <- transferAnnsT isComma ap2' ap1-    rhs <- fixOnePat env (cLPat ap2'_0)-    return $ cLPat $ L l1 (ConPat ext1 op1 (InfixCon x rhs))+    let sp = combineSrcSpans (getLocA y) (getLocA z)+        ap2' = L (freshAnn sp) $ ConPat ext2 op2 (InfixCon y z)+    rhs <- fixOnePat env ap2'+    return $ L l2 $ ConPat ext1 op1 (InfixCon x rhs) fixOnePat _ e = return e --- TODO: move to ghc-exactprint-stripComments :: SrcAnn an -> SrcAnn an-stripComments (SrcSpanAnn EpAnnNotUsed l) = SrcSpanAnn EpAnnNotUsed l-stripComments (SrcSpanAnn (EpAnn anc an _) l) = SrcSpanAnn (EpAnn anc an emptyComments) l+#if __GLASGOW_HASKELL__ < 912+freshAnn :: Monoid an => SrcSpan -> SrcAnn an+freshAnn = noAnnSrcSpanDP0+#else+freshAnn :: NoAnn an => SrcSpan -> EpAnn an+freshAnn sp = EpAnn (EpaDelta sp (SameLine 0) []) noAnn emptyComments+#endif  -- Move leading whitespace from the left child of an operator application -- to the application itself. We need this so we have correct offsets when@@ -144,25 +183,6 @@   -> LocatedA a -- ^ Left child   -> TransformT m (LocatedA a, LocatedA a) fixOneEntry e x = do-  -- lift $ liftIO $ debugPrint Loud "fixOneEntry:(e,x)="  [showAst (e,x)]-  -- -- anns <- getAnnsT-  -- let-  --   zeros = SameLine 0-  --   (xdp, ard) =-  --     case M.lookup (mkAnnKey x) anns of-  --       Nothing -> (zeros, zeros)-  --       Just ann -> (annLeadingCommentEntryDelta ann, annEntryDelta ann)-  --   xr = getDeltaLine xdp-  --   xc = deltaColumn xdp-  --   actualRow = getDeltaLine ard-  --   edp =-  --     maybe zeros annLeadingCommentEntryDelta $ M.lookup (mkAnnKey e) anns-  --   er = getDeltaLine edp-  --   ec = deltaColumn edp-  -- when (actualRow == 0) $ do-  --   setEntryDPT e $ deltaPos (er, xc + ec)-  --   setEntryDPT x $ deltaPos (xr, 0)-   -- We assume that ghc-exactprint has converted all Anchor's to use their delta variants.   -- Get the dp for the x component   let xdp = entryDP x@@ -173,40 +193,44 @@   let er = getDeltaLine edp   let ec = deltaColumn edp   case xdp of-    SameLine n -> do+    SameLine _n -> do       -- lift $ liftIO $ debugPrint Loud "fixOneEntry:(xdp,edp)="  [showAst (xdp,edp)]       -- lift $ liftIO $ debugPrint Loud "fixOneEntry:(dpx,dpe)="  [showAst ((deltaPos er (xc + ec)),(deltaPos xr 0))]       -- lift $ liftIO $ debugPrint Loud "fixOneEntry:e'="  [showAst e]       -- lift $ liftIO $ debugPrint Loud "fixOneEntry:e'="  [showAst (setEntryDP e (deltaPos er (xc + ec)))]+#if __GLASGOW_HASKELL__ < 912       return ( setEntryDP e (deltaPos er (xc + ec))              , setEntryDP x (deltaPos xr 0))+#else+      -- In GHC 9.12+, setEntryDP applies the delta to the first comment if present,+      -- which can corrupt spacing. Skip adjustment when either e or x has comments+      -- directly attached to them (not in subtree), as setEntryDP will be called+      -- on these specific nodes.+      if hasComments e || hasComments x+        then return (e, x)+        else return ( setEntryDP e (deltaPos er (xc + ec))+                    , setEntryDP x (deltaPos xr 0))+#endif     _ -> return (e,x) -  -- anns <- getAnnsT-  -- let-  --   zeros = DP (0,0)-  --   (DP (xr,xc), DP (actualRow,_)) =-  --     case M.lookup (mkAnnKey x) anns of-  --       Nothing -> (zeros, zeros)-  --       Just ann -> (annLeadingCommentEntryDelta ann, annEntryDelta ann)-  --   DP (er,ec) =-  --     maybe zeros annLeadingCommentEntryDelta $ M.lookup (mkAnnKey e) anns-  -- when (actualRow == 0) $ do-  --   setEntryDPT e $ DP (er, xc + ec)-  --   setEntryDPT x $ DP (xr, 0)-  -- return e- -- TODO: move this somewhere more appropriate entryDP :: LocatedA a -> DeltaPos+#if __GLASGOW_HASKELL__ < 912 entryDP (L (SrcSpanAnn EpAnnNotUsed _) _) = SameLine 1 entryDP (L (SrcSpanAnn (EpAnn anc _ _) _) _)   = case anchor_op anc of       UnchangedAnchor -> SameLine 1       MovedAnchor dp -> dp+#else+entryDP (L (EpAnn anc _ _) _)+  = case anc of+      EpaSpan _ -> SameLine 1+      EpaDelta _ dp _ -> dp+#endif   fixOneEntryExpr :: MonadIO m => LHsExpr GhcPs -> TransformT m (LHsExpr GhcPs)-fixOneEntryExpr e@(L l (OpApp a x b c)) = do+fixOneEntryExpr e@(L _ (OpApp a x b c)) = do   -- lift $ liftIO $ debugPrint Loud "fixOneEntryExpr:(e,x)="  [showAst (e,x)]   (e',x') <- fixOneEntry e x   -- lift $ liftIO $ debugPrint Loud "fixOneEntryExpr:(e',x')="  [showAst (e',x')]@@ -216,11 +240,7 @@  fixOneEntryPat :: MonadIO m => LPat GhcPs -> TransformT m (LPat GhcPs) fixOneEntryPat pat-#if __GLASGOW_HASKELL__ < 900-  | Just p@(L l (ConPatIn a (InfixCon x b))) <- dLPat pat = do-#else-  | Just p@(L l (ConPat a b (InfixCon x c))) <- dLPat pat = do-#endif+  | Just p@(L _ (ConPat a b (InfixCon x c))) <- dLPat pat = do     (p', x') <- fixOneEntry p (dLPatUnsafe x)     return (cLPat $ (L (getLoc p') (ConPat a b (InfixCon x' c))))   | otherwise = return pat@@ -228,6 +248,7 @@ -------------------------------------------------------------------------------  +#if __GLASGOW_HASKELL__ < 912 -- Swap entryDP and prior comments between the two args swapEntryDPT   :: (Data a, Data b, Monad m, Monoid a1, Monoid a2, Typeable a1, Typeable a2)@@ -236,22 +257,14 @@   b' <- transferEntryDP a b   a' <- transferEntryDP b a   return (a',b')---- swapEntryDPT---   :: (Data a, Data b, Monad m)---   => LocatedAn a1 a -> LocatedAn a2 b -> TransformT m ()--- swapEntryDPT a b =---   modifyAnnsT $ \ anns ->---   let akey = mkAnnKey a---       bkey = mkAnnKey b---       aann = fromMaybe annNone $ M.lookup akey anns---       bann = fromMaybe annNone $ M.lookup bkey anns---   in M.insert akey---       aann { annEntryDelta = annEntryDelta bann---            , annPriorComments = annPriorComments bann } $---      M.insert bkey---       bann { annEntryDelta = annEntryDelta aann---            , annPriorComments = annPriorComments aann } anns+#else+swapEntryDPT+  :: (Monad m, Typeable t2, Typeable t1)+  => LocatedAn t1 a+  -> LocatedAn t2 b+  -> m (LocatedAn t1 a, LocatedAn t2 b)+swapEntryDPT a b = return (transferEntryDP b a, transferEntryDP a b)+#endif  ------------------------------------------------------------------------------- @@ -262,13 +275,7 @@   r <- Parsers.parseModuleFromString libdir fp str   case r of     Left msg -> do-#if __GLASGOW_HASKELL__ < 900-      fail $ show msg-#elif __GLASGOW_HASKELL__ < 904-      fail $ show $ bagToList msg-#else       fail $ showSDoc dflags $ ppr msg-#endif     Right m -> return $ unsafeMkA (makeDeltaAst m) 0  parseContent :: Parsers.LibDir -> FixityEnv -> FilePath -> String -> IO AnnotatedModule@@ -306,7 +313,6 @@   -- debugPrint Loud "parseStmt:for" [str]   res <- parseHelper libdir "parseStmt" Parsers.parseStmt str   return (setEntryDPA res (DifferentLine 1 0))-  -- return res   -- | Parse a 'HsType'.@@ -317,13 +323,7 @@   => Parsers.LibDir -> FilePath -> Parsers.Parser a -> String -> IO (Annotated a) parseHelper libdir fp parser str = join $ Parsers.withDynFlags libdir $ \dflags ->   case parser dflags fp str of-#if __GLASGOW_HASKELL__ < 900-    Left (_, msg) -> throwIO $ ErrorCall msg-#elif __GLASGOW_HASKELL__ < 904-    Left errBag -> throwIO $ ErrorCall (show $ bagToList errBag)-#else     Left msg -> throwIO $ ErrorCall (showSDoc dflags $ ppr msg)-#endif     Right x -> return $ unsafeMkA (makeDeltaAst x) 0  -- type Parser a = GHC.DynFlags -> FilePath -> String -> ParseResult a@@ -352,122 +352,109 @@ -- cloneT :: (Data a, Typeable a, Monad m) => a -> TransformT m a -- cloneT e = getAnnsT >>= flip graftT e --- The following definitions are all the same as the ones from ghc-exactprint,--- but the types are liberalized from 'Transform a' to 'TransformT m a'. transferEntryAnnsT   :: (HasCallStack, Data a, Data b, Monad m)-  => (TrailingAnn -> Bool)  -- transfer Anns matching predicate-  -> LocatedA a             -- from+  => LocatedA a             -- from   -> LocatedA b             -- to   -> TransformT m (LocatedA b)-transferEntryAnnsT p a b = do-  b' <- transferEntryDP a b-  transferAnnsT p a b'---- | 'Transform' monad version of 'transferEntryDP'-transferEntryDPT-  :: (HasCallStack, Data a, Data b, Monad m)-  => Located a -> Located b -> TransformT m ()--- transferEntryDPT a b = modifyAnnsT (transferEntryDP a b)-transferEntryDPT _a _b = error "transferEntryDPT"---- tryTransferEntryDPT---   :: (Data a, Data b, Monad m)---   => Located a -> Located b -> TransformT m ()--- tryTransferEntryDPT a b = modifyAnnsT $ \anns ->---   if M.member (mkAnnKey a) anns---     then transferEntryDP a b anns---     else anns+transferEntryAnnsT a b =+  return+    $ setTrailingAnns (trailingAnns a)+    $ pinPriorComments+    $ prependPriorComments (priorCommentsOf a)+    $ setEntryDelta (getEntryDP a) b --- This function fails if b is not in Anns, which seems dumb, since we are inserting it.--- transferEntryDP :: (HasCallStack, Data a, Data b) => Located a -> Located b -> Anns -> Anns--- transferEntryDP a b anns = setEntryDP b dp anns'---   where---     maybeAnns = do -- Maybe monad---       anA <- M.lookup (mkAnnKey a) anns---       let anB = M.findWithDefault annNone (mkAnnKey b) anns---           anB' = anB { annEntryDelta = DP (0,0) }---       return (M.insert (mkAnnKey b) anB' anns, annLeadingCommentEntryDelta anA)---     (anns',dp) = fromMaybe---                   (error $ "transferEntryDP: lookup failed: " ++ show (mkAnnKey a))---                   maybeAnns+setEntryDelta :: DeltaPos -> LocatedA a -> LocatedA a+#if __GLASGOW_HASKELL__ < 912+-- always give the delta to the first prior comment+setEntryDelta dp (L (SrcSpanAnn (EpAnn anc@(Anchor _ (MovedAnchor _)) an cs) l) x)+  | (L ca c : rest) <- priorComments cs =+      let c' = L (Anchor (anchor ca) (MovedAnchor dp)) c+      in L (SrcSpanAnn (EpAnn anc an (setPriorComments cs (c' : rest))) l) x+#endif+setEntryDelta dp x = setEntryDP x dp  addAllAnnsT+#if __GLASGOW_HASKELL__ < 912   :: (HasCallStack, Monoid an, Data a, Data b, MonadIO m, Typeable an)   => LocatedAn an a -> LocatedAn an b -> TransformT m (LocatedAn an b) addAllAnnsT a b = do   -- AZ: to start with, just transfer the entry DP from a to b   transferEntryDP a b+#else+  :: (HasCallStack, Data a, Data b, Monad m, Typeable an)+  => LocatedAn an a -> LocatedAn an b -> TransformT m (LocatedAn an b)+addAllAnnsT a b = return $ transferEntryDP a b+#endif +setTrailingAnns :: [TrailingAnn] -> LocatedA a -> LocatedA a+#if __GLASGOW_HASKELL__ < 912+setTrailingAnns [] x@(L (SrcSpanAnn EpAnnNotUsed _) _) = x+setTrailingAnns ts (L (SrcSpanAnn EpAnnNotUsed l) x) =+  L (SrcSpanAnn (EpAnn (spanAsAnchor l) (AnnListItem ts) emptyComments) l) x+setTrailingAnns ts (L (SrcSpanAnn (EpAnn anc _ cs) l) x) =+  L (SrcSpanAnn (EpAnn anc (AnnListItem ts) cs) l) x+#else+setTrailingAnns ts (L (EpAnn anc _ cs) x) = L (EpAnn anc (AnnListItem ts) cs) x+#endif --- addAllAnnsT---   :: (HasCallStack, Data a, Data b, Monad m)---   => Located a -> Located b -> TransformT m ()--- addAllAnnsT a b = modifyAnnsT (addAllAnns a b)+trailingAnns :: LocatedA a -> [TrailingAnn]+#if __GLASGOW_HASKELL__ < 912+trailingAnns (L (SrcSpanAnn (EpAnn _ (AnnListItem ts) _) _) _) = ts+trailingAnns _ = []+#else+trailingAnns (L (EpAnn _ (AnnListItem ts) _) _) = ts+#endif --- addAllAnns :: (HasCallStack, Data a, Data b) => Located a -> Located b -> Anns -> Anns--- addAllAnns a b anns =---   fromMaybe---     (error $ "addAllAnns: lookup failed: " ++ show (mkAnnKey a)---       ++ " or " ++ show (mkAnnKey b))---     $ do ann <- M.lookup (mkAnnKey a) anns---          case M.lookup (mkAnnKey b) anns of---            Just ann' -> return $ M.insert (mkAnnKey b) (ann `annAdd` ann') anns---            Nothing -> return $ M.insert (mkAnnKey b) ann anns---   where annAdd ann ann' = ann'---           { annEntryDelta = annEntryDelta ann---           , annPriorComments = ((++) `on` annPriorComments) ann ann'---           , annFollowingComments = ((++) `on` annFollowingComments) ann ann'---           , annsDP = ((++) `on` annsDP) ann ann'---           }+priorCommentsOf :: LocatedA a -> [LEpaComment]+#if __GLASGOW_HASKELL__ < 912+priorCommentsOf (L (SrcSpanAnn EpAnnNotUsed _) _) = []+priorCommentsOf (L (SrcSpanAnn (EpAnn _ _ cs) _) _) = priorComments cs+#else+priorCommentsOf (L (EpAnn _ _ cs) _) = priorComments cs+#endif -transferAnchor :: LocatedA a -> LocatedA b -> LocatedA b-transferAnchor (L (SrcSpanAnn EpAnnNotUsed l)    _) lb = setAnchorAn lb (spanAsAnchor l) emptyComments-transferAnchor (L (SrcSpanAnn (EpAnn anc _ _) _) _) lb = setAnchorAn lb anc              emptyComments+prependPriorComments :: [LEpaComment] -> LocatedA a -> LocatedA a+prependPriorComments [] x = x+#if __GLASGOW_HASKELL__ < 912+prependPriorComments new (L l x) =+  L (setCommentsSrcAnn l (EpaComments new <> epAnnComments (ann l))) x+#else+prependPriorComments new (L l x) =+  L (setCommentsEpAnn l (EpaComments new <> epAnnComments l)) x+#endif +pinPriorComments :: LocatedA a -> LocatedA a+#if __GLASGOW_HASKELL__ < 912+-- exactprint sorts prior comments by span and holds back any that+-- start after the node's anchor, pin them to the nodes anchor so order is+-- consistent across versions.+pinPriorComments (L (SrcSpanAnn (EpAnn anc an cs) l) x) =+  L (SrcSpanAnn (EpAnn anc an (setPriorComments cs (map pin (priorComments cs)))) l) x+  where+    pin (L (Anchor _ op) c) = L (Anchor (anchor anc) op) c+#endif+pinPriorComments x = x +-- | Drop anything that prints outside the node's span.+stripOuterAnns :: LocatedA a -> LocatedA a+stripOuterAnns (L an x) = L (freshAnn (locA an)) x+ isComma :: TrailingAnn -> Bool isComma (AddCommaAnn _) = True isComma _ = False -isCommentKeyword :: AnnKeywordId -> Bool--- isCommentKeyword (AnnComment _) = True-isCommentKeyword _ = False---- isCommentAnnotation :: Annotation -> Bool--- isCommentAnnotation Ann{..} =---   (not . null $ annPriorComments)---   || (not . null $ annFollowingComments)---   || any (isCommentKeyword . fst) annsDP- hasComments :: LocatedAn an a -> Bool+#if __GLASGOW_HASKELL__ < 912 hasComments (L (SrcSpanAnn EpAnnNotUsed _) _) = False-hasComments (L (SrcSpanAnn (EpAnn anc _ cs) _) _)-  = case cs of-      EpaComments [] -> False-      EpaCommentsBalanced [] [] -> False-      _ -> True---- hasComments :: (Data a, Monad m) => Located a -> TransformT m Bool--- hasComments e = do---   anns <- getAnnsT---   let b = isCommentAnnotation <$> M.lookup (mkAnnKey e) anns---   return $ fromMaybe False b---- transferAnnsT---   :: (Data a, Data b, Monad m)---   => (KeywordId -> Bool)        -- transfer Anns matching predicate---   -> Located a                  -- from---   -> Located b                  -- to---   -> TransformT m ()--- transferAnnsT p a b = modifyAnnsT f---   where---     bKey = mkAnnKey b---     f anns = fromMaybe anns $ do---       anA <- M.lookup (mkAnnKey a) anns---       anB <- M.lookup bKey anns---       let anB' = anB { annsDP = annsDP anB ++ filter (p . fst) (annsDP anA) }---       return $ M.insert bKey anB' anns+hasComments (L (SrcSpanAnn (EpAnn _ _ cs) _) _) =+#else+hasComments (L (EpAnn _ _ cs) _) =+#endif+  case cs of+    EpaComments [] -> False+    EpaCommentsBalanced [] [] -> False+    _ -> True  transferAnnsT   :: (Data a, Data b, Monad m)@@ -475,13 +462,18 @@   -> LocatedA a                 -- from   -> LocatedA b                 -- to   -> TransformT m (LocatedA b)-transferAnnsT p (L (SrcSpanAnn EpAnnNotUsed _) _) b = return b-transferAnnsT p (L (SrcSpanAnn (EpAnn anc (AnnListItem ts) cs) l) a) (L (SrcSpanAnn an lb) b) = do+#if __GLASGOW_HASKELL__ < 912+transferAnnsT _ (L (SrcSpanAnn EpAnnNotUsed _) _) b = return b+transferAnnsT p (L (SrcSpanAnn (EpAnn _ (AnnListItem ts) _) _) _) (L (SrcSpanAnn an lb) b) = do   let ps = filter p ts   let an' = case an of         EpAnnNotUsed -> EpAnn (spanAsAnchor lb) (AnnListItem ps) emptyComments         EpAnn ancb (AnnListItem tsb) csb -> EpAnn ancb (AnnListItem (tsb++ps)) csb   return (L (SrcSpanAnn an' lb) b)+#else+transferAnnsT p (L (EpAnn _ (AnnListItem ts) _) _) (L (EpAnn ancb (AnnListItem tsb) csb) b) =+  return $ L (EpAnn ancb (AnnListItem (tsb ++ filter p ts)) csb) b+#endif   -- -- | 'Transform' monad version of 'setEntryDP',
Retrie/ExactPrint/Annotated.hs view
@@ -1,14 +1,15 @@--- Copyright (c) Facebook, Inc. and its affiliates.+-- Copyright (c) 2025 Andrew Farmer+-- Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. -- -- This source code is licensed under the MIT license found in the -- LICENSE file in the root directory of this source tree. --+{-# LANGUAGE CPP #-}+{-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveFunctor #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE StandaloneDeriving #-}-{-# LANGUAGE DeriveDataTypeable #-}-{-# LANGUAGE CPP #-} module Retrie.ExactPrint.Annotated   ( -- * Annotated     Annotated@@ -36,7 +37,7 @@   , unsafeMkA   ) where -import Control.Monad.State.Lazy hiding (fix)+import Control.Monad.State.Lazy import Data.Default as D  import Data.Functor.Identity@@ -61,11 +62,7 @@ type AnnotatedHsType = Annotated (LHsType GhcPs) type AnnotatedImport = Annotated (LImportDecl GhcPs) type AnnotatedImports = Annotated [LImportDecl GhcPs]-#if __GLASGOW_HASKELL__ >= 906 type AnnotatedModule = Annotated (Located (HsModule GhcPs))-#else-type AnnotatedModule = Annotated (Located HsModule)-#endif type AnnotatedPat = Annotated (LPat GhcPs) type AnnotatedStmt = Annotated (LStmt GhcPs (LHsExpr GhcPs)) @@ -153,8 +150,12 @@     nil :: Annotated ()     nil = mempty +#if __GLASGOW_HASKELL__ < 912 setEntryDPA :: (Default an)             => Annotated (LocatedAn an ast) -> DeltaPos -> Annotated (LocatedAn an ast)+#else+setEntryDPA :: Annotated (LocatedAn an ast) -> DeltaPos -> Annotated (LocatedAn an ast)+#endif setEntryDPA (Annotated ast s) dp = Annotated (setEntryDP ast dp) s  -- | Exactprint an 'Annotated' thing.
Retrie/Expr.hs view
@@ -1,9 +1,11 @@--- Copyright (c) Facebook, Inc. and its affiliates.+-- Copyright (c) 2025 Andrew Farmer+-- Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. -- -- This source code is licensed under the MIT license found in the -- LICENSE file in the root directory of this source tree. -- {-# LANGUAGE CPP #-}+{-# LANGUAGE OverloadedLists #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE TupleSections #-}@@ -21,6 +23,7 @@   , mkLoc   , mkLocA   , mkLocatedHsVar+  , mkParen   , mkVarPat   , mkTyVar   , parenify@@ -37,33 +40,20 @@  import Control.Monad import Control.Monad.State.Lazy-import Data.Functor.Identity--- import qualified Data.Map as M-import Data.Maybe--- import Data.Void -import Retrie.AlphaEnv import Retrie.ExactPrint import Retrie.Fixity import Retrie.GHC import Retrie.SYB import Retrie.Types-import Retrie.Util  -------------------------------------------------------------------------------  mkLocatedHsVar :: Monad m => LocatedN RdrName -> TransformT m (LHsExpr GhcPs)-mkLocatedHsVar ln@(L l n) = do-  -- This special casing for [] is gross, but this is apparently how the-  -- annotations work.-  -- let anns =-  --       case occNameString (occName (unLoc v)) of-  --         "[]" -> [(G AnnOpenS, DP (0,0)), (G AnnCloseS, DP (0,0))]-  --         _    -> [(G AnnVal, DP (0,0))]-  -- r <- setAnnsFor v anns-  -- return (L (moveAnchor l)  (HsVar noExtField n))+mkLocatedHsVar (L l n) = do   mkLocA (SameLine 0)  (HsVar noExtField (L (setMoveAnchor (SameLine 0) l) n)) +#if __GLASGOW_HASKELL__ < 912 -- TODO: move to ghc-exactprint setMoveAnchor :: (Monoid an) => DeltaPos -> SrcAnn an -> SrcAnn an setMoveAnchor dp (SrcSpanAnn EpAnnNotUsed l)@@ -74,7 +64,19 @@ -- TODO: move to ghc-exactprint dpAnchor :: SrcSpan -> DeltaPos -> Anchor dpAnchor l dp = Anchor (realSrcSpan l) (MovedAnchor dp)+#else+-- TODO: move to ghc-exactprint+setMoveAnchor :: (Monoid an) => DeltaPos -> EpAnn an -> EpAnn an+setMoveAnchor dp (EpAnn (EpaSpan l) an cs)+  = EpAnn (dpAnchor l dp) an cs+setMoveAnchor dp (EpAnn (EpaDelta l _ _) an cs)+  = EpAnn (dpAnchor l dp) an cs +-- TODO: move to ghc-exactprint+dpAnchor :: SrcSpan -> DeltaPos -> EpaLocation+dpAnchor l dp = EpaDelta l dp []+#endif+ -------------------------------------------------------------------------------  -- setAnnsFor :: (Data e, Monad m)@@ -89,6 +91,7 @@ mkLoc e = do   L <$> uniqueSrcSpanT <*> pure e +#if __GLASGOW_HASKELL__ < 912 -- ++AZ++:TODO: move to ghc-exactprint mkLocA :: (Data e, Monad m, Monoid an)   => DeltaPos -> e -> TransformT m (LocatedAn an e)@@ -112,9 +115,35 @@ mkAnchor dp = do   l <- uniqueSrcSpanT   return (Anchor (realSrcSpan l) (MovedAnchor dp))+#else+-- ++AZ++:TODO: move to ghc-exactprint+mkLocA :: (Data e, Monad m, Monoid an)+  => DeltaPos -> e -> TransformT m (LocatedAn an e)+mkLocA dp e = mkLocAA dp mempty e +-- ++AZ++:TODO: move to ghc-exactprint+mkLocAA :: (Data e, Monad m) => DeltaPos -> an -> e -> TransformT m (LocatedAn an e)+mkLocAA dp an e = do+  l <- uniqueSrcSpanT+  let anc = EpaDelta l dp []+  return (L (EpAnn anc an emptyComments) e)+++-- ++AZ++:TODO: move to ghc-exactprint+mkEpAnn :: Monad m => DeltaPos -> an -> TransformT m (EpAnn an)+mkEpAnn dp an = do+  anc <- mkAnchor dp+  return $ EpAnn anc an emptyComments++mkAnchor :: Monad m => DeltaPos -> TransformT m (EpaLocation)+mkAnchor dp = do+  l <- uniqueSrcSpanT+  return (EpaDelta l dp [])+#endif+ ------------------------------------------------------------------------------- +#if __GLASGOW_HASKELL__ < 912 mkLams   :: [LPat GhcPs]   -> LHsExpr GhcPs@@ -127,57 +156,102 @@     ga = GrhsAnn Nothing (AddEpAnn AnnRarrow (EpaDelta (SameLine 1) []))     ang = EpAnn ancg ga emptyComments     anm = EpAnn ancm [(AddEpAnn AnnLam (EpaDelta (SameLine 0) []))] emptyComments-    L l (Match x ctxt pats (GRHSs cs grhs binds)) = mkMatch LambdaExpr vs e emptyLocalBinds+    L l (Match _ ctxt pats (GRHSs cs grhs binds)) = mkMatch LambdaExpr vs e emptyLocalBinds     grhs' = case grhs of-      [L lg (GRHS an guards rhs)] -> [L lg (GRHS ang guards rhs)]+      [L lg (GRHS _ guards rhs)] -> [L lg (GRHS ang guards rhs)]       _ -> fail "mkLams: lambda expression can only have a single grhs!"   matches <- mkLocA (SameLine 0) [L l (Match anm ctxt pats (GRHSs cs grhs' binds))]   let-    mg = #if __GLASGOW_HASKELL__ < 908-      mkMatchGroup Generated matches+    mg = mkMatchGroup Generated matches #else-      mkMatchGroup (Generated SkipPmc) matches+    mg = mkMatchGroup (Generated SkipPmc) matches #endif   mkLocA (SameLine 1) $ HsLam noExtField mg+#else+mkLams+  :: [LPat GhcPs]+  -> LHsExpr GhcPs+  -> TransformT IO (LHsExpr GhcPs)+mkLams [] e = return e+mkLams (p:ps) e = do+  ancg <- mkAnchor (SameLine 1)+  ancm <- mkAnchor (SameLine 0)+  ancGrhs <- mkAnchor (SameLine 0)+  let+    rarrow = EpUniTok ancg NormalSyntax+    ga = GrhsAnn Nothing (Right rarrow)+    anGrhs = EpAnn ancGrhs ga emptyComments+    +    lamTok = EpTok ancm+    lamAnn = EpAnnLam lamTok Nothing +    -- Ensure space after lambda+    vs' = setEntryDP p (SameLine 1) : ps+    +    L l (Match _ ctxt pats (GRHSs cs grhs binds)) = mkMatch (LamAlt LamSingle) (L (EpaSpan noSrcSpan) vs') e emptyLocalBinds+    grhs' = case grhs of+      [L lg (GRHS _ guards rhs)] -> [L lg (GRHS anGrhs guards rhs)]+      _ -> error "mkLams: lambda expression can only have a single grhs!"+  matches <- mkLocA (SameLine 0) [L l (Match noExtField ctxt pats (GRHSs cs grhs' binds))]+  let+    mg = mkMatchGroup (Generated OtherExpansion SkipPmc) matches+  mkLocA (SameLine 1) $ HsLam lamAnn LamSingle mg+#endif+ mkLet :: Monad m => HsLocalBinds GhcPs -> LHsExpr GhcPs -> TransformT m (LHsExpr GhcPs) mkLet EmptyLocalBinds{} e = return e mkLet lbs e = do-#if __GLASGOW_HASKELL__ < 904-  an <- mkEpAnn (DifferentLine 1 5)-                (AnnsLet {-                   alLet = EpaDelta (SameLine 0) [],-                   alIn = EpaDelta (DifferentLine 1 1) []-                 })-  le <- mkLocA (SameLine 1) $ HsLet an lbs e-  return le-#else-  an <- mkEpAnn (DifferentLine 1 5) NoEpAnns+#if __GLASGOW_HASKELL__ < 912+  an <- mkEpAnn (SameLine 0) NoEpAnns   let tokLet = L (TokenLoc (EpaDelta (SameLine 0) [])) HsTok       tokIn = L (TokenLoc (EpaDelta (DifferentLine 1 1) [])) HsTok   le <- mkLocA (SameLine 1) $ HsLet an tokLet lbs tokIn e-  return le+#else+  letTokLoc <- mkAnchor (SameLine 0)+  inTokLoc <- mkAnchor (DifferentLine 1 1)+  let tokLet = EpTok letTokLoc+      tokIn = EpTok inTokLoc+  le <- mkLocA (SameLine 1) $ HsLet (tokLet, tokIn) lbs e #endif+  transferBinds le +transferBinds :: Monad m => LHsExpr GhcPs -> TransformT m (LHsExpr GhcPs)+#if __GLASGOW_HASKELL__ < 912+transferBinds le = hsDecls le >>= replaceDecls le+#else+transferBinds le = return $ replaceDecls le (hsDecls le)+#endif+ mkApps :: MonadIO m => LHsExpr GhcPs -> [LHsExpr GhcPs] -> TransformT m (LHsExpr GhcPs) mkApps e []     = return e mkApps f (a:as) = do   -- lift $ liftIO $ debugPrint Loud "mkApps:f="  [showAst f]-  f' <- mkLocA (SameLine 0) (HsApp noAnn f a)+  let a' = setEntryDP a (SameLine 1)+#if __GLASGOW_HASKELL__ < 912+  f' <- mkLocA (SameLine 0) (HsApp noAnn f a')+#else+  f' <- mkLocA (SameLine 0) (HsApp noExtField f a')+#endif   mkApps f' as  -- GHC never generates HsAppTy in the parser, using HsAppsTy to keep a list -- of types. mkHsAppsTy :: Monad m => [LHsType GhcPs] -> TransformT m (LHsType GhcPs) mkHsAppsTy [] = error "mkHsAppsTy: empty list"-mkHsAppsTy (t:ts) = foldM (\t1 t2 -> mkLocA (SameLine 1) (HsAppTy noExtField t1 t2)) t ts+mkHsAppsTy (t:ts) = do+  let t' = setEntryDP t (SameLine 0)+  foldM (\t1 t2 -> mkLocA (SameLine 1) (HsAppTy noExtField t1 t2)) t' ts  mkTyVar :: Monad m => LocatedN RdrName -> TransformT m (LHsType GhcPs) mkTyVar nm = do+#if __GLASGOW_HASKELL__ < 912   tv <- mkLocA (SameLine 1) (HsTyVar noAnn NotPromoted nm)+#else+  tv <- mkLocA (SameLine 1) (HsTyVar NoEpTok NotPromoted nm)+#endif   -- _ <- setAnnsFor nm [(G AnnVal, DP (0,0))]-  (tv', nm') <- swapEntryDPT tv nm+  (tv', _) <- swapEntryDPT tv nm   return tv'  mkVarPat :: Monad m => LocatedN RdrName -> TransformT m (LPat GhcPs)@@ -192,7 +266,11 @@   -- -> HsConDetails Void (LocatedN RdrName) [RecordPatSynField GhcPs]   -> TransformT m (LPat GhcPs) mkConPatIn patName params = do+#if __GLASGOW_HASKELL__ < 912   p <- mkLocA (SameLine 0) $ ConPat noAnn patName params+#else+  p <- mkLocA (SameLine 0) $ ConPat (Nothing, Nothing) patName params+#endif   -- setEntryDPT p (DP (0,0))   return p @@ -221,49 +299,48 @@ wildSupply :: [RdrName] -> [RdrName] wildSupply used = wildSupplyP (`notElem` used) -wildSupplyAlphaEnv :: AlphaEnv -> [RdrName]-wildSupplyAlphaEnv env = wildSupplyP (\ nm -> isNothing (lookupAlphaEnv nm env))- wildSupplyP :: (RdrName -> Bool) -> [RdrName] wildSupplyP p =   [ r | i <- [0..]       , let r = mkVarUnqual (mkFastString ('w' : show (i :: Int)))       , p r ] --- patToExprA :: AlphaEnv -> AnnotatedPat -> AnnotatedHsExpr--- patToExprA env pat = runIdentity $ transformA pat $ \ p ->---   fst <$> runStateT (patToExpr $ cLPat p) (wildSupplyAlphaEnv env, [])- patToExpr :: MonadIO m => LPat GhcPs -> PatQ m (LHsExpr GhcPs) patToExpr orig = case dLPat orig of   Nothing -> error "patToExpr: called on unlocated Pat!"   Just lp@(L _ p) -> do     e <- go p+#if __GLASGOW_HASKELL__ < 912     lift $ transferEntryDP lp e+#else+    return $ transferEntryDP lp e+#endif   where     -- go :: Pat GhcPs -> PatQ m (LHsExpr GhcPs)     go WildPat{} = do       w <- newWildVar       v <- lift $ mkLocA (SameLine 1) w       lift $ mkLocatedHsVar v-#if __GLASGOW_HASKELL__ < 900-    go XPat{} = error "patToExpr XPat"-    go CoPat{} = error "patToExpr CoPat"-    go (ConPatIn con ds) = conPatHelper con ds-    go ConPatOut{} = error "patToExpr ConPatOut" -- only exists post-tc-#else     go (ConPat _ con ds) = conPatHelper con ds-#endif     go (LazyPat _ pat) = patToExpr pat     go (BangPat _ pat) = patToExpr pat     go (ListPat _ ps) = do       ps' <- mapM patToExpr ps       lift $ do+#if __GLASGOW_HASKELL__ < 912         an <- mkEpAnn (SameLine 1)                       (AnnList Nothing (Just (AddEpAnn AnnOpenS d0)) (Just (AddEpAnn AnnCloseS d0)) [] [])+#else+        anc1 <- mkAnchor (SameLine 0)+        anc2 <- mkAnchor (SameLine 0)+        let open = EpTok anc1+            close = EpTok anc2+            an = AnnList Nothing (ListSquare open close) [] () []+#endif         el <- mkLocA (SameLine 1) $ ExplicitList an ps'         -- setAnnsFor el [(G AnnOpenS, DP (0,0)), (G AnnCloseS, DP (0,0))]         return el+#if __GLASGOW_HASKELL__ < 912     go (LitPat _ lit) = lift $ do       -- lit' <- cloneT lit       mkLocA (SameLine 1) $ HsLit noAnn lit@@ -273,22 +350,42 @@       negE <- maybe (return e) (mkLocA (SameLine 0) . NegApp noAnn e) mbNeg       -- addAllAnnsT llit negE       return negE-#if __GLASGOW_HASKELL__ < 904-    go (ParPat an p') = do-      p <- patToExpr p'-      lift $ mkLocA (SameLine 1) (HsPar an p)-#else     go (ParPat an _ p' _) = do       p <- patToExpr p'       let tokLP = L (TokenLoc (EpaDelta (SameLine 0) [])) HsTok           tokRP = L (TokenLoc (EpaDelta (SameLine 0) [])) HsTok       lift $ mkLocA (SameLine 1) (HsPar an tokLP p tokRP)+#else+    go (LitPat _ lit) = lift $ do+      -- lit' <- cloneT lit+      mkLocA (SameLine 1) $ HsLit noExtField lit+    go (NPat _ llit mbNeg _) = lift $ do+      -- L _ lit <- cloneT llit+      e <- mkLocA (SameLine 1) $ HsOverLit noExtField (unLoc llit)+      case mbNeg of+        Nothing -> return e+        Just _ -> do+          anc <- mkAnchor (SameLine 0)+          let minusTok = EpTok anc+          mkLocA (SameLine 0) (NegApp minusTok e noSyntaxExpr)+      -- addAllAnnsT llit negE+    go (ParPat _ p') = do+      p <- patToExpr p'+      anc1 <- lift $ mkAnchor (SameLine 0)+      anc2 <- lift $ mkAnchor (SameLine 0)+      let tokLP = EpTok anc1+          tokRP = EpTok anc2+      lift $ mkLocA (SameLine 1) (HsPar (tokLP, tokRP) p) #endif     go SigPat{} = error "patToExpr SigPat"     go (TuplePat an ps boxity) = do       es <- forM ps $ \pat -> do         e <- patToExpr pat+#if __GLASGOW_HASKELL__ < 912         return $ Present noAnn e+#else+        return $ Present noExtField e+#endif       lift $ mkLocA (SameLine 1) $ ExplicitTuple an es boxity     go (VarPat _ i) = lift $ mkLocatedHsVar i     go AsPat{} = error "patToExpr AsPat"@@ -296,6 +393,12 @@     go SplicePat{} = error "patToExpr SplicePat"     go SumPat{} = error "patToExpr SumPat"     go ViewPat{} = error "patToExpr ViewPat"+#if __GLASGOW_HASKELL__ < 912+#else+    go OrPat{} = error "patToExpr OrPat"+    go EmbTyPat{} = error "patToExpr EmbTyPat"+    go InvisPat{} = error "patToExpr InvisPat"+#endif  conPatHelper :: MonadIO m              => LocatedN RdrName@@ -303,13 +406,22 @@              -> PatQ m (LHsExpr GhcPs) conPatHelper con (InfixCon x y) =   lift . mkLocA (SameLine 1)+#if __GLASGOW_HASKELL__ < 912                =<< OpApp <$> pure noAnn+#else+               =<< OpApp <$> pure noExtField+#endif                          <*> patToExpr x                          <*> lift (mkLocatedHsVar con)                          <*> patToExpr y-conPatHelper con (PrefixCon tyargs xs) = do+#if __GLASGOW_HASKELL__ < 914+-- TODO(xich): Properly handle tyargs here!+conPatHelper con (PrefixCon _tyargs xs) = do+#else+conPatHelper con (PrefixCon xs) = do+#endif   f <- lift $ mkLocatedHsVar con-  as <- mapM patToExpr xs+  as <- mapM patToExpr $ dropInvisPats xs   -- lift $ lift $ liftIO $ debugPrint Loud "conPatHelper:f="  [showAst f]   lift $ mkApps f as conPatHelper _ _ = error "conPatHelper RecCon"@@ -319,15 +431,14 @@ grhsToExpr :: LGRHS GhcPs (LHsExpr GhcPs) -> LHsExpr GhcPs grhsToExpr (L _ (GRHS _ [] e)) = e grhsToExpr (L _ (GRHS _ (_:_) e)) = e -- not sure about this-grhsToExpr _ = error "grhsToExpr"  -------------------------------------------------------------------------------  precedence :: FixityEnv -> HsExpr GhcPs -> Maybe Fixity-#if __GLASGOW_HASKELL__ < 908-precedence _        (HsApp {})       = Just $ Fixity (SourceText "HsApp") 10 InfixL+#if __GLASGOW_HASKELL__ < 912+precedence _        (HsApp {})       = Just $ Fixity NoSourceText 10 InfixL #else-precedence _        (HsApp {})       = Just $ Fixity (SourceText (fsLit "HsApp")) 10 InfixL+precedence _        (HsApp {})       = Just $ Fixity 10 InfixL #endif precedence fixities (OpApp _ _ op _) = Just $ lookupOp op fixities precedence _        _                = Nothing@@ -335,75 +446,89 @@ parenify   :: Monad m => Context -> LHsExpr GhcPs -> TransformT m (LHsExpr GhcPs) parenify Context{..} le@(L _ e)-#if __GLASGOW_HASKELL__ < 904   | needed ctxtParentPrec (precedence ctxtFixityEnv e) && needsParens e =-    mkParen' (getEntryDP le) (\an -> HsPar an (setEntryDP le (SameLine 0)))-#else-  | needed ctxtParentPrec (precedence ctxtFixityEnv e) && needsParens e = do-    let tokLP = L (TokenLoc (EpaDelta (SameLine 0) [])) HsTok-        tokRP = L (TokenLoc (EpaDelta (SameLine 0) [])) HsTok-     in mkParen' (getEntryDP le) (\an -> HsPar an tokLP (setEntryDP le (SameLine 0)) tokRP)-#endif+    mkParen le   | otherwise = return le   where            {- parent -}               {- child -}+#if __GLASGOW_HASKELL__ < 912     needed (HasPrec (Fixity _ p1 d1)) (Just (Fixity _ p2 d2)) =+#else+    needed (HasPrec (Fixity p1 d1)) (Just (Fixity p2 d2)) =+#endif       p1 > p2 || (p1 == p2 && (d1 /= d2 || d2 == InfixN))     needed NeverParen _ = False     needed _ Nothing = True     needed _ _ = False +-- | Wrap in parentheses.+mkParen :: Monad m => LHsExpr GhcPs -> TransformT m (LHsExpr GhcPs)+mkParen le = do+  let inner = setTrailingAnns [] (setEntryDP le (SameLine 0))+#if __GLASGOW_HASKELL__ < 912+  let tokLP = L (TokenLoc (EpaDelta (SameLine 0) [])) HsTok+      tokRP = L (TokenLoc (EpaDelta (SameLine 0) [])) HsTok+  p <- mkLocA (getEntryDP le) (HsPar noAnn tokLP inner tokRP)+#else+  anc1 <- mkAnchor (SameLine 0)+  anc2 <- mkAnchor (SameLine 0)+  let tokLP = EpTok anc1+      tokRP = EpTok anc2+  p <- mkParen' (getEntryDP le) (\_ -> HsPar (tokLP, tokRP) inner)+#endif+  transferAnnsT (const True) le p+ getUnparened :: Data k => k -> k getUnparened = mkT unparen `extT` unparenT `extT` unparenP  -- TODO: what about comments? unparen :: LHsExpr GhcPs -> LHsExpr GhcPs-#if __GLASGOW_HASKELL__ < 904-unparen (L _ (HsPar _ e)) = e+unparen expr = case expr of+#if __GLASGOW_HASKELL__ < 912+  L _ (HsPar _ _ e _) #else-unparen (L _ (HsPar _ _ e _)) = e+  L _ (HsPar _ e) #endif-unparen e = e+    -- see Note [Sections in HsSyn] in GHC.Hs.Expr+    | L _ SectionL{} <- e -> expr+    | L _ SectionR{} <- e -> expr+    | otherwise -> e+  _ -> expr  -- | hsExprNeedsParens is not always up-to-date, so this allows us to override needsParens :: HsExpr GhcPs -> Bool needsParens = hsExprNeedsParens (PprPrec 10) -mkParen :: (Data x, Monad m, Monoid an, Typeable an)-  => (LocatedAn an x -> x) -> LocatedAn an x -> TransformT m (LocatedAn an x)-mkParen k e = do-  pe <- mkLocA (SameLine 1) (k e)-  -- _ <- setAnnsFor pe [(G AnnOpenP, DP (0,0)), (G AnnCloseP, DP (0,0))]-  (e0,pe0) <- swapEntryDPT e pe-  return pe0--#if __GLASGOW_HASKELL__ < 904-mkParen' :: (Data x, Monad m, Monoid an)-         => DeltaPos -> (EpAnn AnnParen -> x) -> TransformT m (LocatedAn an x)-mkParen' dp k = do-  let an = AnnParen AnnParens d0 d0-  l <- uniqueSrcSpanT-  let anc = Anchor (realSrcSpan l) (MovedAnchor (SameLine 0))-  pe <- mkLocA dp (k (EpAnn anc an emptyComments))-  return pe+#if __GLASGOW_HASKELL__ < 912 #else mkParen' :: (Data x, Monad m, Monoid an)-         => DeltaPos -> (EpAnn NoEpAnns -> x) -> TransformT m (LocatedAn an x)+         => DeltaPos -> (EpAnn AnnListItem -> x) -> TransformT m (LocatedAn an x) mkParen' dp k = do-  let an = NoEpAnns+  let an = AnnListItem []   l <- uniqueSrcSpanT-  let anc = Anchor (realSrcSpan l) (MovedAnchor (SameLine 0))+  let anc = EpaDelta l dp []   pe <- mkLocA dp (k (EpAnn anc an emptyComments))   return pe+#endif +#if __GLASGOW_HASKELL__ < 912 mkParenTy :: (Data x, Monad m, Monoid an)          => DeltaPos -> (EpAnn AnnParen -> x) -> TransformT m (LocatedAn an x) mkParenTy dp k = do-  let an = AnnParen AnnParens d0 d0+  let an = AnnParen AnnParens (EpaDelta (SameLine 0) []) (EpaDelta (SameLine 0) [])   l <- uniqueSrcSpanT   let anc = Anchor (realSrcSpan l) (MovedAnchor (SameLine 0))   pe <- mkLocA dp (k (EpAnn anc an emptyComments))   return pe+#else+mkParenTy :: (Data x, Monad m, Monoid an)+         => DeltaPos -> (EpAnn AnnListItem -> x) -> TransformT m (LocatedAn an x)+mkParenTy dp k = do+  let an = AnnListItem []+  l <- uniqueSrcSpanT+  let anc = EpaDelta l dp []+  pe <- mkLocA dp (k (EpAnn anc an emptyComments))+  return pe #endif  -- This explicitly operates on 'Located (Pat GhcPs)' instead of 'LPat GhcPs'@@ -413,17 +538,27 @@   => Context   -> LPat GhcPs   -> TransformT m (LPat GhcPs)+#if __GLASGOW_HASKELL__ < 912 parenifyP Context{..} p@(L _ pat)   | IsLhs <- ctxtParentPrec-  , needed pat =-#if __GLASGOW_HASKELL__ < 904-    mkParen' (getEntryDP p) (\an -> ParPat an (setEntryDP p (SameLine 0)))-#else+  , needed pat = do     let tokLP = L (TokenLoc (EpaDelta (SameLine 0) [])) HsTok         tokRP = L (TokenLoc (EpaDelta (SameLine 0) [])) HsTok-     in mkParen' (getEntryDP p) (\an -> ParPat an tokLP (setEntryDP p (SameLine 0)) tokRP)-#endif+    pe <- mkLocA (getEntryDP p) (ParPat noAnn tokLP inner tokRP)+    transferAnnsT (const True) p pe   | otherwise = return p+#else+parenifyP Context{..} p@(L _ pat)+  | IsLhs <- ctxtParentPrec+  , needed pat = do+    anc1 <- mkAnchor (SameLine 0)+    anc2 <- mkAnchor (SameLine 0)+    let tokLP = EpTok anc1+        tokRP = EpTok anc2+    pe <- mkParen' (getEntryDP p) (\_ -> ParPat (tokLP, tokRP) inner)+    transferAnnsT (const True) p pe+  | otherwise = return p+#endif   where     needed BangPat{}                          = False     needed LazyPat{}                          = False@@ -434,44 +569,62 @@     needed TuplePat{}                         = False     needed VarPat{}                           = False     needed WildPat{}                          = False-#if __GLASGOW_HASKELL__ < 900-    needed (ConPatIn _ (PrefixCon []))        = False-    needed ConPatOut{pat_args = PrefixCon []} = False-#else+#if __GLASGOW_HASKELL__ < 914     needed (ConPat _ _ (PrefixCon _ []))      = False+#else+    needed (ConPat _ _ (PrefixCon []))        = False #endif     needed _                                  = True+    inner = setTrailingAnns [] (setEntryDP p (SameLine 0))  parenifyT   :: Monad m => Context -> LHsType GhcPs -> TransformT m (LHsType GhcPs)+#if __GLASGOW_HASKELL__ < 912 parenifyT Context{..} lty@(L _ ty)-  | needed ty =-#if __GLASGOW_HASKELL__ < 904-      mkParen' (getEntryDP lty) (\an -> HsParTy an (setEntryDP lty (SameLine 0)))+  | needed ty = do+      p <- mkParenTy (getEntryDP lty) (\an -> HsParTy an inner)+      transferAnnsT (const True) lty p+  | otherwise = return lty+  where+    needed t = case ctxtParentPrec of+      HasPrec (Fixity _ prec InfixN) -> hsTypeNeedsParens (PprPrec prec) t+      HasPrec (Fixity _ prec _) -> hsTypeNeedsParens (PprPrec $ prec - 1) t+      IsLhs -> False+      NeverParen -> False #else-      mkParenTy (getEntryDP lty) (\an -> HsParTy an (setEntryDP lty (SameLine 0)))-#endif+parenifyT Context{..} lty@(L _ ty)+  | needed ty = do+      anc1 <- mkAnchor (SameLine 0)+      anc2 <- mkAnchor (SameLine 0)+      let tokLP = EpTok anc1+          tokRP = EpTok anc2+      p <- mkParenTy (getEntryDP lty) (\_ -> HsParTy (tokLP, tokRP) inner)+      transferAnnsT (const True) lty p   | otherwise = return lty   where-    needed HsAppTy{}-      | IsHsAppsTy <- ctxtParentPrec = True-      | otherwise = False-    needed t = hsTypeNeedsParens (PprPrec 10) t+    needed t = case ctxtParentPrec of+      HasPrec (Fixity prec InfixN) -> hsTypeNeedsParens (PprPrec prec) t+      HasPrec (Fixity prec _) -> hsTypeNeedsParens (PprPrec $ prec - 1) t+      IsLhs -> False+      NeverParen -> False+#endif+    inner = setTrailingAnns [] (setEntryDP lty (SameLine 0))  unparenT :: LHsType GhcPs -> LHsType GhcPs unparenT (L _ (HsParTy _ ty)) = ty unparenT ty = ty  unparenP :: LPat GhcPs -> LPat GhcPs-#if __GLASGOW_HASKELL__ < 904-unparenP (L _ (ParPat _ p)) = p-#else+#if __GLASGOW_HASKELL__ < 912 unparenP (L _ (ParPat _ _ p _)) = p+#else+unparenP (L _ (ParPat _ p)) = p #endif unparenP p = p  -------------------------------------------------------------------- +#if __GLASGOW_HASKELL__ < 914 bitraverseHsConDetails   :: Applicative m   => ([tyarg] -> m [tyarg'])@@ -485,3 +638,17 @@   RecCon <$> recf r bitraverseHsConDetails _ argf _ (InfixCon a1 a2) =   InfixCon <$> argf a1 <*> argf a2+#else+bitraverseHsConDetails+  :: Applicative m+  => (arg -> m arg')+  -> (rec -> m rec')+  -> HsConDetails arg rec+  -> m (HsConDetails arg' rec')+bitraverseHsConDetails argf _ (PrefixCon args) =+  PrefixCon <$> (argf `traverse` args)+bitraverseHsConDetails _ recf (RecCon r) =+  RecCon <$> recf r+bitraverseHsConDetails argf _ (InfixCon a1 a2) =+  InfixCon <$> argf a1 <*> argf a2+#endif
Retrie/Fixity.hs view
@@ -1,8 +1,10 @@--- Copyright (c) Facebook, Inc. and its affiliates.+-- Copyright (c) 2025 Andrew Farmer+-- Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. -- -- This source code is licensed under the MIT license found in the -- LICENSE file in the root directory of this source tree. --+{-# LANGUAGE CPP #-} {-# LANGUAGE RankNTypes #-} module Retrie.Fixity   ( FixityEnv@@ -45,7 +47,11 @@ ppFixityEnv :: FixityEnv -> String ppFixityEnv = unlines . map ppFixity . nonDetEltsUFM . unFixityEnv   where+#if __GLASGOW_HASKELL__ < 912     ppFixity (fs, Fixity _ p d) = unwords+#else+    ppFixity (fs, Fixity p d) = unwords+#endif       [ case d of           InfixN -> "infix"           InfixL -> "infixl"
Retrie/FreeVars.hs view
@@ -1,4 +1,5 @@--- Copyright (c) Facebook, Inc. and its affiliates.+-- Copyright (c) 2025 Andrew Farmer+-- Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. -- -- This source code is licensed under the MIT license found in the -- LICENSE file in the root directory of this source tree.@@ -25,11 +26,10 @@ emptyFVs = FreeVars emptyUniqSet  instance Semigroup FreeVars where-  (<>) = mappend+  (FreeVars s1) <> (FreeVars s2) = FreeVars $ s1 <> s2  instance Monoid FreeVars where   mempty = emptyFVs-  mappend (FreeVars s1) (FreeVars s2) = FreeVars $ s1 <> s2  instance Show FreeVars where   show (FreeVars m) = show (nonDetEltsUniqSet m)
Retrie/GHC.hs view
@@ -1,4 +1,5 @@--- Copyright (c) Facebook, Inc. and its affiliates.+-- Copyright (c) 2025 Andrew Farmer+-- Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. -- -- This source code is licensed under the MIT license found in the -- LICENSE file in the root directory of this source tree.@@ -53,14 +54,14 @@ import GHC.Types.Unique import GHC.Types.Unique.FM import GHC.Types.Unique.Set-#if __GLASGOW_HASKELL__ >= 906 import Language.Haskell.Syntax.Basic as GHC.Unit.Module.Name-#else-import GHC.Unit.Module.Name-#endif import GHC.Utils.Outputable (Outputable (ppr))  import Data.Bifunctor (second)+#if __GLASGOW_HASKELL__ < 914+#else+import qualified Data.List.NonEmpty as NE+#endif import Data.Maybe  cLPat :: LPat (GhcPass p) -> LPat (GhcPass p)@@ -74,10 +75,11 @@ dLPatUnsafe :: LPat (GhcPass p) -> LPat (GhcPass p) dLPatUnsafe = id -#if __GLASGOW_HASKELL__ == 808-stripSrcSpanPat :: LPat (GhcPass p) -> Pat (GhcPass p)-stripSrcSpanPat (XPat (L _  p)) = stripSrcSpanPat p-stripSrcSpanPat p = p+getMatchPats :: Match GhcPs (LHsExpr GhcPs) -> [LPat GhcPs]+#if __GLASGOW_HASKELL__ < 912+getMatchPats = m_pats+#else+getMatchPats = unLoc . m_pats #endif  rdrFS :: RdrName -> FastString@@ -87,20 +89,42 @@ fsDot :: FastString fsDot = mkFastString "." +#if __GLASGOW_HASKELL__ < 914 varRdrName :: HsExpr p -> Maybe (LIdP p)+#else+varRdrName :: HsExpr p -> Maybe (LIdOccP p)+#endif varRdrName (HsVar _ n) = Just n varRdrName _ = Nothing +#if __GLASGOW_HASKELL__ < 914 tyvarRdrName :: HsType p -> Maybe (LIdP p)+#else+tyvarRdrName :: HsType p -> Maybe (LIdOccP p)+#endif tyvarRdrName (HsTyVar _ _ n) = Just n tyvarRdrName _ = Nothing --- fixityDecls :: HsModule -> [(LIdP p, Fixity)]-#if __GLASGOW_HASKELL__ >= 906-fixityDecls :: HsModule GhcPs -> [(LocatedN RdrName, Fixity)]+-- | On GHC >= 9.14 constructor-pattern type arguments are invisible+-- patterns in the PrefixCon argument list rather than a separate tyargs+-- field. Retrie ignores them, as it ignored the tyargs field on older GHCs.+-- TODO: Handle this case properly.+dropInvisPats :: [LPat GhcPs] -> [LPat GhcPs]+#if __GLASGOW_HASKELL__ < 914+dropInvisPats = id #else-fixityDecls :: HsModule -> [(LocatedN RdrName, Fixity)]+dropInvisPats = dropHsConPatTyArgs #endif++grhssList :: GRHSs GhcPs body -> [LGRHS GhcPs body]+#if __GLASGOW_HASKELL__ < 914+grhssList = grhssGRHSs+#else+grhssList = NE.toList . grhssGRHSs+#endif++-- fixityDecls :: HsModule -> [(LIdP p, Fixity)]+fixityDecls :: HsModule GhcPs -> [(LocatedN RdrName, Fixity)] fixityDecls m =   [ (nm, fixity)   | L _ (SigD _ (FixSig _ (FixitySig _ nms fixity))) <- hsmodDecls m@@ -108,10 +132,10 @@   ]  ruleInfo :: RuleDecl GhcPs -> [RuleInfo]-#if __GLASGOW_HASKELL__ >= 906+#if __GLASGOW_HASKELL__ < 914 ruleInfo (HsRule _ (L _ riName) _ tyBs valBs riLHS riRHS) = #else-ruleInfo (HsRule _ (L _ (_, riName)) _ tyBs valBs riLHS riRHS) =+ruleInfo (HsRule _ (L _ riName) _ (RuleBndrs _ tyBs valBs) riLHS riRHS) = #endif   let     riQuantifiers =@@ -128,11 +152,21 @@   ]  tyBindersToLocatedRdrNames :: [LHsTyVarBndr s GhcPs] -> [LocatedN RdrName]-tyBindersToLocatedRdrNames vars = catMaybes-  [ case var of-      UserTyVar _ _ v -> Just v-      KindedTyVar _ _ v _ -> Just v-  | L _ var <- vars ]+#if __GLASGOW_HASKELL__ < 912+tyBindersToLocatedRdrNames = map getTyVarLName+  where+    getTyVarLName (L _ (UserTyVar _ _ ln)) = ln+    getTyVarLName (L _ (KindedTyVar _ _ ln _)) = ln+    getTyVarLName (L _ (XTyVarBndr _)) = error "tyBindersToLocatedRdrNames: XTyVarBndr not supported"+#else+-- Note: we can't use 'hsLTyVarNames' here because it throws away the wildcards,+-- and we _must_ preserve the length of the list. Also can't use some of the+-- other single-binder variants of hsTyVarLName because they throw away the+-- location on the RdrName result.+tyBindersToLocatedRdrNames = map (fromMaybe mkWildcard . hsTyVarLName . unLoc)+  where+    mkWildcard = error "tyBindersToLocatedRdrNames: wildcard type binder not supported"+#endif  data RuleInfo = RuleInfo   { riName :: RuleName@@ -141,11 +175,6 @@   , riRHS :: LHsExpr GhcPs   } -#if __GLASGOW_HASKELL__ < 810-noExtField :: NoExt-noExtField = noExt-#endif- overlaps :: SrcSpan -> SrcSpan -> Bool overlaps (RealSrcSpan s1 _) (RealSrcSpan s2 _) =      srcSpanFile s1 == srcSpanFile s2 &&@@ -173,17 +202,9 @@ uniqBag = listToUFM_C (++) . map (second pure)  getRealLoc :: SrcLoc -> Maybe RealSrcLoc-#if __GLASGOW_HASKELL__ < 900-getRealLoc (RealSrcLoc l) = Just l-#else getRealLoc (RealSrcLoc l _) = Just l-#endif getRealLoc _ = Nothing  getRealSpan :: SrcSpan -> Maybe RealSrcSpan-#if __GLASGOW_HASKELL__ < 900-getRealSpan (RealSrcSpan s) = Just s-#else getRealSpan (RealSrcSpan s _) = Just s-#endif getRealSpan _ = Nothing
Retrie/GroundTerms.hs view
@@ -1,4 +1,5 @@--- Copyright (c) Facebook, Inc. and its affiliates.+-- Copyright (c) 2025 Andrew Farmer+-- Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. -- -- This source code is licensed under the MIT license found in the -- LICENSE file in the root directory of this source tree.
Retrie/Monad.hs view
@@ -1,4 +1,5 @@--- Copyright (c) Facebook, Inc. and its affiliates.+-- Copyright (c) 2025 Andrew Farmer+-- Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. -- -- This source code is licensed under the MIT license found in the -- LICENSE file in the root directory of this source tree.@@ -37,7 +38,7 @@  import Retrie.Context import Retrie.CPP-import Retrie.ExactPrint hiding (rs)+import Retrie.ExactPrint import Retrie.Fixity import Retrie.GroundTerms import Retrie.Query@@ -124,7 +125,6 @@   (<*>) = ap  instance Monad Retrie where-  return = Pure   (>>=) = Bind  instance MonadIO Retrie where
Retrie/Options.hs view
@@ -1,10 +1,12 @@--- Copyright (c) Facebook, Inc. and its affiliates.+-- Copyright (c) 2025 Andrew Farmer+-- Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. -- -- This source code is licensed under the MIT license found in the -- LICENSE file in the root directory of this source tree. -- {-# LANGUAGE ApplicativeDo #-} {-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE NumericUnderscores #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE TupleSections #-} module Retrie.Options@@ -26,7 +28,11 @@   , GrepCommands(..)   ) where +import Control.Concurrent+  (getNumCapabilities, rtsSupportsBoundThreads, setNumCapabilities) import Control.Concurrent.Async (mapConcurrently)+import Control.Concurrent.QSem+import Control.Exception (bracket_) import Control.Monad (when, foldM) import Data.Bool import Data.Char (isAlphaNum, isSpace)@@ -103,6 +109,11 @@     -- ^ Iterate the given rewrites or 'Retrie' computation up to this many     -- times. Iteration may stop before the limit if no changes are made during     -- a given iteration.+  , jobs :: Maybe Int+    -- ^ Maximum number of target modules to rewrite concurrently. 'Nothing'+    -- (the default) means one per RTS capability, which is one unless the+    -- program is run with @+RTS -N@. Specified by the command-line flag '-j'.+    -- Peak memory use is roughly proportional to this number.   , noDefaultElaborations :: Bool     -- ^ Do not apply any of the built in elaborations in 'defaultElaborations'.   , randomOrder :: Bool@@ -136,6 +147,7 @@   , extraIgnores = []   , fixityEnv = mempty   , iterateN = 1+  , jobs = Nothing   , noDefaultElaborations = False   , randomOrder = False   , rewrites = D.def@@ -208,6 +220,16 @@     , value 1     , help "Iterate rewrites up to N times."     ]+  jobs <- optional $ option (eitherReader jobsReader) $ mconcat+    [ long "jobs"+    , short 'j'+    , metavar "N"+    , help $ unwords+      [ "Rewrite up to N target files concurrently, using N RTS capabilities."+      , "Defaults to the number of capabilities (1 unless run with +RTS -N)."+      , "Peak memory use grows with N."+      ]+    ]    executionMode <- parseMode   rewrites <- parseRewriteSpecOptions@@ -342,6 +364,11 @@ verbosityHelp :: String verbosityHelp = "0: silent, 1: normal, 2: loud (implies --single-threaded)" +jobsReader :: String -> Either String Int+jobsReader s = case reads s of+  [(n, "")] | n >= 1 -> Right n+  _ -> Left "invalid number of jobs. Must be a positive integer."+ -------------------------------------------------------------------------------  -- | Options that have been parsed, but not fully resolved.@@ -352,6 +379,7 @@ -- declared fixities in the target directory. resolveOptions :: LibDir -> ProtoOptions -> IO Options resolveOptions libdir protoOpts = do+  setJobs (jobs protoOpts)   absoluteTargetDir <- makeAbsolute (targetDir protoOpts)   opts@Options{..} <-     addLocalFixities libdir protoOpts { targetDir = absoluteTargetDir }@@ -391,15 +419,28 @@    return opts { fixityEnv = foldr ($) (fixityEnv opts) fixFns } --- | 'forM', but concurrency and input order controled by 'Options'.+-- | Set the number of RTS capabilities to the requested number of jobs, so+-- '-j' parallelizes without also requiring @+RTS -N@. Only possible with the+-- threaded RTS. Without it, concurrent jobs still interleave on one core,+-- which costs memory without any speedup.+setJobs :: Maybe Int -> IO ()+setJobs (Just n) | rtsSupportsBoundThreads = setNumCapabilities n+setJobs _ = return ()++-- | 'forM', but concurrency and input order controlled by 'Options'.+-- At most 'jobs' actions run at once, so peak memory use is bounded by the+-- number of jobs rather than the number of inputs. forFn :: Options_ x y -> [a] -> (a -> IO b) -> IO [b] forFn Options{..} c f-  | randomOrder = fn f =<< shuffleM c-  | otherwise = fn f c+  | randomOrder = fn =<< shuffleM c+  | otherwise = fn c   where-    fn-      | singleThreaded = mapM-      | otherwise = mapConcurrently+    fn xs+      | singleThreaded = mapM f xs+      | otherwise = do+          n <- maybe getNumCapabilities return jobs+          sem <- newQSem (max 1 n)+          mapConcurrently (bracket_ (waitQSem sem) (signalQSem sem) . f) xs  -- | Find all files to target for rewriting. getTargetFiles :: Options_ a b -> [GroundTerms] -> IO [FilePath]@@ -487,13 +528,28 @@  -- | run a command with a list of files as quoted arguments commandStep :: FilePath -> Verbosity -> [FilePath]-> CommandLine -> IO [FilePath]-commandStep targetDir verbosity files cmd = doCmd targetDir verbosity (cmd <> formatPaths files)- where-    formatPaths [] = ""-    formatPaths xs = " " <> unwords (map quotePath xs)+commandStep targetDir verbosity files cmd =+  fmap concat $ forM (chunkifyArgs $ map quotePath files) $ \args ->+    doCmd targetDir verbosity $ cmd <> " " <> unwords args+ quotePath :: FilePath -> FilePath quotePath x = "'" <> x <> "'" +-- Split arguments into chunks whose size does not exceed 'argMax'.+-- Note that @chunkifyArgs []@ returns @[[]]@ intentionally.+chunkifyArgs :: [String] -> [[String]]+chunkifyArgs = go 0 []+  where+    go _ acc [] = [reverse acc]+    go n acc (arg: args)+      | n <= 0 || n + len <= argMax = go (n + len) (arg: acc) args+      | otherwise = reverse acc: go len [arg] args+      where+        len = length arg + 1++-- | Hardcoded default @--max-args=max-args@ used by @xargs@.+argMax :: Int+argMax = 128 * 1024  doCmd :: FilePath -> Verbosity -> String -> IO [FilePath] doCmd targetDir verbosity shellCmd = do
Retrie/PatternMap/Bag.hs view
@@ -1,4 +1,5 @@--- Copyright (c) Facebook, Inc. and its affiliates.+-- Copyright (c) 2025 Andrew Farmer+-- Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. -- -- This source code is licensed under the MIT license found in the -- LICENSE file in the root directory of this source tree.
Retrie/PatternMap/Class.hs view
@@ -1,4 +1,5 @@--- Copyright (c) Facebook, Inc. and its affiliates.+-- Copyright (c) 2025 Andrew Farmer+-- Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. -- -- This source code is licensed under the MIT license found in the -- LICENSE file in the root directory of this source tree.
Retrie/PatternMap/Instances.hs view
@@ -1,4 +1,5 @@--- Copyright (c) Facebook, Inc. and its affiliates.+-- Copyright (c) 2025 Andrew Farmer+-- Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. -- -- This source code is licensed under the MIT license found in the -- LICENSE file in the root directory of this source tree.@@ -54,18 +55,12 @@   mAlter env vs tupArg f m = go tupArg     where       go (Present _ e) = m { tamPresent = mAlter env vs e  f (tamPresent m) }-#if __GLASGOW_HASKELL__ < 900-      go XTupArg{} = missingSyntax "XTupArg"-#endif       go (Missing _) = m { tamMissing = mAlter env vs () f (tamMissing m) }    mMatch :: MatchEnv -> Key TupArgMap -> (Substitution, TupArgMap a) -> [(Substitution, a)]   mMatch env = go     where       go (Present _ e) = mapFor tamPresent >=> mMatch env e-#if __GLASGOW_HASKELL__ < 900-      go XTupArg{} = const []-#endif       go (Missing _) = mapFor tamMissing >=> mMatch env ()  ------------------------------------------------------------------------@@ -182,13 +177,25 @@       go (HsWordPrim _ i)   = m { lmWordPrim = mAlter env vs i f (lmWordPrim m) }       go (HsInt64Prim _ i)  = m { lmInt64Prim = mAlter env vs i f (lmInt64Prim m) }       go (HsWord64Prim _ i) = m { lmWord64Prim = mAlter env vs i f (lmWord64Prim m) }-      go (HsInteger _ _ _) = missingSyntax "HsInteger"+#if __GLASGOW_HASKELL__ < 914+      go HsInteger{} = missingSyntax "HsInteger"       go HsRat{} = missingSyntax "HsRat"+#endif       go HsFloatPrim{} = missingSyntax "HsFloatPrim"       go HsDoublePrim{} = missingSyntax "HsDoublePrim"-#if __GLASGOW_HASKELL__ < 900-      go XLit{} = missingSyntax "XLit"+#if __GLASGOW_HASKELL__ < 908+#else+      go HsInt8Prim{} = missingSyntax "HsInt8Prim"+      go HsInt16Prim{} = missingSyntax "HsInt16Prim"+      go HsInt32Prim{} = missingSyntax "HsInt32Prim"+      go HsWord8Prim{} = missingSyntax "HsWord8Prim"+      go HsWord16Prim{} = missingSyntax "HsWord16Prim"+      go HsWord32Prim{} = missingSyntax "HsWord32Prim" #endif+#if __GLASGOW_HASKELL__ < 912+#else+      go HsMultilineString{} = missingSyntax "HsMultilineString"+#endif    mMatch :: MatchEnv -> Key LMap -> (Substitution, LMap a) -> [(Substitution, a)]   mMatch _   _   (_,LMEmpty) = []@@ -264,9 +271,6 @@ -- back, which allows us to assign it to the expression when building the -- result. --- Note [Lambdas]--- This currently stores both HsLam and HsLamCase- -- Note [Stmt Lists] -- Statement lists bind to the right, so we need to extend the environment -- as we move down it. Thus we cannot simply store them as ListMap SMap a.@@ -278,7 +282,11 @@        , emIPVar :: FSEnv a        , emOverLit :: OLMap a        , emLit   :: LMap a-       , emLam   :: MGMap a -- See Note [Lambdas]+#if __GLASGOW_HASKELL__ < 912+       , emLam   :: MGMap a+#else+       , emLam   :: LVMap (MGMap a)+#endif        , emApp   :: EMap (EMap a)        , emOpApp :: EMap (EMap (EMap a)) -- op, lhs, rhs        , emNegApp :: EMap a@@ -353,101 +361,77 @@         m { emCase = mAlter env vs s (toA (mAlter env vs mg f)) (emCase m) }       go (HsDo _ sc ss) =         m { emDo = mAlter env vs sc (toA (mAlter env vs (unLoc ss) f)) (emDo m) }-#if __GLASGOW_HASKELL__ < 900-      go (HsIf _ _ c tr fl) =-#else       go (HsIf _ c tr fl) =-#endif         m { emIf = mAlter env vs c                       (toA (mAlter env vs tr                           (toA (mAlter env vs fl f)))) (emIf m) }       go (HsIPVar _ (HsIPName ip)) = m { emIPVar = mAlter env vs ip f (emIPVar m) }       go (HsLit _ l) = m { emLit   = mAlter env vs l f (emLit m) }-      go (HsLam _ mg) = m { emLam   = mAlter env vs mg f (emLam m) }+#if __GLASGOW_HASKELL__ < 912+      go (HsLam _ mg) = m { emLam = mAlter env vs mg f (emLam m) }+#else+      go (HsLam _ v mg) = m { emLam = mAlter env vs v (toA (mAlter env vs mg f)) (emLam m) }+#endif       go (HsOverLit _ ol) = m { emOverLit = mAlter env vs (ol_val ol) f (emOverLit m) }       go (NegApp _ e' _) = m { emNegApp = mAlter env vs e' f (emNegApp m) }-#if __GLASGOW_HASKELL__ < 904-      go (HsPar _ e') = m { emPar  = mAlter env vs e' f (emPar m) }-#else+#if __GLASGOW_HASKELL__ < 912       go (HsPar _ _ e' _) = m { emPar  = mAlter env vs e' f (emPar m) }+#else+      go (HsPar _ e') = m { emPar  = mAlter env vs e' f (emPar m) } #endif       go (OpApp _ l o r) =         m { emOpApp = mAlter env vs o (toA (mAlter env vs l (toA (mAlter env vs r f)))) (emOpApp m) }-#if __GLASGOW_HASKELL__ < 904       go (RecordCon _ v fs) =-        m { emRecordCon = mAlter env vs (unLoc v) (toA (mAlter env vs (fieldsToRdrNames $ rec_flds fs) f)) (emRecordCon m) }-#else-      go (RecordCon _ v fs) =         m { emRecordCon = mAlter env vs (unLoc v :: RdrName) (toA (mAlter env vs (rec_flds fs) f)) (emRecordCon m) }-#endif       go (RecordUpd _ e' fs) =         m { emRecordUpd = mAlter env vs e' (toA (mAlter env vs (fieldsToRdrNamesUpd fs) f)) (emRecordUpd m) }       go (SectionL _ lhs o) =         m { emSecL = mAlter env vs o (toA (mAlter env vs lhs f)) (emSecL m) }       go (SectionR _ o rhs) =         m { emSecR = mAlter env vs o (toA (mAlter env vs rhs f)) (emSecR m) }-#if __GLASGOW_HASKELL__ < 904-      go (HsLet _ lbs e') =-#else+#if __GLASGOW_HASKELL__ < 912       go (HsLet _ _ lbs _ e') =+#else+      go (HsLet _ lbs e') = #endif         let           bs = collectLocalBinders CollNoDictBinders lbs           env' = foldr extendAlphaEnvInternal env bs           vs' = vs `exceptQ` bs         in m { emLet = mAlter env vs lbs (toA (mAlter env' vs' e' f)) (emLet m) }+#if __GLASGOW_HASKELL__ < 912       go HsLamCase{} = missingSyntax "HsLamCase"+      go HsRecSel{} = missingSyntax "HsRecSel"+#endif       go HsMultiIf{} = missingSyntax "HsMultiIf"       go (ExplicitList _ es) = m { emExplicitList = mAlter env vs es f (emExplicitList m) }       go ArithSeq{} = missingSyntax "ArithSeq"       go (ExprWithTySig _ e' (HsWC _ (L _ (HsSig _ _ ty)))) =         m { emExprWithTySig = mAlter env vs e' (toA (mAlter env vs ty f)) (emExprWithTySig m) }-#if __GLASGOW_HASKELL__ < 900-      go XExpr{} = missingSyntax "XExpr"-      go ExprWithTySig{} = missingSyntax "ExprWithTySig"-      go HsSCC{} = missingSyntax "HsSCC"-      go HsCoreAnn{} = missingSyntax "HsCoreAnn"-      go HsTickPragma{} = missingSyntax "HsTickPragma"-      go HsWrap{} = missingSyntax "HsWrap"-#else       go HsPragE{} = missingSyntax "HsPragE"-#endif-#if __GLASGOW_HASKELL__ < 904-      go HsBracket{} = missingSyntax "HsBracket"-      go HsRnBracketOut{} = missingSyntax "HsRnBracketOut"-      go HsTcBracketOut{} = missingSyntax "HsTcBracketOut"-      go HsSpliceE{} = missingSyntax "HsSpliceE"-      go HsProc{} = missingSyntax "HsProc"-      go HsStatic{} = missingSyntax "HsStatic"-#else       go HsTypedBracket{} = missingSyntax "HsTypedBracket"       go HsUntypedBracket{} = missingSyntax "HsUntypedBracket"-#if __GLASGOW_HASKELL__ < 906-      go HsSpliceE{} = missingSyntax "HsSpliceE"-#endif-#endif-#if __GLASGOW_HASKELL__ < 810-      go HsArrApp{} = missingSyntax "HsArrApp"-      go HsArrForm{} = missingSyntax "HsArrForm"-      go EWildPat{} = missingSyntax "EWildPat"-      go EAsPat{} = missingSyntax "EAsPat"-      go EViewPat{} = missingSyntax "EViewPat"-      go ELazyPat{} = missingSyntax "ELazyPat"-#endif-#if __GLASGOW_HASKELL__ < 904-      go HsTick{} = missingSyntax "HsTick"-      go HsBinTick{} = missingSyntax "HsBinTick"-#endif+#if __GLASGOW_HASKELL__ < 914       go HsUnboundVar{} = missingSyntax "HsUnboundVar"-#if __GLASGOW_HASKELL__ < 904-      go HsRecFld{} = missingSyntax "HsRecFld"+#else+      go HsHole{} = missingSyntax "HsHole" #endif       go HsOverLabel{} = missingSyntax "HsOverLabel"       go HsAppType{} = missingSyntax "HsAppType"-#if __GLASGOW_HASKELL__ < 904-      go HsConLikeOut{} = missingSyntax "HsConLikeOut"-#endif       go ExplicitSum{} = missingSyntax "ExplicitSum"+      go HsGetField{} = missingSyntax "HsGetField"+      go HsProjection{} = missingSyntax "HsProjection"+      go HsTypedSplice{} = missingSyntax "HsTypedSplice"+      go HsUntypedSplice{} = missingSyntax "HsUntypedSplice"+      go HsProc{} = missingSyntax "HsProc"+      go HsStatic{} = missingSyntax "HsStatic"+#if __GLASGOW_HASKELL__ < 912+#else+      go HsEmbTy{} = missingSyntax "HsEmbTy"+      go HsForAll{} = missingSyntax "HsForAll"+      go HsQual{} = missingSyntax "HsQual"+      go HsFunArr{} = missingSyntax "HsFunArr"+#endif    mMatch :: MatchEnv -> Key EMap -> (Substitution, EMap a) -> [(Substitution, a)]   mMatch _   _ (_,EMEmpty) = []@@ -459,40 +443,35 @@       go (HsApp _ l r) = mapFor emApp >=> mMatch env l >=> mMatch env r       go (HsCase _ s mg) = mapFor emCase >=> mMatch env s >=> mMatch env mg       go (HsDo _ sc ss) = mapFor emDo >=> mMatch env sc >=> mMatch env (unLoc ss)-#if __GLASGOW_HASKELL__ < 900-      go (HsIf _ _ c tr fl) =-#else       go (HsIf _ c tr fl) =-#endif         mapFor emIf >=> mMatch env c >=> mMatch env tr >=> mMatch env fl       go (HsIPVar _ (HsIPName ip)) = mapFor emIPVar >=> mMatch env ip+#if __GLASGOW_HASKELL__ < 912       go (HsLam _ mg) = mapFor emLam >=> mMatch env mg+#else+      go (HsLam _ v mg) = mapFor emLam >=> mMatch env v >=> mMatch env mg+#endif       go (HsLit _ l) = mapFor emLit >=> mMatch env l       go (HsOverLit _ ol) = mapFor emOverLit >=> mMatch env (ol_val ol)-#if __GLASGOW_HASKELL__ < 904-      go (HsPar _ e') = mapFor emPar >=> mMatch env e'-#else+#if __GLASGOW_HASKELL__ < 912       go (HsPar _ _ e' _) = mapFor emPar >=> mMatch env e'+#else+      go (HsPar _ e') = mapFor emPar >=> mMatch env e' #endif       go (HsVar _ v) = mapFor emVar >=> mMatch env (unLoc v)       go (OpApp _ l o r) =         mapFor emOpApp >=> mMatch env o >=> mMatch env l >=> mMatch env r       go (NegApp _ e' _) = mapFor emNegApp >=> mMatch env e'-#if __GLASGOW_HASKELL__ < 904       go (RecordCon _ v fs) =-        mapFor emRecordCon >=> mMatch env (unLoc v) >=> mMatch env (fieldsToRdrNames $ rec_flds fs)-#else-      go (RecordCon _ v fs) =         mapFor emRecordCon >=> mMatch env (unLoc v) >=> mMatch env (rec_flds fs)-#endif       go (RecordUpd _ e' fs) =         mapFor emRecordUpd >=> mMatch env e' >=> mMatch env (fieldsToRdrNamesUpd fs)       go (SectionL _ lhs o) = mapFor emSecL >=> mMatch env o >=> mMatch env lhs       go (SectionR _ o rhs) = mapFor emSecR >=> mMatch env o >=> mMatch env rhs-#if __GLASGOW_HASKELL__ < 904-      go (HsLet _ lbs e') =-#else+#if __GLASGOW_HASKELL__ < 912       go (HsLet _ _ lbs _ e') =+#else+      go (HsLet _ lbs e') = #endif         let           bs = collectLocalBinders CollNoDictBinders lbs@@ -534,15 +513,61 @@  ------------------------------------------------------------------------ +#if __GLASGOW_HASKELL__ < 912+#else+data LVMap a+  = EmptyLVMap+  | LVMap+      { lvmSingle :: MaybeMap a+      , lvmCase :: MaybeMap a+      , lvmCases :: MaybeMap a+      }+  deriving (Functor)++instance PatternMap LVMap where+  type Key LVMap = HsLamVariant++  mEmpty :: LVMap a+  mEmpty = EmptyLVMap++  mUnion :: LVMap a -> LVMap a -> LVMap a+  mUnion EmptyLVMap m = m+  mUnion m EmptyLVMap = m+  mUnion m1 m2 = LVMap+    { lvmSingle = unionOn lvmSingle m1 m2+    , lvmCase = unionOn lvmCase m1 m2+    , lvmCases = unionOn lvmCases m1 m2+    }++  mAlter+    :: AlphaEnv -> Quantifiers -> Key LVMap -> A a -> LVMap a -> LVMap a+  mAlter env qs lv f EmptyLVMap = mAlter env qs lv f (LVMap mEmpty mEmpty mEmpty)+  mAlter env qs lv f m@LVMap{} = go lv+    where+      go LamSingle = m { lvmSingle = mAlter env qs () f (lvmSingle m) }+      go LamCase = m { lvmCase = mAlter env qs () f (lvmCase m) }+      go LamCases = m { lvmCases = mAlter env qs () f (lvmCases m) }++  mMatch+    :: MatchEnv+    -> Key LVMap+    -> (Substitution, LVMap a)+    -> [(Substitution, a)]+  mMatch _ _ (_, EmptyLVMap) = []+  mMatch env lv hs@(_, LVMap{}) = go lv hs+    where+      go LamSingle = mapFor lvmSingle >=> mMatch env ()+      go LamCase = mapFor lvmCase >=> mMatch env ()+      go LamCases = mapFor lvmCases >=> mMatch env ()+#endif++------------------------------------------------------------------------+ data SCMap a   = SCEmpty   | SCM { scmListComp :: MaybeMap a         , scmMonadComp :: MaybeMap a-#if __GLASGOW_HASKELL__ < 900-        , scmDoExpr :: MaybeMap a-#else         , scmDoExpr :: FSEnv a -- We use empty string when modulename is Nothing-#endif         -- TODO: the rest         }   deriving (Functor)@@ -551,15 +576,7 @@ emptySCMapWrapper = SCM mEmpty mEmpty mEmpty  instance PatternMap SCMap where-#if __GLASGOW_HASKELL__ < 900-  type Key SCMap = HsStmtContext Name -- see comment on HsDo in GHC-#elif __GLASGOW_HASKELL__ < 902-  type Key SCMap = HsStmtContext GhcRn-#elif __GLASGOW_HASKELL__ < 904-  type Key SCMap = HsStmtContext (HsDoRn GhcPs)-#else   type Key SCMap = HsDoFlavour-#endif    mEmpty :: SCMap a   mEmpty = SCEmpty@@ -579,18 +596,8 @@     where       go ListComp = m { scmListComp = mAlter env vs () f (scmListComp m) }       go MonadComp = m { scmMonadComp = mAlter env vs () f (scmMonadComp m) }-#if __GLASGOW_HASKELL__ < 900-      go DoExpr = m { scmDoExpr = mAlter env vs () f (scmDoExpr m) }-#else       go (DoExpr mname) = m { scmDoExpr = mAlter env vs (maybe "" moduleNameFS mname) f (scmDoExpr m) }-#endif       go MDoExpr{} = missingSyntax "MDoExpr"-#if __GLASGOW_HASKELL__ < 904-      go ArrowExpr = missingSyntax "ArrowExpr"-      go (PatGuard _) = missingSyntax "PatGuard"-      go (ParStmtCtxt _) = missingSyntax "ParStmtCtxt"-      go (TransStmtCtxt _) = missingSyntax "TransStmtCtxt"-#endif       go GhciStmtCtxt = missingSyntax "GhciStmtCtxt"    mMatch :: MatchEnv -> Key SCMap -> (Substitution, SCMap a) -> [(Substitution, a)]@@ -599,11 +606,7 @@     where       go ListComp = mapFor scmListComp >=> mMatch env ()       go MonadComp = mapFor scmMonadComp >=> mMatch env ()-#if __GLASGOW_HASKELL__ < 900-      go DoExpr = mapFor scmDoExpr >=> mMatch env ()-#else       go (DoExpr mname) = mapFor scmDoExpr >=> mMatch env (maybe "" moduleNameFS mname)-#endif       go _ = const [] -- TODO  ------------------------------------------------------------------------@@ -648,17 +651,18 @@    mAlter :: AlphaEnv -> Quantifiers -> Key MMap -> A a -> MMap a -> MMap a   mAlter env vs match f (MMap m) =-    let lpats = m_pats match-        pbs = collectPatsBinders CollNoDictBinders lpats-        env' = foldr extendAlphaEnvInternal env pbs-        vs' = vs `exceptQ` pbs+    let+      lpats = getMatchPats match+      pbs = collectPatsBinders CollNoDictBinders lpats+      env' = foldr extendAlphaEnvInternal env pbs+      vs' = vs `exceptQ` pbs     in MMap (mAlter env vs lpats               (toA (mAlter env' vs' (m_grhss match) f)) m)    mMatch :: MatchEnv -> Key MMap -> (Substitution, MMap a) -> [(Substitution, a)]   mMatch env match = mapFor unMMap >=> mMatch env lpats >=> mMatch env' (m_grhss match)     where-      lpats = m_pats match+      lpats = getMatchPats match       pbs = collectPatsBinders CollNoDictBinders lpats       env' = extendMatchEnv env pbs @@ -676,14 +680,10 @@ emptyCDMapWrapper = CDMap mEmpty mEmpty  instance PatternMap CDMap where-#if __GLASGOW_HASKELL__ < 810-  type Key CDMap = HsConDetails (LPat GhcPs) (HsRecFields GhcPs (LPat GhcPs))-#elif __GLASGOW_HASKELL__ < 906-  -- We must manually expand 'LPat' to avoid UndecidableInstances in GHC 8.10+-  type Key CDMap = HsConDetails (HsPatSigType GhcPs) (LocatedA (Pat GhcPs)) (HsRecFields GhcPs (LocatedA (Pat GhcPs)))-  -- type HsConPatDetails p = HsConDetails (HsPatSigType (NoGhcTc p)) (LPat p) (HsRecFields p (LPat p))-#else+#if __GLASGOW_HASKELL__ < 914   type Key CDMap = HsConDetails (HsConPatTyArg GhcPs) (LocatedA (Pat GhcPs)) (HsRecFields GhcPs (LocatedA (Pat GhcPs)))+#else+  type Key CDMap = HsConDetails (LocatedA (Pat GhcPs)) (HsRecFields GhcPs (LocatedA (Pat GhcPs))) #endif    mEmpty :: CDMap a@@ -701,7 +701,12 @@   mAlter env vs d f CDEmpty   = mAlter env vs d f emptyCDMapWrapper   mAlter env vs d f m@CDMap{} = go d     where-      go (PrefixCon tyargs ps) = m { cdPrefixCon = mAlter env vs ps f (cdPrefixCon m) }+#if __GLASGOW_HASKELL__ < 914+      -- TODO(xich): properly handle tyargs here!+      go (PrefixCon _tyargs ps) = m { cdPrefixCon = mAlter env vs ps f (cdPrefixCon m) }+#else+      go (PrefixCon ps) = m { cdPrefixCon = mAlter env vs (dropInvisPats ps) f (cdPrefixCon m) }+#endif       go (RecCon _) = missingSyntax "RecCon"       go (InfixCon p1 p2) = m { cdInfixCon = mAlter env vs p1                                               (toA (mAlter env vs p2 f))@@ -711,7 +716,12 @@   mMatch _   _ (_ ,CDEmpty)   = []   mMatch env d (hs,m@CDMap{}) = go d (hs,m)     where-      go (PrefixCon tyargs ps) = mapFor cdPrefixCon >=> mMatch env ps+#if __GLASGOW_HASKELL__ < 914+      -- TODO(xich): properly handle tyargs here!+      go (PrefixCon _tyargs ps) = mapFor cdPrefixCon >=> mMatch env ps+#else+      go (PrefixCon ps) = mapFor cdPrefixCon >=> mMatch env (dropInvisPats ps)+#endif       go (InfixCon p1 p2) = mapFor cdInfixCon >=> mMatch env p1 >=> mMatch env p2       go _ = const [] -- TODO @@ -737,12 +747,8 @@ emptyPatMapWrapper = PatMap mEmpty mEmpty mEmpty mEmpty mEmpty mEmpty  instance PatternMap PatMap where-#if __GLASGOW_HASKELL__ < 810-  type Key PatMap = LPat GhcPs-#else   -- We must manually expand 'LPat' to avoid UndecidableInstances in GHC 8.10+   type Key PatMap = LocatedA (Pat GhcPs)-#endif    mEmpty :: PatMap a   mEmpty = PatEmpty@@ -771,29 +777,28 @@       go AsPat{} = missingSyntax "AsPat"       go BangPat{} = missingSyntax "BangPat"       go ListPat{} = missingSyntax "ListPat"-#if __GLASGOW_HASKELL__ < 900-      go XPat{} = missingSyntax "XPat"-      go CoPat{} = missingSyntax "CoPat"-      go ConPatOut{} = missingSyntax "ConPatOut"-      go (ConPatIn c d) =-#else       go (ConPat _ c d) =-#endif         m { pmConPatIn = mAlter env vs (rdrFS (unLoc c)) (toA (mAlter env vs d f)) (pmConPatIn m) }       go ViewPat{} = missingSyntax "ViewPat"       go SplicePat{} = missingSyntax "SplicePat"       go LitPat{} = missingSyntax "LitPat"       go NPat{} = missingSyntax "NPat"       go NPlusKPat{} = missingSyntax "NPlusKPat"-#if __GLASGOW_HASKELL__ < 904-      go (ParPat _ p) = m { pmParPat = mAlter env vs p f (pmParPat m) }-#else+#if __GLASGOW_HASKELL__ < 912       go (ParPat _ _ p _) = m { pmParPat = mAlter env vs p f (pmParPat m) }+#else+      go (ParPat _ p) = m { pmParPat = mAlter env vs p f (pmParPat m) } #endif       go (TuplePat _ ps b) =         m { pmTuplePat = mAlter env vs b (toA (mAlter env vs ps f)) (pmTuplePat m) }       go SigPat{} = missingSyntax "SigPat"       go SumPat{} = missingSyntax "SumPat"+#if __GLASGOW_HASKELL__ < 912+#else+      go OrPat{} = missingSyntax "OrPat"+      go EmbTyPat{} = missingSyntax "EmbTyPat"+      go InvisPat{} = missingSyntax "InvisPat"+#endif    mMatch :: MatchEnv -> Key PatMap -> (Substitution, PatMap a) -> [(Substitution, a)]   mMatch _   _   (_, PatEmpty)   = []@@ -804,18 +809,14 @@       hss lp = extendResult (pmHole m) (HolePat $ mePruneA env lp) hs        go (WildPat _) = mapFor pmWild >=> mMatch env ()-#if __GLASGOW_HASKELL__ < 904-      go (ParPat _ p) = mapFor pmParPat >=> mMatch env p-#else+#if __GLASGOW_HASKELL__ < 912       go (ParPat _ _ p _) = mapFor pmParPat >=> mMatch env p+#else+      go (ParPat _ p) = mapFor pmParPat >=> mMatch env p #endif       go (TuplePat _ ps b) = mapFor pmTuplePat >=> mMatch env b >=> mMatch env ps       go (VarPat _ _) = mapFor pmVar >=> mMatch env ()-#if __GLASGOW_HASKELL__ < 900-      go (ConPatIn c d) =-#else       go (ConPat _ c d) =-#endif         mapFor pmConPatIn >=> mMatch env (rdrFS (unLoc c)) >=> mMatch env d       go _ = const [] -- TODO @@ -840,11 +841,11 @@         env' = foldr extendAlphaEnvInternal env bs         vs' = vs `exceptQ` bs     in GRHSSMap (mAlter env vs lbs-                  (toA (mAlter env' vs' (map unLoc $ grhssGRHSs grhss) f)) m)+                  (toA (mAlter env' vs' (map unLoc $ grhssList grhss) f)) m)    mMatch :: MatchEnv -> Key GRHSSMap -> (Substitution, GRHSSMap a) -> [(Substitution, a)]   mMatch env grhss = mapFor unGRHSSMap >=> mMatch env lbs-                      >=> mMatch env' (map unLoc $ grhssGRHSs grhss)+                      >=> mMatch env' (map unLoc $ grhssList grhss)     where       lbs = grhssLocalBinds  grhss       bs = collectLocalBinders CollNoDictBinders lbs@@ -865,9 +866,6 @@   mUnion (GRHSMap m1) (GRHSMap m2) = GRHSMap (mUnion m1 m2)    mAlter :: AlphaEnv -> Quantifiers -> Key GRHSMap -> A a -> GRHSMap a -> GRHSMap a-#if __GLASGOW_HASKELL__ < 900-  mAlter _ _ XGRHS{} _ _ = missingSyntax "XGRHS"-#endif   mAlter env vs (GRHS _ gs b) f (GRHSMap m) =     let bs = collectLStmtsBinders CollNoDictBinders gs         env' = foldr extendAlphaEnvInternal env bs@@ -875,9 +873,6 @@     in GRHSMap (mAlter env vs gs (toA (mAlter env' vs' b f)) m)    mMatch :: MatchEnv -> Key GRHSMap -> (Substitution, GRHSMap a) -> [(Substitution, a)]-#if __GLASGOW_HASKELL__ < 900-  mMatch _ XGRHS{} = const []-#endif   mMatch env (GRHS _ gs b) =     mapFor unGRHSMap >=> mMatch env gs >=> mMatch env' b     where@@ -969,9 +964,6 @@   mAlter env vs lbs f m@LB{}  = go lbs     where       go (EmptyLocalBinds _) = m { lbEmpty = mAlter env vs () f (lbEmpty m) }-#if __GLASGOW_HASKELL__ < 900-      go XHsLocalBindsLR{} = missingSyntax "XHsLocalBindsLR"-#endif       go (HsValBinds _ vbs) =         let           bs = collectHsValBinders CollNoDictBinders vbs@@ -993,7 +985,11 @@       go _ = const [] -- TODO  deValBinds :: HsValBinds GhcPs -> [HsBind GhcPs]+#if __GLASGOW_HASKELL__ < 912 deValBinds (ValBinds _ lbs _) = map unLoc (bagToList lbs)+#else+deValBinds (ValBinds _ lbs _) = map unLoc lbs+#endif deValBinds _ = error "deValBinds ValBindsOut"  ------------------------------------------------------------------------@@ -1033,33 +1029,19 @@   mAlter env vs b f BMEmpty = mAlter env vs b f emptyBMapWrapper   mAlter env vs b f m@BM{}  = go b     where -- see Note [Bind env]-#if __GLASGOW_HASKELL__ < 900-      go XHsBindsLR{} = missingSyntax "XHsBindsLR"-      go (FunBind _ _ mg _ _) = m { bmFunBind = mAlter env vs mg f (bmFunBind m) }-      go (VarBind _ _ e _) = m { bmVarBind = mAlter env vs e f (bmVarBind m) }-#else       go (FunBind{fun_matches = mg}) = m { bmFunBind = mAlter env vs mg f (bmFunBind m) }       go (VarBind _ _ e) = m { bmVarBind = mAlter env vs e f (bmVarBind m) }-#endif       go (PatBind{pat_lhs=lhs, pat_rhs=rhs}) =         m { bmPatBind = mAlter env vs lhs               (toA $ mAlter env vs rhs f) (bmPatBind m) }-#if __GLASGOW_HASKELL__ < 904-      go AbsBinds{} = missingSyntax "AbsBinds"-#endif       go PatSynBind{} = missingSyntax "PatSynBind"    mMatch :: MatchEnv -> Key BMap -> (Substitution, BMap a) -> [(Substitution, a)]   mMatch _   _ (_,BMEmpty) = []   mMatch env b (hs,m@BM{}) = go b (hs,m)     where-#if __GLASGOW_HASKELL__ < 900-      go (FunBind _ _ mg _ _) = mapFor bmFunBind >=> mMatch env mg-      go (VarBind _ _ e _) = mapFor bmVarBind >=> mMatch env e-#else       go (FunBind{fun_matches = mg}) = mapFor bmFunBind >=> mMatch env mg       go (VarBind _ _ e) = mapFor bmVarBind >=> mMatch env e-#endif       go (PatBind{pat_lhs=lhs, pat_rhs=rhs})         = mapFor bmPatBind >=> mMatch env lhs >=> mMatch env rhs       go _ = const [] -- TODO@@ -1099,12 +1081,7 @@     where       go (BodyStmt _ e _ _) = m { smBodyStmt = mAlter env vs e f (smBodyStmt m) }       go (LastStmt _ e _ _)   = m { smLastStmt = mAlter env vs e f (smLastStmt m) }-#if __GLASGOW_HASKELL__ < 900-      go XStmtLR{} = missingSyntax "XStmtLR"-      go (BindStmt _ p e _ _) =-#else       go (BindStmt _ p e) =-#endif         let bs = collectPatBinders CollNoDictBinders p             env' = foldr extendAlphaEnvInternal env bs             vs' = vs `exceptQ` bs@@ -1114,7 +1091,9 @@       go ParStmt{} = missingSyntax "ParStmt"       go TransStmt{} = missingSyntax "TransStmt"       go RecStmt{} = missingSyntax "RecStmt"+#if __GLASGOW_HASKELL__ < 912       go ApplicativeStmt{} = missingSyntax "ApplicativeStmt"+#endif    mMatch :: MatchEnv -> Key SMap -> (Substitution, SMap a) -> [(Substitution, a)]   mMatch _   _   (_,SMEmpty) = []@@ -1122,11 +1101,7 @@     where       go (BodyStmt _ e _ _) = mapFor smBodyStmt >=> mMatch env e       go (LastStmt _ e _ _) = mapFor smLastStmt >=> mMatch env e-#if __GLASGOW_HASKELL__ < 900-      go (BindStmt _ p e _ _) =-#else       go (BindStmt _ p e) =-#endif         let bs = collectPatBinders CollNoDictBinders p             env' = extendMatchEnv env bs         in mapFor smBindStmt >=> mMatch env p >=> mMatch env' e@@ -1139,11 +1114,7 @@   | TM { tyHole    :: Map RdrName a -- See Note [Holes]        , tyHsTyVar :: VMap a        , tyHsAppTy :: TyMap (TyMap a)-#if __GLASGOW_HASKELL__ < 810-       , tyHsForAllTy :: ForAllTyMap a -- See Note [Telescope]-#else        , tyHsForAllTy :: ForallVisMap (ForAllTyMap a) -- See Note [Telescope]-#endif        , tyHsFunTy :: TyMap (TyMap a)        , tyHsListTy :: TyMap a        , tyHsParTy :: TyMap a@@ -1194,31 +1165,18 @@       go HsKindSig{} = missingSyntax "HsKindSig"       go HsSpliceTy{} = missingSyntax "HsSpliceTy"       go HsDocTy{} = missingSyntax "HsDocTy"+#if __GLASGOW_HASKELL__ < 914       go HsBangTy{} = missingSyntax "HsBangTy"       go HsRecTy{} = missingSyntax "HsRecTy"+#endif       go (HsAppTy _ ty1 ty2) = m { tyHsAppTy = mAlter env vs ty1 (toA (mAlter env vs ty2 f)) (tyHsAppTy m) }-#if __GLASGOW_HASKELL__ < 810-      go (HsForAllTy _ bndrs ty') = m { tyHsForAllTy = mAlter env vs (map extractBinderInfo bndrs, ty') f (tyHsForAllTy m) }-#elif __GLASGOW_HASKELL__ < 900-      go (HsForAllTy _ vis bndrs ty') =-        m { tyHsForAllTy = mAlter env vs (vis == ForallVis) (toA (mAlter env vs (map extractBinderInfo bndrs, ty') f)) (tyHsForAllTy m) }-#else       go (HsForAllTy _ vis ty') | (isVisible, bndrs) <- splitVisBinders vis =         m { tyHsForAllTy = mAlter env vs isVisible (toA (mAlter env vs (bndrs, ty') f)) (tyHsForAllTy m) }-#endif-#if __GLASGOW_HASKELL__ < 900-      go (HsFunTy _ ty1 ty2) = m { tyHsFunTy = mAlter env vs ty1 (toA (mAlter env vs ty2 f)) (tyHsFunTy m) }-#else       go (HsFunTy _ _ ty1 ty2) = m { tyHsFunTy = mAlter env vs ty1 (toA (mAlter env vs ty2 f)) (tyHsFunTy m) }-#endif       go (HsListTy _ ty') = m { tyHsListTy = mAlter env vs ty' f (tyHsListTy m) }       go (HsParTy _ ty') = m { tyHsParTy = mAlter env vs ty' f (tyHsParTy m) }       go (HsQualTy _ cons ty') =-#if __GLASGOW_HASKELL__ < 904-        m { tyHsQualTy = mAlter env vs ty' (toA (mAlter env vs (fromMaybeContext cons) f)) (tyHsQualTy m) }-#else         m { tyHsQualTy = mAlter env vs ty' (toA (mAlter env vs (fromMaybeContext (Just cons)) f)) (tyHsQualTy m) }-#endif       go HsStarTy{} = missingSyntax "HsStarTy"       go (HsSumTy _ tys) = m { tyHsSumTy = mAlter env vs tys f (tyHsSumTy m) }       go (HsTupleTy _ ts tys) =@@ -1238,40 +1196,17 @@       hss = extendResult (tyHole m) (HoleType $ mePruneA env ty) hs        go (HsAppTy _ ty1 ty2) = mapFor tyHsAppTy >=> mMatch env ty1 >=> mMatch env ty2-#if __GLASGOW_HASKELL__ < 810-      go (HsForAllTy _ bndrs ty') = mapFor tyHsForAllTy >=> mMatch env (map extractBinderInfo bndrs, ty')-#elif __GLASGOW_HASKELL__ < 900-      go (HsForAllTy _ vis bndrs ty') =-        mapFor tyHsForAllTy >=> mMatch env (vis == ForallVis) >=> mMatch env (map extractBinderInfo bndrs, ty')-#else       go (HsForAllTy _ telescope ty') | (isVisible, bndrs) <- splitVisBinders telescope =         mapFor tyHsForAllTy >=> mMatch env isVisible >=> mMatch env (bndrs, ty')-#endif-#if __GLASGOW_HASKELL__ < 900-      go (HsFunTy _ ty1 ty2) = mapFor tyHsFunTy >=> mMatch env ty1 >=> mMatch env ty2-#else       go (HsFunTy _ _ ty1 ty2) = mapFor tyHsFunTy >=> mMatch env ty1 >=> mMatch env ty2-#endif       go (HsListTy _ ty') = mapFor tyHsListTy >=> mMatch env ty'       go (HsParTy _ ty') = mapFor tyHsParTy >=> mMatch env ty'-#if __GLASGOW_HASKELL__ < 904-      go (HsQualTy _ cons ty') = mapFor tyHsQualTy >=> mMatch env ty' >=> mMatch env (fromMaybeContext cons)-#else       go (HsQualTy _ cons ty') = mapFor tyHsQualTy >=> mMatch env ty' >=> mMatch env (fromMaybeContext (Just cons))-#endif       go (HsSumTy _ tys) = mapFor tyHsSumTy >=> mMatch env tys       go (HsTupleTy _ ts tys) = mapFor tyHsTupleTy >=> mMatch env ts >=> mMatch env tys       go (HsTyVar _ _ v) = mapFor tyHsTyVar >=> mMatch env (unLoc v)       go _                  = const [] -- TODO -#if __GLASGOW_HASKELL__ < 900-extractBinderInfo :: LHsTyVarBndr GhcPs -> (RdrName, Maybe (LHsKind GhcPs))-extractBinderInfo = go . unLoc-  where-    go (UserTyVar _ v) = (unLoc v, Nothing)-    go (KindedTyVar _ v k) = (unLoc v, Just k)-    go XTyVarBndr{} = missingSyntax "XTyVarBndr"-#else splitVisBinders :: HsForAllTelescope GhcPs -> (Bool, [(RdrName, Maybe (LHsKind GhcPs))]) splitVisBinders HsForAllVis{..} = (True, map extractBinderInfo hsf_vis_bndrs) splitVisBinders HsForAllInvis{..} = (False, map extractBinderInfo hsf_invis_bndrs)@@ -1279,8 +1214,19 @@ extractBinderInfo :: LHsTyVarBndr flag GhcPs -> (RdrName, Maybe (LHsKind GhcPs)) extractBinderInfo = go . unLoc   where+#if __GLASGOW_HASKELL__ < 912     go (UserTyVar _ _ v) = (unLoc v, Nothing)     go (KindedTyVar _ _ v k) = (unLoc v, Just k)+    go (XTyVarBndr _) = missingSyntax "XTyVarBndr"+#else+    go HsTvb{..} =+      case tvb_var of+        HsBndrVar _ rdr ->+            case tvb_kind of+              HsBndrKind _ lkind -> (unLoc rdr, Just lkind)+              _ -> (unLoc rdr, Nothing)+        HsBndrWildCard _ -> missingSyntax "HsBndrWildCard"+        XBndrVar _ -> missingSyntax "XBndrVar"     go XTyVarBndr{} = missingSyntax "XTyVarBndr" #endif @@ -1290,11 +1236,7 @@   deriving (Functor)  instance PatternMap RFMap where-#if __GLASGOW_HASKELL__ < 904-  type Key RFMap = LocatedA (HsRecField' RdrName (LocatedA (HsExpr GhcPs)))-#else   type Key RFMap = LocatedA (HsRecField GhcPs (LocatedA (HsExpr GhcPs)))-#endif    mEmpty :: RFMap a   mEmpty = RFM mEmpty@@ -1305,24 +1247,14 @@   mAlter :: AlphaEnv -> Quantifiers -> Key RFMap -> A a -> RFMap a -> RFMap a   mAlter env vs lf f m = go (unLoc lf)     where-#if __GLASGOW_HASKELL__ < 904-      go (HsRecField _ lbl arg _pun) =-        m { rfmField = mAlter env vs (unLoc lbl) (toA (mAlter env vs arg f)) (rfmField m) }-#else       go (HsFieldBind _ lbl arg _pun) =         m { rfmField = mAlter env vs (unLoc (foLabel (unLoc lbl))) (toA (mAlter env vs arg f)) (rfmField m) }-#endif    mMatch :: MatchEnv -> Key RFMap -> (Substitution, RFMap a) -> [(Substitution, a)]   mMatch env lf (hs,m) = go (unLoc lf) (hs,m)     where-#if __GLASGOW_HASKELL__ < 904-      go (HsRecField _ lbl arg _pun) =-        mapFor rfmField >=> mMatch env (unLoc lbl) >=> mMatch env arg-#else       go (HsFieldBind _ lbl arg _pun) =         mapFor rfmField >=> mMatch env (unLoc (foLabel (unLoc lbl))) >=> mMatch env arg-#endif  -- Helper class to collapse the complex encoding of record fields into RdrNames. -- (The complexity is to support punning/duplicate/overlapping fields, which@@ -1330,59 +1262,33 @@ class RecordFieldToRdrName f where   recordFieldToRdrName :: f -> RdrName +#if __GLASGOW_HASKELL__ < 912 instance RecordFieldToRdrName (AmbiguousFieldOcc GhcPs) where #if __GLASGOW_HASKELL__ < 908   recordFieldToRdrName = rdrNameAmbiguousFieldOcc #else   recordFieldToRdrName = ambiguousFieldOccRdrName #endif+#endif -#if __GLASGOW_HASKELL__ < 904-instance RecordFieldToRdrName (FieldOcc p) where-  recordFieldToRdrName = unLoc . rdrNameFieldOcc-#else instance RecordFieldToRdrName (FieldOcc GhcPs) where   recordFieldToRdrName = unLoc . foLabel-#endif  instance RecordFieldToRdrName (FieldLabelStrings GhcPs) where-  recordFieldToRdrName = error "TBD"+  recordFieldToRdrName =+    error "recordFieldToRdrName FieldLabelStrings: unimplemented" -#if __GLASGOW_HASKELL__ < 904--- Either [LHsRecUpdField GhcPs] [LHsRecUpdProj GhcPs]-fieldsToRdrNamesUpd-  :: Either [LHsRecUpdField GhcPs] [LHsRecUpdProj GhcPs]-  -> [LHsRecField' GhcPs RdrName (LHsExpr GhcPs)]-fieldsToRdrNamesUpd (Left fs) = map go fs-  where-    go (L l (HsRecField a (L l2 f) arg pun)) =-      L l (HsRecField a (L l2 (recordFieldToRdrName f)) arg pun)-fieldsToRdrNamesUpd (Right fs) = map go fs-  where-    go (L l (HsRecField a (L l2 f) arg pun)) =-      L l (HsRecField a (L l2 (recordFieldToRdrName f)) arg pun)-#elif __GLASGOW_HASKELL__ < 908+#if __GLASGOW_HASKELL__ < 912+#if __GLASGOW_HASKELL__ < 908 fieldsToRdrNamesUpd :: Either [LHsRecUpdField GhcPs] [LHsRecUpdProj GhcPs]   -> [LHsRecField GhcPs (LHsExpr GhcPs)]-fieldsToRdrNamesUpd (Left xs) = map go xs-  where-    go (L l (HsFieldBind a (L l2 f) arg pun)) =-      let lrdrName = case f of-            Unambiguous _ n -> n-            Ambiguous _ n -> n-            XAmbiguousFieldOcc{} -> error "XAmbiguousFieldOcc"-          f' = FieldOcc NoExtField lrdrName-       in L l (HsFieldBind a (L l2 f') arg pun)-fieldsToRdrNamesUpd (Right xs) = map go xs-  where-    go (L l (HsFieldBind a (L l2 _f) arg pun)) =-      let lrdrName = error "TBD" -- same as GHC 9.2-          f' = FieldOcc NoExtField lrdrName-       in L l (HsFieldBind a (L l2 f') arg pun)+fieldsToRdrNamesUpd (Left xs) = #else fieldsToRdrNamesUpd :: LHsRecUpdFields GhcPs   -> [LHsRecField GhcPs (LHsExpr GhcPs)]-fieldsToRdrNamesUpd (RegularRecUpdFields _ xs) = map go xs+fieldsToRdrNamesUpd (RegularRecUpdFields _ xs) =+#endif+  map go xs   where     go (L l (HsFieldBind a (L l2 f) arg pun)) =       let lrdrName = case f of@@ -1391,23 +1297,23 @@             XAmbiguousFieldOcc{} -> error "XAmbiguousFieldOcc"           f' = FieldOcc NoExtField lrdrName        in L l (HsFieldBind a (L l2 f') arg pun)-fieldsToRdrNamesUpd (OverloadedRecUpdFields _ xs) = map go xs+#if __GLASGOW_HASKELL__ < 908+fieldsToRdrNamesUpd (Right xs) =+#else+fieldsToRdrNamesUpd (OverloadedRecUpdFields _ xs) =+#endif+  map go xs   where     go (L l (HsFieldBind a (L l2 _f) arg pun)) =       let lrdrName = error "TBD" -- same as GHC 9.2           f' = FieldOcc NoExtField lrdrName        in L l (HsFieldBind a (L l2 f') arg pun)-#endif--#if __GLASGOW_HASKELL__ < 904-fieldsToRdrNames-  :: RecordFieldToRdrName f-  => [LHsRecField' GhcPs f arg]-  -> [LHsRecField' GhcPs RdrName arg]-fieldsToRdrNames = map go-  where-    go (L l (HsRecField a (L l2 f) arg pun)) =-      L l (HsRecField a (L l2 (recordFieldToRdrName f)) arg pun)+#else+-- GHC 9.12+fieldsToRdrNamesUpd :: LHsRecUpdFields GhcPs+  -> [LHsRecField GhcPs (LHsExpr GhcPs)]+fieldsToRdrNamesUpd RegularRecUpdFields{..} = recUpdFields+fieldsToRdrNamesUpd OverloadedRecUpdFields{} = error "fieldsToRdrNamesUpd: OverloadedRecUpdFields unsupported!" #endif  ------------------------------------------------------------------------@@ -1496,8 +1402,6 @@     where       env' = extendMatchEnv env [v] -#if __GLASGOW_HASKELL__ < 810-#else newtype ForallVisMap a = ForallVisMap { favBoolMap :: BoolMap a }   deriving (Functor) @@ -1515,4 +1419,3 @@    mMatch :: MatchEnv -> Key ForallVisMap -> (Substitution, ForallVisMap a) -> [(Substitution, a)]   mMatch env b = mapFor favBoolMap >=> mMatch env b-#endif
Retrie/Pretty.hs view
@@ -1,9 +1,9 @@--- Copyright (c) Facebook, Inc. and its affiliates.+-- Copyright (c) 2025 Andrew Farmer+-- Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. -- -- This source code is licensed under the MIT license found in the -- LICENSE file in the root directory of this source tree. ---{-# LANGUAGE CPP #-} module Retrie.Pretty   ( noColor   , addColor@@ -38,11 +38,7 @@ ppSrcSpan :: ColoriseFun -> SrcSpan -> String ppSrcSpan colorise spn = case srcSpanStart spn of   UnhelpfulLoc x -> unpackFS x-#if __GLASGOW_HASKELL__ < 900-  RealSrcLoc loc -> intercalate (colorise Dull Cyan ":")-#else   RealSrcLoc loc _ -> intercalate (colorise Dull Cyan ":")-#endif     [ colorise Dull Magenta $ unpackFS $ srcLocFile loc     , colorise Dull Green $ show $ srcLocLine loc     , colorise Dull Green $ show $ srcLocCol loc
Retrie/Quantifiers.hs view
@@ -1,4 +1,5 @@--- Copyright (c) Facebook, Inc. and its affiliates.+-- Copyright (c) 2025 Andrew Farmer+-- Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. -- -- This source code is licensed under the MIT license found in the -- LICENSE file in the root directory of this source tree.
Retrie/Query.hs view
@@ -1,4 +1,5 @@--- Copyright (c) Facebook, Inc. and its affiliates.+-- Copyright (c) 2025 Andrew Farmer+-- Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. -- -- This source code is licensed under the MIT license found in the -- LICENSE file in the root directory of this source tree.
Retrie/Replace.hs view
@@ -1,4 +1,5 @@--- Copyright (c) Facebook, Inc. and its affiliates.+-- Copyright (c) 2025 Andrew Farmer+-- Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. -- -- This source code is licensed under the MIT license found in the -- LICENSE file in the root directory of this source tree.@@ -16,6 +17,7 @@ import Control.Monad.Trans.Class import Control.Monad.Writer.Strict import Data.Char (isSpace)+import Data.List (intercalate, isSuffixOf) import Data.Generics  import Retrie.ExactPrint@@ -25,7 +27,6 @@ import Retrie.Subst import Retrie.Types import Retrie.Universe-import Retrie.Util  ------------------------------------------------------------------------ @@ -80,19 +81,16 @@       t' <- graftA tTemplate       -- substitute for quantifiers in grafted template       r <- subst sub c t'-      -- copy appropriate annotations from old expression to template-      r0 <- addAllAnnsT e r       -- add parens to template if needed-      res' <- (mkM (parenify c) `extM` parenifyT c `extM` parenifyP c) r0-      -- Make sure the replacement has the same anchor as the thing-      -- being replaced-      let res = transferAnchor e res'--      -- prune the resulting expression and log it with location-      orig <- printNoLeadingSpaces <$> pruneA e-      -- orig <- printA' <$> pruneA e+      r' <- (mkM (parenify c) `extM` parenifyT c `extM` parenifyP c) r+      -- copy appropriate annotations from old expression to template+      res <- transferEntryAnnsT e r' -      repl <- printNoLeadingSpaces <$> pruneA res+      -- 'getLocA' excludes e's trailing anns and comments, so strip+      -- them from the original. print the template without its trailing+      -- anns+      orig <- printNoLeadingSpaces <$> pruneA (stripOuterAnns e)+      repl <- reindentAt (getLocA e) <$> pruneA r'       -- repl <- printA' <$> pruneA r       -- repl <- printA' <$> pruneA res       -- repl <- return $ showAst t'@@ -102,14 +100,14 @@        -- lift $ liftIO $ debugPrint Loud "replaceImpl:e="  [showAst e]       -- lift $ liftIO $ debugPrint Loud "replaceImpl:r="  [showAst r]-      -- lift $ liftIO $ debugPrint Loud "replaceImpl:r0="  [showAst r0]+      -- lift $ liftIO $ debugPrint Loud "replaceImpl:r'="  [showAst r']       -- lift $ liftIO $ debugPrint Loud "replaceImpl:t'=" [showAst t']       -- lift $ liftIO $ debugPrint Loud "replaceImpl:res=" [showAst res]        let replacement = Replacement (getLocA e) orig repl       TransformT $ lift $ tell $ Change [replacement] [tImports]       -- make the actual replacement-      return res'+      return res   -- | Records a replacement made. In cases where we cannot use ghc-exactprint@@ -126,14 +124,13 @@ data Change = NoChange | Change [Replacement] [AnnotatedImports]  instance Semigroup Change where-  (<>) = mappend+  NoChange         <> other            = other+  other            <> NoChange         = other+  (Change rs1 is1) <> (Change rs2 is2) =+    Change (rs1 <> rs2) (is1 <> is2)  instance Monoid Change where   mempty = NoChange-  mappend NoChange     other        = other-  mappend other        NoChange     = other-  mappend (Change rs1 is1) (Change rs2 is2) =-    Change (rs1 <> rs2) (is1 <> is2)  -- The location of 'e' accurately points to the first non-space character -- of 'e', but when we exactprint 'e', we might get some leading spaces (if@@ -144,3 +141,21 @@ -- drop leading spaces like this. printNoLeadingSpaces :: (Data k, ExactPrint k) => Annotated k -> String printNoLeadingSpaces = dropWhile isSpace . printA++-- | Print a replacement that will be spliced in as text starting at the given+-- location. Continuation lines are shifted by however far the first token+-- moves, so they keep their position relative to it (and thus any layout+-- blocks opened on the first line stay aligned).+reindentAt :: (Data k, ExactPrint k) => SrcSpan -> Annotated k -> String+reindentAt loc a = case (lines rest, srcSpanStartCol <$> getRealSpan loc) of+  (l:ls, Just c1) | shift <- c1 - s, shift /= 0 ->+    intercalate "\n" (l : map (reindent shift) ls) ++ trailingNl+  _ -> rest+  where+    (lead, rest) = span isSpace (printA a)+    s = 1 + length (takeWhile (/= '\n') (reverse lead))+    trailingNl = if "\n" `isSuffixOf` rest then "\n" else ""+    reindent n ln+      | all isSpace ln = ln+      | n > 0 = replicate n ' ' ++ ln+      | otherwise = drop (min (negate n) (length (takeWhile (== ' ') ln))) ln
Retrie/Rewrites.hs view
@@ -1,10 +1,10 @@ {-# LANGUAGE RecordWildCards #-}--- Copyright (c) Facebook, Inc. and its affiliates.+-- Copyright (c) 2025 Andrew Farmer+-- Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. -- -- This source code is licensed under the MIT license found in the -- LICENSE file in the root directory of this source tree. ---{-# LANGUAGE CPP #-} {-# LANGUAGE OverloadedStrings #-} module Retrie.Rewrites   ( RewriteSpec(..)@@ -17,7 +17,6 @@ import Control.Exception import qualified Data.Map as Map import Data.Maybe-import Data.Data hiding (Fixity) import qualified Data.Text as Text import Data.Traversable import System.FilePath@@ -25,18 +24,13 @@ import Retrie.CPP import Retrie.ExactPrint import Retrie.Fixity-#if __GLASGOW_HASKELL__ < 904 import Retrie.GHC-#else-import Retrie.GHC hiding (Pattern)-#endif import Retrie.Rewrites.Function import Retrie.Rewrites.Patterns import Retrie.Rewrites.Rules import Retrie.Rewrites.Types import Retrie.Types import Retrie.Universe-import Retrie.Util  -- | A qualified name. (e.g. @"Module.Name.functionName"@) type QualifiedName = String@@ -169,10 +163,6 @@       ]  -showCpp :: (Data ast, ExactPrint ast) => CPP (Annotated ast) -> String-showCpp (NoCPP c) = showAstA c-showCpp (CPP{}) = "CPP{}"- parseAdhocTypes :: LibDir -> FixityEnv -> [String] -> IO [Rewrite Universe] parseAdhocTypes _ _ [] = return [] parseAdhocTypes libdir fixities tySyns = do@@ -233,21 +223,13 @@   -> FileBasedTy   -> [(FastString, Direction)]   -> AnnotatedModule-#if __GLASGOW_HASKELL__ < 900-  -> IO (UniqFM [Rewrite Universe])-#else   -> IO (UniqFM FastString [Rewrite Universe])-#endif tyBuilder libdir FoldUnfold specs am = promote <$> dfnsToRewrites libdir specs am tyBuilder _libdir Rule specs am = promote <$> rulesToRewrites specs am tyBuilder _libdir Type specs am = promote <$> typeSynonymsToRewrites specs am tyBuilder libdir Pattern specs am = patternSynonymsToRewrites libdir specs am -#if __GLASGOW_HASKELL__ < 900-promote :: Matchable a => UniqFM [Rewrite a] -> UniqFM [Rewrite Universe]-#else promote :: Matchable a => UniqFM k [Rewrite a] -> UniqFM k [Rewrite Universe]-#endif promote = fmap (map toURewrite)  parseQualified :: String -> Either String (FilePath, FastString)
Retrie/Rewrites/Function.hs view
@@ -1,4 +1,5 @@--- Copyright (c) Facebook, Inc. and its affiliates.+-- Copyright (c) 2025 Andrew Farmer+-- Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. -- -- This source code is licensed under the MIT license found in the -- LICENSE file in the root directory of this source tree.@@ -22,7 +23,6 @@ import Retrie.GHC import Retrie.Quantifiers import Retrie.Types-import Retrie.Util  dfnsToRewrites   :: LibDir@@ -63,9 +63,8 @@   -> LMatch GhcPs (LHsExpr GhcPs)   -> TransformT IO [Rewrite (LHsExpr GhcPs)] matchToRewrites e imps dir (L _ alt) = do-  -- lift $ debugPrint Loud "matchToRewrites:e="  [showAst e]   let-    pats = m_pats alt+    pats = getMatchPats alt     grhss = m_grhss alt   qss <- for (zip (inits pats) (tails pats)) $     makeFunctionQuery e imps dir grhss mkApps@@ -81,15 +80,12 @@     go WildPat{} = True     go VarPat{} = True     go (LazyPat _ p) = irrefutablePat p-#if __GLASGOW_HASKELL__ <= 904-    go (AsPat _ _ p) = irrefutablePat p-#else+#if __GLASGOW_HASKELL__ < 912     go (AsPat _ _ _ p) = irrefutablePat p-#endif-#if __GLASGOW_HASKELL__ < 904-    go (ParPat _ p) = irrefutablePat p-#else     go (ParPat _ _ p _) = irrefutablePat p+#else+    go (AsPat _ _ p) = irrefutablePat p+    go (ParPat _ p) = irrefutablePat p #endif     go (BangPat _ p) = irrefutablePat p     go _ = False@@ -106,13 +102,14 @@   | any (not . irrefutablePat) bndpats = return []   | otherwise = do     let-      GRHSs _ rhss lbs = grhss+      GRHSs _ _ lbs = grhss+      rhssList = grhssList grhss       bs = collectPatsBinders CollNoDictBinders argpats     -- See Note [Wildcards]     (es,(_,bs')) <- runStateT (mapM patToExpr argpats) (wildSupply bs, bs)     -- lift $ debugPrint Loud "makeFunctionQuery:e="  [showAst e]     lhs <- mkAppFn e es-    for rhss $ \ grhs -> do+    for rhssList $ \ grhs -> do       le <- mkLet lbs (grhsToExpr grhs)       rhs <- mkLams bndpats le       let@@ -131,21 +128,49 @@   -> GRHSs GhcPs (LHsExpr GhcPs)   -> [LPat GhcPs]   -> TransformT IO [Rewrite (LHsExpr GhcPs)]-backtickRules e imps dir@LeftToRight grhss ps@[p1, p2] = do+backtickRules e imps dir@LeftToRight grhss (p1:p2:rest) = do   let+#if __GLASGOW_HASKELL__ < 912+    na = noAnn+#else+    na = noExtField+#endif++    wrapOpApps op [] = pure op+    wrapOpApps op extra = do+      o <- mkParen op+      mkApps o extra+     both, left, right :: AppBuilder-    both op [l, r] = mkLocA (SameLine 1) (OpApp noAnn l op r)+    -- A function of arity greater than two used infix supplies its+    -- first two arguments via the operator and the rest by application.+    both op (l:r:extra) = do+      opApp <- mkLocA (SameLine 1) (OpApp na l op r)+      wrapOpApps opApp extra     both _ _ = fail "backtickRules - both: impossible!" -    left op [l] = mkLocA (SameLine 1) (SectionL noAnn l op)+    left op (l:extra) = do+      opSecL <- mkLocA (SameLine 1) (SectionL na l op)+      wrapOpApps opSecL extra     left _ _ = fail "backtickRules - left: impossible!" -    right op [r] = mkLocA (SameLine 1) (SectionR noAnn op r)+    right op (r:extra) = do+      opSecR <- mkLocA (SameLine 1) (SectionR na op r)+      wrapOpApps opSecR extra     right _ _ = fail "backtickRules - right: impossible!"-  qs <- makeFunctionQuery e imps dir grhss both (ps, [])-  qsl <- makeFunctionQuery e imps dir grhss left ([p1], [p2])-  qsr <- makeFunctionQuery e imps dir grhss right ([p2], [p1])-  return $ qs ++ qsl ++ qsr++    splits r = for (zip (inits r) (tails r))++  -- (p1 `op` p2) rest+  qss <- splits rest $ \(ri, rt) ->+    makeFunctionQuery e imps dir grhss both (p1 : p2 : ri, rt)+  -- (p1 `op`) p2 rest+  qsl <- splits (p2:rest) $ \(ri, rt) ->+    makeFunctionQuery e imps dir grhss left (p1 : ri, rt)+  -- (`op` p2) p1 rest+  qsr <- splits (p1:rest) $ \(ri, rt) ->+    makeFunctionQuery e imps dir grhss right (p2 : ri, rt)+  return $ concat qss ++ concat qsl ++ concat qsr backtickRules _ _ _ _ _ = return []  -- Note [fold only]
Retrie/Rewrites/Patterns.hs view
@@ -1,4 +1,5 @@--- Copyright (c) Facebook, Inc. and its affiliates.+-- Copyright (c) 2025 Andrew Farmer+-- Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. -- -- This source code is licensed under the MIT license found in the -- LICENSE file in the root directory of this source tree.@@ -9,11 +10,13 @@ {-# LANGUAGE RecordWildCards #-} module Retrie.Rewrites.Patterns (patternSynonymsToRewrites) where -import Control.Monad.State (StateT(runStateT), lift)+import Control.Monad.State (StateT(runStateT)) import Control.Monad import Control.Monad.IO.Class import Data.Maybe+#if __GLASGOW_HASKELL__ < 914 import Data.Void+#endif  import Retrie.ExactPrint import Retrie.Expr@@ -50,7 +53,11 @@   :: Direction   -> AnnotatedImports   -> LocatedN RdrName+#if __GLASGOW_HASKELL__ < 914   -> HsConDetails Void (LocatedN RdrName) [RecordPatSynField GhcPs]+#else+  -> HsConDetails (LocatedN RdrName) [RecordPatSynField GhcPs]+#endif   -> LPat GhcPs   -> TransformT IO (Rewrite (LPat GhcPs)) mkPatRewrite dir imports patName params rhs = do@@ -76,6 +83,7 @@       = (L l (ConPat x (setEntryDP nm dp) args))     setEntryDPTunderConPatIn p _ = p +#if __GLASGOW_HASKELL__ < 914 asPat   :: Monad m   => LocatedN RdrName@@ -86,43 +94,55 @@   mkConPatIn patName params'   where -#if __GLASGOW_HASKELL__ <= 904-    convertTyVars :: (Monad m) => [Void] -> TransformT m [HsPatSigType GhcPs]-#else     convertTyVars :: (Monad m) => [Void] -> TransformT m [HsConPatTyArg GhcPs]-#endif     convertTyVars _ = return []+#else+asPat+  :: Monad m+  => LocatedN RdrName+  -> HsConDetails (LocatedN RdrName) [RecordPatSynField GhcPs]+  -> TransformT m (LPat GhcPs)+asPat patName params = do+  params' <- bitraverseHsConDetails mkVarPat convertFields params+  mkConPatIn patName params'+  where+#endif      convertFields :: (Monad m) => [RecordPatSynField GhcPs]                       -> TransformT m (HsRecFields GhcPs (LPat GhcPs))     convertFields fields =+#if __GLASGOW_HASKELL__ < 912       HsRecFields <$> traverse convertField fields <*> pure Nothing+#else+      HsRecFields noExtField <$> traverse convertField fields <*> pure Nothing+#endif      convertField :: (Monad m) => RecordPatSynField GhcPs                       -> TransformT m (LHsRecField GhcPs (LPat GhcPs))     convertField RecordPatSynField{..} = do-#if __GLASGOW_HASKELL__ < 904-      hsRecFieldLbl <- mkLoc $ recordPatSynField-      hsRecFieldArg <- mkVarPat recordPatSynPatVar-      let hsRecPun = False-      let hsRecFieldAnn = noAnn-      mkLocA (SameLine 0) HsRecField{..}-#else+#if __GLASGOW_HASKELL__ < 912       s <- uniqueSrcSpanT       an <- mkEpAnn (SameLine 0) NoEpAnns       let srcspan = SrcSpanAnn an s           hfbLHS = L srcspan recordPatSynField+#else+      an <- mkEpAnn (SameLine 0) noAnn+      let hfbLHS = L an recordPatSynField+#endif       hfbRHS <- mkVarPat recordPatSynPatVar       let hfbPun = False           hfbAnn = noAnn       mkLocA (SameLine 0) HsFieldBind{..}-#endif  mkExpRewrite   :: Direction   -> AnnotatedImports   -> LocatedN RdrName+#if __GLASGOW_HASKELL__ < 914   -> HsConDetails Void (LocatedN RdrName) [RecordPatSynField GhcPs]+#else+  -> HsConDetails (LocatedN RdrName) [RecordPatSynField GhcPs]+#endif   -> LPat GhcPs   -> HsPatSynDir GhcPs   -> TransformT IO [Rewrite (LHsExpr GhcPs)]@@ -130,7 +150,11 @@   fe <- mkLocatedHsVar patName   -- lift $ debugPrint Loud "mkExpRewrite:fe="  [showAst fe]   let altsFromParams = case params of+#if __GLASGOW_HASKELL__ < 914         PrefixCon _tyargs names -> buildMatch names rhs+#else+        PrefixCon names -> buildMatch names rhs+#endif         InfixCon a1 a2 -> buildMatch [a1, a2] rhs         RecCon{} -> missingSyntax "RecCon"   alts <- case patDir of@@ -148,5 +172,9 @@   pats <- traverse mkVarPat names   let bs = collectPatBinders CollNoDictBinders rhs   (rhsExpr,(_,_bs')) <- runStateT (patToExpr rhs) (wildSupply bs, bs)+#if __GLASGOW_HASKELL__ < 912   let alt = mkMatch PatSyn pats rhsExpr emptyLocalBinds+#else+  let alt = mkMatch PatSyn (noLocA pats) rhsExpr emptyLocalBinds+#endif   return [alt]
Retrie/Rewrites/Rules.hs view
@@ -1,9 +1,9 @@--- Copyright (c) Facebook, Inc. and its affiliates.+-- Copyright (c) 2025 Andrew Farmer+-- Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. -- -- This source code is licensed under the MIT license found in the -- LICENSE file in the root directory of this source tree. ---{-# LANGUAGE CPP #-} {-# LANGUAGE RecordWildCards #-} module Retrie.Rewrites.Rules (rulesToRewrites) where @@ -14,20 +14,11 @@ import Retrie.GHC import Retrie.Quantifiers import Retrie.Types-import Retrie.Util-import Retrie.Monad-import Control.Monad-import Control.Monad.IO.Class-import Control.Monad.Trans.Class  rulesToRewrites   :: [(FastString, Direction)]   -> AnnotatedModule-#if __GLASGOW_HASKELL__ < 900-  -> IO (UniqFM [Rewrite (LHsExpr GhcPs)])-#else   -> IO (UniqFM RuleName [Rewrite (LHsExpr GhcPs)])-#endif rulesToRewrites specs am = fmap astA $ transformA am $ \ m -> do   let     fsMap = uniqBag specs
Retrie/Rewrites/Types.hs view
@@ -1,4 +1,5 @@--- Copyright (c) Facebook, Inc. and its affiliates.+-- Copyright (c) 2025 Andrew Farmer+-- Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. -- -- This source code is licensed under the MIT license found in the -- LICENSE file in the root directory of this source tree.@@ -21,11 +22,7 @@ typeSynonymsToRewrites   :: [(FastString, Direction)]   -> AnnotatedModule-#if __GLASGOW_HASKELL__ < 900-  -> IO (UniqFM [Rewrite (LHsType GhcPs)])-#else   -> IO (UniqFM FastString [Rewrite (LHsType GhcPs)])-#endif typeSynonymsToRewrites specs am = fmap astA $ transformA am $ \ m -> do   let     fsMap = uniqBag specs
Retrie/Run.hs view
@@ -1,4 +1,5 @@--- Copyright (c) Facebook, Inc. and its affiliates.+-- Copyright (c) 2025 Andrew Farmer+-- Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. -- -- This source code is licensed under the MIT license found in the -- LICENSE file in the root directory of this source tree.@@ -19,7 +20,6 @@   ) where  import Control.Monad-import Control.Monad.State.Strict import Data.Char import Data.List import Data.Monoid
Retrie/SYB.hs view
@@ -1,4 +1,5 @@--- Copyright (c) Facebook, Inc. and its affiliates.+-- Copyright (c) 2025 Andrew Farmer+-- Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. -- -- This source code is licensed under the MIT license found in the -- LICENSE file in the root directory of this source tree.@@ -19,7 +20,7 @@   ) where  import Control.Monad-import Data.Generics hiding (Fixity(..))+import Data.Generics hiding (Fixity(..), ext2)  -- | Monadic rewrite with context type GenericMC m c = forall a. Data a => c -> a -> m a
Retrie/Subst.hs view
@@ -1,4 +1,5 @@--- Copyright (c) Facebook, Inc. and its affiliates.+-- Copyright (c) 2025 Andrew Farmer+-- Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. -- -- This source code is licensed under the MIT license found in the -- LICENSE file in the root directory of this source tree.@@ -17,7 +18,6 @@ import Retrie.Substitution import Retrie.SYB import Retrie.Types-import Retrie.Util  ------------------------------------------------------------------------ @@ -56,15 +56,12 @@       -- lift $ liftIO $ debugPrint Loud "substExpr:HoleExpr:e" [showAst e]       -- lift $ liftIO $ debugPrint Loud "substExpr:HoleExpr:eA" [showAst eA]       e0 <- graftA (unparen <$> eA)-      let comments = hasComments e0-      -- unless comments $ transferEntryDPT e e'-      e1 <- if comments-               then return e0-               else transferEntryDP e e0-      e2 <- transferAnnsT isComma e e1-      -- let e'' = setEntryDP e' (SameLine 1)-      -- lift $ liftIO $ debugPrint Loud "substExpr:HoleExpr:e2" [showAst e2]-      parenify ctxt e2+      -- copy over the template hole's entry delta and transfer any+      -- annotations such as trailing commas. we should only ever take the+      -- trailing annotations from the template, rather than whatever was+      -- attached to the expression in its previous location.+      e1 <- transferEntryAnnsT e e0+      parenify ctxt e1     Just (HoleRdr rdr) ->       return $ L l1 $ HsVar x $ L l2 rdr     _ -> return e@@ -81,7 +78,7 @@       -- lift $ liftIO $ debugPrint Loud "substPat:HolePat:p" [showAst p]       -- lift $ liftIO $ debugPrint Loud "substPat:HolePat:pA" [showAst pA]       p' <- graftA (unparenP <$> pA)-      p0 <- transferEntryAnnsT isComma p p'+      p0 <- transferEntryAnnsT p p'       -- the relevant entry delta is sometimes attached to       -- the OccName and not to the VarPat.       -- This seems to be the case only when the pattern comes from a lhs,@@ -104,7 +101,7 @@     -- lift $ liftIO $ debugPrint Loud "substType:HoleType:ty" [showAst ty]     -- lift $ liftIO $ debugPrint Loud "substType:HoleType:tyA" [showAst tyA]     ty' <- graftA (unparenT <$> tyA)-    ty0 <- transferEntryAnnsT isComma ty ty'+    ty0 <- transferEntryAnnsT ty ty'     parenifyT ctxt ty0 substType _ ty = return ty @@ -114,16 +111,19 @@ substHsMatchContext   :: Monad m   => Context-#if __GLASGOW_HASKELL__ < 900-  -> HsMatchContext RdrName-  -> TransformT m (HsMatchContext RdrName)-#else+#if __GLASGOW_HASKELL__ < 912   -> HsMatchContext GhcPs   -> TransformT m (HsMatchContext GhcPs)-#endif substHsMatchContext ctxt (FunRhs (L l v) f s)-  | Just (HoleRdr rdr) <- lookupHoleVar v ctxt =-    return $ FunRhs (L l rdr) f s+  | Just (HoleRdr rdr) <- lookupHoleVar v ctxt+  = return $ FunRhs (L l rdr) f s+#else+  -> HsMatchContext (LIdP GhcPs)+  -> TransformT m (HsMatchContext (LIdP GhcPs))+substHsMatchContext ctxt (FunRhs (L l v) f s _)+  | Just (HoleRdr rdr) <- lookupHoleVar v ctxt+  = return $ FunRhs (L l rdr) f s (AnnFunRhs NoEpTok [] [])+#endif substHsMatchContext _ other = return other  substBind
Retrie/Substitution.hs view
@@ -1,4 +1,5 @@--- Copyright (c) Facebook, Inc. and its affiliates.+-- Copyright (c) 2025 Andrew Farmer+-- Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. -- -- This source code is licensed under the MIT license found in the -- LICENSE file in the root directory of this source tree.
Retrie/Types.hs view
@@ -1,4 +1,5 @@--- Copyright (c) Facebook, Inc. and its affiliates.+-- Copyright (c) 2025 Andrew Farmer+-- Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. -- -- This source code is licensed under the MIT license found in the -- LICENSE file in the root directory of this source tree.@@ -91,7 +92,6 @@ data ParentPrec   = HasPrec Fixity -- ^ Parent has precedence info.   | IsLhs      -- ^ We are a pattern in a left-hand-side-  | IsHsAppsTy -- ^ Parent is HsAppsTy   | NeverParen -- ^ Based on parent, we should never add parentheses.  ------------------------------------------------------------------------@@ -130,11 +130,10 @@ -- See Note [AlphaEnv Offset] for details.  instance Semigroup (Matcher a) where-  (<>) = mappend+  (Matcher m1) <> (Matcher m2) = Matcher (I.unionWith mUnion m1 m2)  instance Monoid (Matcher a) where   mempty = Matcher I.empty-  mappend (Matcher m1) (Matcher m2) = Matcher (I.unionWith mUnion m1 m2)  -- | Compile a 'Query' into a 'Matcher'. mkMatcher :: Matchable ast => Query ast v -> Matcher v
Retrie/Universe.hs view
@@ -1,4 +1,5 @@--- Copyright (c) Facebook, Inc. and its affiliates.+-- Copyright (c) 2025 Andrew Farmer+-- Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. -- -- This source code is licensed under the MIT license found in the -- LICENSE file in the root directory of this source tree.
Retrie/Util.hs view
@@ -1,4 +1,5 @@--- Copyright (c) Facebook, Inc. and its affiliates.+-- Copyright (c) 2025 Andrew Farmer+-- Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. -- -- This source code is licensed under the MIT license found in the -- LICENSE file in the root directory of this source tree.@@ -106,6 +107,6 @@ missingSyntax :: String -> a missingSyntax constructor = error $ unlines   [ "Missing syntax support: " ++ constructor-  , "Please file an issue at https://github.com/facebookincubator/retrie/issues"+  , "Please file an issue at https://github.com/xich/retrie/issues"   , "with an example of the rewrite you are attempting and we'll add it."   ]
Setup.hs view
@@ -1,4 +1,5 @@--- Copyright (c) Facebook, Inc. and its affiliates.+-- Copyright (c) 2025 Andrew Farmer+-- Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. -- -- This source code is licensed under the MIT license found in the -- LICENSE file in the root directory of this source tree.
bin/Main.hs view
@@ -1,4 +1,5 @@--- Copyright (c) Facebook, Inc. and its affiliates.+-- Copyright (c) 2025 Andrew Farmer+-- Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. -- -- This source code is licensed under the MIT license found in the -- LICENSE file in the root directory of this source tree.
demo/Main.hs view
@@ -1,4 +1,5 @@--- Copyright (c) Facebook, Inc. and its affiliates.+-- Copyright (c) 2025 Andrew Farmer+-- Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. -- -- This source code is licensed under the MIT license found in the -- LICENSE file in the root directory of this source tree.
hse/Fixity.hs view
@@ -1,4 +1,5 @@--- Copyright (c) Facebook, Inc. and its affiliates.+-- Copyright (c) 2025 Andrew Farmer+-- Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. -- -- This source code is licensed under the MIT license found in the -- LICENSE file in the root directory of this source tree.@@ -33,8 +34,10 @@ hseToGHC (HSE.Fixity assoc p nm) = #if __GLASGOW_HASKELL__ < 908   (fs, (fs, Fixity (SourceText nm') p (dir assoc)))-#else+#elif __GLASGOW_HASKELL__ < 912   (fs, (fs, Fixity (SourceText (fsLit nm')) p (dir assoc)))+#else+  (fs, (fs, Fixity p (dir assoc))) #endif    where
retrie.cabal view
@@ -1,29 +1,31 @@--- Copyright (c) Facebook, Inc. and its affiliates.+-- Copyright (c) 2025 Andrew Farmer+-- Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. -- -- This source code is licensed under the MIT license found in the -- LICENSE file in the root directory of this source tree. -- name: retrie-version: 1.2.3+version: 2.0.0 synopsis: A powerful, easy-to-use codemodding tool for Haskell.-homepage: https://github.com/facebookincubator/retrie-bug-reports: https://github.com/facebookincubator/retrie/issues+homepage: https://github.com/xich/retrie+bug-reports: https://github.com/xich/retrie/issues license: MIT license-file: LICENSE-author: Andrew Farmer <anfarmer@fb.com>-maintainer: Andrew Farmer <anfarmer@fb.com>-copyright: Copyright (c) Facebook, Inc. and its affiliates.+author: Andrew Farmer <andrew@andrewfarmer.name>+maintainer: Andrew Farmer <andrew@andrewfarmer.name>+copyright:+  Copyright (c) 2025 Andrew Farmer+  Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. category: Development build-type: Simple cabal-version: >=1.10 extra-source-files:   CHANGELOG.md-  CODE_OF_CONDUCT.md   CONTRIBUTING.md   README.md   tests/inputs/*.custom   tests/inputs/*.test-tested-with: GHC ==9.2.1, GHC ==9.4.1, GHC ==9.6.1, GHC ==9.8.1+tested-with: GHC ==9.6.7, GHC ==9.8.4, GHC ==9.12.4, GHC ==9.14.1  description:   Retrie is a tool for codemodding Haskell. Key goals include:@@ -74,17 +76,20 @@     Retrie.Universe,     Retrie.Util   GHC-Options: -Wall+  if flag(Werror)+    GHC-Options: -Werror+  if impl(ghc >= 9.10)+    GHC-Options: -Wno-incomplete-record-selectors   build-depends:-    ansi-terminal >= 0.10.3 && < 1.1,+    ansi-terminal >= 0.10.3 && < 1.2,     async >= 2.2.2 && < 2.3,-    base >= 4.11 && < 4.20,+    base >= 4.11 && < 4.23,     bytestring >= 0.10.8 && < 0.13,-    containers >= 0.5.11 && < 0.8,-    data-default >= 0.7.1 && < 0.8,+    containers >= 0.5.11 && < 0.9,+    data-default >= 0.7.1 && < 0.9,     directory >= 1.3.1 && < 1.4,     filepath >= 1.4.2 && < 1.6,-    ghc >= 9.2 && < 9.9,-    ghc-exactprint >= 1.5.0 && < 1.9,+    ghc >= 9.6 && < 9.9 || >= 9.12 && < 9.13 || >= 9.14 && < 9.15,     list-t >= 1.0.4 && < 1.1,     mtl >= 2.2.2 && < 2.4,     optparse-applicative >= 0.15.1 && < 0.19,@@ -94,12 +99,26 @@     text >= 1.2.3 && < 2.2,     transformers >= 0.5.5 && < 0.7,     unordered-containers >= 0.2.10 && < 0.3+  -- Each ghc-exactprint major series only builds against one GHC series.+  if impl(ghc >= 9.14 && < 9.15)+    build-depends: ghc-exactprint >= 1.14.2 && < 1.15+  if impl(ghc >= 9.12 && < 9.13)+    build-depends: ghc-exactprint >= 1.12.1 && < 1.13+  if impl(ghc < 9.12)+    build-depends: ghc-exactprint >= 1.7.1 && < 1.12   default-language: Haskell2010  Flag BuildExecutable   Description: build the retrie executable   Default: True +-- Off by default because Hackage rejects packages that build with -Werror+-- unconditionally. cabal.project turns it on for development and CI.+Flag Werror+  Description: build with -Werror+  Default: False+  Manual: True+ executable retrie   if flag(BuildExecutable)     Buildable: True@@ -109,11 +128,13 @@     Main.hs   hs-source-dirs: bin hse   other-modules: Fixity-  GHC-Options: -Wall+  GHC-Options: -Wall -threaded+  if flag(Werror)+    GHC-Options: -Werror   build-depends:     retrie,-    base >= 4.11 && < 4.20,-    haskell-src-exts >= 1.23.0 && < 1.24,+    base >= 4.11 && < 4.23,+    haskell-src-exts >= 1.23.0 && < 1.25,     ghc-paths   default-language: Haskell2010 @@ -126,11 +147,13 @@     Main.hs   hs-source-dirs: demo hse   other-modules: Fixity-  GHC-Options: -Wall+  GHC-Options: -Wall -threaded+  if flag(Werror)+    GHC-Options: -Werror   build-depends:     retrie,-    base >= 4.11 && < 4.20,-    haskell-src-exts >= 1.23.0 && < 1.24,+    base >= 4.11 && < 4.23,+    haskell-src-exts >= 1.23.0 && < 1.25,     ghc-paths   default-language: Haskell2010 @@ -173,11 +196,10 @@     process,     syb,     tasty,-    tasty-hunit,     temporary,     text,     unordered-containers  source-repository head   type:     git-  location: https://github.com/facebookincubator/retrie+  location: https://github.com/xich/retrie
tests/AllTests.hs view
@@ -1,4 +1,5 @@--- Copyright (c) Facebook, Inc. and its affiliates.+-- Copyright (c) 2025 Andrew Farmer+-- Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. -- -- This source code is licensed under the MIT license found in the -- LICENSE file in the root directory of this source tree.@@ -44,6 +45,12 @@       [ TestLabel rtName $ TestCase $ runTest libdir p RetrieTest{..}       | testFile <- testFiles       , takeExtension testFile == ".test"+#if __GLASGOW_HASKELL__ < 908+      -- The TypeAbstractions pragma is unknown to the GHC 9.6 parser, so+      -- retrie cannot parse this test's target module there. The pre-9.14+      -- code path it exercises is still covered by the 9.8/9.12 runs.+      , testFile /= "TypeAbs.test"+#endif       , let           rtName = dropExtension testFile           rtTest = testFile
tests/Annotated.hs view
@@ -1,9 +1,9 @@--- Copyright (c) Facebook, Inc. and its affiliates.+-- Copyright (c) 2025 Andrew Farmer+-- Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. -- -- This source code is licensed under the MIT license found in the -- LICENSE file in the root directory of this source tree. ---{-# LANGUAGE CPP #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-} module Annotated (annotatedTest) where@@ -16,9 +16,7 @@ -- import Data.Maybe import qualified GHC.Paths as GHC.Paths import Test.HUnit-#if MIN_VERSION_mtl(2, 3, 0) import Control.Monad ((>=>))-#endif  import Retrie.ExactPrint import Retrie.GHC@@ -203,11 +201,7 @@ -- assertExactPrintAnns :: Anns -> Anns -> IO () -- assertExactPrintAnns annsPreGraft annsPostGraft = --   forM_ newKeys $ \(AnnKey ss _) ->--- #if __GLASGOW_HASKELL__ < 900---     assertGoodSrcSpan ss--- #else --     assertGoodRealSrcSpan ss--- #endif --   where --     newKeys :: S.Set AnnKey --     newKeys = M.keysSet annsPostGraft `S.difference` M.keysSet annsPreGraft
tests/CPP.hs view
@@ -1,4 +1,5 @@--- Copyright (c) Facebook, Inc. and its affiliates.+-- Copyright (c) 2025 Andrew Farmer+-- Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. -- -- This source code is licensed under the MIT license found in the -- LICENSE file in the root directory of this source tree.
tests/Demo.hs view
@@ -1,4 +1,5 @@--- Copyright (c) Facebook, Inc. and its affiliates.+-- Copyright (c) 2025 Andrew Farmer+-- Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. -- -- This source code is licensed under the MIT license found in the -- LICENSE file in the root directory of this source tree.
tests/Dependent.hs view
@@ -1,4 +1,5 @@--- Copyright (c) Facebook, Inc. and its affiliates.+-- Copyright (c) 2025 Andrew Farmer+-- Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. -- -- This source code is licensed under the MIT license found in the -- LICENSE file in the root directory of this source tree.
tests/Exclude.hs view
@@ -1,4 +1,5 @@--- Copyright (c) Facebook, Inc. and its affiliates.+-- Copyright (c) 2025 Andrew Farmer+-- Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. -- -- This source code is licensed under the MIT license found in the -- LICENSE file in the root directory of this source tree.@@ -30,7 +31,7 @@ excludeTest :: Verbosity -> Test excludeTest v = TestLabel "exclude path prefixes" $   TestCase $ do-    withFakeHgRepo [] allFiles $ \dir -> do+    withFakeGitRepo [] allFiles $ \dir -> do       let opts = optionsWithDefaultFixities $ optionsWithExtraIgnores dir v       filepaths <- getTargetFiles opts []       assertBool (unlines ["Expected ", show excludedPaths,
tests/Golden.hs view
@@ -1,4 +1,5 @@--- Copyright (c) Facebook, Inc. and its affiliates.+-- Copyright (c) 2025 Andrew Farmer+-- Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. -- -- This source code is licensed under the MIT license found in the -- LICENSE file in the root directory of this source tree.
tests/GroundTerms.hs view
@@ -1,4 +1,5 @@--- Copyright (c) Facebook, Inc. and its affiliates.+-- Copyright (c) 2025 Andrew Farmer+-- Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. -- -- This source code is licensed under the MIT license found in the -- LICENSE file in the root directory of this source tree.
tests/Ignore.hs view
@@ -1,4 +1,5 @@--- Copyright (c) Facebook, Inc. and its affiliates.+-- Copyright (c) 2025 Andrew Farmer+-- Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. -- -- This source code is licensed under the MIT license found in the -- LICENSE file in the root directory of this source tree.
tests/Main.hs view
@@ -1,22 +1,38 @@--- Copyright (c) Facebook, Inc. and its affiliates.+-- Copyright (c) 2025 Andrew Farmer+-- Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. -- -- This source code is licensed under the MIT license found in the -- LICENSE file in the root directory of this source tree. -- module Main (main) where +import Control.Exception import Test.HUnit import Test.Tasty-import Test.Tasty.HUnit+import Test.Tasty.Providers+import Test.Tasty.Runners (Result(..))  import qualified GHC.Paths as GHC.Paths import Retrie import AllTests+import Util (SkipTest(..))  main :: IO () main = allTests GHC.Paths.libdir Silent >>= defaultMain . toTasty . TestLabel "retrie"  toTasty :: Test -> TestTree-toTasty (TestLabel lbl (TestCase io)) = testCase lbl io+toTasty (TestLabel lbl (TestCase io)) = singleTest lbl (SkippableCase io) toTasty (TestLabel lbl (TestList ts)) = testGroup lbl (map toTasty ts) toTasty t = error $ "toTasty: unlabeled test " ++ show t++-- | Like tasty-hunit's 'testCase', but a 'SkipTest' exception reports the test+-- as SKIPPED (which does not fail the run) instead of failing it.+newtype SkippableCase = SkippableCase Assertion++instance IsTest SkippableCase where+  run _ (SkippableCase io) _ = do+    r <- try io+    return $ case r of+      Left (SkipTest why) -> (testPassed why) { resultShortDescription = "SKIPPED" }+      Right () -> testPassed ""+  testOptions = return []
tests/ParseQualified.hs view
@@ -1,4 +1,5 @@--- Copyright (c) Facebook, Inc. and its affiliates.+-- Copyright (c) 2025 Andrew Farmer+-- Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. -- -- This source code is licensed under the MIT license found in the -- LICENSE file in the root directory of this source tree.
tests/Targets.hs view
@@ -1,4 +1,5 @@--- Copyright (c) Facebook, Inc. and its affiliates.+-- Copyright (c) 2025 Andrew Farmer+-- Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. -- -- This source code is licensed under the MIT license found in the -- LICENSE file in the root directory of this source tree.@@ -27,7 +28,7 @@     where       gts = [HashSet.fromList ["Groundterm"]]       targetFps = retrieTargetFiles-      -- 'withFakeHgRepo' creates every file with its own name as the contents+      -- 'withFakeGitRepo' creates every file with its own name as the contents       expectedFps = ["targeted" </> "Groundterm.hs"]  assertFileListEqual@@ -36,7 +37,7 @@   -> [FilePath]   -> Assertion assertFileListEqual expected gts targetFps =-  withFakeHgRepo [] allFiles $ \dir -> do+  withFakeGitRepo [] allFiles $ \dir -> do     let opts = optionsWithTargetFiles dir targetFps     filepaths <- getTargetFiles opts gts     assertPermutationOf "Targeted files should be all of those specified"
tests/Util.hs view
@@ -1,12 +1,15 @@--- Copyright (c) Facebook, Inc. and its affiliates.+-- Copyright (c) 2025 Andrew Farmer+-- Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. -- -- This source code is licensed under the MIT license found in the -- LICENSE file in the root directory of this source tree. -- module Util where +import Control.Exception import Control.Monad-import System.Directory (createDirectoryIfMissing)+import System.Directory (createDirectoryIfMissing, findExecutable)+import System.Environment (lookupEnv) import System.Exit import System.FilePath import System.IO.Temp@@ -39,7 +42,8 @@       writeFile filePath fp  withFakeHgRepo :: [FilePath] -> [FilePath] -> (FilePath -> IO ()) -> IO ()-withFakeHgRepo ignoredFiles allFiles f =+withFakeHgRepo ignoredFiles allFiles f = do+  requireExecutable "hg"   withFakeRepoCmds "hg init" ".hgignore" ignoredFiles allFiles $ \dir -> do     -- Tell 'hg' which ignore file to use for the repo, because Facebook's     -- 'hg' looks at .gitignore by default.@@ -50,7 +54,27 @@     f dir  withFakeGitRepo :: [FilePath] -> [FilePath] -> (FilePath -> IO ()) -> IO ()-withFakeGitRepo = withFakeRepoCmds "git init" ".gitignore"+withFakeGitRepo ignoredFiles allFiles f = do+  requireExecutable "git"+  withFakeRepoCmds "git init" ".gitignore" ignoredFiles allFiles f++-- | Thrown to mark a test as skipped rather than failed. See 'toTasty' in Main.+newtype SkipTest = SkipTest String+  deriving Show++instance Exception SkipTest++-- | Skip the test if the given executable is not on the PATH. On CI (where the+-- CI environment variable is set) every executable should be installed, so+-- fail instead.+requireExecutable :: String -> IO ()+requireExecutable exe = do+  found <- findExecutable exe+  onCI <- maybe False (not . null) <$> lookupEnv "CI"+  when (null found) $+    if onCI+      then assertFailure $ exe ++ " is not installed, but is required on CI"+      else throwIO $ SkipTest $ exe ++ " is not installed"  doOrDie :: FilePath -> String -> IO () doOrDie dir cmd = do
tests/inputs/Adhoc.test view
@@ -1,4 +1,5 @@-# Copyright (c) Facebook, Inc. and its affiliates.+# Copyright (c) 2025 Andrew Farmer+# Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree.
tests/inputs/Adhoc2.custom view
@@ -1,4 +1,5 @@-# Copyright (c) Facebook, Inc. and its affiliates.+# Copyright (c) 2025 Andrew Farmer+# Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree.
tests/inputs/Backticks.test view
@@ -1,4 +1,5 @@-# Copyright (c) Facebook, Inc. and its affiliates.+# Copyright (c) 2025 Andrew Farmer+# Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree.
tests/inputs/Backticks2.test view
@@ -1,4 +1,5 @@-# Copyright (c) Facebook, Inc. and its affiliates.+# Copyright (c) 2025 Andrew Farmer+# Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree.@@ -12,9 +13,9 @@ -  print $ foo `bar` [1..10] +  print $ foo + sum [1..10] -  print $ (foo `bar`) [1..10]-+  print $ (\ xs -> foo + sum xs) [1..10]++  print $ foo + sum [1..10] -  print $ (`bar` [1..10]) foo-+  print $ (\ x -> x + sum [1..10]) foo++  print $ foo + sum [1..10]    foo :: Int  foo = baz `div` quux 10
+ tests/inputs/Backticks3.test view
@@ -0,0 +1,45 @@+# Unfolding a function of arity greater than two used in backtick+# form.+-u Backticks3.bar -u Backticks3.quux+===+ module Backticks3 where++ main :: IO ()+ main = do+-  print $ (1 `bar` 2) 3++  print $ 1 + 2 * 3+-  print $ (foo `bar` 2) 4++  print $ foo + 2 * 4+-  print $ (foo `bar`) 2 5++  print $ foo + 2 * 5+-  print $ (`bar` 2) foo 6++  print $ foo + 2 * 6+-  print $ zipWith (foo `bar`) [7] [8]++  print $ zipWith (\ y z -> foo + y * z) [7] [8]+-  print $ zipWith (`bar` 2) [foo] [9]++  print $ zipWith (\ x z -> x + 2 * z) [foo] [9]+-  print $ map ((foo `bar`) 2) [10]++  print $ map (\ z -> foo + 2 * z) [10]+-  print $ map ((`bar` 2) foo) [11]++  print $ map (\ z -> foo + 2 * z) [11]+-  print $ map (foo `bar` 2) [12]++  print $ map (\ z -> foo + 2 * z) [12]+-  print $ foo `bar` 2 $ 13++  print $ (\ z -> foo + 2 * z) $ 13+-  print $ (foo `quux` 2) 3 14++  print $ foo + 2 * 3 - 14+-  print $ (foo `quux`) 2 3 15++  print $ foo + 2 * 3 - 15+-  print $ (`quux` 2) foo 3 16++  print $ foo + 2 * 3 - 16+-  print $ map ((foo `quux` 2) 3) [17]++  print $ map (\ d -> foo + 2 * 3 - d) [17]++ foo :: Int+ foo = 100++ bar :: Int -> Int -> Int -> Int+ bar x y z = x + y * z++ quux :: Int -> Int -> Int -> Int -> Int+ quux a b c d = a + b * c - d
tests/inputs/CPP.test view
@@ -1,24 +1,30 @@-# Copyright (c) Facebook, Inc. and its affiliates.+# Copyright (c) 2025 Andrew Farmer+# Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. # --adhoc "forall f g xs. map f (map g xs) = map (f . g) xs" -u CPP.otherthing+--adhoc "forall a b. a * b = mul a b"+--pattern-backward CPP.One+-u CPP.baz+-u CPP.baz2 ===  {-# LANGUAGE CPP #-}+ {-# LANGUAGE PatternSynonyms #-}  module CPP where- +  #define TRUE 1   infixr 0 $   main :: IO ()  main = print $ foo (bar [1..10])- +  foo :: Int -> Int  foo x = x - 2- +  #if TRUE  bar :: [Int] -> Int  bar ys = length (filter even zs)@@ -27,7 +33,28 @@ +    zs = map ((+1) . (*3)) ys  #endif + pattern One :: a -> [a]+ pattern One y = y : []+  #if TRUE+ fixityExpr :: Int -> Int -> Int -> Int+-fixityExpr x y w = x + y * w++fixityExpr x y w = x + mul y w++ fixityPat :: [Int] -> Int+-fixityPat (x : y : []) = x++fixityPat (x : One y) = x++ fixityExpr3 :: (Int -> Int) -> Int -> Int -> Int -> Int+-fixityExpr3 f p q z = f $ p + q * z++fixityExpr3 f p q z = f $ p + mul q z++ fixityPat3 :: [Int] -> Int+-fixityPat3 ( a  :   b    :     c      :       d        :         []) = a++fixityPat3 ( a  :   b    :     c      :       One d) = a+ #endif++ #if TRUE  bar2 :: [Int] -> Int  bar2 ys = length (filter even zs)    where@@ -48,14 +75,30 @@  useit :: Int -useit = otherthing (Just 54) +useit = case Just 54 of-+  Just{} -> 1-+  Nothing -> 0++         Just{} -> 1++         Nothing -> 0   #if TRUE  useit2 :: Int -useit2 = otherthing (Just 42) +useit2 = case Just 42 of-+  Just{} -> 1-+  Nothing -> 0++          Just{} -> 1++          Nothing -> 0  #endif  #endif++ anns :: IO ()+-anns = print [baz, pred baz, baz]++anns = print [succ 4, pred (succ 4), succ 4]++ baz :: Int+ baz = succ 4++ baz2 :: Int+ baz2 =+   -- one+   1++-comment = baz2++comment = -- one++          1
tests/inputs/CPPConflict.test view
@@ -1,4 +1,5 @@-# Copyright (c) Facebook, Inc. and its affiliates.+# Copyright (c) 2025 Andrew Farmer+# Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree.
+ tests/inputs/CPPLayout.test view
@@ -0,0 +1,39 @@+# Copyright (c) 2025 Andrew Farmer+#+# This source code is licensed under the MIT license found in the+# LICENSE file in the root directory of this source tree.+#+# https://github.com/xich/retrie/issues/24+# A multi-line replacement spliced in as text (CPP module) must have its+# continuation lines re-indented relative to the destination column, not+# the column of the template in its original definition.+-u CPPLayout.foo+-u CPPLayout.baz+===+ {-# LANGUAGE CPP #-}+ module CPPLayout where++ #define KEEP 1++ foo :: Int+ foo =+   succ+     1++ bar :: Int+ bar = x+   where+-    x = foo++    x = succ++          1++ baz :: IO ()+ baz = do print 1+          print 2++ qux :: IO ()+ qux = x+   where+-    x = baz++    x = do print 1++           print 2
tests/inputs/Capture.test view
@@ -1,4 +1,5 @@-# Copyright (c) Facebook, Inc. and its affiliates.+# Copyright (c) 2025 Andrew Farmer+# Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree.
tests/inputs/Combined.test view
@@ -1,4 +1,5 @@-# Copyright (c) Facebook, Inc. and its affiliates.+# Copyright (c) 2025 Andrew Farmer+# Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree.@@ -46,7 +47,7 @@    baz2 :: Int -baz2 = foo * bar-+baz2 = (3 + 4) * 5 * foo++baz2 = (3 + 4) * (5 `quot` foo)    quux :: Int -> Int -quux x = foo * x@@ -65,20 +66,20 @@  blerg :: Int -blerg = blarg 42 +blerg = (case 54 of-+    0 -> pred-+    _ -> succ) 42++          0 -> pred++          _ -> succ) 42    jank :: IO (Int -> Int) -jank = return blarg +jank = return (case 54 of-+    0 -> pred-+    _ -> succ)++                0 -> pred++                _ -> succ)    jenk :: IO Int -jenk = return $ blarg 42 +jenk = return $ (case 54 of-+    0 -> pred-+    _ -> succ) 42++                  0 -> pred++                  _ -> succ) 42   mneh :: Bool -mneh = 3 == 2
tests/inputs/Commas.test view
@@ -1,9 +1,13 @@-# Copyright (c) Facebook, Inc. and its affiliates.+# Copyright (c) 2025 Andrew Farmer+# Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. # -u Commas.foo+--adhoc "forall a b. f [a, b] = g [a, b]"+--adhoc "forall a b. h [a, b] = k a b"+--type-backward Commas.Pair ===  module Commas where  @@ -15,3 +19,26 @@    foo :: Int  foo = succ 4++ test2 :: IO ()+-test2 = print (f [succ 1, 2])++test2 = print (g [succ 1, 2])+ + test3 :: IO ()+-test3 = print (h [succ 1, 2])++test3 = print (k (succ 1) 2)++ type Pair a = (a, a)++-test4 :: (Maybe Int, Maybe Int)++test4 :: Pair (Maybe Int)+ test4 = (Nothing, Nothing)++ test5 :: IO ()+-test5 = print (h [succ 1 {- t -}, 2])++test5 = print (k (succ 1) 2)++ test6 :: IO ()+-test6 = print (h [ succ 1+-                 , 2 ])++test6 = print (k (succ 1) 2)
tests/inputs/Comments.test view
@@ -1,4 +1,5 @@-# Copyright (c) Facebook, Inc. and its affiliates.+# Copyright (c) 2025 Andrew Farmer+# Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree.@@ -7,12 +8,15 @@ -l Comments.swap  -l Comments.convt  -u Comments.oldFunc+-l Comments.tmpl+-u Comments.idFunc ===  module Comments where    {-# RULES "old" forall x. oldfunc x = newfunc x #-}  {-# RULES "swap" forall x y. swapFunc x y = newSwapFunc y x #-}  {-# RULES "convt" a = alpha #-}+ {-# RULES "tmpl" forall x. h x = k {- template comment -} x #-}    main1 :: IO ()  main1 =@@ -23,9 +27,9 @@  main2 :: IO ()  main2 = -   swapFunc-+   newSwapFunc arg2-      -- note: swap args and update+-     -- note: swap args and update -     arg1 arg2++   newSwapFunc arg2 -- note: swap args and update +     arg1    main3 :: IO ()@@ -54,3 +58,24 @@ +  -- more comment +    foo +  ]++-main5 = h 1++main5 = k {- template comment -} 1++ idFunc x = x++-main6 = idFunc -- note++main6 = -- note+   1++-main7 = idFunc {- c -} 2++main7 = {- c -} 2++-main8 = [3, {- d -} idFunc 4, 5]++main8 = [3, {- d -} 4, 5]++ main9 = [6,+   -- e+-  idFunc -- f++  -- f+     7]
tests/inputs/DependentStmt.custom view
@@ -1,4 +1,5 @@-# Copyright (c) Facebook, Inc. and its affiliates.+# Copyright (c) 2025 Andrew Farmer+# Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree.
+ tests/inputs/FixityAnnotations.test view
@@ -0,0 +1,26 @@+# Unfold foo to reprint the whole module. Fixity reassociation rotates+# x : y : zs and x + y * w. This test ensures the annotations, spacing and+# comments are untouched.+-u FixityAnnotations.foo+===+ module FixityAnnotations where++ f :: ([Int], Int) -> [Int]+ f ( x : y : zs, w) = [x + y * w, w]++ b :: ([Int], Int) -> [Int]+ b ({- a -} x : y : zs {- b -}, w) = [x + y * w, w]++ c :: ([Int], Int) -> [Int]+ c (x : y : zs+   , w) = [x + y * w, w]++ g :: [[Int]] -> Int+ g [x : y : zs, _] = x++ h :: Int+-h = foo++h = 1++ foo :: Int+ foo = 1
tests/inputs/Foo.test view
@@ -1,4 +1,5 @@-# Copyright (c) Facebook, Inc. and its affiliates.+# Copyright (c) 2025 Andrew Farmer+# Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree.
tests/inputs/FooFold.test view
@@ -1,4 +1,5 @@-# Copyright (c) Facebook, Inc. and its affiliates.+# Copyright (c) 2025 Andrew Farmer+# Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree.
tests/inputs/Imports.test view
@@ -1,4 +1,5 @@-# Copyright (c) Facebook, Inc. and its affiliates.+# Copyright (c) 2025 Andrew Farmer+# Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree.
tests/inputs/Iterate.test view
@@ -1,4 +1,5 @@-# Copyright (c) Facebook, Inc. and its affiliates.+# Copyright (c) 2025 Andrew Farmer+# Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree.
+ tests/inputs/Layout.test view
@@ -0,0 +1,33 @@+# Copyright (c) 2025 Andrew Farmer+#+# This source code is licensed under the MIT license found in the+# LICENSE file in the root directory of this source tree.+#+# Non-CPP counterpart of CPPLayout.test (issue #24): exactprint path.+-u Layout.foo+-u Layout.baz+===+ module Layout where++ foo :: Int+ foo =+   succ+     1++ bar :: Int+ bar = x+   where+-    x = foo++    x = succ++        1++ baz :: IO ()+ baz = do print 1+          print 2++ qux :: IO ()+ qux = x+   where+-    x = baz++    x = do print 1++           print 2
tests/inputs/MatchGroup.test view
@@ -1,4 +1,5 @@-# Copyright (c) Facebook, Inc. and its affiliates.+# Copyright (c) 2025 Andrew Farmer+# Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree.
tests/inputs/Operator.test view
@@ -1,4 +1,5 @@-# Copyright (c) Facebook, Inc. and its affiliates.+# Copyright (c) 2025 Andrew Farmer+# Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree.
tests/inputs/Parens.test view
@@ -1,4 +1,5 @@-# Copyright (c) Facebook, Inc. and its affiliates.+# Copyright (c) 2025 Andrew Farmer+# Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree.@@ -7,23 +8,33 @@ -u Parens.bar  -u Parens.quux  -u Parens.blarg+-u Parens.shl1+-u Parens.neg+-u Parens.two+-u Parens.mkR+--adhoc "forall a. a . id = a"+--type-forward Parens.Fn+--type-forward Parens.MaybeInt ===+ {-# LANGUAGE OverloadedRecordDot #-}  module Parens where  + import Data.Bits+   foo :: Int  foo = 3 + 4    bar :: Int--bar = 5 * foo-+bar = 5 * (3 + 4)+-bar = 5 `quot` foo++bar = 5 `quot` (3 + 4)    baz :: Int -baz = quux bar +baz = foo * bar    baz2 :: Int--baz2 = foo * bar-+baz2 = (3 + 4) * 5 * foo+-baz2 = foo `quot` bar++baz2 = (3 + 4) `quot` (5 `quot` foo)    quux :: Int -> Int -quux x = foo * x@@ -56,3 +67,96 @@ +jenk = return $ (case 54 of +    0 -> pred +    _ -> succ) 42+ + shl1 :: Int -> Int+ shl1 n = n `shiftL` 1+ + shl2 :: Int -> Int+-shl2 = (`shiftL` 2) . id++shl2 = (`shiftL` 2)+ + shl3 :: Int -> Int+-shl3 n = shl1 n `shiftL` 2++shl3 n = n `shiftL` 1 `shiftL` 2+ + shl4 :: Int -> Int+-shl4 n = n `shiftL` shl1 2++shl4 n = n `shiftL` (2 `shiftL` 1)+ + mixedDirs :: Int+-mixedDirs = shl1 3 ^ shl1 4++mixedDirs = (3 `shiftL` 1) ^ (4 `shiftL` 1)+ + sectL :: Int -> Int+-sectL = (foo +)++sectL = (3 + 4 +)+ + sectR :: Int -> Int+-sectR = (+ foo)++sectR = (+ (3 + 4))+ + neg :: Int+ neg = negate $ 1+ + sectLower :: [Int] -> [Int]+-sectLower = (neg :)++sectLower = ((negate $ 1) :)+ + two :: [Int]+ two = [1] ++ [2]+ + sectAssoc :: [Int] -> [Int]+-sectAssoc = (two ++)++sectAssoc = (([1] ++ [2]) ++)+ + -- a record update's head must be atomic+ data R = R { r1 :: Int, r2 :: Int }+ + mkR :: R+ mkR = let x = 1 in R x 2+ + updR :: R+-updR = mkR { r2 = 3 }++updR = (let x = 1 in R x 2) { r2 = 3 }++ -- a projection's head must be atomic+ proj :: Int+-proj = mkR.r1++proj = (let x = 1 in R x 2).r1++ -- prefix minus binds like an infix-6 operator+ negFoo :: Int+-negFoo = - foo++negFoo = - (3 + 4)++ negBar :: Int+-negBar = - bar++negBar = - 5 `quot` foo++ type Fn a b = a -> b+ type MaybeInt = Maybe Int+ +-($!) :: Fn (a -> b) (a -> b)++($!) :: (a -> b) -> a -> b+ f $! x = f (x)+ +-(&!) :: a -> Fn (a -> b) b++(&!) :: a -> (a -> b) -> b+ (&!) x f = (f) x+ +-konst :: b -> Fn a b++konst :: b -> a -> b+ konst x _ = x+ +-noop :: Fn a a++noop :: a -> a+ noop x = x+ +-idMaybeInt :: MaybeInt -> MaybeInt++idMaybeInt :: Maybe Int -> Maybe Int+ idMaybeInt x = x+ +-swapEither :: (Either MaybeInt Int) -> Either Int MaybeInt++swapEither :: (Either (Maybe Int) Int) -> Either Int (Maybe Int)+ swapEither (Left x) = Right x+ swapEither (Right x) = Left x
tests/inputs/PartialF.test view
@@ -1,4 +1,5 @@-# Copyright (c) Facebook, Inc. and its affiliates.+# Copyright (c) 2025 Andrew Farmer+# Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree.
tests/inputs/PartialU.test view
@@ -1,4 +1,5 @@-# Copyright (c) Facebook, Inc. and its affiliates.+# Copyright (c) 2025 Andrew Farmer+# Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree.
tests/inputs/PatBind.test view
@@ -1,4 +1,5 @@-# Copyright (c) Facebook, Inc. and its affiliates.+# Copyright (c) 2025 Andrew Farmer+# Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree.
tests/inputs/PatternSyn1.test view
@@ -1,4 +1,5 @@-# Copyright (c) Facebook, Inc. and its affiliates.+# Copyright (c) 2025 Andrew Farmer+# Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree.
tests/inputs/PatternSyn2.test view
@@ -1,4 +1,5 @@-# Copyright (c) Facebook, Inc. and its affiliates.+# Copyright (c) 2025 Andrew Farmer+# Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree.
tests/inputs/Qualified.test view
@@ -1,4 +1,5 @@-# Copyright (c) Facebook, Inc. and its affiliates.+# Copyright (c) 2025 Andrew Farmer+# Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree.
tests/inputs/Query.custom view
@@ -1,4 +1,5 @@-# Copyright (c) Facebook, Inc. and its affiliates.+# Copyright (c) 2025 Andrew Farmer+# Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree.
tests/inputs/Readme.custom view
@@ -1,4 +1,5 @@-# Copyright (c) Facebook, Inc. and its affiliates.+# Copyright (c) 2025 Andrew Farmer+# Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree.
tests/inputs/Readme1.test view
@@ -1,4 +1,5 @@-# Copyright (c) Facebook, Inc. and its affiliates.+# Copyright (c) 2025 Andrew Farmer+# Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree.
tests/inputs/Readme2.test view
@@ -1,4 +1,5 @@-# Copyright (c) Facebook, Inc. and its affiliates.+# Copyright (c) 2025 Andrew Farmer+# Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree.
tests/inputs/Readme3.test view
@@ -1,4 +1,5 @@-# Copyright (c) Facebook, Inc. and its affiliates.+# Copyright (c) 2025 Andrew Farmer+# Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree.
tests/inputs/Readme4.test view
@@ -1,4 +1,5 @@-# Copyright (c) Facebook, Inc. and its affiliates.+# Copyright (c) 2025 Andrew Farmer+# Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree.
tests/inputs/Readme5.test view
@@ -1,4 +1,5 @@-# Copyright (c) Facebook, Inc. and its affiliates.+# Copyright (c) 2025 Andrew Farmer+# Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree.
tests/inputs/Records.test view
@@ -1,4 +1,5 @@-# Copyright (c) Facebook, Inc. and its affiliates.+# Copyright (c) 2025 Andrew Farmer+# Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree.
tests/inputs/Records2.test view
@@ -1,4 +1,5 @@-# Copyright (c) Facebook, Inc. and its affiliates.+# Copyright (c) 2025 Andrew Farmer+# Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree.
tests/inputs/Recursion.test view
@@ -1,4 +1,5 @@-# Copyright (c) Facebook, Inc. and its affiliates.+# Copyright (c) 2025 Andrew Farmer+# Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree.
tests/inputs/Shadowing.test view
@@ -1,4 +1,5 @@-# Copyright (c) Facebook, Inc. and its affiliates.+# Copyright (c) 2025 Andrew Farmer+# Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree.
+ tests/inputs/TypeAbs.test view
@@ -0,0 +1,23 @@+# This source code is licensed under the MIT license found in the+# LICENSE file in the root directory of this source tree.+#+# Regression test for type applications in constructor patterns. On+# GHC >= 9.14 the type argument is an InvisPat element of the PrefixCon+# pattern list (older GHCs kept it in a separate tyargs field that retrie+# ignored). Unfolding baz runs patToExpr over its argument pattern+# (Just @Int x), which must ignore the type argument rather than crash+# with 'patToExpr InvisPat'.+-u TypeAbs.baz+===+ {-# LANGUAGE TypeApplications #-}+ {-# LANGUAGE TypeAbstractions #-}+ + module TypeAbs where+ + baz :: Maybe Int -> Int+ baz (Just @Int x) = x+ baz Nothing = 0+ + f :: Int+-f = baz (Just 1)++f = 1
+ tests/inputs/TypeParens.test view
@@ -0,0 +1,26 @@+# Types substituted into tuple, list and paren components must not be+# parenthesized because the enclosing brackets already delimit them.+--adhoc-type "T a b = U (a, b)"+--adhoc-type "L a = M [a]"+--adhoc-type "P a = Q (a)"+===+ module TypeParens where++ data T a b = T a b+ data U a = U a+ data L a = L a+ data M a = M a+ data P a = P a+ data Q a = Q a++-tup :: T (Maybe Int) (Int -> Bool)++tup :: U (Maybe Int, Int -> Bool)+ tup = T Nothing even++-lst :: L (Int -> Bool)++lst :: M [Int -> Bool]+ lst = L even++-par :: P (Maybe Int)++par :: Q (Maybe Int)+ par = P Nothing
tests/inputs/Types.test view
@@ -1,4 +1,5 @@-# Copyright (c) Facebook, Inc. and its affiliates.+# Copyright (c) 2025 Andrew Farmer+# Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree.@@ -22,6 +23,25 @@    type Pointless a = a  type Fn a b = a -> b+ + data Meh = Meh+-  { entryKey :: Pointless (Int -> String)+-  , entryVal :: Fn Int String++  { entryKey :: Int -> String++  , entryVal :: Int -> String+   }+ +-getKey :: Meh -> Pointless (Int -> String)++getKey :: Meh -> Int -> String+ getKey m x = entryKey m x+ +-setKey :: Pointless (Int -> String) -> Meh -> Meh++setKey :: (Int -> String) -> Meh -> Meh+ setKey m k = m{ entryKey = k }+ +-errorKey :: Fn Int String++errorKey :: Int -> String+ errorKey = getKey undefined   -blah :: IO (Fn Int Bool) +blah :: IO (Int -> Bool)
tests/inputs/Types2.test view
@@ -1,10 +1,12 @@-# Copyright (c) Facebook, Inc. and its affiliates.+# Copyright (c) 2025 Andrew Farmer+# Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. # --type-forward Types2.Foo --type-forward Types2.MyMaybe+--type-forward Types2.Pair ===  module Types2 where  @@ -20,7 +22,12 @@ +blech2 :: Maybe Bar  blech2 = blech  +-blech3 :: Pair (Maybe Bar)++blech3 :: (Maybe Bar, Maybe Bar)+ blech3 = (blech2, blech2)+   type Foo = Either String Bar  type Bar = Int    type MyMaybe a = Maybe a+ type Pair a = (a, a)
tests/inputs/Types3.test view
@@ -1,4 +1,5 @@-# Copyright (c) Facebook, Inc. and its affiliates.+# Copyright (c) 2025 Andrew Farmer+# Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree.
tests/inputs/Types4.test view
@@ -1,4 +1,5 @@-# Copyright (c) Facebook, Inc. and its affiliates.+# Copyright (c) 2025 Andrew Farmer+# Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree.
tests/inputs/Union.test view
@@ -1,4 +1,5 @@-# Copyright (c) Facebook, Inc. and its affiliates.+# Copyright (c) 2025 Andrew Farmer+# Copyright (c) 2020-2024 Facebook, Inc. and its affiliates. # # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree.
+ tests/inputs/WhereBindings.test view
@@ -0,0 +1,76 @@+# Unfolding a definition with a where clause moves the bindings into a let+-u WhereBindings.empty+-u WhereBindings.plain+-u WhereBindings.sig+-u WhereBindings.subst+-u WhereBindings.partial+-u WhereBindings.comm+===+ module WhereBindings where++ -- empty where bindings translate into empty let bindings+ empty x = x+   where++-test1 a = empty a++test1 a = let++           in a++ -- a single binding+ plain x = f x+   where+     f y = y + 1++-test2 x = plain x++test2 x = let++            f y = y + 1++           in f x++ -- binding with signature+ sig x = f x+   where+     f :: Int -> Int+     f y = y + 1++-test3 x = sig x++test3 x = let++            f :: Int -> Int++            f y = y + 1++           in f x++ -- ensure bindings are substituted+ subst x = y+   where+     y = x + 1++-test4 = subst 1++test4 = let++          y = 1 + 1++         in y++ -- check that the let is wrapped with a lambda correctly+ partial :: Int -> Int+ partial x = x * two+   where+     two = 2++-test5 = map partial [1, 2, 3]++test5 = map (\ x -> let++                      two = 2++                     in x * two) [1, 2, 3]++ -- make sure comments are preserved+ comm x = f x + h x+   -- a+   where+     f y = y + 1+     -- b+     h y = y++-test6 a = comm a++test6 a = let++            -- a++            f y = y + 1++            -- b++            h y = y++           in f a + h a