Skip to content

Commit 0047d13

Browse files
authored
Fix warnings in hls-graph, enable pedantic in CI (#4047)
* Fix warnings in hls-graph, enable pedantic in CI * Fix build with flags * stylish-haskell * Split Key stuff to separate module with explicit export list * Try the cabal configure suggestion in CI flags job * Newline fix * Enable pedantic for all * Typo * stylish-haskell * pedantic is already enabled for all * Fix error in hls-plugin-api * Address nitpick, use lsp-types in tests instead
1 parent b91c907 commit 0047d13

File tree

19 files changed

+256
-199
lines changed

19 files changed

+256
-199
lines changed

.github/workflows/flags.yml

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -69,14 +69,21 @@ jobs:
6969
ghc: ${{ matrix.ghc }}
7070
os: ${{ runner.os }}
7171

72-
- name: Build `hls-graph` with flags
73-
run: cabal v2-build hls-graph --flags="embed-files stm-stats"
72+
# The purpose of this job is to ensure that the build works even with flags
73+
# in their non-default settings. Below we:
74+
# - enable flags that are off by default
75+
# - disable flags that are on by default
76+
- name: Configue non-default flags for all components
77+
run: |
78+
cabal configure \
79+
--constraint "hls-graph +embed-files +stm-stats" \
80+
--constraint "ghcide +ekg +executable +test-exe" \
81+
--constraint "hls-plugin-api -use-fingertree" \
82+
--constraint "all +pedantic"
83+
cat cabal.project.local
7484
75-
- name: Build `ghcide` with flags
76-
run: cabal v2-build ghcide --flags="ghc-patched-unboxed-bytecode test-exe executable bench-exe ekg"
77-
78-
- name: Build with pedantic (-WError)
79-
run: cabal v2-build --flags="pedantic"
85+
- name: Build everything with non-default flags
86+
run: cabal build all
8087

8188
flags_post_job:
8289
if: always()

.hlint.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@
6060
- Development.IDE.Graph.Internal.Database
6161
- Development.IDE.Graph.Internal.Paths
6262
- Development.IDE.Graph.Internal.Profile
63-
- Development.IDE.Graph.Internal.Types
63+
- Development.IDE.Graph.Internal.Key
6464
- Ide.Types
6565
- Test.Hls
6666
- Test.Hls.Command

ghcide/src/Development/IDE/Types/Shake.hs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,8 @@ import Data.Typeable (cast)
2424
import Data.Vector (Vector)
2525
import Development.IDE.Core.PositionMapping
2626
import Development.IDE.Core.RuleTypes (FileVersion)
27-
import Development.IDE.Graph (Key (..), RuleResult,
28-
newKey)
27+
import Development.IDE.Graph (Key, RuleResult, newKey,
28+
pattern Key)
2929
import qualified Development.IDE.Graph as Shake
3030
import Development.IDE.Types.Diagnostics
3131
import Development.IDE.Types.Location

hls-graph/hls-graph.cabal

Lines changed: 14 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,16 @@ source-repository head
3939
type: git
4040
location: https://github.com/haskell/haskell-language-server
4141

42+
common warnings
43+
ghc-options:
44+
-Wall
45+
-Wredundant-constraints
46+
-Wunused-packages
47+
-Wno-name-shadowing
48+
-Wno-unticked-promoted-constructors
49+
4250
library
51+
import: warnings
4352
exposed-modules:
4453
Control.Concurrent.STM.Stats
4554
Development.IDE.Graph
@@ -48,6 +57,7 @@ library
4857
Development.IDE.Graph.Internal.Action
4958
Development.IDE.Graph.Internal.Database
5059
Development.IDE.Graph.Internal.Options
60+
Development.IDE.Graph.Internal.Key
5161
Development.IDE.Graph.Internal.Paths
5262
Development.IDE.Graph.Internal.Profile
5363
Development.IDE.Graph.Internal.Rules
@@ -66,7 +76,6 @@ library
6676
, bytestring
6777
, containers
6878
, deepseq
69-
, directory
7079
, exceptions
7180
, extra
7281
, filepath
@@ -89,14 +98,13 @@ library
8998
build-depends:
9099
, file-embed >=0.0.11
91100
, template-haskell
101+
else
102+
build-depends:
103+
directory
92104

93105
if flag(stm-stats)
94106
cpp-options: -DSTM_STATS
95107

96-
ghc-options:
97-
-Wall -Wredundant-constraints -Wno-name-shadowing
98-
-Wno-unticked-promoted-constructors -Wunused-packages
99-
100108
if flag(pedantic)
101109
ghc-options: -Werror
102110

@@ -105,6 +113,7 @@ library
105113
DataKinds
106114

107115
test-suite tests
116+
import: warnings
108117
type: exitcode-stdio-1.0
109118
default-language: GHC2021
110119
hs-source-dirs: test
@@ -118,23 +127,16 @@ test-suite tests
118127

119128
ghc-options:
120129
-threaded -rtsopts -with-rtsopts=-N -fno-ignore-asserts
121-
-Wunused-packages
122130

123131
build-depends:
124132
, base
125-
, containers
126-
, directory
127133
, extra
128-
, filepath
129134
, hls-graph
130135
, hspec
131136
, stm
132137
, stm-containers
133138
, tasty
134139
, tasty-hspec
135-
, tasty-hunit
136140
, tasty-rerun
137-
, text
138-
, unordered-containers
139141

140142
build-tool-depends: hspec-discover:hspec-discover

hls-graph/src/Development/IDE/Graph.hs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ module Development.IDE.Graph(
33
shakeOptions,
44
Rules,
55
Action, action,
6-
Key(.., Key),
6+
pattern Key,
77
newKey, renderKey,
88
actionFinally, actionBracket, actionCatch, actionFork,
99
-- * Configuration
@@ -25,9 +25,10 @@ module Development.IDE.Graph(
2525
) where
2626

2727
import Development.IDE.Graph.Database
28-
import Development.IDE.Graph.KeyMap
29-
import Development.IDE.Graph.KeySet
3028
import Development.IDE.Graph.Internal.Action
29+
import Development.IDE.Graph.Internal.Key
3130
import Development.IDE.Graph.Internal.Options
3231
import Development.IDE.Graph.Internal.Rules
3332
import Development.IDE.Graph.Internal.Types
33+
import Development.IDE.Graph.KeyMap
34+
import Development.IDE.Graph.KeySet

hls-graph/src/Development/IDE/Graph/Database.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import Data.Maybe
1616
import Development.IDE.Graph.Classes ()
1717
import Development.IDE.Graph.Internal.Action
1818
import Development.IDE.Graph.Internal.Database
19+
import Development.IDE.Graph.Internal.Key
1920
import Development.IDE.Graph.Internal.Options
2021
import Development.IDE.Graph.Internal.Profile (writeProfile)
2122
import Development.IDE.Graph.Internal.Rules

hls-graph/src/Development/IDE/Graph/Internal/Action.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import Data.Functor.Identity
2727
import Data.IORef
2828
import Development.IDE.Graph.Classes
2929
import Development.IDE.Graph.Internal.Database
30+
import Development.IDE.Graph.Internal.Key
3031
import Development.IDE.Graph.Internal.Rules (RuleResult)
3132
import Development.IDE.Graph.Internal.Types
3233
import System.Exit

hls-graph/src/Development/IDE/Graph/Internal/Database.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import Data.Traversable (for)
3333
import Data.Tuple.Extra
3434
import Debug.Trace (traceM)
3535
import Development.IDE.Graph.Classes
36+
import Development.IDE.Graph.Internal.Key
3637
import Development.IDE.Graph.Internal.Rules
3738
import Development.IDE.Graph.Internal.Types
3839
import qualified Focus
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
{-# LANGUAGE DerivingStrategies #-}
2+
{-# LANGUAGE PatternSynonyms #-}
3+
{-# LANGUAGE ViewPatterns #-}
4+
5+
module Development.IDE.Graph.Internal.Key
6+
( Key -- Opaque - don't expose constructor, use newKey to create
7+
, KeyValue (..)
8+
, pattern Key
9+
, newKey
10+
, renderKey
11+
-- * KeyMap
12+
, KeyMap
13+
, mapKeyMap
14+
, insertKeyMap
15+
, lookupKeyMap
16+
, lookupDefaultKeyMap
17+
, fromListKeyMap
18+
, fromListWithKeyMap
19+
, toListKeyMap
20+
, elemsKeyMap
21+
, restrictKeysKeyMap
22+
-- * KeySet
23+
, KeySet
24+
, nullKeySet
25+
, insertKeySet
26+
, memberKeySet
27+
, toListKeySet
28+
, lengthKeySet
29+
, filterKeySet
30+
, singletonKeySet
31+
, fromListKeySet
32+
, deleteKeySet
33+
, differenceKeySet
34+
) where
35+
36+
--import Control.Monad.IO.Class ()
37+
import Data.Coerce
38+
import Data.Dynamic
39+
import qualified Data.HashMap.Strict as Map
40+
import Data.IntMap (IntMap)
41+
import qualified Data.IntMap.Strict as IM
42+
import Data.IntSet (IntSet)
43+
import qualified Data.IntSet as IS
44+
import Data.IORef
45+
import Data.Text (Text)
46+
import qualified Data.Text as T
47+
import Data.Typeable
48+
import Development.IDE.Graph.Classes
49+
import System.IO.Unsafe
50+
51+
52+
newtype Key = UnsafeMkKey Int
53+
54+
pattern Key :: () => (Typeable a, Hashable a, Show a) => a -> Key
55+
pattern Key a <- (lookupKeyValue -> KeyValue a _)
56+
{-# COMPLETE Key #-}
57+
58+
data KeyValue = forall a . (Typeable a, Hashable a, Show a) => KeyValue a Text
59+
60+
instance Eq KeyValue where
61+
KeyValue a _ == KeyValue b _ = Just a == cast b
62+
instance Hashable KeyValue where
63+
hashWithSalt i (KeyValue x _) = hashWithSalt i (typeOf x, x)
64+
instance Show KeyValue where
65+
show (KeyValue _ t) = T.unpack t
66+
67+
data GlobalKeyValueMap = GlobalKeyValueMap !(Map.HashMap KeyValue Key) !(IntMap KeyValue) {-# UNPACK #-} !Int
68+
69+
keyMap :: IORef GlobalKeyValueMap
70+
keyMap = unsafePerformIO $ newIORef (GlobalKeyValueMap Map.empty IM.empty 0)
71+
72+
{-# NOINLINE keyMap #-}
73+
74+
newKey :: (Typeable a, Hashable a, Show a) => a -> Key
75+
newKey k = unsafePerformIO $ do
76+
let !newKey = KeyValue k (T.pack (show k))
77+
atomicModifyIORef' keyMap $ \km@(GlobalKeyValueMap hm im n) ->
78+
let new_key = Map.lookup newKey hm
79+
in case new_key of
80+
Just v -> (km, v)
81+
Nothing ->
82+
let !new_index = UnsafeMkKey n
83+
in (GlobalKeyValueMap (Map.insert newKey new_index hm) (IM.insert n newKey im) (n+1), new_index)
84+
{-# NOINLINE newKey #-}
85+
86+
lookupKeyValue :: Key -> KeyValue
87+
lookupKeyValue (UnsafeMkKey x) = unsafePerformIO $ do
88+
GlobalKeyValueMap _ im _ <- readIORef keyMap
89+
pure $! im IM.! x
90+
91+
{-# NOINLINE lookupKeyValue #-}
92+
93+
instance Eq Key where
94+
UnsafeMkKey a == UnsafeMkKey b = a == b
95+
instance Hashable Key where
96+
hashWithSalt i (UnsafeMkKey x) = hashWithSalt i x
97+
instance Show Key where
98+
show (Key x) = show x
99+
100+
renderKey :: Key -> Text
101+
renderKey (lookupKeyValue -> KeyValue _ t) = t
102+
103+
newtype KeySet = KeySet IntSet
104+
deriving newtype (Eq, Ord, Semigroup, Monoid)
105+
106+
instance Show KeySet where
107+
showsPrec p (KeySet is)= showParen (p > 10) $
108+
showString "fromList " . shows ks
109+
where ks = coerce (IS.toList is) :: [Key]
110+
111+
insertKeySet :: Key -> KeySet -> KeySet
112+
insertKeySet = coerce IS.insert
113+
114+
memberKeySet :: Key -> KeySet -> Bool
115+
memberKeySet = coerce IS.member
116+
117+
toListKeySet :: KeySet -> [Key]
118+
toListKeySet = coerce IS.toList
119+
120+
nullKeySet :: KeySet -> Bool
121+
nullKeySet = coerce IS.null
122+
123+
differenceKeySet :: KeySet -> KeySet -> KeySet
124+
differenceKeySet = coerce IS.difference
125+
126+
deleteKeySet :: Key -> KeySet -> KeySet
127+
deleteKeySet = coerce IS.delete
128+
129+
fromListKeySet :: [Key] -> KeySet
130+
fromListKeySet = coerce IS.fromList
131+
132+
singletonKeySet :: Key -> KeySet
133+
singletonKeySet = coerce IS.singleton
134+
135+
filterKeySet :: (Key -> Bool) -> KeySet -> KeySet
136+
filterKeySet = coerce IS.filter
137+
138+
lengthKeySet :: KeySet -> Int
139+
lengthKeySet = coerce IS.size
140+
141+
newtype KeyMap a = KeyMap (IntMap a)
142+
deriving newtype (Eq, Ord, Semigroup, Monoid)
143+
144+
instance Show a => Show (KeyMap a) where
145+
showsPrec p (KeyMap im)= showParen (p > 10) $
146+
showString "fromList " . shows ks
147+
where ks = coerce (IM.toList im) :: [(Key,a)]
148+
149+
mapKeyMap :: (a -> b) -> KeyMap a -> KeyMap b
150+
mapKeyMap f (KeyMap m) = KeyMap (IM.map f m)
151+
152+
insertKeyMap :: Key -> a -> KeyMap a -> KeyMap a
153+
insertKeyMap (UnsafeMkKey k) v (KeyMap m) = KeyMap (IM.insert k v m)
154+
155+
lookupKeyMap :: Key -> KeyMap a -> Maybe a
156+
lookupKeyMap (UnsafeMkKey k) (KeyMap m) = IM.lookup k m
157+
158+
lookupDefaultKeyMap :: a -> Key -> KeyMap a -> a
159+
lookupDefaultKeyMap a (UnsafeMkKey k) (KeyMap m) = IM.findWithDefault a k m
160+
161+
fromListKeyMap :: [(Key,a)] -> KeyMap a
162+
fromListKeyMap xs = KeyMap (IM.fromList (coerce xs))
163+
164+
fromListWithKeyMap :: (a -> a -> a) -> [(Key,a)] -> KeyMap a
165+
fromListWithKeyMap f xs = KeyMap (IM.fromListWith f (coerce xs))
166+
167+
toListKeyMap :: KeyMap a -> [(Key,a)]
168+
toListKeyMap (KeyMap m) = coerce (IM.toList m)
169+
170+
elemsKeyMap :: KeyMap a -> [a]
171+
elemsKeyMap (KeyMap m) = IM.elems m
172+
173+
restrictKeysKeyMap :: KeyMap a -> KeySet -> KeyMap a
174+
restrictKeysKeyMap (KeyMap m) (KeySet s) = KeyMap (IM.restrictKeys m s)

hls-graph/src/Development/IDE/Graph/Internal/Profile.hs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import Data.Maybe
2222
import Data.Time (getCurrentTime)
2323
import Data.Time.Format.ISO8601 (iso8601Show)
2424
import Development.IDE.Graph.Internal.Database (getDirtySet)
25+
import Development.IDE.Graph.Internal.Key
2526
import Development.IDE.Graph.Internal.Paths
2627
import Development.IDE.Graph.Internal.Types
2728
import qualified Language.Javascript.DGTable as DGTable
@@ -63,14 +64,15 @@ resultsOnly mp = mapKeyMap (\r ->
6364
-- | Given a map of representing a dependency order (with a show for error messages), find an ordering for the items such
6465
-- that no item points to an item before itself.
6566
-- Raise an error if you end up with a cycle.
66-
-- dependencyOrder :: (Eq a, Hashable a) => (a -> String) -> [(a,[a])] -> [a]
67+
--
6768
-- Algorithm:
6869
-- Divide everyone up into those who have no dependencies [Id]
6970
-- And those who depend on a particular Id, Dep :-> Maybe [(Key,[Dep])]
7071
-- Where d :-> Just (k, ds), k depends on firstly d, then remaining on ds
7172
-- For each with no dependencies, add to list, then take its dep hole and
7273
-- promote them either to Nothing (if ds == []) or into a new slot.
7374
-- k :-> Nothing means the key has already been freed
75+
dependencyOrder :: (Key -> String) -> [(Key, [Key])] -> [Key]
7476
dependencyOrder shw status =
7577
f (map fst noDeps) $
7678
mapKeyMap Just $
@@ -87,7 +89,7 @@ dependencyOrder shw status =
8789
where (bad,badOverflow) = splitAt 10 [shw i | (i, Just _) <- toListKeyMap mp]
8890

8991
f (x:xs) mp = x : f (now++xs) later
90-
where Just free = lookupDefaultKeyMap (Just []) x mp
92+
where free = fromMaybe [] $ lookupDefaultKeyMap (Just []) x mp
9193
(now,later) = foldl' g ([], insertKeyMap x Nothing mp) free
9294

9395
g (free, mp) (k, []) = (k:free, mp)

hls-graph/src/Development/IDE/Graph/Internal/Rules.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ import Data.IORef
1717
import Data.Maybe
1818
import Data.Typeable
1919
import Development.IDE.Graph.Classes
20+
import Development.IDE.Graph.Internal.Key
2021
import Development.IDE.Graph.Internal.Types
2122

2223
-- | The type mapping between the @key@ or a rule and the resulting @value@.

0 commit comments

Comments
 (0)