PageRenderTime 46ms CodeModel.GetById 10ms RepoModel.GetById 1ms app.codeStats 0ms

/Language/Haskell/GhcMod/Gap.hs

https://github.com/kazu-yamamoto/ghc-mod
Haskell | 566 lines | 453 code | 74 blank | 39 comment | 2 complexity | f46365caade261cbd033ec668ab005bf MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause
  1. {-# LANGUAGE TypeSynonymInstances, FlexibleInstances, CPP, ScopedTypeVariables, RankNTypes #-}
  2. module Language.Haskell.GhcMod.Gap (
  3. Language.Haskell.GhcMod.Gap.ClsInst
  4. , mkTarget
  5. , withStyle
  6. , GmLogAction
  7. , setLogAction
  8. , getSrcSpan
  9. , getSrcFile
  10. , withInteractiveContext
  11. , fOptions
  12. , toStringBuffer
  13. , showSeverityCaption
  14. , setCabalPkg
  15. , setHideAllPackages
  16. , setDeferTypeErrors
  17. , setDeferTypedHoles
  18. , setWarnTypedHoles
  19. , setDumpSplices
  20. , isDumpSplices
  21. , filterOutChildren
  22. , infoThing
  23. , pprInfo
  24. , HasType(..)
  25. , errorMsgSpan
  26. , typeForUser
  27. , nameForUser
  28. , occNameForUser
  29. , deSugar
  30. , showDocWith
  31. , GapThing(..)
  32. , fromTyThing
  33. , fileModSummary
  34. , WarnFlags
  35. , emptyWarnFlags
  36. , GLMatch
  37. , GLMatchI
  38. , getClass
  39. , occName
  40. , listVisibleModuleNames
  41. , listVisibleModules
  42. , lookupModulePackageInAllPackages
  43. , Language.Haskell.GhcMod.Gap.isSynTyCon
  44. , parseModuleHeader
  45. , mkErrStyle'
  46. ) where
  47. import Control.Applicative hiding (empty)
  48. import Control.Monad (filterM)
  49. import CoreSyn (CoreExpr)
  50. import Data.List (intersperse)
  51. import Data.Maybe (catMaybes)
  52. import Data.Time.Clock (UTCTime)
  53. import Data.Traversable hiding (mapM)
  54. import DataCon (dataConRepType)
  55. import Desugar (deSugarExpr)
  56. import DynFlags
  57. import ErrUtils
  58. import Exception
  59. import FastString
  60. import GhcMonad
  61. import HscTypes
  62. import NameSet
  63. import OccName
  64. import Outputable
  65. import PprTyThing
  66. import StringBuffer
  67. import TcType
  68. import Var (varType)
  69. import System.Directory
  70. import qualified Name
  71. import qualified InstEnv
  72. import qualified Pretty
  73. import qualified StringBuffer as SB
  74. #if __GLASGOW_HASKELL__ >= 708
  75. import FamInstEnv
  76. import ConLike (ConLike(..))
  77. import PatSyn (patSynType)
  78. #else
  79. import TcRnTypes
  80. #endif
  81. #if __GLASGOW_HASKELL__ >= 706
  82. import GHC hiding (ClsInst)
  83. #else
  84. import GHC hiding (Instance)
  85. import Control.Arrow hiding ((<+>))
  86. import Data.Convertible
  87. import RdrName (rdrNameOcc)
  88. #endif
  89. #if __GLASGOW_HASKELL__ < 710
  90. import UniqFM (eltsUFM)
  91. import Module
  92. #endif
  93. #if __GLASGOW_HASKELL__ >= 704
  94. import qualified Data.IntSet as I (IntSet, empty)
  95. #endif
  96. import Bag
  97. import Lexer as L
  98. import Parser
  99. import SrcLoc
  100. import Packages
  101. import Language.Haskell.GhcMod.Types (Expression(..))
  102. import Prelude
  103. ----------------------------------------------------------------
  104. ----------------------------------------------------------------
  105. --
  106. #if __GLASGOW_HASKELL__ >= 706
  107. type ClsInst = InstEnv.ClsInst
  108. #else
  109. type ClsInst = InstEnv.Instance
  110. #endif
  111. mkTarget :: TargetId -> Bool -> Maybe (SB.StringBuffer, UTCTime) -> Target
  112. #if __GLASGOW_HASKELL__ >= 706
  113. mkTarget = Target
  114. #else
  115. mkTarget tid allowObjCode = Target tid allowObjCode . (fmap . second) convert
  116. #endif
  117. ----------------------------------------------------------------
  118. ----------------------------------------------------------------
  119. withStyle :: DynFlags -> PprStyle -> SDoc -> Pretty.Doc
  120. #if __GLASGOW_HASKELL__ >= 706
  121. withStyle = withPprStyleDoc
  122. #else
  123. withStyle _ = withPprStyleDoc
  124. #endif
  125. #if __GLASGOW_HASKELL__ >= 706
  126. type GmLogAction = LogAction
  127. #else
  128. type GmLogAction = DynFlags -> LogAction
  129. #endif
  130. setLogAction :: DynFlags -> GmLogAction -> DynFlags
  131. setLogAction df f =
  132. #if __GLASGOW_HASKELL__ >= 706
  133. df { log_action = f }
  134. #else
  135. df { log_action = f df }
  136. #endif
  137. showDocWith :: DynFlags -> Pretty.Mode -> Pretty.Doc -> String
  138. #if __GLASGOW_HASKELL__ >= 708
  139. -- Pretty.showDocWith disappeard.
  140. -- https://github.com/ghc/ghc/commit/08a3536e4246e323fbcd8040e0b80001950fe9bc
  141. showDocWith dflags mode = Pretty.showDoc mode (pprCols dflags)
  142. #else
  143. showDocWith _ = Pretty.showDocWith
  144. #endif
  145. ----------------------------------------------------------------
  146. ----------------------------------------------------------------
  147. getSrcSpan :: SrcSpan -> Maybe (Int,Int,Int,Int)
  148. #if __GLASGOW_HASKELL__ >= 702
  149. getSrcSpan (RealSrcSpan spn)
  150. #else
  151. getSrcSpan spn | isGoodSrcSpan spn
  152. #endif
  153. = Just (srcSpanStartLine spn
  154. , srcSpanStartCol spn
  155. , srcSpanEndLine spn
  156. , srcSpanEndCol spn)
  157. getSrcSpan _ = Nothing
  158. getSrcFile :: SrcSpan -> Maybe String
  159. #if __GLASGOW_HASKELL__ >= 702
  160. getSrcFile (RealSrcSpan spn) = Just . unpackFS . srcSpanFile $ spn
  161. #else
  162. getSrcFile spn | isGoodSrcSpan spn = Just . unpackFS . srcSpanFile $ spn
  163. #endif
  164. getSrcFile _ = Nothing
  165. ----------------------------------------------------------------
  166. toStringBuffer :: GhcMonad m => [String] -> m StringBuffer
  167. #if __GLASGOW_HASKELL__ >= 702
  168. toStringBuffer = return . stringToStringBuffer . unlines
  169. #else
  170. toStringBuffer = liftIO . stringToStringBuffer . unlines
  171. #endif
  172. ----------------------------------------------------------------
  173. fOptions :: [String]
  174. #if __GLASGOW_HASKELL__ >= 710
  175. fOptions = [option | (FlagSpec option _ _ _) <- fFlags]
  176. ++ [option | (FlagSpec option _ _ _) <- fWarningFlags]
  177. ++ [option | (FlagSpec option _ _ _) <- fLangFlags]
  178. #elif __GLASGOW_HASKELL__ >= 704
  179. fOptions = [option | (option,_,_) <- fFlags]
  180. ++ [option | (option,_,_) <- fWarningFlags]
  181. ++ [option | (option,_,_) <- fLangFlags]
  182. #else
  183. fOptions = [option | (option,_,_,_) <- fFlags]
  184. ++ [option | (option,_,_,_) <- fWarningFlags]
  185. ++ [option | (option,_,_,_) <- fLangFlags]
  186. #endif
  187. ----------------------------------------------------------------
  188. ----------------------------------------------------------------
  189. fileModSummary :: GhcMonad m => FilePath -> m ModSummary
  190. fileModSummary file' = do
  191. mss <- getModuleGraph
  192. file <- liftIO $ canonicalizePath file'
  193. [ms] <- liftIO $ flip filterM mss $ \m ->
  194. (Just file==) <$> canonicalizePath `traverse` ml_hs_file (ms_location m)
  195. return ms
  196. withInteractiveContext :: GhcMonad m => m a -> m a
  197. withInteractiveContext action = gbracket setup teardown body
  198. where
  199. setup = getContext
  200. teardown = setCtx
  201. body _ = do
  202. topImports >>= setCtx
  203. action
  204. topImports = do
  205. ms <- filterM moduleIsInterpreted =<< map ms_mod <$> getModuleGraph
  206. let iis = map (IIModule . modName) ms
  207. #if __GLASGOW_HASKELL__ >= 704
  208. return iis
  209. #else
  210. return (iis,[])
  211. #endif
  212. #if __GLASGOW_HASKELL__ >= 706
  213. modName = moduleName
  214. setCtx = setContext
  215. #elif __GLASGOW_HASKELL__ >= 704
  216. modName = id
  217. setCtx = setContext
  218. #else
  219. modName = ms_mod
  220. setCtx = uncurry setContext
  221. #endif
  222. showSeverityCaption :: Severity -> String
  223. #if __GLASGOW_HASKELL__ >= 706
  224. showSeverityCaption SevWarning = "Warning: "
  225. showSeverityCaption _ = ""
  226. #else
  227. showSeverityCaption = const ""
  228. #endif
  229. ----------------------------------------------------------------
  230. ----------------------------------------------------------------
  231. setCabalPkg :: DynFlags -> DynFlags
  232. #if __GLASGOW_HASKELL__ >= 708
  233. setCabalPkg dflag = gopt_set dflag Opt_BuildingCabalPackage
  234. #else
  235. setCabalPkg dflag = dopt_set dflag Opt_BuildingCabalPackage
  236. #endif
  237. ----------------------------------------------------------------
  238. setHideAllPackages :: DynFlags -> DynFlags
  239. #if __GLASGOW_HASKELL__ >= 708
  240. setHideAllPackages df = gopt_set df Opt_HideAllPackages
  241. #else
  242. setHideAllPackages df = dopt_set df Opt_HideAllPackages
  243. #endif
  244. ----------------------------------------------------------------
  245. setDumpSplices :: DynFlags -> DynFlags
  246. setDumpSplices dflag = dopt_set dflag Opt_D_dump_splices
  247. isDumpSplices :: DynFlags -> Bool
  248. isDumpSplices dflag = dopt Opt_D_dump_splices dflag
  249. ----------------------------------------------------------------
  250. setDeferTypeErrors :: DynFlags -> DynFlags
  251. #if __GLASGOW_HASKELL__ >= 708
  252. setDeferTypeErrors dflag = gopt_set dflag Opt_DeferTypeErrors
  253. #elif __GLASGOW_HASKELL__ >= 706
  254. setDeferTypeErrors dflag = dopt_set dflag Opt_DeferTypeErrors
  255. #else
  256. setDeferTypeErrors = id
  257. #endif
  258. setDeferTypedHoles :: DynFlags -> DynFlags
  259. #if __GLASGOW_HASKELL__ >= 710
  260. setDeferTypedHoles dflag = gopt_set dflag Opt_DeferTypedHoles
  261. #else
  262. setDeferTypedHoles = id
  263. #endif
  264. setWarnTypedHoles :: DynFlags -> DynFlags
  265. #if __GLASGOW_HASKELL__ >= 708
  266. setWarnTypedHoles dflag = wopt_set dflag Opt_WarnTypedHoles
  267. #else
  268. setWarnTypedHoles = id
  269. #endif
  270. ----------------------------------------------------------------
  271. ----------------------------------------------------------------
  272. class HasType a where
  273. getType :: GhcMonad m => TypecheckedModule -> a -> m (Maybe (SrcSpan, Type))
  274. instance HasType (LHsBind Id) where
  275. #if __GLASGOW_HASKELL__ >= 708
  276. getType _ (L spn FunBind{fun_matches = m}) = return $ Just (spn, typ)
  277. where in_tys = mg_arg_tys m
  278. out_typ = mg_res_ty m
  279. typ = mkFunTys in_tys out_typ
  280. #else
  281. getType _ (L spn FunBind{fun_matches = MatchGroup _ typ}) = return $ Just (spn, typ)
  282. #endif
  283. getType _ _ = return Nothing
  284. ----------------------------------------------------------------
  285. ----------------------------------------------------------------
  286. -- from ghc/InteractiveUI.hs
  287. filterOutChildren :: (a -> TyThing) -> [a] -> [a]
  288. filterOutChildren get_thing xs
  289. = [x | x <- xs, not (getName (get_thing x) `elemNameSet` implicits)]
  290. where
  291. implicits = mkNameSet [getName t | x <- xs, t <- implicitTyThings (get_thing x)]
  292. infoThing :: GhcMonad m => (FilePath -> FilePath) -> Expression -> m SDoc
  293. infoThing m (Expression str) = do
  294. names <- parseName str
  295. #if __GLASGOW_HASKELL__ >= 708
  296. mb_stuffs <- mapM (getInfo False) names
  297. let filtered = filterOutChildren (\(t,_f,_i,_fam) -> t) (catMaybes mb_stuffs)
  298. #else
  299. mb_stuffs <- mapM getInfo names
  300. let filtered = filterOutChildren (\(t,_f,_i) -> t) (catMaybes mb_stuffs)
  301. #endif
  302. return $ vcat (intersperse (text "") $ map (pprInfo m False) filtered)
  303. #if __GLASGOW_HASKELL__ >= 708
  304. pprInfo :: (FilePath -> FilePath) -> Bool -> (TyThing, GHC.Fixity, [ClsInst], [FamInst]) -> SDoc
  305. pprInfo m _ (thing, fixity, insts, famInsts)
  306. = pprTyThingInContextLoc' thing
  307. $$ show_fixity fixity
  308. $$ InstEnv.pprInstances insts
  309. $$ pprFamInsts famInsts
  310. #else
  311. pprInfo :: (FilePath -> FilePath) -> PrintExplicitForalls -> (TyThing, GHC.Fixity, [ClsInst]) -> SDoc
  312. pprInfo m pefas (thing, fixity, insts)
  313. = pprTyThingInContextLoc' pefas thing
  314. $$ show_fixity fixity
  315. $$ vcat (map pprInstance insts)
  316. #endif
  317. where
  318. show_fixity fx
  319. | fx == defaultFixity = Outputable.empty
  320. | otherwise = ppr fx <+> ppr (getName thing)
  321. #if __GLASGOW_HASKELL__ >= 708
  322. pprTyThingInContextLoc' thing' = hang (pprTyThingInContext thing') 2
  323. (char '\t' <> ptext (sLit "--") <+> loc)
  324. where loc = ptext (sLit "Defined") <+> pprNameDefnLoc' (getName thing')
  325. #else
  326. pprTyThingInContextLoc' pefas thing' = hang (pprTyThingInContext pefas thing') 2
  327. (char '\t' <> ptext (sLit "--") <+> loc)
  328. where loc = ptext (sLit "Defined") <+> pprNameDefnLoc' (getName thing')
  329. #endif
  330. pprNameDefnLoc' name
  331. = case Name.nameSrcLoc name of
  332. RealSrcLoc s -> ptext (sLit "at") <+> ppr (subst s)
  333. UnhelpfulLoc s
  334. | Name.isInternalName name || Name.isSystemName name
  335. -> ptext (sLit "at") <+> ftext s
  336. | otherwise
  337. -> ptext (sLit "in") <+> quotes (ppr (nameModule name))
  338. where subst s = mkRealSrcLoc (realFP s) (srcLocLine s) (srcLocCol s)
  339. realFP = mkFastString . m . unpackFS . srcLocFile
  340. ----------------------------------------------------------------
  341. ----------------------------------------------------------------
  342. errorMsgSpan :: ErrMsg -> SrcSpan
  343. #if __GLASGOW_HASKELL__ >= 708
  344. errorMsgSpan = errMsgSpan
  345. #else
  346. errorMsgSpan = head . errMsgSpans
  347. #endif
  348. typeForUser :: Type -> SDoc
  349. #if __GLASGOW_HASKELL__ >= 708
  350. typeForUser = pprTypeForUser
  351. #else
  352. typeForUser = pprTypeForUser False
  353. #endif
  354. nameForUser :: Name -> SDoc
  355. nameForUser = pprOccName . getOccName
  356. occNameForUser :: OccName -> SDoc
  357. occNameForUser = pprOccName
  358. deSugar :: TypecheckedModule -> LHsExpr Id -> HscEnv
  359. -> IO (Maybe CoreExpr)
  360. #if __GLASGOW_HASKELL__ >= 708
  361. deSugar _ e hs_env = snd <$> deSugarExpr hs_env e
  362. #else
  363. deSugar tcm e hs_env = snd <$> deSugarExpr hs_env modu rn_env ty_env e
  364. where
  365. modu = ms_mod $ pm_mod_summary $ tm_parsed_module tcm
  366. tcgEnv = fst $ tm_internals_ tcm
  367. rn_env = tcg_rdr_env tcgEnv
  368. ty_env = tcg_type_env tcgEnv
  369. #endif
  370. ----------------------------------------------------------------
  371. ----------------------------------------------------------------
  372. data GapThing = GtA Type | GtT TyCon | GtN
  373. fromTyThing :: TyThing -> GapThing
  374. fromTyThing (AnId i) = GtA $ varType i
  375. #if __GLASGOW_HASKELL__ >= 708
  376. fromTyThing (AConLike (RealDataCon d)) = GtA $ dataConRepType d
  377. fromTyThing (AConLike (PatSynCon p)) = GtA $ patSynType p
  378. #else
  379. fromTyThing (ADataCon d) = GtA $ dataConRepType d
  380. #endif
  381. fromTyThing (ATyCon t) = GtT t
  382. fromTyThing _ = GtN
  383. ----------------------------------------------------------------
  384. ----------------------------------------------------------------
  385. #if __GLASGOW_HASKELL__ >= 704
  386. type WarnFlags = I.IntSet
  387. emptyWarnFlags :: WarnFlags
  388. emptyWarnFlags = I.empty
  389. #else
  390. type WarnFlags = [WarningFlag]
  391. emptyWarnFlags :: WarnFlags
  392. emptyWarnFlags = []
  393. #endif
  394. ----------------------------------------------------------------
  395. ----------------------------------------------------------------
  396. #if __GLASGOW_HASKELL__ >= 708
  397. type GLMatch = LMatch RdrName (LHsExpr RdrName)
  398. type GLMatchI = LMatch Id (LHsExpr Id)
  399. #else
  400. type GLMatch = LMatch RdrName
  401. type GLMatchI = LMatch Id
  402. #endif
  403. getClass :: [LInstDecl Name] -> Maybe (Name, SrcSpan)
  404. #if __GLASGOW_HASKELL__ >= 710
  405. -- Instance declarations of sort 'instance F (G a)'
  406. getClass [L loc (ClsInstD (ClsInstDecl {cid_poly_ty = (L _ (HsForAllTy _ _ _ _ (L _ (HsAppTy (L _ (HsTyVar className)) _))))}))] = Just (className, loc)
  407. -- Instance declarations of sort 'instance F G' (no variables)
  408. getClass [L loc (ClsInstD (ClsInstDecl {cid_poly_ty = (L _ (HsAppTy (L _ (HsTyVar className)) _))}))] = Just (className, loc)
  409. #elif __GLASGOW_HASKELL__ >= 708
  410. -- Instance declarations of sort 'instance F (G a)'
  411. getClass [L loc (ClsInstD (ClsInstDecl {cid_poly_ty = (L _ (HsForAllTy _ _ _ (L _ (HsAppTy (L _ (HsTyVar className)) _))))}))] = Just (className, loc)
  412. -- Instance declarations of sort 'instance F G' (no variables)
  413. getClass [L loc (ClsInstD (ClsInstDecl {cid_poly_ty = (L _ (HsAppTy (L _ (HsTyVar className)) _))}))] = Just (className, loc)
  414. #elif __GLASGOW_HASKELL__ >= 706
  415. getClass [L loc (ClsInstD (L _ (HsForAllTy _ _ _ (L _ (HsAppTy (L _ (HsTyVar className)) _)))) _ _ _)] = Just (className, loc)
  416. getClass[L loc (ClsInstD (L _ (HsAppTy (L _ (HsTyVar className)) _)) _ _ _)] = Just (className, loc)
  417. #else
  418. getClass [L loc (InstDecl (L _ (HsForAllTy _ _ _ (L _ (HsAppTy (L _ (HsTyVar className)) _)))) _ _ _)] = Just (className, loc)
  419. getClass [L loc (InstDecl (L _ (HsAppTy (L _ (HsTyVar className)) _)) _ _ _)] = Just (className, loc)
  420. #endif
  421. getClass _ = Nothing
  422. #if __GLASGOW_HASKELL__ < 706
  423. occName :: RdrName -> OccName
  424. occName = rdrNameOcc
  425. #endif
  426. ----------------------------------------------------------------
  427. #if __GLASGOW_HASKELL__ < 710
  428. -- Copied from ghc/InteractiveUI.hs
  429. allExposedPackageConfigs :: DynFlags -> [PackageConfig]
  430. allExposedPackageConfigs df = filter exposed $ eltsUFM $ pkgIdMap $ pkgState df
  431. allExposedModules :: DynFlags -> [ModuleName]
  432. allExposedModules df = concat $ map exposedModules $ allExposedPackageConfigs df
  433. listVisibleModuleNames :: DynFlags -> [ModuleName]
  434. listVisibleModuleNames = allExposedModules
  435. #endif
  436. lookupModulePackageInAllPackages ::
  437. DynFlags -> ModuleName -> [String]
  438. lookupModulePackageInAllPackages df mn =
  439. #if __GLASGOW_HASKELL__ >= 710
  440. unpackSPId . sourcePackageId . snd <$> lookupModuleInAllPackages df mn
  441. where
  442. unpackSPId (SourcePackageId fs) = unpackFS fs
  443. #else
  444. unpackPId . sourcePackageId . fst <$> lookupModuleInAllPackages df mn
  445. where
  446. unpackPId pid = packageIdString $ mkPackageId pid
  447. -- n ++ "-" ++ showVersion v
  448. #endif
  449. listVisibleModules :: DynFlags -> [GHC.Module]
  450. listVisibleModules df = let
  451. #if __GLASGOW_HASKELL__ >= 710
  452. modNames = listVisibleModuleNames df
  453. mods = [ m | mn <- modNames, (m, _) <- lookupModuleInAllPackages df mn ]
  454. #else
  455. pkgCfgs = allExposedPackageConfigs df
  456. mods = [ mkModule pid modname | p <- pkgCfgs
  457. , let pid = packageConfigId p
  458. , modname <- exposedModules p ]
  459. #endif
  460. in mods
  461. isSynTyCon :: TyCon -> Bool
  462. #if __GLASGOW_HASKELL__ >= 710
  463. isSynTyCon = GHC.isTypeSynonymTyCon
  464. #else
  465. isSynTyCon = GHC.isSynTyCon
  466. #endif
  467. parseModuleHeader
  468. :: String -- ^ Haskell module source text (full Unicode is supported)
  469. -> DynFlags
  470. -> FilePath -- ^ the filename (for source locations)
  471. -> Either ErrorMessages (WarningMessages, Located (HsModule RdrName))
  472. parseModuleHeader str dflags filename =
  473. let
  474. loc = mkRealSrcLoc (mkFastString filename) 1 1
  475. buf = stringToStringBuffer str
  476. in
  477. case L.unP Parser.parseHeader (mkPState dflags buf loc) of
  478. PFailed sp err ->
  479. #if __GLASGOW_HASKELL__ >= 706
  480. Left (unitBag (mkPlainErrMsg dflags sp err))
  481. #else
  482. Left (unitBag (mkPlainErrMsg sp err))
  483. #endif
  484. POk pst rdr_module ->
  485. let (warns,_) = getMessages pst in
  486. Right (warns, rdr_module)
  487. mkErrStyle' :: DynFlags -> PrintUnqualified -> PprStyle
  488. #if __GLASGOW_HASKELL__ >= 706
  489. mkErrStyle' = Outputable.mkErrStyle
  490. #else
  491. mkErrStyle' _ = Outputable.mkErrStyle
  492. #endif