Skip to content

Commit 510bd51

Browse files
authored
Remove some partial functions from Shake.hs (#2986)
Also removes a partial pattern match from Action.hs.
1 parent c3c73cf commit 510bd51

File tree

6 files changed

+38
-28
lines changed

6 files changed

+38
-28
lines changed

.hlint.yaml

-2
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,6 @@
8888
within:
8989
- Main
9090
- Experiments
91-
- Development.IDE.Core.Shake
9291
- Development.IDE.Plugin.CodeAction
9392
- Development.IDE.Plugin.Completions
9493
- Development.IDE.Plugin.CodeAction.ExactPrint
@@ -137,7 +136,6 @@
137136
- Wingman.CaseSplit
138137
- Wingman.Simplify
139138

140-
141139
- name: Data.Text.head
142140
within:
143141
- Development.IDE.Plugin.CodeAction

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

+15-14
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ import Data.EnumMap.Strict (EnumMap)
9999
import qualified Data.EnumMap.Strict as EM
100100
import Data.Foldable (for_, toList)
101101
import Data.Functor ((<&>))
102+
import Data.Functor.Identity
102103
import Data.Hashable
103104
import qualified Data.HashMap.Strict as HMap
104105
import Data.HashSet (HashSet)
@@ -920,21 +921,21 @@ defineNoDiagnostics recorder op = defineEarlyCutoff recorder $ RuleNoDiagnostics
920921
-- | Request a Rule result if available
921922
use :: IdeRule k v
922923
=> k -> NormalizedFilePath -> Action (Maybe v)
923-
use key file = head <$> uses key [file]
924+
use key file = runIdentity <$> uses key (Identity file)
924925

925926
-- | Request a Rule result, it not available return the last computed result, if any, which may be stale
926927
useWithStale :: IdeRule k v
927928
=> k -> NormalizedFilePath -> Action (Maybe (v, PositionMapping))
928-
useWithStale key file = head <$> usesWithStale key [file]
929+
useWithStale key file = runIdentity <$> usesWithStale key (Identity file)
929930

930931
-- | Request a Rule result, it not available return the last computed result which may be stale.
931932
-- Errors out if none available.
932933
useWithStale_ :: IdeRule k v
933934
=> k -> NormalizedFilePath -> Action (v, PositionMapping)
934-
useWithStale_ key file = head <$> usesWithStale_ key [file]
935+
useWithStale_ key file = runIdentity <$> usesWithStale_ key (Identity file)
935936

936937
-- | Plural version of 'useWithStale_'
937-
usesWithStale_ :: IdeRule k v => k -> [NormalizedFilePath] -> Action [(v, PositionMapping)]
938+
usesWithStale_ :: (Traversable f, IdeRule k v) => k -> f NormalizedFilePath -> Action (f (v, PositionMapping))
938939
usesWithStale_ key files = do
939940
res <- usesWithStale key files
940941
case sequence res of
@@ -999,37 +1000,37 @@ useNoFile :: IdeRule k v => k -> Action (Maybe v)
9991000
useNoFile key = use key emptyFilePath
10001001

10011002
use_ :: IdeRule k v => k -> NormalizedFilePath -> Action v
1002-
use_ key file = head <$> uses_ key [file]
1003+
use_ key file = runIdentity <$> uses_ key (Identity file)
10031004

10041005
useNoFile_ :: IdeRule k v => k -> Action v
10051006
useNoFile_ key = use_ key emptyFilePath
10061007

1007-
uses_ :: IdeRule k v => k -> [NormalizedFilePath] -> Action [v]
1008+
uses_ :: (Traversable f, IdeRule k v) => k -> f NormalizedFilePath -> Action (f v)
10081009
uses_ key files = do
10091010
res <- uses key files
10101011
case sequence res of
10111012
Nothing -> liftIO $ throwIO $ BadDependency (show key)
10121013
Just v -> return v
10131014

10141015
-- | Plural version of 'use'
1015-
uses :: IdeRule k v
1016-
=> k -> [NormalizedFilePath] -> Action [Maybe v]
1017-
uses key files = map (\(A value) -> currentValue value) <$> apply (map (Q . (key,)) files)
1016+
uses :: (Traversable f, IdeRule k v)
1017+
=> k -> f NormalizedFilePath -> Action (f (Maybe v))
1018+
uses key files = fmap (\(A value) -> currentValue value) <$> apply (fmap (Q . (key,)) files)
10181019

10191020
-- | Return the last computed result which might be stale.
1020-
usesWithStale :: IdeRule k v
1021-
=> k -> [NormalizedFilePath] -> Action [Maybe (v, PositionMapping)]
1021+
usesWithStale :: (Traversable f, IdeRule k v)
1022+
=> k -> f NormalizedFilePath -> Action (f (Maybe (v, PositionMapping)))
10221023
usesWithStale key files = do
1023-
_ <- apply (map (Q . (key,)) files)
1024+
_ <- apply (fmap (Q . (key,)) files)
10241025
-- We don't look at the result of the 'apply' since 'lastValue' will
10251026
-- return the most recent successfully computed value regardless of
10261027
-- whether the rule succeeded or not.
1027-
mapM (lastValue key) files
1028+
traverse (lastValue key) files
10281029

10291030
useWithoutDependency :: IdeRule k v
10301031
=> k -> NormalizedFilePath -> Action (Maybe v)
10311032
useWithoutDependency key file =
1032-
(\[A value] -> currentValue value) <$> applyWithoutDependency [Q (key, file)]
1033+
(\(Identity (A value)) -> currentValue value) <$> applyWithoutDependency (Identity (Q (key, file)))
10331034

10341035
data RuleBody k v
10351036
= Rule (k -> NormalizedFilePath -> Action (Maybe BS.ByteString, IdeResult v))

hls-graph/hls-graph.cabal

+1
Original file line numberDiff line numberDiff line change
@@ -134,4 +134,5 @@ test-suite tests
134134
, tasty-hunit
135135
, tasty-rerun
136136
, text
137+
, unordered-containers
137138
build-tool-depends: hspec-discover:hspec-discover -any

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

+6-4
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ import Control.Monad.IO.Class
2525
import Control.Monad.Trans.Class
2626
import Control.Monad.Trans.Reader
2727
import Data.IORef
28+
import Data.Functor.Identity
29+
import Data.Foldable (toList)
2830
import Development.IDE.Graph.Classes
2931
import Development.IDE.Graph.Internal.Database
3032
import Development.IDE.Graph.Internal.Rules (RuleResult)
@@ -111,19 +113,19 @@ actionFinally a b = do
111113
Action $ lift $ finally (runReaderT (fromAction a) v) b
112114

113115
apply1 :: (RuleResult key ~ value, ShakeValue key, Typeable value) => key -> Action value
114-
apply1 k = head <$> apply [k]
116+
apply1 k = runIdentity <$> apply (Identity k)
115117

116-
apply :: (RuleResult key ~ value, ShakeValue key, Typeable value) => [key] -> Action [value]
118+
apply :: (Traversable f, RuleResult key ~ value, ShakeValue key, Typeable value) => f key -> Action (f value)
117119
apply ks = do
118120
db <- Action $ asks actionDatabase
119121
stack <- Action $ asks actionStack
120122
(is, vs) <- liftIO $ build db stack ks
121123
ref <- Action $ asks actionDeps
122-
liftIO $ modifyIORef ref (ResultDeps is <>)
124+
liftIO $ modifyIORef ref (ResultDeps (toList is) <>)
123125
pure vs
124126

125127
-- | Evaluate a list of keys without recording any dependencies.
126-
applyWithoutDependency :: (RuleResult key ~ value, ShakeValue key, Typeable value) => [key] -> Action [value]
128+
applyWithoutDependency :: (Traversable f, RuleResult key ~ value, ShakeValue key, Typeable value) => f key -> Action (f value)
127129
applyWithoutDependency ks = do
128130
db <- Action $ asks actionDatabase
129131
stack <- Action $ asks actionStack

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

+14-6
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@
1212

1313
module Development.IDE.Graph.Internal.Database (newDatabase, incDatabase, build, getDirtySet, getKeysAndVisitAge) where
1414

15+
import Prelude hiding (unzip)
16+
1517
import Control.Concurrent.Async
1618
import Control.Concurrent.Extra
1719
import Control.Concurrent.STM.Stats (STM, atomically,
@@ -30,6 +32,7 @@ import Data.Foldable (for_, traverse_)
3032
import Data.HashSet (HashSet)
3133
import qualified Data.HashSet as HSet
3234
import Data.IORef.Extra
35+
import Data.List.NonEmpty (unzip)
3336
import Data.Maybe
3437
import Data.Traversable (for)
3538
import Data.Tuple.Extra
@@ -43,6 +46,7 @@ import qualified StmContainers.Map as SMap
4346
import System.Time.Extra (duration, sleep)
4447
import System.IO.Unsafe
4548

49+
4650
newDatabase :: Dynamic -> TheRules -> IO Database
4751
newDatabase databaseExtra databaseRules = do
4852
databaseStep <- newTVarIO $ Step 0
@@ -78,13 +82,17 @@ updateDirty = Focus.adjust $ \(KeyDetails status rdeps) ->
7882
in KeyDetails status' rdeps
7983
-- | Unwrap and build a list of keys in parallel
8084
build
81-
:: forall key value . (RuleResult key ~ value, Typeable key, Show key, Hashable key, Eq key, Typeable value)
82-
=> Database -> Stack -> [key] -> IO ([Key], [value])
85+
:: forall f key value . (Traversable f, RuleResult key ~ value, Typeable key, Show key, Hashable key, Eq key, Typeable value)
86+
=> Database -> Stack -> f key -> IO (f Key, f value)
8387
-- build _ st k | traceShow ("build", st, k) False = undefined
8488
build db stack keys = do
85-
(ids, vs) <- runAIO $ fmap unzip $ either return liftIO =<<
86-
builder db stack (map Key keys)
87-
pure (ids, map (asV . resultValue) vs)
89+
built <- runAIO $ do
90+
built <- builder db stack (fmap Key keys)
91+
case built of
92+
Left clean -> return clean
93+
Right dirty -> liftIO dirty
94+
let (ids, vs) = unzip built
95+
pure (ids, fmap (asV . resultValue) vs)
8896
where
8997
asV :: Value -> value
9098
asV (Value x) = unwrapDynamic x
@@ -93,7 +101,7 @@ build db stack keys = do
93101
-- If none of the keys are dirty, we can return the results immediately.
94102
-- Otherwise, a blocking computation is returned *which must be evaluated asynchronously* to avoid deadlock.
95103
builder
96-
:: Database -> Stack -> [Key] -> AIO (Either [(Key, Result)] (IO [(Key, Result)]))
104+
:: Traversable f => Database -> Stack -> f Key -> AIO (Either (f (Key, Result)) (IO (f (Key, Result))))
97105
-- builder _ st kk | traceShow ("builder", st,kk) False = undefined
98106
builder db@Database{..} stack keys = withRunInIO $ \(RunInIO run) -> do
99107
-- Things that I need to force before my results are ready

hls-graph/test/ActionSpec.hs

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
{-# LANGUAGE OverloadedLists #-}
21
{-# LANGUAGE OverloadedStrings #-}
32
{-# LANGUAGE RecordWildCards #-}
43
{-# LANGUAGE TypeApplications #-}
@@ -12,6 +11,7 @@ import Development.IDE.Graph.Database (shakeNewDatabase, shakeRunDatabase)
1211
import Development.IDE.Graph.Internal.Action (apply1)
1312
import Development.IDE.Graph.Internal.Types
1413
import Development.IDE.Graph.Rule
14+
import qualified Data.HashSet as HashSet
1515
import Example
1616
import qualified StmContainers.Map as STM
1717
import Test.Hspec
@@ -54,7 +54,7 @@ spec = do
5454
apply1 theKey
5555
res `shouldBe` [True]
5656
Just KeyDetails {..} <- atomically $ STM.lookup (Key (Rule @())) databaseValues
57-
keyReverseDeps `shouldBe` [Key theKey]
57+
keyReverseDeps `shouldBe` HashSet.fromList [Key theKey]
5858
it "rethrows exceptions" $ do
5959
db <- shakeNewDatabase shakeOptions $ do
6060
addRule $ \(Rule :: Rule ()) old mode -> error "boom"

0 commit comments

Comments
 (0)