From 388f520a1fde7abc0962845a95ff72d7112d166e Mon Sep 17 00:00:00 2001 From: Yuriy Syrovetskiy Date: Thu, 11 Apr 2019 18:27:46 +0300 Subject: [PATCH 1/9] Gardening code with hlint --- .../src/Language/C/Inline/Cpp/Exceptions.hs | 6 +-- inline-c-cpp/test/tests.hs | 3 +- inline-c/src/Language/C/Inline.hs | 5 +-- inline-c/src/Language/C/Inline/Context.hs | 20 +++++----- .../Language/C/Inline/HaskellIdentifier.hs | 5 +-- inline-c/src/Language/C/Inline/Internal.hs | 4 +- inline-c/src/Language/C/Types.hs | 25 ++++++------ inline-c/src/Language/C/Types/Parse.hs | 15 ++++--- .../test/Language/C/Inline/ContextSpec.hs | 40 +++++++++---------- inline-c/test/Language/C/Inline/ParseSpec.hs | 23 +++++------ inline-c/test/Language/C/Types/ParseSpec.hs | 27 ++++++------- inline-c/test/tests.hs | 12 +++--- 12 files changed, 90 insertions(+), 95 deletions(-) diff --git a/inline-c-cpp/src/Language/C/Inline/Cpp/Exceptions.hs b/inline-c-cpp/src/Language/C/Inline/Cpp/Exceptions.hs index 1217b04..004ccbb 100644 --- a/inline-c-cpp/src/Language/C/Inline/Cpp/Exceptions.hs +++ b/inline-c-cpp/src/Language/C/Inline/Cpp/Exceptions.hs @@ -70,7 +70,7 @@ handleForeignCatch cont = -- them in an 'Either' throwBlock :: QuasiQuoter throwBlock = QuasiQuoter - { quoteExp = \blockStr -> do + { quoteExp = \blockStr -> [e| either throwIO return =<< $(tryBlockQuoteExp blockStr) |] , quotePat = unsupported , quoteType = unsupported @@ -87,7 +87,7 @@ catchBlock = QuasiQuoter , quoteDec = unsupported } where unsupported _ = fail "Unsupported quasiquotation." - + tryBlockQuoteExp :: String -> Q Exp tryBlockQuoteExp blockStr = do @@ -147,7 +147,7 @@ tryBlockQuoteExp blockStr = do , "}" ] [e| handleForeignCatch $ \ $(varP typePtrVarName) $(varP msgPtrVarName) -> $(quoteExp C.block inlineCStr) |] - + -- | Similar to `C.block`, but C++ exceptions will be caught and the result is (Either CppException value). The return type must be void or constructible with @{}@. -- Using this will automatically include @exception@, @cstring@ and @cstdlib@. tryBlock :: QuasiQuoter diff --git a/inline-c-cpp/test/tests.hs b/inline-c-cpp/test/tests.hs index b84bbd1..a086884 100644 --- a/inline-c-cpp/test/tests.hs +++ b/inline-c-cpp/test/tests.hs @@ -3,7 +3,6 @@ {-# LANGUAGE ScopedTypeVariables #-} import Control.Exception.Safe -import Control.Monad import qualified Language.C.Inline.Cpp as C import qualified Language.C.Inline.Cpp.Exceptions as C import qualified Test.Hspec as Hspec @@ -16,7 +15,7 @@ C.include "" main :: IO () main = Hspec.hspec $ do - Hspec.describe "Basic C++" $ do + Hspec.describe "Basic C++" $ Hspec.it "Hello World" $ do let x = 3 [C.block| void { diff --git a/inline-c/src/Language/C/Inline.hs b/inline-c/src/Language/C/Inline.hs index d6810f5..1fbe98f 100644 --- a/inline-c/src/Language/C/Inline.hs +++ b/inline-c/src/Language/C/Inline.hs @@ -1,10 +1,7 @@ {-# LANGUAGE CPP #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE OverloadedStrings #-} -{-# LANGUAGE QuasiQuotes #-} -{-# LANGUAGE RecordWildCards #-} {-# LANGUAGE ScopedTypeVariables #-} -{-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeFamilies #-} {-# LANGUAGE TypeOperators #-} @@ -315,7 +312,7 @@ verbatim s = do -- | Like 'alloca', but also peeks the contents of the 'Ptr' and returns -- them once the provided action has finished. withPtr :: (Storable a) => (Ptr a -> IO b) -> IO (a, b) -withPtr f = do +withPtr f = alloca $ \ptr -> do x <- f ptr y <- peek ptr diff --git a/inline-c/src/Language/C/Inline/Context.hs b/inline-c/src/Language/C/Inline/Context.hs index 108b11d..2495f38 100644 --- a/inline-c/src/Language/C/Inline/Context.hs +++ b/inline-c/src/Language/C/Inline/Context.hs @@ -174,7 +174,9 @@ instance Monoid Context where , ctxForeignSrcLang = Nothing } -#if !MIN_VERSION_base(4,11,0) +#if MIN_VERSION_base(4,9,0) + mappend = (<>) +#else mappend ctx2 ctx1 = Context { ctxTypesTable = ctxTypesTable ctx1 <> ctxTypesTable ctx2 , ctxAntiQuoters = ctxAntiQuoters ctx1 <> ctxAntiQuoters ctx2 @@ -278,7 +280,7 @@ convertType purity cTypes = runMaybeT . go C.Array _mbSize cTy' -> do hsTy <- go cTy' lift [t| CArray $(return hsTy) |] - C.Proto _retType _pars -> do + C.Proto _retType _pars -> -- We cannot convert standalone prototypes mzero @@ -453,7 +455,7 @@ vecLenAntiQuoter = AntiQuoter hId <- C.parseIdentifier let cId = mangleHaskellIdentifier hId return (cId, C.TypeSpecifier mempty (C.Long C.Signed), hId) - , aqMarshaller = \_purity _cTypes cTy cId -> do + , aqMarshaller = \_purity _cTypes cTy cId -> case cTy of C.TypeSpecifier _ (C.Long C.Signed) -> do hsExp <- getHsVariable "vecCtx" cId @@ -461,7 +463,7 @@ vecLenAntiQuoter = AntiQuoter hsTy <- [t| CLong |] hsExp'' <- [| \cont -> cont $(return hsExp') |] return (hsTy, hsExp'') - _ -> do + _ -> fail "impossible: got type different from `long' (vecCtx)" } @@ -488,7 +490,7 @@ bsPtrAntiQuoter = AntiQuoter hId <- C.parseIdentifier let cId = mangleHaskellIdentifier hId return (cId, C.Ptr [] (C.TypeSpecifier mempty (C.Char Nothing)), hId) - , aqMarshaller = \_purity _cTypes cTy cId -> do + , aqMarshaller = \_purity _cTypes cTy cId -> case cTy of C.Ptr _ (C.TypeSpecifier _ (C.Char Nothing)) -> do hsTy <- [t| Ptr CChar |] @@ -505,7 +507,7 @@ bsLenAntiQuoter = AntiQuoter hId <- C.parseIdentifier let cId = mangleHaskellIdentifier hId return (cId, C.TypeSpecifier mempty (C.Long C.Signed), hId) - , aqMarshaller = \_purity _cTypes cTy cId -> do + , aqMarshaller = \_purity _cTypes cTy cId -> case cTy of C.TypeSpecifier _ (C.Long C.Signed) -> do hsExp <- getHsVariable "bsCtx" cId @@ -513,7 +515,7 @@ bsLenAntiQuoter = AntiQuoter hsTy <- [t| CLong |] hsExp'' <- [| \cont -> cont $(return hsExp') |] return (hsTy, hsExp'') - _ -> do + _ -> fail "impossible: got type different from `long' (bsCtx)" } @@ -523,7 +525,7 @@ bsCStrAntiQuoter = AntiQuoter hId <- C.parseIdentifier let cId = mangleHaskellIdentifier hId return (cId, C.Ptr [] (C.TypeSpecifier mempty (C.Char Nothing)), hId) - , aqMarshaller = \_purity _cTypes cTy cId -> do + , aqMarshaller = \_purity _cTypes cTy cId -> case cTy of C.Ptr _ (C.TypeSpecifier _ (C.Char Nothing)) -> do hsTy <- [t| Ptr CChar |] @@ -553,7 +555,7 @@ cDeclAqParser = do deHaskellifyCType :: C.CParser HaskellIdentifier m => C.Type HaskellIdentifier -> m (C.Type C.CIdentifier) -deHaskellifyCType = traverse $ \hId -> do +deHaskellifyCType = traverse $ \hId -> case C.cIdentifierFromString (unHaskellIdentifier hId) of Left err -> fail $ "Illegal Haskell identifier " ++ unHaskellIdentifier hId ++ " in C type:\n" ++ err diff --git a/inline-c/src/Language/C/Inline/HaskellIdentifier.hs b/inline-c/src/Language/C/Inline/HaskellIdentifier.hs index 57b48c9..2d061ce 100644 --- a/inline-c/src/Language/C/Inline/HaskellIdentifier.hs +++ b/inline-c/src/Language/C/Inline/HaskellIdentifier.hs @@ -21,7 +21,7 @@ import Control.Monad (when, msum, void) import Data.Char (ord) import qualified Data.HashSet as HashSet import Data.Hashable (Hashable) -import Data.List (intercalate, partition, intersperse) +import Data.List (intercalate, partition) import Data.Monoid ((<>)) import Data.String (IsString(..)) import Data.Typeable (Typeable) @@ -135,7 +135,7 @@ mangleHaskellIdentifier (HaskellIdentifier hs) = where (valid, invalid) = partition (`elem` C.cIdentLetter) hs - mangled = concat $ intersperse "_" $ map (`showHex` "") $ map ord invalid + mangled = intercalate "_" $ map ((`showHex` "") . ord) invalid -- Utils ------------------------------------------------------------------------ @@ -146,4 +146,3 @@ identNoLex s = fmap fromString $ try $ do ((:) <$> _styleStart s <*> many (_styleLetter s) _styleName s) when (HashSet.member name (_styleReserved s)) $ unexpected $ "reserved " ++ _styleName s ++ " " ++ show name return name - diff --git a/inline-c/src/Language/C/Inline/Internal.hs b/inline-c/src/Language/C/Inline/Internal.hs index 8a301ca..d4ac8ee 100644 --- a/inline-c/src/Language/C/Inline/Internal.hs +++ b/inline-c/src/Language/C/Inline/Internal.hs @@ -425,7 +425,7 @@ instance Show SomeEq where toSomeEq :: (Eq a, Typeable a) => a -> SomeEq toSomeEq x = SomeEq x -fromSomeEq :: (Eq a, Typeable a) => SomeEq -> Maybe a +fromSomeEq :: Typeable a => SomeEq -> Maybe a fromSomeEq (SomeEq x) = cast x data ParameterType @@ -523,7 +523,7 @@ parseTypedC antiQs = do -- The @m@ is polymorphic because we use this both for the plain -- parser and the StateT parser we use above. We only need 'fail'. purgeHaskellIdentifiers - :: forall n. (Applicative n, Monad n) + :: forall n. Monad n => C.Type HaskellIdentifier -> n (C.Type C.CIdentifier) purgeHaskellIdentifiers cTy = for cTy $ \hsIdent -> do let hsIdentS = unHaskellIdentifier hsIdent diff --git a/inline-c/src/Language/C/Types.hs b/inline-c/src/Language/C/Types.hs index a5c4d39..996ff73 100644 --- a/inline-c/src/Language/C/Types.hs +++ b/inline-c/src/Language/C/Types.hs @@ -3,7 +3,6 @@ {-# LANGUAGE DeriveDataTypeable #-} {-# LANGUAGE DeriveFoldable #-} {-# LANGUAGE DeriveFunctor #-} -{-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE DeriveTraversable #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} @@ -117,7 +116,9 @@ instance Semigroup Specifiers where instance Monoid Specifiers where mempty = Specifiers [] [] [] -#if !MIN_VERSION_base(4,11,0) +#if MIN_VERSION_base(4,9,0) + mappend = (<>) +#else mappend (Specifiers x1 y1 z1) (Specifiers x2 y2 z2) = Specifiers (x1 ++ x2) (y1 ++ y2) (z1 ++ z2) #endif @@ -136,7 +137,7 @@ data Sign data ParameterDeclaration i = ParameterDeclaration { parameterDeclarationId :: Maybe i - , parameterDeclarationType :: (Type i) + , parameterDeclarationType :: Type i } deriving (Typeable, Show, Eq, Functor, Foldable, Traversable) ------------------------------------------------------------------------ @@ -167,7 +168,7 @@ untangleParameterDeclaration P.ParameterDeclaration{..} = do untangleDeclarationSpecifiers :: [P.DeclarationSpecifier] -> Either UntangleErr (Specifiers, TypeSpecifier) untangleDeclarationSpecifiers declSpecs = do - let (pStorage, pTySpecs, pTyQuals, pFunSpecs) = flip execState ([], [], [], []) $ do + let (pStorage, pTySpecs, pTyQuals, pFunSpecs) = flip execState ([], [], [], []) $ forM_ (reverse declSpecs) $ \declSpec -> case declSpec of P.StorageClassSpecifier x -> modify $ \(a, b, c, d) -> (x:a, b, c, d) P.TypeSpecifier x -> modify $ \(a, b, c, d) -> (a, x:b, c, d) @@ -175,7 +176,7 @@ untangleDeclarationSpecifiers declSpecs = do P.FunctionSpecifier x -> modify $ \(a, b, c, d) -> (a, b, c, x:d) -- Split data type and specifiers let (dataTypes, specs) = - partition (\x -> not (x `elem` [P.SIGNED, P.UNSIGNED, P.LONG, P.SHORT])) pTySpecs + partition (`notElem` [P.SIGNED, P.UNSIGNED, P.LONG, P.SHORT]) pTySpecs let illegalSpecifiers s = failConversion $ IllegalSpecifiers s specs -- Find out sign, if present mbSign0 <- case filter (== P.SIGNED) specs of @@ -219,26 +220,26 @@ untangleDeclarationSpecifiers declSpecs = do P.CHAR -> do checkNoLength return $ Char mbSign - P.INT | longs == 0 && shorts == 0 -> do + P.INT | longs == 0 && shorts == 0 -> return $ Int sign - P.INT | longs == 1 -> do + P.INT | longs == 1 -> return $ Long sign - P.INT | longs == 2 -> do + P.INT | longs == 2 -> return $ LLong sign - P.INT | shorts == 1 -> do + P.INT | shorts == 1 -> return $ Short sign - P.INT -> do + P.INT -> illegalSpecifiers "too many long/short" P.FLOAT -> do checkNoLength return Float - P.DOUBLE -> do + P.DOUBLE -> if longs == 1 then return LDouble else do checkNoLength return Double - _ -> do + _ -> error $ "untangleDeclarationSpecifiers impossible: " ++ show dataType return (Specifiers pStorage pTyQuals pFunSpecs, tySpec) diff --git a/inline-c/src/Language/C/Types/Parse.hs b/inline-c/src/Language/C/Types/Parse.hs index dfc2f95..c2c2981 100644 --- a/inline-c/src/Language/C/Types/Parse.hs +++ b/inline-c/src/Language/C/Types/Parse.hs @@ -186,7 +186,7 @@ runCParser -- ^ Source name. -> s -- ^ String to parse. - -> (ReaderT (CParserContext i) (Parsec.Parsec s ()) a) + -> ReaderT (CParserContext i) (Parsec.Parsec s ()) a -- ^ Parser. Anything with type @forall m. CParser i m => m a@ is a -- valid argument. -> Either Parsec.ParseError a @@ -198,7 +198,7 @@ quickCParser :: CParserContext i -> String -- ^ String to parse. - -> (ReaderT (CParserContext i) (Parsec.Parsec String ()) a) + -> ReaderT (CParserContext i) (Parsec.Parsec String ()) a -- ^ Parser. Anything with type @forall m. CParser i m => m a@ is a -- valid argument. -> a @@ -211,7 +211,7 @@ quickCParser typeNames s p = case runCParser typeNames "quickCParser" s p of quickCParser_ :: String -- ^ String to parse. - -> (ReaderT (CParserContext CIdentifier) (Parsec.Parsec String ()) a) + -> ReaderT (CParserContext CIdentifier) (Parsec.Parsec String ()) a -- ^ Parser. Anything with type @forall m. CParser i m => m a@ is a -- valid argument. -> a @@ -235,7 +235,7 @@ cIdentStart = ['a'..'z'] ++ ['A'..'Z'] ++ ['_'] cIdentLetter :: [Char] cIdentLetter = ['a'..'z'] ++ ['A'..'Z'] ++ ['_'] ++ ['0'..'9'] -cIdentStyle :: (TokenParsing m, Monad m) => IdentifierStyle m +cIdentStyle :: TokenParsing m => IdentifierStyle m cIdentStyle = IdentifierStyle { _styleName = "C identifier" , _styleStart = oneOf cIdentStart @@ -376,7 +376,7 @@ function_specifier = msum data Declarator i = Declarator { declaratorPointers :: [Pointer] - , declaratorDirect :: (DirectDeclarator i) + , declaratorDirect :: DirectDeclarator i } deriving (Typeable, Eq, Show, Functor, Foldable, Traversable) declarator :: CParser i m => m (Declarator i) @@ -424,7 +424,7 @@ direct_declarator = do aops <- many array_or_proto return $ foldl ArrayOrProto ddecltor aops -data Pointer +newtype Pointer = Pointer [TypeQualifier] deriving (Typeable, Eq, Show) @@ -539,8 +539,7 @@ instance Pretty i => Pretty (Declarator i) where _:_ -> prettyPointers ptrs <+> pretty ddecltor prettyPointers :: [Pointer] -> Doc -prettyPointers [] = "" -prettyPointers (x : xs) = pretty x <> prettyPointers xs +prettyPointers = foldr ((<>) . pretty) "" instance Pretty Pointer where pretty (Pointer tyQual) = "*" <> hsep (map pretty tyQual) diff --git a/inline-c/test/Language/C/Inline/ContextSpec.hs b/inline-c/test/Language/C/Inline/ContextSpec.hs index 9c7ec2b..15ee5b1 100644 --- a/inline-c/test/Language/C/Inline/ContextSpec.hs +++ b/inline-c/test/Language/C/Inline/ContextSpec.hs @@ -26,52 +26,52 @@ import Language.C.Inline.Context spec :: Hspec.SpecWith () spec = do - Hspec.it "converts simple type correctly (1)" $ do + Hspec.it "converts simple type correctly (1)" $ shouldBeType (cty "int") [t| CInt |] - Hspec.it "converts simple type correctly (2)" $ do + Hspec.it "converts simple type correctly (2)" $ shouldBeType (cty "char") [t| CChar |] - Hspec.it "converts void" $ do + Hspec.it "converts void" $ shouldBeType (cty "void") [t| () |] - Hspec.it "converts standard library types (1)" $ do + Hspec.it "converts standard library types (1)" $ shouldBeType (cty "FILE") [t| CFile |] - Hspec.it "converts standard library types (2)" $ do + Hspec.it "converts standard library types (2)" $ shouldBeType (cty "uint16_t") [t| Word16 |] - Hspec.it "converts standard library types (3)" $ do + Hspec.it "converts standard library types (3)" $ shouldBeType (cty "jmp_buf") [t| CJmpBuf |] - Hspec.it "converts single ptr type" $ do + Hspec.it "converts single ptr type" $ shouldBeType (cty "long*") [t| Ptr CLong |] - Hspec.it "converts double ptr type" $ do + Hspec.it "converts double ptr type" $ shouldBeType (cty "unsigned long**") [t| Ptr (Ptr CULong) |] - Hspec.it "converts arrays" $ do + Hspec.it "converts arrays" $ shouldBeType (cty "double[]") [t| CArray CDouble |] - Hspec.it "converts named things" $ do + Hspec.it "converts named things" $ shouldBeType (cty "unsigned int foo[]") [t| CArray CUInt |] - Hspec.it "converts arrays of pointers" $ do + Hspec.it "converts arrays of pointers" $ shouldBeType (cty "unsigned short *foo[]") [t| CArray (Ptr CUShort) |] - Hspec.it "ignores qualifiers" $ do + Hspec.it "ignores qualifiers" $ shouldBeType (cty "const short*") [t| Ptr CShort |] - Hspec.it "ignores storage information" $ do + Hspec.it "ignores storage information" $ shouldBeType (cty "extern unsigned long") [t| CULong |] - Hspec.it "converts sized arrays" $ do + Hspec.it "converts sized arrays" $ shouldBeType (cty "float[4]") [t| CArray CFloat |] - Hspec.it "converts variably sized arrays" $ do + Hspec.it "converts variably sized arrays" $ shouldBeType (cty "float[*]") [t| CArray CFloat |] - Hspec.it "converts function pointers" $ do + Hspec.it "converts function pointers" $ shouldBeType (cty "int (*f)(unsigned char, float)") [t| FunPtr (CUChar -> CFloat -> IO CInt) |] - Hspec.it "converts complicated function pointers (1)" $ do + Hspec.it "converts complicated function pointers (1)" $ -- pointer to function returning pointer to function returning int shouldBeType (cty "int (*(*)())()") [t| FunPtr (IO (FunPtr (IO CInt))) |] - Hspec.it "converts complicated function pointerst (2)" $ do + Hspec.it "converts complicated function pointerst (2)" $ -- foo is an array of pointer to pointer to function returning -- pointer to array of pointer to char shouldBeType (cty "char *(*(**foo [])())[]") [t| CArray (Ptr (FunPtr (IO (Ptr (CArray (Ptr CChar)))))) |] - Hspec.it "converts complicated function pointers (3)" $ do + Hspec.it "converts complicated function pointers (3)" $ -- foo is an array of pointer to pointer to function taking int -- returning pointer to array of pointer to char shouldBeType @@ -81,7 +81,7 @@ spec = do goodConvert cTy = do mbHsTy <- TH.runQ $ convertType IO baseTypes cTy case mbHsTy of - Nothing -> error $ "Could not convert type (goodConvert)" + Nothing -> error "Could not convert type (goodConvert)" Just hsTy -> return hsTy shouldBeType cTy hsTy = do diff --git a/inline-c/test/Language/C/Inline/ParseSpec.hs b/inline-c/test/Language/C/Inline/ParseSpec.hs index 92c943a..d7e5e51 100644 --- a/inline-c/test/Language/C/Inline/ParseSpec.hs +++ b/inline-c/test/Language/C/Inline/ParseSpec.hs @@ -5,7 +5,6 @@ {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE QuasiQuotes #-} -{-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE OverloadedStrings #-} module Language.C.Inline.ParseSpec (spec) where @@ -30,45 +29,45 @@ import Language.C.Inline.Internal import qualified Language.C.Types as C spec :: Hspec.SpecWith () -spec = do +spec = Hspec.describe "parsing" $ do Hspec.it "parses simple C expression" $ do (retType, params, cExp) <- goodParse [r| int { (int) ceil($(double x) + ((double) $(float y))) } |] - retType `Hspec.shouldBe` (cty "int") + retType `Hspec.shouldBe` cty "int" params `shouldMatchParameters` [(cty "double", Plain "x"), (cty "float", Plain "y")] cExp `shouldMatchBody` " (int) ceil(x[a-z0-9_]+ \\+ ((double) y[a-z0-9_]+)) " - Hspec.it "accepts anti quotes" $ do + Hspec.it "accepts anti quotes" $ void $ goodParse [r| int { $(int x) } |] - Hspec.it "rejects if bad braces (1)" $ do + Hspec.it "rejects if bad braces (1)" $ badParse [r| int x |] - Hspec.it "rejects if bad braces (2)" $ do + Hspec.it "rejects if bad braces (2)" $ badParse [r| int { x |] - Hspec.it "parses function pointers" $ do + Hspec.it "parses function pointers" $ void $ goodParse [r| int(int (*add)(int, int)) { add(3, 4) } |] Hspec.it "parses returning function pointers" $ do (retType, params, cExp) <- goodParse [r| double (*)(double) { &cos } |] - retType `Hspec.shouldBe` (cty "double (*)(double)") + retType `Hspec.shouldBe` cty "double (*)(double)" params `shouldMatchParameters` [] cExp `shouldMatchBody` " &cos " Hspec.it "parses Haskell identifier (1)" $ do (retType, params, cExp) <- goodParse [r| double { $(double x') } |] - retType `Hspec.shouldBe` (cty "double") + retType `Hspec.shouldBe` cty "double" params `shouldMatchParameters` [(cty "double", Plain "x'")] cExp `shouldMatchBody` " x[a-z0-9_]+ " Hspec.it "parses Haskell identifier (2)" $ do (retType, params, cExp) <- goodParse [r| double { $(double ä') } |] - retType `Hspec.shouldBe` (cty "double") + retType `Hspec.shouldBe` cty "double" params `shouldMatchParameters` [(cty "double", Plain "ä'")] cExp `shouldMatchBody` " [a-z0-9_]+ " Hspec.it "parses Haskell identifier (3)" $ do (retType, params, cExp) <- goodParse [r| int { $(int Foo.bar) } |] - retType `Hspec.shouldBe` (cty "int") + retType `Hspec.shouldBe` cty "int" params `shouldMatchParameters` [(cty "int", Plain "Foo.bar")] cExp `shouldMatchBody` " Foobar[a-z0-9_]+ " - Hspec.it "does not parse Haskell identifier in bad position" $ do + Hspec.it "does not parse Haskell identifier in bad position" $ badParse [r| double (*)(double Foo.bar) { 3.0 } |] where ctx = baseCtx <> funCtx diff --git a/inline-c/test/Language/C/Types/ParseSpec.hs b/inline-c/test/Language/C/Types/ParseSpec.hs index 4426118..9012597 100644 --- a/inline-c/test/Language/C/Types/ParseSpec.hs +++ b/inline-c/test/Language/C/Types/ParseSpec.hs @@ -29,7 +29,7 @@ import Prelude -- Fix for 7.10 unused warnings. spec :: Hspec.SpecWith () spec = do - Hspec.it "parses everything which is pretty-printable (C)" $ do + Hspec.it "parses everything which is pretty-printable (C)" $ #if MIN_VERSION_QuickCheck(2,9,0) QC.property $ QC.again $ do -- Work around #else @@ -40,7 +40,7 @@ spec = do return $ isGoodType ty QC.==> let ty' = assertParse (cCParserContext typeNames) parameter_declaration (prettyOneLine ty) in Types.untangleParameterDeclaration ty == Types.untangleParameterDeclaration ty' - Hspec.it "parses everything which is pretty-printable (Haskell)" $ do + Hspec.it "parses everything which is pretty-printable (Haskell)" $ #if MIN_VERSION_QuickCheck(2,9,0) QC.property $ QC.again $ do -- Work around #else @@ -92,7 +92,7 @@ halveSize m = QC.sized $ \n -> QC.resize (n `div` 2) m instance QC.Arbitrary CIdentifier where arbitrary = do - s <- ((:) <$> QC.elements cIdentStart <*> QC.listOf (QC.elements cIdentLetter)) + s <- (:) <$> QC.elements cIdentStart <*> QC.listOf (QC.elements cIdentLetter) if HashSet.member s cReservedWords then QC.arbitrary else return $ fromString s @@ -101,7 +101,7 @@ instance QC.Arbitrary CIdentifier where -- arbitrary allowed type names. data ParameterDeclarationWithTypeNames i = ParameterDeclarationWithTypeNames { _pdwtnTypeNames :: HashSet.HashSet CIdentifier - , _pdwtnParameterDeclaration :: (ParameterDeclaration i) + , _pdwtnParameterDeclaration :: ParameterDeclaration i } deriving (Typeable, Eq, Show) data ArbitraryContext i = ArbitraryContext @@ -120,8 +120,8 @@ arbitraryParameterDeclarationWithTypeNames identToString = do return $ ParameterDeclarationWithTypeNames names decl arbitraryDeclarationSpecifierFrom - :: (QC.Arbitrary i, Hashable i) => ArbitraryContext i -> QC.Gen DeclarationSpecifier -arbitraryDeclarationSpecifierFrom typeNames = QC.oneof $ + :: ArbitraryContext i -> QC.Gen DeclarationSpecifier +arbitraryDeclarationSpecifierFrom typeNames = QC.oneof [ StorageClassSpecifier <$> QC.arbitrary , TypeQualifier <$> QC.arbitrary , FunctionSpecifier <$> QC.arbitrary @@ -137,7 +137,7 @@ instance QC.Arbitrary StorageClassSpecifier where , return REGISTER ] -arbitraryTypeSpecifierFrom :: (Hashable i, QC.Arbitrary i) => ArbitraryContext i -> QC.Gen TypeSpecifier +arbitraryTypeSpecifierFrom :: ArbitraryContext i -> QC.Gen TypeSpecifier arbitraryTypeSpecifierFrom ctx = QC.oneof $ [ return VOID , return CHAR @@ -170,8 +170,7 @@ arbitraryDeclaratorFrom arbitraryDeclaratorFrom typeNames = halveSize $ Declarator <$> QC.arbitrary <*> arbitraryDirectDeclaratorFrom typeNames -arbitraryCIdentifierFrom - :: (Hashable i, QC.Arbitrary i) => ArbitraryContext i -> QC.Gen CIdentifier +arbitraryCIdentifierFrom :: ArbitraryContext i -> QC.Gen CIdentifier arbitraryCIdentifierFrom ctx = arbitraryIdentifierFrom ctx{acIdentToString = unCIdentifier} @@ -185,7 +184,7 @@ arbitraryIdentifierFrom ctx = do arbitraryDirectDeclaratorFrom :: (Hashable i, QC.Arbitrary i) => ArbitraryContext i -> QC.Gen (DirectDeclarator i) -arbitraryDirectDeclaratorFrom typeNames = halveSize $ oneOfSized $ +arbitraryDirectDeclaratorFrom typeNames = halveSize $ oneOfSized [ Anyhow $ DeclaratorRoot <$> arbitraryIdentifierFrom typeNames , IfPositive $ DeclaratorParens <$> arbitraryDeclaratorFrom typeNames , IfPositive $ ArrayOrProto @@ -195,7 +194,7 @@ arbitraryDirectDeclaratorFrom typeNames = halveSize $ oneOfSized $ arbitraryArrayOrProtoFrom :: (Hashable i, QC.Arbitrary i) => ArbitraryContext i -> QC.Gen (ArrayOrProto i) -arbitraryArrayOrProtoFrom typeNames = halveSize $ oneOfSized $ +arbitraryArrayOrProtoFrom typeNames = halveSize $ oneOfSized [ Anyhow $ Array <$> arbitraryArrayTypeFrom typeNames , IfPositive $ Proto <$> QC.listOf (arbitraryParameterDeclarationFrom typeNames) ] @@ -235,7 +234,7 @@ arbitraryAbstractDeclaratorFrom typeNames = halveSize $ do arbitraryDirectAbstractDeclaratorFrom :: (Hashable i, QC.Arbitrary i) => ArbitraryContext i -> QC.Gen (DirectAbstractDeclarator i) -arbitraryDirectAbstractDeclaratorFrom typeNames = halveSize $ oneOfSized $ +arbitraryDirectAbstractDeclaratorFrom typeNames = halveSize $ oneOfSized [ Anyhow $ ArrayOrProtoHere <$> arbitraryArrayOrProtoFrom typeNames , IfPositive $ AbstractDeclaratorParens <$> arbitraryAbstractDeclaratorFrom typeNames , IfPositive $ ArrayOrProtoThere @@ -254,10 +253,10 @@ instance QC.Arbitrary HaskellIdentifier where arbitraryModId = arbitraryConId arbitraryConId = - ((:) <$> QC.elements large <*> QC.listOf (QC.elements (small ++ large ++ digit' ++ ['\'']))) + (:) <$> QC.elements large <*> QC.listOf (QC.elements (small ++ large ++ digit' ++ ['\''])) arbitraryVarId = - ((:) <$> QC.elements small <*> QC.listOf (QC.elements (small ++ large ++ digit' ++ ['\'']))) + (:) <$> QC.elements small <*> QC.listOf (QC.elements (small ++ large ++ digit' ++ ['\''])) -- We currently do not generate unicode identifiers. large = ['A'..'Z'] diff --git a/inline-c/test/tests.hs b/inline-c/test/tests.hs index 697e413..9f3156e 100644 --- a/inline-c/test/tests.hs +++ b/inline-c/test/tests.hs @@ -74,7 +74,7 @@ main = Hspec.hspec $ do [] [r| 1 + 4 |]) x `Hspec.shouldBe` 1 + 4 - Hspec.it "inlineCode" $ do + Hspec.it "inlineCode" $ francescos_mul 3 4 `Hspec.shouldBe` 12 Hspec.it "exp" $ do let x = 3 @@ -96,7 +96,7 @@ main = Hspec.hspec $ do let y = 10 z <- [CI.exp| int{ 7 + $(int x) + $(int y) } |] z `Hspec.shouldBe` x + y + 7 - Hspec.it "void exp" $ do + Hspec.it "void exp" [C.exp| void { printf("Hello\n") } |] Hspec.it "Foreign.C.Types library types" $ do let x = 1 @@ -205,11 +205,11 @@ main = Hspec.hspec $ do bits `Hspec.shouldBe` 16 Hspec.it "Haskell identifiers" $ do let x' = 3 - void $ [C.exp| int { $(int x') } |] + void [C.exp| int { $(int x') } |] let ä = 3 - void $ [C.exp| int { $(int ä) } |] - void $ [C.exp| int { $(int Prelude.maxBound) } |] - Hspec.it "Function pointers" $ do + void [C.exp| int { $(int ä) } |] + void [C.exp| int { $(int Prelude.maxBound) } |] + Hspec.it "Function pointers" $ alloca $ \x_ptr -> do poke x_ptr 7 let fp = [C.funPtr| void poke42(int *ptr) { *ptr = 42; } |] From 12764c638f4cf6c8aac95529e006baf411658bda Mon Sep 17 00:00:00 2001 From: Yuriy Syrovetskiy Date: Mon, 6 May 2019 15:08:05 +0300 Subject: [PATCH 2/9] fixup! Gardening code with hlint --- .hlint.yaml | 60 +++++++++++++++++++ inline-c/examples/gsl-ode.hs | 2 +- inline-c/src/Language/C/Inline/Context.hs | 3 + .../Language/C/Inline/HaskellIdentifier.hs | 7 ++- inline-c/src/Language/C/Inline/Internal.hs | 35 ++++------- inline-c/src/Language/C/Types.hs | 5 +- inline-c/src/Language/C/Types/Parse.hs | 2 + 7 files changed, 87 insertions(+), 27 deletions(-) create mode 100644 .hlint.yaml diff --git a/.hlint.yaml b/.hlint.yaml new file mode 100644 index 0000000..08f723a --- /dev/null +++ b/.hlint.yaml @@ -0,0 +1,60 @@ +# HLint configuration file +# https://github.com/ndmitchell/hlint +########################## + +# This file contains a template configuration file, which is typically +# placed as .hlint.yaml in the root of your project + + +# Specify additional command line arguments +# +# - arguments: [--color, --cpp-simple, -XQuasiQuotes] + + +# Control which extensions/flags/modules/functions can be used +# +# - extensions: +# - default: false # all extension are banned by default +# - name: [PatternGuards, ViewPatterns] # only these listed extensions can be used +# - {name: CPP, within: CrossPlatform} # CPP can only be used in a given module +# +# - flags: +# - {name: -w, within: []} # -w is allowed nowhere +# +# - modules: +# - {name: [Data.Set, Data.HashSet], as: Set} # if you import Data.Set qualified, it must be as 'Set' +# - {name: Control.Arrow, within: []} # Certain modules are banned entirely +# +# - functions: +# - {name: unsafePerformIO, within: []} # unsafePerformIO can only appear in no modules + + +# Add custom hints for this project +# +# Will suggest replacing "wibbleMany [myvar]" with "wibbleOne myvar" +# - error: {lhs: "wibbleMany [x]", rhs: wibbleOne x} + + +# Turn on hints that are off by default +# +# Ban "module X(module X) where", to require a real export list +# - warn: {name: Use explicit module export list} +# +# Replace a $ b $ c with a . b $ c +# - group: {name: dollar, enabled: true} +# +# Generalise map to fmap, ++ to <> +# - group: {name: generalise, enabled: true} + + +# Ignore some builtin hints +# - ignore: {name: Use const, within: SpecialModule} # Only within certain modules +- ignore: {name: Use camelCase} + + +# Define some custom infix operators +# - fixity: infixr 3 ~^#^~ + + +# To generate a suitable file for HLint do: +# $ hlint --default > .hlint.yaml diff --git a/inline-c/examples/gsl-ode.hs b/inline-c/examples/gsl-ode.hs index b1d5007..4d03c63 100644 --- a/inline-c/examples/gsl-ode.hs +++ b/inline-c/examples/gsl-ode.hs @@ -104,7 +104,7 @@ lorenz -> Double -- ^ End point -> Either String (V.Vector Double) -lorenz x0 f0 xend = solveOde fun x0 f0 xend +lorenz = solveOde fun where sigma = 10.0; _R = 28.0; diff --git a/inline-c/src/Language/C/Inline/Context.hs b/inline-c/src/Language/C/Inline/Context.hs index 2495f38..285b676 100644 --- a/inline-c/src/Language/C/Inline/Context.hs +++ b/inline-c/src/Language/C/Inline/Context.hs @@ -42,6 +42,9 @@ module Language.C.Inline.Context , bsCtx ) where +{- HLINT ignore "Use fewer imports" -} +{- HLINT ignore "Reduce duplication" -} + import Control.Applicative ((<|>)) import Control.Monad (mzero) import Control.Monad.Trans.Class (lift) diff --git a/inline-c/src/Language/C/Inline/HaskellIdentifier.hs b/inline-c/src/Language/C/Inline/HaskellIdentifier.hs index 2d061ce..d5afa65 100644 --- a/inline-c/src/Language/C/Inline/HaskellIdentifier.hs +++ b/inline-c/src/Language/C/Inline/HaskellIdentifier.hs @@ -16,6 +16,8 @@ module Language.C.Inline.HaskellIdentifier , haskellReservedWords ) where +{- HLINT ignore "Use fewer imports" -} + import Control.Applicative ((<|>)) import Control.Monad (when, msum, void) import Data.Char (ord) @@ -94,9 +96,8 @@ haskellReservedWords = C.cReservedWords <> HashSet.fromList -- | See -- . parseHaskellIdentifier :: forall i m. C.CParser i m => m HaskellIdentifier -parseHaskellIdentifier = do - segments <- go - return $ HaskellIdentifier $ intercalate "." segments +parseHaskellIdentifier = + HaskellIdentifier . intercalate "." <$> go where small = lower <|> char '_' large = upper diff --git a/inline-c/src/Language/C/Inline/Internal.hs b/inline-c/src/Language/C/Inline/Internal.hs index d4ac8ee..55dd4a1 100644 --- a/inline-c/src/Language/C/Inline/Internal.hs +++ b/inline-c/src/Language/C/Inline/Internal.hs @@ -199,7 +199,7 @@ setContext ctx = do void $ initialiseModuleState $ Just ctx bumpGeneratedNames :: TH.Q Int -bumpGeneratedNames = do +bumpGeneratedNames = modifyModuleState $ \ms -> let c' = msGeneratedNames ms in (ms{msGeneratedNames = c' + 1}, c') @@ -406,10 +406,10 @@ runParserInQ s ctx p = do let parsecLoc = Parsec.newPos (TH.loc_filename loc) line col let p' = lift (Parsec.setPosition parsecLoc) *> p <* lift Parser.eof case C.runCParser ctx (TH.loc_filename loc) s p' of - Left err -> do + Left err -> -- TODO consider prefixing with "error while parsing C" or similar fail $ show err - Right res -> do + Right res -> return res data SomeEq = forall a. (Typeable a, Eq a) => SomeEq a @@ -423,7 +423,7 @@ instance Show SomeEq where show _ = "<>" toSomeEq :: (Eq a, Typeable a) => a -> SomeEq -toSomeEq x = SomeEq x +toSomeEq = SomeEq fromSomeEq :: Typeable a => SomeEq -> Maybe a fromSomeEq (SomeEq x) = cast x @@ -481,7 +481,6 @@ parseTypedC antiQs = do return (decls1 ++ decls2, s1 ++ s2) ] return (decls, s ++ s') - where parseAntiQuote :: StateT Int m ([(C.CIdentifier, C.Type C.CIdentifier, ParameterType)], String) @@ -557,14 +556,14 @@ genericQuote purity build = quoteCode $ \s -> do (haskellCParserContext (typeNamesFromTypesTable (ctxTypesTable ctx))) (parseTypedC (ctxAntiQuoters ctx)) hsType <- cToHs ctx cType - hsParams <- forM cParams $ \(_cId, cTy, parTy) -> do + hsParams <- forM cParams $ \(_cId, cTy, parTy) -> case parTy of Plain s' -> do hsTy <- cToHs ctx cTy let hsName = TH.mkName (unHaskellIdentifier s') hsExp <- [| \cont -> cont ($(TH.varE hsName) :: $(return hsTy)) |] return (hsTy, hsExp) - AntiQuote antiId dyn -> do + AntiQuote antiId dyn -> case Map.lookup antiId (ctxAntiQuoters ctx) of Nothing -> fail $ "IMPOSSIBLE: could not find anti-quoter " ++ show antiId ++ @@ -599,13 +598,9 @@ genericQuote purity build = quoteCode $ \s -> do |] convertCFunSig :: TH.Type -> [TH.Type] -> TH.TypeQ - convertCFunSig retType params0 = do - go params0 - where - go [] = - [t| IO $(return retType) |] - go (paramType : params) = do - [t| $(return paramType) -> $(go params) |] + convertCFunSig retType = go where + go [] = [t| IO $(return retType) |] + go (paramType : params) = [t| $(return paramType) -> $(go params) |] splitTypedC :: String -> (String, String) -- ^ Returns the type and the body separately @@ -640,13 +635,9 @@ funPtrQuote callSafety = quoteCode $ \code -> do Just hsTy -> return hsTy convertCFunSig :: TH.Type -> [TH.Type] -> TH.TypeQ - convertCFunSig retType params0 = do - go params0 - where - go [] = - [t| IO $(return retType) |] - go (paramType : params) = do - [t| $(return paramType) -> $(go params) |] + convertCFunSig retType = go where + go [] = [t| IO $(return retType) |] + go (paramType : params) = [t| $(return paramType) -> $(go params) |] parse :: C.CParser C.CIdentifier m => m FunPtrDecl parse = do @@ -669,7 +660,7 @@ funPtrQuote callSafety = quoteCode $ \code -> do , funPtrBody = body , funPtrName = fmap C.unCIdentifier mbName } - _ -> fail $ "Expecting function declaration" + _ -> fail "Expecting function declaration" parseBody :: C.CParser C.CIdentifier m => m String parseBody = do diff --git a/inline-c/src/Language/C/Types.hs b/inline-c/src/Language/C/Types.hs index 996ff73..c21cddd 100644 --- a/inline-c/src/Language/C/Types.hs +++ b/inline-c/src/Language/C/Types.hs @@ -6,6 +6,7 @@ {-# LANGUAGE DeriveTraversable #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} +{-# LANGUAGE LambdaCase #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-} {-# LANGUAGE ScopedTypeVariables #-} @@ -59,6 +60,8 @@ module Language.C.Types , describeType ) where +{- HLINT ignore "Use fewer imports" -} + import Control.Arrow (second) import Control.Monad (when, unless, forM_) import Control.Monad.State (execState, modify) @@ -169,7 +172,7 @@ untangleDeclarationSpecifiers :: [P.DeclarationSpecifier] -> Either UntangleErr (Specifiers, TypeSpecifier) untangleDeclarationSpecifiers declSpecs = do let (pStorage, pTySpecs, pTyQuals, pFunSpecs) = flip execState ([], [], [], []) $ - forM_ (reverse declSpecs) $ \declSpec -> case declSpec of + forM_ (reverse declSpecs) $ \case P.StorageClassSpecifier x -> modify $ \(a, b, c, d) -> (x:a, b, c, d) P.TypeSpecifier x -> modify $ \(a, b, c, d) -> (a, x:b, c, d) P.TypeQualifier x -> modify $ \(a, b, c, d) -> (a, b, x:c, d) diff --git a/inline-c/src/Language/C/Types/Parse.hs b/inline-c/src/Language/C/Types/Parse.hs index c2c2981..db03ed3 100644 --- a/inline-c/src/Language/C/Types/Parse.hs +++ b/inline-c/src/Language/C/Types/Parse.hs @@ -231,9 +231,11 @@ cReservedWords = HashSet.fromList cIdentStart :: [Char] cIdentStart = ['a'..'z'] ++ ['A'..'Z'] ++ ['_'] +{- HLINT ignore cIdentStart "Use String" -} cIdentLetter :: [Char] cIdentLetter = ['a'..'z'] ++ ['A'..'Z'] ++ ['_'] ++ ['0'..'9'] +{- HLINT ignore cIdentLetter "Use String" -} cIdentStyle :: TokenParsing m => IdentifierStyle m cIdentStyle = IdentifierStyle From 05b68e4501fec556249c6c0e50534e25eba621e6 Mon Sep 17 00:00:00 2001 From: Yuriy Syrovetskiy Date: Mon, 6 May 2019 15:23:29 +0300 Subject: [PATCH 3/9] fixup! fixup! Gardening code with hlint --- inline-c-cpp/test/tests.hs | 4 +- .../test/Language/C/Inline/ContextSpec.hs | 40 ++++++++++--------- 2 files changed, 24 insertions(+), 20 deletions(-) diff --git a/inline-c-cpp/test/tests.hs b/inline-c-cpp/test/tests.hs index a086884..65c326b 100644 --- a/inline-c-cpp/test/tests.hs +++ b/inline-c-cpp/test/tests.hs @@ -15,7 +15,7 @@ C.include "" main :: IO () main = Hspec.hspec $ do - Hspec.describe "Basic C++" $ + Hspec.describe "Basic C++" $ do Hspec.it "Hello World" $ do let x = 3 [C.block| void { @@ -128,3 +128,5 @@ main = Hspec.hspec $ do |] result `Hspec.shouldBe` Right 0xDEADBEEF + +{- HLINT ignore main "Redundant do" -} diff --git a/inline-c/test/Language/C/Inline/ContextSpec.hs b/inline-c/test/Language/C/Inline/ContextSpec.hs index 15ee5b1..95fc922 100644 --- a/inline-c/test/Language/C/Inline/ContextSpec.hs +++ b/inline-c/test/Language/C/Inline/ContextSpec.hs @@ -26,52 +26,52 @@ import Language.C.Inline.Context spec :: Hspec.SpecWith () spec = do - Hspec.it "converts simple type correctly (1)" $ + Hspec.it "converts simple type correctly (1)" $ do shouldBeType (cty "int") [t| CInt |] - Hspec.it "converts simple type correctly (2)" $ + Hspec.it "converts simple type correctly (2)" $ do shouldBeType (cty "char") [t| CChar |] - Hspec.it "converts void" $ + Hspec.it "converts void" $ do shouldBeType (cty "void") [t| () |] - Hspec.it "converts standard library types (1)" $ + Hspec.it "converts standard library types (1)" $ do shouldBeType (cty "FILE") [t| CFile |] - Hspec.it "converts standard library types (2)" $ + Hspec.it "converts standard library types (2)" $ do shouldBeType (cty "uint16_t") [t| Word16 |] - Hspec.it "converts standard library types (3)" $ + Hspec.it "converts standard library types (3)" $ do shouldBeType (cty "jmp_buf") [t| CJmpBuf |] - Hspec.it "converts single ptr type" $ + Hspec.it "converts single ptr type" $ do shouldBeType (cty "long*") [t| Ptr CLong |] - Hspec.it "converts double ptr type" $ + Hspec.it "converts double ptr type" $ do shouldBeType (cty "unsigned long**") [t| Ptr (Ptr CULong) |] - Hspec.it "converts arrays" $ + Hspec.it "converts arrays" $ do shouldBeType (cty "double[]") [t| CArray CDouble |] - Hspec.it "converts named things" $ + Hspec.it "converts named things" $ do shouldBeType (cty "unsigned int foo[]") [t| CArray CUInt |] - Hspec.it "converts arrays of pointers" $ + Hspec.it "converts arrays of pointers" $ do shouldBeType (cty "unsigned short *foo[]") [t| CArray (Ptr CUShort) |] - Hspec.it "ignores qualifiers" $ + Hspec.it "ignores qualifiers" $ do shouldBeType (cty "const short*") [t| Ptr CShort |] - Hspec.it "ignores storage information" $ + Hspec.it "ignores storage information" $ do shouldBeType (cty "extern unsigned long") [t| CULong |] - Hspec.it "converts sized arrays" $ + Hspec.it "converts sized arrays" $ do shouldBeType (cty "float[4]") [t| CArray CFloat |] - Hspec.it "converts variably sized arrays" $ + Hspec.it "converts variably sized arrays" $ do shouldBeType (cty "float[*]") [t| CArray CFloat |] - Hspec.it "converts function pointers" $ + Hspec.it "converts function pointers" $ do shouldBeType (cty "int (*f)(unsigned char, float)") [t| FunPtr (CUChar -> CFloat -> IO CInt) |] - Hspec.it "converts complicated function pointers (1)" $ + Hspec.it "converts complicated function pointers (1)" $ do -- pointer to function returning pointer to function returning int shouldBeType (cty "int (*(*)())()") [t| FunPtr (IO (FunPtr (IO CInt))) |] - Hspec.it "converts complicated function pointerst (2)" $ + Hspec.it "converts complicated function pointerst (2)" $ do -- foo is an array of pointer to pointer to function returning -- pointer to array of pointer to char shouldBeType (cty "char *(*(**foo [])())[]") [t| CArray (Ptr (FunPtr (IO (Ptr (CArray (Ptr CChar)))))) |] - Hspec.it "converts complicated function pointers (3)" $ + Hspec.it "converts complicated function pointers (3)" $ do -- foo is an array of pointer to pointer to function taking int -- returning pointer to array of pointer to char shouldBeType @@ -97,3 +97,5 @@ spec = do cty s = C.parameterDeclarationType $ assertParse C.parseParameterDeclaration s baseTypes = ctxTypesTable baseCtx + +{- HLINT ignore spec "Redundant do" -} From 103359ac334f32a6ccca83a8a45f64f2ceaeff3d Mon Sep 17 00:00:00 2001 From: Yuriy Syrovetskiy Date: Mon, 6 May 2019 15:33:49 +0300 Subject: [PATCH 4/9] fixup! fixup! fixup! Gardening code with hlint --- inline-c/test/Language/C/Inline/ParseSpec.hs | 14 ++++++++------ inline-c/test/Language/C/Types/ParseSpec.hs | 5 +++-- inline-c/test/tests.hs | 8 +++++--- 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/inline-c/test/Language/C/Inline/ParseSpec.hs b/inline-c/test/Language/C/Inline/ParseSpec.hs index d7e5e51..de08bf5 100644 --- a/inline-c/test/Language/C/Inline/ParseSpec.hs +++ b/inline-c/test/Language/C/Inline/ParseSpec.hs @@ -29,7 +29,7 @@ import Language.C.Inline.Internal import qualified Language.C.Types as C spec :: Hspec.SpecWith () -spec = +spec = do Hspec.describe "parsing" $ do Hspec.it "parses simple C expression" $ do (retType, params, cExp) <- goodParse [r| @@ -38,13 +38,13 @@ spec = retType `Hspec.shouldBe` cty "int" params `shouldMatchParameters` [(cty "double", Plain "x"), (cty "float", Plain "y")] cExp `shouldMatchBody` " (int) ceil(x[a-z0-9_]+ \\+ ((double) y[a-z0-9_]+)) " - Hspec.it "accepts anti quotes" $ + Hspec.it "accepts anti quotes" $ do void $ goodParse [r| int { $(int x) } |] - Hspec.it "rejects if bad braces (1)" $ + Hspec.it "rejects if bad braces (1)" $ do badParse [r| int x |] - Hspec.it "rejects if bad braces (2)" $ + Hspec.it "rejects if bad braces (2)" $ do badParse [r| int { x |] - Hspec.it "parses function pointers" $ + Hspec.it "parses function pointers" $ do void $ goodParse [r| int(int (*add)(int, int)) { add(3, 4) } |] Hspec.it "parses returning function pointers" $ do (retType, params, cExp) <- @@ -67,7 +67,7 @@ spec = retType `Hspec.shouldBe` cty "int" params `shouldMatchParameters` [(cty "int", Plain "Foo.bar")] cExp `shouldMatchBody` " Foobar[a-z0-9_]+ " - Hspec.it "does not parse Haskell identifier in bad position" $ + Hspec.it "does not parse Haskell identifier in bad position" $ do badParse [r| double (*)(double Foo.bar) { 3.0 } |] where ctx = baseCtx <> funCtx @@ -109,3 +109,5 @@ spec = ')' -> "\\)" ch -> [ch] (x =~ concatMap f y) `Hspec.shouldBe` True + +{- HLINT ignore spec "Redundant do" -} diff --git a/inline-c/test/Language/C/Types/ParseSpec.hs b/inline-c/test/Language/C/Types/ParseSpec.hs index 9012597..8d8cb5f 100644 --- a/inline-c/test/Language/C/Types/ParseSpec.hs +++ b/inline-c/test/Language/C/Types/ParseSpec.hs @@ -29,7 +29,7 @@ import Prelude -- Fix for 7.10 unused warnings. spec :: Hspec.SpecWith () spec = do - Hspec.it "parses everything which is pretty-printable (C)" $ + Hspec.it "parses everything which is pretty-printable (C)" $ do #if MIN_VERSION_QuickCheck(2,9,0) QC.property $ QC.again $ do -- Work around #else @@ -40,7 +40,7 @@ spec = do return $ isGoodType ty QC.==> let ty' = assertParse (cCParserContext typeNames) parameter_declaration (prettyOneLine ty) in Types.untangleParameterDeclaration ty == Types.untangleParameterDeclaration ty' - Hspec.it "parses everything which is pretty-printable (Haskell)" $ + Hspec.it "parses everything which is pretty-printable (Haskell)" $ do #if MIN_VERSION_QuickCheck(2,9,0) QC.property $ QC.again $ do -- Work around #else @@ -51,6 +51,7 @@ spec = do return $ isGoodType ty QC.==> let ty' = assertParse (haskellCParserContext typeNames) parameter_declaration (prettyOneLine ty) in Types.untangleParameterDeclaration ty == Types.untangleParameterDeclaration ty' +{- HLINT ignore spec "Redundant do" -} ------------------------------------------------------------------------ -- Utils diff --git a/inline-c/test/tests.hs b/inline-c/test/tests.hs index 9f3156e..a799b0f 100644 --- a/inline-c/test/tests.hs +++ b/inline-c/test/tests.hs @@ -74,7 +74,7 @@ main = Hspec.hspec $ do [] [r| 1 + 4 |]) x `Hspec.shouldBe` 1 + 4 - Hspec.it "inlineCode" $ + Hspec.it "inlineCode" $ do francescos_mul 3 4 `Hspec.shouldBe` 12 Hspec.it "exp" $ do let x = 3 @@ -96,7 +96,7 @@ main = Hspec.hspec $ do let y = 10 z <- [CI.exp| int{ 7 + $(int x) + $(int y) } |] z `Hspec.shouldBe` x + y + 7 - Hspec.it "void exp" + Hspec.it "void exp" $ do [C.exp| void { printf("Hello\n") } |] Hspec.it "Foreign.C.Types library types" $ do let x = 1 @@ -209,10 +209,12 @@ main = Hspec.hspec $ do let ä = 3 void [C.exp| int { $(int ä) } |] void [C.exp| int { $(int Prelude.maxBound) } |] - Hspec.it "Function pointers" $ + Hspec.it "Function pointers" $ do alloca $ \x_ptr -> do poke x_ptr 7 let fp = [C.funPtr| void poke42(int *ptr) { *ptr = 42; } |] [C.exp| void { $(void (*fp)(int *))($(int *x_ptr)) } |] x <- peek x_ptr x `Hspec.shouldBe` 42 + +{- HLINT ignore main "Redundant do" -} From 2e2a8cd82852beb81e61956db5855107b298451b Mon Sep 17 00:00:00 2001 From: Yuriy Syrovetskiy Date: Mon, 6 May 2019 15:44:11 +0300 Subject: [PATCH 5/9] fixup! fixup! fixup! fixup! Gardening code with hlint --- .travis.yml | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index 4a30c26..d53180b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,11 +13,7 @@ addons: - libcairo2-dev env: -- ARGS="--flag inline-c:gsl-example" -- ARGS="--stack-yaml stack-lts-12.14.yaml --flag inline-c:gsl-example" -# gtk2hs-buildtools is not present in nightly a bit of a pain to install, -# skip it for now -- ARGS="--stack-yaml stack-nightly-2018-10-24.yaml" +- STACK="stack --no-terminal --install-ghc test --haddock" before_install: # Download and unpack the stack executable @@ -28,7 +24,15 @@ before_install: # This line does all of the work: installs GHC if necessary, build the library, # executables, and test suites, and runs the test suites. --no-terminal works # around some quirks in Travis's terminal implementation. -script: stack --no-terminal --install-ghc test --haddock $ARGS +matrix: + include: + - script: $STACK --flag inline-c:gsl-example + - script: + $STACK --stack-yaml stack-lts-12.14.yaml --flag inline-c:gsl-example + # gtk2hs-buildtools is not present in nightly a bit of a pain to install, + # skip it for now + - script: $STACK --stack-yaml stack-nightly-2018-10-24.yaml + - script: hlint . # Caching so the next build will be fast too. cache: From d9722c1f8e3d161fd7f95febd9c4270fbde6aac1 Mon Sep 17 00:00:00 2001 From: Yuriy Syrovetskiy Date: Mon, 6 May 2019 15:54:15 +0300 Subject: [PATCH 6/9] fixup! fixup! fixup! fixup! fixup! Gardening code with hlint --- .travis.yml | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index d53180b..88488f6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -13,7 +13,8 @@ addons: - libcairo2-dev env: -- STACK="stack --no-terminal --install-ghc test --haddock" +- STACK="stack --no-terminal --install-ghc" + STACK_TEST="$STACK test --haddock" before_install: # Download and unpack the stack executable @@ -26,13 +27,19 @@ before_install: # around some quirks in Travis's terminal implementation. matrix: include: - - script: $STACK --flag inline-c:gsl-example - - script: - $STACK --stack-yaml stack-lts-12.14.yaml --flag inline-c:gsl-example + - name: test +gsl + script: $STACK_TEST --flag inline-c:gsl-example + - name: test +gsl lts-12.14 + script: + $STACK_TEST + --stack-yaml stack-lts-12.14.yaml --flag inline-c:gsl-example # gtk2hs-buildtools is not present in nightly a bit of a pain to install, # skip it for now - - script: $STACK --stack-yaml stack-nightly-2018-10-24.yaml - - script: hlint . + - name: test nightly + script: $STACK_TEST --stack-yaml stack-nightly-2018-10-24.yaml + - name: HLint + install: $STACK build hlint + script: $STACK exec -- hlint . # Caching so the next build will be fast too. cache: From 63dffe21f3a78df833b1a3ee8025036355edb411 Mon Sep 17 00:00:00 2001 From: Yuriy Syrovetskiy Date: Mon, 6 May 2019 17:10:22 +0300 Subject: [PATCH 7/9] fixup! fixup! fixup! fixup! fixup! fixup! Gardening code with hlint --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 88488f6..c11bc46 100644 --- a/.travis.yml +++ b/.travis.yml @@ -38,7 +38,7 @@ matrix: - name: test nightly script: $STACK_TEST --stack-yaml stack-nightly-2018-10-24.yaml - name: HLint - install: $STACK build hlint + install: $STACK --resolver=lts-12.14 build hlint script: $STACK exec -- hlint . # Caching so the next build will be fast too. From f597feacc87b1fc0997b90ee70fc805d8c768f5c Mon Sep 17 00:00:00 2001 From: Yuriy Syrovetskiy Date: Mon, 6 May 2019 17:27:07 +0300 Subject: [PATCH 8/9] fixup! fixup! fixup! fixup! fixup! fixup! fixup! Gardening code with hlint --- .travis.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index c11bc46..0a81225 100644 --- a/.travis.yml +++ b/.travis.yml @@ -38,8 +38,7 @@ matrix: - name: test nightly script: $STACK_TEST --stack-yaml stack-nightly-2018-10-24.yaml - name: HLint - install: $STACK --resolver=lts-12.14 build hlint - script: $STACK exec -- hlint . + script: $STACK --resolver=lts-12.14 build hlint --exec -- hlint . # Caching so the next build will be fast too. cache: From 30a604aaa362509cddb1f7b14f9d9aa78012b1d1 Mon Sep 17 00:00:00 2001 From: Yuriy Syrovetskiy Date: Mon, 6 May 2019 17:50:25 +0300 Subject: [PATCH 9/9] fixup! fixup! fixup! fixup! fixup! fixup! fixup! fixup! Gardening code with hlint --- .travis.yml | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 0a81225..d2bb3fd 100644 --- a/.travis.yml +++ b/.travis.yml @@ -33,12 +33,13 @@ matrix: script: $STACK_TEST --stack-yaml stack-lts-12.14.yaml --flag inline-c:gsl-example - # gtk2hs-buildtools is not present in nightly a bit of a pain to install, - # skip it for now - name: test nightly + # gtk2hs-buildtools is not present in nightly a bit of a pain to install, + # skip it for now script: $STACK_TEST --stack-yaml stack-nightly-2018-10-24.yaml - name: HLint - script: $STACK --resolver=lts-12.14 build hlint --exec -- hlint . + # 2.1.11 inroduced {- HLINT -} pragmas, use it until lts-12.22 + script: $STACK build hlint-2.1.11 --exec 'hlint .' # Caching so the next build will be fast too. cache: