Skip to content

Commit f39c4da

Browse files
committed
Implement lookupMod function
1 parent 2aecda9 commit f39c4da

File tree

2 files changed

+84
-3
lines changed

2 files changed

+84
-3
lines changed

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

Lines changed: 83 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,20 @@ module Development.IDE.Core.Actions
1010
, lookupMod
1111
) where
1212

13+
import Control.Concurrent.MVar (MVar, newEmptyMVar, putMVar, readMVar)
14+
import Control.Concurrent.STM (atomically)
15+
import Control.Concurrent.STM.TQueue (unGetTQueue)
16+
import Control.Monad (unless)
1317
import Control.Monad.Extra (mapMaybeM)
1418
import Control.Monad.Reader
1519
import Control.Monad.Trans.Maybe
20+
import qualified Data.ByteString as BS
21+
import Data.Function ((&))
1622
import qualified Data.HashMap.Strict as HM
1723
import Data.Maybe
1824
import qualified Data.Text as T
1925
import Data.Tuple.Extra
26+
import Development.IDE.Core.Compile (loadHieFile)
2027
import Development.IDE.Core.OfInterest
2128
import Development.IDE.Core.PluginUtils
2229
import Development.IDE.Core.PositionMapping
@@ -33,18 +40,91 @@ import Language.LSP.Protocol.Types (DocumentHighlight (..),
3340
SymbolInformation (..),
3441
normalizedFilePathToUri,
3542
uriToNormalizedFilePath)
43+
import Language.LSP.Server (resRootPath)
44+
import System.Directory (createDirectoryIfMissing,
45+
doesFileExist,
46+
getPermissions,
47+
setOwnerExecutable,
48+
setOwnerWritable,
49+
setPermissions)
50+
import System.FilePath ((</>), (<.>), takeDirectory)
3651

3752

38-
-- | Eventually this will lookup/generate URIs for files in dependencies, but not in the
39-
-- project. Right now, this is just a stub.
53+
-- | Generates URIs for files in dependencies, but not in the
54+
-- project. Dependency files are produced from an HIE file and
55+
-- placed in the .hls/dependencies directory.
4056
lookupMod
4157
:: HieDbWriter -- ^ access the database
4258
-> FilePath -- ^ The `.hie` file we got from the database
4359
-> ModuleName
4460
-> Unit
4561
-> Bool -- ^ Is this file a boot file?
4662
-> MaybeT IdeAction Uri
47-
lookupMod _dbchan _hie_f _mod _uid _boot = MaybeT $ pure Nothing
63+
lookupMod HieDbWriter{indexQueue} hieFile moduleName uid _boot = MaybeT $ do
64+
-- We need the project root directory to determine where to put
65+
-- the .hls directory.
66+
mProjectRoot <- (resRootPath =<<) <$> asks lspEnv
67+
case mProjectRoot of
68+
Nothing -> pure Nothing
69+
Just projectRoot -> do
70+
-- Database writes happen asynchronously. We use an MVar to mark
71+
-- completion of the database update.
72+
completionToken <- liftIO $ newEmptyMVar
73+
-- Write out the contents of the dependency source to the
74+
-- .hls/dependencies directory, generate a URI for that
75+
-- location, and update the HieDb database with the source
76+
-- file location.
77+
moduleUri <- writeAndIndexSource projectRoot completionToken
78+
-- Wait for the database update to be completed.
79+
-- Reading the completionToken is blocked until it has
80+
-- a value.
81+
liftIO $ readMVar completionToken
82+
pure $ Just moduleUri
83+
where
84+
writeAndIndexSource :: FilePath -> MVar () -> IdeAction Uri
85+
writeAndIndexSource projectRoot completionToken = do
86+
fileExists <- liftIO $ doesFileExist writeOutPath
87+
-- No need to write out the file if it already exists.
88+
unless fileExists $ do
89+
nc <- asks ideNc
90+
liftIO $ do
91+
-- Create the directory where we will put the source.
92+
createDirectoryIfMissing True $ takeDirectory writeOutPath
93+
-- Load a raw Bytestring of the source from the HIE file.
94+
moduleSource <- hie_hs_src <$> loadHieFile (mkUpdater nc) hieFile
95+
-- Write the source into the .hls/dependencies directory.
96+
BS.writeFile writeOutPath moduleSource
97+
fileDefaultPermissions <- getPermissions writeOutPath
98+
let filePermissions = fileDefaultPermissions
99+
& setOwnerWritable False
100+
& setOwnerExecutable False
101+
-- Set the source file to readonly permissions.
102+
setPermissions writeOutPath filePermissions
103+
liftIO $ atomically $
104+
unGetTQueue indexQueue $ \withHieDb -> do
105+
withHieDb $ \db ->
106+
-- Add a source file to the database row for
107+
-- the HIE file.
108+
HieDb.addSrcFile db hieFile writeOutPath False
109+
-- Mark completion of the database update.
110+
putMVar completionToken ()
111+
pure $ moduleUri
112+
where
113+
-- The source will be written out in a directory from the
114+
-- name and hash of the package the dependency module is
115+
-- found in. The name and hash are both parts of the UnitId.
116+
writeOutDir :: FilePath
117+
writeOutDir = projectRoot </> ".hls" </> "dependencies" </> show uid
118+
-- The module name is separated into directories, with the
119+
-- last part of the module name giving the name of the
120+
-- haskell file with a .hs extension.
121+
writeOutFile :: FilePath
122+
writeOutFile = moduleNameSlashes moduleName <.> "hs"
123+
writeOutPath :: FilePath
124+
writeOutPath = writeOutDir </> writeOutFile
125+
moduleUri :: Uri
126+
moduleUri = AtPoint.toUri writeOutPath
127+
48128

49129

50130
-- IMPORTANT NOTE : make sure all rules `useWithStaleFastMT`d by these have a "Persistent Stale" rule defined,

ghcide/src/Development/IDE/Spans/AtPoint.hs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ module Development.IDE.Spans.AtPoint (
2020
, defRowToSymbolInfo
2121
, getNamesAtPoint
2222
, toCurrentLocation
23+
, toUri
2324
, rowToLoc
2425
, nameToLocation
2526
, LookupModule

0 commit comments

Comments
 (0)