on master help sign in
Hlinting
cbec132Adam Bergmark
.travis.yml+3
@@ -40,6 +40,9 @@ matrix:
40 - env: BUILD=cabal CABALVER=1.22 GHCVER=7.10.3
40 - env: BUILD=cabal CABALVER=1.22 GHCVER=7.10.3
41 compiler: ": #GHC 7.10.3"
41 compiler: ": #GHC 7.10.3"
42 addons: {apt: {packages: [cabal-install-1.22,ghc-7.10.3], sources: [hvr-ghc]}}
42 addons: {apt: {packages: [cabal-install-1.22,ghc-7.10.3], sources: [hvr-ghc]}}
43+ - env: BUILD=hlint CABALVER=1.24 GHCVER=8.0.2
44+ compiler: ": #GHC 8.0.2"
45+ addons: {apt: {packages: [cabal-install-1.24,ghc-8.0.2], sources: [hvr-ghc]}}
43
46
44before_install:
47before_install:
45 - unset CC
48 - unset CC
Data/Aeson/Encoding/Builder.hs+1−1
@@ -292,7 +292,7 @@ encodeUtf8BuilderEscaped be =
292 where
292 where
293 iend = off + len
293 iend = off + len
294
294
295− outerLoop !i0 !br@(B.BufferRange op0 ope)
295+ outerLoop !i0 br@(B.BufferRange op0 ope)
296 | i0 >= iend = k br
296 | i0 >= iend = k br
297 | outRemaining > 0 = goPartial (i0 + min outRemaining inpRemaining)
297 | outRemaining > 0 = goPartial (i0 + min outRemaining inpRemaining)
298 -- TODO: Use a loop with an integrated bound's check if outRemaining
298 -- TODO: Use a loop with an integrated bound's check if outRemaining
Data/Aeson/TH.hs+7−8
@@ -1629,7 +1629,7 @@ buildTypeInstanceFromTys tyConName jc dataCxt varTysOrig isDataFamily = do
1629 -- instance C (Fam [Char])
1629 -- instance C (Fam [Char])
1630 remainingTysOrigSubst :: [Type]
1630 remainingTysOrigSubst :: [Type]
1631 remainingTysOrigSubst =
1631 remainingTysOrigSubst =
1632− map (substNamesWithKindStar (union droppedKindVarNames kvNames'))
1632+ map (substNamesWithKindStar (droppedKindVarNames `union` kvNames'))
1633 $ take remainingLength varTysOrig
1633 $ take remainingLength varTysOrig
1634
1634
1635 remainingTysOrigSubst' :: [Type]
1635 remainingTysOrigSubst' :: [Type]
@@ -2118,7 +2118,7 @@ createKindChain :: Int -> Kind
2118createKindChain = go starK
2118createKindChain = go starK
2119 where
2119 where
2120 go :: Kind -> Int -> Kind
2120 go :: Kind -> Int -> Kind
2121− go k !0 = k
2121+ go k 0 = k
2122#if MIN_VERSION_template_haskell(2,8,0)
2122#if MIN_VERSION_template_haskell(2,8,0)
2123 go k !n = go (AppT (AppT ArrowT StarT) k) (n - 1)
2123 go k !n = go (AppT (AppT ArrowT StarT) k) (n - 1)
2124#else
2124#else
@@ -2245,7 +2245,7 @@ substNameWithKind :: Name -> Kind -> Type -> Type
2245substNameWithKind n k = substKind (M.singleton n k)
2245substNameWithKind n k = substKind (M.singleton n k)
2246
2246
2247substNamesWithKindStar :: [Name] -> Type -> Type
2247substNamesWithKindStar :: [Name] -> Type -> Type
2248−substNamesWithKindStar ns t = foldr' (flip substNameWithKind starK) t ns
2248+substNamesWithKindStar ns t = foldr' (`substNameWithKind` starK) t ns
2249
2249
2250-------------------------------------------------------------------------------
2250-------------------------------------------------------------------------------
2251-- Error messages
2251-- Error messages
@@ -2394,13 +2394,12 @@ data StarKindStatus = NotKindStar
2394
2394
2395-- | Does a Type have kind * or k (for some kind variable k)?
2395-- | Does a Type have kind * or k (for some kind variable k)?
2396canRealizeKindStar :: Type -> StarKindStatus
2396canRealizeKindStar :: Type -> StarKindStatus
2397−canRealizeKindStar t
2397+canRealizeKindStar t = case t of
2398− | hasKindStar t = KindStar
2398+ _ | hasKindStar t -> KindStar
2399− | otherwise = case t of
2400#if MIN_VERSION_template_haskell(2,8,0)
2399#if MIN_VERSION_template_haskell(2,8,0)
2401− SigT _ (VarT k) -> IsKindVar k
2400+ SigT _ (VarT k) -> IsKindVar k
2402#endif
2401#endif
2403− _ -> NotKindStar
2402+ _ -> NotKindStar
2404
2403
2405-- | Returns 'Just' the kind variable 'Name' of a 'StarKindStatus' if it exists.
2404-- | Returns 'Just' the kind variable 'Name' of a 'StarKindStatus' if it exists.
2406-- Otherwise, returns 'Nothing'.
2405-- Otherwise, returns 'Nothing'.
Data/Aeson/Types/ToJSON.hs+4−3
@@ -1,4 +1,3 @@
1−{-# LANGUAGE BangPatterns #-}
2{-# LANGUAGE CPP #-}
1{-# LANGUAGE CPP #-}
3{-# LANGUAGE DataKinds #-}
2{-# LANGUAGE DataKinds #-}
4{-# LANGUAGE DefaultSignatures #-}
3{-# LANGUAGE DefaultSignatures #-}
@@ -132,6 +131,8 @@ import qualified Data.ByteString.Internal as S
132import qualified Data.ByteString.Lazy.Internal as L
131import qualified Data.ByteString.Lazy.Internal as L
133#endif
132#endif
134
133
134+{-# ANN module ("HLint: ignore Reduce duplication"::String) #-}
135+
135toJSONPair :: (a -> Value) -> (b -> Value) -> (a, b) -> Value
136toJSONPair :: (a -> Value) -> (b -> Value) -> (a, b) -> Value
136toJSONPair a b = liftToJSON2 a (listValue a) b (listValue b)
137toJSONPair a b = liftToJSON2 a (listValue a) b (listValue b)
137{-# INLINE toJSONPair #-}
138{-# INLINE toJSONPair #-}
@@ -2809,8 +2810,8 @@ packChunks :: L.ByteString -> S.ByteString
2809packChunks lbs =
2810packChunks lbs =
2810 S.unsafeCreate (fromIntegral $ L.length lbs) (copyChunks lbs)
2811 S.unsafeCreate (fromIntegral $ L.length lbs) (copyChunks lbs)
2811 where
2812 where
2812− copyChunks !L.Empty !_pf = return ()
2813+ copyChunks L.Empty _pf = return ()
2813− copyChunks !(L.Chunk (S.PS fpbuf o l) lbs') !pf = do
2814+ copyChunks (L.Chunk (S.PS fpbuf o l) lbs') pf = do
2814 withForeignPtr fpbuf $ \pbuf ->
2815 withForeignPtr fpbuf $ \pbuf ->
2815 copyBytes pf (pbuf `plusPtr` o) l
2816 copyBytes pf (pbuf `plusPtr` o) l
2816 copyChunks lbs' (pf `plusPtr` l)
2817 copyChunks lbs' (pf `plusPtr` l)
HLint.hsnew file+10
@@ -0,0 +1,10 @@
1+module HLint.HLint where
2+
3+import "hint" HLint.Default
4+import "hint" HLint.Builtin.All
5+import "hint" HLint.Dollar
6+
7+ignore "Avoid lambda"
8+ignore "Eta reduce"
9+ignore "Functor law"
10+ignore "Use >=>"
Makefilenew file+2
@@ -0,0 +1,2 @@
1+lint:
2+ hlint --cpp-include include/ .
benchmarks/AesonCompareAutoInstances.hs+2−2
@@ -43,7 +43,7 @@ d :: T
43d = Record
43d = Record
44 { testOne = 1234.56789
44 { testOne = 1234.56789
45 , testTwo = True
45 , testTwo = True
46− , testThree = Product "Hello World!" 'a' $
46+ , testThree = Product "Hello World!" 'a'
47 Record
47 Record
48 { testOne = 9876.54321
48 { testOne = 9876.54321
49 , testTwo = False
49 , testTwo = False
@@ -80,7 +80,7 @@ d' :: T'
80d' = Record'
80d' = Record'
81 { testOne' = 1234.56789
81 { testOne' = 1234.56789
82 , testTwo' = True
82 , testTwo' = True
83− , testThree' = Product' "Hello World!" 'a' $
83+ , testThree' = Product' "Hello World!" 'a'
84 Record'
84 Record'
85 { testOne' = 9876.54321
85 { testOne' = 9876.54321
86 , testTwo' = False
86 , testTwo' = False
benchmarks/AesonEncode.hs+2−3
@@ -7,7 +7,6 @@ import Prelude ()
7import Prelude.Compat
7import Prelude.Compat
8
8
9import Control.DeepSeq
9import Control.DeepSeq
10−import Control.Exception
11import Control.Monad
10import Control.Monad
12import Data.Aeson
11import Data.Aeson
13import Data.Attoparsec.ByteString (IResult(..), parseWith)
12import Data.Attoparsec.ByteString (IResult(..), parseWith)
@@ -25,7 +24,7 @@ main = do
25 (c:a) -> (c,a)
24 (c:a) -> (c,a)
26 [] -> error "Unexpected empty list"
25 [] -> error "Unexpected empty list"
27 let count = read cnt :: Int
26 let count = read cnt :: Int
28− forM_ args $ \arg -> bracket (openFile arg ReadMode) hClose $ \h -> do
27+ forM_ args $ \arg -> withFile arg ReadMode $ \h -> do
29 putStrLn $ arg ++ ":"
28 putStrLn $ arg ++ ":"
30 let refill = B.hGet h 16384
29 let refill = B.hGet h 16384
31 result0 <- parseWith refill json =<< refill
30 result0 <- parseWith refill json =<< refill
@@ -35,7 +34,7 @@ main = do
35 start <- getCurrentTime
34 start <- getCurrentTime
36 let loop !n r
35 let loop !n r
37 | n >= count = return ()
36 | n >= count = return ()
38− | otherwise = {-# SCC "loop" #-} do
37+ | otherwise = {-# SCC "loop" #-}
39 rnf (encode r) `seq` loop (n+1) r
38 rnf (encode r) `seq` loop (n+1) r
40 loop 0 r0
39 loop 0 r0
41 delta <- flip diffUTCTime start `fmap` getCurrentTime
40 delta <- flip diffUTCTime start `fmap` getCurrentTime
benchmarks/AesonMap.hs+4−4
@@ -97,16 +97,16 @@ value1000 = value 1000
97value10000 = value 10000
97value10000 = value 10000
98
98
99encodedValue10 :: LBS.ByteString
99encodedValue10 :: LBS.ByteString
100−encodedValue10 = B.encode $ value10
100+encodedValue10 = B.encode value10
101
101
102encodedValue100 :: LBS.ByteString
102encodedValue100 :: LBS.ByteString
103−encodedValue100 = B.encode $ value100
103+encodedValue100 = B.encode value100
104
104
105encodedValue1000 :: LBS.ByteString
105encodedValue1000 :: LBS.ByteString
106−encodedValue1000 = B.encode $ value1000
106+encodedValue1000 = B.encode value1000
107
107
108encodedValue10000 :: LBS.ByteString
108encodedValue10000 :: LBS.ByteString
109−encodedValue10000 = B.encode $ value10000
109+encodedValue10000 = B.encode value10000
110
110
111-------------------------------------------------------------------------------
111-------------------------------------------------------------------------------
112-- Helpers
112-- Helpers
benchmarks/AesonParse.hs+1−2
@@ -8,7 +8,6 @@ import Prelude ()
8import Prelude.Compat
8import Prelude.Compat
9
9
10import "aeson-benchmarks" Data.Aeson
10import "aeson-benchmarks" Data.Aeson
11−import Control.Exception
12import Control.Monad
11import Control.Monad
13import Data.Attoparsec.ByteString (IResult(..), parseWith)
12import Data.Attoparsec.ByteString (IResult(..), parseWith)
14import Data.Time.Clock
13import Data.Time.Clock
@@ -21,7 +20,7 @@ main = do
21 (bs:cnt:args) <- getArgs
20 (bs:cnt:args) <- getArgs
22 let count = read cnt :: Int
21 let count = read cnt :: Int
23 blkSize = read bs
22 blkSize = read bs
24− forM_ args $ \arg -> bracket (openFile arg ReadMode) hClose $ \h -> do
23+ forM_ args $ \arg -> withFile arg ReadMode $ \h -> do
25 putStrLn $ arg ++ ":"
24 putStrLn $ arg ++ ":"
26 start <- getCurrentTime
25 start <- getCurrentTime
27 let loop !good !bad
26 let loop !good !bad
benchmarks/AesonTuples.hs−2
@@ -1,5 +1,3 @@
1−module Main where
2−
3module Main (main) where
1module Main (main) where
4
2
5import Prelude ()
3import Prelude ()
benchmarks/Compare/JsonBench.hs+2−3
@@ -3,7 +3,6 @@
3-- https://github.com/chadaustin/buffer-builder/blob/master/test.json
3-- https://github.com/chadaustin/buffer-builder/blob/master/test.json
4
4
5{-# LANGUAGE BangPatterns #-}
5{-# LANGUAGE BangPatterns #-}
6−{-# LANGUAGE GeneralizedNewtypeDeriving #-}
7{-# LANGUAGE MagicHash #-}
6{-# LANGUAGE MagicHash #-}
8{-# LANGUAGE OverloadedStrings #-}
7{-# LANGUAGE OverloadedStrings #-}
9{-# LANGUAGE RecordWildCards #-}
8{-# LANGUAGE RecordWildCards #-}
@@ -65,10 +64,10 @@ instance NFData Gender where rnf !_ = ()
65instance NFData Fruit where rnf !_ = ()
64instance NFData Fruit where rnf !_ = ()
66
65
67instance NFData Friend where
66instance NFData Friend where
68− rnf Friend {..} = (rnf fId) `seq` (rnf fName) `seq` ()
67+ rnf Friend {..} = rnf fId `seq` rnf fName `seq` ()
69
68
70instance NFData User where
69instance NFData User where
71− rnf User {..} = (rnf uId) `seq` (rnf uIndex) `seq` (rnf uGuid) `seq` (rnf uIsActive) `seq` (rnf uBalance) `seq` (rnf uPicture) `seq` (rnf uAge) `seq` (rnf uEyeColor) `seq` (rnf uName) `seq` (rnf uGender) `seq` (rnf uCompany) `seq` (rnf uEmail) `seq` (rnf uPhone) `seq` (rnf uAddress) `seq` (rnf uAbout) `seq` (rnf uRegistered) `seq` (rnf uLatitude) `seq` (rnf uLongitude) `seq` (rnf uTags) `seq` (rnf uFriends) `seq` (rnf uGreeting) `seq` (rnf uFavouriteFruit) `seq` ()
70+ rnf User {..} = rnf uId `seq` rnf uIndex `seq` rnf uGuid `seq` rnf uIsActive `seq` rnf uBalance `seq` rnf uPicture `seq` rnf uAge `seq` rnf uEyeColor `seq` rnf uName `seq` rnf uGender `seq` rnf uCompany `seq` rnf uEmail `seq` rnf uPhone `seq` rnf uAddress `seq` rnf uAbout `seq` rnf uRegistered `seq` rnf uLatitude `seq` rnf uLongitude `seq` rnf uTags `seq` rnf uFriends `seq` rnf uGreeting `seq` rnf uFavouriteFruit `seq` ()
72
71
73eyeColorTable :: [(Text, EyeColor)]
72eyeColorTable :: [(Text, EyeColor)]
74eyeColorTable = [("brown", Brown), ("green", Green), ("blue", Blue)]
73eyeColorTable = [("brown", Brown), ("green", Green), ("blue", Blue)]
benchmarks/CompareWithJSON.hs+3−6
@@ -9,6 +9,7 @@ import Blaze.ByteString.Builder (toLazyByteString)
9import Blaze.ByteString.Builder.Char.Utf8 (fromString)
9import Blaze.ByteString.Builder.Char.Utf8 (fromString)
10import Control.DeepSeq (NFData(rnf))
10import Control.DeepSeq (NFData(rnf))
11import Criterion.Main
11import Criterion.Main
12+import Data.Maybe (fromMaybe)
12import qualified Data.Aeson as A
13import qualified Data.Aeson as A
13import qualified Data.Aeson.Text as A
14import qualified Data.Aeson.Text as A
14import qualified Data.ByteString.Lazy as BL
15import qualified Data.ByteString.Lazy as BL
@@ -35,14 +36,10 @@ decodeJ s =
35 J.Error _ -> error "fail to parse via JSON"
36 J.Error _ -> error "fail to parse via JSON"
36
37
37decodeA :: BL.ByteString -> A.Value
38decodeA :: BL.ByteString -> A.Value
38−decodeA s = case A.decode s of
39− Just v -> v
40− Nothing -> error "fail to parse via Aeson"
39+decodeA s = fromMaybe (error "fail to parse via Aeson") $ A.decode s
41
40
42decodeA' :: BL.ByteString -> A.Value
41decodeA' :: BL.ByteString -> A.Value
43−decodeA' s = case A.decode' s of
44− Just v -> v
45− Nothing -> error "fail to parse via Aeson"
42+decodeA' s = fromMaybe (error "fail to parse via Aeson") $ A.decode' s
46
43
47encodeJ :: J.JSValue -> BL.ByteString
44encodeJ :: J.JSValue -> BL.ByteString
48encodeJ = toLazyByteString . fromString . J.encode
45encodeJ = toLazyByteString . fromString . J.encode
benchmarks/Dates.hs+8−8
@@ -22,22 +22,22 @@ main = do
22 defaultMain [
22 defaultMain [
23 bgroup "decode" [
23 bgroup "decode" [
24 bgroup "UTCTime" [
24 bgroup "UTCTime" [
25− env file1 $ \ ~bs -> bench "whole" $ nf utcTime bs
25+ env file1 $ \bs -> bench "whole" $ nf utcTime bs
26− , env file2 $ \ ~bs -> bench "fractional" $ nf utcTime bs
26+ , env file2 $ \bs -> bench "fractional" $ nf utcTime bs
27 ]
27 ]
28 , bgroup "ZonedTime" [
28 , bgroup "ZonedTime" [
29− env file1 $ \ ~bs -> bench "whole" $ nf zTime bs
29+ env file1 $ \bs -> bench "whole" $ nf zTime bs
30− , env file2 $ \ ~bs -> bench "fractional" $ nf zTime bs
30+ , env file2 $ \bs -> bench "fractional" $ nf zTime bs
31 ]
31 ]
32 ]
32 ]
33 , bgroup "encode" [
33 , bgroup "encode" [
34 bgroup "UTCTime" [
34 bgroup "UTCTime" [
35− env (utcTime <$> file1) $ \ ~ts -> bench "whole" $ nf encode ts
35+ env (utcTime <$> file1) $ \ts -> bench "whole" $ nf encode ts
36− , env (utcTime <$> file2) $ \ ~ts -> bench "fractional" $ nf encode ts
36+ , env (utcTime <$> file2) $ \ts -> bench "fractional" $ nf encode ts
37 ]
37 ]
38 , bgroup "ZonedTime" [
38 , bgroup "ZonedTime" [
39− env (zTime <$> file1) $ \ ~ts -> bench "whole" $ nf encode ts
39+ env (zTime <$> file1) $ \ts -> bench "whole" $ nf encode ts
40− , env (zTime <$> file2) $ \ ~ts -> bench "fractional" $ nf encode ts
40+ , env (zTime <$> file2) $ \ts -> bench "fractional" $ nf encode ts
41 ]
41 ]
42 ]
42 ]
43 ]
43 ]
benchmarks/ReadFile.hs+1−1
@@ -20,7 +20,7 @@ import qualified Data.ByteString as B
20main = do
20main = do
21 (cnt:args) <- getArgs
21 (cnt:args) <- getArgs
22 let count = read cnt :: Int
22 let count = read cnt :: Int
23− forM_ args $ \arg -> bracket (openFile arg ReadMode) hClose $ \h -> do
23+ forM_ args $ \arg -> withFile arg ReadMode $ \h -> do
24 putStrLn $ arg ++ ":"
24 putStrLn $ arg ++ ":"
25 start <- getCurrentTime
25 start <- getCurrentTime
26 let loop !n
26 let loop !n
benchmarks/Typed/Common.hs+2
@@ -1,5 +1,7 @@
1{-# LANGUAGE CPP #-}
1{-# LANGUAGE CPP #-}
2+#ifdef HAS_BOTH_AESON_AND_BENCHMARKS
2{-# LANGUAGE PackageImports #-}
3{-# LANGUAGE PackageImports #-}
4+#endif
3
5
4{-# OPTIONS_GHC -fno-warn-unused-imports #-}
6{-# OPTIONS_GHC -fno-warn-unused-imports #-}
5
7
examples/Twitter.hs+3
@@ -29,6 +29,9 @@ import Data.Text (Text)
29import GHC.Generics (Generic)
29import GHC.Generics (Generic)
30import Prelude hiding (id)
30import Prelude hiding (id)
31
31
32+{-# ANN module "Hlint: ignore Use camelCase" #-}
33+{-# ANN module "Hlint: ignore Use newtype instead of data" #-}
34+
32data Metadata = Metadata {
35data Metadata = Metadata {
33 result_type :: Text
36 result_type :: Text
34 } deriving (Eq, Show, Typeable, Data, Generic)
37 } deriving (Eq, Show, Typeable, Data, Generic)
examples/Twitter/Generic.hs−1
@@ -1,6 +1,5 @@
1-- Use GHC generics to automatically generate good instances.
1-- Use GHC generics to automatically generate good instances.
2{-# LANGUAGE CPP #-}
2{-# LANGUAGE CPP #-}
3−{-# LANGUAGE PackageImports #-}
4{-# OPTIONS_GHC -fno-warn-orphans #-}
3{-# OPTIONS_GHC -fno-warn-orphans #-}
5
4
6module Twitter.Generic
5module Twitter.Generic
examples/Twitter/Manual.hs+4−1
@@ -1,11 +1,14 @@
1-- Manually write instances.
1-- Manually write instances.
2
2
3{-# LANGUAGE CPP #-}
3{-# LANGUAGE CPP #-}
4−{-# LANGUAGE PackageImports #-}
5{-# LANGUAGE OverloadedStrings #-}
4{-# LANGUAGE OverloadedStrings #-}
6{-# LANGUAGE RecordWildCards #-}
5{-# LANGUAGE RecordWildCards #-}
7{-# OPTIONS_GHC -fno-warn-orphans #-}
6{-# OPTIONS_GHC -fno-warn-orphans #-}
8
7
8+#ifdef HAS_BOTH_AESON_AND_BENCHMARKS
9+{-# LANGUAGE PackageImports #-}
10+#endif
11+
9module Twitter.Manual
12module Twitter.Manual
10 (
13 (
11 Metadata(..)
14 Metadata(..)
pure/Data/Aeson/Parser/UnescapePure.hs+9−9
@@ -52,23 +52,23 @@ setByte1 point word = point .|. fromIntegral (word .&. 0x3f)
52{-# INLINE setByte1 #-}
52{-# INLINE setByte1 #-}
53
53
54setByte2 :: (Num a, Bits b, Bits a, Integral b) => a -> b -> a
54setByte2 :: (Num a, Bits b, Bits a, Integral b) => a -> b -> a
55−setByte2 point word = point .|. ((fromIntegral $ word .&. 0x3f) `shiftL` 6)
55+setByte2 point word = point .|. (fromIntegral (word .&. 0x3f) `shiftL` 6)
56{-# INLINE setByte2 #-}
56{-# INLINE setByte2 #-}
57
57
58setByte2Top :: (Num a, Bits b, Bits a, Integral b) => a -> b -> a
58setByte2Top :: (Num a, Bits b, Bits a, Integral b) => a -> b -> a
59−setByte2Top point word = point .|. ((fromIntegral $ word .&. 0x1f) `shiftL` 6)
59+setByte2Top point word = point .|. (fromIntegral (word .&. 0x1f) `shiftL` 6)
60{-# INLINE setByte2Top #-}
60{-# INLINE setByte2Top #-}
61
61
62setByte3 :: (Num a, Bits b, Bits a, Integral b) => a -> b -> a
62setByte3 :: (Num a, Bits b, Bits a, Integral b) => a -> b -> a
63−setByte3 point word = point .|. ((fromIntegral $ word .&. 0x3f) `shiftL` 12)
63+setByte3 point word = point .|. (fromIntegral (word .&. 0x3f) `shiftL` 12)
64{-# INLINE setByte3 #-}
64{-# INLINE setByte3 #-}
65
65
66setByte3Top :: (Num a, Bits b, Bits a, Integral b) => a -> b -> a
66setByte3Top :: (Num a, Bits b, Bits a, Integral b) => a -> b -> a
67−setByte3Top point word = point .|. ((fromIntegral $ word .&. 0xf) `shiftL` 12)
67+setByte3Top point word = point .|. (fromIntegral (word .&. 0xf) `shiftL` 12)
68{-# INLINE setByte3Top #-}
68{-# INLINE setByte3Top #-}
69
69
70setByte4 :: (Num a, Bits b, Bits a, Integral b) => a -> b -> a
70setByte4 :: (Num a, Bits b, Bits a, Integral b) => a -> b -> a
71−setByte4 point word = point .|. ((fromIntegral $ word .&. 0x7) `shiftL` 18)
71+setByte4 point word = point .|. (fromIntegral (word .&. 0x7) `shiftL` 18)
72{-# INLINE setByte4 #-}
72{-# INLINE setByte4 #-}
73
73
74decode :: Utf -> Word32 -> Word8 -> (Utf, Word32)
74decode :: Utf -> Word32 -> Word8 -> (Utf, Word32)
@@ -207,12 +207,12 @@ unescapeText' bs = runText $ \done -> do
207 let u = w' .|. w in
207 let u = w' .|. w in
208
208
209 -- Get next state based on surrogates.
209 -- Get next state based on surrogates.
210− let st =
210+ let st
211− if u >= 0xd800 && u <= 0xdbff then -- High surrogate.
211+ | u >= 0xd800 && u <= 0xdbff = -- High surrogate.
212 StateS0
212 StateS0
213− else if u >= 0xdc00 && u <= 0xdfff then -- Low surrogate.
213+ | u >= 0xdc00 && u <= 0xdfff = -- Low surrogate.
214 throwDecodeError
214 throwDecodeError
215− else
215+ | otherwise =
216 StateNone
216 StateNone
217 in
217 in
218 writeAndReturn dest pos u st
218 writeAndReturn dest pos u st
tests/Instances.hs+2−1
@@ -3,7 +3,6 @@
3{-# LANGUAGE FlexibleInstances #-}
3{-# LANGUAGE FlexibleInstances #-}
4{-# LANGUAGE OverloadedStrings #-}
4{-# LANGUAGE OverloadedStrings #-}
5{-# LANGUAGE RecordWildCards #-}
5{-# LANGUAGE RecordWildCards #-}
6−{-# LANGUAGE StandaloneDeriving #-}
7{-# OPTIONS_GHC -fno-warn-orphans #-}
6{-# OPTIONS_GHC -fno-warn-orphans #-}
8
7
9module Instances () where
8module Instances () where
@@ -45,6 +44,8 @@ import Data.Hashable.Time ()
45import Numeric.Natural
44import Numeric.Natural
46#endif
45#endif
47
46
47+{-# ANN module ("HLint: ignore Use fewer imports"::String) #-}
48+
48-- "System" types.
49-- "System" types.
49
50
50instance Arbitrary DotNetTime where
51instance Arbitrary DotNetTime where
tests/Properties.hs+1−1
@@ -235,7 +235,7 @@ tests = testGroup "properties" [
235 [ testProperty "Identity Char" $ roundTripEq (undefined :: I Int)
235 [ testProperty "Identity Char" $ roundTripEq (undefined :: I Int)
236
236
237 , testProperty "Identity Char" $ roundTripEq (undefined :: I Char)
237 , testProperty "Identity Char" $ roundTripEq (undefined :: I Char)
238− , testProperty "Identity [Char]" $ roundTripEq (undefined :: I [Char])
238+ , testProperty "Identity [Char]" $ roundTripEq (undefined :: I String)
239 , testProperty "[Identity Char]" $ roundTripEq (undefined :: [I Char])
239 , testProperty "[Identity Char]" $ roundTripEq (undefined :: [I Char])
240
240
241 , testProperty "Compose I I Int" $ roundTripEq (undefined :: LogScaled (Compose I I Int))
241 , testProperty "Compose I I Int" $ roundTripEq (undefined :: LogScaled (Compose I I Int))
tests/SerializationFormatSpec.hs+3−3
@@ -86,7 +86,7 @@ jsonExamples =
86 , Example "Map Int Int" "{\"0\":1,\"2\":3}" (M.fromList [(0,1),(2,3)] :: M.Map Int Int)
86 , Example "Map Int Int" "{\"0\":1,\"2\":3}" (M.fromList [(0,1),(2,3)] :: M.Map Int Int)
87 , Example "Map (Tagged Int Int) Int" "{\"0\":1,\"2\":3}" (M.fromList [(Tagged 0,1),(Tagged 2,3)] :: M.Map (Tagged Int Int) Int)
87 , Example "Map (Tagged Int Int) Int" "{\"0\":1,\"2\":3}" (M.fromList [(Tagged 0,1),(Tagged 2,3)] :: M.Map (Tagged Int Int) Int)
88 , Example "Map [Int] Int" "[[[0],1],[[2],3]]" (M.fromList [([0],1),([2],3)] :: M.Map [Int] Int)
88 , Example "Map [Int] Int" "[[[0],1],[[2],3]]" (M.fromList [([0],1),([2],3)] :: M.Map [Int] Int)
89− , Example "Map [Char] Int" "{\"ab\":1,\"cd\":3}" (M.fromList [("ab",1),("cd",3)] :: M.Map [Char] Int)
89+ , Example "Map [Char] Int" "{\"ab\":1,\"cd\":3}" (M.fromList [("ab",1),("cd",3)] :: M.Map String Int)
90 , Example "Map [I Char] Int" "{\"ab\":1,\"cd\":3}" (M.fromList [(map pure "ab",1),(map pure "cd",3)] :: M.Map [I Char] Int)
90 , Example "Map [I Char] Int" "{\"ab\":1,\"cd\":3}" (M.fromList [(map pure "ab",1),(map pure "cd",3)] :: M.Map [I Char] Int)
91
91
92 , Example "nan :: Double" "null" (Approx $ 0/0 :: Approx Double)
92 , Example "nan :: Double" "null" (Approx $ 0/0 :: Approx Double)
@@ -197,9 +197,9 @@ jsonDecodingExamples :: [Example]
197jsonDecodingExamples = [
197jsonDecodingExamples = [
198 -- Maybe serialising is lossy
198 -- Maybe serialising is lossy
199 -- https://github.com/bos/aeson/issues/376
199 -- https://github.com/bos/aeson/issues/376
200− MaybeExample "Nothing" "null" (Just $ Nothing :: Maybe (Maybe Int))
200+ MaybeExample "Nothing" "null" (Just Nothing :: Maybe (Maybe Int))
201 , MaybeExample "Just" "1" (Just $ Just 1 :: Maybe (Maybe Int))
201 , MaybeExample "Just" "1" (Just $ Just 1 :: Maybe (Maybe Int))
202− , MaybeExample "Just Nothing" "null" (Just $ Nothing :: Maybe (Maybe (Maybe Int)))
202+ , MaybeExample "Just Nothing" "null" (Just Nothing :: Maybe (Maybe (Maybe Int)))
203 -- Integral values are truncated, and overflowed
203 -- Integral values are truncated, and overflowed
204 -- https://github.com/bos/aeson/issues/317
204 -- https://github.com/bos/aeson/issues/317
205 , MaybeExample "Word8 3" "3" (Just 3 :: Maybe Word8)
205 , MaybeExample "Word8 3" "3" (Just 3 :: Maybe Word8)
tests/UnitTests.hs+9−11
@@ -74,14 +74,14 @@ tests = testGroup "unit" [
74 assertEqual "" "camel_api_case" (camelTo2 '_' "CamelAPICase")
74 assertEqual "" "camel_api_case" (camelTo2 '_' "CamelAPICase")
75 ]
75 ]
76 , testGroup "encoding" [
76 , testGroup "encoding" [
77− testCase "goodProducer" $ goodProducer
77+ testCase "goodProducer" goodProducer
78 ]
78 ]
79 , testGroup "utctime" [
79 , testGroup "utctime" [
80− testCase "good" $ utcTimeGood
80+ testCase "good" utcTimeGood
81− , testCase "bad" $ utcTimeBad
81+ , testCase "bad" utcTimeBad
82 ]
82 ]
83 , testGroup "formatError" [
83 , testGroup "formatError" [
84− testCase "example 1" $ formatErrorExample
84+ testCase "example 1" formatErrorExample
85 ]
85 ]
86 , testGroup ".:, .:?, .:!" $ fmap (testCase "-") dotColonMark
86 , testGroup ".:, .:?, .:!" $ fmap (testCase "-") dotColonMark
87 , testGroup "JSONPath" $ fmap (testCase "-") jsonPath
87 , testGroup "JSONPath" $ fmap (testCase "-") jsonPath
@@ -187,11 +187,9 @@ utcTimeGood = do
187 where
187 where
188 parseWithRead :: String -> LT.Text -> UTCTime
188 parseWithRead :: String -> LT.Text -> UTCTime
189 parseWithRead f s =
189 parseWithRead f s =
190− case parseTime defaultTimeLocale f . LT.unpack $ s of
190+ fromMaybe (error "parseTime input malformed") . parseTime defaultTimeLocale f . LT.unpack $ s
191− Nothing -> error "parseTime input malformed"
192− Just t -> t
193 parseWithAeson :: LT.Text -> Maybe UTCTime
191 parseWithAeson :: LT.Text -> Maybe UTCTime
194− parseWithAeson s = decode . LT.encodeUtf8 $ (LT.concat ["\"", s, "\""])
192+ parseWithAeson s = decode . LT.encodeUtf8 $ LT.concat ["\"", s, "\""]
195
193
196-- Test that a few non-timezone qualified timestamp formats get
194-- Test that a few non-timezone qualified timestamp formats get
197-- rejected if decoding to UTCTime.
195-- rejected if decoding to UTCTime.
@@ -207,7 +205,7 @@ utcTimeBad = do
207 verifyFailParse "2015-01-03 12:13.000Z" -- decimal at the end, but no seconds
205 verifyFailParse "2015-01-03 12:13.000Z" -- decimal at the end, but no seconds
208 where
206 where
209 verifyFailParse (s :: LT.Text) =
207 verifyFailParse (s :: LT.Text) =
210− let (dec :: Maybe UTCTime) = decode . LT.encodeUtf8 $ (LT.concat ["\"", s, "\""]) in
208+ let (dec :: Maybe UTCTime) = decode . LT.encodeUtf8 $ LT.concat ["\"", s, "\""] in
211 assertEqual "verify failure" Nothing dec
209 assertEqual "verify failure" Nothing dec
212
210
213-- Non identifier keys should be escaped & enclosed in brackets
211-- Non identifier keys should be escaped & enclosed in brackets
@@ -235,11 +233,11 @@ dotColonMark = [
235 , assertEqual ".: 42" (Just (T1 (Just 42))) (decode ex2 :: Maybe T1)
233 , assertEqual ".: 42" (Just (T1 (Just 42))) (decode ex2 :: Maybe T1)
236 , assertEqual ".: null" (Just (T1 Nothing)) (decode ex3 :: Maybe T1)
234 , assertEqual ".: null" (Just (T1 Nothing)) (decode ex3 :: Maybe T1)
237
235
238− , assertEqual ".:? not-present" (Just (T2 (Nothing))) (decode ex1 :: Maybe T2)
236+ , assertEqual ".:? not-present" (Just (T2 Nothing)) (decode ex1 :: Maybe T2)
239 , assertEqual ".:? 42" (Just (T2 (Just 42))) (decode ex2 :: Maybe T2)
237 , assertEqual ".:? 42" (Just (T2 (Just 42))) (decode ex2 :: Maybe T2)
240 , assertEqual ".:? null" (Just (T2 Nothing)) (decode ex3 :: Maybe T2)
238 , assertEqual ".:? null" (Just (T2 Nothing)) (decode ex3 :: Maybe T2)
241
239
242− , assertEqual ".:! not-present" (Just (T3 (Nothing))) (decode ex1 :: Maybe T3)
240+ , assertEqual ".:! not-present" (Just (T3 Nothing)) (decode ex1 :: Maybe T3)
243 , assertEqual ".:! 42" (Just (T3 (Just 42))) (decode ex2 :: Maybe T3)
241 , assertEqual ".:! 42" (Just (T3 (Just 42))) (decode ex2 :: Maybe T3)
244 , assertEqual ".:! null" Nothing (decode ex3 :: Maybe T3)
242 , assertEqual ".:! null" Nothing (decode ex3 :: Maybe T3)
245 ]
243 ]
travis/script.sh+4
@@ -19,4 +19,8 @@ case $BUILD in
19 SRC_TGZ=$(cabal info . | awk '{print $2;exit}').tar.gz &&
19 SRC_TGZ=$(cabal info . | awk '{print $2;exit}').tar.gz &&
20 (cd dist && cabal install --force-reinstalls "$SRC_TGZ")
20 (cd dist && cabal install --force-reinstalls "$SRC_TGZ")
21 ;;
21 ;;
22+ hlint)
23+ stack install hlint --resolver lts-8 --system-ghc --no-terminal
24+ make lint
25+ ;;
22esac
26esac