3
3
{-# LANGUAGE ScopedTypeVariables #-}
4
4
{-# LANGUAGE OverloadedStrings #-}
5
5
{-# LANGUAGE TypeFamilies #-}
6
+ {-# LANGUAGE LambdaCase #-}
6
7
module Haskell.Ide.Engine.Plugin.HieExtras
7
8
( getDynFlags
8
9
, WithSnippets (.. )
@@ -29,6 +30,7 @@ import Control.Lens.Prism ( _Just )
29
30
import Control.Lens.Setter ((%~) )
30
31
import Control.Lens.Traversal (traverseOf )
31
32
import Control.Monad.Reader
33
+ import Control.Monad.Trans.Maybe
32
34
import Data.Aeson
33
35
import qualified Data.Aeson.Types as J
34
36
import Data.Char
@@ -478,6 +480,9 @@ getTypeForName n = do
478
480
getSymbolsAtPoint :: Position -> CachedInfo -> [(Range ,Name )]
479
481
getSymbolsAtPoint pos info = maybe [] (`getArtifactsAtPos` locMap info) $ newPosToOld info pos
480
482
483
+ -- | Get a symbol from the given location map at the given location.
484
+ -- Retrieves the name and range of the symbol at the given location
485
+ -- from the cached location map.
481
486
symbolFromTypecheckedModule
482
487
:: LocMap
483
488
-> Position
@@ -540,6 +545,12 @@ getModule df n = do
540
545
541
546
-- ---------------------------------------------------------------------
542
547
-- TODO: there has to be a simpler way, using the appropriate GHC internals
548
+ -- | Find the Id for a given Name.
549
+ -- Requires an already TypecheckedModule.
550
+ -- A TypecheckedModule can be obtained by using the functions
551
+ -- @ifCachedModuleAndData@ or @withCachedModuleAndData@.
552
+ --
553
+ -- Function is copied from @HaRe/src/Language/Haskell/Refact/Utils/TypeUtils.hs:2954@.
543
554
findIdForName :: TypecheckedModule -> Name -> IdeM (Maybe Id )
544
555
findIdForName tm n = do
545
556
let t = GHC. tm_typechecked_source tm
@@ -550,60 +561,80 @@ findIdForName tm n = do
550
561
551
562
-- ---------------------------------------------------------------------
552
563
564
+ -- | Get the type for a name.
565
+ -- Requires an already TypecheckedModule.
566
+ -- A TypecheckedModule can be obtained by using the functions
567
+ -- @ifCachedModuleAndData@ or @withCachedModuleAndData@.
568
+ --
569
+ -- Returns the type of a variable or a sum type constructor.
570
+ --
571
+ -- Function is taken from @HaRe/src/Language/Haskell/Refact/Utils/TypeUtils.hs:2966@.
553
572
getTypeForName' :: TypecheckedModule -> Name -> IdeM (Maybe Type )
554
573
getTypeForName' tm n = do
555
574
mId <- findIdForName tm n
556
575
case mId of
557
576
Nothing -> getTypeForName n
558
577
Just i -> return $ Just (varType i)
559
578
560
- -- | Return the type definition
579
+ -- | Return the type definition of the symbol at the given position.
580
+ -- Works for Datatypes, Newtypes and Type Definitions.
581
+ -- The latter is only possible, if the type that is defined is defined in the project.
582
+ -- Sum Types can also be searched.
561
583
findTypeDef :: Uri -> Position -> IdeDeferM (IdeResult [Location ])
562
584
findTypeDef uri pos = pluginGetFile " findTypeDef: " uri $ \ file ->
563
- ifCachedModuleAndData
564
- file
565
- (IdeResultOk [] )
585
+ ifCachedModuleAndData -- Dont wait on this function if the module is not cached.
586
+ file
587
+ (IdeResultOk [] ) -- Default result
566
588
(\ tm info NMD {} -> do
567
589
let rfm = revMap info
568
590
lm = locMap info
569
591
mm = moduleMap info
570
592
oldPos = newPosToOld info pos
571
593
case (\ x -> Just $ getArtifactsAtPos x mm) =<< oldPos of
572
594
Just ((_, mn) : _) -> gotoModule rfm mn
573
- _ -> case symbolFromTypecheckedModule lm =<< oldPos of
574
- Nothing -> return $ IdeResultOk []
575
- Just (_, n) -> do
576
- mayType <- lift $ getTypeForName' tm n
577
- case mayType of
578
- Nothing ->
579
- return $ IdeResultOk []
580
- Just t -> case tyConAppTyCon_maybe t of
581
- Nothing ->
582
- return $ IdeResultOk []
583
- Just tyCon ->
584
- case nameSrcSpan (getName tyCon) of
585
- UnhelpfulSpan _ -> return $ IdeResultOk []
586
- realSpan -> do
587
- res <- srcSpan2Loc rfm realSpan
588
- case res of
589
- Right l@ (J. Location luri range) -> case uriToFilePath luri of
590
- Nothing -> return $ IdeResultOk [l]
591
- Just fp ->
592
- ifCachedModule fp (IdeResultOk [l])
593
- $ \ (_ :: ParsedModule ) info' ->
594
- case oldRangeToNew info' range of
595
- Just r ->
596
- return $ IdeResultOk [J. Location luri r]
597
- Nothing -> return $ IdeResultOk [l]
598
- Left x -> do
599
- debugm " findTypeDef: name srcspan not found/valid"
600
- pure
601
- (IdeResultFail
602
- (IdeError PluginError
603
- (" hare:findTypeDef" <> " : \" " <> x <> " \" " )
604
- Null
605
- )
606
- )
595
+ _ -> do
596
+ let
597
+ -- | Get SrcSpan of the name at the given position.
598
+ -- If the old position is Nothing, e.g. there is no cached info about it,
599
+ -- Nothing is returned.
600
+ --
601
+ -- Otherwise, searches for the Type of the given position
602
+ -- and retrieves its SrcSpan.
603
+ getSrcSpanFromPosition :: Maybe Position -> MaybeT IdeDeferM SrcSpan
604
+ getSrcSpanFromPosition oldPosition = do
605
+ (_, n) <- MaybeT $ return $ symbolFromTypecheckedModule lm =<< oldPosition
606
+ t <- MaybeT $ lift $ getTypeForName' tm n
607
+ tyCon <- MaybeT $ return $ tyConAppTyCon_maybe t
608
+ case nameSrcSpan (getName tyCon) of
609
+ UnhelpfulSpan _ -> fail " Unhelpful Span" -- this message is never shown
610
+ realSpan -> return realSpan
611
+
612
+ runMaybeT (getSrcSpanFromPosition oldPos) >>= \ case
613
+ Nothing -> return $ IdeResultOk []
614
+ Just realSpan -> do
615
+ -- Since we found a real SrcSpan, we now translate it
616
+ -- to the position in the file
617
+ res <- srcSpan2Loc rfm realSpan
618
+ case res of
619
+ Right l@ (J. Location luri range) -> case uriToFilePath luri of
620
+ Nothing -> return $ IdeResultOk [l]
621
+ Just fp ->
622
+ ifCachedModule fp (IdeResultOk [l])
623
+ $ \ (_ :: ParsedModule ) info' ->
624
+ case oldRangeToNew info' range of
625
+ Just r ->
626
+ return $ IdeResultOk [J. Location luri r]
627
+ Nothing -> return $ IdeResultOk [l]
628
+ Left x -> do
629
+ -- SrcSpan does not have a file location!
630
+ debugm " findTypeDef: name srcspan not found/valid"
631
+ pure
632
+ (IdeResultFail
633
+ (IdeError PluginError
634
+ (" hare:findTypeDef" <> " : \" " <> x <> " \" " )
635
+ Null
636
+ )
637
+ )
607
638
)
608
639
609
640
-- | Return the definition
0 commit comments