packages feed

require 0.4.5 → 0.4.6

raw patch · 8 files changed

+141/−208 lines, 8 filesdep +reludedep −universumPVP ok

version bump matches the API change (PVP)

Dependencies added: relude

Dependencies removed: universum

API changes (from Hackage documentation)

Files

benchmark/Main.hs view
@@ -1,7 +1,7 @@ -- You can benchmark your code quickly and effectively with Criterion. See its -- website for help: <http://www.serpentine.com/criterion/>. -import Universum+import Relude  main :: IO () main = putTextLn "Hello"
executable/AutoRequire/Main.hs view
@@ -1,8 +1,9 @@ -- It is generally a good idea to keep all your business logic in your library -- and only use it in the executable. Doing so allows others to use what you -- wrote in their libraries.++import Relude import qualified Require-import Universum  main :: IO () main = Require.autorequireMain
executable/Require/Main.hs view
@@ -1,8 +1,9 @@ -- It is generally a good idea to keep all your business logic in your library -- and only use it in the executable. Doing so allows others to use what you -- wrote in their libraries.++import Relude import qualified Require-import Universum  main :: IO () main = Require.requireMain
library/Require.hs view
@@ -1,27 +1,30 @@ module Require where -import Universum--import qualified Text.Megaparsec      as Megaparsec-import qualified Text.Megaparsec.Char as Megaparsec-import qualified Data.Text            as Text+import qualified Data.Text as Text import Options.Generic+import Relude import System.Directory+import qualified Text.Megaparsec as Megaparsec+import qualified Text.Megaparsec.Char as Megaparsec -newtype FileName   = FileName { unFileName :: Text }+newtype FileName = FileName {unFileName :: Text}+ newtype LineNumber = LineNumber Int-type Parser        = Megaparsec.Parsec Void Text -data RequireInfo = RequireInfo-  { riFullModuleName :: Text-  , riModuleAlias    :: Text-  , riImportedTypes  :: Maybe [Text]-  } deriving Show+type Parser = Megaparsec.Parsec Void Text -data CommandArguments =-  CommandArguments Text Text Text-  deriving Generic+data RequireInfo+  = RequireInfo+      { riFullModuleName :: Text,+        riModuleAlias :: Text,+        riImportedTypes :: Maybe [Text]+      }+  deriving (Show) +data CommandArguments+  = CommandArguments Text Text Text+  deriving (Generic)+ instance ParseRecord CommandArguments  findRequires :: IO (Maybe Text)@@ -29,24 +32,25 @@   currentDir <- getCurrentDirectory   files <- getDirectoryContents currentDir   let textFiles = fmap toText files-  return $ head <$> (nonEmpty $ filter (Text.isSuffixOf "Requires") textFiles)+  return $ head <$> nonEmpty (filter (Text.isSuffixOf "Requires") textFiles)  requireMain :: IO () requireMain = do-  CommandArguments _ inputFile outputFile <- getRecord "Require Haskell preprocessor" :: IO CommandArguments+  CommandArguments inputFile _ outputFile <- getRecord "Require Haskell preprocessor" :: IO CommandArguments   content <- readFile (toString inputFile)   writeFile     (toString outputFile)-    ( Require.transform-        False-        (Require.FileName inputFile)-        ""-        content+    ( toString $+        Require.transform+          False+          (Require.FileName inputFile)+          ""+          (toText content)     )  autorequireMain :: IO () autorequireMain = do-  CommandArguments _ inputFile outputFile <- getRecord "Require Haskell preprocessor" :: IO CommandArguments+  CommandArguments inputFile _ outputFile <- getRecord "Require Haskell preprocessor" :: IO CommandArguments   requiresFile <- findRequires   case requiresFile of     Nothing -> die "There is no Requires file in the system"@@ -55,97 +59,97 @@       content <- readFile (toString inputFile)       writeFile         (toString outputFile)-        (Require.transform-          True-          (Require.FileName inputFile)-          file-          content)+        ( toString $+            Require.transform+              True+              (Require.FileName inputFile)+              (toText file)+              (toText content)+        )  transform :: Bool -> FileName -> Text -> Text -> Text transform autorequireEnabled filename imports input   | autorequireEnabled = transform' True filename imports input-  | noAutorequire  = transform' False filename imports input-  | otherwise      = transform' True filename imports input- where-  noAutorequire = (length $ filter (\t -> "autorequire" `Text.isPrefixOf` t) $ lines input) == 0-+  | noAutorequire = transform' False filename imports input+  | otherwise = transform' True filename imports input+  where+    noAutorequire = not (any ("autorequire" `Text.isPrefixOf`) $ lines input)  transform' :: Bool -> FileName -> Text -> Text -> Text transform' shouldPrepend filename prepended input =   Text.lines input-  &   filter (\t -> not $ "autorequire" `Text.isPrefixOf` t)-  &   zip [1..]-  >>= prependAfterModuleLine-  <&> (\(ln, text) -> maybe (text <> "\n") (renderImport filename (LineNumber ln)) $ Megaparsec.parseMaybe requireParser text)-  &   (lineTag filename (LineNumber 1) :)-  &   Text.concat- where-  enumeratedPrepend ln-   | shouldPrepend = zip (repeat ln) (Text.lines prepended)-   | otherwise     = []-  prependAfterModuleLine (ln, text)-   | ("module" `Text.isPrefixOf` text)-     && ("where" `Text.isSuffixOf`) text = (ln, text) : enumeratedPrepend ln-   | ("instance" `Text.isPrefixOf` text)-     && ("where" `Text.isSuffixOf`) text = [(ln, text)]-   | ("data" `Text.isPrefixOf` text)-     && ("where" `Text.isSuffixOf`) text = [(ln, text)]-   | ("class" `Text.isPrefixOf` text)-     && ("where" `Text.isSuffixOf`) text = [(ln, text)]-   | (not $ "instance" `Text.isPrefixOf` text)-     && (not $ "class" `Text.isPrefixOf` text)-     && (not $ "data" `Text.isPrefixOf` text)-     && ("where" `Text.isPrefixOf`) text = (ln, text) : enumeratedPrepend (ln)-   | otherwise                      = [(ln, text)]+    & filter (\t -> not $ "autorequire" `Text.isPrefixOf` t)+    & zip [1 ..]+    >>= prependAfterModuleLine+    <&> (\(ln, text) -> maybe (text <> "\n") (renderImport filename (LineNumber ln)) $ Megaparsec.parseMaybe requireParser text)+    & (lineTag filename (LineNumber 1) :)+    & Text.concat+  where+    enumeratedPrepend ln+      | shouldPrepend = zip (repeat ln) (Text.lines prepended)+      | otherwise = []+    prependAfterModuleLine (ln, text)+      | ("module" `Text.isPrefixOf` text)+          && ("where" `Text.isSuffixOf`) text =+        (ln, text) : enumeratedPrepend ln+      | ("instance" `Text.isPrefixOf` text)+          && ("where" `Text.isSuffixOf`) text =+        [(ln, text)]+      | ("data" `Text.isPrefixOf` text)+          && ("where" `Text.isSuffixOf`) text =+        [(ln, text)]+      | ("class" `Text.isPrefixOf` text)+          && ("where" `Text.isSuffixOf`) text =+        [(ln, text)]+      | not ("instance" `Text.isPrefixOf` text)+          && not ("class" `Text.isPrefixOf` text)+          && not ("data" `Text.isPrefixOf` text)+          && ("where" `Text.isPrefixOf`) text =+        (ln, text) : enumeratedPrepend ln+      | otherwise = [(ln, text)]  lineTag :: FileName -> LineNumber -> Text lineTag (FileName fn) (LineNumber ln) =   "{-# LINE "-  <> show ln-  <> " \""-  <> fn-  <> "\" #-}\n"-+    <> show ln+    <> " \""+    <> fn+    <> "\" #-}\n"  renderImport :: FileName -> LineNumber -> RequireInfo -> Text renderImport filename linenumber RequireInfo {..} =-  case (Text.isInfixOf riFullModuleName (unFileName filename)) of-    True  -> ""-    False -> typesImport <> lineTag filename linenumber <> qualifiedImport- where-  types = maybe (Text.takeWhileEnd (/= '.') riFullModuleName) (Text.intercalate ",") riImportedTypes-  typesImport = "import " <> riFullModuleName <> " (" <> types <> ")\n"-  qualifiedImport = "import qualified " <> riFullModuleName <> " as " <> riModuleAlias <> "\n"-+  if Text.isInfixOf riFullModuleName (unFileName filename)+    then ""+    else typesImport <> lineTag filename linenumber <> qualifiedImport+  where+    types = maybe (Text.takeWhileEnd (/= '.') riFullModuleName) (Text.intercalate ",") riImportedTypes+    typesImport = "import " <> riFullModuleName <> " (" <> types <> ")\n"+    qualifiedImport = "import qualified " <> riFullModuleName <> " as " <> riModuleAlias <> "\n"  requireParser :: Parser RequireInfo requireParser = do   void $ Megaparsec.string "require"-  void $ Megaparsec.space1+  void Megaparsec.space1   module' <- Megaparsec.some (Megaparsec.alphaNumChar <|> Megaparsec.punctuationChar)-  void $ Megaparsec.space--  alias'  <- Megaparsec.try $ Megaparsec.option Nothing $ do+  void Megaparsec.space+  alias' <- Megaparsec.try $ Megaparsec.option Nothing $ do     void $ Megaparsec.string "as"-    void $ Megaparsec.space1-    Just <$> Megaparsec.some (Megaparsec.alphaNumChar)--  void $ Megaparsec.space--  types'  <- Megaparsec.option Nothing $ do+    void Megaparsec.space1+    Just <$> Megaparsec.some Megaparsec.alphaNumChar+  void Megaparsec.space+  types' <- Megaparsec.option Nothing $ do     void $ Megaparsec.char '('     t' <- Megaparsec.many (Megaparsec.alphaNumChar <|> Megaparsec.char ',' <|> Megaparsec.char ' ')     void $ Megaparsec.char ')'     return $ Just t'-   void $ Megaparsec.option Nothing $ do-    void $ Megaparsec.space+    void Megaparsec.space     void $ Megaparsec.some (Megaparsec.char '-')     void $ Megaparsec.many (Megaparsec.alphaNumChar <|> Megaparsec.char ' ')     return Nothing--  return RequireInfo-    { riFullModuleName = toText $ module'-    , riModuleAlias    = maybe (Text.takeWhileEnd (/= '.') $ toText module') toText alias'-    , riImportedTypes  = fmap Text.strip <$> Text.splitOn "," <$> toText <$> types'-    }+  return+    RequireInfo+      { riFullModuleName = toText module',+        riModuleAlias = maybe (Text.takeWhileEnd (/= '.') $ toText module') toText alias',+        riImportedTypes = (fmap Text.strip <$> Text.splitOn ",") . toText <$> types'+      }
package.yaml view
@@ -1,5 +1,5 @@ name: require-version: "0.4.5"+version: "0.4.6" github: "theam/require" license: Apache-2.0 author: "The Agile Monkeys"@@ -29,7 +29,7 @@  dependencies:   - base >= 4.9 && < 5-  - universum >= 1.2.0 && < 2+  - relude   - bytestring >= 0.10 && < 0.11   - text >= 1.2.3.0 && < 2   - megaparsec >= 7 && < 8
require.cabal view
@@ -4,10 +4,10 @@ -- -- see: https://github.com/sol/hpack ----- hash: b849a629980c70464aa83e3846fceb3efdc2bed39b17efb17ad90970ee0da8e7+-- hash: f6bc9c2371f0a167829d05ea4cb94a51e5d3ca3e2bc863a82685611213b5cb05  name:           require-version:        0.4.5+version:        0.4.6 synopsis:       Scrap your qualified import clutter description:    See <https://theam.github.io/require> category:       Other@@ -47,8 +47,8 @@     , inliterate     , megaparsec >=7 && <8     , optparse-generic+    , relude     , text >=1.2.3.0 && <2-    , universum >=1.2.0 && <2   default-language: Haskell2010  executable autorequirepp@@ -66,9 +66,9 @@     , inliterate     , megaparsec >=7 && <8     , optparse-generic+    , relude     , require     , text >=1.2.3.0 && <2-    , universum >=1.2.0 && <2   default-language: Haskell2010  executable requirepp@@ -86,9 +86,9 @@     , inliterate     , megaparsec >=7 && <8     , optparse-generic+    , relude     , require     , text >=1.2.3.0 && <2-    , universum >=1.2.0 && <2   default-language: Haskell2010  test-suite require-test-suite@@ -107,11 +107,11 @@     , inliterate     , megaparsec >=7 && <8     , optparse-generic+    , relude     , require     , tasty     , tasty-hspec     , text >=1.2.3.0 && <2-    , universum >=1.2.0 && <2   default-language: Haskell2010  benchmark require-benchmarks@@ -131,7 +131,7 @@     , inliterate     , megaparsec >=7 && <8     , optparse-generic+    , relude     , require     , text >=1.2.3.0 && <2-    , universum >=1.2.0 && <2   default-language: Haskell2010
stack.yaml view
@@ -1,67 +1,6 @@-# This file was automatically generated by 'stack init'-#-# Some commonly used options have been documented as comments in this file.-# For advanced use and comprehensive documentation of the format, please see:-# https://docs.haskellstack.org/en/stable/yaml_configuration/--# Resolver to choose a 'specific' stackage snapshot or a compiler version.-# A snapshot resolver dictates the compiler version and the set of packages-# to be used for project dependencies. For example:-#-# resolver: lts-3.5-# resolver: nightly-2015-09-21-# resolver: ghc-7.10.2-# resolver: ghcjs-0.1.0_ghc-7.10.2-# resolver:-#  name: custom-snapshot-#  location: "./custom-snapshot.yaml"-resolver: lts-13.3+resolver: lts-14.27 -# User packages to be built.-# Various formats can be used as shown in the example below.-#-# packages:-# - some-directory-# - https://example.com/foo/bar/baz-0.0.2.tar.gz-# - location:-#    git: https://github.com/commercialhaskell/stack.git-#    commit: e7b331f14bcffb8367cd58fbfc8b40ec7642100a-# - location: https://github.com/commercialhaskell/stack/commit/e7b331f14bcffb8367cd58fbfc8b40ec7642100a-#   extra-dep: true-#  subdirs:-#  - auto-update-#  - wai-#-# A package marked 'extra-dep: true' will only be built if demanded by a-# non-dependency (i.e. a user package), and its test suites and benchmarks-# will not be run. This is useful for tweaking upstream packages. packages:-- .-# Dependency packages to be pulled from upstream that are not in the resolver-# (e.g., acme-missiles-0.3)-extra-deps:-  - universum-1.2.0--# Override default flag values for local packages and extra-deps-# flags: {}--# Extra package databases containing global packages-# extra-package-dbs: []+  - . -# Control whether we use the GHC we find on the path-# system-ghc: true-#-# Require a specific version of stack, using version ranges-# require-stack-version: -any # Default-# require-stack-version: ">=1.6"-#-# Override the architecture used by stack, especially useful on Windows-# arch: i386-# arch: x86_64-#-# Extra directories used by stack for building-# extra-include-dirs: [/path/to/dir]-# extra-lib-dirs: [/path/to/dir]-#-# Allow a newer minor version of GHC than the snapshot specifies-# compiler-check: newer-minor+extra-deps: []
test-suite/Main.hs view
@@ -1,81 +1,69 @@-import           Universum--import qualified Data.Text        as Text-import qualified Test.Tasty-import           Test.Tasty.Hspec-+import qualified Data.Text as Text+import Relude import qualified Require-+import qualified Test.Tasty+import Test.Tasty.Hspec  main :: IO () main = do-    test <- testSpec "require" spec-    Test.Tasty.defaultMain test-+  test <- testSpec "require" spec+  Test.Tasty.defaultMain test  spec :: Spec spec = parallel $ do   it "transforms the 'require' keyword into a properly qualified import" $ do-    let input    = "require Data.Text"+    let input = "require Data.Text"     let expected = "import qualified Data.Text as Text"-    let actual   = Require.transform False (Require.FileName "Foo.hs") "" input+    let actual = Require.transform False (Require.FileName "Foo.hs") "" input     expected `Text.isInfixOf` actual-   it "imports the type based on the module" $ do-    let input    = "require Data.Text"+    let input = "require Data.Text"     let expected = "import Data.Text (Text)"-    let actual   = Require.transform False (Require.FileName "Foo.hs") "" input+    let actual = Require.transform False (Require.FileName "Foo.hs") "" input     expected `Text.isInfixOf` actual-   it "keeps the rest of the content intact" $ do-    let input                   = "module Foo where\nrequire Data.Text\nfoo = 42"-    let expectedStart           = "{-# LINE 1"-    let expectedModule          = "module Foo where"-    let expectedTypeImport      = "import Data.Text (Text)"+    let input = "module Foo where\nrequire Data.Text\nfoo = 42"+    let expectedStart = "{-# LINE 1"+    let expectedModule = "module Foo where"+    let expectedTypeImport = "import Data.Text (Text)"     let expectedQualifiedImport = "import qualified Data.Text as Text"-    let expectedContent         = "foo = 42\n"-    let actual                  = toString $ Require.transform False (Require.FileName "Foo.hs") "" input+    let expectedContent = "foo = 42\n"+    let actual = toString $ Require.transform False (Require.FileName "Foo.hs") "" input     actual `shouldStartWith` expectedStart-    actual `shouldContain`   expectedModule-    actual `shouldContain`   expectedTypeImport-    actual `shouldContain`   expectedQualifiedImport-    actual `shouldEndWith`   expectedContent-+    actual `shouldContain` expectedModule+    actual `shouldContain` expectedTypeImport+    actual `shouldContain` expectedQualifiedImport+    actual `shouldEndWith` expectedContent   it "aliases the modules properly" $ do     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 False (Require.FileName "Foo.hs") "" input-    actual `shouldContain`   expectedTypeImport-    actual `shouldContain`   expectedQualifiedImport-+    actual `shouldContain` expectedTypeImport+    actual `shouldContain` expectedQualifiedImport   it "imports the types properly" $ do     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 False (Require.FileName "Foo.hs") "" input-    actual `shouldContain`   expectedTypeImport-    actual `shouldContain`   expectedQualifiedImport-+    actual `shouldContain` expectedTypeImport+    actual `shouldContain` expectedQualifiedImport   it "imports the types and aliases the modules properly" $ do     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 False (Require.FileName "Foo.hs") "" input-    actual `shouldContain`   expectedTypeImport-    actual `shouldContain`   expectedQualifiedImport-+    actual `shouldContain` expectedTypeImport+    actual `shouldContain` expectedQualifiedImport   it "skips comments" $ do-    let input    = "require Data.Text -- test of comments"+    let input = "require Data.Text -- test of comments"     let expected = "import Data.Text (Text)"-    let actual   = Require.transform False (Require.FileName "Foo.hs") "" input+    let actual = Require.transform False (Require.FileName "Foo.hs") "" input     expected `Text.isInfixOf` actual-   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 False (Require.FileName "Foo.hs") "" input+    let input = "require Data.Text ()"+    let expected1 = "import Data.Text ()"+    let expected2 = "import qualified Data.Text as Text"+    let actual = lines $ Require.transform False (Require.FileName "Foo.hs") "" input     actual `shouldSatisfy` elem expected1     actual `shouldSatisfy` elem expected2-