/src/Haskell/Ide/Engine/Support/FromHaRe.hs
https://github.com/haskell/haskell-ide-engine · Haskell · 221 lines · 142 code · 43 blank · 36 comment · 6 complexity · 49041e5c436bef1be4b3bb2d22f22b8f MD5 · raw file
- {-# LANGUAGE ScopedTypeVariables #-}
- {-# LANGUAGE CPP #-}
- module Haskell.Ide.Engine.Support.FromHaRe
- (
- initRdrNameMap
- , NameMap
- , hsNamessRdr
- ) where
- -- Code migrated from HaRe, until HaRe comes back
- -- import Control.Monad.State
- import Data.List
- import Data.Maybe
- import qualified GHC as GHC
- -- import qualified GhcMonad as GHC
- -- import qualified Haskell.Ide.Engine.PluginApi as HIE (makeRevRedirMapFunc)
- import qualified Module as GHC
- import qualified Name as GHC
- import qualified Unique as GHC
- -- import qualified HscTypes as GHC (md_exports)
- -- import qualified TcRnTypes as GHC (tcg_rdr_env)
- #if __GLASGOW_HASKELL__ > 710
- import qualified Var
- #endif
- import qualified Data.Generics as SYB
- -- import Language.Haskell.GHC.ExactPrint
- -- import Language.Haskell.GHC.ExactPrint.Annotate
- -- import Language.Haskell.GHC.ExactPrint.Parsers
- import Language.Haskell.GHC.ExactPrint.Utils
- import Language.Haskell.GHC.ExactPrint.Types
- -- import Language.Haskell.Refact.Utils.Monad
- -- import Language.Haskell.Refact.Utils.TypeSyn
- -- import Language.Haskell.Refact.Utils.Types
- import qualified Data.Map as Map
- -- import Outputable
- -- ---------------------------------------------------------------------
- type NameMap = Map.Map GHC.SrcSpan GHC.Name
- -- ---------------------------------------------------------------------
- -- |We need the ParsedSource because it more closely reflects the actual source
- -- code, but must be able to work with the renamed representation of the names
- -- involved. This function constructs a map from every Located RdrName in the
- -- ParsedSource to its corresponding name in the RenamedSource. It also deals
- -- with the wrinkle that we need to Location of the RdrName to make sure we have
- -- the right Name, but not all RdrNames have a Location.
- -- This function is called before the RefactGhc monad is active.
- initRdrNameMap :: GHC.TypecheckedModule -> NameMap
- initRdrNameMap tm = r
- where
- parsed = GHC.pm_parsed_source $ GHC.tm_parsed_module tm
- renamed = GHC.tm_renamed_source tm
- #if __GLASGOW_HASKELL__ > 710
- typechecked = GHC.tm_typechecked_source tm
- #endif
- checkRdr :: GHC.Located GHC.RdrName -> Maybe [(GHC.SrcSpan,GHC.RdrName)]
- checkRdr (GHC.L l n@(GHC.Unqual _)) = Just [(l,n)]
- checkRdr (GHC.L l n@(GHC.Qual _ _)) = Just [(l,n)]
- checkRdr (GHC.L _ _)= Nothing
- checkName :: GHC.Located GHC.Name -> Maybe [GHC.Located GHC.Name]
- checkName ln = Just [ln]
- rdrNames = gfromJust "initRdrNameMap" $ SYB.everything mappend (nameSybQuery checkRdr ) parsed
- #if __GLASGOW_HASKELL__ >= 806
- names1 = gfromJust "initRdrNameMap" $ SYB.everything mappend (nameSybQuery checkName) renamed
- names2 = names1 ++ SYB.everything (++) ([] `SYB.mkQ` fieldOcc
- `SYB.extQ` hsRecFieldN) renamed
- names = names2 ++ SYB.everything (++) ([] `SYB.mkQ` hsRecFieldT) typechecked
- fieldOcc :: GHC.FieldOcc GhcRn -> [GHC.Located GHC.Name]
- fieldOcc (GHC.FieldOcc n (GHC.L l _)) = [(GHC.L l n)]
- fieldOcc (GHC.XFieldOcc _) = []
- hsRecFieldN :: GHC.LHsExpr GhcRn -> [GHC.Located GHC.Name]
- hsRecFieldN (GHC.L _ (GHC.HsRecFld _ (GHC.Unambiguous n (GHC.L l _) ) )) = [GHC.L l n]
- hsRecFieldN _ = []
- hsRecFieldT :: GHC.LHsExpr GhcTc -> [GHC.Located GHC.Name]
- hsRecFieldT (GHC.L _ (GHC.HsRecFld _ (GHC.Ambiguous n (GHC.L l _)) )) = [GHC.L l (Var.varName n)]
- hsRecFieldT _ = []
- #elif __GLASGOW_HASKELL__ > 710
- names1 = gfromJust "initRdrNameMap" $ SYB.everything mappend (nameSybQuery checkName) renamed
- names2 = names1 ++ SYB.everything (++) ([] `SYB.mkQ` fieldOcc
- `SYB.extQ` hsRecFieldN) renamed
- names = names2 ++ SYB.everything (++) ([] `SYB.mkQ` hsRecFieldT) typechecked
- fieldOcc :: GHC.FieldOcc GhcRn -> [GHC.Located GHC.Name]
- fieldOcc (GHC.FieldOcc (GHC.L l _) n) = [(GHC.L l n)]
- hsRecFieldN :: GHC.LHsExpr GhcRn -> [GHC.Located GHC.Name]
- hsRecFieldN (GHC.L _ (GHC.HsRecFld (GHC.Unambiguous (GHC.L l _) n) )) = [GHC.L l n]
- hsRecFieldN _ = []
- hsRecFieldT :: GHC.LHsExpr GhcTc -> [GHC.Located GHC.Name]
- hsRecFieldT (GHC.L _ (GHC.HsRecFld (GHC.Ambiguous (GHC.L l _) n) )) = [GHC.L l (Var.varName n)]
- hsRecFieldT _ = []
- #else
- names = gfromJust "initRdrNameMap" $ SYB.everything mappend (nameSybQuery checkName) renamed
- #endif
- #if __GLASGOW_HASKELL__ >= 806
- namesIe = names
- #elif (defined(MIN_VERSION_GLASGOW_HASKELL) && (MIN_VERSION_GLASGOW_HASKELL(8,2,1,0)))
- -- This is a workaround for https://ghc.haskell.org/trac/ghc/ticket/14189
- -- namesIeParsedL = SYB.everything (++) ([] `SYB.mkQ` ieThingWith) (GHC.hsmodExports $ GHC.unLoc parsed)
- namesIeParsed = Map.fromList $ SYB.everything (++) ([] `SYB.mkQ` ieThingWith) (GHC.hsmodExports $ GHC.unLoc parsed)
- ieThingWith :: GHC.IE GhcPs -> [(GHC.SrcSpan, [GHC.SrcSpan])]
- ieThingWith (GHC.IEThingWith l _ sub_rdrs _) = [(GHC.getLoc l,map GHC.getLoc sub_rdrs)]
- ieThingWith _ = []
- renamedExports = case renamed of
- Nothing -> Nothing
- Just (_,_,es,_) -> es
- namesIeRenamed = SYB.everything (++) ([] `SYB.mkQ` ieThingWithNames) renamedExports
- ieThingWithNames :: GHC.IE GhcRn -> [GHC.Located GHC.Name]
- ieThingWithNames (GHC.IEThingWith l _ sub_rdrs _) = (GHC.ieLWrappedName l:nameSubs)
- where
- rdrSubLocs = gfromJust "ieThingWithNames" $ Map.lookup (GHC.getLoc l) namesIeParsed
- nameSubs = map (\(loc,GHC.L _ lwn) -> GHC.L loc (GHC.ieWrappedName lwn)) $ zip rdrSubLocs sub_rdrs
- ieThingWithNames _ = []
- namesIe = case SYB.everything mappend (nameSybQuery checkName) namesIeRenamed of
- Nothing -> names
- Just ns -> names ++ ns
- #else
- namesIe = names
- #endif
- nameMap = Map.fromList $ map (\(GHC.L l n) -> (l,n)) namesIe
- -- If the name does not exist (e.g. a TH Splice that has been expanded, make a new one)
- -- No attempt is made to make sure that equivalent ones have equivalent names.
- lookupName l n i = case Map.lookup l nameMap of
- Just v -> v
- Nothing -> case n of
- GHC.Unqual u -> mkNewGhcNamePure 'h' i Nothing (GHC.occNameString u)
- #if __GLASGOW_HASKELL__ <= 710
- GHC.Qual q u -> mkNewGhcNamePure 'h' i (Just (GHC.Module (GHC.stringToPackageKey "") q)) (GHC.occNameString u)
- #else
- GHC.Qual q u -> mkNewGhcNamePure 'h' i (Just (GHC.Module (GHC.stringToUnitId "") q)) (GHC.occNameString u)
- #endif
- _ -> error "initRdrNameMap:should not happen"
- r = Map.fromList $ map (\((l,n),i) -> (l,lookupName l n i)) $ zip rdrNames [1..]
- -- ---------------------------------------------------------------------
- nameSybQuery :: (SYB.Typeable a, SYB.Typeable t)
- => (GHC.Located a -> Maybe r) -> t -> Maybe r
- nameSybQuery checker = q
- where
- q = Nothing `SYB.mkQ` worker
- #if __GLASGOW_HASKELL__ <= 710
- `SYB.extQ` workerBind
- `SYB.extQ` workerExpr
- `SYB.extQ` workerHsTyVarBndr
- `SYB.extQ` workerLHsType
- #endif
- worker (pnt :: (GHC.Located a))
- = checker pnt
- #if __GLASGOW_HASKELL__ <= 710
- workerBind (GHC.L l (GHC.VarPat name))
- = checker (GHC.L l name)
- workerBind _ = Nothing
- workerExpr ((GHC.L l (GHC.HsVar name)))
- = checker (GHC.L l name)
- workerExpr _ = Nothing
- -- workerLIE ((GHC.L _l (GHC.IEVar (GHC.L ln name))) :: (GHC.LIE a))
- -- = checker (GHC.L ln name)
- -- workerLIE _ = Nothing
- workerHsTyVarBndr ((GHC.L l (GHC.UserTyVar name)))
- = checker (GHC.L l name)
- workerHsTyVarBndr _ = Nothing
- workerLHsType ((GHC.L l (GHC.HsTyVar name)))
- = checker (GHC.L l name)
- workerLHsType _ = Nothing
- #endif
- -- ---------------------------------------------------------------------
- mkNewGhcNamePure :: Char -> Int -> Maybe GHC.Module -> String -> GHC.Name
- mkNewGhcNamePure c i maybeMod name =
- let un = GHC.mkUnique c i -- H for HaRe :)
- n = case maybeMod of
- Nothing -> GHC.mkInternalName un (GHC.mkVarOcc name) GHC.noSrcSpan
- Just modu -> GHC.mkExternalName un modu (GHC.mkVarOcc name) GHC.noSrcSpan
- in n
- -- ---------------------------------------------------------------------
- -- |Get all the names in the given syntax element
- hsNamessRdr :: (SYB.Data t) => t -> [GHC.Located GHC.RdrName]
- hsNamessRdr t = nub $ fromMaybe [] r
- where
- r = (SYB.everything mappend (inName) t)
- checker :: GHC.Located GHC.RdrName -> Maybe [GHC.Located GHC.RdrName]
- checker x = Just [x]
- inName :: (SYB.Typeable a) => a -> Maybe [GHC.Located GHC.RdrName]
- inName = nameSybQuery checker
- -- ---------------------------------------------------------------------