@@ -50,6 +50,7 @@ import Development.IDE.GHC.Compat hiding (parseModule, typecheckModule)
50
50
import Development.IDE.GHC.Util
51
51
import Development.IDE.GHC.WithDynFlags
52
52
import Data.Either.Extra
53
+ import qualified Development.IDE.Types.Logger as L
53
54
import Data.Maybe
54
55
import Data.Foldable
55
56
import qualified Data.IntMap.Strict as IntMap
@@ -62,6 +63,7 @@ import Development.Shake hiding (Diagnostic)
62
63
import Development.IDE.Core.RuleTypes
63
64
import Development.IDE.Spans.Type
64
65
import qualified Data.ByteString.Char8 as BS
66
+ import Development.IDE.Core.PositionMapping
65
67
66
68
import qualified GHC.LanguageExtensions as LangExt
67
69
import HscTypes
@@ -76,10 +78,12 @@ import Development.Shake.Classes hiding (get, put)
76
78
import Control.Monad.Trans.Except (runExceptT )
77
79
import Data.ByteString (ByteString )
78
80
import Control.Concurrent.Async (concurrently )
81
+ import System.Time.Extra
82
+ import Control.Monad.Reader
83
+ import System.Directory ( getModificationTime )
84
+ import Control.Exception
79
85
80
86
import Control.Monad.State
81
- import System.IO.Error (isDoesNotExistError )
82
- import Control.Exception.Safe (IOException , catch )
83
87
import FastString (FastString (uniq ))
84
88
import qualified HeaderInfo as Hdr
85
89
@@ -91,14 +95,14 @@ toIdeResult = either (, Nothing) (([],) . Just)
91
95
92
96
-- | useE is useful to implement functions that aren’t rules but need shortcircuiting
93
97
-- e.g. getDefinition.
94
- useE :: IdeRule k v => k -> NormalizedFilePath -> MaybeT Action v
95
- useE k = MaybeT . use k
98
+ useE :: IdeRule k v => k -> NormalizedFilePath -> MaybeT IdeAction ( v , PositionMapping )
99
+ useE k = MaybeT . useWithStaleFast k
96
100
97
- useNoFileE :: IdeRule k v => k -> MaybeT Action v
98
- useNoFileE k = useE k emptyFilePath
101
+ useNoFileE :: IdeRule k v => IdeState -> k -> MaybeT IdeAction v
102
+ useNoFileE _ide k = fst <$> useE k emptyFilePath
99
103
100
- usesE :: IdeRule k v => k -> [NormalizedFilePath ] -> MaybeT Action [ v ]
101
- usesE k = MaybeT . fmap sequence . uses k
104
+ usesE :: IdeRule k v => k -> [NormalizedFilePath ] -> MaybeT IdeAction [( v , PositionMapping ) ]
105
+ usesE k = MaybeT . fmap sequence . mapM (useWithStaleFast k)
102
106
103
107
defineNoFile :: IdeRule k v => (k -> Action v ) -> Rules ()
104
108
defineNoFile f = define $ \ k file -> do
@@ -120,78 +124,91 @@ getDependencies :: NormalizedFilePath -> Action (Maybe [NormalizedFilePath])
120
124
getDependencies file = fmap transitiveModuleDeps <$> use GetDependencies file
121
125
122
126
-- | Try to get hover text for the name under point.
123
- getAtPoint :: NormalizedFilePath -> Position -> Action (Maybe (Maybe Range , [T. Text ]))
127
+ getAtPoint :: NormalizedFilePath -> Position -> IdeAction (Maybe (Maybe Range , [T. Text ]))
124
128
getAtPoint file pos = fmap join $ runMaybeT $ do
125
- opts <- lift getIdeOptions
126
- spans <- useE GetSpanInfo file
127
- return $ AtPoint. atPoint opts spans pos
129
+ ide <- ask
130
+ opts <- liftIO $ getIdeOptionsIO ide
131
+ (spans, mapping) <- useE GetSpanInfo file
132
+ ! pos' <- MaybeT (return $ fromCurrentPosition mapping pos)
133
+ return $ AtPoint. atPoint opts spans pos'
128
134
129
135
-- | Goto Definition.
130
- getDefinition :: NormalizedFilePath -> Position -> Action (Maybe Location )
131
- getDefinition file pos = fmap join $ runMaybeT $ do
132
- opts <- lift getIdeOptions
133
- spans <- useE GetSpanInfo file
134
- lift $ AtPoint. gotoDefinition (getHieFile file) opts (spansExprs spans) pos
135
-
136
- getTypeDefinition :: NormalizedFilePath -> Position -> Action (Maybe [Location ])
136
+ getDefinition :: NormalizedFilePath -> Position -> IdeAction (Maybe Location )
137
+ getDefinition file pos = runMaybeT $ do
138
+ ide <- ask
139
+ opts <- liftIO $ getIdeOptionsIO ide
140
+ (spans,mapping) <- useE GetSpanInfo file
141
+ ! pos' <- MaybeT (return $ fromCurrentPosition mapping pos)
142
+ AtPoint. gotoDefinition (getHieFile ide file) opts (spansExprs spans) pos'
143
+
144
+ getTypeDefinition :: NormalizedFilePath -> Position -> IdeAction (Maybe [Location ])
137
145
getTypeDefinition file pos = runMaybeT $ do
138
- opts <- lift getIdeOptions
139
- spans <- useE GetSpanInfo file
140
- lift $ AtPoint. gotoTypeDefinition (getHieFile file) opts (spansExprs spans) pos
141
-
146
+ ide <- ask
147
+ opts <- liftIO $ getIdeOptionsIO ide
148
+ (spans,mapping) <- useE GetSpanInfo file
149
+ ! pos' <- MaybeT (return $ fromCurrentPosition mapping pos)
150
+ AtPoint. gotoTypeDefinition (getHieFile ide file) opts (spansExprs spans) pos'
142
151
143
152
getHieFile
144
- :: NormalizedFilePath -- ^ file we're editing
153
+ :: ShakeExtras
154
+ -> NormalizedFilePath -- ^ file we're editing
145
155
-> Module -- ^ module dep we want info for
146
- -> Action ( Maybe (HieFile , FilePath ) ) -- ^ hie stuff for the module
147
- getHieFile file mod = do
148
- TransitiveDependencies {transitiveNamedModuleDeps} <- use_ GetDependencies file
156
+ -> MaybeT IdeAction (HieFile , FilePath ) -- ^ hie stuff for the module
157
+ getHieFile ide file mod = do
158
+ TransitiveDependencies {transitiveNamedModuleDeps} <- fst <$> useE GetDependencies file
149
159
case find (\ x -> nmdModuleName x == moduleName mod ) transitiveNamedModuleDeps of
150
160
Just NamedModuleDep {nmdFilePath= nfp} -> do
151
161
let modPath = fromNormalizedFilePath nfp
152
- (_diags, hieFile) <- getHomeHieFile nfp
153
- return $ (, modPath) <$> hieFile
154
- _ -> getPackageHieFile mod file
155
-
162
+ hieFile <- getHomeHieFile nfp
163
+ return (hieFile, modPath)
164
+ _ -> getPackageHieFile ide mod file
156
165
157
- getHomeHieFile :: NormalizedFilePath -> Action ([ IOException ], Maybe HieFile )
166
+ getHomeHieFile :: NormalizedFilePath -> MaybeT IdeAction HieFile
158
167
getHomeHieFile f = do
159
- ms <- use_ GetModSummary f
160
-
161
- -- .hi and .hie files are generated as a byproduct of typechecking.
162
- -- To avoid duplicating staleness checking already performed for .hi files,
163
- -- we overapproximate here by depending on the GetModIface rule.
164
- hiFile <- use GetModIface f
165
-
166
- case hiFile of
167
- Nothing -> return ([] , Nothing )
168
- Just _ -> liftIO $ do
169
- hf <- loadHieFile $ ml_hie_file $ ms_location ms
170
- return ([] , Just hf)
171
- `catch` \ e ->
172
- if isDoesNotExistError e
173
- then return ([] , Nothing )
174
- else return ([e], Nothing )
175
-
176
- getPackageHieFile :: Module -- ^ Package Module to load .hie file for
168
+ ms <- fst <$> useE GetModSummary f
169
+ let normal_hie_f = toNormalizedFilePath' hie_f
170
+ hie_f = ml_hie_file $ ms_location ms
171
+
172
+ mbHieTimestamp <- either (\ (_ :: IOException ) -> Nothing ) Just <$> (liftIO $ try $ getModificationTime hie_f)
173
+ srcTimestamp <- MaybeT (either (\ (_ :: IOException ) -> Nothing ) Just <$> (liftIO $ try $ getModificationTime $ fromNormalizedFilePath f))
174
+ liftIO $ print (mbHieTimestamp, srcTimestamp, hie_f, normal_hie_f)
175
+ let isUpToDate
176
+ | Just d <- mbHieTimestamp = d > srcTimestamp
177
+ | otherwise = False
178
+
179
+ if isUpToDate
180
+ then do
181
+ hf <- liftIO $ whenMaybe isUpToDate (loadHieFile hie_f)
182
+ MaybeT $ return hf
183
+ else do
184
+ wait <- lift $ delayedAction $ mkDelayedAction " OutOfDateHie" L. Info $ do
185
+ hsc <- hscEnv <$> use_ GhcSession f
186
+ pm <- use_ GetParsedModule f
187
+ typeCheckRuleDefinition hsc pm DoGenerateInterfaceFiles
188
+ _ <- MaybeT $ liftIO $ timeout 1 wait
189
+ liftIO $ loadHieFile hie_f
190
+
191
+
192
+ getPackageHieFile :: ShakeExtras
193
+ -> Module -- ^ Package Module to load .hie file for
177
194
-> NormalizedFilePath -- ^ Path of home module importing the package module
178
- -> Action ( Maybe (HieFile , FilePath ) )
179
- getPackageHieFile mod file = do
180
- pkgState <- hscEnv <$> use_ GhcSession file
181
- IdeOptions {.. } <- getIdeOptions
195
+ -> MaybeT IdeAction (HieFile , FilePath )
196
+ getPackageHieFile ide mod file = do
197
+ pkgState <- hscEnv . fst <$> useE GhcSession file
198
+ IdeOptions {.. } <- liftIO $ getIdeOptionsIO ide
182
199
let unitId = moduleUnitId mod
183
200
case lookupPackageConfig unitId pkgState of
184
201
Just pkgConfig -> do
185
202
-- 'optLocateHieFile' returns Nothing if the file does not exist
186
203
hieFile <- liftIO $ optLocateHieFile optPkgLocationOpts pkgConfig mod
187
204
path <- liftIO $ optLocateSrcFile optPkgLocationOpts pkgConfig mod
188
205
case (hieFile, path) of
189
- (Just hiePath, Just modPath) ->
206
+ (Just hiePath, Just modPath) -> MaybeT $
190
207
-- deliberately loaded outside the Shake graph
191
208
-- to avoid dependencies on non-workspace files
192
209
liftIO $ Just . (, modPath) <$> loadHieFile hiePath
193
- _ -> return Nothing
194
- _ -> return Nothing
210
+ _ -> MaybeT $ return Nothing
211
+ _ -> MaybeT $ return Nothing
195
212
196
213
-- | Parse the contents of a daml file.
197
214
getParsedModule :: NormalizedFilePath -> Action (Maybe ParsedModule )
0 commit comments