@@ -53,12 +53,20 @@ import qualified Data.Text as T
53
53
54
54
import qualified Data.Array as A
55
55
import Data.Either
56
- import Data.List (isSuffixOf )
57
56
import Data.List.Extra (dropEnd1 , nubOrd )
58
57
59
58
import HieDb hiding (pointCommand )
60
59
import System.Directory (doesFileExist )
61
60
61
+ #if MIN_VERSION_ghc(9,0,1)
62
+ import qualified Outputable as O
63
+ import Data.Tree
64
+ import qualified Data.Tree as T
65
+ import Data.List (isSuffixOf , sortOn )
66
+ #else
67
+ import Data.List (isSuffixOf )
68
+ #endif
69
+
62
70
-- | Gives a Uri for the module, given the .hie file location and the the module info
63
71
-- The Bool denotes if it is a boot module
64
72
type LookupModule m = FilePath -> ModuleName -> Unit -> Bool -> MaybeT m Uri
@@ -155,7 +163,13 @@ documentHighlight
155
163
-> MaybeT m [DocumentHighlight ]
156
164
documentHighlight hf rf pos = pure highlights
157
165
where
158
- ns = concat $ pointCommand hf pos (rights . M. keys . getNodeIds)
166
+ #if MIN_VERSION_ghc(9,0,1)
167
+ -- We don't want to show document highlights for evidence variables, which is invisible
168
+ notEvidence = not . any isEvidenceContext . identInfo
169
+ #else
170
+ notEvidence = const True
171
+ #endif
172
+ ns = concat $ pointCommand hf pos (rights . M. keys . M. filter notEvidence . getNodeIds)
159
173
highlights = do
160
174
n <- ns
161
175
ref <- fromMaybe [] (M. lookup (Right n) rf)
@@ -185,7 +199,7 @@ gotoDefinition
185
199
-> LookupModule m
186
200
-> IdeOptions
187
201
-> M. Map ModuleName NormalizedFilePath
188
- -> HieASTs a
202
+ -> HieAstResult
189
203
-> Position
190
204
-> MaybeT m [Location ]
191
205
gotoDefinition hiedb getHieFile ideOpts imports srcSpans pos
@@ -198,7 +212,7 @@ atPoint
198
212
-> DocAndKindMap
199
213
-> Position
200
214
-> Maybe (Maybe Range , [T. Text ])
201
- atPoint IdeOptions {} (HAR _ hf _ _ kind) (DKMap dm km) pos = listToMaybe $ pointCommand hf pos hoverInfo
215
+ atPoint IdeOptions {} (HAR _ ( hf :: HieASTs a ) _rf _ kind) (DKMap dm km) pos = listToMaybe $ pointCommand hf pos hoverInfo
202
216
where
203
217
-- Hover info for values/data
204
218
hoverInfo ast = (Just range, prettyNames ++ pTypes)
@@ -211,12 +225,21 @@ atPoint IdeOptions{} (HAR _ hf _ _ kind) (DKMap dm km) pos = listToMaybe $ point
211
225
212
226
wrapHaskell x = " \n ```haskell\n " <> x<> " \n ```\n "
213
227
info = nodeInfoH kind ast
214
- names = M. assocs $ nodeIdentifiers info
228
+ names =
229
+ #if MIN_VERSION_ghc(9,0,1)
230
+ sortOn (any isEvidenceUse . identInfo . snd ) $
231
+ #endif
232
+ M. assocs $ nodeIdentifiers info
215
233
types = nodeType info
216
234
217
235
prettyNames :: [T. Text ]
218
236
prettyNames = map prettyName names
219
- prettyName (Right n, dets) = T. unlines $
237
+ prettyName (Right n, dets)
238
+ #if MIN_VERSION_ghc(9,0,1)
239
+ | any isEvidenceUse (identInfo dets) = maybe " " (showSD . renderEvidenceTree) (getEvidenceTree _rf n) <> " \n "
240
+ | otherwise
241
+ #endif
242
+ = T. unlines $
220
243
wrapHaskell (showNameWithoutUniques n <> maybe " " (" :: " <> ) ((prettyType <$> identType dets) <|> maybeKind))
221
244
: definedAt n
222
245
++ catMaybes [ T. unlines . spanDocToMarkdown <$> lookupNameEnv dm n
@@ -225,9 +248,12 @@ atPoint IdeOptions{} (HAR _ hf _ _ kind) (DKMap dm km) pos = listToMaybe $ point
225
248
prettyName (Left m,_) = showGhc m
226
249
227
250
prettyTypes = map ((" _ :: " <> ) . prettyType) types
228
- prettyType t = case kind of
229
- HieFresh -> showGhc t
230
- HieFromDisk full_file -> showGhc $ hieTypeToIface $ recoverFullType t (hie_types full_file)
251
+ prettyType = showSD . expandType
252
+
253
+ expandType :: a -> SDoc
254
+ expandType t = case kind of
255
+ HieFresh -> ppr t
256
+ HieFromDisk full_file -> ppr $ hieTypeToIface $ recoverFullType t (hie_types full_file)
231
257
232
258
definedAt name =
233
259
-- do not show "at <no location info>" and similar messages
@@ -236,6 +262,43 @@ atPoint IdeOptions{} (HAR _ hf _ _ kind) (DKMap dm km) pos = listToMaybe $ point
236
262
UnhelpfulLoc {} | isInternalName name || isSystemName name -> []
237
263
_ -> [" *Defined " <> T. pack (showSDocUnsafe $ pprNameDefnLoc name) <> " *" ]
238
264
265
+ #if MIN_VERSION_ghc(9,0,1)
266
+ -- We want to render the root constraint even if it is a let,
267
+ -- but we don't want to render any subsequent lets
268
+ renderEvidenceTree :: Tree (EvidenceInfo a ) -> SDoc
269
+ -- However, if the root constraint is simply an indirection (via let) to a single other constraint,
270
+ -- we can still skip rendering it
271
+ renderEvidenceTree (T. Node (EvidenceInfo {evidenceDetails= Just (EvLetBind _,_,_)}) [x])
272
+ = renderEvidenceTree x
273
+ renderEvidenceTree (T. Node (EvidenceInfo {evidenceDetails= Just (EvLetBind _,_,_), .. }) xs)
274
+ = hang (text " - Evidence of constraint `" O. <> expandType evidenceType O. <> " `" ) 2 $
275
+ vcat $ text " depending on:" : map renderEvidenceTree' xs
276
+ renderEvidenceTree x = renderEvidenceTree' x
277
+
278
+ -- renderEvidenceTree' skips let bound evidence variables and prints the children directly
279
+ renderEvidenceTree' (T. Node (EvidenceInfo {evidenceDetails= Just (EvLetBind _,_,_)}) xs)
280
+ = vcat (map renderEvidenceTree' xs)
281
+ renderEvidenceTree' (T. Node (EvidenceInfo {.. }) xs)
282
+ = hang (text " - Evidence of constraint `" O. <> expandType evidenceType O. <> " `" ) 2 $
283
+ vcat $ map (text . T. unpack) (definedAt evidenceVar)
284
+ ++ [printDets evidenceSpan evidenceDetails (null xs)]
285
+ ++ map renderEvidenceTree' xs
286
+
287
+ printDets :: RealSrcSpan -> Maybe (EvVarSource , Scope , Maybe Span ) -> Bool -> SDoc
288
+ printDets _ Nothing True = text " "
289
+ printDets _ Nothing False = text " constructed using:"
290
+ printDets ospn (Just (src,_,mspn)) _ = pprSrc
291
+ $$ text " at" <+> ppr spn
292
+ where
293
+ -- Use the bind span if we have one, else use the occurence span
294
+ spn = fromMaybe ospn mspn
295
+ pprSrc = case src of
296
+ -- Users don't know what HsWrappers are
297
+ EvWrapperBind -> " bound by type signature or pattern"
298
+ _ -> ppr src
299
+ #endif
300
+
301
+
239
302
typeLocationsAtPoint
240
303
:: forall m
241
304
. MonadIO m
@@ -251,7 +314,7 @@ typeLocationsAtPoint hiedb lookupModule _ideOptions pos (HAR _ ast _ _ hieKind)
251
314
let arr = hie_types hf
252
315
ts = concat $ pointCommand ast pos getts
253
316
unfold = map (arr A. ! )
254
- getts x = nodeType ni ++ ( mapMaybe identType $ M. elems $ nodeIdentifiers ni)
317
+ getts x = nodeType ni ++ mapMaybe identType ( M. elems $ nodeIdentifiers ni)
255
318
where ni = nodeInfo' x
256
319
getTypes ts = flip concatMap (unfold ts) $ \ case
257
320
HTyVarTy n -> [n]
@@ -270,12 +333,12 @@ typeLocationsAtPoint hiedb lookupModule _ideOptions pos (HAR _ ast _ _ hieKind)
270
333
HQualTy a b -> getTypes [a,b]
271
334
HCastTy a -> getTypes [a]
272
335
_ -> []
273
- in fmap nubOrd $ concatMapM (fmap (fromMaybe [] ) . nameToLocation hiedb lookupModule) (getTypes ts)
336
+ in nubOrd <$> concatMapM (fmap (fromMaybe [] ) . nameToLocation hiedb lookupModule) (getTypes ts)
274
337
HieFresh ->
275
338
let ts = concat $ pointCommand ast pos getts
276
- getts x = nodeType ni ++ ( mapMaybe identType $ M. elems $ nodeIdentifiers ni)
339
+ getts x = nodeType ni ++ mapMaybe identType ( M. elems $ nodeIdentifiers ni)
277
340
where ni = nodeInfo x
278
- in fmap nubOrd $ concatMapM (fmap (fromMaybe [] ) . nameToLocation hiedb lookupModule) (getTypes ts)
341
+ in nubOrd <$> concatMapM (fmap (fromMaybe [] ) . nameToLocation hiedb lookupModule) (getTypes ts)
279
342
280
343
namesInType :: Type -> [Name ]
281
344
namesInType (TyVarTy n) = [Var. varName n]
@@ -288,24 +351,30 @@ namesInType (LitTy _) = []
288
351
namesInType _ = []
289
352
290
353
getTypes :: [Type ] -> [Name ]
291
- getTypes ts = concatMap namesInType ts
354
+ getTypes = concatMap namesInType
292
355
293
356
locationsAtPoint
294
- :: forall m a
357
+ :: forall m
295
358
. MonadIO m
296
359
=> HieDb
297
360
-> LookupModule m
298
361
-> IdeOptions
299
362
-> M. Map ModuleName NormalizedFilePath
300
363
-> Position
301
- -> HieASTs a
364
+ -> HieAstResult
302
365
-> m [Location ]
303
- locationsAtPoint hiedb lookupModule _ideOptions imports pos ast =
366
+ locationsAtPoint hiedb lookupModule _ideOptions imports pos ( HAR _ ast _rm _ _) =
304
367
let ns = concat $ pointCommand ast pos (M. keys . getNodeIds)
368
+ #if MIN_VERSION_ghc(9,0,1)
369
+ evTrees = mapMaybe (either (const Nothing ) $ getEvidenceTree _rm) ns
370
+ evNs = concatMap (map (Right . evidenceVar) . T. flatten) evTrees
371
+ #else
372
+ evNs = []
373
+ #endif
305
374
zeroPos = Position 0 0
306
375
zeroRange = Range zeroPos zeroPos
307
- modToLocation m = fmap (\ fs -> pure $ Location (fromNormalizedUri $ filePathToUri' fs) zeroRange) $ M. lookup m imports
308
- in fmap ( nubOrd . concat ) $ mapMaybeM (either (pure . modToLocation) $ nameToLocation hiedb lookupModule) ns
376
+ modToLocation m = (\ fs -> pure $ Location (fromNormalizedUri $ filePathToUri' fs) zeroRange) <$> M. lookup m imports
377
+ in nubOrd . concat <$> mapMaybeM (either (pure . modToLocation) $ nameToLocation hiedb lookupModule) (ns ++ evNs)
309
378
310
379
-- | Given a 'Name' attempt to find the location where it is defined.
311
380
nameToLocation :: MonadIO m => HieDb -> LookupModule m -> Name -> m (Maybe [Location ])
0 commit comments