packages feed

implicit-hie (empty) → 0.1.0.0

raw patch · 10 files changed

+747/−0 lines, 10 filesdep +attoparsecdep +basedep +directorysetup-changed

Dependencies added: attoparsec, base, directory, filepath, filepattern, hspec, hspec-attoparsec, implicit-hie, text, transformers, yaml

Files

+ ChangeLog.md view
@@ -0,0 +1,3 @@+# Changelog for implicit-hie++## Unreleased changes
+ LICENSE view
@@ -0,0 +1,30 @@+Copyright Avi Dessauer (c) 2020++All rights reserved.++Redistribution and use in source and binary forms, with or without+modification, are permitted provided that the following conditions are met:++    * Redistributions of source code must retain the above copyright+      notice, this list of conditions and the following disclaimer.++    * Redistributions in binary form must reproduce the above+      copyright notice, this list of conditions and the following+      disclaimer in the documentation and/or other materials provided+      with the distribution.++    * Neither the name of Avi Dessauer nor the names of other+      contributors may be used to endorse or promote products derived+      from this software without specific prior written permission.++THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT+OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ README.md view
@@ -0,0 +1,69 @@+# implicit-hie+```bash+cd your-stack-or-cabal-package+gen-hie > hie.yaml+```+`gen-hie` should be run the root of a cabal or stack project.+The config type (cabal or stack) is determined by the existence of+`dist-newstyle`, `.stack-work`, `stack.yaml`, if none are found the default is cabal.++# Cabal Multi project example+```bash+❯ git clone https://github.com/well-typed/optics.git+❯ cd optics+❯ gen-hie+cradle:+  cabal:+    - path: "indexed-profunctors/src"+      component: "lib:indexed-profunctors"++    - path: "optics-th/src"+      component: "lib:optics-th"++    - path: "optics-th/tests"+      component: "optics-th:test:optics-th-tests"++    - path: "optics-vl/src"+      component: "lib:optics-vl"++    - path: "codegen/./Subtypes.hs"+      component: "optics-codegen:exe:optics-codegen-subtypes"++    - path: "optics-core/src"+      component: "lib:optics-core"++    - path: "optics-sop/src"+      component: "lib:optics-sop"++    - path: "optics-extra/src"+      component: "lib:optics-extra"++    - path: "template-haskell-optics/src"+      component: "lib:template-haskell-optics"++    - path: "optics/src"+      component: "lib:optics"++    - path: "optics/tests"+      component: "optics:test:optics-tests"++    - path: "metametapost/src/Cli.hs"+      component: "metametapost:exe:metametapost-optics"++```++## Features++All common Cabal and Stack configurations should just work.+If you use more advanced features, the generated config may not be complete.++- [x] multi component cabal, stack projects+- [x] multiple executables under a single path+- [x] multiple paths provided to `hs-source-dirs`+- [x] lookup nested packages in `cabal.project` or `stack.yaml`+- [x] Handle Exe and Bench `other-modules`+- [ ] common stanzas++### Work, Twitter+- I'm currently looking for work as a Haskell or Rust developer. I can be reached via email or a twitter message.+- Follow me on twitter [@AviDessauer](https://twitter.com/AviDessauer).
+ Setup.hs view
@@ -0,0 +1,2 @@+import Distribution.Simple+main = defaultMain
+ app/Main.hs view
@@ -0,0 +1,37 @@+{-# LANGUAGE MultiWayIf #-}++module Main where++import Control.Monad+import Control.Monad.Trans.Maybe+import Data.Attoparsec.Text+import Data.List+import Data.Maybe+import qualified Data.Text as T+import qualified Data.Text.IO as T+import Hie.Cabal.Parser+import Hie.Locate+import Hie.Yaml+import System.Directory+import System.Directory.Internal+import System.FilePath.Posix++main :: IO ()+main = do+  pwd <- getCurrentDirectory+  files <- listDirectory pwd+  let name =+        if  | any (("dist-newstyle" ==) . takeFileName) files -> "cabal"+            | any ((".stack-work" ==) . takeFileName) files -> "stack"+            | any (("cabal.project" ==) . takeFileName) files -> "cabal"+            | any (("stack.yaml" ==) . takeFileName) files -> "stack"+            | otherwise -> "cabal"+  cfs <- runMaybeT $ case name of+    "cabal" -> cabalPkgs pwd+    _ -> stackYamlPkgs pwd+  when (null cfs) $ error $+    "No .cabal files found under"+      <> pwd+      <> "\n You may need to run stack build."+  pkgs <- catMaybes <$> mapM (nestedPkg pwd) (concat cfs)+  putStr <$> hieYaml name $ fmtPkgs name pkgs
+ implicit-hie.cabal view
@@ -0,0 +1,96 @@+cabal-version: 2.0++-- This file has been generated from package.yaml by hpack version 0.33.0.+--+-- see: https://github.com/sol/hpack+--+-- hash: 18f92037a7863d121ac45e847f7dc6177adf0ebc7951dfa1588340f86e64456b++name:           implicit-hie+version:        0.1.0.0+description:    Auto generate a stack or cabal multi component hie.yaml file+category:       Development, Tools, Hie, HLS+synopsis:       Auto generate hie-bios cradles & hie.yaml+homepage:       https://github.com/Avi-D-coder/implicit-hie#readme+bug-reports:    https://github.com/Avi-D-coder/implicit-hie/issues+author:         Avi Dessauer+maintainer:     avi.the.coder@gmail.com+copyright:      2020+license:        BSD3+license-file:   LICENSE+build-type:     Simple+extra-source-files:+    README.md+    ChangeLog.md++source-repository head+  type: git+  location: https://github.com/Avi-D-coder/implicit-hie++library+  exposed-modules:+      Hie.Cabal.Parser+      Hie.Locate+      Hie.Yaml+  other-modules:+      Paths_implicit_hie+  autogen-modules:+      Paths_implicit_hie+  hs-source-dirs:+      src+  ghc-options: -Wall -Wincomplete-record-updates -Wincomplete-uni-patterns -fno-warn-unused-imports -fno-warn-unused-binds -fno-warn-name-shadowing -fwarn-redundant-constraints+  build-depends:+      attoparsec >= 0.13+    , base >=4.7 && <5+    , directory >= 1.3+    , filepath >= 1.4+    , filepattern >= 0.1+    , text >= 1.2+    , transformers >= 0.5+    , yaml >= 0.5+  default-language: Haskell2010++executable gen-hie+  main-is: Main.hs+  other-modules:+      Paths_implicit_hie+  autogen-modules:+      Paths_implicit_hie+  hs-source-dirs:+      app+  ghc-options: -Wall -Wincomplete-record-updates -Wincomplete-uni-patterns -fno-warn-unused-imports -fno-warn-unused-binds -fno-warn-name-shadowing -fwarn-redundant-constraints -threaded -rtsopts -with-rtsopts=-N+  build-depends:+      attoparsec+    , base >=4.7 && <5+    , directory+    , filepath+    , filepattern+    , implicit-hie+    , text+    , transformers+    , yaml+  default-language: Haskell2010++test-suite implicit-hie-test+  type: exitcode-stdio-1.0+  main-is: Spec.hs+  other-modules:+      Paths_implicit_hie+  autogen-modules:+      Paths_implicit_hie+  hs-source-dirs:+      test+  ghc-options: -Wall -Wincomplete-record-updates -Wincomplete-uni-patterns -fno-warn-unused-imports -fno-warn-unused-binds -fno-warn-name-shadowing -fwarn-redundant-constraints -threaded -rtsopts -with-rtsopts=-N+  build-depends:+      attoparsec+    , base >=4.7 && <5+    , directory+    , filepath+    , filepattern+    , hspec+    , hspec-attoparsec+    , implicit-hie+    , text+    , transformers+    , yaml+  default-language: Haskell2010
+ src/Hie/Cabal/Parser.hs view
@@ -0,0 +1,188 @@+{-# LANGUAGE OverloadedStrings #-}++module Hie.Cabal.Parser where++import Control.Applicative+import Control.Monad+import Data.Attoparsec.Text+import Data.Char+import Data.Maybe+import Data.Text (Text)+import qualified Data.Text as T+import System.FilePath.Posix ((</>))++type Name = Text++type Path = Text++type Indent = Int++data Package = Package Name [Component]+  deriving (Show, Eq, Ord)++data CompType = Lib | Exe | Test | Bench+  deriving (Show, Eq, Ord)++data Component+  = Comp CompType Name Path+  deriving (Show, Eq, Ord)++parsePackage' :: Text -> Either String Package+parsePackage' = parseOnly parsePackage++parsePackage :: Parser Package+parsePackage =+  ( do+      n <- field 0 "name" $ const parseString+      (Package _ t) <- parsePackage+      pure $ Package n t+  )+    <|> ( do+            h <- parseComponent 0+            (Package n t) <- parsePackage+            pure $ Package n (h <> t)+        )+    <|> (skipToNextLine >> parsePackage)+    <|> pure (Package "" [])++componentHeader :: Indent -> Text -> Parser Name+componentHeader i t = do+  _ <- indent i+  _ <- asciiCI t+  skipMany tabOrSpace+  n <- parseString <|> pure ""+  skipToNextLine+  pure n++parseComponent :: Indent -> Parser [Component]+parseComponent i =+  parseExe i+    <|> parseLib i+    <|> parseBench i+    <|> parseTestSuite i++parseLib :: Indent -> Parser [Component]+parseLib i = parseSec i "library" $ Comp Lib++parseTestSuite :: Indent -> Parser [Component]+parseTestSuite i = parseSec i "test-suite" $ Comp Test++parseExe :: Indent -> Parser [Component]+parseExe = parseSecMain (Comp Exe) "executable"++parseBench :: Indent -> Parser [Component]+parseBench = parseSecMain (Comp Bench) "benchmark"++parseSecMain :: (Name -> Path -> Component) -> Text -> Indent -> Parser [Component]+parseSecMain c s i = do+  n <- componentHeader i s+  p <- pathMain (i + 1) ["./"] "" [] []+  pure $ map (c n) p++parseQuoted :: Parser Text+parseQuoted = do+  q <- char '"' <|> char '\''+  s <- takeTill (== q)+  _ <- char q+  pure s++parseString :: Parser Name+parseString = parseQuoted <|> unqualName++unqualName :: Parser Text+unqualName = takeWhile1 (not . (\c -> isSpace c || c == ','))++parseList :: Indent -> Parser [Text]+parseList i = items <|> (emptyOrComLine >> indent i >> items)+  where+    items = do+      skipMany tabOrSpace+      h <- parseString+      skipMany tabOrSpace+      skipMany (char ',')+      t <-+        items+          <|> (skipToNextLine >> indent i >> parseList i)+          <|> pure []+      pure $ h : t++pathMain :: Indent -> [Text] -> Text -> [Text] -> [Text] -> Parser [Text]+pathMain i p m o a =+  (hsSourceDir i >>= (\p' -> pathMain i p' m o a))+    <|> (field i "main-is" (const parseString) >>= (\m' -> pathMain i p m' o a))+    <|> (field i "other-modules" parseList >>= flip (pathMain i p m) a)+    <|> (field i "autogen-modules" parseList >>= pathMain i p m o)+    <|> (skipBlockLine i >> pathMain i p m o a)+    <|> pure+      ( map (<//> m) p+          <> [ p' <//> (o' <> ".hs")+               | p' <- p,+                 o' <- filter (`notElem` a) o+             ]+      )++(<//>) :: Text -> Text -> Text+a <//> b = T.pack (T.unpack a </> T.unpack b)++infixr 5 <//>++parseSec :: Indent -> Text -> (Name -> Path -> Component) -> Parser [Component]+parseSec i compType compCon = do+  n <- componentHeader i compType+  p <- extractPath (i + 1) []+  let p' = if null p then ["./"] else p+  pure $ map (compCon n) p'++skipToNextLine :: Parser ()+skipToNextLine = skipWhile (not . isEndOfLine) >> endOfLine++skipBlock :: Indent -> Parser ()+skipBlock i = skipMany $ skipBlockLine i++comment :: Parser ()+comment = skipMany tabOrSpace >> "--" >> skipToNextLine++skipBlockLine :: Indent -> Parser ()+skipBlockLine i = (indent i >> skipToNextLine) <|> emptyOrComLine++emptyOrComLine :: Parser ()+emptyOrComLine = skipMany tabOrSpace >> endOfLine <|> comment++tabOrSpace :: Parser Char+tabOrSpace = char ' ' <|> char '\t'++hsSourceDir :: Indent -> Parser [Text]+hsSourceDir i = field i "hs-source-dirs" parseList++-- field :: Indent -> Text -> Parser Text+field ::+  Indent ->+  Text ->+  (Indent -> Parser a) ->+  Parser a+field i f p =+  do+    i' <- indent i+    _ <- asciiCI f+    skipSpace+    _ <- char ':'+    skipSpace+    p' <- p $ i' + 1+    skipToNextLine+    pure p'++extractPath :: Indent -> [Path] -> Parser [Path]+extractPath i ps =+  (field i "hs-source-dirs" parseList >>= (\p -> extractPath i $ ps <> p))+    <|> (skipBlockLine i >> extractPath i ps)+    <|> (comment >> extractPath i ps)+    <|> pure ps++-- | Skip at least n spaces+indent :: Indent -> Parser Int+indent i = do+  c <- length <$> many' tabOrSpace+  if c >= i then pure c else fail "insufficient indent"++extractPkgs :: Parser [T.Text]+extractPkgs = join . catMaybes <$> many' (Just <$> field 0 "packages" parseList <|> (skipToNextLine >> pure Nothing))
+ src/Hie/Locate.hs view
@@ -0,0 +1,85 @@+{-# LANGUAGE LambdaCase #-}+{-# LANGUAGE OverloadedStrings #-}++module Hie.Locate+  ( nestedPkg,+    stackYamlPkgs,+    cabalPkgs,+  )+where++import Control.Applicative+import Control.Exception+import Control.Monad+import Control.Monad.IO.Class+import Control.Monad.Trans.Maybe+import Data.Attoparsec.Text (parseOnly)+import Data.Either+import Data.List+import Data.Maybe+import qualified Data.Text as T+import qualified Data.Text.IO as T+import Data.Yaml+import GHC.Generics+import Hie.Cabal.Parser+import Hie.Yaml+import System.Directory+import System.FilePath.Posix+import System.FilePattern.Directory (getDirectoryFiles)++newtype Pkgs = Pkgs [FilePath]+  deriving (Eq, Ord)++instance FromJSON Pkgs where+  parseJSON (Object v) = Pkgs <$> v .: "packages"+  parseJSON _ = fail "could not read packages from stack.yaml"++stackYamlPkgs :: FilePath -> MaybeT IO [FilePath]+stackYamlPkgs p = liftIO $+  decodeFileEither (p </> "stack.yaml") >>= \case+    Right (Pkgs f) ->+      liftIO $+        map (p </>)+          <$> getDirectoryFiles p (map (</> "*.cabal") f)+    Left e -> fail $ show e++cabalPkgs :: FilePath -> MaybeT IO [FilePath]+cabalPkgs p = do+  cp <- cabalP "cabal.project"+  cl <- cabalP "cabal.project.local"+  case concat . rights $ map (parseOnly extractPkgs) $ rights [cp, cl] of+    [] -> liftIO (cfs p) >>= \case+      [] -> fail "no cabal files found"+      h : _ -> pure [p </> h]+    xs -> do+      cd <- liftIO $ map (p </>) <$> getDirectoryFiles p (map (matchDirs . T.unpack) xs)+      cf <-+        liftIO $+          mapM (\p -> if takeExtension p == ".cabal" then pure [p] else cfs p) cd+      pure $ concat cf+  where+    cabalP n = liftIO (try $ T.readFile $ p </> n :: IO (Either IOException T.Text))+    cfs d = filter ((".cabal" ==) . takeExtension) <$> listDirectory d+    matchDirs "." = "./*.cabal"+    matchDirs p | "/" `isSuffixOf` p || p == "." = p <> "*.cabal"+    matchDirs p | "*" `isSuffixOf` p || takeExtension p == "" = p <> "/*.cabal"+    matchDirs p = p++nestedPkg :: FilePath -> FilePath -> IO (Maybe Package)+nestedPkg parrent child = do+  f' <- T.readFile child+  case parsePackage' f' of+    Right (Package n cs) -> do+      let dir =+            fromJust $ stripPrefix (splitDirectories parrent)+              $ splitDirectories+              $ fst (splitFileName child)+          pkg =+            Package n $+              map+                ( \(Comp t n p) ->+                    Comp t n (T.pack $ joinPath dir </> T.unpack p)+                )+                cs+      pure $ Just pkg+    _ -> pure Nothing
+ src/Hie/Yaml.hs view
@@ -0,0 +1,64 @@+{-# LANGUAGE OverloadedStrings #-}++module Hie.Yaml+  ( hieYaml,+    fmtComponent,+    fmtPkgs,+    cabalComponent,+    stackComponent,+  )+where++import qualified Data.Text as T+import Hie.Cabal.Parser++hieYaml :: String -> String -> String+hieYaml sOrC pkgs =+  "cradle:\n"+    <> indent'+      (sOrC <> ":\n" <> indent' pkgs)++indent' :: String -> String+indent' =+  unlines+    . map+      ( \l -> case l of+          "" -> ""+          _ -> "  " <> l+      )+    . lines++cabalComponent :: Name -> Component -> (FilePath, String)+cabalComponent n (Comp Lib "" p) = (T.unpack p, T.unpack $ "lib:" <> n)+cabalComponent n (Comp Lib cn p) = (T.unpack p, T.unpack $ n <> ":lib:" <> cn)+cabalComponent n (Comp Exe cn p) = (T.unpack p, T.unpack $ n <> ":exe:" <> cn)+cabalComponent n (Comp Bench cn p) = (T.unpack p, T.unpack $ n <> ":bench:" <> cn)+cabalComponent n (Comp Test cn p) = (T.unpack p, T.unpack $ n <> ":test:" <> cn)++stackComponent :: Name -> Component -> (FilePath, String)+stackComponent n (Comp Lib "" p) = (T.unpack p, T.unpack $ n <> ":lib")+stackComponent n (Comp Lib cn p) = (T.unpack p, T.unpack $ n <> ":lib:" <> cn)+stackComponent n (Comp Exe cn p) = (T.unpack p, T.unpack $ n <> ":exe:" <> cn)+stackComponent n (Comp Bench cn p) = (T.unpack p, T.unpack $ n <> ":bench:" <> cn)+stackComponent n (Comp Test cn p) = (T.unpack p, T.unpack $ n <> ":test:" <> cn)++fmtComponent :: (FilePath, String) -> String+fmtComponent (p, c) =+  "- path: "+    <> dQuote p+    <> "\n  "+    <> "component: "+    <> dQuote c++dropLast :: [a] -> [a]+dropLast l = take (length l - 1) l++fmtPkgs :: String -> [Package] -> String+fmtPkgs sOrC pkgs = dropLast $ unlines l+  where+    comp = if sOrC == "cabal" then cabalComponent else stackComponent+    f (Package n cs) = map ((<> "\n") . fmtComponent . comp n) cs+    l = concatMap f pkgs++dQuote :: String -> String+dQuote t = '"' : t <> "\""
+ test/Spec.hs view
@@ -0,0 +1,173 @@+{-# LANGUAGE OverloadedStrings #-}++import Data.Attoparsec.Text+import qualified Data.Text as T+import Data.Text (Text)+import qualified Data.Text.IO as T+import Hie.Cabal.Parser+import Hie.Yaml+import Test.Hspec+import Test.Hspec.Attoparsec++main :: IO ()+main = hspec spec++spec :: Spec+spec = do+  describe "Should Succeed"+    $ it "successfully parses executable section"+    $ exeSection ~> parseExe 0+      `shouldParse` [Comp Exe "gen-hie" "app/Main.hs"]+  describe "Should Succeed"+    $ it "successfully parses test section"+    $ testSection ~> parseTestSuite 0+      `shouldParse` [Comp Test "implicit-hie-test" "test"]+  describe "Should Succeed"+    $ it "successfully parses library section"+    $ libSection ~> parseLib 0+      `shouldParse` [Comp Lib "" "src"]+  describe "Should Succeed"+    $ it "successfully parses library section with 2 hs-source-dirs"+    $ libSection2 ~> parseLib 0+      `shouldParse` [Comp Lib "" "src", Comp Lib "" "src2"]+  describe "Should Succeed"+    $ it "successfully parses library section with 2 paths under hs-source-dirs"+    $ libSection3 ~> parseLib 0+      `shouldParse` [Comp Lib "" "src", Comp Lib "" "src2"]+  describe "Should Succeed"+    $ it "successfully parses bench section"+    $ do+      bs <- T.readFile "test/benchSection"+      bs ~> parseBench 0+        `shouldParse` [Comp Bench "folds" "benchmarks/folds.hs"]+  describe "Should Succeed"+    $ it "successfully parses package"+    $ do+      cf <- T.readFile "implicit-hie.cabal"+      cf ~> parsePackage+        `shouldParse` Package+          "implicit-hie"+          [ Comp Lib "" "src",+            Comp Exe "gen-hie" "app/Main.hs",+            Comp Test "implicit-hie-test" "test"+          ]+  describe "Should Succeed"+    $ it+      "skips to end of block section"+    $ let r = "test\n"+       in (libSection <> r) ~?> parseLib 0+            `leavesUnconsumed` r+  describe "Should Succeed"+    $ it "successfully generates stack hie.yaml"+    $ do+      sf <- readFile "test/stackHie.yaml"+      cf <- T.readFile "implicit-hie.cabal"+      (hieYaml "stack" . fmtPkgs "stack" . (: []) <$> parseOnly parsePackage cf)+        `shouldBe` Right sf+  describe "Should Succeed"+    $ it "successfully generates cabal hie.yaml for haskell-language-server"+    $ do+      f <- T.readFile "test/haskell-language-server-cabal"+      o <- readFile "test/hie.yaml.cbl"+      (hieYaml "cabal" . fmtPkgs "cabal" . (: []) <$> parseOnly parsePackage f)+        `shouldBe` Right o+  describe "Should Succeed"+    $ it "successfully parses comma list"+    $ ("one, two" :: Text) ~> parseList 1 `shouldParse` ["one", "two"]+  describe "Should Succeed"+    $ it "successfully parses newline list"+    $ ("one\n two \n three3" :: Text) ~> parseList 1+      `shouldParse` ["one", "two", "three3"]+  describe "Should Succeed"+    $ it "successfully parses newline comma list"+    $ ("one\n two,  three3" :: Text) ~> parseList 1+      `shouldParse` ["one", "two", "three3"]+  describe "Should Succeed"+    $ it "quoted list"+    $ ("\"one\"\n two\n three3" :: Text) ~> parseList 1+      `shouldParse` ["one", "two", "three3"]++exeSection :: Text+exeSection =+  "executable gen-hie\n\+  \  other-modules:\n\+  \    Paths_implicit_hie\n\+  \  autogen-modules:\n\+  \    Paths_implicit_hie\n\+  \  hs-source-dirs:\n\+  \      app\n\+  \  ghc-options: -O2\n\+  \  main-is: Main.hs \n"++testSection :: Text+testSection =+  "test-suite implicit-hie-test\n\+  \  type: exitcode-stdio-1.0\n\+  \  other-modules:\n\+  \      Paths_implicit_hie\n\+  \  hs-source-dirs:\n\+  \      test\n\+  \  ghc-options: -fspecialize-aggressively -Wall -Wincomplete-record-updates -Wincomplete-uni-patterns -fno-warn-unused-imports -fno-warn-unused-binds -fno-warn-name-shadowing -fwarn-redundant-constraints -threaded -rtsopts -with-rtsopts=-N\n\+  \  main-is: Spec.hs\n\+  \  build-depends:\n\+  \      attoparsec\n\+  \    , base >=4.7 && <5\n\+  \    , hspec\n\+  \    , hspec-attoparsec\n\+  \    , implicit-hie\n\+  \    , text\n\+  \  default-language: Haskell2010\n"++libSection :: Text+libSection =+  "library\n\+  \  exposed-modules:\n\+  \  Lib\n\+  \  other-modules:\n\+  \  Paths_implicit_hie\n\+  \  hs-source-dirs:\n\+  \  src\n\+  \  ghc-options: -fspecialize-aggressively -Wall -Wincomplete-record-updates -Wincomplete-uni-patterns -fno-warn-unused-imports -fno-warn-unused-binds -fno-warn-name-shadowing -fwarn-redundant-constraints\n\+  \  build-depends:\n\+  \  attoparsec\n\+  \  , base >=4.7 && <5\n\+  \  , text\n\+  \  default-language: Haskell2010\n\+  \"++libSection2 :: Text+libSection2 =+  "library\n\+  \  exposed-modules:\n\+  \  Lib\n\+  \  other-modules:\n\+  \  Paths_implicit_hie\n\+  \  hs-source-dirs:\n\+  \    src\n\+  \  hs-source-dirs:\n\+  \   src2\n\+  \  ghc-options: -fspecialize-aggressively -Wall -Wincomplete-record-updates -Wincomplete-uni-patterns -fno-warn-unused-imports -fno-warn-unused-binds -fno-warn-name-shadowing -fwarn-redundant-constraints\n\+  \  build-depends:\n\+  \  attoparsec\n\+  \  , base >=4.7 && <5\n\+  \  , text\n\+  \  default-language: Haskell2010\n\+  \"++libSection3 :: Text+libSection3 =+  "library\n\+  \  exposed-modules:\n\+  \  Lib\n\+  \  other-modules:\n\+  \  Paths_implicit_hie\n\+  \  hs-source-dirs:\n\+  \   src,\n\+  \   src2\n\+  \  ghc-options: -fspecialize-aggressively -Wall -Wincomplete-record-updates -Wincomplete-uni-patterns -fno-warn-unused-imports -fno-warn-unused-binds -fno-warn-name-shadowing -fwarn-redundant-constraints\n\+  \  build-depends:\n\+  \  attoparsec\n\+  \  , base >=4.7 && <5\n\+  \  , text\n\+  \  default-language: Haskell2010\n\+  \"