@@ -52,11 +52,14 @@ import qualified Data.Text as T
52
52
53
53
import qualified Data.Array as A
54
54
import Data.Either
55
- import Data.List (isSuffixOf )
56
55
import Data.List.Extra (dropEnd1 , nubOrd )
57
56
57
+ import Data.List (isSuffixOf , sortOn )
58
+ import Data.Tree
59
+ import qualified Data.Tree as T
58
60
import Data.Version (showVersion )
59
61
import Development.IDE.Types.Shake (WithHieDb )
62
+ import qualified GHC.Utils.Outputable as O
60
63
import HieDb hiding (pointCommand ,
61
64
withHieDb )
62
65
import System.Directory (doesFileExist )
@@ -198,7 +201,7 @@ gotoDefinition
198
201
-> LookupModule m
199
202
-> IdeOptions
200
203
-> M. Map ModuleName NormalizedFilePath
201
- -> HieASTs a
204
+ -> HieAstResult
202
205
-> Position
203
206
-> MaybeT m [(Location , Identifier )]
204
207
gotoDefinition withHieDb getHieFile ideOpts imports srcSpans pos
@@ -212,7 +215,7 @@ atPoint
212
215
-> HscEnv
213
216
-> Position
214
217
-> IO (Maybe (Maybe Range , [T. Text ]))
215
- atPoint IdeOptions {} (HAR _ hf _ _ (kind :: HieKind hietype )) (DKMap dm km) env pos =
218
+ atPoint IdeOptions {} (HAR _ ( hf :: HieASTs a ) rf _ (kind :: HieKind hietype )) (DKMap dm km) env pos =
216
219
listToMaybe <$> sequence (pointCommand hf pos hoverInfo)
217
220
where
218
221
-- Hover info for values/data
@@ -236,7 +239,7 @@ atPoint IdeOptions{} (HAR _ hf _ _ (kind :: HieKind hietype)) (DKMap dm km) env
236
239
info = nodeInfoH kind ast
237
240
238
241
names :: [(Identifier , IdentifierDetails hietype )]
239
- names = M. assocs $ nodeIdentifiers info
242
+ names = sortOn ( any isEvidenceUse . identInfo . snd ) $ M. assocs $ nodeIdentifiers info
240
243
241
244
-- Check for evidence bindings
242
245
isInternal :: (Identifier , IdentifierDetails a ) -> Bool
@@ -248,11 +251,14 @@ atPoint IdeOptions{} (HAR _ hf _ _ (kind :: HieKind hietype)) (DKMap dm km) env
248
251
filteredNames = filter (not . isInternal) names
249
252
250
253
prettyName :: (Either ModuleName Name , IdentifierDetails hietype ) -> IO T. Text
251
- prettyName (Right n, dets) = pure $ T. unlines $
252
- wrapHaskell (printOutputable n <> maybe " " (" :: " <> ) ((prettyType <$> identType dets) <|> maybeKind))
253
- : maybeToList (pretty (definedAt n) (prettyPackageName n))
254
- ++ catMaybes [ T. unlines . spanDocToMarkdown <$> lookupNameEnv dm n
255
- ]
254
+ prettyName (Right n, dets)
255
+ | any isEvidenceUse (identInfo dets) =
256
+ pure $ maybe " " (printOutputable . renderEvidenceTree) (getEvidenceTree rf n) <> " \n "
257
+ | otherwise = pure $ T. unlines $
258
+ wrapHaskell (printOutputable n <> maybe " " (" :: " <> ) ((prettyType <$> identType dets) <|> maybeKind))
259
+ : maybeToList (pretty (definedAt n) (prettyPackageName n))
260
+ ++ catMaybes [ T. unlines . spanDocToMarkdown <$> lookupNameEnv dm n
261
+ ]
256
262
where maybeKind = fmap printOutputable $ safeTyThingType =<< lookupNameEnv km n
257
263
pretty Nothing Nothing = Nothing
258
264
pretty (Just define) Nothing = Just $ define <> " \n "
@@ -298,6 +304,12 @@ atPoint IdeOptions{} (HAR _ hf _ _ (kind :: HieKind hietype)) (DKMap dm km) env
298
304
prettyType t = case kind of
299
305
HieFresh -> printOutputable t
300
306
HieFromDisk full_file -> printOutputable $ hieTypeToIface $ recoverFullType t (hie_types full_file)
307
+ -- prettyType = printOutputable . expandType
308
+
309
+ expandType :: a -> SDoc
310
+ expandType t = case kind of
311
+ HieFresh -> ppr t
312
+ HieFromDisk full_file -> ppr $ hieTypeToIface $ recoverFullType t (hie_types full_file)
301
313
302
314
definedAt :: Name -> Maybe T. Text
303
315
definedAt name =
@@ -307,6 +319,40 @@ atPoint IdeOptions{} (HAR _ hf _ _ (kind :: HieKind hietype)) (DKMap dm km) env
307
319
UnhelpfulLoc {} | isInternalName name || isSystemName name -> Nothing
308
320
_ -> Just $ " *Defined " <> printOutputable (pprNameDefnLoc name) <> " *"
309
321
322
+ -- We want to render the root constraint even if it is a let,
323
+ -- but we don't want to render any subsequent lets
324
+ renderEvidenceTree :: Tree (EvidenceInfo a ) -> SDoc
325
+ -- However, if the root constraint is simply an indirection (via let) to a single other constraint,
326
+ -- we can still skip rendering it
327
+ renderEvidenceTree (T. Node (EvidenceInfo {evidenceDetails= Just (EvLetBind _,_,_)}) [x])
328
+ = renderEvidenceTree x
329
+ renderEvidenceTree (T. Node (EvidenceInfo {evidenceDetails= Just (EvLetBind _,_,_), .. }) xs)
330
+ = hang (text " - Evidence of constraint `" O. <> expandType evidenceType O. <> " `" ) 2 $
331
+ vcat $ text " depending on:" : map renderEvidenceTree' xs
332
+ renderEvidenceTree x = renderEvidenceTree' x
333
+
334
+ -- renderEvidenceTree' skips let bound evidence variables and prints the children directly
335
+ renderEvidenceTree' (T. Node (EvidenceInfo {evidenceDetails= Just (EvLetBind _,_,_)}) xs)
336
+ = vcat (map renderEvidenceTree' xs)
337
+ renderEvidenceTree' (T. Node (EvidenceInfo {.. }) xs)
338
+ = hang (text " - Evidence of constraint `" O. <> expandType evidenceType O. <> " `" ) 2 $
339
+ vcat $ map (text . T. unpack) (maybeToList $ definedAt evidenceVar)
340
+ ++ [printDets evidenceSpan evidenceDetails (null xs)]
341
+ ++ map renderEvidenceTree' xs
342
+
343
+ printDets :: RealSrcSpan -> Maybe (EvVarSource , Scope , Maybe Span ) -> Bool -> SDoc
344
+ printDets _ Nothing True = text " "
345
+ printDets _ Nothing False = text " constructed using:"
346
+ printDets ospn (Just (src,_,mspn)) _ = pprSrc
347
+ $$ text " at" <+> ppr spn
348
+ where
349
+ -- Use the bind span if we have one, else use the occurence span
350
+ spn = fromMaybe ospn mspn
351
+ pprSrc = case src of
352
+ -- Users don't know what HsWrappers are
353
+ EvWrapperBind -> " bound by type signature or pattern"
354
+ _ -> ppr src
355
+
310
356
-- | Find 'Location's of type definition at a specific point and return them along with their 'Identifier's.
311
357
typeLocationsAtPoint
312
358
:: forall m
@@ -323,7 +369,7 @@ typeLocationsAtPoint withHieDb lookupModule _ideOptions pos (HAR _ ast _ _ hieKi
323
369
let arr = hie_types hf
324
370
ts = concat $ pointCommand ast pos getts
325
371
unfold = map (arr A. ! )
326
- getts x = nodeType ni ++ ( mapMaybe identType $ M. elems $ nodeIdentifiers ni)
372
+ getts x = nodeType ni ++ mapMaybe identType ( M. elems $ nodeIdentifiers ni)
327
373
where ni = nodeInfo' x
328
374
getTypes' ts' = flip concatMap (unfold ts') $ \ case
329
375
HTyVarTy n -> [n]
@@ -337,7 +383,7 @@ typeLocationsAtPoint withHieDb lookupModule _ideOptions pos (HAR _ ast _ _ hieKi
337
383
in fmap nubOrd $ concatMapM (\ n -> fmap (maybe [] (fmap (,Right n))) (nameToLocation withHieDb lookupModule n)) (getTypes' ts)
338
384
HieFresh ->
339
385
let ts = concat $ pointCommand ast pos getts
340
- getts x = nodeType ni ++ ( mapMaybe identType $ M. elems $ nodeIdentifiers ni)
386
+ getts x = nodeType ni ++ mapMaybe identType ( M. elems $ nodeIdentifiers ni)
341
387
where ni = nodeInfo x
342
388
in fmap nubOrd $ concatMapM (\ n -> fmap (maybe [] (fmap (,Right n))) (nameToLocation withHieDb lookupModule n)) (getTypes ts)
343
389
@@ -352,28 +398,48 @@ namesInType (LitTy _) = []
352
398
namesInType _ = []
353
399
354
400
getTypes :: [Type ] -> [Name ]
355
- getTypes ts = concatMap namesInType ts
401
+ getTypes = concatMap namesInType
356
402
357
403
-- | Find 'Location's of definition at a specific point and return them along with their 'Identifier's.
358
404
locationsAtPoint
359
- :: forall m a
405
+ :: forall m
360
406
. MonadIO m
361
407
=> WithHieDb
362
408
-> LookupModule m
363
409
-> IdeOptions
364
410
-> M. Map ModuleName NormalizedFilePath
365
411
-> Position
412
+ <<<<<<< HEAD
366
413
-> HieASTs a
367
414
-> m [(Location , Identifier )]
368
415
locationsAtPoint withHieDb lookupModule _ideOptions imports pos ast =
416
+ ||||||| parent of 86 ebcf859 (Jump to instance definition and explain typeclass evidence)
417
+ -> HieASTs a
418
+ -> m [Location ]
419
+ locationsAtPoint withHieDb lookupModule _ideOptions imports pos ast =
420
+ =======
421
+ -> HieAstResult
422
+ -> m [Location ]
423
+ locationsAtPoint withHieDb lookupModule _ideOptions imports pos (HAR _ ast _rm _ _) =
424
+ >>>>>>> 86 ebcf859 (Jump to instance definition and explain typeclass evidence)
369
425
let ns = concat $ pointCommand ast pos (M. keys . getNodeIds)
426
+ evTrees = mapMaybe (either (const Nothing ) $ getEvidenceTree _rm) ns
427
+ evNs = concatMap (map (Right . evidenceVar) . T. flatten) evTrees
370
428
zeroPos = Position 0 0
371
429
zeroRange = Range zeroPos zeroPos
430
+ <<<<<<< HEAD
372
431
modToLocation m = fmap (\ fs -> pure (Location (fromNormalizedUri $ filePathToUri' fs) zeroRange)) $ M. lookup m imports
373
432
in fmap (nubOrd . concat ) $ mapMaybeM
374
433
(either (\ m -> pure ((fmap $ fmap (,Left m)) (modToLocation m)))
375
434
(\ n -> fmap (fmap $ fmap (,Right n)) (nameToLocation withHieDb lookupModule n)))
376
435
ns
436
+ ||||||| parent of 86 ebcf859 (Jump to instance definition and explain typeclass evidence)
437
+ modToLocation m = fmap (\ fs -> pure $ Location (fromNormalizedUri $ filePathToUri' fs) zeroRange) $ M. lookup m imports
438
+ in fmap (nubOrd . concat ) $ mapMaybeM (either (pure . modToLocation) $ nameToLocation withHieDb lookupModule) ns
439
+ =======
440
+ modToLocation m = (\ fs -> pure $ Location (fromNormalizedUri $ filePathToUri' fs) zeroRange) <$> M. lookup m imports
441
+ in nubOrd . concat <$> mapMaybeM (either (pure . modToLocation) $ nameToLocation withHieDb lookupModule) (ns ++ evNs)
442
+ >>>>>>> 86 ebcf859 (Jump to instance definition and explain typeclass evidence)
377
443
378
444
-- | Given a 'Name' attempt to find the location where it is defined.
379
445
nameToLocation :: MonadIO m => WithHieDb -> LookupModule m -> Name -> m (Maybe [Location ])
0 commit comments