Skip to content

Commit 12b21f7

Browse files
authored
Change getDocumentation to work with parsed modules (#413)
* Refactor getDocumentation to work with parsed modules * Fix names to express semantic rather than type information
1 parent eb69b81 commit 12b21f7

File tree

5 files changed

+49
-47
lines changed

5 files changed

+49
-47
lines changed

src/Development/IDE/Core/Rules.hs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -266,10 +266,10 @@ getSpanInfoRule =
266266
define $ \GetSpanInfo file -> do
267267
tc <- use_ TypeCheck file
268268
deps <- maybe (TransitiveDependencies [] []) fst <$> useWithStale GetDependencies file
269-
tms <- mapMaybe (fmap fst) <$> usesWithStale TypeCheck (transitiveModuleDeps deps)
269+
parsedDeps <- mapMaybe (fmap fst) <$> usesWithStale GetParsedModule (transitiveModuleDeps deps)
270270
(fileImports, _) <- use_ GetLocatedImports file
271271
packageState <- hscEnv <$> use_ GhcSession file
272-
x <- liftIO $ getSrcSpanInfos packageState fileImports tc tms
272+
x <- liftIO $ getSrcSpanInfos packageState fileImports tc parsedDeps
273273
return ([], Just x)
274274

275275
-- Typechecks a module.

src/Development/IDE/Plugin/Completions.hs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,13 +32,13 @@ produceCompletions :: Rules ()
3232
produceCompletions =
3333
define $ \ProduceCompletions file -> do
3434
deps <- maybe (TransitiveDependencies [] []) fst <$> useWithStale GetDependencies file
35-
tms <- mapMaybe (fmap fst) <$> usesWithStale TypeCheck (transitiveModuleDeps deps)
35+
parsedDeps <- mapMaybe (fmap fst) <$> usesWithStale GetParsedModule (transitiveModuleDeps deps)
3636
tm <- fmap fst <$> useWithStale TypeCheck file
3737
packageState <- fmap (hscEnv . fst) <$> useWithStale GhcSession file
3838
case (tm, packageState) of
3939
(Just tm', Just packageState') -> do
4040
cdata <- liftIO $ cacheDataProducer packageState' (hsc_dflags packageState')
41-
(tmrModule tm') (map tmrModule tms)
41+
(tmrModule tm') parsedDeps
4242
return ([], Just (cdata, tm'))
4343
_ -> return ([], Nothing)
4444

src/Development/IDE/Plugin/Completions/Logic.hs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -210,8 +210,8 @@ mkPragmaCompl label insertText =
210210
Nothing Nothing Nothing Nothing Nothing (Just insertText) (Just Snippet)
211211
Nothing Nothing Nothing Nothing Nothing
212212

213-
cacheDataProducer :: HscEnv -> DynFlags -> TypecheckedModule -> [TypecheckedModule] -> IO CachedCompletions
214-
cacheDataProducer packageState dflags tm tcs = do
213+
cacheDataProducer :: HscEnv -> DynFlags -> TypecheckedModule -> [ParsedModule] -> IO CachedCompletions
214+
cacheDataProducer packageState dflags tm deps = do
215215
let parsedMod = tm_parsed_module tm
216216
curMod = moduleName $ ms_mod $ pm_mod_summary parsedMod
217217
Just (_,limports,_,_) = tm_renamed_source tm
@@ -269,12 +269,12 @@ cacheDataProducer packageState dflags tm tcs = do
269269
let typ = Just $ varType var
270270
name = Var.varName var
271271
label = T.pack $ showGhc name
272-
docs <- runGhcEnv packageState $ getDocumentationTryGhc (tm:tcs) name
272+
docs <- runGhcEnv packageState $ getDocumentationTryGhc (tm_parsed_module tm : deps) name
273273
return $ CI name (showModName curMod) typ label Nothing docs
274274

275275
toCompItem :: ModuleName -> Name -> IO CompItem
276276
toCompItem mn n = do
277-
docs <- runGhcEnv packageState $ getDocumentationTryGhc (tm:tcs) n
277+
docs <- runGhcEnv packageState $ getDocumentationTryGhc (tm_parsed_module tm : deps) n
278278
-- lookupName uses runInteractiveHsc, i.e., GHCi stuff which does not work with GHCi
279279
-- and leads to fun errors like "Cannot continue after interface file error".
280280
#ifdef GHC_LIB

src/Development/IDE/Spans/Calculate.hs

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -51,25 +51,25 @@ getSrcSpanInfos
5151
:: HscEnv
5252
-> [(Located ModuleName, Maybe NormalizedFilePath)]
5353
-> TcModuleResult
54-
-> [TcModuleResult]
54+
-> [ParsedModule]
5555
-> IO SpansInfo
56-
getSrcSpanInfos env imports tc tms =
56+
getSrcSpanInfos env imports tc deps =
5757
runGhcEnv env $
58-
getSpanInfo imports (tmrModule tc) (map tmrModule tms)
58+
getSpanInfo imports (tmrModule tc) deps
5959

6060
-- | Get ALL source spans in the module.
6161
getSpanInfo :: GhcMonad m
6262
=> [(Located ModuleName, Maybe NormalizedFilePath)] -- ^ imports
6363
-> TypecheckedModule
64-
-> [TypecheckedModule]
64+
-> [ParsedModule]
6565
-> m SpansInfo
66-
getSpanInfo mods tcm tcms =
66+
getSpanInfo mods tcm deps =
6767
do let tcs = tm_typechecked_source tcm
6868
bs = listifyAllSpans tcs :: [LHsBind GhcTc]
6969
es = listifyAllSpans tcs :: [LHsExpr GhcTc]
7070
ps = listifyAllSpans' tcs :: [Pat GhcTc]
7171
ts = listifyAllSpans $ tm_renamed_source tcm :: [LHsType GhcRn]
72-
allModules = tcm:tcms
72+
allModules = tm_parsed_module tcm : deps
7373
funBinds = funBindMap $ tm_parsed_module tcm
7474
bts <- mapM (getTypeLHsBind allModules funBinds) bs -- binds
7575
ets <- mapM (getTypeLHsExpr allModules) es -- expressions
@@ -117,19 +117,19 @@ ieLNames _ = []
117117

118118
-- | Get the name and type of a binding.
119119
getTypeLHsBind :: (GhcMonad m)
120-
=> [TypecheckedModule]
120+
=> [ParsedModule]
121121
-> OccEnv (HsBind GhcPs)
122122
-> LHsBind GhcTc
123123
-> m [(SpanSource, SrcSpan, Maybe Type, SpanDoc)]
124-
getTypeLHsBind tms funBinds (L _spn FunBind{fun_id = pid})
124+
getTypeLHsBind deps funBinds (L _spn FunBind{fun_id = pid})
125125
| Just FunBind {fun_matches = MG{mg_alts=L _ matches}} <- lookupOccEnv funBinds (occName $ unLoc pid) = do
126126
let name = getName (unLoc pid)
127-
docs <- getDocumentationTryGhc tms name
127+
docs <- getDocumentationTryGhc deps name
128128
return [(Named name, getLoc mc_fun, Just (varType (unLoc pid)), docs) | match <- matches, FunRhs{mc_fun = mc_fun} <- [m_ctxt $ unLoc match] ]
129129
-- In theory this shouldn’t ever fail but if it does, we can at least show the first clause.
130-
getTypeLHsBind tms _ (L _spn FunBind{fun_id = pid,fun_matches = MG{}}) = do
130+
getTypeLHsBind deps _ (L _spn FunBind{fun_id = pid,fun_matches = MG{}}) = do
131131
let name = getName (unLoc pid)
132-
docs <- getDocumentationTryGhc tms name
132+
docs <- getDocumentationTryGhc deps name
133133
return [(Named name, getLoc pid, Just (varType (unLoc pid)), docs)]
134134
getTypeLHsBind _ _ _ = return []
135135

@@ -142,17 +142,17 @@ getConstraintsLHsBind _ = []
142142

143143
-- | Get the name and type of an expression.
144144
getTypeLHsExpr :: (GhcMonad m)
145-
=> [TypecheckedModule]
145+
=> [ParsedModule]
146146
-> LHsExpr GhcTc
147147
-> m (Maybe (SpanSource, SrcSpan, Maybe Type, SpanDoc))
148-
getTypeLHsExpr tms e = do
148+
getTypeLHsExpr deps e = do
149149
hs_env <- getSession
150150
(_, mbe) <- liftIO (deSugarExpr hs_env e)
151151
case mbe of
152152
Just expr -> do
153153
let ss = getSpanSource (unLoc e)
154154
docs <- case ss of
155-
Named n -> getDocumentationTryGhc tms n
155+
Named n -> getDocumentationTryGhc deps n
156156
_ -> return emptySpanDoc
157157
return $ Just (ss, getLoc e, Just (CoreUtils.exprType expr), docs)
158158
Nothing -> return Nothing
@@ -198,13 +198,13 @@ getTypeLHsExpr tms e = do
198198

199199
-- | Get the name and type of a pattern.
200200
getTypeLPat :: (GhcMonad m)
201-
=> [TypecheckedModule]
201+
=> [ParsedModule]
202202
-> Pat GhcTc
203203
-> m (Maybe (SpanSource, SrcSpan, Maybe Type, SpanDoc))
204-
getTypeLPat tms pat = do
204+
getTypeLPat deps pat = do
205205
let (src, spn) = getSpanSource pat
206206
docs <- case src of
207-
Named n -> getDocumentationTryGhc tms n
207+
Named n -> getDocumentationTryGhc deps n
208208
_ -> return emptySpanDoc
209209
return $ Just (src, spn, Just (hsPatType pat), docs)
210210
where
@@ -216,12 +216,12 @@ getTypeLPat tms pat = do
216216

217217
getLHsType
218218
:: GhcMonad m
219-
=> [TypecheckedModule]
219+
=> [ParsedModule]
220220
-> LHsType GhcRn
221221
-> m [(SpanSource, SrcSpan, Maybe Type, SpanDoc)]
222-
getLHsType tms (L spn (HsTyVar U _ v)) = do
222+
getLHsType deps (L spn (HsTyVar U _ v)) = do
223223
let n = unLoc v
224-
docs <- getDocumentationTryGhc tms n
224+
docs <- getDocumentationTryGhc deps n
225225
#ifdef GHC_LIB
226226
let ty = Right Nothing
227227
#else

src/Development/IDE/Spans/Documentation.hs

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -14,33 +14,33 @@ import Data.List.Extra
1414
import qualified Data.Map as M
1515
import Data.Maybe
1616
import qualified Data.Text as T
17+
import Development.IDE.GHC.Compat
1718
import Development.IDE.GHC.Error
1819
import Development.IDE.Spans.Common
1920
import FastString
20-
import GHC
2121
import SrcLoc
2222

2323

2424
getDocumentationTryGhc
2525
:: GhcMonad m
26-
=> [TypecheckedModule]
26+
=> [ParsedModule]
2727
-> Name
2828
-> m SpanDoc
2929
-- getDocs goes through the GHCi codepaths which cause problems on ghc-lib.
3030
-- See https://github.com/digital-asset/daml/issues/4152 for more details.
3131
#if MIN_GHC_API_VERSION(8,6,0) && !defined(GHC_LIB)
32-
getDocumentationTryGhc tcs name = do
32+
getDocumentationTryGhc sources name = do
3333
res <- catchSrcErrors "docs" $ getDocs name
3434
case res of
3535
Right (Right (Just docs, _)) -> return $ SpanDocString docs
36-
_ -> return $ SpanDocText $ getDocumentation tcs name
36+
_ -> return $ SpanDocText $ getDocumentation sources name
3737
#else
38-
getDocumentationTryGhc tcs name = do
39-
return $ SpanDocText $ getDocumentation tcs name
38+
getDocumentationTryGhc sources name = do
39+
return $ SpanDocText $ getDocumentation sources name
4040
#endif
4141

4242
getDocumentation
43-
:: [TypecheckedModule] -- ^ All of the possible modules it could be defined in.
43+
:: [ParsedModule] -- ^ All of the possible modules it could be defined in.
4444
-> Name -- ^ The name you want documentation for.
4545
-> [T.Text]
4646
-- This finds any documentation between the name you want
@@ -50,16 +50,18 @@ getDocumentation
5050
-- may be edge cases where it is very wrong).
5151
-- TODO : Build a version of GHC exactprint to extract this information
5252
-- more accurately.
53-
getDocumentation tcs targetName = fromMaybe [] $ do
53+
getDocumentation sources targetName = fromMaybe [] $ do
5454
-- Find the module the target is defined in.
5555
targetNameSpan <- realSpan $ nameSrcSpan targetName
5656
tc <-
5757
find ((==) (Just $ srcSpanFile targetNameSpan) . annotationFileName)
58-
$ reverse tcs -- TODO : Is reversing the list here really neccessary?
59-
-- Names bound by the module (we want to exclude non-"top-level"
60-
-- bindings but unfortunately we get all here).
61-
let bs = mapMaybe name_of_bind
62-
(listifyAllSpans (tm_typechecked_source tc) :: [LHsBind GhcTc])
58+
$ reverse sources -- TODO : Is reversing the list here really neccessary?
59+
60+
-- Top level names bound by the module
61+
let bs = [ n | let L _ HsModule{hsmodDecls} = pm_parsed_source tc
62+
, L _ (ValD hsbind) <- hsmodDecls
63+
, Just n <- [name_of_bind hsbind]
64+
]
6365
-- Sort the names' source spans.
6466
let sortedSpans = sortedNameSpans bs
6567
-- Now go ahead and extract the docs.
@@ -81,16 +83,16 @@ getDocumentation tcs targetName = fromMaybe [] $ do
8183
where
8284
-- Get the name bound by a binding. We only concern ourselves with
8385
-- @FunBind@ (which covers functions and variables).
84-
name_of_bind :: LHsBind GhcTc -> Maybe Name
85-
name_of_bind (L _ FunBind {fun_id}) = Just (getName (unLoc fun_id))
86+
name_of_bind :: HsBind GhcPs -> Maybe (Located RdrName)
87+
name_of_bind FunBind {fun_id} = Just fun_id
8688
name_of_bind _ = Nothing
8789
-- Get source spans from names, discard unhelpful spans, remove
8890
-- duplicates and sort.
89-
sortedNameSpans :: [Name] -> [RealSrcSpan]
90-
sortedNameSpans ls = nubSort (mapMaybe (realSpan . nameSrcSpan) ls)
91+
sortedNameSpans :: [Located RdrName] -> [RealSrcSpan]
92+
sortedNameSpans ls = nubSort (mapMaybe (realSpan . getLoc) ls)
9193
isBetween target before after = before <= target && target <= after
92-
ann = snd . pm_annotations . tm_parsed_module
93-
annotationFileName :: TypecheckedModule -> Maybe FastString
94+
ann = snd . pm_annotations
95+
annotationFileName :: ParsedModule -> Maybe FastString
9496
annotationFileName = fmap srcSpanFile . listToMaybe . realSpans . ann
9597
realSpans :: M.Map SrcSpan [Located a] -> [RealSrcSpan]
9698
realSpans =

0 commit comments

Comments
 (0)