packages feed

require 0.4.8 → 0.4.9

raw patch · 7 files changed

+259/−143 lines, 7 filesdep +ansi-terminaldep +dlistdep +mtldep −inliteratedep ~megaparsec

Dependencies added: ansi-terminal, dlist, mtl

Dependencies removed: inliterate

Dependency ranges changed: megaparsec

Files

library/Require.hs view
@@ -4,6 +4,7 @@ import Options.Generic import Relude import System.Directory+import qualified Require.Error as Error import qualified Require.File as File import Require.Transform import Require.Types@@ -33,12 +34,13 @@   CommandArguments inputFile _ outputFile <- getRecord "Require Haskell preprocessor" :: IO CommandArguments   requiresFile <- findRequires   case requiresFile of-    Nothing -> die "There is no Requires file in the system"+    Nothing -> Error.die (File.Name inputFile) Error.MissingRequiresFile     Just fn -> run (AutorequireEnabled fn) (File.Name inputFile) (File.Name outputFile)  run :: AutorequireMode File.Name -> File.Name -> File.Name -> IO () run autoMode inputFile outputFile = do   input <- File.read inputFile   autoInput <- traverse File.read autoMode-  let transformed = transform autoInput input-  File.write outputFile transformed+  case transform autoInput input of+    Left err -> Error.die inputFile err+    Right ls -> File.writeLines outputFile ls
+ library/Require/Error.hs view
@@ -0,0 +1,41 @@+module Require.Error where++import Control.Exception+import Relude+import qualified Require.File as File+import System.Console.ANSI+import System.IO+++data Error+  = MissingRequiresFile+  | MissingOptionalRequiresFile+  | AutorequireImpossible+  deriving (Eq, Show)+++describe :: Error -> [String]+describe MissingRequiresFile =+  [ "`autorequirepp` couldn't find a `Requires` file in the system." ]+describe MissingOptionalRequiresFile =+  [ "Discovered an `autorequire` directive but no `Requires` file was found." ]+describe AutorequireImpossible =+  [ "Unable to determine where to insert the autorequire contents."+  , "Use the `autorequire` directive to specify a location yourself."+  ]+++die :: File.Name -> Error -> IO a+die (File.Name fn) e = do+  let outputHeaderColored = do+        hSetSGR stderr [SetConsoleIntensity BoldIntensity]+        hPutStr stderr (toString fn ++ ": ")+        hSetSGR stderr [SetColor Foreground Vivid Red]+        hPutStr stderr "error:\n"++  -- Don't mess up the terminal if there is an exception half-way through.+  outputHeaderColored `finally` hSetSGR stderr []++  let indent s = replicate 4 ' ' ++ s+  traverse_ (hPutStrLn stderr . indent) (describe e)+  exitFailure
library/Require/File.hs view
@@ -9,6 +9,7 @@ module Require.File where  import Relude+import qualified Data.Text.IO as TIO  -- | Wraps the name of a file as given by the user. Usually this corresponds to -- the file's path.@@ -30,7 +31,7 @@ -- | Returns the 'LineTag' referencing the first line in a given 'FileInput'. -- -- Note that the tag's line number is 1-based, which fits well with how GHC--- understands @{-# LINE ... #-}@ pragmas.+-- understands @{-\# LINE ... #-}@ pragmas. initialLineTag :: Input -> LineTag initialLineTag inp = LineTag (inputName inp) (LineNumber 1) @@ -42,9 +43,11 @@ read :: Name -> IO Input read f = Input f <$> readFileText (nameToPath f) --- | @write name content@ writes @content@ to the file identified by @name@.-write :: Name -> Text -> IO ()-write = writeFileText . nameToPath+-- | @write name lines@ writes all every line in @lines@ to the file identified+-- by @name@ and appends a newline.+writeLines :: Name -> [Text] -> IO ()+writeLines name theLines = withFile (nameToPath name) WriteMode $ \h ->+  traverse_ (TIO.hPutStrLn h) theLines  -- | Splits the input into lines and annotates each with a 'LineTag'. inputLines :: Input -> [(LineTag, Text)]
library/Require/Transform.hs view
@@ -1,79 +1,110 @@ {-# LANGUAGE FlexibleContexts #-} module Require.Transform where +import Control.Monad.Except+import Control.Monad.Writer.Strict+import Data.DList (DList) import qualified Data.Text as Text import Relude+import Require.Error (Error(..)) import qualified Require.File as File import qualified Require.Parser as Parser import Require.Types  -type LineTagPrepend = File.LineTag -> Text -> Text+-- | The monad stack used during transformation:+--+-- * @'StateT' 'TransformState'@ to keep track of whether to render the next+--   line tag, the module's name etc.+-- * @'WriterT' ('DList' 'Text')@ to collect the output lines. Instead of+--   haskell's built-in list type we use 'DList' because of it's /O(1)/ append+--   operation.+-- * @'Either' 'Error'@ to return errors.+type TransformM =+  StateT TransformState+    (WriterT (DList Text)+      (Either Error)) + data TransformState = TransformState-  { tstLineTagPrepend :: !LineTagPrepend+  { tstLineTagOutput  :: File.LineTag -> TransformM ()   , tstHostModule     :: !(Maybe ModuleName)   , tstAutorequire    :: !(AutorequireMode File.Input)   }  -renderLineTag :: File.LineTag -> Text-renderLineTag (File.LineTag (File.Name fn) (File.LineNumber ln)) =-  "{-# LINE " <> show ln <> " \"" <> fn <> "\" #-}\n"-+-- | Outputs a single line.+output :: Text -> TransformM ()+output = tell . pure -prependLineTag :: LineTagPrepend-prependLineTag = (<>) . renderLineTag+-- | Outputs the pragma representation of the given line tag.+renderLineTag :: File.LineTag -> TransformM ()+renderLineTag (File.LineTag (File.Name fn) (File.LineNumber ln)) =+  output $ "{-# LINE " <> show ln <> " \"" <> fn <> "\" #-}" -ignoreLineTag :: LineTagPrepend-ignoreLineTag = const id+-- | Ignore the given line tag, specifically don't render it.+ignoreLineTag :: File.LineTag -> TransformM ()+ignoreLineTag = const (pure ())  -transform :: AutorequireMode File.Input -> File.Input -> Text+transform :: AutorequireMode File.Input -> File.Input -> Either Error [Text] transform autorequire input =-  -- TODO:-  --  * if the mapM overhead is too much maybe use a streaming library-  --  * there is no need to concatenate the whole output in memory, a lazy text would be fine-  --  * maybe we should check if tstAutorequired is set after processing   File.inputLines input-    & mapM (process (pure Nothing))-    & flip evalState initialState-    & mconcat+    & traverse_ (process False)+    & flip execStateT initialState+    & chainedTo checkDidAutorequire+    & execWriterT+    & fmap toList   where     initialState = TransformState-      { tstLineTagPrepend = prependLineTag+      { tstLineTagOutput  = renderLineTag       , tstHostModule     = Nothing       , tstAutorequire    = autorequire       } -process-  :: State TransformState (Maybe ModuleName)-  -> (File.LineTag, Text)-  -> State TransformState Text-process getHostModule (tag, line) = do-  let useTagPrep text = do-        prep <- gets tstLineTagPrepend-        modify $ \s -> s { tstLineTagPrepend = ignoreLineTag }-        pure $ prep tag text+    unableToAutorequire resultState+      -- If the autorequire mode was `enabled` initially and still is+      -- afterwards, we were unable to find where to place the Require contents.+      | AutorequireEnabled _ <- autorequire+      , AutorequireEnabled _ <- tstAutorequire resultState+      = True+      -- In any other case this either wasn't goal or it was done successfully.+      | otherwise+      = False +    checkDidAutorequire resultState+      | unableToAutorequire resultState = throwError AutorequireImpossible+      | otherwise = pure ()+++process :: Bool -> (File.LineTag, Text) -> TransformM ()+process filterImports (tag, line) = do+  -- Uses 'tstLineTagOutput' to render the current lines tag if necessary.+  let useTagPrep = do+        tst <- get+        tstLineTagOutput tst tag+        put (tst { tstLineTagOutput = ignoreLineTag })+   let lineWithAutorequire isDirective autoCondition = do         autoMode <- gets tstAutorequire         case autoMode of           AutorequireEnabled autoContent             | isDirective || autoCondition -> do-                line' <- if isDirective then pure "" else useTagPrep (line <> "\n")-                auto  <- processAutorequireContent autoContent-                pure $ line' <> auto-          AutorequireOnDirective (Just autoContent)-            | isDirective -> do+                -- If this is an `autorequire` directive, ignore it. Otherwise+                -- output the line tag if necessary (useTagPrep) and then the+                -- line itself.+                unless isDirective (useTagPrep >> output line)                 processAutorequireContent autoContent++          AutorequireOnDirective (Just autoContent)+            | isDirective -> processAutorequireContent autoContent+           AutorequireOnDirective Nothing-            | isDirective ->-                -- TODO: Better error reporting.-                error "Found an `autorequire` directive but no `Requires` file was found."-          _ | isDirective -> pure ""-            | otherwise   -> useTagPrep $ line <> "\n"+            | isDirective -> throwError MissingOptionalRequiresFile +          _ | isDirective -> pure ()+            | otherwise   -> useTagPrep >> output line+   let hasWhere =         -- TODO: This assumes that comments have whitespace before them and         -- that `where` has whitespace before it. But@@ -95,51 +126,47 @@      Just (RequireDirective ri) ->       -- renderImport already prepends the line tag if necessary.-      renderImport getHostModule tag ri+      renderImport filterImports tag ri      Just AutorequireDirective ->       lineWithAutorequire True False  -processAutorequireContent :: File.Input -> State TransformState Text+processAutorequireContent :: File.Input -> TransformM () processAutorequireContent autorequireContent = do   modify $ \s -> s-     { tstLineTagPrepend = prependLineTag+     { tstLineTagOutput  = renderLineTag      , tstAutorequire    = AutorequireDisabled      } -  processed <- File.inputLines autorequireContent-     & mapM (process (gets tstHostModule))-     & fmap mconcat+  traverse_ (process True) (File.inputLines autorequireContent)+  modify $ \s -> s { tstLineTagOutput = renderLineTag } -  modify $ \s -> s { tstLineTagPrepend = prependLineTag }-  pure processed +renderImport :: Bool -> File.LineTag -> RequireInfo -> TransformM ()+renderImport filterImports line RequireInfo {..} = do+    tst <- get+    if filterImports && tstHostModule tst == Just riFullModuleName+      then+        -- We skipped a line, therefore we need a line tag before outputting+        -- the next one.+        put (tst { tstLineTagOutput = renderLineTag }) -renderImport-  :: MonadState TransformState m-  => m (Maybe ModuleName)-  -> File.LineTag-  -> RequireInfo-  -> m Text-renderImport getHostModule line RequireInfo {..} = do-    mhostModule <- getHostModule-    lineTagPrep <- gets tstLineTagPrepend-    let (res, prep) =-          if mhostModule == Just riFullModuleName-             then ("", prependLineTag)-             else (typesImport <> renderLineTag line <> qualifiedImport, ignoreLineTag)-    modify $ \s -> s { tstLineTagPrepend = prep }-    pure $ lineTagPrep line res+      else do+        tstLineTagOutput tst line+        output typesImport+        renderLineTag line+        output qualifiedImport+        put (tst { tstLineTagOutput = ignoreLineTag })   where     typesImport = unwords       [ "import"       , unModuleName riFullModuleName       , "(" <> riImportedTypes <> ")"-      ] <> "\n"+      ]     qualifiedImport = unwords       [ "import qualified"       , unModuleName riFullModuleName       , "as"       , riModuleAlias-      ] <> "\n"+      ]
package.yaml view
@@ -1,5 +1,5 @@ name: require-version: "0.4.8"+version: "0.4.9" github: "theam/require" license: Apache-2.0 author: "The Agile Monkeys"@@ -32,10 +32,12 @@   - relude   - bytestring >= 0.10 && < 0.11   - text >= 1.2.3.0 && < 2-  - megaparsec >= 7 && < 8+  - megaparsec >= 7 && < 9+  - mtl >= 2.2.1   - directory-  - inliterate   - optparse-generic+  - dlist+  - ansi-terminal  library:   source-dirs: library@@ -48,8 +50,6 @@       - require     ghc-options:       - -rtsopts-      - -threaded-      - -with-rtsopts=-N   autorequirepp:     source-dirs: executable/AutoRequire/     main: Main.hs@@ -57,8 +57,6 @@       - require     ghc-options:       - -rtsopts-      - -threaded-      - -with-rtsopts=-N  benchmarks:   require-benchmarks:
require.cabal view
@@ -4,10 +4,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: ceeb2f9c5a160393a1fd86ca01c63c4d957d256ae92501abfd87e3d415f5c686+-- hash: 17d63ecaad4aef59bc1c65336dd500edd837396b8e80b9609aacca8fed98e770  name:           require-version:        0.4.8+version:        0.4.9 synopsis:       Scrap your qualified import clutter description:    See <https://theam.github.io/require> category:       Other@@ -34,6 +34,7 @@ library   exposed-modules:       Require+      Require.Error       Require.File       Require.Parser       Require.Transform@@ -45,11 +46,13 @@   default-extensions: NoImplicitPrelude OverloadedStrings TypeApplications RecordWildCards DeriveGeneric   ghc-options: -Wall   build-depends:-      base >=4.9 && <5+      ansi-terminal+    , base >=4.9 && <5     , bytestring >=0.10 && <0.11     , directory-    , inliterate-    , megaparsec >=7 && <8+    , dlist+    , megaparsec >=7 && <9+    , mtl >=2.2.1     , optparse-generic     , relude     , text >=1.2.3.0 && <2@@ -62,13 +65,15 @@   hs-source-dirs:       executable/AutoRequire/   default-extensions: NoImplicitPrelude OverloadedStrings TypeApplications RecordWildCards DeriveGeneric-  ghc-options: -Wall -rtsopts -threaded -with-rtsopts=-N+  ghc-options: -Wall -rtsopts   build-depends:-      base >=4.9 && <5+      ansi-terminal+    , base >=4.9 && <5     , bytestring >=0.10 && <0.11     , directory-    , inliterate-    , megaparsec >=7 && <8+    , dlist+    , megaparsec >=7 && <9+    , mtl >=2.2.1     , optparse-generic     , relude     , require@@ -82,13 +87,15 @@   hs-source-dirs:       executable/Require/   default-extensions: NoImplicitPrelude OverloadedStrings TypeApplications RecordWildCards DeriveGeneric-  ghc-options: -Wall -rtsopts -threaded -with-rtsopts=-N+  ghc-options: -Wall -rtsopts   build-depends:-      base >=4.9 && <5+      ansi-terminal+    , base >=4.9 && <5     , bytestring >=0.10 && <0.11     , directory-    , inliterate-    , megaparsec >=7 && <8+    , dlist+    , megaparsec >=7 && <9+    , mtl >=2.2.1     , optparse-generic     , relude     , require@@ -105,11 +112,13 @@   default-extensions: NoImplicitPrelude OverloadedStrings TypeApplications RecordWildCards DeriveGeneric   ghc-options: -Wall -rtsopts -threaded -with-rtsopts=-N   build-depends:-      base >=4.9 && <5+      ansi-terminal+    , base >=4.9 && <5     , bytestring >=0.10 && <0.11     , directory-    , inliterate-    , megaparsec >=7 && <8+    , dlist+    , megaparsec >=7 && <9+    , mtl >=2.2.1     , optparse-generic     , relude     , require@@ -128,12 +137,14 @@   default-extensions: NoImplicitPrelude OverloadedStrings TypeApplications RecordWildCards DeriveGeneric   ghc-options: -Wall -rtsopts -threaded -with-rtsopts=-N   build-depends:-      base >=4.9 && <5+      ansi-terminal+    , base >=4.9 && <5     , bytestring >=0.10 && <0.11     , criterion     , directory-    , inliterate-    , megaparsec >=7 && <8+    , dlist+    , megaparsec >=7 && <9+    , mtl >=2.2.1     , optparse-generic     , relude     , require
test-suite/Main.hs view
@@ -1,5 +1,6 @@ import qualified Data.Text as Text import Relude+import qualified Require.Error as Error import qualified Require.File as File import qualified Require.Transform as Require import Require.Types@@ -13,21 +14,36 @@  spec :: Spec spec = parallel $ do+  let transformLines autoMode fileInput =+        case Require.transform autoMode fileInput of+          Left err -> do+            -- sadly expectationFailure is not polymorphic in its return type+            expectationFailure $ "Tranform failed: " ++ show err+            pure $ error "expectationFailure should have thrown"+          Right tr ->+            pure tr++      transformString autoMode =+         fmap toString . transform autoMode++      transform autoMode =+         fmap unlines . transformLines autoMode+   describe "the transformation" $ do     it "transforms the 'require' keyword into a properly qualified import" $ do       let input = "require Data.Text"       let expected = "import qualified Data.Text as Text"-      let actual = Require.transform+      actual <- transformString             AutorequireDisabled             (File.Input (File.Name "Foo.hs") input)-      expected `Text.isInfixOf` actual+      actual `shouldContain` expected     it "imports the type based on the module" $ do       let input = "require Data.Text"       let expected = "import Data.Text (Text)"-      let actual = Require.transform+      actual <- transformString             AutorequireDisabled             (File.Input (File.Name "Foo.hs") input)-      expected `Text.isInfixOf` actual+      actual `shouldContain` expected     it "keeps the rest of the content intact" $ do       let input = "module Foo where\nrequire Data.Text\nfoo = 42"       let expectedStart = "{-# LINE 1"@@ -35,7 +51,7 @@       let expectedTypeImport = "import Data.Text (Text)"       let expectedQualifiedImport = "import qualified Data.Text as Text"       let expectedContent = "foo = 42\n"-      let actual = toString $ Require.transform+      actual <- transformString             AutorequireDisabled             (File.Input (File.Name "Foo.hs") input)       actual `shouldStartWith` expectedStart@@ -47,7 +63,7 @@       let input = "require Data.Text as Foo"       let expectedTypeImport = "import Data.Text (Text)"       let expectedQualifiedImport = "import qualified Data.Text as Foo"-      let actual = toString $ Require.transform+      actual <- transformString             AutorequireDisabled             (File.Input (File.Name "Foo.hs") input)       actual `shouldContain` expectedTypeImport@@ -56,7 +72,7 @@       let input = "require Data.Text (Foo)"       let expectedTypeImport = "import Data.Text (Foo)"       let expectedQualifiedImport = "import qualified Data.Text as Text"-      let actual = toString $ Require.transform+      actual <- transformString             AutorequireDisabled             (File.Input (File.Name "Foo.hs") input)       actual `shouldContain` expectedTypeImport@@ -65,7 +81,7 @@       let input = "require Data.Text as Quux (Foo)"       let expectedTypeImport = "import Data.Text (Foo)"       let expectedQualifiedImport = "import qualified Data.Text as Quux"-      let actual = toString $ Require.transform+      actual <- transformString             AutorequireDisabled             (File.Input (File.Name "Foo.hs") input)       actual `shouldContain` expectedTypeImport@@ -73,55 +89,63 @@     it "skips comments" $ do       let input = "require Data.Text -- test of comments"       let expected = "import Data.Text (Text)"-      let actual = Require.transform+      actual <- transformString             AutorequireDisabled             (File.Input (File.Name "Foo.hs") input)-      expected `Text.isInfixOf` actual+      actual `shouldContain` expected     it "allows empty parentheses" $ do       let input = "require Data.Text ()"       let expected1 = "import Data.Text ()"       let expected2 = "import qualified Data.Text as Text"-      let actual = lines $ Require.transform+      actual <- transformLines             AutorequireDisabled             (File.Input (File.Name "Foo.hs") input)       actual `shouldSatisfy` elem expected1       actual `shouldSatisfy` elem expected2    describe "require-mode" $ do-    it "respects autorequire directives" $ do-      let fileInput = Text.unlines [ "module Main where", "autorequire", "import B" ]-      let requireInput = Text.unlines [ "import A" ]-      let actual = Text.lines $ Require.transform-            (AutorequireOnDirective $ Just $ File.Input (File.Name "Requires") requireInput)-            (File.Input (File.Name "src/Foo/Bar.hs") fileInput)-      actual `shouldSatisfy` elem "module Main where"-      actual `shouldSatisfy` elem "import A"-      actual `shouldSatisfy` elem "import B"-      actual `shouldSatisfy` elemN 0 "autorequire"-    it "ignores a second autorequire directive" $ do-      let fileInput = Text.unlines [ "autorequire", "autorequire" ]-      let requireInput = Text.unlines [ "import A" ]-      let actual = Text.lines $ Require.transform-            (AutorequireOnDirective $ Just $ File.Input (File.Name "Requires") requireInput)-            (File.Input (File.Name "src/Foo/Bar.hs") fileInput)-      actual `shouldSatisfy` elemN 1 "import A"-      actual `shouldSatisfy` elemN 0 "autorequire"     it "keeps requires where the module is a substring of the filename" $ do       -- Test case for https://github.com/theam/require/issues/20       let fileInput = Text.unlines [ "module FooTest where", "require Foo" ]       let expected1 = "import Foo (Foo)"       let expected2 = "import qualified Foo as Foo"-      let actual = lines $ Require.transform+      actual <- transformLines             AutorequireDisabled             (File.Input (File.Name "FooTests.hs") fileInput)       actual `shouldSatisfy` elem expected1       actual `shouldSatisfy` elem expected2 +    describe "autorequire directive" $ do+      it "respects them" $ do+        let fileInput = Text.unlines [ "module Main where", "autorequire", "import B" ]+        let requireInput = Text.unlines [ "import A" ]+        actual <- transformLines+              (AutorequireOnDirective $ Just $ File.Input (File.Name "Requires") requireInput)+              (File.Input (File.Name "src/Foo/Bar.hs") fileInput)+        actual `shouldSatisfy` elem "module Main where"+        actual `shouldSatisfy` elem "import A"+        actual `shouldSatisfy` elem "import B"+        actual `shouldSatisfy` elemN 0 "autorequire"+      it "ignores them after the first one" $ do+        let fileInput = Text.unlines [ "autorequire", "autorequire" ]+        let requireInput = Text.unlines [ "import A" ]+        actual <- transformLines+              (AutorequireOnDirective $ Just $ File.Input (File.Name "Requires") requireInput)+              (File.Input (File.Name "src/Foo/Bar.hs") fileInput)+        actual `shouldSatisfy` elemN 1 "import A"+        actual `shouldSatisfy` elemN 0 "autorequire"+      it "throws an error if no requires file is provided" $ do+        let fileInput = "autorequire"+        let actual = Require.transform+              (AutorequireOnDirective Nothing)+              (File.Input (File.Name "Foo.hs") fileInput)+        actual `shouldBe` Left Error.MissingOptionalRequiresFile+   describe "autorequire-mode" $ do     describe "inclusion after module directive" $ do       let checkInclusion n fileInput = do             let requireInput = "import A"-            let actual = Text.lines $ Require.transform+            actual <- transformLines                   (AutorequireEnabled $ File.Input (File.Name "Requires") requireInput)                   (File.Input (File.Name "src/Foo/Bar.hs") fileInput)             actual `shouldSatisfy` elemN n requireInput@@ -141,18 +165,28 @@           , "  ) where"           ]       it "doesn't add after data/class/instance declarations" $ do-        checkInclusion 0 $ Text.unlines-          [ "class Foo a where"-          , "instance Foo x => Bar (Baz x) where"-          , "data Vec n a where"-          , "  Nil :: Vec 0 a"-          , "  Cons :: a -> Vec n a -> Vec (n + 1) a"-          ]+        let fileInput = unlines+              [ "class Foo a where"+              , "instance Foo x => Bar (Baz x) where"+              , "data Vec n a where"+              , "  Nil :: Vec 0 a"+              , "  Cons :: a -> Vec n a -> Vec (n + 1) a"+              ]+        let requireInput = unlines [ "import A" ]+        let actual = Require.transform+              (AutorequireEnabled $ File.Input (File.Name "Requires") requireInput)+              (File.Input (File.Name "Foo.hs") fileInput)+        actual `shouldBe` Left Error.AutorequireImpossible       it "doesn't add after data/class/instance declarations split to multiple lines" $ do-        checkInclusion 0 $ Text.unlines-          [ "class Foo a -- some explanation here"-          , "  where"-          ]+        let fileInput = unlines+              [ "class Foo a -- some explanation here"+              , "  where"+              ]+        let requireInput = unlines [ "import A" ]+        let actual = Require.transform+              (AutorequireEnabled $ File.Input (File.Name "Requires") requireInput)+              (File.Input (File.Name "Foo.hs") fileInput)+        actual `shouldBe` Left Error.AutorequireImpossible      describe "triggered using the autorequire directive" $ do       it "can be triggered before without a module directive" $ do@@ -164,7 +198,7 @@               , "{-# LINE 2 \"Foo.hs\" #-}"               , "main = return ()"               ]-        let actual = Require.transform+        actual <- transform               (AutorequireEnabled $ File.Input (File.Name "Requires") requireInput)               (File.Input (File.Name "Foo.hs") fileInput)         actual `shouldBe` expected@@ -177,7 +211,7 @@               , "{-# LINE 1 \"Requires\" #-}"               , "import A"               ]-        let actual = Require.transform+        actual <- transform               (AutorequireEnabled $ File.Input (File.Name "Requires") requireInput)               (File.Input (File.Name "Foo.hs") fileInput)         actual `shouldBe` expected@@ -190,7 +224,7 @@               , "{-# LINE 2 \"Foo.hs\" #-}"               , "module Main where"               ]-        let actual = Require.transform+        actual <- transform               (AutorequireEnabled $ File.Input (File.Name "Requires") requireInput)               (File.Input (File.Name "Foo.hs") fileInput)         actual `shouldBe` expected@@ -199,7 +233,7 @@       let fileInput = "module Foo.Bar where"       let requireInput = "require Foo.Bar"       let notExpected = "import Foo.Bar"-      let actual = Require.transform+      actual <- transform             (AutorequireEnabled $ File.Input (File.Name "Requires") requireInput)             (File.Input (File.Name "src/Foo/Bar.hs") fileInput)       toString actual `shouldNotContain` notExpected@@ -214,7 +248,7 @@             , "{-# LINE 2 \"Foo.hs\" #-}"             , "import B"             ]-      let actual = Require.transform+      actual <- transform             (AutorequireEnabled $ File.Input (File.Name "Requires") requireInput)             (File.Input (File.Name "Foo.hs") fileInput)       actual `shouldBe` expected