packages feed

ghcide 0.2.0 → 0.3.0

raw patch · 49 files changed

+11311/−3865 lines, 49 filesdep +Chartdep +Chart-diagramsdep +diagramsdep −parser-combinatorsdep ~basedep ~extradep ~ghcnew-component:exe:ghcide-benchnew-uploaderPVP ok

version bump matches the API change (PVP)

Dependencies added: Chart, Chart-diagrams, diagrams, diagrams-svg, process, safe, yaml

Dependencies removed: parser-combinators

Dependency ranges changed: base, extra, ghc, ghc-check, hie-bios, lsp-test

API changes (from Hackage documentation)

- Development.IDE.Core.RuleTypes: GetHiFile :: GetHiFile
- Development.IDE.Core.RuleTypes: data GetHiFile
- Development.IDE.Core.RuleTypes: instance Control.DeepSeq.NFData Development.IDE.Core.RuleTypes.GetHiFile
- Development.IDE.Core.RuleTypes: instance Data.Binary.Class.Binary Development.IDE.Core.RuleTypes.GetHiFile
- Development.IDE.Core.RuleTypes: instance Data.Hashable.Class.Hashable Development.IDE.Core.RuleTypes.GetHiFile
- Development.IDE.Core.RuleTypes: instance GHC.Classes.Eq Development.IDE.Core.RuleTypes.GetHiFile
- Development.IDE.Core.RuleTypes: instance GHC.Generics.Generic Development.IDE.Core.RuleTypes.GetHiFile
- Development.IDE.Core.RuleTypes: instance GHC.Show.Show Development.IDE.Core.RuleTypes.GetHiFile
- Development.IDE.Core.Rules: GhcSessionFun :: (FilePath -> Action (IdeResult HscEnvEq)) -> GhcSessionFun
- Development.IDE.Core.Rules: instance Control.DeepSeq.NFData Development.IDE.Core.Rules.GhcSessionFun
- Development.IDE.Core.Rules: instance GHC.Show.Show Development.IDE.Core.Rules.GhcSessionFun
- Development.IDE.Core.Rules: newtype GhcSessionFun
- Development.IDE.Core.Service: instance Development.IDE.Core.Shake.IsIdeGlobal Development.IDE.Core.Service.GlobalIdeOptions
- Development.IDE.Core.Service: runActionSync :: IdeState -> Action a -> IO a
- Development.IDE.Core.Shake: GetModificationTime :: GetModificationTime
- Development.IDE.Core.Shake: modificationTime :: FileVersion -> Maybe (Int, Int)
- Development.IDE.Core.Shake: shakeRun :: IdeState -> [Action a] -> IO (IO [a])
- Development.IDE.GHC.Error: mergeDiagnostics :: [FileDiagnostic] -> [FileDiagnostic] -> [FileDiagnostic]
- Development.IDE.GHC.Util: GhcVersionMismatch :: !Version -> !Version -> HscEnvEq
- Development.IDE.GHC.Util: [compileTime] :: HscEnvEq -> !Version
- Development.IDE.GHC.Util: [runTime] :: HscEnvEq -> !Version
- Development.IDE.GHC.Util: setDefaultHieDir :: FilePath -> DynFlags -> DynFlags
+ Development.IDE.Core.FileStore: modificationTime :: FileVersion -> Maybe UTCTime
+ Development.IDE.Core.FileStore: setFileModified :: IdeState -> NormalizedFilePath -> IO ()
+ Development.IDE.Core.OfInterest: kick :: DelayedAction ()
+ Development.IDE.Core.RuleTypes: GetModIfaceFromDisk :: GetModIfaceFromDisk
+ Development.IDE.Core.RuleTypes: GetModSummaryWithoutTimestamps :: GetModSummaryWithoutTimestamps
+ Development.IDE.Core.RuleTypes: GhcSessionDeps :: GhcSessionDeps
+ Development.IDE.Core.RuleTypes: data GetModIfaceFromDisk
+ Development.IDE.Core.RuleTypes: data GetModSummaryWithoutTimestamps
+ Development.IDE.Core.RuleTypes: data GhcSessionDeps
+ Development.IDE.Core.RuleTypes: hiFileFingerPrint :: HiFileResult -> ByteString
+ Development.IDE.Core.RuleTypes: instance Control.DeepSeq.NFData Development.IDE.Core.RuleTypes.GetModIfaceFromDisk
+ Development.IDE.Core.RuleTypes: instance Control.DeepSeq.NFData Development.IDE.Core.RuleTypes.GetModSummaryWithoutTimestamps
+ Development.IDE.Core.RuleTypes: instance Control.DeepSeq.NFData Development.IDE.Core.RuleTypes.GhcSessionDeps
+ Development.IDE.Core.RuleTypes: instance Data.Binary.Class.Binary Development.IDE.Core.RuleTypes.GetModIfaceFromDisk
+ Development.IDE.Core.RuleTypes: instance Data.Binary.Class.Binary Development.IDE.Core.RuleTypes.GetModSummaryWithoutTimestamps
+ Development.IDE.Core.RuleTypes: instance Data.Binary.Class.Binary Development.IDE.Core.RuleTypes.GhcSessionDeps
+ Development.IDE.Core.RuleTypes: instance Data.Hashable.Class.Hashable Development.IDE.Core.RuleTypes.GetModIfaceFromDisk
+ Development.IDE.Core.RuleTypes: instance Data.Hashable.Class.Hashable Development.IDE.Core.RuleTypes.GetModSummaryWithoutTimestamps
+ Development.IDE.Core.RuleTypes: instance Data.Hashable.Class.Hashable Development.IDE.Core.RuleTypes.GhcSessionDeps
+ Development.IDE.Core.RuleTypes: instance GHC.Classes.Eq Development.IDE.Core.RuleTypes.GetModIfaceFromDisk
+ Development.IDE.Core.RuleTypes: instance GHC.Classes.Eq Development.IDE.Core.RuleTypes.GetModSummaryWithoutTimestamps
+ Development.IDE.Core.RuleTypes: instance GHC.Classes.Eq Development.IDE.Core.RuleTypes.GhcSessionDeps
+ Development.IDE.Core.RuleTypes: instance GHC.Generics.Generic Development.IDE.Core.RuleTypes.GetModIfaceFromDisk
+ Development.IDE.Core.RuleTypes: instance GHC.Generics.Generic Development.IDE.Core.RuleTypes.GetModSummaryWithoutTimestamps
+ Development.IDE.Core.RuleTypes: instance GHC.Generics.Generic Development.IDE.Core.RuleTypes.GhcSessionDeps
+ Development.IDE.Core.RuleTypes: instance GHC.Show.Show Development.IDE.Core.RuleTypes.GetModIfaceFromDisk
+ Development.IDE.Core.RuleTypes: instance GHC.Show.Show Development.IDE.Core.RuleTypes.GetModSummaryWithoutTimestamps
+ Development.IDE.Core.RuleTypes: instance GHC.Show.Show Development.IDE.Core.RuleTypes.GhcSessionDeps
+ Development.IDE.Core.RuleTypes: tmr_hiFileResult :: TcModuleResult -> HiFileResult
+ Development.IDE.Core.Rules: defineEarlyCutOffNoFile :: IdeRule k v => (k -> Action (ByteString, v)) -> Rules ()
+ Development.IDE.Core.Rules: getTypeDefinition :: NormalizedFilePath -> Position -> IdeAction (Maybe [Location])
+ Development.IDE.Core.Rules: instance Control.DeepSeq.NFData Development.IDE.Core.Rules.IsHiFileStable
+ Development.IDE.Core.Rules: instance Data.Binary.Class.Binary Development.IDE.Core.Rules.IsHiFileStable
+ Development.IDE.Core.Rules: instance Data.Hashable.Class.Hashable Development.IDE.Core.Rules.IsHiFileStable
+ Development.IDE.Core.Rules: instance GHC.Classes.Eq Development.IDE.Core.Rules.IsHiFileStable
+ Development.IDE.Core.Rules: instance GHC.Generics.Generic Development.IDE.Core.Rules.IsHiFileStable
+ Development.IDE.Core.Rules: instance GHC.Show.Show Development.IDE.Core.Rules.IsHiFileStable
+ Development.IDE.Core.Service: getIdeOptionsIO :: ShakeExtras -> IO IdeOptions
+ Development.IDE.Core.Shake: FastResult :: Maybe (a, PositionMapping) -> IO (Maybe a) -> FastResult a
+ Development.IDE.Core.Shake: GetModificationTime_ :: Bool -> GetModificationTime
+ Development.IDE.Core.Shake: GlobalIdeOptions :: IdeOptions -> GlobalIdeOptions
+ Development.IDE.Core.Shake: IdeAction :: ReaderT ShakeExtras IO a -> IdeAction a
+ Development.IDE.Core.Shake: KickCompleted :: ProgressEvent
+ Development.IDE.Core.Shake: KickStarted :: ProgressEvent
+ Development.IDE.Core.Shake: Q :: (k, NormalizedFilePath) -> Q k
+ Development.IDE.Core.Shake: [ideNc] :: ShakeExtras -> IORef NameCache
+ Development.IDE.Core.Shake: [ideTesting] :: ShakeExtras -> IdeTesting
+ Development.IDE.Core.Shake: [missingFileDiagnostics] :: GetModificationTime -> Bool
+ Development.IDE.Core.Shake: [progressUpdate] :: ShakeExtras -> ProgressEvent -> IO ()
+ Development.IDE.Core.Shake: [restartShakeSession] :: ShakeExtras -> [DelayedAction ()] -> IO ()
+ Development.IDE.Core.Shake: [runIdeActionT] :: IdeAction a -> ReaderT ShakeExtras IO a
+ Development.IDE.Core.Shake: [session] :: ShakeExtras -> MVar ShakeSession
+ Development.IDE.Core.Shake: [stale] :: FastResult a -> Maybe (a, PositionMapping)
+ Development.IDE.Core.Shake: [uptoDate] :: FastResult a -> IO (Maybe a)
+ Development.IDE.Core.Shake: [withIndefiniteProgress] :: ShakeExtras -> WithIndefiniteProgressFunc
+ Development.IDE.Core.Shake: [withProgress] :: ShakeExtras -> WithProgressFunc
+ Development.IDE.Core.Shake: data DelayedAction a
+ Development.IDE.Core.Shake: data FastResult a
+ Development.IDE.Core.Shake: data ProgressEvent
+ Development.IDE.Core.Shake: delayedAction :: DelayedAction a -> IdeAction (IO a)
+ Development.IDE.Core.Shake: getIdeGlobalExtras :: forall a. IsIdeGlobal a => ShakeExtras -> IO a
+ Development.IDE.Core.Shake: getIdeOptions :: Action IdeOptions
+ Development.IDE.Core.Shake: getIdeOptionsIO :: ShakeExtras -> IO IdeOptions
+ Development.IDE.Core.Shake: instance Control.Monad.IO.Class.MonadIO Development.IDE.Core.Shake.IdeAction
+ Development.IDE.Core.Shake: instance Control.Monad.Reader.Class.MonadReader Development.IDE.Core.Shake.ShakeExtras Development.IDE.Core.Shake.IdeAction
+ Development.IDE.Core.Shake: instance Development.IDE.Core.Shake.IsIdeGlobal Development.IDE.Core.Shake.GlobalIdeOptions
+ Development.IDE.Core.Shake: instance GHC.Base.Applicative Development.IDE.Core.Shake.IdeAction
+ Development.IDE.Core.Shake: instance GHC.Base.Functor Development.IDE.Core.Shake.IdeAction
+ Development.IDE.Core.Shake: instance GHC.Base.Monad Development.IDE.Core.Shake.IdeAction
+ Development.IDE.Core.Shake: instance GHC.Show.Show (Development.IDE.Core.Shake.DelayedAction a)
+ Development.IDE.Core.Shake: mkDelayedAction :: String -> Priority -> Action a -> DelayedAction a
+ Development.IDE.Core.Shake: mkUpdater :: MaybeT IdeAction NameCacheUpdater
+ Development.IDE.Core.Shake: newtype GlobalIdeOptions
+ Development.IDE.Core.Shake: newtype IdeAction a
+ Development.IDE.Core.Shake: newtype Q k
+ Development.IDE.Core.Shake: pattern GetModificationTime :: GetModificationTime
+ Development.IDE.Core.Shake: runIdeAction :: String -> ShakeExtras -> IdeAction a -> IO a
+ Development.IDE.Core.Shake: shakeEnqueue :: IdeState -> DelayedAction a -> IO (IO a)
+ Development.IDE.Core.Shake: shakeRestart :: IdeState -> [DelayedAction a] -> IO ()
+ Development.IDE.Core.Shake: type WithIndefiniteProgressFunc = forall a. Text -> ProgressCancellable -> IO a -> IO a
+ Development.IDE.Core.Shake: type WithProgressFunc = forall a. Text -> ProgressCancellable -> ((Progress -> IO ()) -> IO a) -> IO a
+ Development.IDE.Core.Shake: useWithStaleFast :: IdeRule k v => k -> NormalizedFilePath -> IdeAction (Maybe (v, PositionMapping))
+ Development.IDE.Core.Shake: useWithStaleFast' :: IdeRule k v => k -> NormalizedFilePath -> IdeAction (FastResult v)
+ Development.IDE.Core.Shake: useWithStale_ :: IdeRule k v => k -> NormalizedFilePath -> Action (v, PositionMapping)
+ Development.IDE.Core.Shake: usesWithStale_ :: IdeRule k v => k -> [NormalizedFilePath] -> Action [(v, PositionMapping)]
+ Development.IDE.GHC.Compat: ABE :: XABE p -> IdP p -> IdP p -> HsWrapper -> TcSpecPrags -> ABExport p
+ Development.IDE.GHC.Compat: ACoAxiom :: CoAxiom Branched -> TyThing
+ Development.IDE.GHC.Compat: AConLike :: ConLike -> TyThing
+ Development.IDE.GHC.Compat: ATyCon :: TyCon -> TyThing
+ Development.IDE.GHC.Compat: AbsBinds :: XAbsBinds idL idR -> [TyVar] -> [EvVar] -> [ABExport idL] -> [TcEvBinds] -> LHsBinds idL -> Bool -> HsBindLR idL idR
+ Development.IDE.GHC.Compat: Ambiguous :: XAmbiguous pass -> Located RdrName -> AmbiguousFieldOcc pass
+ Development.IDE.GHC.Compat: AnId :: Id -> TyThing
+ Development.IDE.GHC.Compat: AnnAnyclass :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnAs :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnAt :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnBackquote :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnBang :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnBlockComment :: String -> AnnotationComment
+ Development.IDE.GHC.Compat: AnnBy :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnCase :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnClass :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnClose :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnCloseB :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnCloseBU :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnCloseC :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnCloseP :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnCloseQ :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnCloseQU :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnCloseS :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnColon :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnComma :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnCommaTuple :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnD :: XAnnD p -> AnnDecl p -> HsDecl p
+ Development.IDE.GHC.Compat: AnnDarrow :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnDarrowU :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnData :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnDcolon :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnDcolonU :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnDefault :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnDeriving :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnDo :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnDocCommentNamed :: String -> AnnotationComment
+ Development.IDE.GHC.Compat: AnnDocCommentNext :: String -> AnnotationComment
+ Development.IDE.GHC.Compat: AnnDocCommentPrev :: String -> AnnotationComment
+ Development.IDE.GHC.Compat: AnnDocOptions :: String -> AnnotationComment
+ Development.IDE.GHC.Compat: AnnDocSection :: Int -> String -> AnnotationComment
+ Development.IDE.GHC.Compat: AnnDot :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnDotdot :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnElse :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnEofPos :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnEqual :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnExport :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnFamily :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnForall :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnForallU :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnForeign :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnFunId :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnGroup :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnHeader :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnHiding :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnIf :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnImport :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnIn :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnInfix :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnInstance :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnLam :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnLarrow :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnLarrowU :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnLarrowtail :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnLarrowtailU :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnLet :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnLineComment :: String -> AnnotationComment
+ Development.IDE.GHC.Compat: AnnMdo :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnMinus :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnModule :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnName :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnNewtype :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnOf :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnOpen :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnOpenB :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnOpenBU :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnOpenC :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnOpenE :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnOpenEQ :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnOpenEQU :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnOpenP :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnOpenPE :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnOpenPTE :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnOpenS :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnPackageName :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnPattern :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnProc :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnQualified :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnRarrow :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnRarrowU :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnRarrowtail :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnRarrowtailU :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnRec :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnRole :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnSafe :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnSemi :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnSignature :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnSimpleQuote :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnStatic :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnStock :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnThIdSplice :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnThIdTySplice :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnThTyQuote :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnThen :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnTilde :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnType :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnUnit :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnUsing :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnVal :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnValStr :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnVbar :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnVia :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnWhere :: AnnKeywordId
+ Development.IDE.GHC.Compat: Annlarrowtail :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnlarrowtailU :: AnnKeywordId
+ Development.IDE.GHC.Compat: Annrarrowtail :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnnrarrowtailU :: AnnKeywordId
+ Development.IDE.GHC.Compat: AnonWildCard :: Located Name -> HsWildCardInfo
+ Development.IDE.GHC.Compat: AnyclassStrategy :: DerivStrategy pass
+ Development.IDE.GHC.Compat: ApplicativeArgMany :: XApplicativeArgMany idL -> [ExprLStmt idL] -> HsExpr idL -> LPat idL -> ApplicativeArg idL
+ Development.IDE.GHC.Compat: ApplicativeArgOne :: XApplicativeArgOne idL -> LPat idL -> LHsExpr idL -> Bool -> ApplicativeArg idL
+ Development.IDE.GHC.Compat: ApplicativeStmt :: XApplicativeStmt idL idR body -> [(SyntaxExpr idR, ApplicativeArg idL)] -> Maybe (SyntaxExpr idR) -> StmtLR idL idR body
+ Development.IDE.GHC.Compat: ArgDocMap :: Map Name (Map Int HsDocString) -> ArgDocMap
+ Development.IDE.GHC.Compat: ArithSeq :: XArithSeq p -> Maybe (SyntaxExpr p) -> ArithSeqInfo p -> HsExpr p
+ Development.IDE.GHC.Compat: ArrowExpr :: HsStmtContext id
+ Development.IDE.GHC.Compat: AsPat :: XAsPat p -> Located (IdP p) -> LPat p -> Pat p
+ Development.IDE.GHC.Compat: BangPat :: XBangPat p -> LPat p -> Pat p
+ Development.IDE.GHC.Compat: BindStmt :: XBindStmt idL idR body -> LPat idL -> body -> SyntaxExpr idR -> SyntaxExpr idR -> StmtLR idL idR body
+ Development.IDE.GHC.Compat: BodyStmt :: XBodyStmt idL idR body -> body -> SyntaxExpr idR -> SyntaxExpr idR -> StmtLR idL idR body
+ Development.IDE.GHC.Compat: CExport :: Located CExportSpec -> Located SourceText -> ForeignExport
+ Development.IDE.GHC.Compat: CFunction :: CCallTarget -> CImportSpec
+ Development.IDE.GHC.Compat: CImport :: Located CCallConv -> Located Safety -> Maybe Header -> CImportSpec -> Located SourceText -> ForeignImport
+ Development.IDE.GHC.Compat: CLabel :: CLabelString -> CImportSpec
+ Development.IDE.GHC.Compat: CWrapper :: CImportSpec
+ Development.IDE.GHC.Compat: CaseAlt :: HsMatchContext id
+ Development.IDE.GHC.Compat: ClassDec :: DeclType
+ Development.IDE.GHC.Compat: ClassDecl :: XClassDecl pass -> LHsContext pass -> Located (IdP pass) -> LHsQTyVars pass -> LexicalFixity -> [Located (FunDep (Located (IdP pass)))] -> [LSig pass] -> LHsBinds pass -> [LFamilyDecl pass] -> [LTyFamDefltEqn pass] -> [LDocDecl] -> TyClDecl pass
+ Development.IDE.GHC.Compat: ClassTyDecl :: Maybe Span -> ContextInfo
+ Development.IDE.GHC.Compat: ClosedTypeFamily :: Maybe [LTyFamInstEqn pass] -> FamilyInfo pass
+ Development.IDE.GHC.Compat: ClsInstD :: XClsInstD pass -> ClsInstDecl pass -> InstDecl pass
+ Development.IDE.GHC.Compat: ClsInstDecl :: XCClsInstDecl pass -> LHsSigType pass -> LHsBinds pass -> [LSig pass] -> [LTyFamInstDecl pass] -> [LDataFamInstDecl pass] -> Maybe (Located OverlapMode) -> ClsInstDecl pass
+ Development.IDE.GHC.Compat: CmdLineError :: String -> GhcException
+ Development.IDE.GHC.Compat: CmdTopTc :: Type -> Type -> CmdSyntaxTable GhcTc -> CmdTopTc
+ Development.IDE.GHC.Compat: CoPat :: XCoPat p -> HsWrapper -> Pat p -> Type -> Pat p
+ Development.IDE.GHC.Compat: CompManager :: GhcMode
+ Development.IDE.GHC.Compat: CompleteMatchSig :: XCompleteMatchSig pass -> SourceText -> Located [Located (IdP pass)] -> Maybe (Located (IdP pass)) -> Sig pass
+ Development.IDE.GHC.Compat: ConDec :: DeclType
+ Development.IDE.GHC.Compat: ConDeclField :: XConDeclField pass -> [LFieldOcc pass] -> LBangType pass -> Maybe LHsDocString -> ConDeclField pass
+ Development.IDE.GHC.Compat: ConDeclGADT :: XConDeclGADT pass -> [Located (IdP pass)] -> Located Bool -> LHsQTyVars pass -> Maybe (LHsContext pass) -> HsConDeclDetails pass -> LHsType pass -> Maybe LHsDocString -> ConDecl pass
+ Development.IDE.GHC.Compat: ConDeclH98 :: XConDeclH98 pass -> Located (IdP pass) -> Located Bool -> [LHsTyVarBndr pass] -> Maybe (LHsContext pass) -> HsConDeclDetails pass -> Maybe LHsDocString -> ConDecl pass
+ Development.IDE.GHC.Compat: ConPatIn :: Located (IdP p) -> HsConPatDetails p -> Pat p
+ Development.IDE.GHC.Compat: ConPatOut :: Located ConLike -> [Type] -> [TyVar] -> [EvVar] -> TcEvBinds -> HsConPatDetails p -> HsWrapper -> Pat p
+ Development.IDE.GHC.Compat: CoreModule :: !Module -> !TypeEnv -> CoreProgram -> SafeHaskellMode -> CoreModule
+ Development.IDE.GHC.Compat: DataDec :: DeclType
+ Development.IDE.GHC.Compat: DataDecl :: XDataDecl pass -> Located (IdP pass) -> LHsQTyVars pass -> LexicalFixity -> HsDataDefn pass -> TyClDecl pass
+ Development.IDE.GHC.Compat: DataDeclRn :: Bool -> NameSet -> DataDeclRn
+ Development.IDE.GHC.Compat: DataFamInstD :: XDataFamInstD pass -> DataFamInstDecl pass -> InstDecl pass
+ Development.IDE.GHC.Compat: DataFamInstDecl :: FamInstEqn pass (HsDataDefn pass) -> DataFamInstDecl pass
+ Development.IDE.GHC.Compat: DataFamily :: FamilyInfo pass
+ Development.IDE.GHC.Compat: DataType :: NewOrData
+ Development.IDE.GHC.Compat: DecBrG :: XDecBrG p -> HsGroup p -> HsBracket p
+ Development.IDE.GHC.Compat: DecBrL :: XDecBrL p -> [LHsDecl p] -> HsBracket p
+ Development.IDE.GHC.Compat: Decl :: DeclType -> Maybe Span -> ContextInfo
+ Development.IDE.GHC.Compat: DeclDocMap :: Map Name HsDocString -> DeclDocMap
+ Development.IDE.GHC.Compat: DefD :: XDefD p -> DefaultDecl p -> HsDecl p
+ Development.IDE.GHC.Compat: DefaultDecl :: XCDefaultDecl pass -> [LHsType pass] -> DefaultDecl pass
+ Development.IDE.GHC.Compat: DerivDecl :: XCDerivDecl pass -> LHsSigWcType pass -> Maybe (LDerivStrategy pass) -> Maybe (Located OverlapMode) -> DerivDecl pass
+ Development.IDE.GHC.Compat: DesugaredModule :: TypecheckedModule -> ModGuts -> DesugaredModule
+ Development.IDE.GHC.Compat: DoExpr :: HsStmtContext id
+ Development.IDE.GHC.Compat: DocCommentNamed :: String -> HsDocString -> DocDecl
+ Development.IDE.GHC.Compat: DocCommentNext :: HsDocString -> DocDecl
+ Development.IDE.GHC.Compat: DocCommentPrev :: HsDocString -> DocDecl
+ Development.IDE.GHC.Compat: DocD :: XDocD p -> DocDecl -> HsDecl p
+ Development.IDE.GHC.Compat: DocGroup :: Int -> HsDocString -> DocDecl
+ Development.IDE.GHC.Compat: DynFlags :: GhcMode -> GhcLink -> HscTarget -> Settings -> LlvmTargets -> LlvmPasses -> Int -> Int -> Int -> Int -> Int -> Int -> Maybe String -> Maybe String -> [Int] -> Maybe Int -> Bool -> Maybe Int -> Maybe Int -> Maybe Int -> Maybe Int -> Maybe Int -> Int -> Int -> Maybe Int -> Maybe Int -> Int -> Maybe Int -> Maybe Int -> Maybe Int -> Int -> [FilePath] -> Module -> Maybe String -> IntWithInf -> IntWithInf -> InstalledUnitId -> Maybe ComponentId -> Maybe [(ModuleName, Module)] -> [Way] -> String -> Maybe (String, Int) -> Maybe String -> Maybe String -> Maybe String -> Maybe String -> Maybe String -> String -> String -> String -> IORef Bool -> String -> String -> Maybe String -> Maybe String -> Maybe String -> DynLibLoader -> Maybe FilePath -> Maybe FilePath -> [Option] -> IncludeSpecs -> [String] -> [String] -> [String] -> Maybe String -> RtsOptsEnabled -> Bool -> String -> [ModuleName] -> [(ModuleName, String)] -> [String] -> [LoadedPlugin] -> Hooks -> FilePath -> Bool -> [ModuleName] -> [String] -> [PackageDBFlag] -> [IgnorePackageFlag] -> [PackageFlag] -> [PackageFlag] -> [TrustFlag] -> Maybe FilePath -> Maybe [(FilePath, [PackageConfig])] -> PackageState -> IORef FilesToClean -> IORef (Map FilePath FilePath) -> IORef Int -> IORef (Set FilePath) -> EnumSet DumpFlag -> EnumSet GeneralFlag -> EnumSet WarningFlag -> EnumSet WarningFlag -> Maybe Language -> SafeHaskellMode -> Bool -> Bool -> SrcSpan -> SrcSpan -> SrcSpan -> SrcSpan -> SrcSpan -> SrcSpan -> SrcSpan -> SrcSpan -> [OnOff Extension] -> EnumSet Extension -> Int -> Int -> Int -> Int -> Float -> Int -> Bool -> Int -> Int -> LogAction -> FlushOut -> FlushErr -> Maybe FilePath -> Maybe String -> [String] -> Int -> Int -> Bool -> OverridingBool -> Bool -> Scheme -> ProfAuto -> Maybe String -> IORef (ModuleEnv Int) -> Maybe SseVersion -> Maybe BmiVersion -> Bool -> Bool -> Bool -> Bool -> Bool -> Bool -> IORef (Maybe LinkerInfo) -> IORef (Maybe CompilerInfo) -> Int -> Int -> Int -> Bool -> Maybe Int -> Int -> Int -> DynFlags
+ Development.IDE.GHC.Compat: EAsPat :: XEAsPat p -> Located (IdP p) -> LHsExpr p -> HsExpr p
+ Development.IDE.GHC.Compat: ELazyPat :: XELazyPat p -> LHsExpr p -> HsExpr p
+ Development.IDE.GHC.Compat: EViewPat :: XEViewPat p -> LHsExpr p -> LHsExpr p -> HsExpr p
+ Development.IDE.GHC.Compat: EWildPat :: XEWildPat p -> HsExpr p
+ Development.IDE.GHC.Compat: EmptyLocalBinds :: XEmptyLocalBinds idL idR -> HsLocalBindsLR idL idR
+ Development.IDE.GHC.Compat: ExecBreak :: [Name] -> Maybe BreakInfo -> ExecResult
+ Development.IDE.GHC.Compat: ExecComplete :: Either SomeException [Name] -> Word64 -> ExecResult
+ Development.IDE.GHC.Compat: ExecOptions :: SingleStep -> String -> Int -> (ForeignHValue -> EvalExpr ForeignHValue) -> ExecOptions
+ Development.IDE.GHC.Compat: ExpBr :: XExpBr p -> LHsExpr p -> HsBracket p
+ Development.IDE.GHC.Compat: ExplicitBidirectional :: MatchGroup id (LHsExpr id) -> HsPatSynDir id
+ Development.IDE.GHC.Compat: ExplicitList :: XExplicitList p -> Maybe (SyntaxExpr p) -> [LHsExpr p] -> HsExpr p
+ Development.IDE.GHC.Compat: ExplicitSplice :: SpliceExplicitFlag
+ Development.IDE.GHC.Compat: ExplicitSum :: XExplicitSum p -> ConTag -> Arity -> LHsExpr p -> HsExpr p
+ Development.IDE.GHC.Compat: ExplicitTuple :: XExplicitTuple p -> [LHsTupArg p] -> Boxity -> HsExpr p
+ Development.IDE.GHC.Compat: Export :: IEType
+ Development.IDE.GHC.Compat: ExprWithTySig :: XExprWithTySig p -> LHsExpr p -> HsExpr p
+ Development.IDE.GHC.Compat: Failed :: SuccessFlag
+ Development.IDE.GHC.Compat: FamDec :: DeclType
+ Development.IDE.GHC.Compat: FamDecl :: XFamDecl pass -> FamilyDecl pass -> TyClDecl pass
+ Development.IDE.GHC.Compat: FamEqn :: XCFamEqn pass pats rhs -> Located (IdP pass) -> pats -> LexicalFixity -> rhs -> FamEqn pass pats rhs
+ Development.IDE.GHC.Compat: FamilyDecl :: XCFamilyDecl pass -> FamilyInfo pass -> Located (IdP pass) -> LHsQTyVars pass -> LexicalFixity -> LFamilyResultSig pass -> Maybe (LInjectivityAnn pass) -> FamilyDecl pass
+ Development.IDE.GHC.Compat: FieldOcc :: XCFieldOcc pass -> Located RdrName -> FieldOcc pass
+ Development.IDE.GHC.Compat: FixSig :: XFixSig pass -> FixitySig pass -> Sig pass
+ Development.IDE.GHC.Compat: FixitySig :: XFixitySig pass -> [Located (IdP pass)] -> Fixity -> FixitySig pass
+ Development.IDE.GHC.Compat: ForeignExport :: XForeignExport pass -> Located (IdP pass) -> LHsSigType pass -> ForeignExport -> ForeignDecl pass
+ Development.IDE.GHC.Compat: ForeignImport :: XForeignImport pass -> Located (IdP pass) -> LHsSigType pass -> ForeignImport -> ForeignDecl pass
+ Development.IDE.GHC.Compat: From :: LHsExpr id -> ArithSeqInfo id
+ Development.IDE.GHC.Compat: FromThen :: LHsExpr id -> LHsExpr id -> ArithSeqInfo id
+ Development.IDE.GHC.Compat: FromThenTo :: LHsExpr id -> LHsExpr id -> LHsExpr id -> ArithSeqInfo id
+ Development.IDE.GHC.Compat: FromTo :: LHsExpr id -> LHsExpr id -> ArithSeqInfo id
+ Development.IDE.GHC.Compat: FunBind :: XFunBind idL idR -> Located (IdP idL) -> MatchGroup idR (LHsExpr idR) -> HsWrapper -> [Tickish Id] -> HsBindLR idL idR
+ Development.IDE.GHC.Compat: FunRhs :: Located id -> LexicalFixity -> SrcStrictness -> HsMatchContext id
+ Development.IDE.GHC.Compat: GRHS :: XCGRHS p body -> [GuardLStmt p] -> body -> GRHS p body
+ Development.IDE.GHC.Compat: GRHSs :: XCGRHSs p body -> [LGRHS p body] -> LHsLocalBinds p -> GRHSs p body
+ Development.IDE.GHC.Compat: GhciStmtCtxt :: HsStmtContext id
+ Development.IDE.GHC.Compat: GroupForm :: TransForm
+ Development.IDE.GHC.Compat: HAppTy :: a -> a -> HieType a
+ Development.IDE.GHC.Compat: HCastTy :: a -> HieType a
+ Development.IDE.GHC.Compat: HCoercionTy :: HieType a
+ Development.IDE.GHC.Compat: HForAllTy :: ((Name, a), ArgFlag) -> a -> HieType a
+ Development.IDE.GHC.Compat: HFunTy :: a -> a -> HieType a
+ Development.IDE.GHC.Compat: HLitTy :: IfaceTyLit -> HieType a
+ Development.IDE.GHC.Compat: HQualTy :: a -> a -> HieType a
+ Development.IDE.GHC.Compat: HTS :: !TypeMap TypeIndex -> !IntMap HieTypeFlat -> !TypeIndex -> HieTypeState
+ Development.IDE.GHC.Compat: HTyConApp :: IfaceTyCon -> HieArgs a -> HieType a
+ Development.IDE.GHC.Compat: HTyVarTy :: Name -> HieType a
+ Development.IDE.GHC.Compat: HasDollar :: SpliceDecoration
+ Development.IDE.GHC.Compat: HasParens :: SpliceDecoration
+ Development.IDE.GHC.Compat: HieASTs :: Map FastString (HieAST a) -> HieASTs a
+ Development.IDE.GHC.Compat: HieArgs :: [(Bool, a)] -> HieArgs a
+ Development.IDE.GHC.Compat: HieFile :: FilePath -> Module -> Array TypeIndex HieTypeFlat -> HieASTs TypeIndex -> [AvailInfo] -> ByteString -> HieFile
+ Development.IDE.GHC.Compat: HieFileResult :: Integer -> ByteString -> HieFile -> HieFileResult
+ Development.IDE.GHC.Compat: HsAnnotation :: XHsAnnotation pass -> SourceText -> AnnProvenance (IdP pass) -> Located (HsExpr pass) -> AnnDecl pass
+ Development.IDE.GHC.Compat: HsApp :: XApp p -> LHsExpr p -> LHsExpr p -> HsExpr p
+ Development.IDE.GHC.Compat: HsAppTy :: XAppTy pass -> LHsType pass -> LHsType pass -> HsType pass
+ Development.IDE.GHC.Compat: HsAppType :: XAppTypeE p -> LHsExpr p -> HsExpr p
+ Development.IDE.GHC.Compat: HsArrApp :: XArrApp p -> LHsExpr p -> LHsExpr p -> HsArrAppType -> Bool -> HsExpr p
+ Development.IDE.GHC.Compat: HsArrForm :: XArrForm p -> LHsExpr p -> Maybe Fixity -> [LHsCmdTop p] -> HsExpr p
+ Development.IDE.GHC.Compat: HsBangTy :: XBangTy pass -> HsSrcBang -> LHsType pass -> HsType pass
+ Development.IDE.GHC.Compat: HsBinTick :: XBinTick p -> Int -> Int -> LHsExpr p -> HsExpr p
+ Development.IDE.GHC.Compat: HsBoxedOrConstraintTuple :: HsTupleSort
+ Development.IDE.GHC.Compat: HsBoxedTuple :: HsTupleSort
+ Development.IDE.GHC.Compat: HsBracket :: XBracket p -> HsBracket p -> HsExpr p
+ Development.IDE.GHC.Compat: HsCase :: XCase p -> LHsExpr p -> MatchGroup p (LHsExpr p) -> HsExpr p
+ Development.IDE.GHC.Compat: HsChar :: XHsChar x -> Char -> HsLit x
+ Development.IDE.GHC.Compat: HsCharPrim :: XHsCharPrim x -> Char -> HsLit x
+ Development.IDE.GHC.Compat: HsCmdApp :: XCmdApp id -> LHsCmd id -> LHsExpr id -> HsCmd id
+ Development.IDE.GHC.Compat: HsCmdArrApp :: XCmdArrApp id -> LHsExpr id -> LHsExpr id -> HsArrAppType -> Bool -> HsCmd id
+ Development.IDE.GHC.Compat: HsCmdArrForm :: XCmdArrForm id -> LHsExpr id -> LexicalFixity -> Maybe Fixity -> [LHsCmdTop id] -> HsCmd id
+ Development.IDE.GHC.Compat: HsCmdCase :: XCmdCase id -> LHsExpr id -> MatchGroup id (LHsCmd id) -> HsCmd id
+ Development.IDE.GHC.Compat: HsCmdDo :: XCmdDo id -> Located [CmdLStmt id] -> HsCmd id
+ Development.IDE.GHC.Compat: HsCmdIf :: XCmdIf id -> Maybe (SyntaxExpr id) -> LHsExpr id -> LHsCmd id -> LHsCmd id -> HsCmd id
+ Development.IDE.GHC.Compat: HsCmdLam :: XCmdLam id -> MatchGroup id (LHsCmd id) -> HsCmd id
+ Development.IDE.GHC.Compat: HsCmdLet :: XCmdLet id -> LHsLocalBinds id -> LHsCmd id -> HsCmd id
+ Development.IDE.GHC.Compat: HsCmdPar :: XCmdPar id -> LHsCmd id -> HsCmd id
+ Development.IDE.GHC.Compat: HsCmdTop :: XCmdTop p -> LHsCmd p -> HsCmdTop p
+ Development.IDE.GHC.Compat: HsCmdWrap :: XCmdWrap id -> HsWrapper -> HsCmd id -> HsCmd id
+ Development.IDE.GHC.Compat: HsConLikeOut :: XConLikeOut p -> ConLike -> HsExpr p
+ Development.IDE.GHC.Compat: HsConstraintTuple :: HsTupleSort
+ Development.IDE.GHC.Compat: HsCoreAnn :: XCoreAnn p -> SourceText -> StringLiteral -> LHsExpr p -> HsExpr p
+ Development.IDE.GHC.Compat: HsDataDefn :: XCHsDataDefn pass -> NewOrData -> LHsContext pass -> Maybe (Located CType) -> Maybe (LHsKind pass) -> [LConDecl pass] -> HsDeriving pass -> HsDataDefn pass
+ Development.IDE.GHC.Compat: HsDerivingClause :: XCHsDerivingClause pass -> Maybe (LDerivStrategy pass) -> Located [LHsSigType pass] -> HsDerivingClause pass
+ Development.IDE.GHC.Compat: HsDo :: XDo p -> HsStmtContext Name -> Located [ExprLStmt p] -> HsExpr p
+ Development.IDE.GHC.Compat: HsDocTy :: XDocTy pass -> LHsType pass -> LHsDocString -> HsType pass
+ Development.IDE.GHC.Compat: HsDoublePrim :: XHsDoublePrim x -> FractionalLit -> HsLit x
+ Development.IDE.GHC.Compat: HsExplicitListTy :: XExplicitListTy pass -> Promoted -> [LHsType pass] -> HsType pass
+ Development.IDE.GHC.Compat: HsExplicitTupleTy :: XExplicitTupleTy pass -> [LHsType pass] -> HsType pass
+ Development.IDE.GHC.Compat: HsFirstOrderApp :: HsArrAppType
+ Development.IDE.GHC.Compat: HsFloatPrim :: XHsFloatPrim x -> FractionalLit -> HsLit x
+ Development.IDE.GHC.Compat: HsForAllTy :: XForAllTy pass -> [LHsTyVarBndr pass] -> LHsType pass -> HsType pass
+ Development.IDE.GHC.Compat: HsFractional :: !FractionalLit -> OverLitVal
+ Development.IDE.GHC.Compat: HsFunTy :: XFunTy pass -> LHsType pass -> LHsType pass -> HsType pass
+ Development.IDE.GHC.Compat: HsGroup :: XCHsGroup p -> HsValBinds p -> [LSpliceDecl p] -> [TyClGroup p] -> [LDerivDecl p] -> [LFixitySig p] -> [LDefaultDecl p] -> [LForeignDecl p] -> [LWarnDecls p] -> [LAnnDecl p] -> [LRuleDecls p] -> [LDocDecl] -> HsGroup p
+ Development.IDE.GHC.Compat: HsHigherOrderApp :: HsArrAppType
+ Development.IDE.GHC.Compat: HsIB :: XHsIB pass thing -> thing -> HsImplicitBndrs pass thing
+ Development.IDE.GHC.Compat: HsIBRn :: [Name] -> Bool -> HsIBRn
+ Development.IDE.GHC.Compat: HsIPBinds :: XHsIPBinds idL idR -> HsIPBinds idR -> HsLocalBindsLR idL idR
+ Development.IDE.GHC.Compat: HsIPName :: FastString -> HsIPName
+ Development.IDE.GHC.Compat: HsIPVar :: XIPVar p -> HsIPName -> HsExpr p
+ Development.IDE.GHC.Compat: HsIParamTy :: XIParamTy pass -> Located HsIPName -> LHsType pass -> HsType pass
+ Development.IDE.GHC.Compat: HsIf :: XIf p -> Maybe (SyntaxExpr p) -> LHsExpr p -> LHsExpr p -> LHsExpr p -> HsExpr p
+ Development.IDE.GHC.Compat: HsInt :: XHsInt x -> IntegralLit -> HsLit x
+ Development.IDE.GHC.Compat: HsInt64Prim :: XHsInt64Prim x -> Integer -> HsLit x
+ Development.IDE.GHC.Compat: HsIntPrim :: XHsIntPrim x -> Integer -> HsLit x
+ Development.IDE.GHC.Compat: HsInteger :: XHsInteger x -> Integer -> Type -> HsLit x
+ Development.IDE.GHC.Compat: HsIntegral :: !IntegralLit -> OverLitVal
+ Development.IDE.GHC.Compat: HsIsString :: !SourceText -> !FastString -> OverLitVal
+ Development.IDE.GHC.Compat: HsKindSig :: XKindSig pass -> LHsType pass -> LHsKind pass -> HsType pass
+ Development.IDE.GHC.Compat: HsLam :: XLam p -> MatchGroup p (LHsExpr p) -> HsExpr p
+ Development.IDE.GHC.Compat: HsLamCase :: XLamCase p -> MatchGroup p (LHsExpr p) -> HsExpr p
+ Development.IDE.GHC.Compat: HsLazy :: HsImplBang
+ Development.IDE.GHC.Compat: HsLet :: XLet p -> LHsLocalBinds p -> LHsExpr p -> HsExpr p
+ Development.IDE.GHC.Compat: HsListTy :: XListTy pass -> LHsType pass -> HsType pass
+ Development.IDE.GHC.Compat: HsLit :: XLitE p -> HsLit p -> HsExpr p
+ Development.IDE.GHC.Compat: HsModule :: Maybe (Located ModuleName) -> Maybe (Located [LIE pass]) -> [LImportDecl pass] -> [LHsDecl pass] -> Maybe (Located WarningTxt) -> Maybe LHsDocString -> HsModule pass
+ Development.IDE.GHC.Compat: HsMultiIf :: XMultiIf p -> [LGRHS p (LHsExpr p)] -> HsExpr p
+ Development.IDE.GHC.Compat: HsNumTy :: SourceText -> Integer -> HsTyLit
+ Development.IDE.GHC.Compat: HsOpTy :: XOpTy pass -> LHsType pass -> Located (IdP pass) -> LHsType pass -> HsType pass
+ Development.IDE.GHC.Compat: HsOverLabel :: XOverLabel p -> Maybe (IdP p) -> FastString -> HsExpr p
+ Development.IDE.GHC.Compat: HsOverLit :: XOverLitE p -> HsOverLit p -> HsExpr p
+ Development.IDE.GHC.Compat: HsPar :: XPar p -> LHsExpr p -> HsExpr p
+ Development.IDE.GHC.Compat: HsParTy :: XParTy pass -> LHsType pass -> HsType pass
+ Development.IDE.GHC.Compat: HsProc :: XProc p -> LPat p -> LHsCmdTop p -> HsExpr p
+ Development.IDE.GHC.Compat: HsQTvs :: XHsQTvs pass -> [LHsTyVarBndr pass] -> LHsQTyVars pass
+ Development.IDE.GHC.Compat: HsQTvsRn :: [Name] -> NameSet -> HsQTvsRn
+ Development.IDE.GHC.Compat: HsQualTy :: XQualTy pass -> LHsContext pass -> LHsType pass -> HsType pass
+ Development.IDE.GHC.Compat: HsQuasiQuote :: XQuasiQuote id -> IdP id -> IdP id -> SrcSpan -> FastString -> HsSplice id
+ Development.IDE.GHC.Compat: HsRat :: XHsRat x -> FractionalLit -> Type -> HsLit x
+ Development.IDE.GHC.Compat: HsRecField :: Located id -> arg -> Bool -> HsRecField' id arg
+ Development.IDE.GHC.Compat: HsRecFields :: [LHsRecField p arg] -> Maybe Int -> HsRecFields p arg
+ Development.IDE.GHC.Compat: HsRecFld :: XRecFld p -> AmbiguousFieldOcc p -> HsExpr p
+ Development.IDE.GHC.Compat: HsRecTy :: XRecTy pass -> [LConDeclField pass] -> HsType pass
+ Development.IDE.GHC.Compat: HsRnBracketOut :: XRnBracketOut p -> HsBracket GhcRn -> [PendingRnSplice] -> HsExpr p
+ Development.IDE.GHC.Compat: HsRule :: XHsRule pass -> Located (SourceText, RuleName) -> Activation -> [LRuleBndr pass] -> Located (HsExpr pass) -> Located (HsExpr pass) -> RuleDecl pass
+ Development.IDE.GHC.Compat: HsRuleRn :: NameSet -> NameSet -> HsRuleRn
+ Development.IDE.GHC.Compat: HsRules :: XCRuleDecls pass -> SourceText -> [LRuleDecl pass] -> RuleDecls pass
+ Development.IDE.GHC.Compat: HsSCC :: XSCC p -> SourceText -> StringLiteral -> LHsExpr p -> HsExpr p
+ Development.IDE.GHC.Compat: HsSpliceE :: XSpliceE p -> HsSplice p -> HsExpr p
+ Development.IDE.GHC.Compat: HsSpliceTy :: XSpliceTy pass -> HsSplice pass -> HsType pass
+ Development.IDE.GHC.Compat: HsSpliced :: XSpliced id -> ThModFinalizers -> HsSplicedThing id -> HsSplice id
+ Development.IDE.GHC.Compat: HsSplicedExpr :: HsExpr id -> HsSplicedThing id
+ Development.IDE.GHC.Compat: HsSplicedPat :: Pat id -> HsSplicedThing id
+ Development.IDE.GHC.Compat: HsSplicedTy :: HsType id -> HsSplicedThing id
+ Development.IDE.GHC.Compat: HsSrcBang :: SourceText -> SrcUnpackedness -> SrcStrictness -> HsSrcBang
+ Development.IDE.GHC.Compat: HsStarTy :: XStarTy pass -> Bool -> HsType pass
+ Development.IDE.GHC.Compat: HsStatic :: XStatic p -> LHsExpr p -> HsExpr p
+ Development.IDE.GHC.Compat: HsStrTy :: SourceText -> FastString -> HsTyLit
+ Development.IDE.GHC.Compat: HsStrict :: HsImplBang
+ Development.IDE.GHC.Compat: HsString :: XHsString x -> FastString -> HsLit x
+ Development.IDE.GHC.Compat: HsStringPrim :: XHsStringPrim x -> ByteString -> HsLit x
+ Development.IDE.GHC.Compat: HsSumTy :: XSumTy pass -> [LHsType pass] -> HsType pass
+ Development.IDE.GHC.Compat: HsTcBracketOut :: XTcBracketOut p -> HsBracket GhcRn -> [PendingTcSplice] -> HsExpr p
+ Development.IDE.GHC.Compat: HsTick :: XTick p -> Tickish (IdP p) -> LHsExpr p -> HsExpr p
+ Development.IDE.GHC.Compat: HsTickPragma :: XTickPragma p -> SourceText -> (StringLiteral, (Int, Int), (Int, Int)) -> ((SourceText, SourceText), (SourceText, SourceText)) -> LHsExpr p -> HsExpr p
+ Development.IDE.GHC.Compat: HsTupleTy :: XTupleTy pass -> HsTupleSort -> [LHsType pass] -> HsType pass
+ Development.IDE.GHC.Compat: HsTyLit :: XTyLit pass -> HsTyLit -> HsType pass
+ Development.IDE.GHC.Compat: HsTyVar :: XTyVar pass -> Promoted -> Located (IdP pass) -> HsType pass
+ Development.IDE.GHC.Compat: HsTypedSplice :: XTypedSplice id -> SpliceDecoration -> IdP id -> LHsExpr id -> HsSplice id
+ Development.IDE.GHC.Compat: HsUnboundVar :: XUnboundVar p -> UnboundVar -> HsExpr p
+ Development.IDE.GHC.Compat: HsUnboxedTuple :: HsTupleSort
+ Development.IDE.GHC.Compat: HsUnpack :: Maybe Coercion -> HsImplBang
+ Development.IDE.GHC.Compat: HsUntypedSplice :: XUntypedSplice id -> SpliceDecoration -> IdP id -> LHsExpr id -> HsSplice id
+ Development.IDE.GHC.Compat: HsValBinds :: XHsValBinds idL idR -> HsValBindsLR idL idR -> HsLocalBindsLR idL idR
+ Development.IDE.GHC.Compat: HsVar :: XVar p -> Located (IdP p) -> HsExpr p
+ Development.IDE.GHC.Compat: HsWC :: XHsWC pass thing -> thing -> HsWildCardBndrs pass thing
+ Development.IDE.GHC.Compat: HsWildCardTy :: XWildCardTy pass -> HsType pass
+ Development.IDE.GHC.Compat: HsWord64Prim :: XHsWord64Prim x -> Integer -> HsLit x
+ Development.IDE.GHC.Compat: HsWordPrim :: XHsWordPrim x -> Integer -> HsLit x
+ Development.IDE.GHC.Compat: HsWrap :: XWrap p -> HsWrapper -> HsExpr p -> HsExpr p
+ Development.IDE.GHC.Compat: HscAsm :: HscTarget
+ Development.IDE.GHC.Compat: HscC :: HscTarget
+ Development.IDE.GHC.Compat: HscInterpreted :: HscTarget
+ Development.IDE.GHC.Compat: HscLlvm :: HscTarget
+ Development.IDE.GHC.Compat: HscNothing :: HscTarget
+ Development.IDE.GHC.Compat: IEDoc :: XIEDoc pass -> HsDocString -> IE pass
+ Development.IDE.GHC.Compat: IEDocNamed :: XIEDocNamed pass -> String -> IE pass
+ Development.IDE.GHC.Compat: IEGroup :: XIEGroup pass -> Int -> HsDocString -> IE pass
+ Development.IDE.GHC.Compat: IEModuleContents :: XIEModuleContents pass -> Located ModuleName -> IE pass
+ Development.IDE.GHC.Compat: IEName :: Located name -> IEWrappedName name
+ Development.IDE.GHC.Compat: IEPattern :: Located name -> IEWrappedName name
+ Development.IDE.GHC.Compat: IEThing :: IEType -> ContextInfo
+ Development.IDE.GHC.Compat: IEThingAbs :: XIEThingAbs pass -> LIEWrappedName (IdP pass) -> IE pass
+ Development.IDE.GHC.Compat: IEType :: Located name -> IEWrappedName name
+ Development.IDE.GHC.Compat: IEVar :: XIEVar pass -> LIEWrappedName (IdP pass) -> IE pass
+ Development.IDE.GHC.Compat: IEWildcard :: Int -> IEWildcard
+ Development.IDE.GHC.Compat: IIDecl :: ImportDecl GhcPs -> InteractiveImport
+ Development.IDE.GHC.Compat: IIModule :: ModuleName -> InteractiveImport
+ Development.IDE.GHC.Compat: IPBind :: XCIPBind id -> Either (Located HsIPName) (IdP id) -> LHsExpr id -> IPBind id
+ Development.IDE.GHC.Compat: IPBinds :: XIPBinds id -> [LIPBind id] -> HsIPBinds id
+ Development.IDE.GHC.Compat: IdSig :: XIdSig pass -> Id -> Sig pass
+ Development.IDE.GHC.Compat: IdentifierDetails :: Maybe a -> Set ContextInfo -> IdentifierDetails a
+ Development.IDE.GHC.Compat: IfAlt :: HsMatchContext id
+ Development.IDE.GHC.Compat: ImplicitBidirectional :: HsPatSynDir id
+ Development.IDE.GHC.Compat: ImplicitSplice :: SpliceExplicitFlag
+ Development.IDE.GHC.Compat: Import :: IEType
+ Development.IDE.GHC.Compat: ImportAs :: IEType
+ Development.IDE.GHC.Compat: ImportDecl :: XCImportDecl pass -> SourceText -> Located ModuleName -> Maybe StringLiteral -> Bool -> Bool -> Bool -> Bool -> Maybe (Located ModuleName) -> Maybe (Bool, Located [LIE pass]) -> ImportDecl pass
+ Development.IDE.GHC.Compat: ImportHiding :: IEType
+ Development.IDE.GHC.Compat: Infix :: LexicalFixity
+ Development.IDE.GHC.Compat: InfixCon :: arg -> arg -> HsConDetails arg rec
+ Development.IDE.GHC.Compat: InfixL :: FixityDirection
+ Development.IDE.GHC.Compat: InfixN :: FixityDirection
+ Development.IDE.GHC.Compat: InfixR :: FixityDirection
+ Development.IDE.GHC.Compat: InjectivityAnn :: Located (IdP pass) -> [Located (IdP pass)] -> InjectivityAnn pass
+ Development.IDE.GHC.Compat: InlineSig :: XInlineSig pass -> Located (IdP pass) -> InlinePragma -> Sig pass
+ Development.IDE.GHC.Compat: InstDec :: DeclType
+ Development.IDE.GHC.Compat: InstallationError :: String -> GhcException
+ Development.IDE.GHC.Compat: InstanceBind :: BindType
+ Development.IDE.GHC.Compat: InteractiveName :: GetDocsFailure
+ Development.IDE.GHC.Compat: IsDefaultMethod :: TcSpecPrags
+ Development.IDE.GHC.Compat: KindSig :: XCKindSig pass -> LHsKind pass -> FamilyResultSig pass
+ Development.IDE.GHC.Compat: KindedTyVar :: XKindedTyVar pass -> Located (IdP pass) -> LHsKind pass -> HsTyVarBndr pass
+ Development.IDE.GHC.Compat: L :: l -> e -> GenLocated l e
+ Development.IDE.GHC.Compat: LambdaExpr :: HsMatchContext id
+ Development.IDE.GHC.Compat: LastStmt :: XLastStmt idL idR body -> body -> Bool -> SyntaxExpr idR -> StmtLR idL idR body
+ Development.IDE.GHC.Compat: LazyPat :: XLazyPat p -> LPat p -> Pat p
+ Development.IDE.GHC.Compat: LetStmt :: XLetStmt idL idR body -> LHsLocalBindsLR idL idR -> StmtLR idL idR body
+ Development.IDE.GHC.Compat: LinkBinary :: GhcLink
+ Development.IDE.GHC.Compat: LinkDynLib :: GhcLink
+ Development.IDE.GHC.Compat: LinkInMemory :: GhcLink
+ Development.IDE.GHC.Compat: LinkStaticLib :: GhcLink
+ Development.IDE.GHC.Compat: ListComp :: HsStmtContext id
+ Development.IDE.GHC.Compat: ListPat :: XListPat p -> [LPat p] -> Pat p
+ Development.IDE.GHC.Compat: ListPatTc :: Type -> Maybe (Type, SyntaxExpr GhcTc) -> ListPatTc
+ Development.IDE.GHC.Compat: LitPat :: XLitPat p -> HsLit p -> Pat p
+ Development.IDE.GHC.Compat: LoadAllTargets :: LoadHowMuch
+ Development.IDE.GHC.Compat: LoadDependenciesOf :: ModuleName -> LoadHowMuch
+ Development.IDE.GHC.Compat: LoadUpTo :: ModuleName -> LoadHowMuch
+ Development.IDE.GHC.Compat: LocalScope :: Span -> Scope
+ Development.IDE.GHC.Compat: MDoExpr :: HsStmtContext id
+ Development.IDE.GHC.Compat: MG :: XMG p body -> Located [LMatch p body] -> Origin -> MatchGroup p body
+ Development.IDE.GHC.Compat: MarkedStrict :: StrictnessMark
+ Development.IDE.GHC.Compat: Match :: XCMatch p body -> HsMatchContext (NameOrRdrName (IdP p)) -> [LPat p] -> GRHSs p body -> Match p body
+ Development.IDE.GHC.Compat: MatchBind :: ContextInfo
+ Development.IDE.GHC.Compat: MatchGroupTc :: [Type] -> Type -> MatchGroupTc
+ Development.IDE.GHC.Compat: MinimalSig :: XMinimalSig pass -> SourceText -> LBooleanFormula (Located (IdP pass)) -> Sig pass
+ Development.IDE.GHC.Compat: Missing :: XMissing id -> HsTupArg id
+ Development.IDE.GHC.Compat: MkDepend :: GhcMode
+ Development.IDE.GHC.Compat: ModBreaks :: ForeignRef BreakArray -> !Array BreakIndex SrcSpan -> !Array BreakIndex [OccName] -> !Array BreakIndex [String] -> !Array BreakIndex (RemotePtr CostCentre) -> IntMap CgBreakInfo -> ModBreaks
+ Development.IDE.GHC.Compat: ModIface :: !Module -> !Maybe Module -> !Fingerprint -> !Fingerprint -> !Fingerprint -> !Fingerprint -> !Fingerprint -> !Fingerprint -> !WhetherHasOrphans -> !WhetherHasFamInst -> !HscSource -> Dependencies -> [Usage] -> ![IfaceExport] -> !Fingerprint -> !Bool -> [(OccName, Fixity)] -> Warnings -> [IfaceAnnotation] -> [(Fingerprint, IfaceDecl)] -> !Maybe GlobalRdrEnv -> [IfaceClsInst] -> [IfaceFamInst] -> [IfaceRule] -> !Fingerprint -> (OccName -> Maybe WarningTxt) -> (OccName -> Maybe Fixity) -> (OccName -> Maybe (OccName, Fingerprint)) -> !AnyHpcUsage -> !IfaceTrustInfo -> !Bool -> [IfaceCompleteMatch] -> Maybe HsDocString -> DeclDocMap -> ArgDocMap -> ModIface
+ Development.IDE.GHC.Compat: ModSummary :: Module -> HscSource -> ModLocation -> UTCTime -> Maybe UTCTime -> Maybe UTCTime -> [(Maybe FastString, Located ModuleName)] -> [(Maybe FastString, Located ModuleName)] -> Maybe HsParsedModule -> FilePath -> DynFlags -> Maybe StringBuffer -> ModSummary
+ Development.IDE.GHC.Compat: ModuleAnnProvenance :: AnnProvenance name
+ Development.IDE.GHC.Compat: ModuleScope :: Scope
+ Development.IDE.GHC.Compat: MonadComp :: HsStmtContext id
+ Development.IDE.GHC.Compat: NCU :: (forall c. () => (NameCache -> (NameCache, c)) -> IO c) -> NameCacheUpdater
+ Development.IDE.GHC.Compat: NHsCoreTy :: Type -> NewHsTypeX
+ Development.IDE.GHC.Compat: NPat :: XNPat p -> Located (HsOverLit p) -> Maybe (SyntaxExpr p) -> SyntaxExpr p -> Pat p
+ Development.IDE.GHC.Compat: NPatBindTc :: NameSet -> Type -> NPatBindTc
+ Development.IDE.GHC.Compat: NPlusKPat :: XNPlusKPat p -> Located (IdP p) -> Located (HsOverLit p) -> HsOverLit p -> SyntaxExpr p -> SyntaxExpr p -> Pat p
+ Development.IDE.GHC.Compat: NValBinds :: [(RecFlag, LHsBinds idL)] -> [LSig GhcRn] -> NHsValBindsLR idL
+ Development.IDE.GHC.Compat: NameHasNoModule :: Name -> GetDocsFailure
+ Development.IDE.GHC.Compat: NegApp :: XNegApp p -> LHsExpr p -> SyntaxExpr p -> HsExpr p
+ Development.IDE.GHC.Compat: NewType :: NewOrData
+ Development.IDE.GHC.Compat: NewtypeStrategy :: DerivStrategy pass
+ Development.IDE.GHC.Compat: NoDocsInIface :: Module -> Bool -> GetDocsFailure
+ Development.IDE.GHC.Compat: NoExt :: NoExt
+ Development.IDE.GHC.Compat: NoIEWildcard :: IEWildcard
+ Development.IDE.GHC.Compat: NoLink :: GhcLink
+ Development.IDE.GHC.Compat: NoParens :: SpliceDecoration
+ Development.IDE.GHC.Compat: NoScope :: Scope
+ Development.IDE.GHC.Compat: NoSig :: XNoSig pass -> FamilyResultSig pass
+ Development.IDE.GHC.Compat: NoSrcStrict :: SrcStrictness
+ Development.IDE.GHC.Compat: NoSrcUnpack :: SrcUnpackedness
+ Development.IDE.GHC.Compat: Node :: NodeInfo a -> Span -> [HieAST a] -> HieAST a
+ Development.IDE.GHC.Compat: NodeInfo :: Set (FastString, FastString) -> [a] -> NodeIdentifiers a -> NodeInfo a
+ Development.IDE.GHC.Compat: NotMarkedStrict :: StrictnessMark
+ Development.IDE.GHC.Compat: NotPromoted :: Promoted
+ Development.IDE.GHC.Compat: OneShot :: GhcMode
+ Development.IDE.GHC.Compat: OpApp :: XOpApp p -> LHsExpr p -> LHsExpr p -> LHsExpr p -> HsExpr p
+ Development.IDE.GHC.Compat: OpenTypeFamily :: FamilyInfo pass
+ Development.IDE.GHC.Compat: Opt_AbstractRefHoleFits :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_AlignmentSanitisation :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_AsmShortcutting :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_AutoLinkPackages :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_AutoSccsOnIndividualCafs :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_BreakOnError :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_BreakOnException :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_BuildDynamicToo :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_BuildingCabalPackage :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_CSE :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_CallArity :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_CaseFolding :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_CaseMerge :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_CatchBottoms :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_CmmElimCommonBlocks :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_CmmSink :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_CprAnal :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_CrossModuleSpecialise :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_D_dump_minimal_imports :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_D_faststring_stats :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_DeferOutOfScopeVariables :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_DeferTypeErrors :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_DeferTypedHoles :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_DiagnosticsShowCaret :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_DictsCheap :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_DictsStrict :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_DistrustAllPackages :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_DmdTxDictSel :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_DoAnnotationLinting :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_DoAsmLinting :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_DoCmmLinting :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_DoCoreLinting :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_DoEtaReduction :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_DoLambdaEtaExpansion :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_DoStgLinting :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_DumpToFile :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_EagerBlackHoling :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_EmbedManifest :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_EnableRewriteRules :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_ErrorSpans :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_ExcessPrecision :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_Exitification :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_ExposeAllUnfoldings :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_ExternalDynamicRefs :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_ExternalInterpreter :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_FastLlvm :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_FlatCache :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_FloatIn :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_ForceRecomp :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_FullLaziness :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_FunToThunk :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_G_NoOptCoercion :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_G_NoStateHack :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_GenManifest :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_GhciHistory :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_GhciLeakCheck :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_GhciSandbox :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_Haddock :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_HaddockOptions :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_HelpfulErrors :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_HexWordLiterals :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_HideAllPackages :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_HideAllPluginPackages :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_HideSourcePaths :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_Hpc :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_IgnoreAsserts :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_IgnoreDotGhci :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_IgnoreHpcChanges :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_IgnoreInterfacePragmas :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_IgnoreOptimChanges :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_ImplicitImportQualified :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_IrrefutableTuples :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_KeepHcFiles :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_KeepHiDiffs :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_KeepHiFiles :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_KeepLlvmFiles :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_KeepOFiles :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_KeepRawTokenStream :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_KeepSFiles :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_KeepTmpFiles :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_KillAbsence :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_KillOneShot :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_LateDmdAnal :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_LateSpecialise :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_LiberateCase :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_LlvmFillUndefWithGarbage :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_LlvmPassVectorsInRegisters :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_LlvmTBAA :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_LocalGhciHistory :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_Loopification :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_NoHsMain :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_NoIt :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_NoLlvmMangler :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_NumConstantFolding :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_OmitInterfacePragmas :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_OmitYields :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_OptimalApplicativeDo :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_PIC :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_PICExecutable :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_PIE :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_PackageTrust :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_PedanticBottoms :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_Pp :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_PprCaseAsLet :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_PprShowTicks :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_PrintBindContents :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_PrintBindResult :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_PrintEqualityRelations :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_PrintEvldWithShow :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_PrintExpandedSynonyms :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_PrintExplicitCoercions :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_PrintExplicitForalls :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_PrintExplicitKinds :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_PrintExplicitRuntimeReps :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_PrintPotentialInstances :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_PrintTypecheckerElaboration :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_PrintUnicodeSyntax :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_ProfCountEntries :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_RPath :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_RegsGraph :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_RegsIterative :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_RelativeDynlibPaths :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_SccProfilingOn :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_SharedImplib :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_ShowHoleConstraints :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_ShowLoadedModules :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_ShowMatchesOfHoleFits :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_ShowProvOfHoleFits :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_ShowTypeAppOfHoleFits :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_ShowTypeAppVarsOfHoleFits :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_ShowTypeOfHoleFits :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_ShowValidHoleFits :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_ShowWarnGroups :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_SimplPreInlining :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_SingleLibFolder :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_SolveConstantDicts :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_SortBySizeHoleFits :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_SortBySubsumHoleFits :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_SortValidHoleFits :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_SpecConstr :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_SpecConstrKeen :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_Specialise :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_SpecialiseAggressively :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_SplitObjs :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_SplitSections :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_StaticArgumentTransformation :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_StgCSE :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_StgStats :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_Strictness :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_SuppressCoercions :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_SuppressIdInfo :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_SuppressModulePrefixes :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_SuppressStgFreeVars :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_SuppressTicks :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_SuppressTimestamps :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_SuppressTypeApplications :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_SuppressTypeSignatures :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_SuppressUnfoldings :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_SuppressUniques :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_SuppressVarKinds :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_Ticky :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_Ticky_Allocd :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_Ticky_Dyn_Thunk :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_Ticky_LNE :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_UnboxSmallStrictFields :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_UnboxStrictFields :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_UnclutterValidHoleFits :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_VersionMacros :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_WarnIsError :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_WholeArchiveHsLibs :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_WorkerWrapper :: GeneralFlag
+ Development.IDE.GHC.Compat: Opt_WriteInterface :: GeneralFlag
+ Development.IDE.GHC.Compat: OutOfScope :: OccName -> GlobalRdrEnv -> UnboundVar
+ Development.IDE.GHC.Compat: OverLit :: XOverLit p -> OverLitVal -> HsExpr p -> HsOverLit p
+ Development.IDE.GHC.Compat: OverLitTc :: Bool -> Type -> OverLitTc
+ Development.IDE.GHC.Compat: Panic :: String -> GhcException
+ Development.IDE.GHC.Compat: ParPat :: XParPat p -> LPat p -> Pat p
+ Development.IDE.GHC.Compat: ParStmt :: XParStmt idL idR body -> [ParStmtBlock idL idR] -> HsExpr idR -> SyntaxExpr idR -> StmtLR idL idR body
+ Development.IDE.GHC.Compat: ParStmtBlock :: XParStmtBlock idL idR -> [ExprLStmt idL] -> [IdP idR] -> SyntaxExpr idR -> ParStmtBlock idL idR
+ Development.IDE.GHC.Compat: ParStmtCtxt :: HsStmtContext id -> HsStmtContext id
+ Development.IDE.GHC.Compat: Parsed :: Pass
+ Development.IDE.GHC.Compat: ParsedModule :: ModSummary -> ParsedSource -> [FilePath] -> ApiAnns -> ParsedModule
+ Development.IDE.GHC.Compat: PatBind :: XPatBind idL idR -> LPat idL -> GRHSs idR (LHsExpr idR) -> ([Tickish Id], [[Tickish Id]]) -> HsBindLR idL idR
+ Development.IDE.GHC.Compat: PatBindGuards :: HsMatchContext id
+ Development.IDE.GHC.Compat: PatBindRhs :: HsMatchContext id
+ Development.IDE.GHC.Compat: PatBr :: XPatBr p -> LPat p -> HsBracket p
+ Development.IDE.GHC.Compat: PatGuard :: HsMatchContext id -> HsStmtContext id
+ Development.IDE.GHC.Compat: PatSyn :: HsMatchContext id
+ Development.IDE.GHC.Compat: PatSynDec :: DeclType
+ Development.IDE.GHC.Compat: PatSynSig :: XPatSynSig pass -> [Located (IdP pass)] -> LHsSigType pass -> Sig pass
+ Development.IDE.GHC.Compat: PatternBind :: Scope -> Scope -> Maybe Span -> ContextInfo
+ Development.IDE.GHC.Compat: PendingRnSplice :: UntypedSpliceFlavour -> SplicePointName -> LHsExpr GhcRn -> PendingRnSplice
+ Development.IDE.GHC.Compat: PendingTcSplice :: SplicePointName -> LHsExpr GhcTc -> PendingTcSplice
+ Development.IDE.GHC.Compat: PprPanic :: String -> SDoc -> GhcException
+ Development.IDE.GHC.Compat: PprProgramError :: String -> SDoc -> GhcException
+ Development.IDE.GHC.Compat: PprSorry :: String -> SDoc -> GhcException
+ Development.IDE.GHC.Compat: Prefix :: LexicalFixity
+ Development.IDE.GHC.Compat: PrefixCon :: [arg] -> HsConDetails arg rec
+ Development.IDE.GHC.Compat: Present :: XPresent id -> LHsExpr id -> HsTupArg id
+ Development.IDE.GHC.Compat: ProcExpr :: HsMatchContext id
+ Development.IDE.GHC.Compat: ProgramError :: String -> GhcException
+ Development.IDE.GHC.Compat: Promoted :: Promoted
+ Development.IDE.GHC.Compat: Qual :: ModuleName -> OccName -> RdrName
+ Development.IDE.GHC.Compat: RealSrcLoc :: {-# UNPACK #-} !RealSrcLoc -> SrcLoc
+ Development.IDE.GHC.Compat: RealSrcSpan :: !RealSrcSpan -> SrcSpan
+ Development.IDE.GHC.Compat: RecCon :: rec -> HsConDetails arg rec
+ Development.IDE.GHC.Compat: RecField :: RecFieldContext -> Maybe Span -> ContextInfo
+ Development.IDE.GHC.Compat: RecFieldAssign :: RecFieldContext
+ Development.IDE.GHC.Compat: RecFieldDecl :: RecFieldContext
+ Development.IDE.GHC.Compat: RecFieldMatch :: RecFieldContext
+ Development.IDE.GHC.Compat: RecFieldOcc :: RecFieldContext
+ Development.IDE.GHC.Compat: RecStmt :: XRecStmt idL idR body -> [LStmtLR idL idR body] -> [IdP idR] -> [IdP idR] -> SyntaxExpr idR -> SyntaxExpr idR -> SyntaxExpr idR -> StmtLR idL idR body
+ Development.IDE.GHC.Compat: RecStmtTc :: Type -> [PostTcExpr] -> [PostTcExpr] -> Type -> RecStmtTc
+ Development.IDE.GHC.Compat: RecUpd :: HsMatchContext id
+ Development.IDE.GHC.Compat: RecordCon :: XRecordCon p -> Located (IdP p) -> HsRecordBinds p -> HsExpr p
+ Development.IDE.GHC.Compat: RecordConTc :: ConLike -> PostTcExpr -> RecordConTc
+ Development.IDE.GHC.Compat: RecordPatSynField :: a -> a -> RecordPatSynField a
+ Development.IDE.GHC.Compat: RecordUpd :: XRecordUpd p -> LHsExpr p -> [LHsRecUpdField p] -> HsExpr p
+ Development.IDE.GHC.Compat: RecordUpdTc :: [ConLike] -> [Type] -> [Type] -> HsWrapper -> RecordUpdTc
+ Development.IDE.GHC.Compat: RegularBind :: BindType
+ Development.IDE.GHC.Compat: Renamed :: Pass
+ Development.IDE.GHC.Compat: ResolvedScopes :: [Scope] -> TyVarScope
+ Development.IDE.GHC.Compat: Resume :: String -> ForeignRef (ResumeContext [HValueRef]) -> ([TyThing], GlobalRdrEnv) -> [Id] -> ForeignHValue -> Maybe BreakInfo -> SrcSpan -> String -> RemotePtr CostCentreStack -> [History] -> Int -> Resume
+ Development.IDE.GHC.Compat: RoleAnnotD :: XRoleAnnotD p -> RoleAnnotDecl p -> HsDecl p
+ Development.IDE.GHC.Compat: RoleAnnotDecl :: XCRoleAnnotDecl pass -> Located (IdP pass) -> [Located (Maybe Role)] -> RoleAnnotDecl pass
+ Development.IDE.GHC.Compat: Roll :: HieType HieTypeFix -> HieTypeFix
+ Development.IDE.GHC.Compat: RuleBndr :: XCRuleBndr pass -> Located (IdP pass) -> RuleBndr pass
+ Development.IDE.GHC.Compat: RuleBndrSig :: XRuleBndrSig pass -> Located (IdP pass) -> LHsSigWcType pass -> RuleBndr pass
+ Development.IDE.GHC.Compat: RuleD :: XRuleD p -> RuleDecls p -> HsDecl p
+ Development.IDE.GHC.Compat: RunAndLogSteps :: SingleStep
+ Development.IDE.GHC.Compat: RunToCompletion :: SingleStep
+ Development.IDE.GHC.Compat: SCCFunSig :: XSCCFunSig pass -> SourceText -> Located (IdP pass) -> Maybe (Located StringLiteral) -> Sig pass
+ Development.IDE.GHC.Compat: SectionL :: XSectionL p -> LHsExpr p -> LHsExpr p -> HsExpr p
+ Development.IDE.GHC.Compat: SectionR :: XSectionR p -> LHsExpr p -> LHsExpr p -> HsExpr p
+ Development.IDE.GHC.Compat: SevDump :: Severity
+ Development.IDE.GHC.Compat: SevError :: Severity
+ Development.IDE.GHC.Compat: SevFatal :: Severity
+ Development.IDE.GHC.Compat: SevInfo :: Severity
+ Development.IDE.GHC.Compat: SevInteractive :: Severity
+ Development.IDE.GHC.Compat: SevOutput :: Severity
+ Development.IDE.GHC.Compat: SevWarning :: Severity
+ Development.IDE.GHC.Compat: Sf_None :: SafeHaskellMode
+ Development.IDE.GHC.Compat: Sf_Safe :: SafeHaskellMode
+ Development.IDE.GHC.Compat: Sf_Trustworthy :: SafeHaskellMode
+ Development.IDE.GHC.Compat: Sf_Unsafe :: SafeHaskellMode
+ Development.IDE.GHC.Compat: SigPat :: XSigPat p -> LPat p -> Pat p
+ Development.IDE.GHC.Compat: Signal :: Int -> GhcException
+ Development.IDE.GHC.Compat: SingleStep :: SingleStep
+ Development.IDE.GHC.Compat: Sorry :: String -> GhcException
+ Development.IDE.GHC.Compat: SpecInstSig :: XSpecInstSig pass -> SourceText -> LHsSigType pass -> Sig pass
+ Development.IDE.GHC.Compat: SpecPrag :: Id -> HsWrapper -> InlinePragma -> TcSpecPrag
+ Development.IDE.GHC.Compat: SpecPrags :: [LTcSpecPrag] -> TcSpecPrags
+ Development.IDE.GHC.Compat: SpecSig :: XSpecSig pass -> Located (IdP pass) -> [LHsSigType pass] -> InlinePragma -> Sig pass
+ Development.IDE.GHC.Compat: SpliceD :: XSpliceD p -> SpliceDecl p -> HsDecl p
+ Development.IDE.GHC.Compat: SpliceDecl :: XSpliceDecl p -> Located (HsSplice p) -> SpliceExplicitFlag -> SpliceDecl p
+ Development.IDE.GHC.Compat: SplicePat :: XSplicePat p -> HsSplice p -> Pat p
+ Development.IDE.GHC.Compat: SrcLazy :: SrcStrictness
+ Development.IDE.GHC.Compat: SrcNoUnpack :: SrcUnpackedness
+ Development.IDE.GHC.Compat: SrcStrict :: SrcStrictness
+ Development.IDE.GHC.Compat: SrcUnpack :: SrcUnpackedness
+ Development.IDE.GHC.Compat: StmtCtxt :: HsStmtContext id -> HsMatchContext id
+ Development.IDE.GHC.Compat: StockStrategy :: DerivStrategy pass
+ Development.IDE.GHC.Compat: Succeeded :: SuccessFlag
+ Development.IDE.GHC.Compat: SumPat :: XSumPat p -> LPat p -> ConTag -> Arity -> Pat p
+ Development.IDE.GHC.Compat: SynDec :: DeclType
+ Development.IDE.GHC.Compat: SynDecl :: XSynDecl pass -> Located (IdP pass) -> LHsQTyVars pass -> LexicalFixity -> LHsType pass -> TyClDecl pass
+ Development.IDE.GHC.Compat: SyntaxExpr :: HsExpr p -> [HsWrapper] -> HsWrapper -> SyntaxExpr p
+ Development.IDE.GHC.Compat: TExpBr :: XTExpBr p -> LHsExpr p -> HsBracket p
+ Development.IDE.GHC.Compat: TM_Default :: TcRnExprMode
+ Development.IDE.GHC.Compat: TM_Inst :: TcRnExprMode
+ Development.IDE.GHC.Compat: TM_NoInst :: TcRnExprMode
+ Development.IDE.GHC.Compat: Target :: TargetId -> Bool -> Maybe (StringBuffer, UTCTime) -> Target
+ Development.IDE.GHC.Compat: TargetFile :: FilePath -> Maybe Phase -> TargetId
+ Development.IDE.GHC.Compat: TargetModule :: ModuleName -> TargetId
+ Development.IDE.GHC.Compat: ThModFinalizers :: [ForeignRef (Q ())] -> ThModFinalizers
+ Development.IDE.GHC.Compat: ThPatQuote :: HsMatchContext id
+ Development.IDE.GHC.Compat: ThPatSplice :: HsMatchContext id
+ Development.IDE.GHC.Compat: ThenForm :: TransForm
+ Development.IDE.GHC.Compat: TransStmt :: XTransStmt idL idR body -> TransForm -> [ExprLStmt idL] -> [(IdP idR, IdP idR)] -> LHsExpr idR -> Maybe (LHsExpr idR) -> SyntaxExpr idR -> SyntaxExpr idR -> HsExpr idR -> StmtLR idL idR body
+ Development.IDE.GHC.Compat: TransStmtCtxt :: HsStmtContext id -> HsStmtContext id
+ Development.IDE.GHC.Compat: TrueExprHole :: OccName -> UnboundVar
+ Development.IDE.GHC.Compat: TuplePat :: XTuplePat p -> [LPat p] -> Boxity -> Pat p
+ Development.IDE.GHC.Compat: TyClGroup :: XCTyClGroup pass -> [LTyClDecl pass] -> [LRoleAnnotDecl pass] -> [LInstDecl pass] -> TyClGroup pass
+ Development.IDE.GHC.Compat: TyDecl :: ContextInfo
+ Development.IDE.GHC.Compat: TyFamInstD :: XTyFamInstD pass -> TyFamInstDecl pass -> InstDecl pass
+ Development.IDE.GHC.Compat: TyFamInstDecl :: TyFamInstEqn pass -> TyFamInstDecl pass
+ Development.IDE.GHC.Compat: TyVarBind :: Scope -> TyVarScope -> ContextInfo
+ Development.IDE.GHC.Compat: TyVarSig :: XTyVarSig pass -> LHsTyVarBndr pass -> FamilyResultSig pass
+ Development.IDE.GHC.Compat: TypBr :: XTypBr p -> LHsType p -> HsBracket p
+ Development.IDE.GHC.Compat: TypeAnnProvenance :: Located name -> AnnProvenance name
+ Development.IDE.GHC.Compat: Typechecked :: Pass
+ Development.IDE.GHC.Compat: TypecheckedModule :: ParsedModule -> Maybe RenamedSource -> TypecheckedSource -> ModuleInfo -> (TcGblEnv, ModDetails) -> TypecheckedModule
+ Development.IDE.GHC.Compat: Unambiguous :: XUnambiguous pass -> Located RdrName -> AmbiguousFieldOcc pass
+ Development.IDE.GHC.Compat: UnhelpfulLoc :: FastString -> SrcLoc
+ Development.IDE.GHC.Compat: UnhelpfulSpan :: !FastString -> SrcSpan
+ Development.IDE.GHC.Compat: Unidirectional :: HsPatSynDir id
+ Development.IDE.GHC.Compat: Unqual :: OccName -> RdrName
+ Development.IDE.GHC.Compat: UnresolvedScope :: [Name] -> Maybe Span -> TyVarScope
+ Development.IDE.GHC.Compat: UntypedDeclSplice :: UntypedSpliceFlavour
+ Development.IDE.GHC.Compat: UntypedExpSplice :: UntypedSpliceFlavour
+ Development.IDE.GHC.Compat: UntypedPatSplice :: UntypedSpliceFlavour
+ Development.IDE.GHC.Compat: UntypedTypeSplice :: UntypedSpliceFlavour
+ Development.IDE.GHC.Compat: UsageError :: String -> GhcException
+ Development.IDE.GHC.Compat: Use :: ContextInfo
+ Development.IDE.GHC.Compat: UserTyVar :: XUserTyVar pass -> Located (IdP pass) -> HsTyVarBndr pass
+ Development.IDE.GHC.Compat: ValBind :: BindType -> Scope -> Maybe Span -> ContextInfo
+ Development.IDE.GHC.Compat: ValBinds :: XValBinds idL idR -> LHsBindsLR idL idR -> [LSig idR] -> HsValBindsLR idL idR
+ Development.IDE.GHC.Compat: ValueAnnProvenance :: Located name -> AnnProvenance name
+ Development.IDE.GHC.Compat: VarBind :: XVarBind idL idR -> IdP idL -> LHsExpr idR -> Bool -> HsBindLR idL idR
+ Development.IDE.GHC.Compat: VarBr :: XVarBr p -> Bool -> IdP p -> HsBracket p
+ Development.IDE.GHC.Compat: ViaStrategy :: XViaStrategy pass -> DerivStrategy pass
+ Development.IDE.GHC.Compat: ViewPat :: XViewPat p -> LHsExpr p -> LPat p -> Pat p
+ Development.IDE.GHC.Compat: Warning :: XWarning pass -> [Located (IdP pass)] -> WarningTxt -> WarnDecl pass
+ Development.IDE.GHC.Compat: WarningD :: XWarningD p -> WarnDecls p -> HsDecl p
+ Development.IDE.GHC.Compat: Warnings :: XWarnings pass -> SourceText -> [LWarnDecl pass] -> WarnDecls pass
+ Development.IDE.GHC.Compat: WildPat :: XWildPat p -> Pat p
+ Development.IDE.GHC.Compat: XABExport :: XXABExport p -> ABExport p
+ Development.IDE.GHC.Compat: XAmbiguousFieldOcc :: XXAmbiguousFieldOcc pass -> AmbiguousFieldOcc pass
+ Development.IDE.GHC.Compat: XAnnDecl :: XXAnnDecl pass -> AnnDecl pass
+ Development.IDE.GHC.Compat: XApplicativeArg :: XXApplicativeArg idL -> ApplicativeArg idL
+ Development.IDE.GHC.Compat: XBracket :: XXBracket p -> HsBracket p
+ Development.IDE.GHC.Compat: XClsInstDecl :: XXClsInstDecl pass -> ClsInstDecl pass
+ Development.IDE.GHC.Compat: XCmd :: XXCmd id -> HsCmd id
+ Development.IDE.GHC.Compat: XCmdTop :: XXCmdTop p -> HsCmdTop p
+ Development.IDE.GHC.Compat: XConDecl :: XXConDecl pass -> ConDecl pass
+ Development.IDE.GHC.Compat: XConDeclField :: XXConDeclField pass -> ConDeclField pass
+ Development.IDE.GHC.Compat: XDefaultDecl :: XXDefaultDecl pass -> DefaultDecl pass
+ Development.IDE.GHC.Compat: XDerivDecl :: XXDerivDecl pass -> DerivDecl pass
+ Development.IDE.GHC.Compat: XExpr :: XXExpr p -> HsExpr p
+ Development.IDE.GHC.Compat: XFamEqn :: XXFamEqn pass pats rhs -> FamEqn pass pats rhs
+ Development.IDE.GHC.Compat: XFamilyDecl :: XXFamilyDecl pass -> FamilyDecl pass
+ Development.IDE.GHC.Compat: XFamilyResultSig :: XXFamilyResultSig pass -> FamilyResultSig pass
+ Development.IDE.GHC.Compat: XFieldOcc :: XXFieldOcc pass -> FieldOcc pass
+ Development.IDE.GHC.Compat: XFixitySig :: XXFixitySig pass -> FixitySig pass
+ Development.IDE.GHC.Compat: XForeignDecl :: XXForeignDecl pass -> ForeignDecl pass
+ Development.IDE.GHC.Compat: XGRHS :: XXGRHS p body -> GRHS p body
+ Development.IDE.GHC.Compat: XGRHSs :: XXGRHSs p body -> GRHSs p body
+ Development.IDE.GHC.Compat: XHsBindsLR :: XXHsBindsLR idL idR -> HsBindLR idL idR
+ Development.IDE.GHC.Compat: XHsDataDefn :: XXHsDataDefn pass -> HsDataDefn pass
+ Development.IDE.GHC.Compat: XHsDecl :: XXHsDecl p -> HsDecl p
+ Development.IDE.GHC.Compat: XHsDerivingClause :: XXHsDerivingClause pass -> HsDerivingClause pass
+ Development.IDE.GHC.Compat: XHsGroup :: XXHsGroup p -> HsGroup p
+ Development.IDE.GHC.Compat: XHsIPBinds :: XXHsIPBinds id -> HsIPBinds id
+ Development.IDE.GHC.Compat: XHsImplicitBndrs :: XXHsImplicitBndrs pass thing -> HsImplicitBndrs pass thing
+ Development.IDE.GHC.Compat: XHsLocalBindsLR :: XXHsLocalBindsLR idL idR -> HsLocalBindsLR idL idR
+ Development.IDE.GHC.Compat: XHsType :: XXType pass -> HsType pass
+ Development.IDE.GHC.Compat: XHsWildCardBndrs :: XXHsWildCardBndrs pass thing -> HsWildCardBndrs pass thing
+ Development.IDE.GHC.Compat: XIE :: XXIE pass -> IE pass
+ Development.IDE.GHC.Compat: XIPBind :: XXIPBind id -> IPBind id
+ Development.IDE.GHC.Compat: XImportDecl :: XXImportDecl pass -> ImportDecl pass
+ Development.IDE.GHC.Compat: XInstDecl :: XXInstDecl pass -> InstDecl pass
+ Development.IDE.GHC.Compat: XLHsQTyVars :: XXLHsQTyVars pass -> LHsQTyVars pass
+ Development.IDE.GHC.Compat: XLit :: XXLit x -> HsLit x
+ Development.IDE.GHC.Compat: XMatch :: XXMatch p body -> Match p body
+ Development.IDE.GHC.Compat: XMatchGroup :: XXMatchGroup p body -> MatchGroup p body
+ Development.IDE.GHC.Compat: XOverLit :: XXOverLit p -> HsOverLit p
+ Development.IDE.GHC.Compat: XParStmtBlock :: XXParStmtBlock idL idR -> ParStmtBlock idL idR
+ Development.IDE.GHC.Compat: XPat :: XXPat p -> Pat p
+ Development.IDE.GHC.Compat: XRoleAnnotDecl :: XXRoleAnnotDecl pass -> RoleAnnotDecl pass
+ Development.IDE.GHC.Compat: XRuleBndr :: XXRuleBndr pass -> RuleBndr pass
+ Development.IDE.GHC.Compat: XRuleDecl :: XXRuleDecl pass -> RuleDecl pass
+ Development.IDE.GHC.Compat: XRuleDecls :: XXRuleDecls pass -> RuleDecls pass
+ Development.IDE.GHC.Compat: XSig :: XXSig pass -> Sig pass
+ Development.IDE.GHC.Compat: XSplice :: XXSplice id -> HsSplice id
+ Development.IDE.GHC.Compat: XSpliceDecl :: XXSpliceDecl p -> SpliceDecl p
+ Development.IDE.GHC.Compat: XStmtLR :: XXStmtLR idL idR body -> StmtLR idL idR body
+ Development.IDE.GHC.Compat: XTupArg :: XXTupArg id -> HsTupArg id
+ Development.IDE.GHC.Compat: XTyClDecl :: XXTyClDecl pass -> TyClDecl pass
+ Development.IDE.GHC.Compat: XTyClGroup :: XXTyClGroup pass -> TyClGroup pass
+ Development.IDE.GHC.Compat: XTyVarBndr :: XXTyVarBndr pass -> HsTyVarBndr pass
+ Development.IDE.GHC.Compat: XValBindsLR :: XXValBindsLR idL idR -> HsValBindsLR idL idR
+ Development.IDE.GHC.Compat: XWarnDecl :: XXWarnDecl pass -> WarnDecl pass
+ Development.IDE.GHC.Compat: XWarnDecls :: XXWarnDecls pass -> WarnDecls pass
+ Development.IDE.GHC.Compat: [abe_ext] :: ABExport p -> XABE p
+ Development.IDE.GHC.Compat: [abe_mono] :: ABExport p -> IdP p
+ Development.IDE.GHC.Compat: [abe_poly] :: ABExport p -> IdP p
+ Development.IDE.GHC.Compat: [abe_prags] :: ABExport p -> TcSpecPrags
+ Development.IDE.GHC.Compat: [abe_wrap] :: ABExport p -> HsWrapper
+ Development.IDE.GHC.Compat: [abs_binds] :: HsBindLR idL idR -> LHsBinds idL
+ Development.IDE.GHC.Compat: [abs_ev_binds] :: HsBindLR idL idR -> [TcEvBinds]
+ Development.IDE.GHC.Compat: [abs_ev_vars] :: HsBindLR idL idR -> [EvVar]
+ Development.IDE.GHC.Compat: [abs_exports] :: HsBindLR idL idR -> [ABExport idL]
+ Development.IDE.GHC.Compat: [abs_ext] :: HsBindLR idL idR -> XAbsBinds idL idR
+ Development.IDE.GHC.Compat: [abs_sig] :: HsBindLR idL idR -> Bool
+ Development.IDE.GHC.Compat: [abs_tvs] :: HsBindLR idL idR -> [TyVar]
+ Development.IDE.GHC.Compat: [avx2] :: DynFlags -> Bool
+ Development.IDE.GHC.Compat: [avx512cd] :: DynFlags -> Bool
+ Development.IDE.GHC.Compat: [avx512er] :: DynFlags -> Bool
+ Development.IDE.GHC.Compat: [avx512f] :: DynFlags -> Bool
+ Development.IDE.GHC.Compat: [avx512pf] :: DynFlags -> Bool
+ Development.IDE.GHC.Compat: [avx] :: DynFlags -> Bool
+ Development.IDE.GHC.Compat: [bmiVersion] :: DynFlags -> Maybe BmiVersion
+ Development.IDE.GHC.Compat: [breakInfo] :: ExecResult -> Maybe BreakInfo
+ Development.IDE.GHC.Compat: [breakNames] :: ExecResult -> [Name]
+ Development.IDE.GHC.Compat: [buildTag] :: DynFlags -> String
+ Development.IDE.GHC.Compat: [canGenerateDynamicToo] :: DynFlags -> IORef Bool
+ Development.IDE.GHC.Compat: [canUseColor] :: DynFlags -> Bool
+ Development.IDE.GHC.Compat: [cd_fld_doc] :: ConDeclField pass -> Maybe LHsDocString
+ Development.IDE.GHC.Compat: [cd_fld_ext] :: ConDeclField pass -> XConDeclField pass
+ Development.IDE.GHC.Compat: [cd_fld_names] :: ConDeclField pass -> [LFieldOcc pass]
+ Development.IDE.GHC.Compat: [cd_fld_type] :: ConDeclField pass -> LBangType pass
+ Development.IDE.GHC.Compat: [cid_binds] :: ClsInstDecl pass -> LHsBinds pass
+ Development.IDE.GHC.Compat: [cid_d_ext] :: InstDecl pass -> XClsInstD pass
+ Development.IDE.GHC.Compat: [cid_datafam_insts] :: ClsInstDecl pass -> [LDataFamInstDecl pass]
+ Development.IDE.GHC.Compat: [cid_ext] :: ClsInstDecl pass -> XCClsInstDecl pass
+ Development.IDE.GHC.Compat: [cid_inst] :: InstDecl pass -> ClsInstDecl pass
+ Development.IDE.GHC.Compat: [cid_overlap_mode] :: ClsInstDecl pass -> Maybe (Located OverlapMode)
+ Development.IDE.GHC.Compat: [cid_poly_ty] :: ClsInstDecl pass -> LHsSigType pass
+ Development.IDE.GHC.Compat: [cid_sigs] :: ClsInstDecl pass -> [LSig pass]
+ Development.IDE.GHC.Compat: [cid_tyfam_insts] :: ClsInstDecl pass -> [LTyFamInstDecl pass]
+ Development.IDE.GHC.Compat: [cm_binds] :: CoreModule -> CoreProgram
+ Development.IDE.GHC.Compat: [cm_module] :: CoreModule -> !Module
+ Development.IDE.GHC.Compat: [cm_safe] :: CoreModule -> SafeHaskellMode
+ Development.IDE.GHC.Compat: [cm_types] :: CoreModule -> !TypeEnv
+ Development.IDE.GHC.Compat: [cmdlineFrameworks] :: DynFlags -> [String]
+ Development.IDE.GHC.Compat: [cmmProcAlignment] :: DynFlags -> Maybe Int
+ Development.IDE.GHC.Compat: [colScheme] :: DynFlags -> Scheme
+ Development.IDE.GHC.Compat: [con_args] :: ConDecl pass -> HsConDeclDetails pass
+ Development.IDE.GHC.Compat: [con_doc] :: ConDecl pass -> Maybe LHsDocString
+ Development.IDE.GHC.Compat: [con_ex_tvs] :: ConDecl pass -> [LHsTyVarBndr pass]
+ Development.IDE.GHC.Compat: [con_ext] :: ConDecl pass -> XConDeclH98 pass
+ Development.IDE.GHC.Compat: [con_forall] :: ConDecl pass -> Located Bool
+ Development.IDE.GHC.Compat: [con_g_ext] :: ConDecl pass -> XConDeclGADT pass
+ Development.IDE.GHC.Compat: [con_mb_cxt] :: ConDecl pass -> Maybe (LHsContext pass)
+ Development.IDE.GHC.Compat: [con_name] :: ConDecl pass -> Located (IdP pass)
+ Development.IDE.GHC.Compat: [con_names] :: ConDecl pass -> [Located (IdP pass)]
+ Development.IDE.GHC.Compat: [con_qvars] :: ConDecl pass -> LHsQTyVars pass
+ Development.IDE.GHC.Compat: [con_res_ty] :: ConDecl pass -> LHsType pass
+ Development.IDE.GHC.Compat: [dd_ND] :: HsDataDefn pass -> NewOrData
+ Development.IDE.GHC.Compat: [dd_cType] :: HsDataDefn pass -> Maybe (Located CType)
+ Development.IDE.GHC.Compat: [dd_cons] :: HsDataDefn pass -> [LConDecl pass]
+ Development.IDE.GHC.Compat: [dd_ctxt] :: HsDataDefn pass -> LHsContext pass
+ Development.IDE.GHC.Compat: [dd_derivs] :: HsDataDefn pass -> HsDeriving pass
+ Development.IDE.GHC.Compat: [dd_ext] :: HsDataDefn pass -> XCHsDataDefn pass
+ Development.IDE.GHC.Compat: [dd_kindSig] :: HsDataDefn pass -> Maybe (LHsKind pass)
+ Development.IDE.GHC.Compat: [debugLevel] :: DynFlags -> Int
+ Development.IDE.GHC.Compat: [depExcludeMods] :: DynFlags -> [ModuleName]
+ Development.IDE.GHC.Compat: [depIncludePkgDeps] :: DynFlags -> Bool
+ Development.IDE.GHC.Compat: [depMakefile] :: DynFlags -> FilePath
+ Development.IDE.GHC.Compat: [depSuffixes] :: DynFlags -> [String]
+ Development.IDE.GHC.Compat: [deriv_clause_ext] :: HsDerivingClause pass -> XCHsDerivingClause pass
+ Development.IDE.GHC.Compat: [deriv_clause_strategy] :: HsDerivingClause pass -> Maybe (LDerivStrategy pass)
+ Development.IDE.GHC.Compat: [deriv_clause_tys] :: HsDerivingClause pass -> Located [LHsSigType pass]
+ Development.IDE.GHC.Compat: [deriv_ext] :: DerivDecl pass -> XCDerivDecl pass
+ Development.IDE.GHC.Compat: [deriv_overlap_mode] :: DerivDecl pass -> Maybe (Located OverlapMode)
+ Development.IDE.GHC.Compat: [deriv_strategy] :: DerivDecl pass -> Maybe (LDerivStrategy pass)
+ Development.IDE.GHC.Compat: [deriv_type] :: DerivDecl pass -> LHsSigWcType pass
+ Development.IDE.GHC.Compat: [dfid_eqn] :: DataFamInstDecl pass -> FamInstEqn pass (HsDataDefn pass)
+ Development.IDE.GHC.Compat: [dfid_ext] :: InstDecl pass -> XDataFamInstD pass
+ Development.IDE.GHC.Compat: [dfid_inst] :: InstDecl pass -> DataFamInstDecl pass
+ Development.IDE.GHC.Compat: [dirsToClean] :: DynFlags -> IORef (Map FilePath FilePath)
+ Development.IDE.GHC.Compat: [dm_core_module] :: DesugaredModule -> ModGuts
+ Development.IDE.GHC.Compat: [dm_typechecked_module] :: DesugaredModule -> TypecheckedModule
+ Development.IDE.GHC.Compat: [dumpDir] :: DynFlags -> Maybe String
+ Development.IDE.GHC.Compat: [dumpFlags] :: DynFlags -> EnumSet DumpFlag
+ Development.IDE.GHC.Compat: [dumpPrefixForce] :: DynFlags -> Maybe FilePath
+ Development.IDE.GHC.Compat: [dumpPrefix] :: DynFlags -> Maybe FilePath
+ Development.IDE.GHC.Compat: [dylibInstallName] :: DynFlags -> Maybe String
+ Development.IDE.GHC.Compat: [dynHiSuf] :: DynFlags -> String
+ Development.IDE.GHC.Compat: [dynLibLoader] :: DynFlags -> DynLibLoader
+ Development.IDE.GHC.Compat: [dynObjectSuf] :: DynFlags -> String
+ Development.IDE.GHC.Compat: [dynOutputFile] :: DynFlags -> Maybe String
+ Development.IDE.GHC.Compat: [enableTimeStats] :: DynFlags -> Bool
+ Development.IDE.GHC.Compat: [execAllocation] :: ExecResult -> Word64
+ Development.IDE.GHC.Compat: [execLineNumber] :: ExecOptions -> Int
+ Development.IDE.GHC.Compat: [execResult] :: ExecResult -> Either SomeException [Name]
+ Development.IDE.GHC.Compat: [execSingleStep] :: ExecOptions -> SingleStep
+ Development.IDE.GHC.Compat: [execSourceFile] :: ExecOptions -> String
+ Development.IDE.GHC.Compat: [execWrap] :: ExecOptions -> ForeignHValue -> EvalExpr ForeignHValue
+ Development.IDE.GHC.Compat: [extFieldOcc] :: FieldOcc pass -> XCFieldOcc pass
+ Development.IDE.GHC.Compat: [extensionFlags] :: DynFlags -> EnumSet Extension
+ Development.IDE.GHC.Compat: [extensions] :: DynFlags -> [OnOff Extension]
+ Development.IDE.GHC.Compat: [fatalWarningFlags] :: DynFlags -> EnumSet WarningFlag
+ Development.IDE.GHC.Compat: [fdExt] :: FamilyDecl pass -> XCFamilyDecl pass
+ Development.IDE.GHC.Compat: [fdFixity] :: FamilyDecl pass -> LexicalFixity
+ Development.IDE.GHC.Compat: [fdInfo] :: FamilyDecl pass -> FamilyInfo pass
+ Development.IDE.GHC.Compat: [fdInjectivityAnn] :: FamilyDecl pass -> Maybe (LInjectivityAnn pass)
+ Development.IDE.GHC.Compat: [fdLName] :: FamilyDecl pass -> Located (IdP pass)
+ Development.IDE.GHC.Compat: [fdResultSig] :: FamilyDecl pass -> LFamilyResultSig pass
+ Development.IDE.GHC.Compat: [fdTyVars] :: FamilyDecl pass -> LHsQTyVars pass
+ Development.IDE.GHC.Compat: [fd_e_ext] :: ForeignDecl pass -> XForeignExport pass
+ Development.IDE.GHC.Compat: [fd_fe] :: ForeignDecl pass -> ForeignExport
+ Development.IDE.GHC.Compat: [fd_fi] :: ForeignDecl pass -> ForeignImport
+ Development.IDE.GHC.Compat: [fd_i_ext] :: ForeignDecl pass -> XForeignImport pass
+ Development.IDE.GHC.Compat: [fd_name] :: ForeignDecl pass -> Located (IdP pass)
+ Development.IDE.GHC.Compat: [fd_sig_ty] :: ForeignDecl pass -> LHsSigType pass
+ Development.IDE.GHC.Compat: [feqn_ext] :: FamEqn pass pats rhs -> XCFamEqn pass pats rhs
+ Development.IDE.GHC.Compat: [feqn_fixity] :: FamEqn pass pats rhs -> LexicalFixity
+ Development.IDE.GHC.Compat: [feqn_pats] :: FamEqn pass pats rhs -> pats
+ Development.IDE.GHC.Compat: [feqn_rhs] :: FamEqn pass pats rhs -> rhs
+ Development.IDE.GHC.Compat: [feqn_tycon] :: FamEqn pass pats rhs -> Located (IdP pass)
+ Development.IDE.GHC.Compat: [filesToClean] :: DynFlags -> IORef FilesToClean
+ Development.IDE.GHC.Compat: [floatLamArgs] :: DynFlags -> Maybe Int
+ Development.IDE.GHC.Compat: [flushErr] :: DynFlags -> FlushErr
+ Development.IDE.GHC.Compat: [flushOut] :: DynFlags -> FlushOut
+ Development.IDE.GHC.Compat: [frameworkPaths] :: DynFlags -> [String]
+ Development.IDE.GHC.Compat: [freshIndex] :: HieTypeState -> !TypeIndex
+ Development.IDE.GHC.Compat: [frontendPluginOpts] :: DynFlags -> [String]
+ Development.IDE.GHC.Compat: [fun_co_fn] :: HsBindLR idL idR -> HsWrapper
+ Development.IDE.GHC.Compat: [fun_ext] :: HsBindLR idL idR -> XFunBind idL idR
+ Development.IDE.GHC.Compat: [fun_id] :: HsBindLR idL idR -> Located (IdP idL)
+ Development.IDE.GHC.Compat: [fun_matches] :: HsBindLR idL idR -> MatchGroup idR (LHsExpr idR)
+ Development.IDE.GHC.Compat: [fun_tick] :: HsBindLR idL idR -> [Tickish Id]
+ Development.IDE.GHC.Compat: [generalFlags] :: DynFlags -> EnumSet GeneralFlag
+ Development.IDE.GHC.Compat: [generatedDumps] :: DynFlags -> IORef (Set FilePath)
+ Development.IDE.GHC.Compat: [getAsts] :: HieASTs a -> Map FastString (HieAST a)
+ Development.IDE.GHC.Compat: [ghcHeapSize] :: DynFlags -> Maybe Int
+ Development.IDE.GHC.Compat: [ghcLink] :: DynFlags -> GhcLink
+ Development.IDE.GHC.Compat: [ghcMode] :: DynFlags -> GhcMode
+ Development.IDE.GHC.Compat: [ghcVersionFile] :: DynFlags -> Maybe FilePath
+ Development.IDE.GHC.Compat: [ghciHistSize] :: DynFlags -> Int
+ Development.IDE.GHC.Compat: [ghciScripts] :: DynFlags -> [String]
+ Development.IDE.GHC.Compat: [grhssExt] :: GRHSs p body -> XCGRHSs p body
+ Development.IDE.GHC.Compat: [grhssGRHSs] :: GRHSs p body -> [LGRHS p body]
+ Development.IDE.GHC.Compat: [grhssLocalBinds] :: GRHSs p body -> LHsLocalBinds p
+ Development.IDE.GHC.Compat: [group_ext] :: TyClGroup pass -> XCTyClGroup pass
+ Development.IDE.GHC.Compat: [group_instds] :: TyClGroup pass -> [LInstDecl pass]
+ Development.IDE.GHC.Compat: [group_roles] :: TyClGroup pass -> [LRoleAnnotDecl pass]
+ Development.IDE.GHC.Compat: [group_tyclds] :: TyClGroup pass -> [LTyClDecl pass]
+ Development.IDE.GHC.Compat: [haddockOptions] :: DynFlags -> Maybe String
+ Development.IDE.GHC.Compat: [hcSuf] :: DynFlags -> String
+ Development.IDE.GHC.Compat: [hiDir] :: DynFlags -> Maybe String
+ Development.IDE.GHC.Compat: [hiSuf] :: DynFlags -> String
+ Development.IDE.GHC.Compat: [hie_asts] :: HieFile -> HieASTs TypeIndex
+ Development.IDE.GHC.Compat: [hie_exports] :: HieFile -> [AvailInfo]
+ Development.IDE.GHC.Compat: [hie_file_result] :: HieFileResult -> HieFile
+ Development.IDE.GHC.Compat: [hie_file_result_ghc_version] :: HieFileResult -> ByteString
+ Development.IDE.GHC.Compat: [hie_file_result_version] :: HieFileResult -> Integer
+ Development.IDE.GHC.Compat: [hie_hs_file] :: HieFile -> FilePath
+ Development.IDE.GHC.Compat: [hie_hs_src] :: HieFile -> ByteString
+ Development.IDE.GHC.Compat: [hie_module] :: HieFile -> Module
+ Development.IDE.GHC.Compat: [hie_types] :: HieFile -> Array TypeIndex HieTypeFlat
+ Development.IDE.GHC.Compat: [historySize] :: DynFlags -> Int
+ Development.IDE.GHC.Compat: [hooks] :: DynFlags -> Hooks
+ Development.IDE.GHC.Compat: [hpcDir] :: DynFlags -> String
+ Development.IDE.GHC.Compat: [hsRecFieldArg] :: HsRecField' id arg -> arg
+ Development.IDE.GHC.Compat: [hsRecFieldLbl] :: HsRecField' id arg -> Located id
+ Development.IDE.GHC.Compat: [hsRecPun] :: HsRecField' id arg -> Bool
+ Development.IDE.GHC.Compat: [hs_annds] :: HsGroup p -> [LAnnDecl p]
+ Development.IDE.GHC.Compat: [hs_defds] :: HsGroup p -> [LDefaultDecl p]
+ Development.IDE.GHC.Compat: [hs_derivds] :: HsGroup p -> [LDerivDecl p]
+ Development.IDE.GHC.Compat: [hs_docs] :: HsGroup p -> [LDocDecl]
+ Development.IDE.GHC.Compat: [hs_ext] :: HsGroup p -> XCHsGroup p
+ Development.IDE.GHC.Compat: [hs_fixds] :: HsGroup p -> [LFixitySig p]
+ Development.IDE.GHC.Compat: [hs_fords] :: HsGroup p -> [LForeignDecl p]
+ Development.IDE.GHC.Compat: [hs_ruleds] :: HsGroup p -> [LRuleDecls p]
+ Development.IDE.GHC.Compat: [hs_splcds] :: HsGroup p -> [LSpliceDecl p]
+ Development.IDE.GHC.Compat: [hs_tyclds] :: HsGroup p -> [TyClGroup p]
+ Development.IDE.GHC.Compat: [hs_valds] :: HsGroup p -> HsValBinds p
+ Development.IDE.GHC.Compat: [hs_warnds] :: HsGroup p -> [LWarnDecls p]
+ Development.IDE.GHC.Compat: [hscTarget] :: DynFlags -> HscTarget
+ Development.IDE.GHC.Compat: [hsib_body] :: HsImplicitBndrs pass thing -> thing
+ Development.IDE.GHC.Compat: [hsib_closed] :: HsIBRn -> Bool
+ Development.IDE.GHC.Compat: [hsib_ext] :: HsImplicitBndrs pass thing -> XHsIB pass thing
+ Development.IDE.GHC.Compat: [hsib_vars] :: HsIBRn -> [Name]
+ Development.IDE.GHC.Compat: [hsmodDecls] :: HsModule pass -> [LHsDecl pass]
+ Development.IDE.GHC.Compat: [hsmodDeprecMessage] :: HsModule pass -> Maybe (Located WarningTxt)
+ Development.IDE.GHC.Compat: [hsmodExports] :: HsModule pass -> Maybe (Located [LIE pass])
+ Development.IDE.GHC.Compat: [hsmodHaddockModHeader] :: HsModule pass -> Maybe LHsDocString
+ Development.IDE.GHC.Compat: [hsmodImports] :: HsModule pass -> [LImportDecl pass]
+ Development.IDE.GHC.Compat: [hsmodName] :: HsModule pass -> Maybe (Located ModuleName)
+ Development.IDE.GHC.Compat: [hsq_dependent] :: HsQTvsRn -> NameSet
+ Development.IDE.GHC.Compat: [hsq_explicit] :: LHsQTyVars pass -> [LHsTyVarBndr pass]
+ Development.IDE.GHC.Compat: [hsq_ext] :: LHsQTyVars pass -> XHsQTvs pass
+ Development.IDE.GHC.Compat: [hsq_implicit] :: HsQTvsRn -> [Name]
+ Development.IDE.GHC.Compat: [hst_bndrs] :: HsType pass -> [LHsTyVarBndr pass]
+ Development.IDE.GHC.Compat: [hst_body] :: HsType pass -> LHsType pass
+ Development.IDE.GHC.Compat: [hst_ctxt] :: HsType pass -> LHsContext pass
+ Development.IDE.GHC.Compat: [hst_xforall] :: HsType pass -> XForAllTy pass
+ Development.IDE.GHC.Compat: [hst_xqual] :: HsType pass -> XQualTy pass
+ Development.IDE.GHC.Compat: [hswc_body] :: HsWildCardBndrs pass thing -> thing
+ Development.IDE.GHC.Compat: [hswc_ext] :: HsWildCardBndrs pass thing -> XHsWC pass thing
+ Development.IDE.GHC.Compat: [htyTable] :: HieTypeState -> !IntMap HieTypeFlat
+ Development.IDE.GHC.Compat: [ideclAs] :: ImportDecl pass -> Maybe (Located ModuleName)
+ Development.IDE.GHC.Compat: [ideclExt] :: ImportDecl pass -> XCImportDecl pass
+ Development.IDE.GHC.Compat: [ideclHiding] :: ImportDecl pass -> Maybe (Bool, Located [LIE pass])
+ Development.IDE.GHC.Compat: [ideclImplicit] :: ImportDecl pass -> Bool
+ Development.IDE.GHC.Compat: [ideclName] :: ImportDecl pass -> Located ModuleName
+ Development.IDE.GHC.Compat: [ideclPkgQual] :: ImportDecl pass -> Maybe StringLiteral
+ Development.IDE.GHC.Compat: [ideclQualified] :: ImportDecl pass -> Bool
+ Development.IDE.GHC.Compat: [ideclSafe] :: ImportDecl pass -> Bool
+ Development.IDE.GHC.Compat: [ideclSourceSrc] :: ImportDecl pass -> SourceText
+ Development.IDE.GHC.Compat: [ideclSource] :: ImportDecl pass -> Bool
+ Development.IDE.GHC.Compat: [identInfo] :: IdentifierDetails a -> Set ContextInfo
+ Development.IDE.GHC.Compat: [identType] :: IdentifierDetails a -> Maybe a
+ Development.IDE.GHC.Compat: [ignorePackageFlags] :: DynFlags -> [IgnorePackageFlag]
+ Development.IDE.GHC.Compat: [importPaths] :: DynFlags -> [FilePath]
+ Development.IDE.GHC.Compat: [includePaths] :: DynFlags -> IncludeSpecs
+ Development.IDE.GHC.Compat: [incoherentOnLoc] :: DynFlags -> SrcSpan
+ Development.IDE.GHC.Compat: [initialUnique] :: DynFlags -> Int
+ Development.IDE.GHC.Compat: [inlineCheck] :: DynFlags -> Maybe String
+ Development.IDE.GHC.Compat: [interactivePrint] :: DynFlags -> Maybe String
+ Development.IDE.GHC.Compat: [language] :: DynFlags -> Maybe Language
+ Development.IDE.GHC.Compat: [ldInputs] :: DynFlags -> [Option]
+ Development.IDE.GHC.Compat: [liberateCaseThreshold] :: DynFlags -> Maybe Int
+ Development.IDE.GHC.Compat: [libraryPaths] :: DynFlags -> [String]
+ Development.IDE.GHC.Compat: [llvmPasses] :: DynFlags -> LlvmPasses
+ Development.IDE.GHC.Compat: [llvmTargets] :: DynFlags -> LlvmTargets
+ Development.IDE.GHC.Compat: [log_action] :: DynFlags -> LogAction
+ Development.IDE.GHC.Compat: [m_ctxt] :: Match p body -> HsMatchContext (NameOrRdrName (IdP p))
+ Development.IDE.GHC.Compat: [m_ext] :: Match p body -> XCMatch p body
+ Development.IDE.GHC.Compat: [m_grhss] :: Match p body -> GRHSs p body
+ Development.IDE.GHC.Compat: [m_pats] :: Match p body -> [LPat p]
+ Development.IDE.GHC.Compat: [mainFunIs] :: DynFlags -> Maybe String
+ Development.IDE.GHC.Compat: [mainModIs] :: DynFlags -> Module
+ Development.IDE.GHC.Compat: [maxErrors] :: DynFlags -> Maybe Int
+ Development.IDE.GHC.Compat: [maxInlineAllocSize] :: DynFlags -> Int
+ Development.IDE.GHC.Compat: [maxInlineMemcpyInsns] :: DynFlags -> Int
+ Development.IDE.GHC.Compat: [maxInlineMemsetInsns] :: DynFlags -> Int
+ Development.IDE.GHC.Compat: [maxPmCheckIterations] :: DynFlags -> Int
+ Development.IDE.GHC.Compat: [maxRefHoleFits] :: DynFlags -> Maybe Int
+ Development.IDE.GHC.Compat: [maxRelevantBinds] :: DynFlags -> Maybe Int
+ Development.IDE.GHC.Compat: [maxSimplIterations] :: DynFlags -> Int
+ Development.IDE.GHC.Compat: [maxUncoveredPatterns] :: DynFlags -> Int
+ Development.IDE.GHC.Compat: [maxValidHoleFits] :: DynFlags -> Maybe Int
+ Development.IDE.GHC.Compat: [maxWorkerArgs] :: DynFlags -> Int
+ Development.IDE.GHC.Compat: [mc_fixity] :: HsMatchContext id -> LexicalFixity
+ Development.IDE.GHC.Compat: [mc_fun] :: HsMatchContext id -> Located id
+ Development.IDE.GHC.Compat: [mc_strictness] :: HsMatchContext id -> SrcStrictness
+ Development.IDE.GHC.Compat: [mg_alts] :: MatchGroup p body -> Located [LMatch p body]
+ Development.IDE.GHC.Compat: [mg_arg_tys] :: MatchGroupTc -> [Type]
+ Development.IDE.GHC.Compat: [mg_ext] :: MatchGroup p body -> XMG p body
+ Development.IDE.GHC.Compat: [mg_origin] :: MatchGroup p body -> Origin
+ Development.IDE.GHC.Compat: [mg_res_ty] :: MatchGroupTc -> Type
+ Development.IDE.GHC.Compat: [mi_anns] :: ModIface -> [IfaceAnnotation]
+ Development.IDE.GHC.Compat: [mi_arg_docs] :: ModIface -> ArgDocMap
+ Development.IDE.GHC.Compat: [mi_complete_sigs] :: ModIface -> [IfaceCompleteMatch]
+ Development.IDE.GHC.Compat: [mi_decl_docs] :: ModIface -> DeclDocMap
+ Development.IDE.GHC.Compat: [mi_decls] :: ModIface -> [(Fingerprint, IfaceDecl)]
+ Development.IDE.GHC.Compat: [mi_deps] :: ModIface -> Dependencies
+ Development.IDE.GHC.Compat: [mi_doc_hdr] :: ModIface -> Maybe HsDocString
+ Development.IDE.GHC.Compat: [mi_exp_hash] :: ModIface -> !Fingerprint
+ Development.IDE.GHC.Compat: [mi_exports] :: ModIface -> ![IfaceExport]
+ Development.IDE.GHC.Compat: [mi_fam_insts] :: ModIface -> [IfaceFamInst]
+ Development.IDE.GHC.Compat: [mi_finsts] :: ModIface -> !WhetherHasFamInst
+ Development.IDE.GHC.Compat: [mi_fix_fn] :: ModIface -> OccName -> Maybe Fixity
+ Development.IDE.GHC.Compat: [mi_fixities] :: ModIface -> [(OccName, Fixity)]
+ Development.IDE.GHC.Compat: [mi_flag_hash] :: ModIface -> !Fingerprint
+ Development.IDE.GHC.Compat: [mi_globals] :: ModIface -> !Maybe GlobalRdrEnv
+ Development.IDE.GHC.Compat: [mi_hash_fn] :: ModIface -> OccName -> Maybe (OccName, Fingerprint)
+ Development.IDE.GHC.Compat: [mi_hpc] :: ModIface -> !AnyHpcUsage
+ Development.IDE.GHC.Compat: [mi_hpc_hash] :: ModIface -> !Fingerprint
+ Development.IDE.GHC.Compat: [mi_hsc_src] :: ModIface -> !HscSource
+ Development.IDE.GHC.Compat: [mi_iface_hash] :: ModIface -> !Fingerprint
+ Development.IDE.GHC.Compat: [mi_insts] :: ModIface -> [IfaceClsInst]
+ Development.IDE.GHC.Compat: [mi_mod_hash] :: ModIface -> !Fingerprint
+ Development.IDE.GHC.Compat: [mi_module] :: ModIface -> !Module
+ Development.IDE.GHC.Compat: [mi_opt_hash] :: ModIface -> !Fingerprint
+ Development.IDE.GHC.Compat: [mi_orphan] :: ModIface -> !WhetherHasOrphans
+ Development.IDE.GHC.Compat: [mi_orphan_hash] :: ModIface -> !Fingerprint
+ Development.IDE.GHC.Compat: [mi_plugin_hash] :: ModIface -> !Fingerprint
+ Development.IDE.GHC.Compat: [mi_rules] :: ModIface -> [IfaceRule]
+ Development.IDE.GHC.Compat: [mi_sig_of] :: ModIface -> !Maybe Module
+ Development.IDE.GHC.Compat: [mi_trust] :: ModIface -> !IfaceTrustInfo
+ Development.IDE.GHC.Compat: [mi_trust_pkg] :: ModIface -> !Bool
+ Development.IDE.GHC.Compat: [mi_usages] :: ModIface -> [Usage]
+ Development.IDE.GHC.Compat: [mi_used_th] :: ModIface -> !Bool
+ Development.IDE.GHC.Compat: [mi_warn_fn] :: ModIface -> OccName -> Maybe WarningTxt
+ Development.IDE.GHC.Compat: [mi_warns] :: ModIface -> Warnings
+ Development.IDE.GHC.Compat: [modBreaks_breakInfo] :: ModBreaks -> IntMap CgBreakInfo
+ Development.IDE.GHC.Compat: [modBreaks_ccs] :: ModBreaks -> !Array BreakIndex (RemotePtr CostCentre)
+ Development.IDE.GHC.Compat: [modBreaks_decls] :: ModBreaks -> !Array BreakIndex [String]
+ Development.IDE.GHC.Compat: [modBreaks_flags] :: ModBreaks -> ForeignRef BreakArray
+ Development.IDE.GHC.Compat: [modBreaks_locs] :: ModBreaks -> !Array BreakIndex SrcSpan
+ Development.IDE.GHC.Compat: [modBreaks_vars] :: ModBreaks -> !Array BreakIndex [OccName]
+ Development.IDE.GHC.Compat: [ms_hs_date] :: ModSummary -> UTCTime
+ Development.IDE.GHC.Compat: [ms_hsc_src] :: ModSummary -> HscSource
+ Development.IDE.GHC.Compat: [ms_hspp_buf] :: ModSummary -> Maybe StringBuffer
+ Development.IDE.GHC.Compat: [ms_hspp_file] :: ModSummary -> FilePath
+ Development.IDE.GHC.Compat: [ms_hspp_opts] :: ModSummary -> DynFlags
+ Development.IDE.GHC.Compat: [ms_iface_date] :: ModSummary -> Maybe UTCTime
+ Development.IDE.GHC.Compat: [ms_location] :: ModSummary -> ModLocation
+ Development.IDE.GHC.Compat: [ms_mod] :: ModSummary -> Module
+ Development.IDE.GHC.Compat: [ms_obj_date] :: ModSummary -> Maybe UTCTime
+ Development.IDE.GHC.Compat: [ms_parsed_mod] :: ModSummary -> Maybe HsParsedModule
+ Development.IDE.GHC.Compat: [ms_srcimps] :: ModSummary -> [(Maybe FastString, Located ModuleName)]
+ Development.IDE.GHC.Compat: [ms_textual_imps] :: ModSummary -> [(Maybe FastString, Located ModuleName)]
+ Development.IDE.GHC.Compat: [newDerivOnLoc] :: DynFlags -> SrcSpan
+ Development.IDE.GHC.Compat: [nextTempSuffix] :: DynFlags -> IORef Int
+ Development.IDE.GHC.Compat: [nextWrapperNum] :: DynFlags -> IORef (ModuleEnv Int)
+ Development.IDE.GHC.Compat: [nodeAnnotations] :: NodeInfo a -> Set (FastString, FastString)
+ Development.IDE.GHC.Compat: [nodeChildren] :: HieAST a -> [HieAST a]
+ Development.IDE.GHC.Compat: [nodeIdentifiers] :: NodeInfo a -> NodeIdentifiers a
+ Development.IDE.GHC.Compat: [nodeInfo] :: HieAST a -> NodeInfo a
+ Development.IDE.GHC.Compat: [nodeSpan] :: HieAST a -> Span
+ Development.IDE.GHC.Compat: [nodeType] :: NodeInfo a -> [a]
+ Development.IDE.GHC.Compat: [objectDir] :: DynFlags -> Maybe String
+ Development.IDE.GHC.Compat: [objectSuf] :: DynFlags -> String
+ Development.IDE.GHC.Compat: [ol_ext] :: HsOverLit p -> XOverLit p
+ Development.IDE.GHC.Compat: [ol_rebindable] :: OverLitTc -> Bool
+ Development.IDE.GHC.Compat: [ol_type] :: OverLitTc -> Type
+ Development.IDE.GHC.Compat: [ol_val] :: HsOverLit p -> OverLitVal
+ Development.IDE.GHC.Compat: [ol_witness] :: HsOverLit p -> HsExpr p
+ Development.IDE.GHC.Compat: [optLevel] :: DynFlags -> Int
+ Development.IDE.GHC.Compat: [outputFile] :: DynFlags -> Maybe String
+ Development.IDE.GHC.Compat: [outputHi] :: DynFlags -> Maybe String
+ Development.IDE.GHC.Compat: [overlapInstLoc] :: DynFlags -> SrcSpan
+ Development.IDE.GHC.Compat: [packageDBFlags] :: DynFlags -> [PackageDBFlag]
+ Development.IDE.GHC.Compat: [packageEnv] :: DynFlags -> Maybe FilePath
+ Development.IDE.GHC.Compat: [packageFlags] :: DynFlags -> [PackageFlag]
+ Development.IDE.GHC.Compat: [parMakeCount] :: DynFlags -> Maybe Int
+ Development.IDE.GHC.Compat: [pat_arg_tys] :: Pat p -> [Type]
+ Development.IDE.GHC.Compat: [pat_args] :: Pat p -> HsConPatDetails p
+ Development.IDE.GHC.Compat: [pat_binds] :: Pat p -> TcEvBinds
+ Development.IDE.GHC.Compat: [pat_con] :: Pat p -> Located ConLike
+ Development.IDE.GHC.Compat: [pat_dicts] :: Pat p -> [EvVar]
+ Development.IDE.GHC.Compat: [pat_ext] :: HsBindLR idL idR -> XPatBind idL idR
+ Development.IDE.GHC.Compat: [pat_fvs] :: NPatBindTc -> NameSet
+ Development.IDE.GHC.Compat: [pat_lhs] :: HsBindLR idL idR -> LPat idL
+ Development.IDE.GHC.Compat: [pat_rhs] :: HsBindLR idL idR -> GRHSs idR (LHsExpr idR)
+ Development.IDE.GHC.Compat: [pat_rhs_ty] :: NPatBindTc -> Type
+ Development.IDE.GHC.Compat: [pat_ticks] :: HsBindLR idL idR -> ([Tickish Id], [[Tickish Id]])
+ Development.IDE.GHC.Compat: [pat_tvs] :: Pat p -> [TyVar]
+ Development.IDE.GHC.Compat: [pat_wrap] :: Pat p -> HsWrapper
+ Development.IDE.GHC.Compat: [pkgDatabase] :: DynFlags -> Maybe [(FilePath, [PackageConfig])]
+ Development.IDE.GHC.Compat: [pkgState] :: DynFlags -> PackageState
+ Development.IDE.GHC.Compat: [pkgTrustOnLoc] :: DynFlags -> SrcSpan
+ Development.IDE.GHC.Compat: [pluginModNameOpts] :: DynFlags -> [(ModuleName, String)]
+ Development.IDE.GHC.Compat: [pluginModNames] :: DynFlags -> [ModuleName]
+ Development.IDE.GHC.Compat: [pluginPackageFlags] :: DynFlags -> [PackageFlag]
+ Development.IDE.GHC.Compat: [plugins] :: DynFlags -> [LoadedPlugin]
+ Development.IDE.GHC.Compat: [pm_annotations] :: ParsedModule -> ApiAnns
+ Development.IDE.GHC.Compat: [pm_extra_src_files] :: ParsedModule -> [FilePath]
+ Development.IDE.GHC.Compat: [pm_mod_summary] :: ParsedModule -> ModSummary
+ Development.IDE.GHC.Compat: [pm_parsed_source] :: ParsedModule -> ParsedSource
+ Development.IDE.GHC.Compat: [pprCols] :: DynFlags -> Int
+ Development.IDE.GHC.Compat: [pprUserLength] :: DynFlags -> Int
+ Development.IDE.GHC.Compat: [profAuto] :: DynFlags -> ProfAuto
+ Development.IDE.GHC.Compat: [rcon_con_expr] :: RecordConTc -> PostTcExpr
+ Development.IDE.GHC.Compat: [rcon_con_like] :: RecordConTc -> ConLike
+ Development.IDE.GHC.Compat: [rcon_con_name] :: HsExpr p -> Located (IdP p)
+ Development.IDE.GHC.Compat: [rcon_ext] :: HsExpr p -> XRecordCon p
+ Development.IDE.GHC.Compat: [rcon_flds] :: HsExpr p -> HsRecordBinds p
+ Development.IDE.GHC.Compat: [rdrNameFieldOcc] :: FieldOcc pass -> Located RdrName
+ Development.IDE.GHC.Compat: [rds_ext] :: RuleDecls pass -> XCRuleDecls pass
+ Development.IDE.GHC.Compat: [rds_rules] :: RuleDecls pass -> [LRuleDecl pass]
+ Development.IDE.GHC.Compat: [rds_src] :: RuleDecls pass -> SourceText
+ Development.IDE.GHC.Compat: [recS_bind_fn] :: StmtLR idL idR body -> SyntaxExpr idR
+ Development.IDE.GHC.Compat: [recS_bind_ty] :: RecStmtTc -> Type
+ Development.IDE.GHC.Compat: [recS_ext] :: StmtLR idL idR body -> XRecStmt idL idR body
+ Development.IDE.GHC.Compat: [recS_later_ids] :: StmtLR idL idR body -> [IdP idR]
+ Development.IDE.GHC.Compat: [recS_later_rets] :: RecStmtTc -> [PostTcExpr]
+ Development.IDE.GHC.Compat: [recS_mfix_fn] :: StmtLR idL idR body -> SyntaxExpr idR
+ Development.IDE.GHC.Compat: [recS_rec_ids] :: StmtLR idL idR body -> [IdP idR]
+ Development.IDE.GHC.Compat: [recS_rec_rets] :: RecStmtTc -> [PostTcExpr]
+ Development.IDE.GHC.Compat: [recS_ret_fn] :: StmtLR idL idR body -> SyntaxExpr idR
+ Development.IDE.GHC.Compat: [recS_ret_ty] :: RecStmtTc -> Type
+ Development.IDE.GHC.Compat: [recS_stmts] :: StmtLR idL idR body -> [LStmtLR idL idR body]
+ Development.IDE.GHC.Compat: [rec_dotdot] :: HsRecFields p arg -> Maybe Int
+ Development.IDE.GHC.Compat: [rec_flds] :: HsRecFields p arg -> [LHsRecField p arg]
+ Development.IDE.GHC.Compat: [recordPatSynPatVar] :: RecordPatSynField a -> a
+ Development.IDE.GHC.Compat: [recordPatSynSelectorId] :: RecordPatSynField a -> a
+ Development.IDE.GHC.Compat: [reductionDepth] :: DynFlags -> IntWithInf
+ Development.IDE.GHC.Compat: [refLevelHoleFits] :: DynFlags -> Maybe Int
+ Development.IDE.GHC.Compat: [resumeApStack] :: Resume -> ForeignHValue
+ Development.IDE.GHC.Compat: [resumeBindings] :: Resume -> ([TyThing], GlobalRdrEnv)
+ Development.IDE.GHC.Compat: [resumeBreakInfo] :: Resume -> Maybe BreakInfo
+ Development.IDE.GHC.Compat: [resumeCCS] :: Resume -> RemotePtr CostCentreStack
+ Development.IDE.GHC.Compat: [resumeContext] :: Resume -> ForeignRef (ResumeContext [HValueRef])
+ Development.IDE.GHC.Compat: [resumeDecl] :: Resume -> String
+ Development.IDE.GHC.Compat: [resumeFinalIds] :: Resume -> [Id]
+ Development.IDE.GHC.Compat: [resumeHistoryIx] :: Resume -> Int
+ Development.IDE.GHC.Compat: [resumeHistory] :: Resume -> [History]
+ Development.IDE.GHC.Compat: [resumeSpan] :: Resume -> SrcSpan
+ Development.IDE.GHC.Compat: [resumeStmt] :: Resume -> String
+ Development.IDE.GHC.Compat: [reverseErrors] :: DynFlags -> Bool
+ Development.IDE.GHC.Compat: [rtccInfo] :: DynFlags -> IORef (Maybe CompilerInfo)
+ Development.IDE.GHC.Compat: [rtldInfo] :: DynFlags -> IORef (Maybe LinkerInfo)
+ Development.IDE.GHC.Compat: [rtsOptsEnabled] :: DynFlags -> RtsOptsEnabled
+ Development.IDE.GHC.Compat: [rtsOptsSuggestions] :: DynFlags -> Bool
+ Development.IDE.GHC.Compat: [rtsOpts] :: DynFlags -> Maybe String
+ Development.IDE.GHC.Compat: [ruleCheck] :: DynFlags -> Maybe String
+ Development.IDE.GHC.Compat: [rupd_cons] :: RecordUpdTc -> [ConLike]
+ Development.IDE.GHC.Compat: [rupd_expr] :: HsExpr p -> LHsExpr p
+ Development.IDE.GHC.Compat: [rupd_ext] :: HsExpr p -> XRecordUpd p
+ Development.IDE.GHC.Compat: [rupd_flds] :: HsExpr p -> [LHsRecUpdField p]
+ Development.IDE.GHC.Compat: [rupd_in_tys] :: RecordUpdTc -> [Type]
+ Development.IDE.GHC.Compat: [rupd_out_tys] :: RecordUpdTc -> [Type]
+ Development.IDE.GHC.Compat: [rupd_wrap] :: RecordUpdTc -> HsWrapper
+ Development.IDE.GHC.Compat: [safeHaskell] :: DynFlags -> SafeHaskellMode
+ Development.IDE.GHC.Compat: [safeInfer] :: DynFlags -> Bool
+ Development.IDE.GHC.Compat: [safeInferred] :: DynFlags -> Bool
+ Development.IDE.GHC.Compat: [settings] :: DynFlags -> Settings
+ Development.IDE.GHC.Compat: [simplPhases] :: DynFlags -> Int
+ Development.IDE.GHC.Compat: [simplTickFactor] :: DynFlags -> Int
+ Development.IDE.GHC.Compat: [solverIterations] :: DynFlags -> IntWithInf
+ Development.IDE.GHC.Compat: [specConstrCount] :: DynFlags -> Maybe Int
+ Development.IDE.GHC.Compat: [specConstrRecursive] :: DynFlags -> Int
+ Development.IDE.GHC.Compat: [specConstrThreshold] :: DynFlags -> Maybe Int
+ Development.IDE.GHC.Compat: [splitInfo] :: DynFlags -> Maybe (String, Int)
+ Development.IDE.GHC.Compat: [sseVersion] :: DynFlags -> Maybe SseVersion
+ Development.IDE.GHC.Compat: [strictnessBefore] :: DynFlags -> [Int]
+ Development.IDE.GHC.Compat: [stubDir] :: DynFlags -> Maybe String
+ Development.IDE.GHC.Compat: [syn_arg_wraps] :: SyntaxExpr p -> [HsWrapper]
+ Development.IDE.GHC.Compat: [syn_expr] :: SyntaxExpr p -> HsExpr p
+ Development.IDE.GHC.Compat: [syn_res_wrap] :: SyntaxExpr p -> HsWrapper
+ Development.IDE.GHC.Compat: [targetAllowObjCode] :: Target -> Bool
+ Development.IDE.GHC.Compat: [targetContents] :: Target -> Maybe (StringBuffer, UTCTime)
+ Development.IDE.GHC.Compat: [targetId] :: Target -> TargetId
+ Development.IDE.GHC.Compat: [tcdATDefs] :: TyClDecl pass -> [LTyFamDefltEqn pass]
+ Development.IDE.GHC.Compat: [tcdATs] :: TyClDecl pass -> [LFamilyDecl pass]
+ Development.IDE.GHC.Compat: [tcdCExt] :: TyClDecl pass -> XClassDecl pass
+ Development.IDE.GHC.Compat: [tcdCtxt] :: TyClDecl pass -> LHsContext pass
+ Development.IDE.GHC.Compat: [tcdDExt] :: TyClDecl pass -> XDataDecl pass
+ Development.IDE.GHC.Compat: [tcdDataCusk] :: DataDeclRn -> Bool
+ Development.IDE.GHC.Compat: [tcdDataDefn] :: TyClDecl pass -> HsDataDefn pass
+ Development.IDE.GHC.Compat: [tcdDocs] :: TyClDecl pass -> [LDocDecl]
+ Development.IDE.GHC.Compat: [tcdFDs] :: TyClDecl pass -> [Located (FunDep (Located (IdP pass)))]
+ Development.IDE.GHC.Compat: [tcdFExt] :: TyClDecl pass -> XFamDecl pass
+ Development.IDE.GHC.Compat: [tcdFVs] :: DataDeclRn -> NameSet
+ Development.IDE.GHC.Compat: [tcdFam] :: TyClDecl pass -> FamilyDecl pass
+ Development.IDE.GHC.Compat: [tcdFixity] :: TyClDecl pass -> LexicalFixity
+ Development.IDE.GHC.Compat: [tcdLName] :: TyClDecl pass -> Located (IdP pass)
+ Development.IDE.GHC.Compat: [tcdMeths] :: TyClDecl pass -> LHsBinds pass
+ Development.IDE.GHC.Compat: [tcdRhs] :: TyClDecl pass -> LHsType pass
+ Development.IDE.GHC.Compat: [tcdSExt] :: TyClDecl pass -> XSynDecl pass
+ Development.IDE.GHC.Compat: [tcdSigs] :: TyClDecl pass -> [LSig pass]
+ Development.IDE.GHC.Compat: [tcdTyVars] :: TyClDecl pass -> LHsQTyVars pass
+ Development.IDE.GHC.Compat: [tfid_eqn] :: TyFamInstDecl pass -> TyFamInstEqn pass
+ Development.IDE.GHC.Compat: [tfid_ext] :: InstDecl pass -> XTyFamInstD pass
+ Development.IDE.GHC.Compat: [tfid_inst] :: InstDecl pass -> TyFamInstDecl pass
+ Development.IDE.GHC.Compat: [thOnLoc] :: DynFlags -> SrcSpan
+ Development.IDE.GHC.Compat: [thisComponentId_] :: DynFlags -> Maybe ComponentId
+ Development.IDE.GHC.Compat: [thisInstalledUnitId] :: DynFlags -> InstalledUnitId
+ Development.IDE.GHC.Compat: [thisUnitIdInsts_] :: DynFlags -> Maybe [(ModuleName, Module)]
+ Development.IDE.GHC.Compat: [tm_checked_module_info] :: TypecheckedModule -> ModuleInfo
+ Development.IDE.GHC.Compat: [tm_internals_] :: TypecheckedModule -> (TcGblEnv, ModDetails)
+ Development.IDE.GHC.Compat: [tm_parsed_module] :: TypecheckedModule -> ParsedModule
+ Development.IDE.GHC.Compat: [tm_renamed_source] :: TypecheckedModule -> Maybe RenamedSource
+ Development.IDE.GHC.Compat: [tm_typechecked_source] :: TypecheckedModule -> TypecheckedSource
+ Development.IDE.GHC.Compat: [trS_bind] :: StmtLR idL idR body -> SyntaxExpr idR
+ Development.IDE.GHC.Compat: [trS_bndrs] :: StmtLR idL idR body -> [(IdP idR, IdP idR)]
+ Development.IDE.GHC.Compat: [trS_by] :: StmtLR idL idR body -> Maybe (LHsExpr idR)
+ Development.IDE.GHC.Compat: [trS_ext] :: StmtLR idL idR body -> XTransStmt idL idR body
+ Development.IDE.GHC.Compat: [trS_fmap] :: StmtLR idL idR body -> HsExpr idR
+ Development.IDE.GHC.Compat: [trS_form] :: StmtLR idL idR body -> TransForm
+ Development.IDE.GHC.Compat: [trS_ret] :: StmtLR idL idR body -> SyntaxExpr idR
+ Development.IDE.GHC.Compat: [trS_stmts] :: StmtLR idL idR body -> [ExprLStmt idL]
+ Development.IDE.GHC.Compat: [trS_using] :: StmtLR idL idR body -> LHsExpr idR
+ Development.IDE.GHC.Compat: [trustFlags] :: DynFlags -> [TrustFlag]
+ Development.IDE.GHC.Compat: [trustworthyOnLoc] :: DynFlags -> SrcSpan
+ Development.IDE.GHC.Compat: [tyMap] :: HieTypeState -> !TypeMap TypeIndex
+ Development.IDE.GHC.Compat: [ufCreationThreshold] :: DynFlags -> Int
+ Development.IDE.GHC.Compat: [ufDearOp] :: DynFlags -> Int
+ Development.IDE.GHC.Compat: [ufDictDiscount] :: DynFlags -> Int
+ Development.IDE.GHC.Compat: [ufFunAppDiscount] :: DynFlags -> Int
+ Development.IDE.GHC.Compat: [ufKeenessFactor] :: DynFlags -> Float
+ Development.IDE.GHC.Compat: [ufUseThreshold] :: DynFlags -> Int
+ Development.IDE.GHC.Compat: [ufVeryAggressive] :: DynFlags -> Bool
+ Development.IDE.GHC.Compat: [uniqueIncrement] :: DynFlags -> Int
+ Development.IDE.GHC.Compat: [updateNameCache] :: NameCacheUpdater -> forall c. () => (NameCache -> (NameCache, c)) -> IO c
+ Development.IDE.GHC.Compat: [useColor] :: DynFlags -> OverridingBool
+ Development.IDE.GHC.Compat: [useUnicode] :: DynFlags -> Bool
+ Development.IDE.GHC.Compat: [var_ext] :: HsBindLR idL idR -> XVarBind idL idR
+ Development.IDE.GHC.Compat: [var_id] :: HsBindLR idL idR -> IdP idL
+ Development.IDE.GHC.Compat: [var_inline] :: HsBindLR idL idR -> Bool
+ Development.IDE.GHC.Compat: [var_rhs] :: HsBindLR idL idR -> LHsExpr idR
+ Development.IDE.GHC.Compat: [verbosity] :: DynFlags -> Int
+ Development.IDE.GHC.Compat: [warnSafeOnLoc] :: DynFlags -> SrcSpan
+ Development.IDE.GHC.Compat: [warnUnsafeOnLoc] :: DynFlags -> SrcSpan
+ Development.IDE.GHC.Compat: [warningFlags] :: DynFlags -> EnumSet WarningFlag
+ Development.IDE.GHC.Compat: [ways] :: DynFlags -> [Way]
+ Development.IDE.GHC.Compat: [wd_ext] :: WarnDecls pass -> XWarnings pass
+ Development.IDE.GHC.Compat: [wd_src] :: WarnDecls pass -> SourceText
+ Development.IDE.GHC.Compat: [wd_warnings] :: WarnDecls pass -> [LWarnDecl pass]
+ Development.IDE.GHC.Compat: abandon :: GhcMonad m => m Bool
+ Development.IDE.GHC.Compat: abandonAll :: GhcMonad m => m Bool
+ Development.IDE.GHC.Compat: addBootSuffix :: FilePath -> FilePath
+ Development.IDE.GHC.Compat: addCLoc :: () => Located a -> Located b -> c -> Located c
+ Development.IDE.GHC.Compat: addIncludePathsQuote :: FilePath -> DynFlags -> DynFlags
+ Development.IDE.GHC.Compat: addSourceToTokens :: RealSrcLoc -> StringBuffer -> [Located Token] -> [(Located Token, String)]
+ Development.IDE.GHC.Compat: addTarget :: GhcMonad m => Target -> m ()
+ Development.IDE.GHC.Compat: alphaTyVars :: [TyVar]
+ Development.IDE.GHC.Compat: alwaysQualify :: PrintUnqualified
+ Development.IDE.GHC.Compat: ambiguousFieldOcc :: FieldOcc GhcTc -> AmbiguousFieldOcc GhcTc
+ Development.IDE.GHC.Compat: annProvenanceName_maybe :: () => AnnProvenance name -> Maybe name
+ Development.IDE.GHC.Compat: appendDocs :: HsDocString -> HsDocString -> HsDocString
+ Development.IDE.GHC.Compat: appendGroups :: () => HsGroup (GhcPass p) -> HsGroup (GhcPass p) -> HsGroup (GhcPass p)
+ Development.IDE.GHC.Compat: back :: GhcMonad m => Int -> m ([Name], Int, SrcSpan, String)
+ Development.IDE.GHC.Compat: chunkify :: () => [a] -> [[a]]
+ Development.IDE.GHC.Compat: class Convertable a b | a -> b
+ Development.IDE.GHC.Compat: class (Functor m, MonadIO m, ExceptionMonad m, HasDynFlags m) => GhcMonad (m :: Type -> Type)
+ Development.IDE.GHC.Compat: class HasSrcSpan a
+ Development.IDE.GHC.Compat: class NamedThing a
+ Development.IDE.GHC.Compat: class ParsedMod m
+ Development.IDE.GHC.Compat: class ParsedMod m => TypecheckedMod m
+ Development.IDE.GHC.Compat: classATs :: Class -> [TyCon]
+ Development.IDE.GHC.Compat: classMethods :: Class -> [Id]
+ Development.IDE.GHC.Compat: classSCTheta :: Class -> [PredType]
+ Development.IDE.GHC.Compat: classTvsFds :: Class -> ([TyVar], [FunDep TyVar])
+ Development.IDE.GHC.Compat: cmpLocated :: Ord a => Located a -> Located a -> Ordering
+ Development.IDE.GHC.Compat: collectEvVarsPat :: Pat GhcTc -> Bag EvVar
+ Development.IDE.GHC.Compat: collectEvVarsPats :: [Pat GhcTc] -> Bag EvVar
+ Development.IDE.GHC.Compat: collectHsBindBinders :: () => HsBindLR idL idR -> [IdP idL]
+ Development.IDE.GHC.Compat: collectHsBindListBinders :: () => [LHsBindLR idL idR] -> [IdP idL]
+ Development.IDE.GHC.Compat: collectHsBindsBinders :: () => LHsBindsLR idL idR -> [IdP idL]
+ Development.IDE.GHC.Compat: collectHsIdBinders :: () => HsValBindsLR (GhcPass idL) (GhcPass idR) -> [IdP (GhcPass idL)]
+ Development.IDE.GHC.Compat: collectHsValBinders :: () => HsValBindsLR (GhcPass idL) (GhcPass idR) -> [IdP (GhcPass idL)]
+ Development.IDE.GHC.Compat: collectLStmtBinders :: () => LStmtLR (GhcPass idL) (GhcPass idR) body -> [IdP (GhcPass idL)]
+ Development.IDE.GHC.Compat: collectLStmtsBinders :: () => [LStmtLR (GhcPass idL) (GhcPass idR) body] -> [IdP (GhcPass idL)]
+ Development.IDE.GHC.Compat: collectLocalBinders :: () => HsLocalBindsLR (GhcPass idL) (GhcPass idR) -> [IdP (GhcPass idL)]
+ Development.IDE.GHC.Compat: collectMethodBinders :: () => LHsBindsLR idL idR -> [Located (IdP idL)]
+ Development.IDE.GHC.Compat: collectPatBinders :: () => LPat a -> [IdP a]
+ Development.IDE.GHC.Compat: collectPatsBinders :: () => [LPat a] -> [IdP a]
+ Development.IDE.GHC.Compat: collectRuleBndrSigTys :: () => [RuleBndr pass] -> [LHsSigWcType pass]
+ Development.IDE.GHC.Compat: collectStmtBinders :: () => StmtLR (GhcPass idL) (GhcPass idR) body -> [IdP (GhcPass idL)]
+ Development.IDE.GHC.Compat: collectStmtsBinders :: () => [StmtLR (GhcPass idL) (GhcPass idR) body] -> [IdP (GhcPass idL)]
+ Development.IDE.GHC.Compat: combineAst :: HieAST Type -> HieAST Type -> HieAST Type
+ Development.IDE.GHC.Compat: combineLocs :: () => Located a -> Located b -> SrcSpan
+ Development.IDE.GHC.Compat: combineNodeInfo :: NodeInfo Type -> NodeInfo Type -> NodeInfo Type
+ Development.IDE.GHC.Compat: combineScopes :: Scope -> Scope -> Scope
+ Development.IDE.GHC.Compat: compareFixity :: Fixity -> Fixity -> (Bool, Bool)
+ Development.IDE.GHC.Compat: compileExpr :: GhcMonad m => String -> m HValue
+ Development.IDE.GHC.Compat: compileExprRemote :: GhcMonad m => String -> m ForeignHValue
+ Development.IDE.GHC.Compat: compileParsedExpr :: GhcMonad m => LHsExpr GhcPs -> m HValue
+ Development.IDE.GHC.Compat: compileParsedExprRemote :: GhcMonad m => LHsExpr GhcPs -> m ForeignHValue
+ Development.IDE.GHC.Compat: compileToCoreModule :: GhcMonad m => FilePath -> m CoreModule
+ Development.IDE.GHC.Compat: compileToCoreSimplified :: GhcMonad m => FilePath -> m CoreModule
+ Development.IDE.GHC.Compat: compressTypes :: HieASTs Type -> (HieASTs TypeIndex, Array TypeIndex HieTypeFlat)
+ Development.IDE.GHC.Compat: concatDocs :: [HsDocString] -> Maybe HsDocString
+ Development.IDE.GHC.Compat: convert :: Convertable a b => a -> b
+ Development.IDE.GHC.Compat: convertLit :: ConvertIdX a b => HsLit a -> HsLit b
+ Development.IDE.GHC.Compat: coreModule :: DesugaredMod m => m -> ModGuts
+ Development.IDE.GHC.Compat: countTyClDecls :: () => [TyClDecl pass] -> (Int, Int, Int, Int, Int)
+ Development.IDE.GHC.Compat: cyclicModuleErr :: [ModSummary] -> SDoc
+ Development.IDE.GHC.Compat: data ABExport p
+ Development.IDE.GHC.Compat: data AmbiguousFieldOcc pass
+ Development.IDE.GHC.Compat: data AnnDecl pass
+ Development.IDE.GHC.Compat: data AnnKeywordId
+ Development.IDE.GHC.Compat: data AnnProvenance name
+ Development.IDE.GHC.Compat: data AnnotationComment
+ Development.IDE.GHC.Compat: data ApplicativeArg idL
+ Development.IDE.GHC.Compat: data ArithSeqInfo id
+ Development.IDE.GHC.Compat: data BindType
+ Development.IDE.GHC.Compat: data BreakInfo
+ Development.IDE.GHC.Compat: data CImportSpec
+ Development.IDE.GHC.Compat: data Class
+ Development.IDE.GHC.Compat: data ClsInst
+ Development.IDE.GHC.Compat: data ClsInstDecl pass
+ Development.IDE.GHC.Compat: data CmdTopTc
+ Development.IDE.GHC.Compat: data ConDecl pass
+ Development.IDE.GHC.Compat: data ConDeclField pass
+ Development.IDE.GHC.Compat: data ContextInfo
+ Development.IDE.GHC.Compat: data CoreModule
+ Development.IDE.GHC.Compat: data DataCon
+ Development.IDE.GHC.Compat: data DataDeclRn
+ Development.IDE.GHC.Compat: data DeclType
+ Development.IDE.GHC.Compat: data DefaultDecl pass
+ Development.IDE.GHC.Compat: data DerivDecl pass
+ Development.IDE.GHC.Compat: data DerivStrategy pass
+ Development.IDE.GHC.Compat: data DesugaredModule
+ Development.IDE.GHC.Compat: data DocDecl
+ Development.IDE.GHC.Compat: data DynFlags
+ Development.IDE.GHC.Compat: data ExecOptions
+ Development.IDE.GHC.Compat: data ExecResult
+ Development.IDE.GHC.Compat: data FamEqn pass pats rhs
+ Development.IDE.GHC.Compat: data FamInst
+ Development.IDE.GHC.Compat: data FamilyDecl pass
+ Development.IDE.GHC.Compat: data FamilyInfo pass
+ Development.IDE.GHC.Compat: data FamilyResultSig pass
+ Development.IDE.GHC.Compat: data FieldOcc pass
+ Development.IDE.GHC.Compat: data Fixity
+ Development.IDE.GHC.Compat: data FixityDirection
+ Development.IDE.GHC.Compat: data FixitySig pass
+ Development.IDE.GHC.Compat: data ForeignDecl pass
+ Development.IDE.GHC.Compat: data ForeignExport
+ Development.IDE.GHC.Compat: data ForeignImport
+ Development.IDE.GHC.Compat: data GRHS p body
+ Development.IDE.GHC.Compat: data GRHSs p body
+ Development.IDE.GHC.Compat: data GenLocated l e
+ Development.IDE.GHC.Compat: data GeneralFlag
+ Development.IDE.GHC.Compat: data GetDocsFailure
+ Development.IDE.GHC.Compat: data Ghc a
+ Development.IDE.GHC.Compat: data GhcException
+ Development.IDE.GHC.Compat: data GhcLink
+ Development.IDE.GHC.Compat: data GhcMode
+ Development.IDE.GHC.Compat: data GhcPass (c :: Pass)
+ Development.IDE.GHC.Compat: data GhcT (m :: Type -> Type) a
+ Development.IDE.GHC.Compat: data HValue
+ Development.IDE.GHC.Compat: data HieAST a
+ Development.IDE.GHC.Compat: data HieFile
+ Development.IDE.GHC.Compat: data HieFileResult
+ Development.IDE.GHC.Compat: data HieType a
+ Development.IDE.GHC.Compat: data HieTypeState
+ Development.IDE.GHC.Compat: data History
+ Development.IDE.GHC.Compat: data HsArrAppType
+ Development.IDE.GHC.Compat: data HsBindLR idL idR
+ Development.IDE.GHC.Compat: data HsBracket p
+ Development.IDE.GHC.Compat: data HsCmd id
+ Development.IDE.GHC.Compat: data HsCmdTop p
+ Development.IDE.GHC.Compat: data HsConDetails arg rec
+ Development.IDE.GHC.Compat: data HsDataDefn pass
+ Development.IDE.GHC.Compat: data HsDecl p
+ Development.IDE.GHC.Compat: data HsDerivingClause pass
+ Development.IDE.GHC.Compat: data HsDocString
+ Development.IDE.GHC.Compat: data HsExpr p
+ Development.IDE.GHC.Compat: data HsGroup p
+ Development.IDE.GHC.Compat: data HsIBRn
+ Development.IDE.GHC.Compat: data HsIPBinds id
+ Development.IDE.GHC.Compat: data HsImplBang
+ Development.IDE.GHC.Compat: data HsImplicitBndrs pass thing
+ Development.IDE.GHC.Compat: data HsLit x
+ Development.IDE.GHC.Compat: data HsLocalBindsLR idL idR
+ Development.IDE.GHC.Compat: data HsMatchContext id
+ Development.IDE.GHC.Compat: data HsModule pass
+ Development.IDE.GHC.Compat: data HsOverLit p
+ Development.IDE.GHC.Compat: data HsPatSynDir id
+ Development.IDE.GHC.Compat: data HsQTvsRn
+ Development.IDE.GHC.Compat: data HsRecField' id arg
+ Development.IDE.GHC.Compat: data HsRecFields p arg
+ Development.IDE.GHC.Compat: data HsRuleRn
+ Development.IDE.GHC.Compat: data HsSplice id
+ Development.IDE.GHC.Compat: data HsSplicedThing id
+ Development.IDE.GHC.Compat: data HsSrcBang
+ Development.IDE.GHC.Compat: data HsStmtContext id
+ Development.IDE.GHC.Compat: data HsTupArg id
+ Development.IDE.GHC.Compat: data HsTupleSort
+ Development.IDE.GHC.Compat: data HsTyLit
+ Development.IDE.GHC.Compat: data HsTyVarBndr pass
+ Development.IDE.GHC.Compat: data HsType pass
+ Development.IDE.GHC.Compat: data HsValBindsLR idL idR
+ Development.IDE.GHC.Compat: data HsWildCardBndrs pass thing
+ Development.IDE.GHC.Compat: data HscEnv
+ Development.IDE.GHC.Compat: data HscTarget
+ Development.IDE.GHC.Compat: data IE pass
+ Development.IDE.GHC.Compat: data IEType
+ Development.IDE.GHC.Compat: data IEWildcard
+ Development.IDE.GHC.Compat: data IEWrappedName name
+ Development.IDE.GHC.Compat: data IPBind id
+ Development.IDE.GHC.Compat: data IdentifierDetails a
+ Development.IDE.GHC.Compat: data ImportDecl pass
+ Development.IDE.GHC.Compat: data InjectivityAnn pass
+ Development.IDE.GHC.Compat: data InstDecl pass
+ Development.IDE.GHC.Compat: data InteractiveImport
+ Development.IDE.GHC.Compat: data LHsQTyVars pass
+ Development.IDE.GHC.Compat: data LexicalFixity
+ Development.IDE.GHC.Compat: data ListPatTc
+ Development.IDE.GHC.Compat: data LoadHowMuch
+ Development.IDE.GHC.Compat: data Match p body
+ Development.IDE.GHC.Compat: data MatchGroup p body
+ Development.IDE.GHC.Compat: data MatchGroupTc
+ Development.IDE.GHC.Compat: data ModBreaks
+ Development.IDE.GHC.Compat: data ModIface
+ Development.IDE.GHC.Compat: data ModLocation
+ Development.IDE.GHC.Compat: data ModSummary
+ Development.IDE.GHC.Compat: data Module
+ Development.IDE.GHC.Compat: data ModuleGraph
+ Development.IDE.GHC.Compat: data ModuleInfo
+ Development.IDE.GHC.Compat: data ModuleName
+ Development.IDE.GHC.Compat: data NHsValBindsLR idL
+ Development.IDE.GHC.Compat: data NPatBindTc
+ Development.IDE.GHC.Compat: data Name
+ Development.IDE.GHC.Compat: data NewHsTypeX
+ Development.IDE.GHC.Compat: data NewOrData
+ Development.IDE.GHC.Compat: data NoExt
+ Development.IDE.GHC.Compat: data NodeInfo a
+ Development.IDE.GHC.Compat: data OverLitTc
+ Development.IDE.GHC.Compat: data OverLitVal
+ Development.IDE.GHC.Compat: data ParStmtBlock idL idR
+ Development.IDE.GHC.Compat: data ParsedModule
+ Development.IDE.GHC.Compat: data Pass
+ Development.IDE.GHC.Compat: data Pat p
+ Development.IDE.GHC.Compat: data PendingRnSplice
+ Development.IDE.GHC.Compat: data PendingTcSplice
+ Development.IDE.GHC.Compat: data Phase
+ Development.IDE.GHC.Compat: data PrintUnqualified
+ Development.IDE.GHC.Compat: data Promoted
+ Development.IDE.GHC.Compat: data RdrName
+ Development.IDE.GHC.Compat: data RealSrcLoc
+ Development.IDE.GHC.Compat: data RealSrcSpan
+ Development.IDE.GHC.Compat: data RecFieldContext
+ Development.IDE.GHC.Compat: data RecStmtTc
+ Development.IDE.GHC.Compat: data RecordConTc
+ Development.IDE.GHC.Compat: data RecordPatSynField a
+ Development.IDE.GHC.Compat: data RecordUpdTc
+ Development.IDE.GHC.Compat: data Resume
+ Development.IDE.GHC.Compat: data RoleAnnotDecl pass
+ Development.IDE.GHC.Compat: data RuleBndr pass
+ Development.IDE.GHC.Compat: data RuleDecl pass
+ Development.IDE.GHC.Compat: data RuleDecls pass
+ Development.IDE.GHC.Compat: data SafeHaskellMode
+ Development.IDE.GHC.Compat: data Scope
+ Development.IDE.GHC.Compat: data Severity
+ Development.IDE.GHC.Compat: data Sig pass
+ Development.IDE.GHC.Compat: data SingleStep
+ Development.IDE.GHC.Compat: data SpliceDecl p
+ Development.IDE.GHC.Compat: data SpliceDecoration
+ Development.IDE.GHC.Compat: data SpliceExplicitFlag
+ Development.IDE.GHC.Compat: data SrcLoc
+ Development.IDE.GHC.Compat: data SrcSpan
+ Development.IDE.GHC.Compat: data SrcStrictness
+ Development.IDE.GHC.Compat: data SrcUnpackedness
+ Development.IDE.GHC.Compat: data StmtLR idL idR body
+ Development.IDE.GHC.Compat: data StrictnessMark
+ Development.IDE.GHC.Compat: data SuccessFlag
+ Development.IDE.GHC.Compat: data SyntaxExpr p
+ Development.IDE.GHC.Compat: data Target
+ Development.IDE.GHC.Compat: data TargetId
+ Development.IDE.GHC.Compat: data TcRnExprMode
+ Development.IDE.GHC.Compat: data TcSpecPrag
+ Development.IDE.GHC.Compat: data TcSpecPrags
+ Development.IDE.GHC.Compat: data Token
+ Development.IDE.GHC.Compat: data TransForm
+ Development.IDE.GHC.Compat: data TyClDecl pass
+ Development.IDE.GHC.Compat: data TyClGroup pass
+ Development.IDE.GHC.Compat: data TyCon
+ Development.IDE.GHC.Compat: data TyThing
+ Development.IDE.GHC.Compat: data TyVarScope
+ Development.IDE.GHC.Compat: data Type
+ Development.IDE.GHC.Compat: data TypecheckedModule
+ Development.IDE.GHC.Compat: data UnboundVar
+ Development.IDE.GHC.Compat: data UnitId
+ Development.IDE.GHC.Compat: data UntypedSpliceFlavour
+ Development.IDE.GHC.Compat: data WarnDecl pass
+ Development.IDE.GHC.Compat: data WarnDecls pass
+ Development.IDE.GHC.Compat: dataConFieldLabels :: DataCon -> [FieldLabel]
+ Development.IDE.GHC.Compat: dataConIsInfix :: DataCon -> Bool
+ Development.IDE.GHC.Compat: dataConSig :: DataCon -> ([TyVar], ThetaType, [Type], Type)
+ Development.IDE.GHC.Compat: dataConSrcBangs :: DataCon -> [HsSrcBang]
+ Development.IDE.GHC.Compat: dataConTyCon :: DataCon -> TyCon
+ Development.IDE.GHC.Compat: dataConType :: DataCon -> Type
+ Development.IDE.GHC.Compat: dataConUserType :: DataCon -> Type
+ Development.IDE.GHC.Compat: defaultCleanupHandler :: ExceptionMonad m => DynFlags -> m a -> m a
+ Development.IDE.GHC.Compat: defaultErrorHandler :: ExceptionMonad m => FatalMessager -> FlushOut -> m a -> m a
+ Development.IDE.GHC.Compat: defaultFixity :: Fixity
+ Development.IDE.GHC.Compat: defaultObjectTarget :: Platform -> HscTarget
+ Development.IDE.GHC.Compat: defaultWarnErrLogger :: WarnErrLogger
+ Development.IDE.GHC.Compat: definedInAsts :: Map FastString (HieAST a) -> Name -> Bool
+ Development.IDE.GHC.Compat: depanal :: GhcMonad m => [ModuleName] -> Bool -> m ModuleGraph
+ Development.IDE.GHC.Compat: derivStrategyName :: () => DerivStrategy a -> SDoc
+ Development.IDE.GHC.Compat: desugarModule :: GhcMonad m => TypecheckedModule -> m DesugaredModule
+ Development.IDE.GHC.Compat: docDeclDoc :: DocDecl -> HsDocString
+ Development.IDE.GHC.Compat: dontWriteHieFiles :: DynFlags -> DynFlags
+ Development.IDE.GHC.Compat: dropWildCards :: () => LHsSigWcType pass -> LHsSigType pass
+ Development.IDE.GHC.Compat: dynCompileExpr :: GhcMonad m => String -> m Dynamic
+ Development.IDE.GHC.Compat: emptyArgDocMap :: ArgDocMap
+ Development.IDE.GHC.Compat: emptyDeclDocMap :: DeclDocMap
+ Development.IDE.GHC.Compat: emptyLHsBinds :: () => LHsBindsLR idL idR
+ Development.IDE.GHC.Compat: emptyLHsQTvs :: LHsQTyVars GhcRn
+ Development.IDE.GHC.Compat: emptyLocalBinds :: () => HsLocalBindsLR (GhcPass a) (GhcPass b)
+ Development.IDE.GHC.Compat: emptyMG :: ModuleGraph
+ Development.IDE.GHC.Compat: emptyRdrGroup :: () => HsGroup (GhcPass p)
+ Development.IDE.GHC.Compat: emptyRecStmt :: () => StmtLR (GhcPass idL) GhcPs bodyR
+ Development.IDE.GHC.Compat: emptyRecStmtId :: () => StmtLR GhcTc GhcTc bodyR
+ Development.IDE.GHC.Compat: emptyRecStmtName :: () => StmtLR GhcRn GhcRn bodyR
+ Development.IDE.GHC.Compat: emptyRnGroup :: () => HsGroup (GhcPass p)
+ Development.IDE.GHC.Compat: emptyTransStmt :: StmtLR GhcPs GhcPs (LHsExpr GhcPs)
+ Development.IDE.GHC.Compat: emptyTyClGroup :: () => TyClGroup (GhcPass p)
+ Development.IDE.GHC.Compat: emptyValBindsIn :: () => HsValBindsLR (GhcPass a) (GhcPass b)
+ Development.IDE.GHC.Compat: emptyValBindsOut :: () => HsValBindsLR (GhcPass a) (GhcPass b)
+ Development.IDE.GHC.Compat: eqEmptyLocalBinds :: () => HsLocalBindsLR a b -> Bool
+ Development.IDE.GHC.Compat: eqLocated :: Eq a => Located a -> Located a -> Bool
+ Development.IDE.GHC.Compat: execOptions :: ExecOptions
+ Development.IDE.GHC.Compat: execStmt :: GhcMonad m => String -> ExecOptions -> m ExecResult
+ Development.IDE.GHC.Compat: exprType :: GhcMonad m => TcRnExprMode -> String -> m Type
+ Development.IDE.GHC.Compat: failed :: SuccessFlag -> Bool
+ Development.IDE.GHC.Compat: famDeclHasCusk :: () => Maybe Bool -> FamilyDecl pass -> Bool
+ Development.IDE.GHC.Compat: findGlobalAnns :: (GhcMonad m, Typeable a) => ([Word8] -> a) -> AnnTarget Name -> m [a]
+ Development.IDE.GHC.Compat: findModule :: GhcMonad m => ModuleName -> Maybe FastString -> m Module
+ Development.IDE.GHC.Compat: flattenAst :: HieAST a -> [HieAST a]
+ Development.IDE.GHC.Compat: flattenRuleDecls :: () => [LRuleDecls pass] -> [LRuleDecl pass]
+ Development.IDE.GHC.Compat: foldType :: (HieType a -> a) -> HieTypeFix -> a
+ Development.IDE.GHC.Compat: forward :: GhcMonad m => Int -> m ([Name], Int, SrcSpan, String)
+ Development.IDE.GHC.Compat: freshTypeIndex :: State HieTypeState TypeIndex
+ Development.IDE.GHC.Compat: funResultTy :: Type -> Type
+ Development.IDE.GHC.Compat: gbracket :: ExceptionMonad m => m a -> (a -> m b) -> (a -> m c) -> m c
+ Development.IDE.GHC.Compat: gcatch :: (ExceptionMonad m, Exception e) => m a -> (e -> m a) -> m a
+ Development.IDE.GHC.Compat: generateReferencesMap :: Foldable f => f (HieAST a) -> Map Identifier [(Span, IdentifierDetails a)]
+ Development.IDE.GHC.Compat: getAndRemoveAnnotation :: ApiAnns -> SrcSpan -> AnnKeywordId -> ([SrcSpan], ApiAnns)
+ Development.IDE.GHC.Compat: getAndRemoveAnnotationComments :: ApiAnns -> SrcSpan -> ([Located AnnotationComment], ApiAnns)
+ Development.IDE.GHC.Compat: getAnnotation :: ApiAnns -> SrcSpan -> AnnKeywordId -> [SrcSpan]
+ Development.IDE.GHC.Compat: getAnnotationComments :: ApiAnns -> SrcSpan -> [Located AnnotationComment]
+ Development.IDE.GHC.Compat: getBangStrictness :: () => LHsType a -> HsSrcBang
+ Development.IDE.GHC.Compat: getBangType :: () => LHsType a -> LHsType a
+ Development.IDE.GHC.Compat: getBindSiteFromContext :: ContextInfo -> Maybe Span
+ Development.IDE.GHC.Compat: getBindings :: GhcMonad m => m [TyThing]
+ Development.IDE.GHC.Compat: getConArgs :: ConDecl pass -> HsConDeclDetails pass
+ Development.IDE.GHC.Compat: getConNames :: () => ConDecl pass -> [Located (IdP pass)]
+ Development.IDE.GHC.Compat: getContext :: GhcMonad m => m [InteractiveImport]
+ Development.IDE.GHC.Compat: getDocs :: GhcMonad m => Name -> m (Either GetDocsFailure (Maybe HsDocString, Map Int HsDocString))
+ Development.IDE.GHC.Compat: getGHCiMonad :: GhcMonad m => m Name
+ Development.IDE.GHC.Compat: getGRE :: GhcMonad m => m GlobalRdrEnv
+ Development.IDE.GHC.Compat: getHeaderImports :: DynFlags -> StringBuffer -> FilePath -> FilePath -> IO (Either ErrorMessages ([(Maybe FastString, Located ModuleName)], [(Maybe FastString, Located ModuleName)], Located ModuleName))
+ Development.IDE.GHC.Compat: getHistoryModule :: History -> Module
+ Development.IDE.GHC.Compat: getHistorySpan :: GhcMonad m => History -> m SrcSpan
+ Development.IDE.GHC.Compat: getInfo :: GhcMonad m => Bool -> Name -> m (Maybe (TyThing, Fixity, [ClsInst], [FamInst], SDoc))
+ Development.IDE.GHC.Compat: getInsts :: GhcMonad m => m ([ClsInst], [FamInst])
+ Development.IDE.GHC.Compat: getInteractiveDynFlags :: GhcMonad m => m DynFlags
+ Development.IDE.GHC.Compat: getLHsInstDeclClass_maybe :: () => LHsSigType (GhcPass p) -> Maybe (Located (IdP (GhcPass p)))
+ Development.IDE.GHC.Compat: getLHsInstDeclHead :: () => LHsSigType pass -> LHsType pass
+ Development.IDE.GHC.Compat: getLoc :: HasSrcSpan a => a -> SrcSpan
+ Development.IDE.GHC.Compat: getModSummary :: GhcMonad m => ModuleName -> m ModSummary
+ Development.IDE.GHC.Compat: getModuleGraph :: GhcMonad m => m ModuleGraph
+ Development.IDE.GHC.Compat: getModuleHash :: ModIface -> Fingerprint
+ Development.IDE.GHC.Compat: getModuleInfo :: GhcMonad m => Module -> m (Maybe ModuleInfo)
+ Development.IDE.GHC.Compat: getName :: NamedThing a => a -> Name
+ Development.IDE.GHC.Compat: getNameBinding :: Name -> Map FastString (HieAST a) -> Maybe Span
+ Development.IDE.GHC.Compat: getNameBindingInClass :: Name -> Span -> Map FastString (HieAST a) -> Maybe Span
+ Development.IDE.GHC.Compat: getNameScope :: Name -> Map FastString (HieAST a) -> Maybe [Scope]
+ Development.IDE.GHC.Compat: getNameScopeAndBinding :: Name -> Map FastString (HieAST a) -> Maybe ([Scope], Maybe Span)
+ Development.IDE.GHC.Compat: getNameToInstancesIndex :: GhcMonad m => [Module] -> Maybe [Module] -> m (Messages, Maybe (NameEnv ([ClsInst], [FamInst])))
+ Development.IDE.GHC.Compat: getNamesInScope :: GhcMonad m => m [Name]
+ Development.IDE.GHC.Compat: getOccName :: NamedThing a => a -> OccName
+ Development.IDE.GHC.Compat: getPackageName :: DynFlags -> InstalledUnitId -> Maybe PackageName
+ Development.IDE.GHC.Compat: getPatSynBinds :: () => [(RecFlag, LHsBinds id)] -> [PatSynBind id id]
+ Development.IDE.GHC.Compat: getPrintUnqual :: GhcMonad m => m PrintUnqualified
+ Development.IDE.GHC.Compat: getProgramDynFlags :: GhcMonad m => m DynFlags
+ Development.IDE.GHC.Compat: getRdrNamesInScope :: GhcMonad m => m [RdrName]
+ Development.IDE.GHC.Compat: getResumeContext :: GhcMonad m => m [Resume]
+ Development.IDE.GHC.Compat: getRichTokenStream :: GhcMonad m => Module -> m [(Located Token, String)]
+ Development.IDE.GHC.Compat: getScopeFromContext :: ContextInfo -> Maybe [Scope]
+ Development.IDE.GHC.Compat: getSession :: GhcMonad m => m HscEnv
+ Development.IDE.GHC.Compat: getSessionDynFlags :: GhcMonad m => m DynFlags
+ Development.IDE.GHC.Compat: getTargets :: GhcMonad m => m [Target]
+ Development.IDE.GHC.Compat: getTokenStream :: GhcMonad m => Module -> m [Located Token]
+ Development.IDE.GHC.Compat: getTypeIndex :: Type -> State HieTypeState TypeIndex
+ Development.IDE.GHC.Compat: gfinally :: ExceptionMonad m => m a -> m b -> m a
+ Development.IDE.GHC.Compat: gopt :: GeneralFlag -> DynFlags -> Bool
+ Development.IDE.GHC.Compat: guessTarget :: GhcMonad m => String -> Maybe Phase -> m Target
+ Development.IDE.GHC.Compat: hPutStringBuffer :: Handle -> StringBuffer -> IO ()
+ Development.IDE.GHC.Compat: handleSourceError :: ExceptionMonad m => (SourceError -> m a) -> m a -> m a
+ Development.IDE.GHC.Compat: hasImport :: DynFlags -> String -> Bool
+ Development.IDE.GHC.Compat: hasSpecPrags :: TcSpecPrags -> Bool
+ Development.IDE.GHC.Compat: hieExportNames :: HieFile -> [(SrcSpan, Name)]
+ Development.IDE.GHC.Compat: hieTypeToIface :: HieTypeFix -> IfaceType
+ Development.IDE.GHC.Compat: hieVersion :: Integer
+ Development.IDE.GHC.Compat: hsAllLTyVarNames :: LHsQTyVars GhcRn -> [Name]
+ Development.IDE.GHC.Compat: hsConDeclArgTys :: () => HsConDeclDetails pass -> [LBangType pass]
+ Development.IDE.GHC.Compat: hsConDeclTheta :: () => Maybe (LHsContext pass) -> [LHsType pass]
+ Development.IDE.GHC.Compat: hsConPatArgs :: () => HsConPatDetails p -> [LPat p]
+ Development.IDE.GHC.Compat: hsDataFamInstBinders :: () => DataFamInstDecl pass -> ([Located (IdP pass)], [LFieldOcc pass])
+ Development.IDE.GHC.Compat: hsDeclHasCusk :: TyClDecl GhcRn -> Bool
+ Development.IDE.GHC.Compat: hsDocStringToByteString :: HsDocString -> ByteString
+ Development.IDE.GHC.Compat: hsExplicitLTyVarNames :: () => LHsQTyVars pass -> [IdP pass]
+ Development.IDE.GHC.Compat: hsExprNeedsParens :: () => PprPrec -> HsExpr p -> Bool
+ Development.IDE.GHC.Compat: hsForeignDeclsBinders :: () => [LForeignDecl pass] -> [Located (IdP pass)]
+ Development.IDE.GHC.Compat: hsGroupBinders :: HsGroup GhcRn -> [Name]
+ Development.IDE.GHC.Compat: hsGroupInstDecls :: () => HsGroup id -> [LInstDecl id]
+ Development.IDE.GHC.Compat: hsIPNameFS :: HsIPName -> FastString
+ Development.IDE.GHC.Compat: hsImplicitBody :: () => HsImplicitBndrs pass thing -> thing
+ Development.IDE.GHC.Compat: hsLMatchPats :: () => LMatch id body -> [LPat id]
+ Development.IDE.GHC.Compat: hsLTyClDeclBinders :: () => Located (TyClDecl pass) -> ([Located (IdP pass)], [LFieldOcc pass])
+ Development.IDE.GHC.Compat: hsLTyVarBndrToType :: () => LHsTyVarBndr (GhcPass p) -> LHsType (GhcPass p)
+ Development.IDE.GHC.Compat: hsLTyVarBndrsToTypes :: () => LHsQTyVars (GhcPass p) -> [LHsType (GhcPass p)]
+ Development.IDE.GHC.Compat: hsLTyVarLocName :: () => LHsTyVarBndr pass -> Located (IdP pass)
+ Development.IDE.GHC.Compat: hsLTyVarLocNames :: () => LHsQTyVars pass -> [Located (IdP pass)]
+ Development.IDE.GHC.Compat: hsLTyVarName :: () => LHsTyVarBndr pass -> IdP pass
+ Development.IDE.GHC.Compat: hsLitNeedsParens :: () => PprPrec -> HsLit x -> Bool
+ Development.IDE.GHC.Compat: hsOverLitNeedsParens :: () => PprPrec -> HsOverLit x -> Bool
+ Development.IDE.GHC.Compat: hsPatSynSelectors :: () => HsValBinds (GhcPass p) -> [IdP (GhcPass p)]
+ Development.IDE.GHC.Compat: hsQTvExplicit :: () => LHsQTyVars pass -> [LHsTyVarBndr pass]
+ Development.IDE.GHC.Compat: hsRecFieldId :: () => HsRecField GhcTc arg -> Located Id
+ Development.IDE.GHC.Compat: hsRecFieldSel :: () => HsRecField pass arg -> Located (XCFieldOcc pass)
+ Development.IDE.GHC.Compat: hsRecFields :: () => HsRecFields p arg -> [XCFieldOcc p]
+ Development.IDE.GHC.Compat: hsRecFieldsArgs :: () => HsRecFields p arg -> [arg]
+ Development.IDE.GHC.Compat: hsRecUpdFieldId :: () => HsRecField' (AmbiguousFieldOcc GhcTc) arg -> Located Id
+ Development.IDE.GHC.Compat: hsRecUpdFieldOcc :: () => HsRecField' (AmbiguousFieldOcc GhcTc) arg -> LFieldOcc GhcTc
+ Development.IDE.GHC.Compat: hsRecUpdFieldRdr :: () => HsRecUpdField (GhcPass p) -> Located RdrName
+ Development.IDE.GHC.Compat: hsScopedTvs :: LHsSigType GhcRn -> [Name]
+ Development.IDE.GHC.Compat: hsSigDoc :: () => Sig name -> SDoc
+ Development.IDE.GHC.Compat: hsSigType :: () => LHsSigType pass -> LHsType pass
+ Development.IDE.GHC.Compat: hsSigWcType :: () => LHsSigWcType pass -> LHsType pass
+ Development.IDE.GHC.Compat: hsTvbAllKinded :: () => LHsQTyVars pass -> Bool
+ Development.IDE.GHC.Compat: hsTyClForeignBinders :: [TyClGroup GhcRn] -> [LForeignDecl GhcRn] -> [Name]
+ Development.IDE.GHC.Compat: hsTyGetAppHead_maybe :: () => LHsType (GhcPass p) -> Maybe (Located (IdP (GhcPass p)), [LHsType (GhcPass p)])
+ Development.IDE.GHC.Compat: hsTyVarName :: () => HsTyVarBndr pass -> IdP pass
+ Development.IDE.GHC.Compat: hsTypeNeedsParens :: () => PprPrec -> HsType pass -> Bool
+ Development.IDE.GHC.Compat: hsValBindsImplicits :: () => HsValBindsLR GhcRn (GhcPass idR) -> NameSet
+ Development.IDE.GHC.Compat: hsWcScopedTvs :: LHsSigWcType GhcRn -> [Name]
+ Development.IDE.GHC.Compat: idDataCon :: Id -> DataCon
+ Development.IDE.GHC.Compat: idType :: Id -> Kind
+ Development.IDE.GHC.Compat: ieLWrappedName :: () => LIEWrappedName name -> Located name
+ Development.IDE.GHC.Compat: ieName :: () => IE pass -> IdP pass
+ Development.IDE.GHC.Compat: ieNames :: () => IE pass -> [IdP pass]
+ Development.IDE.GHC.Compat: ieWrappedName :: () => IEWrappedName name -> name
+ Development.IDE.GHC.Compat: ignoreParens :: () => LHsType pass -> LHsType pass
+ Development.IDE.GHC.Compat: includePathsGlobal :: IncludeSpecs -> [String]
+ Development.IDE.GHC.Compat: includePathsQuote :: IncludeSpecs -> [String]
+ Development.IDE.GHC.Compat: initGhcMonad :: GhcMonad m => Maybe FilePath -> m ()
+ Development.IDE.GHC.Compat: initialHTS :: HieTypeState
+ Development.IDE.GHC.Compat: insertAst :: HieAST Type -> [HieAST Type] -> [HieAST Type]
+ Development.IDE.GHC.Compat: instDeclDataFamInsts :: () => [LInstDecl pass] -> [DataFamInstDecl pass]
+ Development.IDE.GHC.Compat: instance Development.IDE.GHC.Compat.HasSrcSpan (SrcLoc.GenLocated SrcLoc.SrcSpan a)
+ Development.IDE.GHC.Compat: instance Development.IDE.GHC.Compat.HasSrcSpan Name.Name
+ Development.IDE.GHC.Compat: instanceDFunId :: ClsInst -> DFunId
+ Development.IDE.GHC.Compat: isAtomicHsExpr :: () => HsExpr id -> Bool
+ Development.IDE.GHC.Compat: isBangedHsBind :: HsBind GhcTc -> Bool
+ Development.IDE.GHC.Compat: isBangedLPat :: () => LPat p -> Bool
+ Development.IDE.GHC.Compat: isBottomingId :: Var -> Bool
+ Development.IDE.GHC.Compat: isClassDecl :: () => TyClDecl pass -> Bool
+ Development.IDE.GHC.Compat: isClassOpId_maybe :: Id -> Maybe Class
+ Development.IDE.GHC.Compat: isClassTyCon :: TyCon -> Bool
+ Development.IDE.GHC.Compat: isClosedTypeFamilyInfo :: () => FamilyInfo pass -> Bool
+ Development.IDE.GHC.Compat: isCompleteMatchSig :: () => LSig name -> Bool
+ Development.IDE.GHC.Compat: isDataConWorkId :: Id -> Bool
+ Development.IDE.GHC.Compat: isDataDecl :: () => TyClDecl pass -> Bool
+ Development.IDE.GHC.Compat: isDataFamilyDecl :: () => TyClDecl pass -> Bool
+ Development.IDE.GHC.Compat: isDeadBinder :: Id -> Bool
+ Development.IDE.GHC.Compat: isDecl :: DynFlags -> String -> Bool
+ Development.IDE.GHC.Compat: isDefaultMethod :: TcSpecPrags -> Bool
+ Development.IDE.GHC.Compat: isDictonaryId :: Id -> Bool
+ Development.IDE.GHC.Compat: isEmptyIPBindsPR :: () => HsIPBinds (GhcPass p) -> Bool
+ Development.IDE.GHC.Compat: isEmptyIPBindsTc :: HsIPBinds GhcTc -> Bool
+ Development.IDE.GHC.Compat: isEmptyLHsBinds :: () => LHsBindsLR idL idR -> Bool
+ Development.IDE.GHC.Compat: isEmptyLHsQTvs :: LHsQTyVars GhcRn -> Bool
+ Development.IDE.GHC.Compat: isEmptyLocalBindsPR :: () => HsLocalBindsLR (GhcPass a) (GhcPass b) -> Bool
+ Development.IDE.GHC.Compat: isEmptyLocalBindsTc :: () => HsLocalBindsLR (GhcPass a) GhcTc -> Bool
+ Development.IDE.GHC.Compat: isEmptyMatchGroup :: () => MatchGroup id body -> Bool
+ Development.IDE.GHC.Compat: isEmptyValBinds :: () => HsValBindsLR (GhcPass a) (GhcPass b) -> Bool
+ Development.IDE.GHC.Compat: isExportedId :: Var -> Bool
+ Development.IDE.GHC.Compat: isExternalName :: Name -> Bool
+ Development.IDE.GHC.Compat: isFCallId :: Id -> Bool
+ Development.IDE.GHC.Compat: isFamilyDecl :: () => TyClDecl pass -> Bool
+ Development.IDE.GHC.Compat: isFamilyTyCon :: TyCon -> Bool
+ Development.IDE.GHC.Compat: isFixityLSig :: () => LSig name -> Bool
+ Development.IDE.GHC.Compat: isFunTyCon :: TyCon -> Bool
+ Development.IDE.GHC.Compat: isGlobalId :: Var -> Bool
+ Development.IDE.GHC.Compat: isGoodSrcSpan :: SrcSpan -> Bool
+ Development.IDE.GHC.Compat: isHsKindedTyVar :: () => HsTyVarBndr pass -> Bool
+ Development.IDE.GHC.Compat: isImplicitId :: Id -> Bool
+ Development.IDE.GHC.Compat: isImport :: DynFlags -> String -> Bool
+ Development.IDE.GHC.Compat: isInfixFunBind :: () => HsBindLR id1 id2 -> Bool
+ Development.IDE.GHC.Compat: isInfixMatch :: () => Match id body -> Bool
+ Development.IDE.GHC.Compat: isInlineLSig :: () => LSig name -> Bool
+ Development.IDE.GHC.Compat: isIrrefutableHsPat :: OutputableBndrId p => LPat p -> Bool
+ Development.IDE.GHC.Compat: isLHsForAllTy :: () => LHsType p -> Bool
+ Development.IDE.GHC.Compat: isListCompExpr :: () => HsStmtContext id -> Bool
+ Development.IDE.GHC.Compat: isLoaded :: GhcMonad m => ModuleName -> m Bool
+ Development.IDE.GHC.Compat: isLocalId :: Var -> Bool
+ Development.IDE.GHC.Compat: isMarkedStrict :: StrictnessMark -> Bool
+ Development.IDE.GHC.Compat: isMinimalLSig :: () => LSig name -> Bool
+ Development.IDE.GHC.Compat: isModuleTrusted :: GhcMonad m => Module -> m Bool
+ Development.IDE.GHC.Compat: isMonadFailStmtContext :: () => HsStmtContext id -> Bool
+ Development.IDE.GHC.Compat: isNewTyCon :: TyCon -> Bool
+ Development.IDE.GHC.Compat: isOccurrence :: ContextInfo -> Bool
+ Development.IDE.GHC.Compat: isOpenFamilyTyCon :: TyCon -> Bool
+ Development.IDE.GHC.Compat: isOpenTypeFamilyInfo :: () => FamilyInfo pass -> Bool
+ Development.IDE.GHC.Compat: isOpenTypeFamilyTyCon :: TyCon -> Bool
+ Development.IDE.GHC.Compat: isPatSynCtxt :: () => HsMatchContext id -> Bool
+ Development.IDE.GHC.Compat: isPragLSig :: () => LSig name -> Bool
+ Development.IDE.GHC.Compat: isPrimOpId :: Id -> Bool
+ Development.IDE.GHC.Compat: isPrimTyCon :: TyCon -> Bool
+ Development.IDE.GHC.Compat: isQuietHsCmd :: () => HsCmd id -> Bool
+ Development.IDE.GHC.Compat: isQuietHsExpr :: () => HsExpr id -> Bool
+ Development.IDE.GHC.Compat: isRecordSelector :: Id -> Bool
+ Development.IDE.GHC.Compat: isSCCFunSig :: () => LSig name -> Bool
+ Development.IDE.GHC.Compat: isSingletonMatchGroup :: () => [LMatch id body] -> Bool
+ Development.IDE.GHC.Compat: isSpecInstLSig :: () => LSig name -> Bool
+ Development.IDE.GHC.Compat: isSpecLSig :: () => LSig name -> Bool
+ Development.IDE.GHC.Compat: isStmt :: DynFlags -> String -> Bool
+ Development.IDE.GHC.Compat: isSubspanOf :: SrcSpan -> SrcSpan -> Bool
+ Development.IDE.GHC.Compat: isSynDecl :: () => TyClDecl pass -> Bool
+ Development.IDE.GHC.Compat: isTypeFamilyDecl :: () => TyClDecl pass -> Bool
+ Development.IDE.GHC.Compat: isTypeFamilyTyCon :: TyCon -> Bool
+ Development.IDE.GHC.Compat: isTypeLSig :: () => LSig name -> Bool
+ Development.IDE.GHC.Compat: isTypeSynonymTyCon :: TyCon -> Bool
+ Development.IDE.GHC.Compat: isTypedBracket :: () => HsBracket id -> Bool
+ Development.IDE.GHC.Compat: isTypedSplice :: () => HsSplice id -> Bool
+ Development.IDE.GHC.Compat: isUnliftedHsBind :: HsBind GhcTc -> Bool
+ Development.IDE.GHC.Compat: isVanillaDataCon :: DataCon -> Bool
+ Development.IDE.GHC.Compat: lPatImplicits :: LPat GhcRn -> NameSet
+ Development.IDE.GHC.Compat: lStmtsImplicits :: () => [LStmtLR GhcRn (GhcPass idR) (Located (body (GhcPass idR)))] -> NameSet
+ Development.IDE.GHC.Compat: leftOf :: Span -> Span -> Bool
+ Development.IDE.GHC.Compat: leftmost_largest :: SrcSpan -> SrcSpan -> Ordering
+ Development.IDE.GHC.Compat: leftmost_smallest :: SrcSpan -> SrcSpan -> Ordering
+ Development.IDE.GHC.Compat: load :: GhcMonad m => LoadHowMuch -> m SuccessFlag
+ Development.IDE.GHC.Compat: loadModule :: (TypecheckedMod mod, GhcMonad m) => mod -> m mod
+ Development.IDE.GHC.Compat: locOnly :: SrcSpan -> [HieAST a]
+ Development.IDE.GHC.Compat: looksLazyPatBind :: () => HsBind p -> Bool
+ Development.IDE.GHC.Compat: lookupGlobalName :: GhcMonad m => Name -> m (Maybe TyThing)
+ Development.IDE.GHC.Compat: lookupModule :: GhcMonad m => ModuleName -> Maybe FastString -> m Module
+ Development.IDE.GHC.Compat: makeNode :: (Applicative m, Data a) => a -> SrcSpan -> m [HieAST b]
+ Development.IDE.GHC.Compat: makeTypeNode :: (Applicative m, Data a) => a -> SrcSpan -> Type -> m [HieAST Type]
+ Development.IDE.GHC.Compat: mapMG :: (ModSummary -> ModSummary) -> ModuleGraph -> ModuleGraph
+ Development.IDE.GHC.Compat: matchContextErrString :: Outputable id => HsMatchContext id -> SDoc
+ Development.IDE.GHC.Compat: matchGroupArity :: () => MatchGroup id body -> Arity
+ Development.IDE.GHC.Compat: matchSeparator :: () => HsMatchContext id -> SDoc
+ Development.IDE.GHC.Compat: maxPrecedence :: Int
+ Development.IDE.GHC.Compat: mergeAsts :: [HieAST Type] -> [HieAST Type] -> [HieAST Type]
+ Development.IDE.GHC.Compat: mergeSortAsts :: [HieAST Type] -> [HieAST Type]
+ Development.IDE.GHC.Compat: mgLookupModule :: ModuleGraph -> Module -> Maybe ModSummary
+ Development.IDE.GHC.Compat: mgModSummaries :: ModuleGraph -> [ModSummary]
+ Development.IDE.GHC.Compat: missingTupArg :: HsTupArg GhcPs
+ Development.IDE.GHC.Compat: mkAmbiguousFieldOcc :: Located RdrName -> AmbiguousFieldOcc GhcPs
+ Development.IDE.GHC.Compat: mkAnonWildCardTy :: HsType GhcPs
+ Development.IDE.GHC.Compat: mkBigLHsPatTup :: [LPat GhcRn] -> LPat GhcRn
+ Development.IDE.GHC.Compat: mkBigLHsTup :: () => [LHsExpr (GhcPass id)] -> LHsExpr (GhcPass id)
+ Development.IDE.GHC.Compat: mkBigLHsVarPatTup :: [IdP GhcRn] -> LPat GhcRn
+ Development.IDE.GHC.Compat: mkBigLHsVarTup :: () => [IdP (GhcPass id)] -> LHsExpr (GhcPass id)
+ Development.IDE.GHC.Compat: mkBindStmt :: XBindStmt (GhcPass idL) (GhcPass idR) (Located (bodyR (GhcPass idR))) ~ NoExt => LPat (GhcPass idL) -> Located (bodyR (GhcPass idR)) -> StmtLR (GhcPass idL) (GhcPass idR) (Located (bodyR (GhcPass idR)))
+ Development.IDE.GHC.Compat: mkBodyStmt :: () => Located (bodyR GhcPs) -> StmtLR (GhcPass idL) GhcPs (Located (bodyR GhcPs))
+ Development.IDE.GHC.Compat: mkCharLitPat :: () => SourceText -> Char -> OutPat (GhcPass p)
+ Development.IDE.GHC.Compat: mkChunkified :: () => ([a] -> a) -> [a] -> a
+ Development.IDE.GHC.Compat: mkClassOpSigs :: [LSig GhcPs] -> [LSig GhcPs]
+ Development.IDE.GHC.Compat: mkEmptyImplicitBndrs :: () => thing -> HsImplicitBndrs GhcRn thing
+ Development.IDE.GHC.Compat: mkEmptyWildCardBndrs :: () => thing -> HsWildCardBndrs GhcRn thing
+ Development.IDE.GHC.Compat: mkFieldOcc :: Located RdrName -> FieldOcc GhcPs
+ Development.IDE.GHC.Compat: mkFunBind :: Located RdrName -> [LMatch GhcPs (LHsExpr GhcPs)] -> HsBind GhcPs
+ Development.IDE.GHC.Compat: mkGeneralLocated :: () => String -> e -> Located e
+ Development.IDE.GHC.Compat: mkGroupByUsingStmt :: [ExprLStmt GhcPs] -> LHsExpr GhcPs -> LHsExpr GhcPs -> StmtLR GhcPs GhcPs (LHsExpr GhcPs)
+ Development.IDE.GHC.Compat: mkGroupUsingStmt :: [ExprLStmt GhcPs] -> LHsExpr GhcPs -> StmtLR GhcPs GhcPs (LHsExpr GhcPs)
+ Development.IDE.GHC.Compat: mkHieFile :: ModSummary -> TcGblEnv -> RenamedSource -> ByteString -> Hsc HieFile
+ Development.IDE.GHC.Compat: mkHsApp :: () => LHsExpr (GhcPass id) -> LHsExpr (GhcPass id) -> LHsExpr (GhcPass id)
+ Development.IDE.GHC.Compat: mkHsAppTy :: () => LHsType (GhcPass p) -> LHsType (GhcPass p) -> LHsType (GhcPass p)
+ Development.IDE.GHC.Compat: mkHsAppType :: XAppTypeE (GhcPass id) ~ LHsWcType GhcRn => LHsExpr (GhcPass id) -> LHsWcType GhcRn -> LHsExpr (GhcPass id)
+ Development.IDE.GHC.Compat: mkHsAppTypes :: LHsExpr GhcRn -> [LHsWcType GhcRn] -> LHsExpr GhcRn
+ Development.IDE.GHC.Compat: mkHsAppTys :: () => LHsType (GhcPass p) -> [LHsType (GhcPass p)] -> LHsType (GhcPass p)
+ Development.IDE.GHC.Compat: mkHsCaseAlt :: () => LPat (GhcPass p) -> Located (body (GhcPass p)) -> LMatch (GhcPass p) (Located (body (GhcPass p)))
+ Development.IDE.GHC.Compat: mkHsCmdWrap :: () => HsWrapper -> HsCmd (GhcPass p) -> HsCmd (GhcPass p)
+ Development.IDE.GHC.Compat: mkHsComp :: HsStmtContext Name -> [ExprLStmt GhcPs] -> LHsExpr GhcPs -> HsExpr GhcPs
+ Development.IDE.GHC.Compat: mkHsDictLet :: TcEvBinds -> LHsExpr GhcTc -> LHsExpr GhcTc
+ Development.IDE.GHC.Compat: mkHsDo :: HsStmtContext Name -> [ExprLStmt GhcPs] -> HsExpr GhcPs
+ Development.IDE.GHC.Compat: mkHsDocString :: String -> HsDocString
+ Development.IDE.GHC.Compat: mkHsDocStringUtf8ByteString :: ByteString -> HsDocString
+ Development.IDE.GHC.Compat: mkHsFractional :: FractionalLit -> HsOverLit GhcPs
+ Development.IDE.GHC.Compat: mkHsIf :: () => LHsExpr (GhcPass p) -> LHsExpr (GhcPass p) -> LHsExpr (GhcPass p) -> HsExpr (GhcPass p)
+ Development.IDE.GHC.Compat: mkHsImplicitBndrs :: () => thing -> HsImplicitBndrs GhcPs thing
+ Development.IDE.GHC.Compat: mkHsIntegral :: IntegralLit -> HsOverLit GhcPs
+ Development.IDE.GHC.Compat: mkHsIsString :: SourceText -> FastString -> HsOverLit GhcPs
+ Development.IDE.GHC.Compat: mkHsLam :: [LPat GhcPs] -> LHsExpr GhcPs -> LHsExpr GhcPs
+ Development.IDE.GHC.Compat: mkHsLams :: [TyVar] -> [EvVar] -> LHsExpr GhcTc -> LHsExpr GhcTc
+ Development.IDE.GHC.Compat: mkHsOpApp :: LHsExpr GhcPs -> IdP GhcPs -> LHsExpr GhcPs -> HsExpr GhcPs
+ Development.IDE.GHC.Compat: mkHsOpTy :: () => LHsType (GhcPass p) -> Located (IdP (GhcPass p)) -> LHsType (GhcPass p) -> HsType (GhcPass p)
+ Development.IDE.GHC.Compat: mkHsPar :: () => LHsExpr (GhcPass id) -> LHsExpr (GhcPass id)
+ Development.IDE.GHC.Compat: mkHsQTvs :: [LHsTyVarBndr GhcPs] -> LHsQTyVars GhcPs
+ Development.IDE.GHC.Compat: mkHsQuasiQuote :: RdrName -> SrcSpan -> FastString -> HsSplice GhcPs
+ Development.IDE.GHC.Compat: mkHsSigEnv :: () => (LSig GhcRn -> Maybe ([Located Name], a)) -> [LSig GhcRn] -> NameEnv a
+ Development.IDE.GHC.Compat: mkHsSpliceE :: SpliceDecoration -> LHsExpr GhcPs -> HsExpr GhcPs
+ Development.IDE.GHC.Compat: mkHsSpliceTE :: SpliceDecoration -> LHsExpr GhcPs -> HsExpr GhcPs
+ Development.IDE.GHC.Compat: mkHsSpliceTy :: SpliceDecoration -> LHsExpr GhcPs -> HsType GhcPs
+ Development.IDE.GHC.Compat: mkHsString :: () => String -> HsLit (GhcPass p)
+ Development.IDE.GHC.Compat: mkHsStringPrimLit :: () => FastString -> HsLit (GhcPass p)
+ Development.IDE.GHC.Compat: mkHsVarBind :: SrcSpan -> RdrName -> LHsExpr GhcPs -> LHsBind GhcPs
+ Development.IDE.GHC.Compat: mkHsWildCardBndrs :: () => thing -> HsWildCardBndrs GhcPs thing
+ Development.IDE.GHC.Compat: mkHsWrap :: () => HsWrapper -> HsExpr (GhcPass id) -> HsExpr (GhcPass id)
+ Development.IDE.GHC.Compat: mkHsWrapCo :: () => TcCoercionN -> HsExpr (GhcPass id) -> HsExpr (GhcPass id)
+ Development.IDE.GHC.Compat: mkHsWrapCoR :: () => TcCoercionR -> HsExpr (GhcPass id) -> HsExpr (GhcPass id)
+ Development.IDE.GHC.Compat: mkHsWrapPat :: () => HsWrapper -> Pat (GhcPass id) -> Type -> Pat (GhcPass id)
+ Development.IDE.GHC.Compat: mkHsWrapPatCo :: () => TcCoercionN -> Pat (GhcPass id) -> Type -> Pat (GhcPass id)
+ Development.IDE.GHC.Compat: mkLHsCmdWrap :: () => HsWrapper -> LHsCmd (GhcPass p) -> LHsCmd (GhcPass p)
+ Development.IDE.GHC.Compat: mkLHsPar :: () => LHsExpr (GhcPass id) -> LHsExpr (GhcPass id)
+ Development.IDE.GHC.Compat: mkLHsSigType :: LHsType GhcPs -> LHsSigType GhcPs
+ Development.IDE.GHC.Compat: mkLHsSigWcType :: LHsType GhcPs -> LHsSigWcType GhcPs
+ Development.IDE.GHC.Compat: mkLHsTupleExpr :: () => [LHsExpr (GhcPass a)] -> LHsExpr (GhcPass a)
+ Development.IDE.GHC.Compat: mkLHsVarTuple :: () => [IdP (GhcPass a)] -> LHsExpr (GhcPass a)
+ Development.IDE.GHC.Compat: mkLHsWrap :: () => HsWrapper -> LHsExpr (GhcPass id) -> LHsExpr (GhcPass id)
+ Development.IDE.GHC.Compat: mkLHsWrapCo :: () => TcCoercionN -> LHsExpr (GhcPass id) -> LHsExpr (GhcPass id)
+ Development.IDE.GHC.Compat: mkLScope :: Located a -> Scope
+ Development.IDE.GHC.Compat: mkLastStmt :: () => Located (bodyR (GhcPass idR)) -> StmtLR (GhcPass idL) (GhcPass idR) (Located (bodyR (GhcPass idR)))
+ Development.IDE.GHC.Compat: mkMatch :: () => HsMatchContext (NameOrRdrName (IdP (GhcPass p))) -> [LPat (GhcPass p)] -> LHsExpr (GhcPass p) -> Located (HsLocalBinds (GhcPass p)) -> LMatch (GhcPass p) (LHsExpr (GhcPass p))
+ Development.IDE.GHC.Compat: mkMatchGroup :: XMG name (Located (body name)) ~ NoExt => Origin -> [LMatch name (Located (body name))] -> MatchGroup name (Located (body name))
+ Development.IDE.GHC.Compat: mkModule :: UnitId -> ModuleName -> Module
+ Development.IDE.GHC.Compat: mkModuleGraph :: [ModSummary] -> ModuleGraph
+ Development.IDE.GHC.Compat: mkModuleName :: String -> ModuleName
+ Development.IDE.GHC.Compat: mkNPat :: Located (HsOverLit GhcPs) -> Maybe (SyntaxExpr GhcPs) -> Pat GhcPs
+ Development.IDE.GHC.Compat: mkNPlusKPat :: Located RdrName -> Located (HsOverLit GhcPs) -> Pat GhcPs
+ Development.IDE.GHC.Compat: mkNilPat :: () => Type -> OutPat p
+ Development.IDE.GHC.Compat: mkParPat :: () => LPat (GhcPass name) -> LPat (GhcPass name)
+ Development.IDE.GHC.Compat: mkPatSynBind :: Located RdrName -> HsPatSynDetails (Located RdrName) -> LPat GhcPs -> HsPatSynDir GhcPs -> HsBind GhcPs
+ Development.IDE.GHC.Compat: mkPrefixConPat :: () => DataCon -> [OutPat p] -> [Type] -> OutPat p
+ Development.IDE.GHC.Compat: mkPrefixFunRhs :: () => Located id -> HsMatchContext id
+ Development.IDE.GHC.Compat: mkPrintUnqualifiedForModule :: GhcMonad m => ModuleInfo -> m (Maybe PrintUnqualified)
+ Development.IDE.GHC.Compat: mkRecStmt :: () => [LStmtLR (GhcPass idL) GhcPs bodyR] -> StmtLR (GhcPass idL) GhcPs bodyR
+ Development.IDE.GHC.Compat: mkRnSyntaxExpr :: Name -> SyntaxExpr GhcRn
+ Development.IDE.GHC.Compat: mkScope :: SrcSpan -> Scope
+ Development.IDE.GHC.Compat: mkSimpleMatch :: () => HsMatchContext (NameOrRdrName (IdP (GhcPass p))) -> [LPat (GhcPass p)] -> Located (body (GhcPass p)) -> LMatch (GhcPass p) (Located (body (GhcPass p)))
+ Development.IDE.GHC.Compat: mkSrcLoc :: FastString -> Int -> Int -> SrcLoc
+ Development.IDE.GHC.Compat: mkSrcSpan :: SrcLoc -> SrcLoc -> SrcSpan
+ Development.IDE.GHC.Compat: mkTcBindStmt :: () => LPat GhcTc -> Located (bodyR GhcTc) -> StmtLR GhcTc GhcTc (Located (bodyR GhcTc))
+ Development.IDE.GHC.Compat: mkTopFunBind :: Origin -> Located Name -> [LMatch GhcRn (LHsExpr GhcRn)] -> HsBind GhcRn
+ Development.IDE.GHC.Compat: mkTransformByStmt :: [ExprLStmt GhcPs] -> LHsExpr GhcPs -> LHsExpr GhcPs -> StmtLR GhcPs GhcPs (LHsExpr GhcPs)
+ Development.IDE.GHC.Compat: mkTransformStmt :: [ExprLStmt GhcPs] -> LHsExpr GhcPs -> StmtLR GhcPs GhcPs (LHsExpr GhcPs)
+ Development.IDE.GHC.Compat: mkTyClGroup :: () => [LTyClDecl (GhcPass p)] -> [LInstDecl (GhcPass p)] -> TyClGroup (GhcPass p)
+ Development.IDE.GHC.Compat: mkUntypedSplice :: SpliceDecoration -> LHsExpr GhcPs -> HsSplice GhcPs
+ Development.IDE.GHC.Compat: mkVarBind :: () => IdP (GhcPass p) -> LHsExpr (GhcPass p) -> LHsBind (GhcPass p)
+ Development.IDE.GHC.Compat: mk_easy_FunBind :: SrcSpan -> RdrName -> [LPat GhcPs] -> LHsExpr GhcPs -> LHsBind GhcPs
+ Development.IDE.GHC.Compat: ml_hi_file :: ModLocation -> FilePath
+ Development.IDE.GHC.Compat: ml_hie_file :: ModLocation -> FilePath
+ Development.IDE.GHC.Compat: ml_hs_file :: ModLocation -> Maybe FilePath
+ Development.IDE.GHC.Compat: ml_obj_file :: ModLocation -> FilePath
+ Development.IDE.GHC.Compat: modInfoExports :: ModuleInfo -> [Name]
+ Development.IDE.GHC.Compat: modInfoExportsWithSelectors :: ModuleInfo -> [Name]
+ Development.IDE.GHC.Compat: modInfoIface :: ModuleInfo -> Maybe ModIface
+ Development.IDE.GHC.Compat: modInfoInstances :: ModuleInfo -> [ClsInst]
+ Development.IDE.GHC.Compat: modInfoIsExportedName :: ModuleInfo -> Name -> Bool
+ Development.IDE.GHC.Compat: modInfoLookupName :: GhcMonad m => ModuleInfo -> Name -> m (Maybe TyThing)
+ Development.IDE.GHC.Compat: modInfoModBreaks :: ModuleInfo -> ModBreaks
+ Development.IDE.GHC.Compat: modInfoSafe :: ModuleInfo -> SafeHaskellMode
+ Development.IDE.GHC.Compat: modInfoTopLevelScope :: ModuleInfo -> Maybe [Name]
+ Development.IDE.GHC.Compat: modInfoTyThings :: ModuleInfo -> [TyThing]
+ Development.IDE.GHC.Compat: moduleInfo :: TypecheckedMod m => m -> ModuleInfo
+ Development.IDE.GHC.Compat: moduleIsBootOrNotObjectLinkable :: GhcMonad m => ModSummary -> m Bool
+ Development.IDE.GHC.Compat: moduleIsInterpreted :: GhcMonad m => Module -> m Bool
+ Development.IDE.GHC.Compat: moduleNameString :: ModuleName -> String
+ Development.IDE.GHC.Compat: moduleTrustReqs :: GhcMonad m => Module -> m (Bool, Set InstalledUnitId)
+ Development.IDE.GHC.Compat: ms_mod_name :: ModSummary -> ModuleName
+ Development.IDE.GHC.Compat: nameModule :: HasDebugCallStack -> Name -> Module
+ Development.IDE.GHC.Compat: nameSrcSpan :: Name -> SrcSpan
+ Development.IDE.GHC.Compat: needsTemplateHaskellOrQQ :: ModuleGraph -> Bool
+ Development.IDE.GHC.Compat: negateFixity :: Fixity
+ Development.IDE.GHC.Compat: negateOverLitVal :: OverLitVal -> OverLitVal
+ Development.IDE.GHC.Compat: newOrDataToFlavour :: NewOrData -> TyConFlavour
+ Development.IDE.GHC.Compat: newtype ArgDocMap
+ Development.IDE.GHC.Compat: newtype DataFamInstDecl pass
+ Development.IDE.GHC.Compat: newtype DeclDocMap
+ Development.IDE.GHC.Compat: newtype HieASTs a
+ Development.IDE.GHC.Compat: newtype HieArgs a
+ Development.IDE.GHC.Compat: newtype HieTypeFix
+ Development.IDE.GHC.Compat: newtype HsIPName
+ Development.IDE.GHC.Compat: newtype HsWildCardInfo
+ Development.IDE.GHC.Compat: newtype NameCacheUpdater
+ Development.IDE.GHC.Compat: newtype ThModFinalizers
+ Development.IDE.GHC.Compat: newtype TyFamInstDecl pass
+ Development.IDE.GHC.Compat: nlConPat :: RdrName -> [LPat GhcPs] -> LPat GhcPs
+ Development.IDE.GHC.Compat: nlConPatName :: Name -> [LPat GhcRn] -> LPat GhcRn
+ Development.IDE.GHC.Compat: nlConVarPat :: RdrName -> [RdrName] -> LPat GhcPs
+ Development.IDE.GHC.Compat: nlConVarPatName :: Name -> [Name] -> LPat GhcRn
+ Development.IDE.GHC.Compat: nlHsApp :: () => LHsExpr (GhcPass id) -> LHsExpr (GhcPass id) -> LHsExpr (GhcPass id)
+ Development.IDE.GHC.Compat: nlHsAppTy :: () => LHsType (GhcPass p) -> LHsType (GhcPass p) -> LHsType (GhcPass p)
+ Development.IDE.GHC.Compat: nlHsApps :: () => IdP (GhcPass id) -> [LHsExpr (GhcPass id)] -> LHsExpr (GhcPass id)
+ Development.IDE.GHC.Compat: nlHsCase :: LHsExpr GhcPs -> [LMatch GhcPs (LHsExpr GhcPs)] -> LHsExpr GhcPs
+ Development.IDE.GHC.Compat: nlHsDataCon :: DataCon -> LHsExpr GhcTc
+ Development.IDE.GHC.Compat: nlHsDo :: HsStmtContext Name -> [LStmt GhcPs (LHsExpr GhcPs)] -> LHsExpr GhcPs
+ Development.IDE.GHC.Compat: nlHsFunTy :: () => LHsType (GhcPass p) -> LHsType (GhcPass p) -> LHsType (GhcPass p)
+ Development.IDE.GHC.Compat: nlHsIf :: () => LHsExpr (GhcPass id) -> LHsExpr (GhcPass id) -> LHsExpr (GhcPass id) -> LHsExpr (GhcPass id)
+ Development.IDE.GHC.Compat: nlHsIntLit :: () => Integer -> LHsExpr (GhcPass p)
+ Development.IDE.GHC.Compat: nlHsLam :: LMatch GhcPs (LHsExpr GhcPs) -> LHsExpr GhcPs
+ Development.IDE.GHC.Compat: nlHsLit :: () => HsLit (GhcPass p) -> LHsExpr (GhcPass p)
+ Development.IDE.GHC.Compat: nlHsOpApp :: LHsExpr GhcPs -> IdP GhcPs -> LHsExpr GhcPs -> LHsExpr GhcPs
+ Development.IDE.GHC.Compat: nlHsPar :: () => LHsExpr (GhcPass id) -> LHsExpr (GhcPass id)
+ Development.IDE.GHC.Compat: nlHsParTy :: () => LHsType (GhcPass p) -> LHsType (GhcPass p)
+ Development.IDE.GHC.Compat: nlHsSyntaxApps :: () => SyntaxExpr (GhcPass id) -> [LHsExpr (GhcPass id)] -> LHsExpr (GhcPass id)
+ Development.IDE.GHC.Compat: nlHsTyApp :: () => IdP (GhcPass id) -> [Type] -> LHsExpr (GhcPass id)
+ Development.IDE.GHC.Compat: nlHsTyApps :: () => IdP (GhcPass id) -> [Type] -> [LHsExpr (GhcPass id)] -> LHsExpr (GhcPass id)
+ Development.IDE.GHC.Compat: nlHsTyConApp :: () => IdP (GhcPass p) -> [LHsType (GhcPass p)] -> LHsType (GhcPass p)
+ Development.IDE.GHC.Compat: nlHsTyVar :: () => IdP (GhcPass p) -> LHsType (GhcPass p)
+ Development.IDE.GHC.Compat: nlHsVar :: () => IdP (GhcPass id) -> LHsExpr (GhcPass id)
+ Development.IDE.GHC.Compat: nlHsVarApps :: () => IdP (GhcPass id) -> [IdP (GhcPass id)] -> LHsExpr (GhcPass id)
+ Development.IDE.GHC.Compat: nlInfixConPat :: RdrName -> LPat GhcPs -> LPat GhcPs -> LPat GhcPs
+ Development.IDE.GHC.Compat: nlList :: [LHsExpr GhcPs] -> LHsExpr GhcPs
+ Development.IDE.GHC.Compat: nlLitPat :: HsLit GhcPs -> LPat GhcPs
+ Development.IDE.GHC.Compat: nlNullaryConPat :: () => IdP id -> LPat id
+ Development.IDE.GHC.Compat: nlParPat :: () => LPat (GhcPass name) -> LPat (GhcPass name)
+ Development.IDE.GHC.Compat: nlTuplePat :: [LPat GhcPs] -> Boxity -> LPat GhcPs
+ Development.IDE.GHC.Compat: nlVarPat :: () => IdP (GhcPass id) -> LPat (GhcPass id)
+ Development.IDE.GHC.Compat: nlWildConPat :: DataCon -> LPat GhcPs
+ Development.IDE.GHC.Compat: nlWildPat :: LPat GhcPs
+ Development.IDE.GHC.Compat: nlWildPatName :: LPat GhcRn
+ Development.IDE.GHC.Compat: noExpr :: () => HsExpr (GhcPass p)
+ Development.IDE.GHC.Compat: noExt :: NoExt
+ Development.IDE.GHC.Compat: noLoc :: () => e -> Located e
+ Development.IDE.GHC.Compat: noSpecPrags :: TcSpecPrags
+ Development.IDE.GHC.Compat: noSrcLoc :: SrcLoc
+ Development.IDE.GHC.Compat: noSrcSpan :: SrcSpan
+ Development.IDE.GHC.Compat: noSyntaxExpr :: () => SyntaxExpr (GhcPass p)
+ Development.IDE.GHC.Compat: obtainTermFromId :: GhcMonad m => Int -> Bool -> Id -> m Term
+ Development.IDE.GHC.Compat: obtainTermFromVal :: GhcMonad m => Int -> Bool -> Type -> a -> m Term
+ Development.IDE.GHC.Compat: overLitType :: HsOverLit GhcTc -> Type
+ Development.IDE.GHC.Compat: parenthesizeHsExpr :: () => PprPrec -> LHsExpr (GhcPass p) -> LHsExpr (GhcPass p)
+ Development.IDE.GHC.Compat: parenthesizeHsType :: () => PprPrec -> LHsType (GhcPass p) -> LHsType (GhcPass p)
+ Development.IDE.GHC.Compat: parenthesizePat :: () => PprPrec -> LPat (GhcPass p) -> LPat (GhcPass p)
+ Development.IDE.GHC.Compat: parseDynamicFlags :: MonadIO m => DynFlags -> [Located String] -> m (DynFlags, [Located String], [Warn])
+ Development.IDE.GHC.Compat: parseExpr :: GhcMonad m => String -> m (LHsExpr GhcPs)
+ Development.IDE.GHC.Compat: parseImportDecl :: GhcMonad m => String -> m (ImportDecl GhcPs)
+ Development.IDE.GHC.Compat: parseModule :: GhcMonad m => ModSummary -> m ParsedModule
+ Development.IDE.GHC.Compat: parseName :: GhcMonad m => String -> m [Name]
+ Development.IDE.GHC.Compat: parsedSource :: ParsedMod m => m -> ParsedSource
+ Development.IDE.GHC.Compat: parser :: String -> DynFlags -> FilePath -> (WarningMessages, Either ErrorMessages (Located (HsModule GhcPs)))
+ Development.IDE.GHC.Compat: patNeedsParens :: () => PprPrec -> Pat p -> Bool
+ Development.IDE.GHC.Compat: pattern ClassOpSig :: Bool -> [Located (IdP pass)] -> LHsSigType pass -> Sig pass
+ Development.IDE.GHC.Compat: pattern DerivD :: DerivDecl p -> HsDecl p
+ Development.IDE.GHC.Compat: pattern ForD :: ForeignDecl p -> HsDecl p
+ Development.IDE.GHC.Compat: pattern IEThingAll :: LIEWrappedName (IdP pass) -> IE pass
+ Development.IDE.GHC.Compat: pattern IEThingWith :: LIEWrappedName (IdP pass) -> IEWildcard -> [LIEWrappedName (IdP pass)] -> [Located (FieldLbl (IdP pass))] -> IE pass
+ Development.IDE.GHC.Compat: pattern InstD :: InstDecl p -> HsDecl p
+ Development.IDE.GHC.Compat: pattern ModLocation :: Maybe FilePath -> FilePath -> FilePath -> ModLocation
+ Development.IDE.GHC.Compat: pattern PatSynBind :: PatSynBind p p -> HsBind p
+ Development.IDE.GHC.Compat: pattern SigD :: Sig p -> HsDecl p
+ Development.IDE.GHC.Compat: pattern TyClD :: TyClDecl p -> HsDecl p
+ Development.IDE.GHC.Compat: pattern TypeSig :: [Located (IdP p)] -> LHsSigWcType p -> Sig p
+ Development.IDE.GHC.Compat: pattern ValD :: HsBind p -> HsDecl p
+ Development.IDE.GHC.Compat: pattern VarPat :: Located (IdP p) -> Pat p
+ Development.IDE.GHC.Compat: pattern PSB :: () => () => XPSB idL idR -> Located (IdP idL) -> HsPatSynDetails (Located (IdP idR)) -> LPat idR -> HsPatSynDir idR -> PatSynBind idL idR
+ Development.IDE.GHC.Compat: pattern XPatSynBind :: () => () => XXPatSynBind idL idR -> PatSynBind idL idR
+ Development.IDE.GHC.Compat: placeHolderNamesTc :: NameSet
+ Development.IDE.GHC.Compat: plusHsValBinds :: () => HsValBinds (GhcPass a) -> HsValBinds (GhcPass a) -> HsValBinds (GhcPass a)
+ Development.IDE.GHC.Compat: pmPprHsLit :: () => HsLit (GhcPass x) -> SDoc
+ Development.IDE.GHC.Compat: pp_dotdot :: SDoc
+ Development.IDE.GHC.Compat: pp_rhs :: Outputable body => HsMatchContext idL -> body -> SDoc
+ Development.IDE.GHC.Compat: pp_st_suffix :: SourceText -> SDoc -> SDoc -> SDoc
+ Development.IDE.GHC.Compat: pprAStmtContext :: (Outputable id, Outputable (NameOrRdrName id)) => HsStmtContext id -> SDoc
+ Development.IDE.GHC.Compat: pprAnonWildCard :: SDoc
+ Development.IDE.GHC.Compat: pprBinds :: (OutputableBndrId (GhcPass idL), OutputableBndrId (GhcPass idR)) => HsLocalBindsLR (GhcPass idL) (GhcPass idR) -> SDoc
+ Development.IDE.GHC.Compat: pprBy :: Outputable body => Maybe body -> SDoc
+ Development.IDE.GHC.Compat: pprCmd :: OutputableBndrId (GhcPass p) => HsCmd (GhcPass p) -> SDoc
+ Development.IDE.GHC.Compat: pprCmdArg :: OutputableBndrId (GhcPass p) => HsCmdTop (GhcPass p) -> SDoc
+ Development.IDE.GHC.Compat: pprComp :: (OutputableBndrId (GhcPass p), Outputable body) => [LStmt (GhcPass p) body] -> SDoc
+ Development.IDE.GHC.Compat: pprConArgs :: OutputableBndrId (GhcPass p) => HsConPatDetails (GhcPass p) -> SDoc
+ Development.IDE.GHC.Compat: pprConDeclFields :: OutputableBndrId (GhcPass p) => [LConDeclField (GhcPass p)] -> SDoc
+ Development.IDE.GHC.Compat: pprDataFamInstFlavour :: () => DataFamInstDecl (GhcPass p) -> SDoc
+ Development.IDE.GHC.Compat: pprDebugParendExpr :: OutputableBndrId (GhcPass p) => PprPrec -> LHsExpr (GhcPass p) -> SDoc
+ Development.IDE.GHC.Compat: pprDeclList :: [SDoc] -> SDoc
+ Development.IDE.GHC.Compat: pprDo :: (OutputableBndrId (GhcPass p), Outputable body) => HsStmtContext any -> [LStmt (GhcPass p) body] -> SDoc
+ Development.IDE.GHC.Compat: pprExpr :: OutputableBndrId (GhcPass p) => HsExpr (GhcPass p) -> SDoc
+ Development.IDE.GHC.Compat: pprExternalSrcLoc :: (StringLiteral, (Int, Int), (Int, Int)) -> SDoc
+ Development.IDE.GHC.Compat: pprFamInst :: FamInst -> SDoc
+ Development.IDE.GHC.Compat: pprFamInstLHS :: OutputableBndrId (GhcPass p) => Located (IdP (GhcPass p)) -> HsTyPats (GhcPass p) -> LexicalFixity -> HsContext (GhcPass p) -> Maybe (LHsKind (GhcPass p)) -> SDoc
+ Development.IDE.GHC.Compat: pprForAll :: [TyVarBinder] -> SDoc
+ Development.IDE.GHC.Compat: pprFullRuleName :: Located (SourceText, RuleName) -> SDoc
+ Development.IDE.GHC.Compat: pprFunBind :: (OutputableBndrId (GhcPass idR), Outputable body) => MatchGroup (GhcPass idR) body -> SDoc
+ Development.IDE.GHC.Compat: pprFundeps :: Outputable a => [FunDep a] -> SDoc
+ Development.IDE.GHC.Compat: pprGRHS :: (OutputableBndrId (GhcPass idR), Outputable body) => HsMatchContext idL -> GRHS (GhcPass idR) body -> SDoc
+ Development.IDE.GHC.Compat: pprGRHSs :: (OutputableBndrId (GhcPass idR), Outputable body) => HsMatchContext idL -> GRHSs (GhcPass idR) body -> SDoc
+ Development.IDE.GHC.Compat: pprHsBracket :: OutputableBndrId (GhcPass p) => HsBracket (GhcPass p) -> SDoc
+ Development.IDE.GHC.Compat: pprHsContext :: OutputableBndrId (GhcPass p) => HsContext (GhcPass p) -> SDoc
+ Development.IDE.GHC.Compat: pprHsContextMaybe :: OutputableBndrId (GhcPass p) => HsContext (GhcPass p) -> Maybe SDoc
+ Development.IDE.GHC.Compat: pprHsContextNoArrow :: OutputableBndrId (GhcPass p) => HsContext (GhcPass p) -> SDoc
+ Development.IDE.GHC.Compat: pprHsForAll :: OutputableBndrId (GhcPass p) => [LHsTyVarBndr (GhcPass p)] -> LHsContext (GhcPass p) -> SDoc
+ Development.IDE.GHC.Compat: pprHsForAllExtra :: OutputableBndrId (GhcPass p) => Maybe SrcSpan -> [LHsTyVarBndr (GhcPass p)] -> LHsContext (GhcPass p) -> SDoc
+ Development.IDE.GHC.Compat: pprHsForAllTvs :: OutputableBndrId (GhcPass p) => [LHsTyVarBndr (GhcPass p)] -> SDoc
+ Development.IDE.GHC.Compat: pprHsType :: OutputableBndrId (GhcPass p) => HsType (GhcPass p) -> SDoc
+ Development.IDE.GHC.Compat: pprImpExp :: (HasOccName name, OutputableBndr name) => name -> SDoc
+ Development.IDE.GHC.Compat: pprInstance :: ClsInst -> SDoc
+ Development.IDE.GHC.Compat: pprInstanceHdr :: ClsInst -> SDoc
+ Development.IDE.GHC.Compat: pprLCmd :: OutputableBndrId (GhcPass p) => LHsCmd (GhcPass p) -> SDoc
+ Development.IDE.GHC.Compat: pprLExpr :: OutputableBndrId (GhcPass p) => LHsExpr (GhcPass p) -> SDoc
+ Development.IDE.GHC.Compat: pprLHsBinds :: (OutputableBndrId (GhcPass idL), OutputableBndrId (GhcPass idR)) => LHsBindsLR (GhcPass idL) (GhcPass idR) -> SDoc
+ Development.IDE.GHC.Compat: pprLHsBindsForUser :: (OutputableBndrId (GhcPass idL), OutputableBndrId (GhcPass idR), OutputableBndrId (GhcPass id2)) => LHsBindsLR (GhcPass idL) (GhcPass idR) -> [LSig (GhcPass id2)] -> [SDoc]
+ Development.IDE.GHC.Compat: pprMatch :: (OutputableBndrId (GhcPass idR), Outputable body) => Match (GhcPass idR) body -> SDoc
+ Development.IDE.GHC.Compat: pprMatchContext :: (Outputable (NameOrRdrName id), Outputable id) => HsMatchContext id -> SDoc
+ Development.IDE.GHC.Compat: pprMatchContextNoun :: (Outputable (NameOrRdrName id), Outputable id) => HsMatchContext id -> SDoc
+ Development.IDE.GHC.Compat: pprMatchInCtxt :: (OutputableBndrId (GhcPass idR), Outputable (NameOrRdrName (NameOrRdrName (IdP (GhcPass idR)))), Outputable body) => Match (GhcPass idR) body -> SDoc
+ Development.IDE.GHC.Compat: pprMatches :: (OutputableBndrId (GhcPass idR), Outputable body) => MatchGroup (GhcPass idR) body -> SDoc
+ Development.IDE.GHC.Compat: pprMinimalSig :: OutputableBndr name => LBooleanFormula (Located name) -> SDoc
+ Development.IDE.GHC.Compat: pprModule :: Module -> SDoc
+ Development.IDE.GHC.Compat: pprParenSymName :: NamedThing a => a -> SDoc
+ Development.IDE.GHC.Compat: pprParendExpr :: OutputableBndrId (GhcPass p) => PprPrec -> HsExpr (GhcPass p) -> SDoc
+ Development.IDE.GHC.Compat: pprParendLExpr :: OutputableBndrId (GhcPass p) => PprPrec -> LHsExpr (GhcPass p) -> SDoc
+ Development.IDE.GHC.Compat: pprParendLPat :: OutputableBndrId (GhcPass p) => PprPrec -> LPat (GhcPass p) -> SDoc
+ Development.IDE.GHC.Compat: pprParendType :: Type -> SDoc
+ Development.IDE.GHC.Compat: pprPatBind :: (OutputableBndrId (GhcPass bndr), OutputableBndrId (GhcPass p), Outputable body) => LPat (GhcPass bndr) -> GRHSs (GhcPass p) body -> SDoc
+ Development.IDE.GHC.Compat: pprPendingSplice :: OutputableBndrId (GhcPass p) => SplicePointName -> LHsExpr (GhcPass p) -> SDoc
+ Development.IDE.GHC.Compat: pprQuals :: (OutputableBndrId (GhcPass p), Outputable body) => [LStmt (GhcPass p) body] -> SDoc
+ Development.IDE.GHC.Compat: pprSpec :: OutputableBndr id => id -> SDoc -> InlinePragma -> SDoc
+ Development.IDE.GHC.Compat: pprSplice :: OutputableBndrId (GhcPass p) => HsSplice (GhcPass p) -> SDoc
+ Development.IDE.GHC.Compat: pprSpliceDecl :: OutputableBndrId (GhcPass p) => HsSplice (GhcPass p) -> SpliceExplicitFlag -> SDoc
+ Development.IDE.GHC.Compat: pprStmt :: (OutputableBndrId (GhcPass idL), OutputableBndrId (GhcPass idR), Outputable body) => StmtLR (GhcPass idL) (GhcPass idR) body -> SDoc
+ Development.IDE.GHC.Compat: pprStmtContext :: (Outputable id, Outputable (NameOrRdrName id)) => HsStmtContext id -> SDoc
+ Development.IDE.GHC.Compat: pprStmtInCtxt :: (OutputableBndrId (GhcPass idL), OutputableBndrId (GhcPass idR), Outputable body) => HsStmtContext (IdP (GhcPass idL)) -> StmtLR (GhcPass idL) (GhcPass idR) body -> SDoc
+ Development.IDE.GHC.Compat: pprTcSpecPrags :: TcSpecPrags -> SDoc
+ Development.IDE.GHC.Compat: pprThetaArrowTy :: ThetaType -> SDoc
+ Development.IDE.GHC.Compat: pprTicks :: SDoc -> SDoc -> SDoc
+ Development.IDE.GHC.Compat: pprTransStmt :: Outputable body => Maybe body -> body -> TransForm -> SDoc
+ Development.IDE.GHC.Compat: pprTransformStmt :: OutputableBndrId (GhcPass p) => [IdP (GhcPass p)] -> LHsExpr (GhcPass p) -> Maybe (LHsExpr (GhcPass p)) -> SDoc
+ Development.IDE.GHC.Compat: pprTyClDeclFlavour :: () => TyClDecl (GhcPass p) -> SDoc
+ Development.IDE.GHC.Compat: pprTypeApp :: TyCon -> [Type] -> SDoc
+ Development.IDE.GHC.Compat: pprVarSig :: OutputableBndr id => [id] -> SDoc -> SDoc
+ Development.IDE.GHC.Compat: ppr_apps :: OutputableBndrId (GhcPass p) => HsExpr (GhcPass p) -> [Either (LHsExpr (GhcPass p)) (XAppTypeE (GhcPass p))] -> SDoc
+ Development.IDE.GHC.Compat: ppr_cmd :: OutputableBndrId (GhcPass p) => HsCmd (GhcPass p) -> SDoc
+ Development.IDE.GHC.Compat: ppr_do_stmts :: (OutputableBndrId (GhcPass idL), OutputableBndrId (GhcPass idR), Outputable body) => [LStmtLR (GhcPass idL) (GhcPass idR) body] -> SDoc
+ Development.IDE.GHC.Compat: ppr_expr :: OutputableBndrId (GhcPass p) => HsExpr (GhcPass p) -> SDoc
+ Development.IDE.GHC.Compat: ppr_lcmd :: OutputableBndrId (GhcPass p) => LHsCmd (GhcPass p) -> SDoc
+ Development.IDE.GHC.Compat: ppr_lexpr :: OutputableBndrId (GhcPass p) => LHsExpr (GhcPass p) -> SDoc
+ Development.IDE.GHC.Compat: ppr_mbDoc :: Maybe LHsDocString -> SDoc
+ Development.IDE.GHC.Compat: ppr_monobind :: (OutputableBndrId (GhcPass idL), OutputableBndrId (GhcPass idR)) => HsBindLR (GhcPass idL) (GhcPass idR) -> SDoc
+ Development.IDE.GHC.Compat: ppr_quasi :: OutputableBndr p => p -> p -> FastString -> SDoc
+ Development.IDE.GHC.Compat: ppr_sig :: OutputableBndrId (GhcPass p) => Sig (GhcPass p) -> SDoc
+ Development.IDE.GHC.Compat: ppr_splice :: OutputableBndrId (GhcPass p) => SDoc -> IdP (GhcPass p) -> LHsExpr (GhcPass p) -> SDoc -> SDoc
+ Development.IDE.GHC.Compat: ppr_splice_decl :: OutputableBndrId (GhcPass p) => HsSplice (GhcPass p) -> SDoc
+ Development.IDE.GHC.Compat: pragBrackets :: SDoc -> SDoc
+ Development.IDE.GHC.Compat: pragSrcBrackets :: SourceText -> String -> SDoc -> SDoc
+ Development.IDE.GHC.Compat: prettyPrintGhcErrors :: ExceptionMonad m => DynFlags -> m a -> m a
+ Development.IDE.GHC.Compat: printException :: GhcMonad m => SourceError -> m ()
+ Development.IDE.GHC.Compat: psb_args :: PatSynBind idL idR -> HsPatSynDetails (Located (IdP idR))
+ Development.IDE.GHC.Compat: psb_def :: PatSynBind idL idR -> LPat idR
+ Development.IDE.GHC.Compat: psb_dir :: PatSynBind idL idR -> HsPatSynDir idR
+ Development.IDE.GHC.Compat: psb_ext :: PatSynBind idL idR -> XPSB idL idR
+ Development.IDE.GHC.Compat: psb_id :: PatSynBind idL idR -> Located (IdP idL)
+ Development.IDE.GHC.Compat: rdrNameAmbiguousFieldOcc :: () => AmbiguousFieldOcc (GhcPass p) -> RdrName
+ Development.IDE.GHC.Compat: readHieFile :: NameCacheUpdater -> FilePath -> IO HieFileResult
+ Development.IDE.GHC.Compat: reconstructType :: HscEnv -> Int -> Id -> IO (Maybe Type)
+ Development.IDE.GHC.Compat: recordSelectorTyCon :: Id -> RecSelParent
+ Development.IDE.GHC.Compat: recoverFullType :: TypeIndex -> Array TypeIndex HieTypeFlat -> HieTypeFix
+ Development.IDE.GHC.Compat: removeTarget :: GhcMonad m => TargetId -> m ()
+ Development.IDE.GHC.Compat: renamedSource :: TypecheckedMod m => m -> Maybe RenamedSource
+ Development.IDE.GHC.Compat: renderHieType :: DynFlags -> HieTypeFix -> String
+ Development.IDE.GHC.Compat: replaceLWrappedName :: () => LIEWrappedName name1 -> name2 -> LIEWrappedName name2
+ Development.IDE.GHC.Compat: replaceWrappedName :: () => IEWrappedName name1 -> name2 -> IEWrappedName name2
+ Development.IDE.GHC.Compat: resolveTyVarScopeLocal :: HieAST a -> Map FastString (HieAST a) -> HieAST a
+ Development.IDE.GHC.Compat: resolveTyVarScopes :: Map FastString (HieAST a) -> Map FastString (HieAST a)
+ Development.IDE.GHC.Compat: resolveVisibility :: Type -> [Type] -> [(Bool, Type)]
+ Development.IDE.GHC.Compat: resultVariableName :: () => FamilyResultSig a -> Maybe (IdP a)
+ Development.IDE.GHC.Compat: resumeExec :: GhcMonad m => (SrcSpan -> Bool) -> SingleStep -> m ExecResult
+ Development.IDE.GHC.Compat: rightOf :: Span -> Span -> Bool
+ Development.IDE.GHC.Compat: rightmost :: SrcSpan -> SrcSpan -> Ordering
+ Development.IDE.GHC.Compat: roleAnnotDeclName :: () => RoleAnnotDecl pass -> IdP pass
+ Development.IDE.GHC.Compat: runDecls :: GhcMonad m => String -> m [Name]
+ Development.IDE.GHC.Compat: runDeclsWithLocation :: GhcMonad m => String -> Int -> String -> m [Name]
+ Development.IDE.GHC.Compat: runGhc :: () => Maybe FilePath -> Ghc a -> IO a
+ Development.IDE.GHC.Compat: runGhcT :: ExceptionMonad m => Maybe FilePath -> GhcT m a -> m a
+ Development.IDE.GHC.Compat: runTcInteractive :: () => HscEnv -> TcRn a -> IO (Messages, Maybe a)
+ Development.IDE.GHC.Compat: sameWildCard :: Located HsWildCardInfo -> Located HsWildCardInfo -> Bool
+ Development.IDE.GHC.Compat: scopeContainsSpan :: Scope -> Span -> Bool
+ Development.IDE.GHC.Compat: selectLargestContainedBy :: Span -> HieAST a -> Maybe (HieAST a)
+ Development.IDE.GHC.Compat: selectSmallestContaining :: Span -> HieAST a -> Maybe (HieAST a)
+ Development.IDE.GHC.Compat: selectorAmbiguousFieldOcc :: AmbiguousFieldOcc GhcTc -> Id
+ Development.IDE.GHC.Compat: setContext :: GhcMonad m => [InteractiveImport] -> m ()
+ Development.IDE.GHC.Compat: setGHCiMonad :: GhcMonad m => String -> m ()
+ Development.IDE.GHC.Compat: setHieDir :: FilePath -> DynFlags -> DynFlags
+ Development.IDE.GHC.Compat: setInteractiveDynFlags :: GhcMonad m => DynFlags -> m ()
+ Development.IDE.GHC.Compat: setLogAction :: GhcMonad m => LogAction -> m ()
+ Development.IDE.GHC.Compat: setProgramDynFlags :: GhcMonad m => DynFlags -> m [InstalledUnitId]
+ Development.IDE.GHC.Compat: setSession :: GhcMonad m => HscEnv -> m ()
+ Development.IDE.GHC.Compat: setSessionDynFlags :: GhcMonad m => DynFlags -> m [InstalledUnitId]
+ Development.IDE.GHC.Compat: setTargets :: GhcMonad m => [Target] -> m ()
+ Development.IDE.GHC.Compat: showGhcException :: GhcException -> ShowS
+ Development.IDE.GHC.Compat: showModule :: GhcMonad m => ModSummary -> m String
+ Development.IDE.GHC.Compat: showRichTokenStream :: [(Located Token, String)] -> String
+ Development.IDE.GHC.Compat: simpleImportDecl :: () => ModuleName -> ImportDecl (GhcPass p)
+ Development.IDE.GHC.Compat: simpleNodeInfo :: FastString -> FastString -> NodeInfo a
+ Development.IDE.GHC.Compat: smallestContainingSatisfying :: Span -> (HieAST a -> Bool) -> HieAST a -> Maybe (HieAST a)
+ Development.IDE.GHC.Compat: spans :: SrcSpan -> (Int, Int) -> Bool
+ Development.IDE.GHC.Compat: splitForAllTys :: Type -> ([TyVar], Type)
+ Development.IDE.GHC.Compat: splitHsAppTys :: LHsType GhcRn -> [LHsType GhcRn] -> (LHsType GhcRn, [LHsType GhcRn])
+ Development.IDE.GHC.Compat: splitHsFunType :: LHsType GhcRn -> ([LHsType GhcRn], LHsType GhcRn)
+ Development.IDE.GHC.Compat: splitLHsForAllTy :: () => LHsType pass -> ([LHsTyVarBndr pass], LHsType pass)
+ Development.IDE.GHC.Compat: splitLHsInstDeclTy :: LHsSigType GhcRn -> ([Name], LHsContext GhcRn, LHsType GhcRn)
+ Development.IDE.GHC.Compat: splitLHsPatSynTy :: () => LHsType pass -> ([LHsTyVarBndr pass], LHsContext pass, [LHsTyVarBndr pass], LHsContext pass, LHsType pass)
+ Development.IDE.GHC.Compat: splitLHsQualTy :: () => LHsType pass -> (LHsContext pass, LHsType pass)
+ Development.IDE.GHC.Compat: splitLHsSigmaTy :: () => LHsType pass -> ([LHsTyVarBndr pass], LHsContext pass, LHsType pass)
+ Development.IDE.GHC.Compat: srcLocCol :: RealSrcLoc -> Int
+ Development.IDE.GHC.Compat: srcLocFile :: RealSrcLoc -> FastString
+ Development.IDE.GHC.Compat: srcLocLine :: RealSrcLoc -> Int
+ Development.IDE.GHC.Compat: srcLocSpan :: SrcLoc -> SrcSpan
+ Development.IDE.GHC.Compat: srcSpanEnd :: SrcSpan -> SrcLoc
+ Development.IDE.GHC.Compat: srcSpanEndCol :: RealSrcSpan -> Int
+ Development.IDE.GHC.Compat: srcSpanEndLine :: RealSrcSpan -> Int
+ Development.IDE.GHC.Compat: srcSpanStart :: SrcSpan -> SrcLoc
+ Development.IDE.GHC.Compat: srcSpanStartCol :: RealSrcSpan -> Int
+ Development.IDE.GHC.Compat: srcSpanStartLine :: RealSrcSpan -> Int
+ Development.IDE.GHC.Compat: startsRightOf :: Span -> Span -> Bool
+ Development.IDE.GHC.Compat: succeeded :: SuccessFlag -> Bool
+ Development.IDE.GHC.Compat: supportsHieFiles :: Bool
+ Development.IDE.GHC.Compat: synTyConDefn_maybe :: TyCon -> Maybe ([TyVar], Type)
+ Development.IDE.GHC.Compat: synTyConRhs_maybe :: TyCon -> Maybe Type
+ Development.IDE.GHC.Compat: tcdName :: () => TyClDecl pass -> IdP pass
+ Development.IDE.GHC.Compat: thBrackets :: SDoc -> SDoc -> SDoc
+ Development.IDE.GHC.Compat: thTyBrackets :: SDoc -> SDoc
+ Development.IDE.GHC.Compat: topSortModuleGraph :: Bool -> ModuleGraph -> Maybe ModuleName -> [SCC ModSummary]
+ Development.IDE.GHC.Compat: tupArgPresent :: () => LHsTupArg id -> Bool
+ Development.IDE.GHC.Compat: tyClDeclLName :: () => TyClDecl pass -> Located (IdP pass)
+ Development.IDE.GHC.Compat: tyClDeclTyVars :: () => TyClDecl pass -> LHsQTyVars pass
+ Development.IDE.GHC.Compat: tyClGroupInstDecls :: () => [TyClGroup pass] -> [LInstDecl pass]
+ Development.IDE.GHC.Compat: tyClGroupRoleDecls :: () => [TyClGroup pass] -> [LRoleAnnotDecl pass]
+ Development.IDE.GHC.Compat: tyClGroupTyClDecls :: () => [TyClGroup pass] -> [LTyClDecl pass]
+ Development.IDE.GHC.Compat: tyConClass_maybe :: TyCon -> Maybe Class
+ Development.IDE.GHC.Compat: tyConDataCons :: TyCon -> [DataCon]
+ Development.IDE.GHC.Compat: tyFamInstDeclLName :: () => TyFamInstDecl pass -> Located (IdP pass)
+ Development.IDE.GHC.Compat: tyFamInstDeclName :: () => TyFamInstDecl pass -> IdP pass
+ Development.IDE.GHC.Compat: type ApiAnns = (Map ApiAnnKey [SrcSpan], Map SrcSpan [Located AnnotationComment])
+ Development.IDE.GHC.Compat: type BangType pass = HsType pass
+ Development.IDE.GHC.Compat: type BreakIndex = Int
+ Development.IDE.GHC.Compat: type CmdLStmt id = LStmt id LHsCmd id
+ Development.IDE.GHC.Compat: type CmdStmt id = Stmt id LHsCmd id
+ Development.IDE.GHC.Compat: type CmdSyntaxTable p = [(Name, HsExpr p)]
+ Development.IDE.GHC.Compat: type ConvertIdX a b = (XHsDoublePrim a ~ XHsDoublePrim b, XHsFloatPrim a ~ XHsFloatPrim b, XHsRat a ~ XHsRat b, XHsInteger a ~ XHsInteger b, XHsWord64Prim a ~ XHsWord64Prim b, XHsInt64Prim a ~ XHsInt64Prim b, XHsWordPrim a ~ XHsWordPrim b, XHsIntPrim a ~ XHsIntPrim b, XHsInt a ~ XHsInt b, XHsStringPrim a ~ XHsStringPrim b, XHsString a ~ XHsString b, XHsCharPrim a ~ XHsCharPrim b, XHsChar a ~ XHsChar b, XXLit a ~ XXLit b)
+ Development.IDE.GHC.Compat: type ExprLStmt id = LStmt id LHsExpr id
+ Development.IDE.GHC.Compat: type ExprStmt id = Stmt id LHsExpr id
+ Development.IDE.GHC.Compat: type FamInstEqn pass rhs = HsImplicitBndrs pass FamEqn pass HsTyPats pass rhs
+ Development.IDE.GHC.Compat: type ForallXABExport (c :: Type -> Constraint) x = (c XABE x, c XXABExport x)
+ Development.IDE.GHC.Compat: type ForallXAmbiguousFieldOcc (c :: Type -> Constraint) x = (c XUnambiguous x, c XAmbiguous x, c XXAmbiguousFieldOcc x)
+ Development.IDE.GHC.Compat: type ForallXAnnDecl (c :: Type -> Constraint) x = (c XHsAnnotation x, c XXAnnDecl x)
+ Development.IDE.GHC.Compat: type ForallXApplicativeArg (c :: Type -> Constraint) x = (c XApplicativeArgOne x, c XApplicativeArgMany x, c XXApplicativeArg x)
+ Development.IDE.GHC.Compat: type ForallXBracket (c :: Type -> Constraint) x = (c XExpBr x, c XPatBr x, c XDecBrL x, c XDecBrG x, c XTypBr x, c XVarBr x, c XTExpBr x, c XXBracket x)
+ Development.IDE.GHC.Compat: type ForallXClsInstDecl (c :: Type -> Constraint) x = (c XCClsInstDecl x, c XXClsInstDecl x)
+ Development.IDE.GHC.Compat: type ForallXCmd (c :: Type -> Constraint) x = (c XCmdArrApp x, c XCmdArrForm x, c XCmdApp x, c XCmdLam x, c XCmdPar x, c XCmdCase x, c XCmdIf x, c XCmdLet x, c XCmdDo x, c XCmdWrap x, c XXCmd x)
+ Development.IDE.GHC.Compat: type ForallXCmdTop (c :: Type -> Constraint) x = (c XCmdTop x, c XXCmdTop x)
+ Development.IDE.GHC.Compat: type ForallXConDecl (c :: Type -> Constraint) x = (c XConDeclGADT x, c XConDeclH98 x, c XXConDecl x)
+ Development.IDE.GHC.Compat: type ForallXConDeclField (c :: Type -> Constraint) x = (c XConDeclField x, c XXConDeclField x)
+ Development.IDE.GHC.Compat: type ForallXDefaultDecl (c :: Type -> Constraint) x = (c XCDefaultDecl x, c XXDefaultDecl x)
+ Development.IDE.GHC.Compat: type ForallXDerivDecl (c :: Type -> Constraint) x = (c XCDerivDecl x, c XXDerivDecl x)
+ Development.IDE.GHC.Compat: type ForallXExpr (c :: Type -> Constraint) x = (c XVar x, c XUnboundVar x, c XConLikeOut x, c XRecFld x, c XOverLabel x, c XIPVar x, c XOverLitE x, c XLitE x, c XLam x, c XLamCase x, c XApp x, c XAppTypeE x, c XOpApp x, c XNegApp x, c XPar x, c XSectionL x, c XSectionR x, c XExplicitTuple x, c XExplicitSum x, c XCase x, c XIf x, c XMultiIf x, c XLet x, c XDo x, c XExplicitList x, c XRecordCon x, c XRecordUpd x, c XExprWithTySig x, c XArithSeq x, c XSCC x, c XCoreAnn x, c XBracket x, c XRnBracketOut x, c XTcBracketOut x, c XSpliceE x, c XProc x, c XStatic x, c XArrApp x, c XArrForm x, c XTick x, c XBinTick x, c XTickPragma x, c XEWildPat x, c XEAsPat x, c XEViewPat x, c XELazyPat x, c XWrap x, c XXExpr x)
+ Development.IDE.GHC.Compat: type ForallXFamEqn (c :: Type -> Constraint) x p r = (c XCFamEqn x p r, c XXFamEqn x p r)
+ Development.IDE.GHC.Compat: type ForallXFamilyDecl (c :: Type -> Constraint) x = (c XCFamilyDecl x, c XXFamilyDecl x)
+ Development.IDE.GHC.Compat: type ForallXFamilyResultSig (c :: Type -> Constraint) x = (c XNoSig x, c XCKindSig x, c XTyVarSig x, c XXFamilyResultSig x)
+ Development.IDE.GHC.Compat: type ForallXFieldOcc (c :: Type -> Constraint) x = (c XCFieldOcc x, c XXFieldOcc x)
+ Development.IDE.GHC.Compat: type ForallXFixitySig (c :: Type -> Constraint) x = (c XFixitySig x, c XXFixitySig x)
+ Development.IDE.GHC.Compat: type ForallXForeignDecl (c :: Type -> Constraint) x = (c XForeignImport x, c XForeignExport x, c XXForeignDecl x)
+ Development.IDE.GHC.Compat: type ForallXGRHS (c :: Type -> Constraint) x b = (c XCGRHS x b, c XXGRHS x b)
+ Development.IDE.GHC.Compat: type ForallXGRHSs (c :: Type -> Constraint) x b = (c XCGRHSs x b, c XXGRHSs x b)
+ Development.IDE.GHC.Compat: type ForallXHsBindsLR (c :: Type -> Constraint) x x' = (c XFunBind x x', c XPatBind x x', c XVarBind x x', c XAbsBinds x x', c XPatSynBind x x', c XXHsBindsLR x x')
+ Development.IDE.GHC.Compat: type ForallXHsDataDefn (c :: Type -> Constraint) x = (c XCHsDataDefn x, c XXHsDataDefn x)
+ Development.IDE.GHC.Compat: type ForallXHsDecl (c :: Type -> Constraint) x = (c XTyClD x, c XInstD x, c XDerivD x, c XValD x, c XSigD x, c XDefD x, c XForD x, c XWarningD x, c XAnnD x, c XRuleD x, c XSpliceD x, c XDocD x, c XRoleAnnotD x, c XXHsDecl x)
+ Development.IDE.GHC.Compat: type ForallXHsDerivingClause (c :: Type -> Constraint) x = (c XCHsDerivingClause x, c XXHsDerivingClause x)
+ Development.IDE.GHC.Compat: type ForallXHsGroup (c :: Type -> Constraint) x = (c XCHsGroup x, c XXHsGroup x)
+ Development.IDE.GHC.Compat: type ForallXHsIPBinds (c :: Type -> Constraint) x = (c XIPBinds x, c XXHsIPBinds x)
+ Development.IDE.GHC.Compat: type ForallXHsImplicitBndrs (c :: Type -> Constraint) x b = (c XHsIB x b, c XXHsImplicitBndrs x b)
+ Development.IDE.GHC.Compat: type ForallXHsLit (c :: Type -> Constraint) x = (c XHsChar x, c XHsCharPrim x, c XHsDoublePrim x, c XHsFloatPrim x, c XHsInt x, c XHsInt64Prim x, c XHsIntPrim x, c XHsInteger x, c XHsRat x, c XHsString x, c XHsStringPrim x, c XHsWord64Prim x, c XHsWordPrim x, c XXLit x)
+ Development.IDE.GHC.Compat: type ForallXHsLocalBindsLR (c :: Type -> Constraint) x x' = (c XHsValBinds x x', c XHsIPBinds x x', c XEmptyLocalBinds x x', c XXHsLocalBindsLR x x')
+ Development.IDE.GHC.Compat: type ForallXHsWildCardBndrs (c :: Type -> Constraint) x b = (c XHsWC x b, c XXHsWildCardBndrs x b)
+ Development.IDE.GHC.Compat: type ForallXIE (c :: Type -> Constraint) x = (c XIEVar x, c XIEThingAbs x, c XIEThingAll x, c XIEThingWith x, c XIEModuleContents x, c XIEGroup x, c XIEDoc x, c XIEDocNamed x, c XXIE x)
+ Development.IDE.GHC.Compat: type ForallXIPBind (c :: Type -> Constraint) x = (c XCIPBind x, c XXIPBind x)
+ Development.IDE.GHC.Compat: type ForallXImportDecl (c :: Type -> Constraint) x = (c XCImportDecl x, c XXImportDecl x)
+ Development.IDE.GHC.Compat: type ForallXInstDecl (c :: Type -> Constraint) x = (c XClsInstD x, c XDataFamInstD x, c XTyFamInstD x, c XXInstDecl x)
+ Development.IDE.GHC.Compat: type ForallXLHsQTyVars (c :: Type -> Constraint) x = (c XHsQTvs x, c XXLHsQTyVars x)
+ Development.IDE.GHC.Compat: type ForallXMatch (c :: Type -> Constraint) x b = (c XCMatch x b, c XXMatch x b)
+ Development.IDE.GHC.Compat: type ForallXMatchGroup (c :: Type -> Constraint) x b = (c XMG x b, c XXMatchGroup x b)
+ Development.IDE.GHC.Compat: type ForallXOverLit (c :: Type -> Constraint) x = (c XOverLit x, c XXOverLit x)
+ Development.IDE.GHC.Compat: type ForallXParStmtBlock (c :: Type -> Constraint) x x' = (c XParStmtBlock x x', c XXParStmtBlock x x')
+ Development.IDE.GHC.Compat: type ForallXPat (c :: Type -> Constraint) x = (c XWildPat x, c XVarPat x, c XLazyPat x, c XAsPat x, c XParPat x, c XBangPat x, c XListPat x, c XTuplePat x, c XSumPat x, c XViewPat x, c XSplicePat x, c XLitPat x, c XNPat x, c XNPlusKPat x, c XSigPat x, c XCoPat x, c XXPat x)
+ Development.IDE.GHC.Compat: type ForallXPatSynBind (c :: Type -> Constraint) x x' = (c XPSB x x', c XXPatSynBind x x')
+ Development.IDE.GHC.Compat: type ForallXRoleAnnotDecl (c :: Type -> Constraint) x = (c XCRoleAnnotDecl x, c XXRoleAnnotDecl x)
+ Development.IDE.GHC.Compat: type ForallXRuleBndr (c :: Type -> Constraint) x = (c XCRuleBndr x, c XRuleBndrSig x, c XXRuleBndr x)
+ Development.IDE.GHC.Compat: type ForallXRuleDecl (c :: Type -> Constraint) x = (c XHsRule x, c XXRuleDecl x)
+ Development.IDE.GHC.Compat: type ForallXRuleDecls (c :: Type -> Constraint) x = (c XCRuleDecls x, c XXRuleDecls x)
+ Development.IDE.GHC.Compat: type ForallXSig (c :: Type -> Constraint) x = (c XTypeSig x, c XPatSynSig x, c XClassOpSig x, c XIdSig x, c XFixSig x, c XInlineSig x, c XSpecSig x, c XSpecInstSig x, c XMinimalSig x, c XSCCFunSig x, c XCompleteMatchSig x, c XXSig x)
+ Development.IDE.GHC.Compat: type ForallXSplice (c :: Type -> Constraint) x = (c XTypedSplice x, c XUntypedSplice x, c XQuasiQuote x, c XSpliced x, c XXSplice x)
+ Development.IDE.GHC.Compat: type ForallXSpliceDecl (c :: Type -> Constraint) x = (c XSpliceDecl x, c XXSpliceDecl x)
+ Development.IDE.GHC.Compat: type ForallXStmtLR (c :: Type -> Constraint) x x' b = (c XLastStmt x x' b, c XBindStmt x x' b, c XApplicativeStmt x x' b, c XBodyStmt x x' b, c XLetStmt x x' b, c XParStmt x x' b, c XTransStmt x x' b, c XRecStmt x x' b, c XXStmtLR x x' b)
+ Development.IDE.GHC.Compat: type ForallXTupArg (c :: Type -> Constraint) x = (c XPresent x, c XMissing x, c XXTupArg x)
+ Development.IDE.GHC.Compat: type ForallXTyClDecl (c :: Type -> Constraint) x = (c XFamDecl x, c XSynDecl x, c XDataDecl x, c XClassDecl x, c XXTyClDecl x)
+ Development.IDE.GHC.Compat: type ForallXTyClGroup (c :: Type -> Constraint) x = (c XCTyClGroup x, c XXTyClGroup x)
+ Development.IDE.GHC.Compat: type ForallXTyVarBndr (c :: Type -> Constraint) x = (c XUserTyVar x, c XKindedTyVar x, c XXTyVarBndr x)
+ Development.IDE.GHC.Compat: type ForallXType (c :: Type -> Constraint) x = (c XForAllTy x, c XQualTy x, c XTyVar x, c XAppTy x, c XFunTy x, c XListTy x, c XTupleTy x, c XSumTy x, c XOpTy x, c XParTy x, c XIParamTy x, c XStarTy x, c XKindSig x, c XSpliceTy x, c XDocTy x, c XBangTy x, c XRecTy x, c XExplicitListTy x, c XExplicitTupleTy x, c XTyLit x, c XWildCardTy x, c XXType x)
+ Development.IDE.GHC.Compat: type ForallXValBindsLR (c :: Type -> Constraint) x x' = (c XValBinds x x', c XXValBindsLR x x')
+ Development.IDE.GHC.Compat: type ForallXWarnDecl (c :: Type -> Constraint) x = (c XWarning x, c XXWarnDecl x)
+ Development.IDE.GHC.Compat: type ForallXWarnDecls (c :: Type -> Constraint) x = (c XWarnings x, c XXWarnDecls x)
+ Development.IDE.GHC.Compat: type ForeignHValue = ForeignRef HValue
+ Development.IDE.GHC.Compat: type GhcPs = GhcPass Parsed
+ Development.IDE.GHC.Compat: type GhcRn = GhcPass Renamed
+ Development.IDE.GHC.Compat: type GhcTc = GhcPass Typechecked
+ Development.IDE.GHC.Compat: type GhcTcId = GhcTc
+ Development.IDE.GHC.Compat: type GhciLStmt id = LStmt id LHsExpr id
+ Development.IDE.GHC.Compat: type GhciStmt id = Stmt id LHsExpr id
+ Development.IDE.GHC.Compat: type GuardLStmt id = LStmt id LHsExpr id
+ Development.IDE.GHC.Compat: type GuardStmt id = Stmt id LHsExpr id
+ Development.IDE.GHC.Compat: type HieTypeFlat = HieType TypeIndex
+ Development.IDE.GHC.Compat: type HsBind id = HsBindLR id id
+ Development.IDE.GHC.Compat: type HsConDeclDetails pass = HsConDetails LBangType pass Located [LConDeclField pass]
+ Development.IDE.GHC.Compat: type HsConPatDetails p = HsConDetails LPat p HsRecFields p LPat p
+ Development.IDE.GHC.Compat: type HsContext pass = [LHsType pass]
+ Development.IDE.GHC.Compat: type HsDeriving pass = Located [LHsDerivingClause pass]
+ Development.IDE.GHC.Compat: type HsKind pass = HsType pass
+ Development.IDE.GHC.Compat: type HsLocalBinds id = HsLocalBindsLR id id
+ Development.IDE.GHC.Compat: type HsPatSynDetails arg = HsConDetails arg [RecordPatSynField arg]
+ Development.IDE.GHC.Compat: type HsRecField p arg = HsRecField' FieldOcc p arg
+ Development.IDE.GHC.Compat: type HsRecUpdField p = HsRecField' AmbiguousFieldOcc p LHsExpr p
+ Development.IDE.GHC.Compat: type HsRecordBinds p = HsRecFields p LHsExpr p
+ Development.IDE.GHC.Compat: type HsTyPats pass = [LHsType pass]
+ Development.IDE.GHC.Compat: type HsValBinds id = HsValBindsLR id id
+ Development.IDE.GHC.Compat: type Id = Var
+ Development.IDE.GHC.Compat: type Identifier = Either ModuleName Name
+ Development.IDE.GHC.Compat: type InPat p = LPat p
+ Development.IDE.GHC.Compat: type Kind = Type
+ Development.IDE.GHC.Compat: type LAnnDecl pass = Located AnnDecl pass
+ Development.IDE.GHC.Compat: type LBangType pass = Located BangType pass
+ Development.IDE.GHC.Compat: type LClsInstDecl pass = Located ClsInstDecl pass
+ Development.IDE.GHC.Compat: type LConDecl pass = Located ConDecl pass
+ Development.IDE.GHC.Compat: type LConDeclField pass = Located ConDeclField pass
+ Development.IDE.GHC.Compat: type LDataFamInstDecl pass = Located DataFamInstDecl pass
+ Development.IDE.GHC.Compat: type LDefaultDecl pass = Located DefaultDecl pass
+ Development.IDE.GHC.Compat: type LDerivDecl pass = Located DerivDecl pass
+ Development.IDE.GHC.Compat: type LDerivStrategy pass = Located DerivStrategy pass
+ Development.IDE.GHC.Compat: type LDocDecl = Located DocDecl
+ Development.IDE.GHC.Compat: type LFamInstEqn pass rhs = Located FamInstEqn pass rhs
+ Development.IDE.GHC.Compat: type LFamilyDecl pass = Located FamilyDecl pass
+ Development.IDE.GHC.Compat: type LFamilyResultSig pass = Located FamilyResultSig pass
+ Development.IDE.GHC.Compat: type LFieldOcc pass = Located FieldOcc pass
+ Development.IDE.GHC.Compat: type LFixitySig pass = Located FixitySig pass
+ Development.IDE.GHC.Compat: type LForeignDecl pass = Located ForeignDecl pass
+ Development.IDE.GHC.Compat: type LGRHS id body = Located GRHS id body
+ Development.IDE.GHC.Compat: type LHsBind id = LHsBindLR id id
+ Development.IDE.GHC.Compat: type LHsBindLR idL idR = Located HsBindLR idL idR
+ Development.IDE.GHC.Compat: type LHsBinds id = LHsBindsLR id id
+ Development.IDE.GHC.Compat: type LHsBindsLR idL idR = Bag LHsBindLR idL idR
+ Development.IDE.GHC.Compat: type LHsCmd id = Located HsCmd id
+ Development.IDE.GHC.Compat: type LHsCmdTop p = Located HsCmdTop p
+ Development.IDE.GHC.Compat: type LHsContext pass = Located HsContext pass
+ Development.IDE.GHC.Compat: type LHsDecl p = Located HsDecl p
+ Development.IDE.GHC.Compat: type LHsDerivingClause pass = Located HsDerivingClause pass
+ Development.IDE.GHC.Compat: type LHsDocString = Located HsDocString
+ Development.IDE.GHC.Compat: type LHsExpr p = Located HsExpr p
+ Development.IDE.GHC.Compat: type LHsKind pass = Located HsKind pass
+ Development.IDE.GHC.Compat: type LHsLocalBinds id = Located HsLocalBinds id
+ Development.IDE.GHC.Compat: type LHsLocalBindsLR idL idR = Located HsLocalBindsLR idL idR
+ Development.IDE.GHC.Compat: type LHsRecField p arg = Located HsRecField p arg
+ Development.IDE.GHC.Compat: type LHsRecField' p arg = Located HsRecField' p arg
+ Development.IDE.GHC.Compat: type LHsRecUpdField p = Located HsRecUpdField p
+ Development.IDE.GHC.Compat: type LHsSigType pass = HsImplicitBndrs pass LHsType pass
+ Development.IDE.GHC.Compat: type LHsSigWcType pass = HsWildCardBndrs pass LHsSigType pass
+ Development.IDE.GHC.Compat: type LHsTupArg id = Located HsTupArg id
+ Development.IDE.GHC.Compat: type LHsTyVarBndr pass = Located HsTyVarBndr pass
+ Development.IDE.GHC.Compat: type LHsType pass = Located HsType pass
+ Development.IDE.GHC.Compat: type LHsWcType pass = HsWildCardBndrs pass LHsType pass
+ Development.IDE.GHC.Compat: type LIE pass = Located IE pass
+ Development.IDE.GHC.Compat: type LIEWrappedName name = Located IEWrappedName name
+ Development.IDE.GHC.Compat: type LIPBind id = Located IPBind id
+ Development.IDE.GHC.Compat: type LIdP p = Located IdP p
+ Development.IDE.GHC.Compat: type LImportDecl pass = Located ImportDecl pass
+ Development.IDE.GHC.Compat: type LInjectivityAnn pass = Located InjectivityAnn pass
+ Development.IDE.GHC.Compat: type LInstDecl pass = Located InstDecl pass
+ Development.IDE.GHC.Compat: type LMatch id body = Located Match id body
+ Development.IDE.GHC.Compat: type LPat p = Located Pat p
+ Development.IDE.GHC.Compat: type LRoleAnnotDecl pass = Located RoleAnnotDecl pass
+ Development.IDE.GHC.Compat: type LRuleBndr pass = Located RuleBndr pass
+ Development.IDE.GHC.Compat: type LRuleDecl pass = Located RuleDecl pass
+ Development.IDE.GHC.Compat: type LRuleDecls pass = Located RuleDecls pass
+ Development.IDE.GHC.Compat: type LSig pass = Located Sig pass
+ Development.IDE.GHC.Compat: type LSpliceDecl pass = Located SpliceDecl pass
+ Development.IDE.GHC.Compat: type LStmt id body = Located StmtLR id id body
+ Development.IDE.GHC.Compat: type LStmtLR idL idR body = Located StmtLR idL idR body
+ Development.IDE.GHC.Compat: type LTcSpecPrag = Located TcSpecPrag
+ Development.IDE.GHC.Compat: type LTyClDecl pass = Located TyClDecl pass
+ Development.IDE.GHC.Compat: type LTyFamDefltEqn pass = Located TyFamDefltEqn pass
+ Development.IDE.GHC.Compat: type LTyFamInstDecl pass = Located TyFamInstDecl pass
+ Development.IDE.GHC.Compat: type LTyFamInstEqn pass = Located TyFamInstEqn pass
+ Development.IDE.GHC.Compat: type LWarnDecl pass = Located WarnDecl pass
+ Development.IDE.GHC.Compat: type LWarnDecls pass = Located WarnDecls pass
+ Development.IDE.GHC.Compat: type Located = GenLocated SrcSpan
+ Development.IDE.GHC.Compat: type WarnErrLogger = forall (m :: Type -> Type). GhcMonad m => Maybe SourceError -> m ()
+ Development.IDE.GHC.Compat: type NodeIdentifiers a = Map Identifier (IdentifierDetails a)
+ Development.IDE.GHC.Compat: type OutPat p = LPat p
+ Development.IDE.GHC.Compat: type OutputableBndrId id = (OutputableBndr NameOrRdrName IdP id, OutputableBndr IdP id, OutputableX id)
+ Development.IDE.GHC.Compat: type OutputableX p = (Outputable XSigPat p, Outputable XSigPat GhcRn, Outputable XIPBinds p, Outputable XExprWithTySig p, Outputable XExprWithTySig GhcRn, Outputable XAppTypeE p, Outputable XAppTypeE GhcRn, Outputable XViaStrategy p, Outputable XViaStrategy GhcRn)
+ Development.IDE.GHC.Compat: type ParsedSource = Located HsModule GhcPs
+ Development.IDE.GHC.Compat: type PostTcExpr = HsExpr GhcTc
+ Development.IDE.GHC.Compat: type PostTcTable = [(Name, PostTcExpr)]
+ Development.IDE.GHC.Compat: type PredType = Type
+ Development.IDE.GHC.Compat: type RenamedSource = (HsGroup GhcRn, [LImportDecl GhcRn], Maybe [(LIE GhcRn, Avails)], Maybe LHsDocString)
+ Development.IDE.GHC.Compat: type Span = RealSrcSpan
+ Development.IDE.GHC.Compat: type SplicePointName = Name
+ Development.IDE.GHC.Compat: type Stmt id body = StmtLR id id body
+ Development.IDE.GHC.Compat: type ThetaType = [PredType]
+ Development.IDE.GHC.Compat: type TyFamDefltEqn pass = FamEqn pass LHsQTyVars pass LHsType pass
+ Development.IDE.GHC.Compat: type TyFamInstEqn pass = FamInstEqn pass LHsType pass
+ Development.IDE.GHC.Compat: type TyVar = Var
+ Development.IDE.GHC.Compat: type TypeIndex = Int
+ Development.IDE.GHC.Compat: type TypecheckedSource = LHsBinds GhcTc
+ Development.IDE.GHC.Compat: type family NameOrRdrName id :: Type
+ Development.IDE.GHC.Compat: typeKind :: GhcMonad m => Bool -> String -> m (Type, Kind)
+ Development.IDE.GHC.Compat: typeToLHsType :: Type -> LHsType GhcPs
+ Development.IDE.GHC.Compat: typecheckModule :: GhcMonad m => ParsedModule -> m TypecheckedModule
+ Development.IDE.GHC.Compat: typecheckedSource :: TypecheckedMod m => m -> TypecheckedSource
+ Development.IDE.GHC.Compat: unLoc :: () => GenLocated l e -> e
+ Development.IDE.GHC.Compat: unambiguousFieldOcc :: AmbiguousFieldOcc GhcTc -> FieldOcc GhcTc
+ Development.IDE.GHC.Compat: unboundVarOcc :: UnboundVar -> OccName
+ Development.IDE.GHC.Compat: unguardedGRHSs :: () => Located (body (GhcPass p)) -> GRHSs (GhcPass p) (Located (body (GhcPass p)))
+ Development.IDE.GHC.Compat: unguardedRHS :: () => SrcSpan -> Located (body (GhcPass p)) -> [LGRHS (GhcPass p) (Located (body (GhcPass p)))]
+ Development.IDE.GHC.Compat: unicodeAnn :: AnnKeywordId -> AnnKeywordId
+ Development.IDE.GHC.Compat: unitRecStmtTc :: RecStmtTc
+ Development.IDE.GHC.Compat: unpackHDS :: HsDocString -> String
+ Development.IDE.GHC.Compat: unqualQuasiQuote :: RdrName
+ Development.IDE.GHC.Compat: upNameCache :: IORef NameCache -> (NameCache -> (NameCache, c)) -> IO c
+ Development.IDE.GHC.Compat: userHsLTyVarBndrs :: () => SrcSpan -> [Located (IdP (GhcPass p))] -> [LHsTyVarBndr (GhcPass p)]
+ Development.IDE.GHC.Compat: userHsTyVarBndrs :: () => SrcSpan -> [IdP (GhcPass p)] -> [LHsTyVarBndr (GhcPass p)]
+ Development.IDE.GHC.Compat: wildCardName :: HsWildCardInfo -> Name
+ Development.IDE.GHC.Compat: withCleanupSession :: GhcMonad m => m a -> m a
+ Development.IDE.GHC.Compat: withSignalHandlers :: (ExceptionMonad m, MonadIO m) => m a -> m a
+ Development.IDE.GHC.Compat: workingDirectoryChanged :: GhcMonad m => m ()
+ Development.IDE.GHC.Compat: writeHieFile :: FilePath -> HieFile -> IO ()
+ Development.IDE.GHC.Util: bytestringToStringBuffer :: ByteString -> StringBuffer
+ Development.IDE.GHC.Util: setHieDir :: FilePath -> DynFlags -> DynFlags
+ Development.IDE.LSP.HoverDefinition: gotoTypeDefinition :: IdeState -> TextDocumentPositionParams -> IO (Either ResponseError LocationResponseParams)
+ Development.IDE.LSP.HoverDefinition: setHandlersTypeDefinition :: PartialHandlers c
+ Development.IDE.Plugin.CodeAction: instance GHC.Classes.Eq Development.IDE.Plugin.CodeAction.ExportsAs
+ Development.IDE.Plugin.Completions: instance Control.DeepSeq.NFData Development.IDE.Plugin.Completions.LocalCompletions
+ Development.IDE.Plugin.Completions: instance Control.DeepSeq.NFData Development.IDE.Plugin.Completions.NonLocalCompletions
+ Development.IDE.Plugin.Completions: instance Data.Binary.Class.Binary Development.IDE.Plugin.Completions.LocalCompletions
+ Development.IDE.Plugin.Completions: instance Data.Binary.Class.Binary Development.IDE.Plugin.Completions.NonLocalCompletions
+ Development.IDE.Plugin.Completions: instance Data.Hashable.Class.Hashable Development.IDE.Plugin.Completions.LocalCompletions
+ Development.IDE.Plugin.Completions: instance Data.Hashable.Class.Hashable Development.IDE.Plugin.Completions.NonLocalCompletions
+ Development.IDE.Plugin.Completions: instance GHC.Classes.Eq Development.IDE.Plugin.Completions.LocalCompletions
+ Development.IDE.Plugin.Completions: instance GHC.Classes.Eq Development.IDE.Plugin.Completions.NonLocalCompletions
+ Development.IDE.Plugin.Completions: instance GHC.Generics.Generic Development.IDE.Plugin.Completions.LocalCompletions
+ Development.IDE.Plugin.Completions: instance GHC.Generics.Generic Development.IDE.Plugin.Completions.NonLocalCompletions
+ Development.IDE.Plugin.Completions: instance GHC.Show.Show Development.IDE.Plugin.Completions.LocalCompletions
+ Development.IDE.Plugin.Completions: instance GHC.Show.Show Development.IDE.Plugin.Completions.NonLocalCompletions
+ Development.IDE.Session: instance GHC.Classes.Eq Development.IDE.Session.PackageSetupException
+ Development.IDE.Session: instance GHC.Exception.Type.Exception Development.IDE.Session.PackageSetupException
+ Development.IDE.Session: instance GHC.Show.Show Development.IDE.Session.PackageSetupException
+ Development.IDE.Session: loadSession :: FilePath -> IO (Action IdeGhcSession)
+ Development.IDE.Spans.Common: SpanDocUris :: Maybe Text -> Maybe Text -> SpanDocUris
+ Development.IDE.Spans.Common: [spanDocUriDoc] :: SpanDocUris -> Maybe Text
+ Development.IDE.Spans.Common: [spanDocUriSrc] :: SpanDocUris -> Maybe Text
+ Development.IDE.Spans.Common: data SpanDocUris
+ Development.IDE.Spans.Common: instance GHC.Classes.Eq Development.IDE.Spans.Common.SpanDoc
+ Development.IDE.Spans.Common: instance GHC.Classes.Eq Development.IDE.Spans.Common.SpanDocUris
+ Development.IDE.Spans.Common: instance GHC.Show.Show Development.IDE.Spans.Common.SpanDocUris
+ Development.IDE.Spans.Common: showName :: Outputable a => a -> Text
+ Development.IDE.Types.Options: IdeGhcSession :: (FilePath -> IO (IdeResult HscEnvEq, [FilePath])) -> !Int -> IdeGhcSession
+ Development.IDE.Types.Options: IdeTesting :: Bool -> IdeTesting
+ Development.IDE.Types.Options: [loadSessionFun] :: IdeGhcSession -> FilePath -> IO (IdeResult HscEnvEq, [FilePath])
+ Development.IDE.Types.Options: [sessionVersion] :: IdeGhcSession -> !Int
+ Development.IDE.Types.Options: data IdeGhcSession
+ Development.IDE.Types.Options: instance Control.DeepSeq.NFData Development.IDE.Types.Options.IdeGhcSession
+ Development.IDE.Types.Options: instance GHC.Show.Show Development.IDE.Types.Options.IdeGhcSession
+ Development.IDE.Types.Options: newtype IdeTesting
- Development.IDE.Core.FileStore: getFileContents :: NormalizedFilePath -> Action (FileVersion, Maybe Text)
+ Development.IDE.Core.FileStore: getFileContents :: NormalizedFilePath -> Action (UTCTime, Maybe Text)
- Development.IDE.Core.Rules: getAtPoint :: NormalizedFilePath -> Position -> Action (Maybe (Maybe Range, [Text]))
+ Development.IDE.Core.Rules: getAtPoint :: NormalizedFilePath -> Position -> IdeAction (Maybe (Maybe Range, [Text]))
- Development.IDE.Core.Rules: getDefinition :: NormalizedFilePath -> Position -> Action (Maybe Location)
+ Development.IDE.Core.Rules: getDefinition :: NormalizedFilePath -> Position -> IdeAction (Maybe Location)
- Development.IDE.Core.Rules: runAction :: IdeState -> Action a -> IO a
+ Development.IDE.Core.Rules: runAction :: String -> IdeState -> Action a -> IO a
- Development.IDE.Core.Rules: useE :: IdeRule k v => k -> NormalizedFilePath -> MaybeT Action v
+ Development.IDE.Core.Rules: useE :: IdeRule k v => k -> NormalizedFilePath -> MaybeT IdeAction (v, PositionMapping)
- Development.IDE.Core.Rules: useNoFileE :: IdeRule k v => k -> MaybeT Action v
+ Development.IDE.Core.Rules: useNoFileE :: IdeRule k v => IdeState -> k -> MaybeT IdeAction v
- Development.IDE.Core.Rules: usesE :: IdeRule k v => k -> [NormalizedFilePath] -> MaybeT Action [v]
+ Development.IDE.Core.Rules: usesE :: IdeRule k v => k -> [NormalizedFilePath] -> MaybeT IdeAction [(v, PositionMapping)]
- Development.IDE.Core.Service: initialise :: ClientCapabilities -> Rules () -> IO LspId -> (FromServerMessage -> IO ()) -> Logger -> Debouncer NormalizedUri -> IdeOptions -> VFSHandle -> IO IdeState
+ Development.IDE.Core.Service: initialise :: ClientCapabilities -> Rules () -> IO LspId -> (FromServerMessage -> IO ()) -> WithProgressFunc -> WithIndefiniteProgressFunc -> Logger -> Debouncer NormalizedUri -> IdeOptions -> VFSHandle -> IO IdeState
- Development.IDE.Core.Service: runAction :: IdeState -> Action a -> IO a
+ Development.IDE.Core.Service: runAction :: String -> IdeState -> Action a -> IO a
- Development.IDE.Core.Shake: ModificationTime :: !Int -> !Int -> FileVersion
+ Development.IDE.Core.Shake: ModificationTime :: !Int64 -> !Int64 -> FileVersion
- Development.IDE.Core.Shake: ShakeExtras :: (FromServerMessage -> IO ()) -> Debouncer NormalizedUri -> Logger -> Var (HashMap TypeRep Dynamic) -> Var Values -> Var DiagnosticStore -> Var DiagnosticStore -> Var (HashMap NormalizedUri [Diagnostic]) -> Var (HashMap NormalizedUri (Map TextDocumentVersion (PositionDelta, PositionMapping))) -> Var (HashMap NormalizedFilePath Int) -> ShakeExtras
+ Development.IDE.Core.Shake: ShakeExtras :: (FromServerMessage -> IO ()) -> Debouncer NormalizedUri -> Logger -> Var (HashMap TypeRep Dynamic) -> Var Values -> Var DiagnosticStore -> Var DiagnosticStore -> Var (HashMap NormalizedUri [Diagnostic]) -> Var (HashMap NormalizedUri (Map TextDocumentVersion (PositionDelta, PositionMapping))) -> Var (HashMap NormalizedFilePath Int) -> (ProgressEvent -> IO ()) -> IdeTesting -> MVar ShakeSession -> WithProgressFunc -> WithIndefiniteProgressFunc -> ([DelayedAction ()] -> IO ()) -> IORef NameCache -> ShakeExtras
- Development.IDE.Core.Shake: shakeOpen :: IO LspId -> (FromServerMessage -> IO ()) -> Logger -> Debouncer NormalizedUri -> Maybe FilePath -> IdeReportProgress -> ShakeOptions -> Rules () -> IO IdeState
+ Development.IDE.Core.Shake: shakeOpen :: IO LspId -> (FromServerMessage -> IO ()) -> WithProgressFunc -> WithIndefiniteProgressFunc -> Logger -> Debouncer NormalizedUri -> Maybe FilePath -> IdeReportProgress -> IdeTesting -> ShakeOptions -> Rules () -> IO IdeState
- Development.IDE.LSP.LanguageServer: runLanguageServer :: forall config. Show config => Options -> PartialHandlers config -> (InitializeRequest -> Either Text config) -> (DidChangeConfigurationNotification -> Either Text config) -> (IO LspId -> (FromServerMessage -> IO ()) -> VFSHandle -> ClientCapabilities -> IO IdeState) -> IO ()
+ Development.IDE.LSP.LanguageServer: runLanguageServer :: forall config. Show config => Options -> PartialHandlers config -> (InitializeRequest -> Either Text config) -> (DidChangeConfigurationNotification -> Either Text config) -> (IO LspId -> (FromServerMessage -> IO ()) -> VFSHandle -> ClientCapabilities -> WithProgressFunc -> WithIndefiniteProgressFunc -> IO IdeState) -> IO ()
- Development.IDE.Spans.Common: SpanDocString :: HsDocString -> SpanDoc
+ Development.IDE.Spans.Common: SpanDocString :: HsDocString -> SpanDocUris -> SpanDoc
- Development.IDE.Spans.Common: SpanDocText :: [Text] -> SpanDoc
+ Development.IDE.Spans.Common: SpanDocText :: [Text] -> SpanDocUris -> SpanDoc
- Development.IDE.Types.Options: IdeOptions :: (ParsedSource -> IdePreprocessedSource) -> Action (FilePath -> Action (IdeResult HscEnvEq)) -> IdePkgLocationOptions -> [String] -> Int -> Maybe FilePath -> Maybe FilePath -> Bool -> IdeReportProgress -> String -> Bool -> [Text] -> IdeDefer -> IdeOptions
+ Development.IDE.Types.Options: IdeOptions :: (ParsedSource -> IdePreprocessedSource) -> Action IdeGhcSession -> IdePkgLocationOptions -> [String] -> Int -> Maybe FilePath -> Maybe FilePath -> IdeTesting -> IdeReportProgress -> String -> Bool -> [Text] -> IdeDefer -> IdeOptions
- Development.IDE.Types.Options: [optGhcSession] :: IdeOptions -> Action (FilePath -> Action (IdeResult HscEnvEq))
+ Development.IDE.Types.Options: [optGhcSession] :: IdeOptions -> Action IdeGhcSession
- Development.IDE.Types.Options: [optTesting] :: IdeOptions -> Bool
+ Development.IDE.Types.Options: [optTesting] :: IdeOptions -> IdeTesting
- Development.IDE.Types.Options: defaultIdeOptions :: Action (FilePath -> Action (IdeResult HscEnvEq)) -> IdeOptions
+ Development.IDE.Types.Options: defaultIdeOptions :: Action IdeGhcSession -> IdeOptions

Files

CHANGELOG.md view
@@ -1,5 +1,61 @@ ### unreleased +### 0.3.0 (2020-09-02)++* CI: remove (internal) DA Slack notifications (#750) - (Gary Verhaegen)+* Add session-loader to hie.yaml (#714) - (Luke Lau)+* Codeaction for exporting unused top-level bindings (#711) - (shaurya gupta)+* Add links to haddock and hscolour pages in documentation (#699) - (Luke Lau)+* Expose GHC.Compat module (#709) - (Pepe Iborra)+* Move session loading logic into ghcide library (#697) - (Luke Lau)+* Code action: remove redundant constraints for type signature (#692) - (Denis Frezzato)+* Fix Binary instance of Q to handle empty file paths (#707) - (Moritz Kiefer)+* Populate ms_hs_date in GetModSummary rule (#694) - (Pepe Iborra)+* Allow GHC plugins to be called with an updated StringBuffer (#698) - (Alfredo Di Napoli)+* Relax upper bounds for GHC 8.10.1 (#705) - (Pepe Iborra)+* Obtain the GHC libdir at runtime (#696) - (Luke Lau)+* Expect bench experiments to fail with Cabal (#704) - (Pepe Iborra)+* Bump lodash from 4.17.15 to 4.17.19 in /extension (#702) - (dependabot[bot])+* Update to hie-bios 0.6.1 (#693) - (fendor)+* Backport HIE files to GHC 8.6 (#689) - (wz1000)+* Performance improvements for GetSpanInfo (#681) - (Pepe Iborra)+* Code action add default type annotation to remove `-Wtype-defaults` warning (#680) - (Serhii)+* Use a global namecache to read `.hie` files (#677) - (wz1000)+* Completions need not depend on typecheck of the current file (#670) - (Pepe Iborra)+* Fix spaninfo Haddocks for local modules (#678) - (Pepe Iborra)+* Avoid excessive retypechecking of TH codebases (#673) - (Pepe Iborra)+* Use stale information if it's available to answer requests quickly (#624) - (Matthew Pickering)+* Code action: add constraint (#653) - (Denis Frezzato)+* Make BenchHist non buildable by default and save logs (#666) - (Pepe Iborra)+* Delete unused top level binding code action (#657) - (Serhii)+* stack810.yaml: bump (#651) - (Domen Kozar)+* Fix debouncer for 0 delay (#662) - (Pepe Iborra)+* Interface file fixes (#645) - (Pepe Iborra)+* Retry GHC 8.10 on Windows (#661) - (Moritz Kiefer)+* Finer dependencies for GhcSessionFun (#643) - (Pepe Iborra)+* Send WorkDoneProgressEnd only when work is done (#649) - (Pepe Iborra)+* Add a note on differential benchmarks (#647) - (Pepe Iborra)+* Cache a ghc session per file of interest (#630) - (Pepe Iborra)+* Remove `Strict` from the language extensions used for code actions (#638) - (Torsten Schmits)+* Report progress when setting up cradle (#644) - (Luke Lau)+* Fix crash when writing to a Barrier more than once (#637) - (Pepe Iborra)+* Write a cabal.project file in the benchmark example (#640) - (Pepe Iborra)+* Performance analysis over time (#629) - (Pepe Iborra)+* More benchmarks (#625) - (Pepe Iborra)+* Canonicalize the locations in the cradle tests (#628) - (Luke Lau)+* Add hie.yaml.stack and use none cradle for test data (#626) - (Javier Neira)+* Fix a bug in getHiFileRule (#623) - (Pepe Iborra)+* ghc initialization error handling (#609) - (Pepe Iborra)+* Fix regression in getSpanInfoRule (#622) - (Pepe Iborra)+* Restore Shake profiling (#621) - (Pepe Iborra)+* Use a better noRange (#612) - (Neil Mitchell)+* Add back a .ghci file (#607) - (Neil Mitchell)+* #573, make haddock errors warnings with the word Haddock in front (#608) - (Neil Mitchell)+* Implement Goto Type Definition (#533) - (Matthew Pickering)+* remove unnecessary FileExists dependency in GetHiFile (#589) - (Pepe Iborra)+* ShakeSession and shakeEnqueue (#554) - (Pepe Iborra)+* Benchmark suite (#590) - (Pepe Iborra)+ ### 0.2.0 (2020-06-02)  * Multi-component support (thanks @mpickering)
README.md view
@@ -4,7 +4,7 @@  Our vision is that you should build an IDE by combining: -![vscode](https://raw.githubusercontent.com/digital-asset/ghcide/master/img/vscode2.png)+![vscode](https://raw.githubusercontent.com/haskell/ghcide/master/img/vscode2.png)  * [`hie-bios`](https://github.com/mpickering/hie-bios) for determining where your files are, what are their dependencies, what extensions are enabled and so on; * `ghcide` (i.e. this library) for defining how to type check, when to type check, and producing diagnostic messages;@@ -64,7 +64,7 @@  First install the `ghcide` binary using `stack` or `cabal`, e.g. -1. `git clone https://github.com/digital-asset/ghcide.git`+1. `git clone https://github.com/haskell/ghcide.git` 2. `cd ghcide` 3. `cabal install` or `stack install` (and make sure `~/.local/bin` is on your `$PATH`) @@ -310,6 +310,17 @@ This writes a log file called `.tasty-rerun-log` of the failures, and only runs those. See the [tasty-rerun](https://hackage.haskell.org/package/tasty-rerun-1.1.17/docs/Test-Tasty-Ingredients-Rerun.html) documentation for other options. +If you are touching performance sensitive code, take the time to run a differential+benchmark between HEAD and upstream using the benchHist script. The configuration in+`bench/hist.yaml` is setup to do this by default assuming upstream is+`origin/master`. Run the benchmarks with `stack`:++    export STACK_YAML=...+    stack bench++It should take around 15 minutes and the results will be stored in the `bench-hist` folder.+To interpret the results, see the comments in the `bench/hist/Main.hs` module.+ ### Building the extension  For development, you can also the VSCode extension from this repository (see@@ -327,8 +338,8 @@  The teams behind this project and the [`haskell-ide-engine`](https://github.com/haskell/haskell-ide-engine#readme) have agreed to join forces under the [`haskell-language-server` project](https://github.com/haskell/haskell-language-server), see the [original announcement](https://neilmitchell.blogspot.com/2020/01/one-haskell-ide-to-rule-them-all.html). The technical work is ongoing, with the likely model being that this project serves as the core, while plugins and integrations are kept in the [`haskell-language-server` project](https://github.com/haskell/haskell-language-server). -The code behind `ghcide` was originally developed by [Digital Asset](https://digitalasset.com/) as part of the [DAML programming language](https://github.com/digital-asset/daml). DAML is a smart contract language targeting distributed-ledger runtimes, based on [GHC](https://www.haskell.org/ghc/) with custom language extensions. The DAML programming language has [an IDE](https://webide.daml.com/), and work was done to separate off a reusable Haskell-only IDE (what is now `ghcide`) which the [DAML IDE then builds upon](https://github.com/digital-asset/daml/tree/master/compiler/damlc). Since that time, there have been various [non-Digital Asset contributors](https://github.com/digital-asset/ghcide/graphs/contributors), in addition to continued investment by Digital Asset. All contributions require a [Contributor License Agreement](https://cla.digitalasset.com/digital-asset/ghcide) that states you license the code under the [Apache License](LICENSE).+The code behind `ghcide` was originally developed by [Digital Asset](https://digitalasset.com/) as part of the [DAML programming language](https://github.com/digital-asset/daml). DAML is a smart contract language targeting distributed-ledger runtimes, based on [GHC](https://www.haskell.org/ghc/) with custom language extensions. The DAML programming language has [an IDE](https://webide.daml.com/), and work was done to separate off a reusable Haskell-only IDE (what is now `ghcide`) which the [DAML IDE then builds upon](https://github.com/digital-asset/daml/tree/master/compiler/damlc). Since that time, there have been various [non-Digital Asset contributors](https://github.com/digital-asset/ghcide/graphs/contributors), in addition to continued investment by Digital Asset. The project has been handed over to Haskell.org as of September 2020.  The Haskell community [has](https://github.com/DanielG/ghc-mod) [various](https://github.com/chrisdone/intero) [IDE](https://github.com/rikvdkleij/intellij-haskell) [choices](http://leksah.org/), but the one that had been gathering momentum is [`haskell-ide-engine`](https://github.com/haskell/haskell-ide-engine#readme). Our project owes a debt of gratitude to the `haskell-ide-engine`. We reuse libraries from their ecosystem, including [`hie-bios`](https://github.com/mpickering/hie-bios#readme) (a likely future environment setup layer in `haskell-ide-engine`), [`haskell-lsp`](https://github.com/alanz/haskell-lsp#readme) and [`lsp-test`](https://github.com/bubba/lsp-test#readme) (the `haskell-ide-engine` [LSP protocol](https://microsoft.github.io/language-server-protocol/) pieces). We make heavy use of their contributions to GHC itself, in particular the work to make GHC take string buffers rather than files. -The best summary of the architecture of `ghcide` is available [this talk](https://www.youtube.com/watch?v=cijsaeWNf2E&list=PLxxF72uPfQVRdAsvj7THoys-nVj-oc4Ss) ([slides](https://ndmitchell.com/downloads/slides-making_a_haskell_ide-07_sep_2019.pdf)), given at [MuniHac 2019](https://munihac.de/2019.html). However, since that talk the project has renamed from `hie-core` to `ghcide`, and the repo has moved to [this location](https://github.com/digital-asset/ghcide/).+The best summary of the architecture of `ghcide` is available [this talk](https://www.youtube.com/watch?v=cijsaeWNf2E&list=PLxxF72uPfQVRdAsvj7THoys-nVj-oc4Ss) ([slides](https://ndmitchell.com/downloads/slides-making_a_haskell_ide-07_sep_2019.pdf)), given at [MuniHac 2019](https://munihac.de/2019.html). However, since that talk the project has renamed from `hie-core` to `ghcide`, and the repo has moved to [this location](https://github.com/haskell/ghcide/).
+ bench/exe/Main.hs view
@@ -0,0 +1,50 @@+{- An automated benchmark built around the simple experiment described in:++  > https://neilmitchell.blogspot.com/2020/05/fixing-space-leaks-in-ghcide.html++  As an example project, it unpacks Cabal-3.2.0.0 in the local filesystem and+  loads the module 'Distribution.Simple'. The rationale for this choice is:++    - It's convenient to download with `cabal unpack Cabal-3.2.0.0`+    - It has very few dependencies, and all are already needed to build ghcide+    - Distribution.Simple has 235 transitive module dependencies, so non trivial++  The experiments are sequences of lsp commands scripted using lsp-test.+  A more refined approach would be to record and replay real IDE interactions,+  once the replay functionality is available in lsp-test.+  A more declarative approach would be to reuse ide-debug-driver:++  > https://github.com/digital-asset/daml/blob/master/compiler/damlc/ide-debug-driver/README.md++  The result of an experiment is a total duration in seconds after a preset+  number of iterations. There is ample room for improvement:+     - Statistical analysis to detect outliers and auto infer the number of iterations needed+     - GC stats analysis (currently -S is printed as part of the experiment)+     - Analyisis of performance over the commit history of the project++  How to run:+     1. `cabal exec cabal run ghcide-bench -- -- ghcide-bench-options`+     1. `stack build ghcide:ghcide-bench && stack exec ghcide-bench -- -- ghcide-bench-options`++  Note that the package database influences the response times of certain actions,+  e.g. code actions, and therefore the two methods above do not necessarily+  produce the same results.++ -}++{-# LANGUAGE ImplicitParams #-}++import Control.Exception.Safe+import Experiments+import Options.Applicative++main :: IO ()+main = do+  config <- execParser $ info (configP <**> helper) fullDesc+  let ?config = config++  output "starting test"++  cleanUp <- setup++  runBenchmarks experiments `finally` cleanUp
+ bench/hist/Main.hs view
@@ -0,0 +1,472 @@+{-  Bench history++    A Shake script to analyze the performance of ghcide over the git history of the project++    Driven by a config file `bench/hist.yaml` containing the list of Git references to analyze.++    Builds each one of them and executes a set of experiments using the ghcide-bench suite.++    The results of the benchmarks and the analysis are recorded in the file+    system with the following structure:++    bench-hist+    ├── <git-reference>                       - one folder per version+    │   ├── <experiment>.benchmark-gcStats    - RTS -s output+    │   ├── <experiment>.csv                  - stats for the experiment+    │   ├── <experiment>.svg                  - Graph of bytes over elapsed time+    │   ├── <experiment>.diff.svg             - idem, including the previous version+    │   ├── <experiment>.log                  - ghcide-bench output+    │   ├── ghc.path                          - path to ghc used to build the binary+    │   ├── ghcide                            - binary for this version+    │   └── results.csv                       - results of all the experiments for the version+    ├── results.csv        - aggregated results of all the experiments and versions+    ├── <experiment>.svg   - graph of bytes over elapsed time, for all the included versions++   For diff graphs, the "previous version" is the preceding entry in the list of versions+   in the config file. A possible improvement is to obtain this info via `git rev-list`.++   The script relies on stack for building and running all the binaries.++   To execute the script:++   > stack bench++   To build a specific analysis, enumerate the desired file artifacts++   > stack bench --ba "bench-hist/HEAD/results.csv bench-hist/HEAD/edit.diff.svg"++ -}+{-# LANGUAGE DeriveAnyClass    #-}+{-# LANGUAGE DerivingStrategies#-}+{-# LANGUAGE TypeFamilies      #-}++import Control.Applicative (Alternative (empty))+import Control.Monad (when, forM, forM_, replicateM)+import Data.Foldable (find)+import Data.Maybe (fromMaybe)+import Data.Text (Text)+import qualified Data.Text as T+import Data.Yaml ((.!=), (.:?), FromJSON (..), ToJSON (..), Value (..), decodeFileThrow)+import Development.Shake+import Development.Shake.Classes (Binary, Hashable, NFData)+import GHC.Exts (IsList (..))+import GHC.Generics (Generic)+import qualified Graphics.Rendering.Chart.Backend.Diagrams as E+import Graphics.Rendering.Chart.Easy ((.=))+import qualified Graphics.Rendering.Chart.Easy as E+import Numeric.Natural (Natural)+import System.Directory+import System.FilePath+import qualified Text.ParserCombinators.ReadP as P+import Text.Read (Read (..), get, readMaybe, readP_to_Prec)++config :: FilePath+config = "bench/hist.yaml"++-- | Read the config without dependency+readConfigIO :: FilePath -> IO Config+readConfigIO = decodeFileThrow++newtype GetSamples = GetSamples () deriving newtype (Binary, Eq, Hashable, NFData, Show)++newtype GetExperiments = GetExperiments () deriving newtype (Binary, Eq, Hashable, NFData, Show)++newtype GetVersions = GetVersions () deriving newtype (Binary, Eq, Hashable, NFData, Show)++newtype GetParent = GetParent Text deriving newtype (Binary, Eq, Hashable, NFData, Show)++newtype GetCommitId = GetCommitId String deriving newtype (Binary, Eq, Hashable, NFData, Show)++type instance RuleResult GetSamples = Natural++type instance RuleResult GetExperiments = [Unescaped String]++type instance RuleResult GetVersions = [GitCommit]++type instance RuleResult GetParent = Text++type instance RuleResult GetCommitId = String++main :: IO ()+main = shakeArgs shakeOptions {shakeChange = ChangeModtimeAndDigest} $ do+  want ["all"]++  readConfig <- newCache $ \fp -> need [fp] >> liftIO (readConfigIO fp)++  _ <- addOracle $ \GetSamples {} -> samples <$> readConfig config+  _ <- addOracle $ \GetExperiments {} -> experiments <$> readConfig config+  _ <- addOracle $ \GetVersions {} -> versions <$> readConfig config+  _ <- addOracle $ \(GetParent name) -> findPrev name . versions <$> readConfig config++  let readVersions = askOracle $ GetVersions ()+      readExperiments = askOracle $ GetExperiments ()+      readSamples = askOracle $ GetSamples ()+      getParent = askOracle . GetParent++  build <- liftIO $ outputFolder <$> readConfigIO config+  ghcideBenchPath <- ghcideBench <$> liftIO (readConfigIO config)++  phony "all" $ do+    Config {..} <- readConfig config++    forM_ versions $ \ver ->+      need [build </> T.unpack (humanName ver) </> "results.csv"]++    need $+      [build </> "results.csv"]+        ++ [ build </> escaped (escapeExperiment e) <.> "svg"+             | e <- experiments+           ]+        ++ [ build </> T.unpack (humanName ver) </> escaped (escapeExperiment e) <.> mode <.> "svg"+             | e <- experiments,+               ver <- versions,+               mode <- ["", "diff"]+           ]++  build -/- "*/commitid" %> \out -> do+      alwaysRerun++      let [_,ver,_] = splitDirectories out+      mbEntry <- find ((== T.pack ver) . humanName) <$> readVersions+      let gitThing :: String+          gitThing = maybe ver (T.unpack . gitName) mbEntry+      Stdout commitid <- command [] "git" ["rev-list", "-n", "1", gitThing]+      writeFileChanged out $ init commitid++  priority 10 $ [build -/- "HEAD/ghcide"+                , build -/- "HEAD/ghc.path"+                ]+    &%> \[out, ghcpath] -> do+      liftIO $ createDirectoryIfMissing True $ dropFileName out+      need =<< getDirectoryFiles "." ["src//*.hs", "exe//*.hs", "ghcide.cabal"]+      cmd_+          ( "stack --local-bin-path=" <> takeDirectory out+              <> " --stack-yaml=stack88.yaml build ghcide:ghcide --copy-bins --ghc-options -rtsopts"+          )+      Stdout ghcLoc <- cmd (s "stack --stack-yaml=stack88.yaml exec which ghc")+      writeFile' ghcpath ghcLoc++  [ build -/- "*/ghcide",+    build -/- "*/ghc.path"+    ]+    &%> \[out, ghcpath] -> do+      let [b, ver, _] = splitDirectories out+      liftIO $ createDirectoryIfMissing True $ dropFileName out+      commitid <- readFile' $ b </> ver </> "commitid"+      cmd_ $ "git worktree add bench-temp " ++ commitid+      flip actionFinally (cmd_ (s "git worktree remove bench-temp --force")) $ do+        Stdout ghcLoc <- cmd [Cwd "bench-temp"] (s "stack --stack-yaml=stack88.yaml exec which ghc")+        cmd_+          [Cwd "bench-temp"]+          ( "stack --local-bin-path=../"+              <> takeDirectory out+              <> " --stack-yaml=stack88.yaml build ghcide:ghcide --copy-bins --ghc-options -rtsopts"+          )+        writeFile' ghcpath ghcLoc++  priority 8000 $+    build -/- "*/results.csv" %> \out -> do+      experiments <- readExperiments++      let allResultFiles = [takeDirectory out </> escaped (escapeExperiment e) <.> "csv" | e <- experiments]+      allResults <- traverse readFileLines allResultFiles++      let header = head $ head allResults+          results = map tail allResults+      writeFileChanged out $ unlines $ header : concat results++  ghcideBenchResource <- newResource "ghcide-bench" 1++  priority 0 $+    [ build -/- "*/*.csv",+      build -/- "*/*.benchmark-gcStats",+      build -/- "*/*.log"+    ]+      &%> \[outcsv, _outGc, outLog] -> do+        let [_, _, exp] = splitDirectories outcsv+        samples <- readSamples+        liftIO $ createDirectoryIfMissing True $ dropFileName outcsv+        let ghcide = dropFileName outcsv </> "ghcide"+            ghcpath = dropFileName outcsv </> "ghc.path"+        need [ghcide, ghcpath]+        ghcPath <- readFile' ghcpath+        withResource ghcideBenchResource 1 $ do+          command_+              [ EchoStdout False,+                FileStdout outLog,+                RemEnv "NIX_GHC_LIBDIR",+                RemEnv "GHC_PACKAGE_PATH",+                AddPath [takeDirectory ghcPath, "."] []+              ]+              ghcideBenchPath+              [ "--timeout=3000",+                "-v",+                "--samples=" <> show samples,+                "--csv=" <> outcsv,+                "--example-package-version=3.0.0.0",+                "--ghcide-options= +RTS -I0.5 -RTS",+                "--ghcide=" <> ghcide,+                "--select",+                unescaped (unescapeExperiment (Escaped $ dropExtension exp))+              ]+          cmd_ Shell $ "mv *.benchmark-gcStats " <> dropFileName outcsv++  build -/- "results.csv" %> \out -> do+    versions <- readVersions+    let allResultFiles =+          [build </> T.unpack (humanName v) </> "results.csv" | v <- versions]++    need [build </> T.unpack (humanName v) </> "ghcide" | v <- versions]++    allResults <- traverse readFileLines allResultFiles++    let header = head $ head allResults+        results = map tail allResults+        header' = "version, " <> header+        results' = zipWith (\v -> map (\l -> T.unpack (humanName v) <> ", " <> l)) versions results++    writeFileChanged out $ unlines $ header' : concat results'++  priority 2 $+    build -/- "*/*.diff.svg" %> \out -> do+      let [b, ver, exp_] = splitDirectories out+          exp = Escaped $ dropExtension $ dropExtension exp_+      prev <- getParent $ T.pack ver++      runLog <- loadRunLog b exp ver+      runLogPrev <- loadRunLog b exp $ T.unpack prev++      let diagram = Diagram Live [runLog, runLogPrev] title+          title = show (unescapeExperiment exp) <> " - live bytes over time compared"+      plotDiagram True diagram out++  priority 1 $+    build -/- "*/*.svg" %> \out -> do+      let [b, ver, exp] = splitDirectories out+      runLog <- loadRunLog b (Escaped $ dropExtension exp) ver+      let diagram = Diagram Live [runLog] title+          title = ver <> " live bytes over time"+      plotDiagram True diagram out++  build -/- "*.svg" %> \out -> do+    let exp = Escaped $ dropExtension $ takeFileName out+    versions <- readVersions++    runLogs <- forM (filter include versions) $ \v -> do+      loadRunLog build exp $ T.unpack $ humanName v++    let diagram = Diagram Live runLogs title+        title = show (unescapeExperiment exp) <> " - live bytes over time"+    plotDiagram False diagram out++----------------------------------------------------------------------------------------------------++data Config = Config+  { experiments :: [Unescaped String],+    samples :: Natural,+    versions :: [GitCommit],+    -- | Path to the ghcide-bench binary for the experiments+    ghcideBench :: FilePath,+    -- | Output folder ('foo' works, 'foo/bar' does not)+    outputFolder :: String+  }+  deriving (Generic, Show)+  deriving anyclass (FromJSON, ToJSON)++data GitCommit = GitCommit+  { -- | A git hash, tag or branch name (e.g. v0.1.0)+    gitName :: Text,+    -- | A human understandable name (e.g. fix-collisions-leak)+    name :: Maybe Text,+    -- | The human understandable name of the parent, if specified explicitly+    parent :: Maybe Text,+    -- | Whether to include this version in the top chart+    include :: Bool+  }+  deriving (Binary, Eq, Hashable, Generic, NFData, Show)++instance FromJSON GitCommit where+  parseJSON (String s) = pure $ GitCommit s Nothing Nothing True+  parseJSON (Object (toList -> [(name, String gitName)])) =+    pure $ GitCommit gitName (Just name) Nothing True+  parseJSON (Object (toList -> [(name, Object props)])) =+    GitCommit+      <$> props .:? "git"  .!= name+      <*> pure (Just name)+      <*> props .:? "parent"+      <*> props .:? "include" .!= True+  parseJSON _ = empty++instance ToJSON GitCommit where+  toJSON GitCommit {..} =+    case name of+      Nothing -> String gitName+      Just n -> Object $ fromList [(n, String gitName)]++humanName :: GitCommit -> Text+humanName GitCommit {..} = fromMaybe gitName name++findPrev :: Text -> [GitCommit] -> Text+findPrev name (x : y : xx)+  | humanName y == name = humanName x+  | otherwise = findPrev name (y : xx)+findPrev name _ = name++----------------------------------------------------------------------------------------------------++-- | A line in the output of -S+data Frame = Frame+  { allocated, copied, live :: !Int,+    user, elapsed, totUser, totElapsed :: !Double,+    generation :: !Int+  }+  deriving (Show)++instance Read Frame where+  readPrec = do+    spaces+    allocated <- readPrec @Int <* spaces+    copied <- readPrec @Int <* spaces+    live <- readPrec @Int <* spaces+    user <- readPrec @Double <* spaces+    elapsed <- readPrec @Double <* spaces+    totUser <- readPrec @Double <* spaces+    totElapsed <- readPrec @Double <* spaces+    _ <- readPrec @Int <* spaces+    _ <- readPrec @Int <* spaces+    "(Gen:  " <- replicateM 7 get+    generation <- readPrec @Int+    ')' <- get+    return Frame {..}+    where+      spaces = readP_to_Prec $ const P.skipSpaces++data TraceMetric = Allocated | Copied | Live | User | Elapsed+  deriving (Generic, Enum, Bounded, Read)++instance Show TraceMetric where+  show Allocated = "Allocated bytes"+  show Copied = "Copied bytes"+  show Live = "Live bytes"+  show User = "User time"+  show Elapsed = "Elapsed time"++frameMetric :: TraceMetric -> Frame -> Double+frameMetric Allocated = fromIntegral . allocated+frameMetric Copied = fromIntegral . copied+frameMetric Live = fromIntegral . live+frameMetric Elapsed = elapsed+frameMetric User = user++data Diagram = Diagram+  { traceMetric :: TraceMetric,+    runLogs :: [RunLog],+    title :: String+  }+  deriving (Generic)++-- | A file path containing the output of -S for a given run+data RunLog = RunLog+  { runVersion :: !String,+    _runExperiment :: !String,+    runFrames :: ![Frame],+    runSuccess :: !Bool+  }++loadRunLog :: FilePath -> Escaped FilePath -> FilePath -> Action RunLog+loadRunLog buildF exp ver = do+  let log_fp = buildF </> ver </> escaped exp <.> "benchmark-gcStats"+      csv_fp = replaceExtension log_fp "csv"+  log <- readFileLines log_fp+  csv <- readFileLines csv_fp+  let frames =+        [ f+          | l <- log,+            Just f <- [readMaybe l],+            -- filter out gen 0 events as there are too many+            generation f == 1+        ]+      success = case map (T.split (== ',') . T.pack) csv of+          [_header, _name:s:_] | Just s <- readMaybe (T.unpack s) -> s+          _ -> error $ "Cannot parse: " <> csv_fp+  return $ RunLog ver (dropExtension $ escaped exp) frames success++plotDiagram :: Bool -> Diagram -> FilePath -> Action ()+plotDiagram includeFailed t@Diagram {traceMetric, runLogs} out = do+  let extract = frameMetric traceMetric+  liftIO $ E.toFile E.def out $ do+    E.layout_title .= title t+    E.setColors myColors+    forM_ runLogs $ \rl ->+      when (includeFailed || runSuccess rl) $ E.plot $ do+        lplot <- E.line+            (runVersion rl ++ if runSuccess rl then "" else " (FAILED)")+            [ [ (totElapsed f, extract f)+                | f <- runFrames rl+                ]+            ]+        return (lplot E.& E.plot_lines_style . E.line_width E.*~ 2)++s :: String -> String+s = id++(-/-) :: FilePattern -> FilePattern -> FilePattern+a -/- b = a <> "/" <> b++newtype Escaped a = Escaped {escaped :: a}++newtype Unescaped a = Unescaped {unescaped :: a}+  deriving newtype (Show, FromJSON, ToJSON, Eq, NFData, Binary, Hashable)++escapeExperiment :: Unescaped String -> Escaped String+escapeExperiment = Escaped . map f . unescaped+  where+    f ' ' = '_'+    f other = other++unescapeExperiment :: Escaped String -> Unescaped String+unescapeExperiment = Unescaped . map f . escaped+  where+    f '_' = ' '+    f other = other++myColors :: [E.AlphaColour Double]+myColors = map E.opaque+  [ E.blue+  , E.green+  , E.red+  , E.orange+  , E.yellow+  , E.violet+  , E.black+  , E.gold+  , E.brown+  , E.hotpink+  , E.aliceblue+  , E.aqua+  , E.beige+  , E.bisque+  , E.blueviolet+  , E.burlywood+  , E.cadetblue+  , E.chartreuse+  , E.coral+  , E.crimson+  , E.darkblue+  , E.darkgray+  , E.darkgreen+  , E.darkkhaki+  , E.darkmagenta+  , E.deeppink+  , E.dodgerblue+  , E.firebrick+  , E.forestgreen+  , E.fuchsia+  , E.greenyellow+  , E.lightsalmon+  , E.seagreen+  , E.olive+  , E.sandybrown+  , E.sienna+  , E.peru+  ]
+ bench/lib/Experiments.hs view
@@ -0,0 +1,423 @@+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE ExistentialQuantification #-}+{-# LANGUAGE ImplicitParams #-}++module Experiments+( Bench(..)+, BenchRun(..)+, Config(..)+, Verbosity(..)+, CabalStack(..)+, experiments+, configP+, defConfig+, output+, setup+, runBench+, runBenchmarks+) where+import Control.Applicative.Combinators (skipManyTill)+import Control.Concurrent+import Control.Exception.Safe+import Control.Monad.Extra+import Control.Monad.IO.Class+import Data.Char (isDigit)+import Data.List+import Data.Maybe+import Data.Version+import Language.Haskell.LSP.Test+import Language.Haskell.LSP.Types+import Language.Haskell.LSP.Types.Capabilities+import Numeric.Natural+import Options.Applicative+import System.Directory+import System.FilePath ((</>))+import System.Process+import System.Time.Extra+import Text.ParserCombinators.ReadP (readP_to_S)+import System.Environment.Blank (getEnv)++-- Points to a string in the target file,+-- convenient for hygienic edits+hygienicP :: Position+hygienicP = Position 854 23++hygienicEdit :: TextDocumentContentChangeEvent+hygienicEdit =+    TextDocumentContentChangeEvent+    { _range = Just (Range hygienicP hygienicP),+        _rangeLength = Nothing,+        _text = " "+    }++breakingEdit :: TextDocumentContentChangeEvent+breakingEdit =+    TextDocumentContentChangeEvent+    { _range = Just (Range identifierP identifierP),+        _rangeLength = Nothing,+        _text = "a"+    }++-- Points to the middle of an identifier,+-- convenient for requesting goto-def, hover and completions+identifierP :: Position+identifierP = Position 853 12++experiments :: [Bench]+experiments =+    [ ---------------------------------------------------------------------------------------+      bench "hover" 10 $ \doc ->+        isJust <$> getHover doc identifierP,+      ---------------------------------------------------------------------------------------+      bench "edit" 10 $ \doc -> do+        changeDoc doc [hygienicEdit]+        void (skipManyTill anyMessage message :: Session WorkDoneProgressEndNotification)+        return True,+      ---------------------------------------------------------------------------------------+      bench "hover after edit" 10 $ \doc -> do+        changeDoc doc [hygienicEdit]+        isJust <$> getHover doc identifierP,+      ---------------------------------------------------------------------------------------+      bench "getDefinition" 10 $ \doc ->+        not . null <$> getDefinitions doc identifierP,+      ---------------------------------------------------------------------------------------+      bench "documentSymbols" 100 $+        fmap (either (not . null) (not . null)) . getDocumentSymbols,+      ---------------------------------------------------------------------------------------+      bench "documentSymbols after edit" 100 $ \doc -> do+        changeDoc doc [hygienicEdit]+        either (not . null) (not . null) <$> getDocumentSymbols doc,+      ---------------------------------------------------------------------------------------+      bench "completions after edit" 10 $ \doc -> do+        changeDoc doc [hygienicEdit]+        not . null <$> getCompletions doc identifierP,+      ---------------------------------------------------------------------------------------+      benchWithSetup+        "code actions"+        10+        ( \doc -> do+            changeDoc doc [breakingEdit]+            void (skipManyTill anyMessage message :: Session WorkDoneProgressEndNotification)+            return identifierP+        )+        ( \p doc -> do+            not . null <$> getCodeActions doc (Range p p)+        ),+      ---------------------------------------------------------------------------------------+      benchWithSetup+        "code actions after edit"+        10+        ( \doc -> do+            changeDoc doc [breakingEdit]+            return identifierP+        )+        ( \p doc -> do+            changeDoc doc [hygienicEdit]+            whileM (null <$> waitForDiagnostics)+            not . null <$> getCodeActions doc (Range p p)+        )+    ]++---------------------------------------------------------------------------------------------++examplePackageName :: HasConfig => String+examplePackageName = name+  where+      (name, _, _) = examplePackageUsed ?config++examplePackage :: HasConfig => String+examplePackage = name <> "-" <> showVersion version+  where+      (name, version, _) = examplePackageUsed ?config++exampleModulePath :: HasConfig => FilePath+exampleModulePath = path+  where+      (_,_, path) = examplePackageUsed ?config++examplesPath :: FilePath+examplesPath = "bench/example"++data Verbosity = Quiet | Normal | All+  deriving (Eq, Show)+data Config = Config+  { verbosity :: !Verbosity,+    -- For some reason, the Shake profile files are truncated and won't load+    shakeProfiling :: !(Maybe FilePath),+    outputCSV :: !FilePath,+    buildTool :: !CabalStack,+    ghcideOptions :: ![String],+    matches :: ![String],+    repetitions :: Maybe Natural,+    ghcide :: FilePath,+    timeoutLsp :: Int,+    examplePackageUsed :: (String, Version, String)+  }+  deriving (Eq, Show)++defConfig :: Config+Success defConfig = execParserPure defaultPrefs (info configP fullDesc) []++quiet, verbose :: Config -> Bool+verbose = (== All) . verbosity+quiet   = (== Quiet) . verbosity++data CabalStack = Cabal | Stack+  deriving (Eq, Show)++type HasConfig = (?config :: Config)++configP :: Parser Config+configP =+  Config+    <$> (flag' All (short 'v' <> long "verbose")+         <|> flag' Quiet (short 'q' <> long "quiet")+         <|> pure Normal+        )+    <*> optional (strOption (long "shake-profiling" <> metavar "PATH"))+    <*> strOption (long "csv" <> metavar "PATH" <> value "results.csv" <> showDefault)+    <*> flag Cabal Stack (long "stack" <> help "Use stack (by default cabal is used)")+    <*> many (strOption (long "ghcide-options" <> help "additional options for ghcide"))+    <*> many (strOption (short 's' <> long "select" <> help "select which benchmarks to run"))+    <*> optional (option auto (long "samples" <> metavar "NAT" <> help "override sampling count"))+    <*> strOption (long "ghcide" <> metavar "PATH" <> help "path to ghcide" <> value "ghcide")+    <*> option auto (long "timeout" <> value 60 <> help "timeout for waiting for a ghcide response")+    <*> ( (,,) <$> strOption (long "example-package-name" <> value "Cabal")+               <*> option versionP (long "example-package-version" <> value (makeVersion [3,2,0,0]))+               <*> strOption (long "example-package-module" <> metavar "PATH" <> value "Distribution/Simple.hs"))++versionP :: ReadM Version+versionP = maybeReader $ extract . readP_to_S parseVersion+  where+      extract parses = listToMaybe [ res | (res,"") <- parses]++output :: (MonadIO m, HasConfig) => String -> m ()+output = if quiet?config then (\_ -> pure ()) else liftIO . putStrLn++---------------------------------------------------------------------------------------++type Experiment = TextDocumentIdentifier -> Session Bool++data Bench = forall setup.+  Bench+  { name :: !String,+    enabled :: !Bool,+    samples :: !Natural,+    benchSetup :: TextDocumentIdentifier -> Session setup,+    experiment :: setup -> Experiment+  }++select :: HasConfig => Bench -> Bool+select Bench {name, enabled} =+  enabled && (null mm || name `elem` mm)+  where+    mm = matches ?config++benchWithSetup ::+  String ->+  Natural ->+  (TextDocumentIdentifier -> Session p) ->+  (p -> Experiment) ->+  Bench+benchWithSetup name samples benchSetup experiment = Bench {..}+  where+    enabled = True++bench :: String -> Natural -> Experiment -> Bench+bench name defSamples userExperiment =+  benchWithSetup name defSamples (const $ pure ()) experiment+  where+    experiment () = userExperiment++runBenchmarks :: HasConfig => [Bench] -> IO ()+runBenchmarks allBenchmarks = do+  let benchmarks = [ b{samples = fromMaybe (samples b) (repetitions ?config) }+                   | b <- allBenchmarks+                   , select b ]+  results <- forM benchmarks $ \b@Bench{name} ->+                let run dir = runSessionWithConfig conf (cmd name dir) lspTestCaps dir+                in (b,) <$> runBench run b++  -- output raw data as CSV+  let headers = ["name", "success", "samples", "startup", "setup", "experiment", "maxResidency"]+      rows =+        [ [ name,+            show success,+            show samples,+            show startup,+            show runSetup',+            show runExperiment,+            showMB maxResidency+          ]+          | (Bench {name, samples}, BenchRun {..}) <- results,+            let runSetup' = if runSetup < 0.01 then 0 else runSetup+        ]+      csv = unlines $ map (intercalate ", ") (headers : rows)+  writeFile (outputCSV ?config) csv++  -- print a nice table+  let pads = map (maximum . map length) (transpose (headers : rowsHuman))+      paddedHeaders = zipWith pad pads headers+      outputRow = putStrLn . intercalate " | "+      rowsHuman =+        [ [ name,+            show success,+            show samples,+            showDuration startup,+            showDuration runSetup',+            showDuration runExperiment,+            showMB maxResidency+          ]+          | (Bench {name, samples}, BenchRun {..}) <- results,+            let runSetup' = if runSetup < 0.01 then 0 else runSetup+        ]+  outputRow paddedHeaders+  outputRow $ (map . map) (const '-') paddedHeaders+  forM_ rowsHuman $ \row -> outputRow $ zipWith pad pads row+  where+    gcStats name = escapeSpaces (name <> ".benchmark-gcStats")+    cmd name dir =+      unwords $+        [ ghcide ?config,+          "--lsp",+          "--cwd",+          dir,+          "+RTS",+          "-S" <> gcStats name,+          "-RTS"+        ]+          ++ ghcideOptions ?config+          ++ concat+            [ ["--shake-profiling", path]+              | Just path <- [shakeProfiling ?config]+            ]+    lspTestCaps =+      fullCaps {_window = Just $ WindowClientCapabilities $ Just True}+    conf =+      defaultConfig+        { logStdErr = verbose ?config,+          logMessages = verbose ?config,+          logColor = False,+          messageTimeout = timeoutLsp ?config+        }++data BenchRun = BenchRun+  { startup :: !Seconds,+    runSetup :: !Seconds,+    runExperiment :: !Seconds,+    success :: !Bool,+    maxResidency :: !Int+  }++badRun :: BenchRun+badRun = BenchRun 0 0 0 False 0++waitForProgressDone :: Session ()+waitForProgressDone =+      void(skipManyTill anyMessage message :: Session WorkDoneProgressEndNotification)++runBench :: (?config::Config) => (String -> Session BenchRun -> IO BenchRun) -> Bench -> IO BenchRun+runBench runSess Bench {..} = handleAny (\e -> print e >> return badRun)+  $ runSess dir+  $ do+    doc <- openDoc exampleModulePath "haskell"+    (startup, _) <- duration $ do+      waitForProgressDone+      -- wait again, as the progress is restarted once while loading the cradle+      -- make an edit, to ensure this doesn't block+      changeDoc doc [hygienicEdit]+      waitForProgressDone+++    liftIO $ output $ "Running " <> name <> " benchmark"+    (runSetup, userState) <- duration $ benchSetup doc+    let loop 0 = return True+        loop n = do+          (t, res) <- duration $ experiment userState doc+          if not res+            then return False+            else do+              output (showDuration t)+              loop (n -1)++    (runExperiment, success) <- duration $ loop samples++    -- sleep to give ghcide a chance to GC+    liftIO $ threadDelay 1100000++    maxResidency <- liftIO $+        ifM (doesFileExist gcStats)+            (parseMaxResidency <$> readFile gcStats)+            (pure 0)++    return BenchRun {..}+  where+    dir = "bench/example/" <> examplePackage+    gcStats = escapeSpaces (name <> ".benchmark-gcStats")++setup :: HasConfig => IO (IO ())+setup = do+  alreadyExists <- doesDirectoryExist examplesPath+  when alreadyExists $ removeDirectoryRecursive examplesPath+  let path = examplesPath </> examplePackage+  case buildTool ?config of+      Cabal -> do+        callCommand $ "cabal get -v0 " <> examplePackage <> " -d " <> examplesPath+        writeFile+            (path </> "hie.yaml")+            ("cradle: {cabal: {component: " <> show examplePackageName <> "}}")+        -- Need this in case there is a parent cabal.project somewhere+        writeFile+            (path </> "cabal.project")+            "packages: ."+        writeFile+            (path </> "cabal.project.local")+            ""+      Stack -> do+        callCommand $ "stack --silent unpack " <> examplePackage <> " --to " <> examplesPath+        -- Generate the stack descriptor to match the one used to build ghcide+        stack_yaml <- fromMaybe "stack.yaml" <$> getEnv "STACK_YAML"+        stack_yaml_lines <- lines <$> readFile stack_yaml+        writeFile (path </> stack_yaml)+                  (unlines $+                   "packages: [.]" :+                    [ l+                    | l <- stack_yaml_lines+                    , any (`isPrefixOf` l)+                        ["resolver"+                        ,"allow-newer"+                        ,"compiler"]+                    ]+                  )++        writeFile+            (path </> "hie.yaml")+            ("cradle: {stack: {component: " <> show (examplePackageName <> ":lib") <> "}}")++  whenJust (shakeProfiling ?config) $ createDirectoryIfMissing True++  return $ removeDirectoryRecursive examplesPath++--------------------------------------------------------------------------------------------++-- Parse the max residency in RTS -s output+parseMaxResidency :: String -> Int+parseMaxResidency input =+  case find ("maximum residency" `isInfixOf`) (reverse $ lines input) of+    Just l -> read $ filter isDigit $ head (words l)+    Nothing -> -1+++escapeSpaces :: String -> String+escapeSpaces = map f+  where+    f ' ' = '_'+    f x = x++pad :: Int -> String -> String+pad n [] = replicate n ' '+pad 0 _ = error "pad"+pad n (x:xx) = x : pad (n-1) xx++showMB :: Int -> String+showMB x = show (x `div` 2^(20::Int)) <> "MB"
exe/Arguments.hs view
@@ -14,6 +14,7 @@     ,argsShakeProfiling :: Maybe FilePath     ,argsTesting :: Bool     ,argsThreads :: Int+    ,argsVerbose :: Bool     }  getArguments :: IO Arguments@@ -33,3 +34,4 @@       <*> optional (strOption $ long "shake-profiling" <> metavar "DIR" <> help "Dump profiling reports to this directory")       <*> switch (long "test" <> help "Enable additional lsp messages used by the testsuite")       <*> option auto (short 'j' <> help "Number of threads (0: automatic)" <> metavar "NUM" <> value 0 <> showDefault)+      <*> switch (long "verbose" <> help "Include internal events in logging output")
exe/Main.hs view
@@ -1,31 +1,18 @@ -- Copyright (c) 2019 The DAML Authors. All rights reserved. -- SPDX-License-Identifier: Apache-2.0 {-# OPTIONS_GHC -Wno-dodgy-imports #-} -- GHC no longer exports def in GHC 8.6 and above-{-# LANGUAGE CPP #-} -- To get precise GHC version {-# LANGUAGE TemplateHaskell #-}-{-# LANGUAGE TypeFamilies #-}  module Main(main) where -import Linker (initDynLinker)-import Data.IORef-import NameCache-import Packages-import Module import Arguments-import Control.Concurrent.Async import Control.Concurrent.Extra-import Control.Exception import Control.Monad.Extra-import Control.Monad.IO.Class import Data.Default-import Data.Either-import Data.Function import Data.List.Extra import Data.Maybe import qualified Data.Text as T import qualified Data.Text.IO as T-import Data.Time.Clock (UTCTime) import Data.Version import Development.IDE.Core.Debouncer import Development.IDE.Core.FileStore@@ -39,44 +26,27 @@ import Development.IDE.Types.Diagnostics import Development.IDE.Types.Options import Development.IDE.Types.Logger-import Development.IDE.GHC.Util import Development.IDE.Plugin import Development.IDE.Plugin.Completions as Completions import Development.IDE.Plugin.CodeAction as CodeAction+import Development.IDE.Session import qualified Language.Haskell.LSP.Core as LSP import Language.Haskell.LSP.Messages import Language.Haskell.LSP.Types-import Data.Aeson (ToJSON(toJSON)) import Development.IDE.LSP.LanguageServer import qualified System.Directory.Extra as IO import System.Environment import System.IO+import System.Info import System.Exit import System.FilePath-import System.Directory import System.Time.Extra-import HIE.Bios.Environment (addCmdOpts, makeDynFlagsAbsolute) import Paths_ghcide import Development.GitRev-import Development.Shake (Action, action) import qualified Data.HashSet as HashSet-import qualified Data.HashMap.Strict as HM-import qualified Data.Map.Strict as Map-import qualified Crypto.Hash.SHA1 as H-import qualified Data.ByteString.Char8 as B-import Data.ByteString.Base16 (encode)-import DynFlags (gopt_set, gopt_unset, updOptLevel, PackageFlag(..), PackageArg(..))-import GhcMonad-import HscTypes (HscEnv(..), ic_dflags)-import GHC hiding (def)-import GHC.Check ( VersionCheck(..), makeGhcVersionChecker )-import Data.Either.Extra  import HIE.Bios.Cradle-import HIE.Bios.Types -import Utils- ghcideVersion :: IO String ghcideVersion = do   path <- getExecutablePath@@ -84,7 +54,7 @@         x | x == "UNKNOWN" -> ""         x -> " (GIT hash: " <> x <> ")"   return $ "ghcide version: " <> showVersion version-             <> " (GHC: " <> VERSION_ghc+             <> " (GHC: " <> showVersion compilerVersion              <> ") (PATH: " <> path <> ")"              <> gitHashSection @@ -118,18 +88,20 @@         t <- offsetTime         hPutStrLn stderr "Starting LSP server..."         hPutStrLn stderr "If you are seeing this in a terminal, you probably should have run ghcide WITHOUT the --lsp option!"-        runLanguageServer options (pluginHandler plugins) onInitialConfiguration onConfigurationChange $ \getLspId event vfs caps -> do+        runLanguageServer options (pluginHandler plugins) onInitialConfiguration onConfigurationChange $ \getLspId event vfs caps wProg wIndefProg -> do             t <- t             hPutStrLn stderr $ "Started LSP server in " ++ showDuration t-            let options = (defaultIdeOptions $ loadSessionShake dir)+            sessionLoader <- loadSession dir+            let options = (defaultIdeOptions sessionLoader)                     { optReportProgress = clientSupportsProgress caps                     , optShakeProfiling = argsShakeProfiling-                    , optTesting        = argsTesting+                    , optTesting        = IdeTesting argsTesting                     , optThreads        = argsThreads                     }+                logLevel = if argsVerbose then minBound else Info             debouncer <- newAsyncDebouncer-            initialise caps (mainRule >> pluginRules plugins >> action kick)-                getLspId event (logger minBound) debouncer options vfs+            initialise caps (mainRule >> pluginRules plugins)+                getLspId event wProg wIndefProg (logger logLevel) debouncer options vfs     else do         -- GHC produces messages with UTF8 in them, so make sure the terminal doesn't error         hSetEncoding stdout utf8@@ -152,18 +124,20 @@         putStrLn "\nStep 3/4: Initializing the IDE"         vfs <- makeVFSHandle         debouncer <- newAsyncDebouncer-        ide <- initialise def mainRule (pure $ IdInt 0) (showEvent lock) (logger Info) debouncer (defaultIdeOptions $ loadSessionShake dir) vfs+        let dummyWithProg _ _ f = f (const (pure ()))+        sessionLoader <- loadSession dir+        ide <- initialise def mainRule (pure $ IdInt 0) (showEvent lock) dummyWithProg (const (const id)) (logger minBound) debouncer (defaultIdeOptions sessionLoader)  vfs          putStrLn "\nStep 4/4: Type checking the files"         setFilesOfInterest ide $ HashSet.fromList $ map toNormalizedFilePath' files-        results <- runActionSync ide $ uses TypeCheck (map toNormalizedFilePath' files)+        results <- runAction "User TypeCheck" ide $ uses TypeCheck (map toNormalizedFilePath' files)         let (worked, failed) = partition fst $ zip (map isJust results) files         when (failed /= []) $             putStr $ unlines $ "Files that failed:" : map ((++) " * " . snd) failed          let files xs = let n = length xs in if n == 1 then "1 file" else show n ++ " files"         putStrLn $ "\nCompleted (" ++ files worked ++ " worked, " ++ files failed ++ " failed)"-        return ()+        unless (null failed) (exitWith $ ExitFailure (length failed))  expandFiles :: [FilePath] -> IO [FilePath] expandFiles = concatMapM $ \x -> do@@ -177,12 +151,6 @@             fail $ "Couldn't find any .hs/.lhs files inside directory: " ++ x         return files --kick :: Action ()-kick = do-    files <- getFilesOfInterest-    void $ uses TypeCheck $ HashSet.toList files- -- | Print an LSP event. showEvent :: Lock -> FromServerMessage -> IO () showEvent _ (EventFileDiagnostics _ []) = return ()@@ -190,494 +158,3 @@     withLock lock $ T.putStrLn $ showDiagnosticsColored $ map (file,ShowDiag,) diags showEvent lock e = withLock lock $ print e ---- | Run the specific cradle on a specific FilePath via hie-bios.-cradleToSessionOpts :: Cradle a -> FilePath -> IO (Either [CradleError] ComponentOptions)-cradleToSessionOpts cradle file = do-    let showLine s = putStrLn ("> " ++ s)-    cradleRes <- runCradle (cradleOptsProg cradle) showLine file-    case cradleRes of-        CradleSuccess r -> pure (Right r)-        CradleFail err -> return (Left [err])-        -- For the None cradle perhaps we still want to report an Info-        -- message about the fact that the file is being ignored.-        CradleNone -> return (Left [])--emptyHscEnv :: IO HscEnv-emptyHscEnv = do-    libdir <- getLibdir-    env <- runGhc (Just libdir) getSession-    initDynLinker env-    pure env---- | Convert a target to a list of potential absolute paths.--- A TargetModule can be anywhere listed by the supplied include--- directories--- A target file is a relative path but with a specific prefix so just need--- to canonicalise it.-targetToFile :: [FilePath] -> TargetId -> IO [NormalizedFilePath]-targetToFile is (TargetModule mod) = do-    let fps = [i </> moduleNameSlashes mod -<.> ext | ext <- exts, i <- is ]-        exts = ["hs", "hs-boot", "lhs"]-    mapM (fmap toNormalizedFilePath' . canonicalizePath) fps-targetToFile _ (TargetFile f _) = do-  f' <- canonicalizePath f-  return [toNormalizedFilePath' f']--setNameCache :: IORef NameCache -> HscEnv -> HscEnv-setNameCache nc hsc = hsc { hsc_NC = nc }--loadSessionShake :: FilePath -> Action (FilePath -> Action (IdeResult HscEnvEq))-loadSessionShake fp = do-  se <- getShakeExtras-  IdeOptions{optTesting} <- getIdeOptions-  res <- liftIO $ loadSession optTesting se fp-  return (fmap liftIO res)---- | This is the key function which implements multi-component support. All--- components mapping to the same hie.yaml file are mapped to the same--- HscEnv which is updated as new components are discovered.-loadSession :: Bool -> ShakeExtras -> FilePath -> IO (FilePath -> IO (IdeResult HscEnvEq))-loadSession optTesting ShakeExtras{logger, eventer} dir = do-  -- Mapping from hie.yaml file to HscEnv, one per hie.yaml file-  hscEnvs <- newVar Map.empty :: IO (Var HieMap)-  -- Mapping from a Filepath to HscEnv-  fileToFlags <- newVar Map.empty :: IO (Var FlagsMap)--  -- This caches the mapping from Mod.hs -> hie.yaml-  cradleLoc <- memoIO $ \v -> do-      res <- findCradle v-      -- Sometimes we get C:, sometimes we get c:, and sometimes we get a relative path-      -- try and normalise that-      -- e.g. see https://github.com/digital-asset/ghcide/issues/126-      res' <- traverse IO.makeAbsolute res-      return $ normalise <$> res'--  -- Create a new HscEnv from a hieYaml root and a set of options-  -- If the hieYaml file already has an HscEnv, the new component is-  -- combined with the components in the old HscEnv into a new HscEnv-  -- which contains the union.-  let packageSetup :: (Maybe FilePath, NormalizedFilePath, ComponentOptions)-                   -> IO (HscEnv, ComponentInfo, [ComponentInfo])-      packageSetup (hieYaml, cfp, opts) = do-        -- Parse DynFlags for the newly discovered component-        hscEnv <- emptyHscEnv-        (df, targets) <- evalGhcEnv hscEnv $-                          setOptions opts (hsc_dflags hscEnv)-        dep_info <- getDependencyInfo (componentDependencies opts ++ maybeToList hieYaml)-        -- Now lookup to see whether we are combining with an existing HscEnv-        -- or making a new one. The lookup returns the HscEnv and a list of-        -- information about other components loaded into the HscEnv-        -- (unitId, DynFlag, Targets)-        modifyVar hscEnvs $ \m -> do-            -- Just deps if there's already an HscEnv-            -- Nothing is it's the first time we are making an HscEnv-            let oldDeps = Map.lookup hieYaml m-            let -- Add the raw information about this component to the list-                -- We will modify the unitId and DynFlags used for-                -- compilation but these are the true source of-                -- information.-                new_deps = RawComponentInfo (thisInstalledUnitId df) df targets cfp opts dep_info-                              : maybe [] snd oldDeps-                -- Get all the unit-ids for things in this component-                inplace = map rawComponentUnitId new_deps--            new_deps' <- forM new_deps $ \RawComponentInfo{..} -> do-                -- Remove all inplace dependencies from package flags for-                -- components in this HscEnv-                let (df2, uids) = removeInplacePackages inplace rawComponentDynFlags-                let prefix = show rawComponentUnitId-                -- See Note [Avoiding bad interface files]-                processed_df <- setCacheDir logger prefix (sort $ map show uids) opts df2-                -- The final component information, mostly the same but the DynFlags don't-                -- contain any packages which are also loaded-                -- into the same component.-                pure $ ComponentInfo rawComponentUnitId-                                     processed_df-                                     uids-                                     rawComponentTargets-                                     rawComponentFP-                                     rawComponentCOptions-                                     rawComponentDependencyInfo-            -- Make a new HscEnv, we have to recompile everything from-            -- scratch again (for now)-            -- It's important to keep the same NameCache though for reasons-            -- that I do not fully understand-            logInfo logger (T.pack ("Making new HscEnv" ++ show inplace))-            hscEnv <- case oldDeps of-                        Nothing -> emptyHscEnv-                        Just (old_hsc, _) -> setNameCache (hsc_NC old_hsc) <$> emptyHscEnv-            newHscEnv <--              -- Add the options for the current component to the HscEnv-              evalGhcEnv hscEnv $ do-                _ <- setSessionDynFlags df-                getSession-            -- Modify the map so the hieYaml now maps to the newly created-            -- HscEnv-            -- Returns-            -- . the new HscEnv so it can be used to modify the-            --   FilePath -> HscEnv map (fileToFlags)-            -- . The information for the new component which caused this cache miss-            -- . The modified information (without -inplace flags) for-            --   existing packages-            pure (Map.insert hieYaml (newHscEnv, new_deps) m, (newHscEnv, head new_deps', tail new_deps'))--  let session :: (Maybe FilePath, NormalizedFilePath, ComponentOptions) -> IO (IdeResult HscEnvEq)-      session (hieYaml, cfp, opts) = do-        (hscEnv, new, old_deps) <- packageSetup (hieYaml, cfp, opts)-        -- Make a map from unit-id to DynFlags, this is used when trying to-        -- resolve imports. (especially PackageImports)-        let uids = map (\ci -> (componentUnitId ci, componentDynFlags ci)) (new : old_deps)--        -- For each component, now make a new HscEnvEq which contains the-        -- HscEnv for the hie.yaml file but the DynFlags for that component--        -- New HscEnv for the component in question, returns the new HscEnvEq and-        -- a mapping from FilePath to the newly created HscEnvEq.-        let new_cache = newComponentCache logger hscEnv uids-        (cs, res) <- new_cache new-        -- Modified cache targets for everything else in the hie.yaml file-        -- which now uses the same EPS and so on-        cached_targets <- concatMapM (fmap fst . new_cache) old_deps-        modifyVar_ fileToFlags $ \var -> do-            pure $ Map.insert hieYaml (HM.fromList (cs ++ cached_targets)) var--        return (fst res)--  let consultCradle :: Maybe FilePath -> FilePath -> IO (IdeResult HscEnvEq)-      consultCradle hieYaml cfp = do-         when optTesting $ eventer $ notifyCradleLoaded cfp-         logInfo logger $ T.pack ("Consulting the cradle for " <> show cfp)-         cradle <- maybe (loadImplicitCradle $ addTrailingPathSeparator dir) loadCradle hieYaml-         eopts <- cradleToSessionOpts cradle cfp-         logDebug logger $ T.pack ("Session loading result: " <> show eopts)-         case eopts of-           -- The cradle gave us some options so get to work turning them-           -- into and HscEnv.-           Right opts -> do-             session (hieYaml, toNormalizedFilePath' cfp, opts)-           -- Failure case, either a cradle error or the none cradle-           Left err -> do-             dep_info <- getDependencyInfo (maybeToList hieYaml)-             let ncfp = toNormalizedFilePath' cfp-             let res = (map (renderCradleError ncfp) err, Nothing)-             modifyVar_ fileToFlags $ \var -> do-               pure $ Map.insertWith HM.union hieYaml (HM.singleton ncfp (res, dep_info)) var-             return res--  -- This caches the mapping from hie.yaml + Mod.hs -> [String]-  let sessionOpts :: (Maybe FilePath, FilePath) -> IO (IdeResult HscEnvEq)-      sessionOpts (hieYaml, file) = do-        v <- fromMaybe HM.empty . Map.lookup hieYaml <$> readVar fileToFlags-        cfp <- canonicalizePath file-        case HM.lookup (toNormalizedFilePath' cfp) v of-          Just (opts, old_di) -> do-            deps_ok <- checkDependencyInfo old_di-            if not deps_ok-              then do-                -- If the dependencies are out of date then clear both caches and start-                -- again.-                modifyVar_ fileToFlags (const (return Map.empty))-                -- Keep the same name cache-                modifyVar_ hscEnvs (return . Map.adjust (\(h, _) -> (h, [])) hieYaml )-                consultCradle hieYaml cfp-              else return opts-          Nothing -> consultCradle hieYaml cfp--  dummyAs <- async $ return (error "Uninitialised")-  runningCradle <- newVar dummyAs :: IO (Var (Async (IdeResult HscEnvEq)))-  -- The main function which gets options for a file. We only want one of these running-  -- at a time. Therefore the IORef contains the currently running cradle, if we try-  -- to get some more options then we wait for the currently running action to finish-  -- before attempting to do so.-  let getOptions :: FilePath -> IO (IdeResult HscEnvEq)-      getOptions file = do-          hieYaml <- cradleLoc file-          sessionOpts (hieYaml, file)-  return $ \file -> do-    join $ mask_ $ modifyVar runningCradle $ \as -> do-      -- If the cradle is not finished, then wait for it to finish.-      void $ wait as-      as <- async $ getOptions file-      return (as, wait as)------ | Create a mapping from FilePaths to HscEnvEqs-newComponentCache-         :: Logger-         -> HscEnv-         -> [(InstalledUnitId, DynFlags)]-         -> ComponentInfo-         -> IO ([(NormalizedFilePath, (IdeResult HscEnvEq, DependencyInfo))], (IdeResult HscEnvEq, DependencyInfo))-newComponentCache logger hsc_env uids ci = do-    let df = componentDynFlags ci-    let hscEnv' = hsc_env { hsc_dflags = df-                          , hsc_IC = (hsc_IC hsc_env) { ic_dflags = df } }--    versionMismatch <- checkGhcVersion-    henv <- case versionMismatch of-              Just mismatch -> return mismatch-              Nothing -> newHscEnvEq hscEnv' uids-    let res = (([], Just henv), componentDependencyInfo ci)-    logDebug logger ("New Component Cache HscEnvEq: " <> T.pack (show res))--    let is = importPaths df-    ctargets <- concatMapM (targetToFile is  . targetId) (componentTargets ci)-    -- A special target for the file which caused this wonderful-    -- component to be created. In case the cradle doesn't list all the targets for-    -- the component, in which case things will be horribly broken anyway.-    -- Otherwise, we will immediately attempt to reload this module which-    -- causes an infinite loop and high CPU usage.-    let special_target = (componentFP ci, res)-    let xs = map (,res) ctargets-    return (special_target:xs, res)--{- Note [Avoiding bad interface files]-~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~-Originally, we set the cache directory for the various components once-on the first occurrence of the component.-This works fine if these components have no references to each other,-but you have components that depend on each other, the interface files are-updated for each component.-After restarting the session and only opening the component that depended-on the other, suddenly the interface files of this component are stale.-However, from the point of view of `ghcide`, they do not look stale,-thus, not regenerated and the IDE shows weird errors such as:-```-typecheckIface-Declaration for Rep_ClientRunFlags-Axiom branches Rep_ClientRunFlags:-  Failed to load interface for ‘Distribution.Simple.Flag’-  Use -v to see a list of the files searched for.-```-and-```-expectJust checkFamInstConsistency-CallStack (from HasCallStack):-  error, called at compiler\\utils\\Maybes.hs:55:27 in ghc:Maybes-  expectJust, called at compiler\\typecheck\\FamInst.hs:461:30 in ghc:FamInst-```--To mitigate this, we set the cache directory for each component dependent-on the components of the current `HscEnv`, additionally to the component options-of the respective components.-Assume two components, c1, c2, where c2 depends on c1, and the options of the-respective components are co1, co2.-If we want to load component c2, followed by c1, we set the cache directory for-each component in this way:--  * Load component c2-    * (Cache Directory State)-        - name of c2 + co2-  * Load component c1-    * (Cache Directory State)-        - name of c2 + name of c1 + co2-        - name of c2 + name of c1 + co1--Overall, we created three cache directories. If we opened c1 first, then we-create a fourth cache directory.-This makes sure that interface files are always correctly updated.--Since this causes a lot of recompilation, we only update the cache-directory,-if the dependencies of a component have really changed.-E.g. when you load two executables, they can not depend on each other. They-should be filtered out, such that we dont have to re-compile everything.--}---- | Set the cache-directory based on the ComponentOptions and a list of--- internal packages.--- For the exact reason, see Note [Avoiding bad interface files].-setCacheDir :: MonadIO m => Logger -> String -> [String] -> ComponentOptions -> DynFlags -> m DynFlags-setCacheDir logger prefix hscComponents comps dflags = do-    cacheDir <- liftIO $ getCacheDir prefix (hscComponents ++ componentOptions comps)-    liftIO $ logInfo logger $ "Using interface files cache dir: " <> T.pack cacheDir-    pure $ dflags-          & setHiDir cacheDir-          & setDefaultHieDir cacheDir---renderCradleError :: NormalizedFilePath -> CradleError -> FileDiagnostic-renderCradleError nfp (CradleError _ec t) =-  ideErrorText nfp (T.unlines (map T.pack t))---- See Note [Multi Cradle Dependency Info]-type DependencyInfo = Map.Map FilePath (Maybe UTCTime)-type HieMap = Map.Map (Maybe FilePath) (HscEnv, [RawComponentInfo])-type FlagsMap = Map.Map (Maybe FilePath) (HM.HashMap NormalizedFilePath (IdeResult HscEnvEq, DependencyInfo))---- This is pristine information about a component-data RawComponentInfo = RawComponentInfo-  { rawComponentUnitId :: InstalledUnitId-  -- | Unprocessed DynFlags. Contains inplace packages such as libraries.-  -- We do not want to use them unprocessed.-  , rawComponentDynFlags :: DynFlags-  -- | All targets of this components.-  , rawComponentTargets :: [Target]-  -- | Filepath which caused the creation of this component-  , rawComponentFP :: NormalizedFilePath-  -- | Component Options used to load the component.-  , rawComponentCOptions :: ComponentOptions-  -- | Maps cradle dependencies, such as `stack.yaml`, or `.cabal` file-  -- to last modification time. See Note [Multi Cradle Dependency Info].-  , rawComponentDependencyInfo :: DependencyInfo-  }---- This is processed information about the component, in particular the dynflags will be modified.-data ComponentInfo = ComponentInfo-  { componentUnitId :: InstalledUnitId-  -- | Processed DynFlags. Does not contain inplace packages such as local-  -- libraries. Can be used to actually load this Component.-  , componentDynFlags :: DynFlags-  -- | Internal units, such as local libraries, that this component-  -- is loaded with. These have been extracted from the original-  -- ComponentOptions.-  , componentInternalUnits :: [InstalledUnitId]-  -- | All targets of this components.-  , componentTargets :: [Target]-  -- | Filepath which caused the creation of this component-  , componentFP :: NormalizedFilePath-  -- | Component Options used to load the component.-  , componentCOptions :: ComponentOptions-  -- | Maps cradle dependencies, such as `stack.yaml`, or `.cabal` file-  -- to last modification time. See Note [Multi Cradle Dependency Info]-  , componentDependencyInfo :: DependencyInfo-  }---- | Check if any dependency has been modified lately.-checkDependencyInfo :: DependencyInfo -> IO Bool-checkDependencyInfo old_di = do-  di <- getDependencyInfo (Map.keys old_di)-  return (di == old_di)---- Note [Multi Cradle Dependency Info]--- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~--- Why do we implement our own file modification tracking here?--- The primary reason is that the custom caching logic is quite complicated and going into shake--- adds even more complexity and more indirection. I did try for about 5 hours to work out how to--- use shake rules rather than IO but eventually gave up.---- | Computes a mapping from a filepath to its latest modification date.--- See Note [Multi Cradle Dependency Info] why we do this ourselves instead--- of letting shake take care of it.-getDependencyInfo :: [FilePath] -> IO DependencyInfo-getDependencyInfo fs = Map.fromList <$> mapM do_one fs--  where-    tryIO :: IO a -> IO (Either IOException a)-    tryIO = try--    do_one :: FilePath -> IO (FilePath, Maybe UTCTime)-    do_one fp = (fp,) . eitherToMaybe <$> tryIO (getModificationTime fp)---- | This function removes all the -package flags which refer to packages we--- are going to deal with ourselves. For example, if a executable depends--- on a library component, then this function will remove the library flag--- from the package flags for the executable------ There are several places in GHC (for example the call to hptInstances in--- tcRnImports) which assume that all modules in the HPT have the same unit--- ID. Therefore we create a fake one and give them all the same unit id.-removeInplacePackages :: [InstalledUnitId] -> DynFlags -> (DynFlags, [InstalledUnitId])-removeInplacePackages us df = (df { packageFlags = ps-                                  , thisInstalledUnitId = fake_uid }, uids)-  where-    (uids, ps) = partitionEithers (map go (packageFlags df))-    fake_uid = toInstalledUnitId (stringToUnitId "fake_uid")-    go p@(ExposePackage _ (UnitIdArg u) _) = if toInstalledUnitId u `elem` us-                                                  then Left (toInstalledUnitId u)-                                                  else Right p-    go p = Right p---- | Memoize an IO function, with the characteristics:------   * If multiple people ask for a result simultaneously, make sure you only compute it once.------   * If there are exceptions, repeatedly reraise them.------   * If the caller is aborted (async exception) finish computing it anyway.-memoIO :: Ord a => (a -> IO b) -> IO (a -> IO b)-memoIO op = do-    ref <- newVar Map.empty-    return $ \k -> join $ mask_ $ modifyVar ref $ \mp ->-        case Map.lookup k mp of-            Nothing -> do-                res <- onceFork $ op k-                return (Map.insert k res mp, res)-            Just res -> return (mp, res)--setOptions :: GhcMonad m => ComponentOptions -> DynFlags -> m (DynFlags, [Target])-setOptions (ComponentOptions theOpts compRoot _) dflags = do-    (dflags', targets) <- addCmdOpts theOpts dflags-    let dflags'' =-          -- disabled, generated directly by ghcide instead-          flip gopt_unset Opt_WriteInterface $-          -- disabled, generated directly by ghcide instead-          -- also, it can confuse the interface stale check-          dontWriteHieFiles $-          setIgnoreInterfacePragmas $-          setLinkerOptions $-          disableOptimisation $-          makeDynFlagsAbsolute compRoot dflags'-    -- initPackages parses the -package flags and-    -- sets up the visibility for each component.-    (final_df, _) <- liftIO $ initPackages dflags''-    return (final_df, targets)----- we don't want to generate object code so we compile to bytecode--- (HscInterpreted) which implies LinkInMemory--- HscInterpreted-setLinkerOptions :: DynFlags -> DynFlags-setLinkerOptions df = df {-    ghcLink   = LinkInMemory-  , hscTarget = HscNothing-  , ghcMode = CompManager-  }--setIgnoreInterfacePragmas :: DynFlags -> DynFlags-setIgnoreInterfacePragmas df =-    gopt_set (gopt_set df Opt_IgnoreInterfacePragmas) Opt_IgnoreOptimChanges--disableOptimisation :: DynFlags -> DynFlags-disableOptimisation df = updOptLevel 0 df--setHiDir :: FilePath -> DynFlags -> DynFlags-setHiDir f d =-    -- override user settings to avoid conflicts leading to recompilation-    d { hiDir      = Just f}--getCacheDir :: String -> [String] -> IO FilePath-getCacheDir prefix opts = IO.getXdgDirectory IO.XdgCache (cacheDir </> prefix ++ "-" ++ opts_hash)-    where-        -- Create a unique folder per set of different GHC options, assuming that each different set of-        -- GHC options will create incompatible interface files.-        opts_hash = B.unpack $ encode $ H.finalize $ H.updates H.init (map B.pack opts)---- | Sub directory for the cache path-cacheDir :: String-cacheDir = "ghcide"--notifyCradleLoaded :: FilePath -> FromServerMessage-notifyCradleLoaded fp =-    NotCustomServer $-    NotificationMessage "2.0" (CustomServerMethod cradleLoadedMethod) $-    toJSON fp--cradleLoadedMethod :: T.Text-cradleLoadedMethod = "ghcide/cradle/loaded"--ghcVersionChecker :: IO VersionCheck-ghcVersionChecker = $$(makeGhcVersionChecker (pure <$> getLibdir))--checkGhcVersion :: IO (Maybe HscEnvEq)-checkGhcVersion = do-    res <- ghcVersionChecker-    case res of-        Failure err -> do-          putStrLn $ "Error while checking GHC version: " ++ show err-          return Nothing-        Mismatch {..} ->-          return $ Just GhcVersionMismatch {..}-        _ ->-          return Nothing
− exe/Utils.hs
@@ -1,9 +0,0 @@-module Utils (getLibdir) where--import qualified GHC.Paths-import System.Environment-import Data.Maybe---- Set the GHC libdir to the nix libdir if it's present.-getLibdir :: IO FilePath-getLibdir = fromMaybe GHC.Paths.libdir <$> lookupEnv "NIX_GHC_LIBDIR"
ghcide.cabal view
@@ -2,17 +2,17 @@ build-type:         Simple category:           Development name:               ghcide-version:            0.2.0+version:            0.3.0 license:            Apache-2.0 license-file:       LICENSE-author:             Digital Asset-maintainer:         Digital Asset-copyright:          Digital Asset 2018-2020+author:             Digital Asset and Ghcide contributors+maintainer:         Ghcide contributors+copyright:          Digital Asset and Ghcide contributors 2018-2020 synopsis:           The core of an IDE description:     A library for building Haskell IDE's on top of the GHC API.-homepage:           https://github.com/digital-asset/ghcide#readme-bug-reports:        https://github.com/digital-asset/ghcide/issues+homepage:           https://github.com/haskell/ghcide#readme+bug-reports:        https://github.com/haskell/ghcide/issues tested-with:        GHC==8.6.5 extra-source-files: include/ghc-api-version.h README.md CHANGELOG.md                     test/data/hover/*.hs@@ -25,7 +25,7 @@  source-repository head     type:     git-    location: https://github.com/digital-asset/ghcide.git+    location: https://github.com/haskell/ghcide.git  flag ghc-lib   description: build against ghc-lib instead of the ghc package@@ -59,6 +59,7 @@         prettyprinter,         regex-tdfa >= 1.3.1.0,         rope-utf16-splay,+        safe,         safe-exceptions,         shake >= 0.18.4,         sorted-list,@@ -79,7 +80,14 @@       build-depends:         ghc-boot-th,         ghc-boot,-        ghc >= 8.4+        ghc >= 8.4,+        -- These dependencies are used by Development.IDE.Session and are+        -- Haskell specific. So don't use them when building with -fghc-lib!+        ghc-check,+        ghc-paths,+        cryptohash-sha1 >=0.11.100 && <0.12,+        hie-bios == 0.6.*,+        base16-bytestring >=0.1.1 && <0.2     if os(windows)       build-depends:         Win32@@ -119,6 +127,7 @@         Development.IDE.Core.RuleTypes         Development.IDE.Core.Service         Development.IDE.Core.Shake+        Development.IDE.GHC.Compat         Development.IDE.GHC.Error         Development.IDE.GHC.Util         Development.IDE.Import.DependencyInformation@@ -135,11 +144,24 @@         Development.IDE.Plugin         Development.IDE.Plugin.Completions         Development.IDE.Plugin.CodeAction++    -- Unfortunately, we cannot use loadSession with ghc-lib since hie-bios uses+    -- the real GHC library and the types are incompatible. Furthermore, when+    -- building with ghc-lib we need to make this Haskell agnostic, so no+    -- hie-bios!+    -- We also put these modules into a separate hs-source-dirs so we can avoid+    -- compiling them at all if ghc-lib is not set+    if !flag(ghc-lib)+      hs-source-dirs:+        session-loader+      exposed-modules:+        Development.IDE.Session+      other-modules:+        Development.IDE.Session.VersionCheck     other-modules:         Development.IDE.Core.Compile         Development.IDE.Core.Preprocessor         Development.IDE.Core.FileExists-        Development.IDE.GHC.Compat         Development.IDE.GHC.CPP         Development.IDE.GHC.Orphans         Development.IDE.GHC.Warnings@@ -155,15 +177,29 @@         Development.IDE.Plugin.CodeAction.RuleTypes         Development.IDE.Plugin.Completions.Logic         Development.IDE.Plugin.Completions.Types+    if (impl(ghc > 8.5) && impl(ghc < 8.7)) && !flag(ghc-lib)+      hs-source-dirs: src-ghc86+      other-modules:+        Development.IDE.GHC.HieAst+        Development.IDE.GHC.HieBin+        Development.IDE.GHC.HieTypes+        Development.IDE.GHC.HieDebug+        Development.IDE.GHC.HieUtils     if (impl(ghc > 8.7) && impl(ghc < 8.10)) || flag(ghc-lib)       hs-source-dirs: src-ghc88       other-modules:         Development.IDE.GHC.HieAst+        Development.IDE.GHC.HieBin     if (impl(ghc > 8.9))       hs-source-dirs: src-ghc810       other-modules:         Development.IDE.GHC.HieAst+        Development.IDE.GHC.HieBin     ghc-options: -Wall -Wno-name-shadowing+    -- This is needed to prevent a GHC crash when building+    -- Development.IDE.Session with stack on 8.10.1 on Windows+    if (impl(ghc > 8.9) && os(windows))+      ghc-options: -fexternal-interpreter  executable ghcide-test-preprocessor     default-language: Haskell2010@@ -173,6 +209,43 @@     build-depends:         base == 4.* +benchmark benchHist+    type: exitcode-stdio-1.0+    default-language: Haskell2010+    ghc-options: -Wall -Wno-name-shadowing -threaded+    main-is: bench/hist/Main.hs+    build-tool-depends:+        ghcide:ghcide,+        ghcide:ghcide-bench+    default-extensions:+        BangPatterns+        DeriveFunctor+        DeriveGeneric+        GeneralizedNewtypeDeriving+        LambdaCase+        NamedFieldPuns+        OverloadedStrings+        RecordWildCards+        ScopedTypeVariables+        StandaloneDeriving+        TupleSections+        TypeApplications+        ViewPatterns++    build-depends:+        aeson,+        base == 4.*,+        Chart,+        Chart-diagrams,+        diagrams,+        diagrams-svg,+        directory,+        extra >= 1.7.2,+        filepath,+        shake,+        text,+        yaml+ executable ghcide     if flag(ghc-lib)       buildable: False@@ -190,36 +263,21 @@                 "-with-rtsopts=-I0 -qg -A128M"     main-is: Main.hs     build-depends:-        time,-        async,-        hslogger,-        aeson,         base == 4.*,-        binary,-        base16-bytestring >=0.1.1 && <0.2,-        bytestring,-        containers,-        cryptohash-sha1 >=0.11.100 && <0.12,         data-default,-        deepseq,         directory,         extra,         filepath,-        ghc-check >= 0.3.0.1 && < 0.4,-        ghc-paths,-        ghc,         gitrev,         hashable,         haskell-lsp,         haskell-lsp-types,-        hie-bios >= 0.5.0 && < 0.6,+        hie-bios >= 0.6.0 && < 0.7,         ghcide,         optparse-applicative,-        shake,         text,         unordered-containers     other-modules:-        Utils         Arguments         Paths_ghcide @@ -249,6 +307,7 @@     build-depends:         aeson,         base,+        binary,         bytestring,         containers,         directory,@@ -270,10 +329,13 @@         network-uri,         lens,         lsp-test >= 0.11.0.1 && < 0.12,-        parser-combinators,+        optparse-applicative,+        process,         QuickCheck,         quickcheck-instances,         rope-utf16-splay,+        safe,+        safe-exceptions,         shake,         tasty,         tasty-expected-failure,@@ -281,13 +343,52 @@         tasty-quickcheck,         tasty-rerun,         text-    hs-source-dirs: test/cabal test/exe test/src+    hs-source-dirs: test/cabal test/exe test/src bench/lib     include-dirs: include     ghc-options: -threaded -Wall -Wno-name-shadowing     main-is: Main.hs     other-modules:         Development.IDE.Test         Development.IDE.Test.Runfiles+        Experiments+    default-extensions:+        BangPatterns+        DeriveFunctor+        DeriveGeneric+        GeneralizedNewtypeDeriving+        LambdaCase+        NamedFieldPuns+        OverloadedStrings+        RecordWildCards+        ScopedTypeVariables+        StandaloneDeriving+        TupleSections+        TypeApplications+        ViewPatterns++executable ghcide-bench+    default-language: Haskell2010+    build-tool-depends:+        ghcide:ghcide+    build-depends:+        aeson,+        base,+        bytestring,+        containers,+        directory,+        extra,+        filepath,+        ghcide,+        lsp-test >= 0.11.0.2 && < 0.12,+        optparse-applicative,+        process,+        safe-exceptions+    hs-source-dirs: bench/lib bench/exe+    include-dirs: include+    ghc-options: -threaded -Wall -Wno-name-shadowing+    main-is: Main.hs+    other-modules:+        Experiments     default-extensions:         BangPatterns         DeriveFunctor
+ session-loader/Development/IDE/Session.hs view
@@ -0,0 +1,632 @@+{-# LANGUAGE TypeFamilies #-}++{-|+The logic for setting up a ghcide session by tapping into hie-bios.+-}+module Development.IDE.Session (loadSession) where++-- Unfortunately, we cannot use loadSession with ghc-lib since hie-bios uses+-- the real GHC library and the types are incompatible. Furthermore, when+-- building with ghc-lib we need to make this Haskell agnostic, so no hie-bios!++import Control.Concurrent.Async+import Control.Concurrent.Extra+import Control.Exception.Safe+import Control.Monad+import Control.Monad.Extra+import Control.Monad.IO.Class+import qualified Crypto.Hash.SHA1 as H+import qualified Data.ByteString.Char8 as B+import qualified Data.HashMap.Strict as HM+import qualified Data.Map.Strict as Map+import qualified Data.Text as T+import Data.Aeson+import Data.Bifunctor+import qualified Data.ByteString.Base16 as B16+import Data.Either.Extra+import Data.Function+import Data.List+import Data.IORef+import Data.Maybe+import Data.Time.Clock+import Data.Version+import Development.IDE.Core.OfInterest+import Development.IDE.Core.Shake+import Development.IDE.GHC.Util+import Development.IDE.Session.VersionCheck+import Development.IDE.Types.Diagnostics+import Development.IDE.Types.Location+import Development.IDE.Types.Logger+import Development.IDE.Types.Options+import Development.Shake (Action)+import GHC.Check+import HIE.Bios+import HIE.Bios.Environment hiding (getCacheDir)+import HIE.Bios.Types+import Language.Haskell.LSP.Core+import Language.Haskell.LSP.Messages+import Language.Haskell.LSP.Types+import System.Directory+import System.FilePath+import System.Info+import System.IO++import GHC+import DynFlags+import HscTypes+import Linker+import Module+import NameCache+import Packages++-- | Given a root directory, return a Shake 'Action' which setups an+-- 'IdeGhcSession' given a file.+-- Some of the many things this does:+--+-- * Find the cradle for the file+-- * Get the session options,+-- * Get the GHC lib directory+-- * Make sure the GHC compiletime and runtime versions match+-- * Restart the Shake session+--+-- This is the key function which implements multi-component support. All+-- components mapping to the same hie.yaml file are mapped to the same+-- HscEnv which is updated as new components are discovered.+loadSession :: FilePath -> IO (Action IdeGhcSession)+loadSession dir = do+  -- Mapping from hie.yaml file to HscEnv, one per hie.yaml file+  hscEnvs <- newVar Map.empty :: IO (Var HieMap)+  -- Mapping from a Filepath to HscEnv+  fileToFlags <- newVar Map.empty :: IO (Var FlagsMap)+  -- Version of the mappings above+  version <- newVar 0+  let returnWithVersion fun = IdeGhcSession fun <$> liftIO (readVar version)+  let invalidateShakeCache = do+        modifyVar_ version (return . succ)+  -- This caches the mapping from Mod.hs -> hie.yaml+  cradleLoc <- liftIO $ memoIO $ \v -> do+      res <- findCradle v+      -- Sometimes we get C:, sometimes we get c:, and sometimes we get a relative path+      -- try and normalise that+      -- e.g. see https://github.com/digital-asset/ghcide/issues/126+      res' <- traverse makeAbsolute res+      return $ normalise <$> res'++  dummyAs <- async $ return (error "Uninitialised")+  runningCradle <- newVar dummyAs :: IO (Var (Async (IdeResult HscEnvEq,[FilePath])))++  return $ do+    ShakeExtras{logger, eventer, restartShakeSession, withIndefiniteProgress, ideNc} <- getShakeExtras+    IdeOptions{optTesting = IdeTesting optTesting} <- getIdeOptions++    -- Create a new HscEnv from a hieYaml root and a set of options+    -- If the hieYaml file already has an HscEnv, the new component is+    -- combined with the components in the old HscEnv into a new HscEnv+    -- which contains the union.+    let packageSetup :: (Maybe FilePath, NormalizedFilePath, ComponentOptions, FilePath)+                     -> IO (HscEnv, ComponentInfo, [ComponentInfo])+        packageSetup (hieYaml, cfp, opts, libDir) = do+          -- Parse DynFlags for the newly discovered component+          hscEnv <- emptyHscEnv ideNc libDir+          (df, targets) <- evalGhcEnv hscEnv $+              setOptions opts (hsc_dflags hscEnv)+          let deps = componentDependencies opts ++ maybeToList hieYaml+          dep_info <- getDependencyInfo deps+          -- Now lookup to see whether we are combining with an existing HscEnv+          -- or making a new one. The lookup returns the HscEnv and a list of+          -- information about other components loaded into the HscEnv+          -- (unitId, DynFlag, Targets)+          modifyVar hscEnvs $ \m -> do+              -- Just deps if there's already an HscEnv+              -- Nothing is it's the first time we are making an HscEnv+              let oldDeps = Map.lookup hieYaml m+              let -- Add the raw information about this component to the list+                  -- We will modify the unitId and DynFlags used for+                  -- compilation but these are the true source of+                  -- information.+                  new_deps = RawComponentInfo (thisInstalledUnitId df) df targets cfp opts dep_info+                                : maybe [] snd oldDeps+                  -- Get all the unit-ids for things in this component+                  inplace = map rawComponentUnitId new_deps++              new_deps' <- forM new_deps $ \RawComponentInfo{..} -> do+                  -- Remove all inplace dependencies from package flags for+                  -- components in this HscEnv+                  let (df2, uids) = removeInplacePackages inplace rawComponentDynFlags+                  let prefix = show rawComponentUnitId+                  -- See Note [Avoiding bad interface files]+                  processed_df <- setCacheDir logger prefix (sort $ map show uids) opts df2+                  -- The final component information, mostly the same but the DynFlags don't+                  -- contain any packages which are also loaded+                  -- into the same component.+                  pure $ ComponentInfo rawComponentUnitId+                                       processed_df+                                       uids+                                       rawComponentTargets+                                       rawComponentFP+                                       rawComponentCOptions+                                       rawComponentDependencyInfo+              -- Make a new HscEnv, we have to recompile everything from+              -- scratch again (for now)+              -- It's important to keep the same NameCache though for reasons+              -- that I do not fully understand+              logInfo logger (T.pack ("Making new HscEnv" ++ show inplace))+              hscEnv <- emptyHscEnv ideNc libDir+              newHscEnv <-+                -- Add the options for the current component to the HscEnv+                evalGhcEnv hscEnv $ do+                  _ <- setSessionDynFlags df+                  getSession++              -- Modify the map so the hieYaml now maps to the newly created+              -- HscEnv+              -- Returns+              -- . the new HscEnv so it can be used to modify the+              --   FilePath -> HscEnv map (fileToFlags)+              -- . The information for the new component which caused this cache miss+              -- . The modified information (without -inplace flags) for+              --   existing packages+              pure (Map.insert hieYaml (newHscEnv, new_deps) m, (newHscEnv, head new_deps', tail new_deps'))+++    let session :: (Maybe FilePath, NormalizedFilePath, ComponentOptions, FilePath)+                -> IO (IdeResult HscEnvEq,[FilePath])+        session args@(hieYaml, _cfp, _opts, _libDir) = do+          (hscEnv, new, old_deps) <- packageSetup args+          -- Make a map from unit-id to DynFlags, this is used when trying to+          -- resolve imports. (especially PackageImports)+          let uids = map (\ci -> (componentUnitId ci, componentDynFlags ci)) (new : old_deps)++          -- For each component, now make a new HscEnvEq which contains the+          -- HscEnv for the hie.yaml file but the DynFlags for that component++          -- New HscEnv for the component in question, returns the new HscEnvEq and+          -- a mapping from FilePath to the newly created HscEnvEq.+          let new_cache = newComponentCache logger hscEnv uids+          (cs, res) <- new_cache new+          -- Modified cache targets for everything else in the hie.yaml file+          -- which now uses the same EPS and so on+          cached_targets <- concatMapM (fmap fst . new_cache) old_deps+          modifyVar_ fileToFlags $ \var -> do+              pure $ Map.insert hieYaml (HM.fromList (cs ++ cached_targets)) var++          -- Invalidate all the existing GhcSession build nodes by restarting the Shake session+          invalidateShakeCache+          restartShakeSession [kick]++          return (second Map.keys res)++    let consultCradle :: Maybe FilePath -> FilePath -> IO (IdeResult HscEnvEq, [FilePath])+        consultCradle hieYaml cfp = do+           when optTesting $ eventer $ notifyCradleLoaded cfp+           logInfo logger $ T.pack ("Consulting the cradle for " <> show cfp)++           cradle <- maybe (loadImplicitCradle $ addTrailingPathSeparator dir) loadCradle hieYaml+           -- Display a user friendly progress message here: They probably don't know what a+           -- cradle is+           let progMsg = "Setting up project " <> T.pack (takeBaseName (cradleRootDir cradle))++           eopts <- withIndefiniteProgress progMsg NotCancellable $+             cradleToOptsAndLibDir cradle cfp++           logDebug logger $ T.pack ("Session loading result: " <> show eopts)+           case eopts of+             -- The cradle gave us some options so get to work turning them+             -- into and HscEnv.+             Right (opts, libDir) -> do+               installationCheck <- ghcVersionChecker libDir+               case installationCheck of+                 InstallationNotFound{..} ->+                     error $ "GHC installation not found in libdir: " <> libdir+                 InstallationMismatch{..} ->+                     return (([renderPackageSetupException cfp GhcVersionMismatch{..}], Nothing),[])+                 InstallationChecked _compileTime _ghcLibCheck ->+                   session (hieYaml, toNormalizedFilePath' cfp, opts, libDir)+             -- Failure case, either a cradle error or the none cradle+             Left err -> do+               dep_info <- getDependencyInfo (maybeToList hieYaml)+               let ncfp = toNormalizedFilePath' cfp+               let res = (map (renderCradleError ncfp) err, Nothing)+               modifyVar_ fileToFlags $ \var -> do+                 pure $ Map.insertWith HM.union hieYaml (HM.singleton ncfp (res, dep_info)) var+               return (res,[])++    -- This caches the mapping from hie.yaml + Mod.hs -> [String]+    -- Returns the Ghc session and the cradle dependencies+    let sessionOpts :: (Maybe FilePath, FilePath) -> IO (IdeResult HscEnvEq, [FilePath])+        sessionOpts (hieYaml, file) = do+          v <- fromMaybe HM.empty . Map.lookup hieYaml <$> readVar fileToFlags+          cfp <- canonicalizePath file+          case HM.lookup (toNormalizedFilePath' cfp) v of+            Just (opts, old_di) -> do+              deps_ok <- checkDependencyInfo old_di+              if not deps_ok+                then do+                  -- If the dependencies are out of date then clear both caches and start+                  -- again.+                  modifyVar_ fileToFlags (const (return Map.empty))+                  -- Keep the same name cache+                  modifyVar_ hscEnvs (return . Map.adjust (\(h, _) -> (h, [])) hieYaml )+                  consultCradle hieYaml cfp+                else return (opts, Map.keys old_di)+            Nothing -> consultCradle hieYaml cfp++    -- The main function which gets options for a file. We only want one of these running+    -- at a time. Therefore the IORef contains the currently running cradle, if we try+    -- to get some more options then we wait for the currently running action to finish+    -- before attempting to do so.+    let getOptions :: FilePath -> IO (IdeResult HscEnvEq, [FilePath])+        getOptions file = do+            hieYaml <- cradleLoc file+            sessionOpts (hieYaml, file) `catch` \e ->+                return (([renderPackageSetupException file e], Nothing),[])++    returnWithVersion $ \file -> do+      liftIO $ join $ mask_ $ modifyVar runningCradle $ \as -> do+        -- If the cradle is not finished, then wait for it to finish.+        void $ wait as+        as <- async $ getOptions file+        return (as, wait as)++-- | Run the specific cradle on a specific FilePath via hie-bios.+-- This then builds dependencies or whatever based on the cradle, gets the+-- GHC options/dynflags needed for the session and the GHC library directory+cradleToOptsAndLibDir :: Show a => Cradle a -> FilePath+                      -> IO (Either [CradleError] (ComponentOptions, FilePath))+cradleToOptsAndLibDir cradle file = do+    -- Start off by getting the session options+    let showLine s = hPutStrLn stderr ("> " ++ s)+    hPutStrLn stderr $ "Output from setting up the cradle " <> show cradle+    cradleRes <- runCradle (cradleOptsProg cradle) showLine file+    case cradleRes of+        CradleSuccess r -> do+            -- Now get the GHC lib dir+            libDirRes <- getRuntimeGhcLibDir cradle+            case libDirRes of+                -- This is the successful path+                CradleSuccess libDir -> pure (Right (r, libDir))+                CradleFail err -> return (Left [err])+                -- For the None cradle perhaps we still want to report an Info+                -- message about the fact that the file is being ignored.+                CradleNone -> return (Left [])++        CradleFail err -> return (Left [err])+        -- Same here+        CradleNone -> return (Left [])++emptyHscEnv :: IORef NameCache -> FilePath -> IO HscEnv+emptyHscEnv nc libDir = do+    env <- runGhc (Just libDir) getSession+    initDynLinker env+    pure $ setNameCache nc env++-- | Convert a target to a list of potential absolute paths.+-- A TargetModule can be anywhere listed by the supplied include+-- directories+-- A target file is a relative path but with a specific prefix so just need+-- to canonicalise it.+targetToFile :: [FilePath] -> TargetId -> IO [NormalizedFilePath]+targetToFile is (TargetModule mod) = do+    let fps = [i </> moduleNameSlashes mod -<.> ext | ext <- exts, i <- is ]+        exts = ["hs", "hs-boot", "lhs"]+    mapM (fmap toNormalizedFilePath' . canonicalizePath) fps+targetToFile _ (TargetFile f _) = do+  f' <- canonicalizePath f+  return [toNormalizedFilePath' f']++setNameCache :: IORef NameCache -> HscEnv -> HscEnv+setNameCache nc hsc = hsc { hsc_NC = nc }+++-- | Create a mapping from FilePaths to HscEnvEqs+newComponentCache+         :: Logger+         -> HscEnv+         -> [(InstalledUnitId, DynFlags)]+         -> ComponentInfo+         -> IO ([(NormalizedFilePath, (IdeResult HscEnvEq, DependencyInfo))], (IdeResult HscEnvEq, DependencyInfo))+newComponentCache logger hsc_env uids ci = do+    let df = componentDynFlags ci+    let hscEnv' = hsc_env { hsc_dflags = df+                          , hsc_IC = (hsc_IC hsc_env) { ic_dflags = df } }++    henv <- newHscEnvEq hscEnv' uids+    let res = (([], Just henv), componentDependencyInfo ci)+    logDebug logger ("New Component Cache HscEnvEq: " <> T.pack (show res))++    let is = importPaths df+    ctargets <- concatMapM (targetToFile is  . targetId) (componentTargets ci)+    -- A special target for the file which caused this wonderful+    -- component to be created. In case the cradle doesn't list all the targets for+    -- the component, in which case things will be horribly broken anyway.+    -- Otherwise, we will immediately attempt to reload this module which+    -- causes an infinite loop and high CPU usage.+    let special_target = (componentFP ci, res)+    let xs = map (,res) ctargets+    return (special_target:xs, res)++{- Note [Avoiding bad interface files]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+Originally, we set the cache directory for the various components once+on the first occurrence of the component.+This works fine if these components have no references to each other,+but you have components that depend on each other, the interface files are+updated for each component.+After restarting the session and only opening the component that depended+on the other, suddenly the interface files of this component are stale.+However, from the point of view of `ghcide`, they do not look stale,+thus, not regenerated and the IDE shows weird errors such as:+```+typecheckIface+Declaration for Rep_ClientRunFlags+Axiom branches Rep_ClientRunFlags:+  Failed to load interface for ‘Distribution.Simple.Flag’+  Use -v to see a list of the files searched for.+```+and+```+expectJust checkFamInstConsistency+CallStack (from HasCallStack):+  error, called at compiler\\utils\\Maybes.hs:55:27 in ghc:Maybes+  expectJust, called at compiler\\typecheck\\FamInst.hs:461:30 in ghc:FamInst+```++To mitigate this, we set the cache directory for each component dependent+on the components of the current `HscEnv`, additionally to the component options+of the respective components.+Assume two components, c1, c2, where c2 depends on c1, and the options of the+respective components are co1, co2.+If we want to load component c2, followed by c1, we set the cache directory for+each component in this way:++  * Load component c2+    * (Cache Directory State)+        - name of c2 + co2+  * Load component c1+    * (Cache Directory State)+        - name of c2 + name of c1 + co2+        - name of c2 + name of c1 + co1++Overall, we created three cache directories. If we opened c1 first, then we+create a fourth cache directory.+This makes sure that interface files are always correctly updated.++Since this causes a lot of recompilation, we only update the cache-directory,+if the dependencies of a component have really changed.+E.g. when you load two executables, they can not depend on each other. They+should be filtered out, such that we dont have to re-compile everything.+-}++-- | Set the cache-directory based on the ComponentOptions and a list of+-- internal packages.+-- For the exact reason, see Note [Avoiding bad interface files].+setCacheDir :: MonadIO m => Logger -> String -> [String] -> ComponentOptions -> DynFlags -> m DynFlags+setCacheDir logger prefix hscComponents comps dflags = do+    cacheDir <- liftIO $ getCacheDir prefix (hscComponents ++ componentOptions comps)+    liftIO $ logInfo logger $ "Using interface files cache dir: " <> T.pack cacheDir+    pure $ dflags+          & setHiDir cacheDir+          & setHieDir cacheDir+++renderCradleError :: NormalizedFilePath -> CradleError -> FileDiagnostic+renderCradleError nfp (CradleError _ _ec t) =+  ideErrorWithSource (Just "cradle") (Just DsError) nfp (T.unlines (map T.pack t))++-- See Note [Multi Cradle Dependency Info]+type DependencyInfo = Map.Map FilePath (Maybe UTCTime)+type HieMap = Map.Map (Maybe FilePath) (HscEnv, [RawComponentInfo])+type FlagsMap = Map.Map (Maybe FilePath) (HM.HashMap NormalizedFilePath (IdeResult HscEnvEq, DependencyInfo))++-- This is pristine information about a component+data RawComponentInfo = RawComponentInfo+  { rawComponentUnitId :: InstalledUnitId+  -- | Unprocessed DynFlags. Contains inplace packages such as libraries.+  -- We do not want to use them unprocessed.+  , rawComponentDynFlags :: DynFlags+  -- | All targets of this components.+  , rawComponentTargets :: [Target]+  -- | Filepath which caused the creation of this component+  , rawComponentFP :: NormalizedFilePath+  -- | Component Options used to load the component.+  , rawComponentCOptions :: ComponentOptions+  -- | Maps cradle dependencies, such as `stack.yaml`, or `.cabal` file+  -- to last modification time. See Note [Multi Cradle Dependency Info].+  , rawComponentDependencyInfo :: DependencyInfo+  }++-- This is processed information about the component, in particular the dynflags will be modified.+data ComponentInfo = ComponentInfo+  { componentUnitId :: InstalledUnitId+  -- | Processed DynFlags. Does not contain inplace packages such as local+  -- libraries. Can be used to actually load this Component.+  , componentDynFlags :: DynFlags+  -- | Internal units, such as local libraries, that this component+  -- is loaded with. These have been extracted from the original+  -- ComponentOptions.+  , _componentInternalUnits :: [InstalledUnitId]+  -- | All targets of this components.+  , componentTargets :: [Target]+  -- | Filepath which caused the creation of this component+  , componentFP :: NormalizedFilePath+  -- | Component Options used to load the component.+  , _componentCOptions :: ComponentOptions+  -- | Maps cradle dependencies, such as `stack.yaml`, or `.cabal` file+  -- to last modification time. See Note [Multi Cradle Dependency Info]+  , componentDependencyInfo :: DependencyInfo+  }++-- | Check if any dependency has been modified lately.+checkDependencyInfo :: DependencyInfo -> IO Bool+checkDependencyInfo old_di = do+  di <- getDependencyInfo (Map.keys old_di)+  return (di == old_di)++-- Note [Multi Cradle Dependency Info]+-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~+-- Why do we implement our own file modification tracking here?+-- The primary reason is that the custom caching logic is quite complicated and going into shake+-- adds even more complexity and more indirection. I did try for about 5 hours to work out how to+-- use shake rules rather than IO but eventually gave up.++-- | Computes a mapping from a filepath to its latest modification date.+-- See Note [Multi Cradle Dependency Info] why we do this ourselves instead+-- of letting shake take care of it.+getDependencyInfo :: [FilePath] -> IO DependencyInfo+getDependencyInfo fs = Map.fromList <$> mapM do_one fs++  where+    tryIO :: IO a -> IO (Either IOException a)+    tryIO = try++    do_one :: FilePath -> IO (FilePath, Maybe UTCTime)+    do_one fp = (fp,) . eitherToMaybe <$> tryIO (getModificationTime fp)++-- | This function removes all the -package flags which refer to packages we+-- are going to deal with ourselves. For example, if a executable depends+-- on a library component, then this function will remove the library flag+-- from the package flags for the executable+--+-- There are several places in GHC (for example the call to hptInstances in+-- tcRnImports) which assume that all modules in the HPT have the same unit+-- ID. Therefore we create a fake one and give them all the same unit id.+removeInplacePackages :: [InstalledUnitId] -> DynFlags -> (DynFlags, [InstalledUnitId])+removeInplacePackages us df = (df { packageFlags = ps+                                  , thisInstalledUnitId = fake_uid }, uids)+  where+    (uids, ps) = partitionEithers (map go (packageFlags df))+    fake_uid = toInstalledUnitId (stringToUnitId "fake_uid")+    go p@(ExposePackage _ (UnitIdArg u) _) = if toInstalledUnitId u `elem` us+                                                  then Left (toInstalledUnitId u)+                                                  else Right p+    go p = Right p++-- | Memoize an IO function, with the characteristics:+--+--   * If multiple people ask for a result simultaneously, make sure you only compute it once.+--+--   * If there are exceptions, repeatedly reraise them.+--+--   * If the caller is aborted (async exception) finish computing it anyway.+memoIO :: Ord a => (a -> IO b) -> IO (a -> IO b)+memoIO op = do+    ref <- newVar Map.empty+    return $ \k -> join $ mask_ $ modifyVar ref $ \mp ->+        case Map.lookup k mp of+            Nothing -> do+                res <- onceFork $ op k+                return (Map.insert k res mp, res)+            Just res -> return (mp, res)++-- | Throws if package flags are unsatisfiable+setOptions :: GhcMonad m => ComponentOptions -> DynFlags -> m (DynFlags, [Target])+setOptions (ComponentOptions theOpts compRoot _) dflags = do+    (dflags', targets) <- addCmdOpts theOpts dflags+    let dflags'' =+          -- disabled, generated directly by ghcide instead+          flip gopt_unset Opt_WriteInterface $+          -- disabled, generated directly by ghcide instead+          -- also, it can confuse the interface stale check+          dontWriteHieFiles $+          setIgnoreInterfacePragmas $+          setLinkerOptions $+          disableOptimisation $+          makeDynFlagsAbsolute compRoot dflags'+    -- initPackages parses the -package flags and+    -- sets up the visibility for each component.+    -- Throws if a -package flag cannot be satisfied.+    (final_df, _) <- liftIO $ wrapPackageSetupException $ initPackages dflags''+    return (final_df, targets)+++-- we don't want to generate object code so we compile to bytecode+-- (HscInterpreted) which implies LinkInMemory+-- HscInterpreted+setLinkerOptions :: DynFlags -> DynFlags+setLinkerOptions df = df {+    ghcLink   = LinkInMemory+  , hscTarget = HscNothing+  , ghcMode = CompManager+  }++setIgnoreInterfacePragmas :: DynFlags -> DynFlags+setIgnoreInterfacePragmas df =+    gopt_set (gopt_set df Opt_IgnoreInterfacePragmas) Opt_IgnoreOptimChanges++disableOptimisation :: DynFlags -> DynFlags+disableOptimisation df = updOptLevel 0 df++setHiDir :: FilePath -> DynFlags -> DynFlags+setHiDir f d =+    -- override user settings to avoid conflicts leading to recompilation+    d { hiDir      = Just f}++getCacheDir :: String -> [String] -> IO FilePath+getCacheDir prefix opts = getXdgDirectory XdgCache (cacheDir </> prefix ++ "-" ++ opts_hash)+    where+        -- Create a unique folder per set of different GHC options, assuming that each different set of+        -- GHC options will create incompatible interface files.+        opts_hash = B.unpack $ B16.encode $ H.finalize $ H.updates H.init (map B.pack opts)++-- | Sub directory for the cache path+cacheDir :: String+cacheDir = "ghcide"++notifyCradleLoaded :: FilePath -> FromServerMessage+notifyCradleLoaded fp =+    NotCustomServer $+    NotificationMessage "2.0" (CustomServerMethod cradleLoadedMethod) $+    toJSON fp++cradleLoadedMethod :: T.Text+cradleLoadedMethod = "ghcide/cradle/loaded"++----------------------------------------------------------------------------------------------------++data PackageSetupException+    = PackageSetupException+        { message     :: !String+        }+    | GhcVersionMismatch+        { compileTime :: !Version+        , runTime     :: !Version+        }+    | PackageCheckFailed !NotCompatibleReason+    deriving (Eq, Show, Typeable)++instance Exception PackageSetupException++-- | Wrap any exception as a 'PackageSetupException'+wrapPackageSetupException :: IO a -> IO a+wrapPackageSetupException = handleAny $ \case+  e | Just (pkgE :: PackageSetupException) <- fromException e -> throwIO pkgE+  e -> (throwIO . PackageSetupException . show) e++showPackageSetupException :: PackageSetupException -> String+showPackageSetupException GhcVersionMismatch{..} = unwords+    ["ghcide compiled against GHC"+    ,showVersion compileTime+    ,"but currently using"+    ,showVersion runTime+    ,"\nThis is unsupported, ghcide must be compiled with the same GHC version as the project."+    ]+showPackageSetupException PackageSetupException{..} = unwords+    [ "ghcide compiled by GHC", showVersion compilerVersion+    , "failed to load packages:", message <> "."+    , "\nPlease ensure that ghcide is compiled with the same GHC installation as the project."]+showPackageSetupException (PackageCheckFailed PackageVersionMismatch{..}) = unwords+    ["ghcide compiled with package "+    , packageName <> "-" <> showVersion compileTime+    ,"but project uses package"+    , packageName <> "-" <> showVersion runTime+    ,"\nThis is unsupported, ghcide must be compiled with the same GHC installation as the project."+    ]+showPackageSetupException (PackageCheckFailed BasePackageAbiMismatch{..}) = unwords+    ["ghcide compiled with base-" <> showVersion compileTime <> "-" <> compileTimeAbi+    ,"but project uses base-" <> showVersion compileTime <> "-" <> runTimeAbi+    ,"\nThis is unsupported, ghcide must be compiled with the same GHC installation as the project."+    ]++renderPackageSetupException :: FilePath -> PackageSetupException -> (NormalizedFilePath, ShowDiagnostic, Diagnostic)+renderPackageSetupException fp e =+    ideErrorWithSource (Just "cradle") (Just DsError) (toNormalizedFilePath' fp) (T.pack $ showPackageSetupException e)
+ session-loader/Development/IDE/Session/VersionCheck.hs view
@@ -0,0 +1,17 @@+{-# LANGUAGE TemplateHaskell #-}++-- | This module exists to circumvent a compile time exception on Windows with+-- Stack and GHC 8.10.1. It's just been pulled out from Development.IDE.Session.+-- See https://github.com/digital-asset/ghcide/pull/697+module Development.IDE.Session.VersionCheck (ghcVersionChecker) where++import Data.Maybe+import GHC.Check+-- Only use this for checking against the compile time GHC libDir!+-- Use getRuntimeGhcLibDir from hie-bios instead for everything else+-- otherwise binaries will not be distributable since paths will be baked into them+import qualified GHC.Paths+import System.Environment++ghcVersionChecker :: GhcVersionChecker+ghcVersionChecker = $$(makeGhcVersionChecker (fromMaybe GHC.Paths.libdir <$> lookupEnv "NIX_GHC_LIBDIR"))
+ src-ghc810/Development/IDE/GHC/HieBin.hs view
@@ -0,0 +1,399 @@+{-+Binary serialization for .hie files.+-}+{- HLINT ignore -}+{-# LANGUAGE ScopedTypeVariables #-}+module Development.IDE.GHC.HieBin ( readHieFile, readHieFileWithVersion, HieHeader, writeHieFile, HieName(..), toHieName, HieFileResult(..), hieMagic, hieNameOcc,NameCacheUpdater(..)) where++import GHC.Settings               ( maybeRead )++import Config                     ( cProjectVersion )+import Binary+import BinIface                   ( getDictFastString )+import FastMutInt+import FastString                 ( FastString )+import Module                     ( Module )+import Name+import NameCache+import Outputable+import PrelInfo+import SrcLoc+import UniqSupply                 ( takeUniqFromSupply )+import Unique+import UniqFM+import IfaceEnv++import qualified Data.Array as A+import Data.IORef+import Data.ByteString            ( ByteString )+import qualified Data.ByteString  as BS+import qualified Data.ByteString.Char8 as BSC+import Data.List                  ( mapAccumR )+import Data.Word                  ( Word8, Word32 )+import Control.Monad              ( replicateM, when )+import System.Directory           ( createDirectoryIfMissing )+import System.FilePath            ( takeDirectory )++import HieTypes++-- | `Name`'s get converted into `HieName`'s before being written into @.hie@+-- files. See 'toHieName' and 'fromHieName' for logic on how to convert between+-- these two types.+data HieName+  = ExternalName !Module !OccName !SrcSpan+  | LocalName !OccName !SrcSpan+  | KnownKeyName !Unique+  deriving (Eq)++instance Ord HieName where+  compare (ExternalName a b c) (ExternalName d e f) = compare (a,b,c) (d,e,f)+  compare (LocalName a b) (LocalName c d) = compare (a,b) (c,d)+  compare (KnownKeyName a) (KnownKeyName b) = nonDetCmpUnique a b+    -- Not actually non determinstic as it is a KnownKey+  compare ExternalName{} _ = LT+  compare LocalName{} ExternalName{} = GT+  compare LocalName{} _ = LT+  compare KnownKeyName{} _ = GT++instance Outputable HieName where+  ppr (ExternalName m n sp) = text "ExternalName" <+> ppr m <+> ppr n <+> ppr sp+  ppr (LocalName n sp) = text "LocalName" <+> ppr n <+> ppr sp+  ppr (KnownKeyName u) = text "KnownKeyName" <+> ppr u++hieNameOcc :: HieName -> OccName+hieNameOcc (ExternalName _ occ _) = occ+hieNameOcc (LocalName occ _) = occ+hieNameOcc (KnownKeyName u) =+  case lookupKnownKeyName u of+    Just n -> nameOccName n+    Nothing -> pprPanic "hieNameOcc:unknown known-key unique"+                        (ppr (unpkUnique u))+++data HieSymbolTable = HieSymbolTable+  { hie_symtab_next :: !FastMutInt+  , hie_symtab_map  :: !(IORef (UniqFM (Int, HieName)))+  }++data HieDictionary = HieDictionary+  { hie_dict_next :: !FastMutInt -- The next index to use+  , hie_dict_map  :: !(IORef (UniqFM (Int,FastString))) -- indexed by FastString+  }++initBinMemSize :: Int+initBinMemSize = 1024*1024++-- | The header for HIE files - Capital ASCII letters "HIE".+hieMagic :: [Word8]+hieMagic = [72,73,69]++hieMagicLen :: Int+hieMagicLen = length hieMagic++ghcVersion :: ByteString+ghcVersion = BSC.pack cProjectVersion++putBinLine :: BinHandle -> ByteString -> IO ()+putBinLine bh xs = do+  mapM_ (putByte bh) $ BS.unpack xs+  putByte bh 10 -- newline char++-- | Write a `HieFile` to the given `FilePath`, with a proper header and+-- symbol tables for `Name`s and `FastString`s+writeHieFile :: FilePath -> HieFile -> IO ()+writeHieFile hie_file_path hiefile = do+  bh0 <- openBinMem initBinMemSize++  -- Write the header: hieHeader followed by the+  -- hieVersion and the GHC version used to generate this file+  mapM_ (putByte bh0) hieMagic+  putBinLine bh0 $ BSC.pack $ show hieVersion+  putBinLine bh0 $ ghcVersion++  -- remember where the dictionary pointer will go+  dict_p_p <- tellBin bh0+  put_ bh0 dict_p_p++  -- remember where the symbol table pointer will go+  symtab_p_p <- tellBin bh0+  put_ bh0 symtab_p_p++  -- Make some intial state+  symtab_next <- newFastMutInt+  writeFastMutInt symtab_next 0+  symtab_map <- newIORef emptyUFM+  let hie_symtab = HieSymbolTable {+                      hie_symtab_next = symtab_next,+                      hie_symtab_map  = symtab_map }+  dict_next_ref <- newFastMutInt+  writeFastMutInt dict_next_ref 0+  dict_map_ref <- newIORef emptyUFM+  let hie_dict = HieDictionary {+                      hie_dict_next = dict_next_ref,+                      hie_dict_map  = dict_map_ref }++  -- put the main thing+  let bh = setUserData bh0 $ newWriteState (putName hie_symtab)+                                           (putName hie_symtab)+                                           (putFastString hie_dict)+  put_ bh hiefile++  -- write the symtab pointer at the front of the file+  symtab_p <- tellBin bh+  putAt bh symtab_p_p symtab_p+  seekBin bh symtab_p++  -- write the symbol table itself+  symtab_next' <- readFastMutInt symtab_next+  symtab_map'  <- readIORef symtab_map+  putSymbolTable bh symtab_next' symtab_map'++  -- write the dictionary pointer at the front of the file+  dict_p <- tellBin bh+  putAt bh dict_p_p dict_p+  seekBin bh dict_p++  -- write the dictionary itself+  dict_next <- readFastMutInt dict_next_ref+  dict_map  <- readIORef dict_map_ref+  putDictionary bh dict_next dict_map++  -- and send the result to the file+  createDirectoryIfMissing True (takeDirectory hie_file_path)+  writeBinMem bh hie_file_path+  return ()++data HieFileResult+  = HieFileResult+  { hie_file_result_version :: Integer+  , hie_file_result_ghc_version :: ByteString+  , hie_file_result :: HieFile+  }++type HieHeader = (Integer, ByteString)++-- | Read a `HieFile` from a `FilePath`. Can use+-- an existing `NameCache`. Allows you to specify+-- which versions of hieFile to attempt to read.+-- `Left` case returns the failing header versions.+readHieFileWithVersion :: (HieHeader -> Bool) -> NameCacheUpdater -> FilePath -> IO (Either HieHeader HieFileResult)+readHieFileWithVersion readVersion ncu file = do+  bh0 <- readBinMem file++  (hieVersion, ghcVersion) <- readHieFileHeader file bh0++  if readVersion (hieVersion, ghcVersion)+  then do+    hieFile <- readHieFileContents bh0 ncu+    return $ Right (HieFileResult hieVersion ghcVersion hieFile)+  else return $ Left (hieVersion, ghcVersion)+++-- | Read a `HieFile` from a `FilePath`. Can use+-- an existing `NameCache`.+readHieFile :: NameCacheUpdater -> FilePath -> IO HieFileResult+readHieFile ncu file = do++  bh0 <- readBinMem file++  (readHieVersion, ghcVersion) <- readHieFileHeader file bh0++  -- Check if the versions match+  when (readHieVersion /= hieVersion) $+    panic $ unwords ["readHieFile: hie file versions don't match for file:"+                    , file+                    , "Expected"+                    , show hieVersion+                    , "but got", show readHieVersion+                    ]+  hieFile <- readHieFileContents bh0 ncu+  return $ HieFileResult hieVersion ghcVersion hieFile++readBinLine :: BinHandle -> IO ByteString+readBinLine bh = BS.pack . reverse <$> loop []+  where+    loop acc = do+      char <- get bh :: IO Word8+      if char == 10 -- ASCII newline '\n'+      then return acc+      else loop (char : acc)++readHieFileHeader :: FilePath -> BinHandle -> IO HieHeader+readHieFileHeader file bh0 = do+  -- Read the header+  magic <- replicateM hieMagicLen (get bh0)+  version <- BSC.unpack <$> readBinLine bh0+  case maybeRead version of+    Nothing ->+      panic $ unwords ["readHieFileHeader: hieVersion isn't an Integer:"+                      , show version+                      ]+    Just readHieVersion -> do+      ghcVersion <- readBinLine bh0++      -- Check if the header is valid+      when (magic /= hieMagic) $+        panic $ unwords ["readHieFileHeader: headers don't match for file:"+                        , file+                        , "Expected"+                        , show hieMagic+                        , "but got", show magic+                        ]+      return (readHieVersion, ghcVersion)++readHieFileContents :: BinHandle -> NameCacheUpdater -> IO HieFile+readHieFileContents bh0 ncu = do++  dict  <- get_dictionary bh0++  -- read the symbol table so we are capable of reading the actual data+  bh1 <- do+      let bh1 = setUserData bh0 $ newReadState (error "getSymtabName")+                                               (getDictFastString dict)+      symtab <- get_symbol_table bh1+      let bh1' = setUserData bh1+               $ newReadState (getSymTabName symtab)+                              (getDictFastString dict)+      return bh1'++  -- load the actual data+  hiefile <- get bh1+  return hiefile+  where+    get_dictionary bin_handle = do+      dict_p <- get bin_handle+      data_p <- tellBin bin_handle+      seekBin bin_handle dict_p+      dict <- getDictionary bin_handle+      seekBin bin_handle data_p+      return dict++    get_symbol_table bh1 = do+      symtab_p <- get bh1+      data_p'  <- tellBin bh1+      seekBin bh1 symtab_p+      symtab <- getSymbolTable bh1 ncu+      seekBin bh1 data_p'+      return symtab++putFastString :: HieDictionary -> BinHandle -> FastString -> IO ()+putFastString HieDictionary { hie_dict_next = j_r,+                              hie_dict_map  = out_r}  bh f+  = do+    out <- readIORef out_r+    let unique = getUnique f+    case lookupUFM out unique of+        Just (j, _)  -> put_ bh (fromIntegral j :: Word32)+        Nothing -> do+           j <- readFastMutInt j_r+           put_ bh (fromIntegral j :: Word32)+           writeFastMutInt j_r (j + 1)+           writeIORef out_r $! addToUFM out unique (j, f)++putSymbolTable :: BinHandle -> Int -> UniqFM (Int,HieName) -> IO ()+putSymbolTable bh next_off symtab = do+  put_ bh next_off+  let names = A.elems (A.array (0,next_off-1) (nonDetEltsUFM symtab))+  mapM_ (putHieName bh) names++getSymbolTable :: BinHandle -> NameCacheUpdater -> IO SymbolTable+getSymbolTable bh ncu = do+  sz <- get bh+  od_names <- replicateM sz (getHieName bh)+  updateNameCache ncu $ \nc ->+    let arr = A.listArray (0,sz-1) names+        (nc', names) = mapAccumR fromHieName nc od_names+        in (nc',arr)++getSymTabName :: SymbolTable -> BinHandle -> IO Name+getSymTabName st bh = do+  i :: Word32 <- get bh+  return $ st A.! (fromIntegral i)++putName :: HieSymbolTable -> BinHandle -> Name -> IO ()+putName (HieSymbolTable next ref) bh name = do+  symmap <- readIORef ref+  case lookupUFM symmap name of+    Just (off, ExternalName mod occ (UnhelpfulSpan _))+      | isGoodSrcSpan (nameSrcSpan name) -> do+      let hieName = ExternalName mod occ (nameSrcSpan name)+      writeIORef ref $! addToUFM symmap name (off, hieName)+      put_ bh (fromIntegral off :: Word32)+    Just (off, LocalName _occ span)+      | notLocal (toHieName name) || nameSrcSpan name /= span -> do+      writeIORef ref $! addToUFM symmap name (off, toHieName name)+      put_ bh (fromIntegral off :: Word32)+    Just (off, _) -> put_ bh (fromIntegral off :: Word32)+    Nothing -> do+        off <- readFastMutInt next+        writeFastMutInt next (off+1)+        writeIORef ref $! addToUFM symmap name (off, toHieName name)+        put_ bh (fromIntegral off :: Word32)++  where+    notLocal :: HieName -> Bool+    notLocal LocalName{} = False+    notLocal _ = True+++-- ** Converting to and from `HieName`'s++toHieName :: Name -> HieName+toHieName name+  | isKnownKeyName name = KnownKeyName (nameUnique name)+  | isExternalName name = ExternalName (nameModule name)+                                       (nameOccName name)+                                       (nameSrcSpan name)+  | otherwise = LocalName (nameOccName name) (nameSrcSpan name)++fromHieName :: NameCache -> HieName -> (NameCache, Name)+fromHieName nc (ExternalName mod occ span) =+    let cache = nsNames nc+    in case lookupOrigNameCache cache mod occ of+         Just name+           | nameSrcSpan name == span -> (nc, name)+           | otherwise ->+             let name' = setNameLoc name span+                 new_cache = extendNameCache cache mod occ name'+             in ( nc{ nsNames = new_cache }, name' )+         Nothing ->+           let (uniq, us) = takeUniqFromSupply (nsUniqs nc)+               name       = mkExternalName uniq mod occ span+               new_cache  = extendNameCache cache mod occ name+           in ( nc{ nsUniqs = us, nsNames = new_cache }, name )+fromHieName nc (LocalName occ span) =+    let (uniq, us) = takeUniqFromSupply (nsUniqs nc)+        name       = mkInternalName uniq occ span+    in ( nc{ nsUniqs = us }, name )+fromHieName nc (KnownKeyName u) = case lookupKnownKeyName u of+    Nothing -> pprPanic "fromHieName:unknown known-key unique"+                        (ppr (unpkUnique u))+    Just n -> (nc, n)++-- ** Reading and writing `HieName`'s++putHieName :: BinHandle -> HieName -> IO ()+putHieName bh (ExternalName mod occ span) = do+  putByte bh 0+  put_ bh (mod, occ, span)+putHieName bh (LocalName occName span) = do+  putByte bh 1+  put_ bh (occName, span)+putHieName bh (KnownKeyName uniq) = do+  putByte bh 2+  put_ bh $ unpkUnique uniq++getHieName :: BinHandle -> IO HieName+getHieName bh = do+  t <- getByte bh+  case t of+    0 -> do+      (modu, occ, span) <- get bh+      return $ ExternalName modu occ span+    1 -> do+      (occ, span) <- get bh+      return $ LocalName occ span+    2 -> do+      (c,i) <- get bh+      return $ KnownKeyName $ mkUnique c i+    _ -> panic "HieBin.getHieName: invalid tag"
+ src-ghc86/Development/IDE/GHC/HieAst.hs view
@@ -0,0 +1,1784 @@++{-+Forked from GHC v8.8.1 to work around the readFile side effect in mkHiefile++Main functions for .hie file generation+-}+{- HLINT ignore -}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE UndecidableInstances #-}+{-# LANGUAGE FlexibleContexts #-}+{-# LANGUAGE TypeSynonymInstances #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TypeFamilies #-}+{-# LANGUAGE TypeApplications #-}+{-# LANGUAGE AllowAmbiguousTypes #-}+{-# LANGUAGE ViewPatterns #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE DataKinds #-}+module Development.IDE.GHC.HieAst ( mkHieFile ) where++import Avail                      ( Avails )+import Bag                        ( Bag, bagToList )+import BasicTypes+import BooleanFormula+import Class                      ( FunDep )+import CoreUtils                  ( exprType )+import ConLike                    ( conLikeName )+import Desugar                    ( deSugarExpr )+import FieldLabel+import HsSyn+import HscTypes+import Module                     ( ModuleName, ml_hs_file )+import MonadUtils                 ( concatMapM, liftIO )+import Name                       ( Name, nameSrcSpan, setNameLoc )+import SrcLoc+import TcHsSyn                    ( hsLitType, hsPatType )+import Type                       ( mkFunTys, Type )+import TysWiredIn                 ( mkListTy, mkSumTy )+import Var                        ( Id, Var, setVarName, varName, varType )+import TcRnTypes+import MkIface                    ( mkIfaceExports )++import Development.IDE.GHC.HieTypes+import Development.IDE.GHC.HieUtils++import qualified Data.Array as A+import qualified Data.ByteString as BS+import qualified Data.Map as M+import qualified Data.Set as S+import Data.Data                  ( Data, Typeable )+import Data.List                  (foldl',  foldl1' )+import Control.Monad.Trans.Reader+import Control.Monad.Trans.Class  ( lift )++-- These synonyms match those defined in main/GHC.hs+type RenamedSource     = ( HsGroup GhcRn, [LImportDecl GhcRn]+                         , Maybe [(LIE GhcRn, Avails)]+                         , Maybe LHsDocString )+type TypecheckedSource = LHsBinds GhcTc++-- | Marks that a field uses the GhcRn variant even when the pass+-- parameter is GhcTc. Useful for storing HsTypes in HsExprs, say, because+-- HsType GhcTc should never occur.+type family NoGhcTc (p :: *) where+    -- this way, GHC can figure out that the result is a GhcPass+  NoGhcTc (GhcPass pass) = GhcPass (NoGhcTcPass pass)+  NoGhcTc other          = other++type family NoGhcTcPass (p :: Pass) :: Pass where+  NoGhcTcPass 'Typechecked = 'Renamed+  NoGhcTcPass other        = other++{- Note [Name Remapping]+The Typechecker introduces new names for mono names in AbsBinds.+We don't care about the distinction between mono and poly bindings,+so we replace all occurrences of the mono name with the poly name.+-}+newtype HieState = HieState+  { name_remapping :: M.Map Name Id+  }++initState :: HieState+initState = HieState M.empty++class ModifyState a where -- See Note [Name Remapping]+  addSubstitution :: a -> a -> HieState -> HieState++instance ModifyState Name where+  addSubstitution _ _ hs = hs++instance ModifyState Id where+  addSubstitution mono poly hs =+    hs{name_remapping = M.insert (varName mono) poly (name_remapping hs)}++modifyState :: ModifyState (IdP p) => [ABExport p] -> HieState -> HieState+modifyState = foldr go id+  where+    go ABE{abe_poly=poly,abe_mono=mono} f = addSubstitution mono poly . f+    go _ f = f++type HieM = ReaderT HieState Hsc++-- | Construct an 'HieFile' from the outputs of the typechecker.+mkHieFile :: ModSummary+          -> TcGblEnv+          -> RenamedSource+          -> BS.ByteString+          -> Hsc HieFile+mkHieFile ms ts rs src = do+  let tc_binds = tcg_binds ts+  (asts', arr) <- getCompressedAsts tc_binds rs+  let Just src_file = ml_hs_file $ ms_location ms+  return $ HieFile+      { hie_hs_file = src_file+      , hie_module = ms_mod ms+      , hie_types = arr+      , hie_asts = asts'+      -- mkIfaceExports sorts the AvailInfos for stability+      , hie_exports = mkIfaceExports (tcg_exports ts)+      , hie_hs_src = src+      }++getCompressedAsts :: TypecheckedSource -> RenamedSource+  -> Hsc (HieASTs TypeIndex, A.Array TypeIndex HieTypeFlat)+getCompressedAsts ts rs = do+  asts <- enrichHie ts rs+  return $ compressTypes asts++enrichHie :: TypecheckedSource -> RenamedSource -> Hsc (HieASTs Type)+enrichHie ts (hsGrp, imports, exports, _) = flip runReaderT initState $ do+    tasts <- toHie $ fmap (BC RegularBind ModuleScope) ts+    rasts <- processGrp hsGrp+    imps <- toHie $ filter (not . ideclImplicit . unLoc) imports+    exps <- toHie $ fmap (map $ IEC Export . fst) exports+    let spanFile children = case children of+          [] -> mkRealSrcSpan (mkRealSrcLoc "" 1 1) (mkRealSrcLoc "" 1 1)+          _ -> mkRealSrcSpan (realSrcSpanStart $ nodeSpan $ head children)+                             (realSrcSpanEnd   $ nodeSpan $ last children)++        modulify xs =+          Node (simpleNodeInfo "Module" "Module") (spanFile xs) xs++        asts = HieASTs+          $ resolveTyVarScopes+          $ M.map (modulify . mergeSortAsts)+          $ M.fromListWith (++)+          $ map (\x -> (srcSpanFile (nodeSpan x),[x])) flat_asts++        flat_asts = concat+          [ tasts+          , rasts+          , imps+          , exps+          ]+    return asts+  where+    processGrp grp = concatM+      [ toHie $ fmap (RS ModuleScope ) hs_valds grp+      , toHie $ hs_splcds grp+      , toHie $ hs_tyclds grp+      , toHie $ hs_derivds grp+      , toHie $ hs_fixds grp+      , toHie $ hs_defds grp+      , toHie $ hs_fords grp+      , toHie $ hs_warnds grp+      , toHie $ hs_annds grp+      , toHie $ hs_ruleds grp+      ]++getRealSpan :: SrcSpan -> Maybe Span+getRealSpan (RealSrcSpan sp) = Just sp+getRealSpan _ = Nothing++grhss_span :: GRHSs p body -> SrcSpan+grhss_span (GRHSs _ xs bs) = foldl' combineSrcSpans (getLoc bs) (map getLoc xs)+grhss_span (XGRHSs _) = error "XGRHS has no span"++bindingsOnly :: [Context Name] -> [HieAST a]+bindingsOnly [] = []+bindingsOnly (C c n : xs) = case nameSrcSpan n of+  RealSrcSpan span -> Node nodeinfo span [] : bindingsOnly xs+    where nodeinfo = NodeInfo S.empty [] (M.singleton (Right n) info)+          info = mempty{identInfo = S.singleton c}+  _ -> bindingsOnly xs++concatM :: Monad m => [m [a]] -> m [a]+concatM xs = concat <$> sequence xs++{- Note [Capturing Scopes and other non local information]+toHie is a local tranformation, but scopes of bindings cannot be known locally,+hence we have to push the relevant info down into the binding nodes.+We use the following types (*Context and *Scoped) to wrap things and+carry the required info+(Maybe Span) always carries the span of the entire binding, including rhs+-}+data Context a = C ContextInfo a -- Used for names and bindings++data RContext a = RC RecFieldContext a+data RFContext a = RFC RecFieldContext (Maybe Span) a+-- ^ context for record fields++data IEContext a = IEC IEType a+-- ^ context for imports/exports++data BindContext a = BC BindType Scope a+-- ^ context for imports/exports++data PatSynFieldContext a = PSC (Maybe Span) a+-- ^ context for pattern synonym fields.++data SigContext a = SC SigInfo a+-- ^ context for type signatures++data SigInfo = SI SigType (Maybe Span)++data SigType = BindSig | ClassSig | InstSig++data RScoped a = RS Scope a+-- ^ Scope spans over everything to the right of a, (mostly) not+-- including a itself+-- (Includes a in a few special cases like recursive do bindings) or+-- let/where bindings++-- | Pattern scope+data PScoped a = PS (Maybe Span)+                    Scope       -- ^ use site of the pattern+                    Scope       -- ^ pattern to the right of a, not including a+                    a+  deriving (Typeable, Data) -- Pattern Scope++{- Note [TyVar Scopes]+Due to -XScopedTypeVariables, type variables can be in scope quite far from+their original binding. We resolve the scope of these type variables+in a separate pass+-}+data TScoped a = TS TyVarScope a -- TyVarScope++data TVScoped a = TVS TyVarScope Scope a -- TyVarScope+-- ^ First scope remains constant+-- Second scope is used to build up the scope of a tyvar over+-- things to its right, ala RScoped++-- | Each element scopes over the elements to the right+listScopes :: Scope -> [Located a] -> [RScoped (Located a)]+listScopes _ [] = []+listScopes rhsScope [pat] = [RS rhsScope pat]+listScopes rhsScope (pat : pats) = RS sc pat : pats'+  where+    pats'@((RS scope p):_) = listScopes rhsScope pats+    sc = combineScopes scope $ mkScope $ getLoc p++-- | 'listScopes' specialised to 'PScoped' things+patScopes+  :: Maybe Span+  -> Scope+  -> Scope+  -> [LPat (GhcPass p)]+  -> [PScoped (LPat (GhcPass p))]+patScopes rsp useScope patScope xs =+  map (\(RS sc a) -> PS rsp useScope sc a) $+    listScopes patScope xs++-- | 'listScopes' specialised to 'TVScoped' things+tvScopes+  :: TyVarScope+  -> Scope+  -> [LHsTyVarBndr a]+  -> [TVScoped (LHsTyVarBndr a)]+tvScopes tvScope rhsScope xs =+  map (\(RS sc a)-> TVS tvScope sc a) $ listScopes rhsScope xs++{- Note [Scoping Rules for SigPat]+Explicitly quantified variables in pattern type signatures are not+brought into scope in the rhs, but implicitly quantified variables+are (HsWC and HsIB).+This is unlike other signatures, where explicitly quantified variables+are brought into the RHS Scope+For example+foo :: forall a. ...;+foo = ... -- a is in scope here++bar (x :: forall a. a -> a) = ... -- a is not in scope here+--   ^ a is in scope here (pattern body)++bax (x :: a) = ... -- a is in scope here+Because of HsWC and HsIB pass on their scope to their children+we must wrap the LHsType in pattern signatures in a+Shielded explictly, so that the HsWC/HsIB scope is not passed+on the the LHsType+-}++data Shielded a = SH Scope a -- Ignores its TScope, uses its own scope instead++type family ProtectedSig a where+  ProtectedSig GhcRn = HsWildCardBndrs GhcRn (HsImplicitBndrs+                                                GhcRn+                                                (Shielded (LHsType GhcRn)))+  ProtectedSig GhcTc = NoExt++class ProtectSig a where+  protectSig :: Scope -> XSigPat a -> ProtectedSig a++instance (HasLoc a) => HasLoc (Shielded a) where+  loc (SH _ a) = loc a++instance (ToHie (TScoped a)) => ToHie (TScoped (Shielded a)) where+  toHie (TS _ (SH sc a)) = toHie (TS (ResolvedScopes [sc]) a)++instance ProtectSig GhcTc where+  protectSig _ _ = NoExt++instance ProtectSig GhcRn where+  protectSig sc (HsWC a (HsIB b sig)) =+    HsWC a (HsIB b (SH sc sig))+  protectSig _ _ = error "protectSig not given HsWC (HsIB)"++class HasLoc a where+  -- ^ defined so that HsImplicitBndrs and HsWildCardBndrs can+  -- know what their implicit bindings are scoping over+  loc :: a -> SrcSpan++instance HasLoc thing => HasLoc (TScoped thing) where+  loc (TS _ a) = loc a++instance HasLoc thing => HasLoc (PScoped thing) where+  loc (PS _ _ _ a) = loc a++instance HasLoc (LHsQTyVars GhcRn) where+  loc (HsQTvs _ vs) = loc vs+  loc _ = noSrcSpan++instance HasLoc thing => HasLoc (HsImplicitBndrs a thing) where+  loc (HsIB _ a) = loc a+  loc _ = noSrcSpan++instance HasLoc thing => HasLoc (HsWildCardBndrs a thing) where+  loc (HsWC _ a) = loc a+  loc _ = noSrcSpan++instance HasLoc (Located a) where+  loc (L l _) = l++instance HasLoc a => HasLoc [a] where+  loc [] = noSrcSpan+  loc xs = foldl1' combineSrcSpans $ map loc xs++instance (HasLoc a, HasLoc b) => HasLoc (FamEqn s a b) where+  loc (FamEqn _ a b _ c) = foldl1' combineSrcSpans [loc a, loc b, loc c]+  loc _ = noSrcSpan+{-+instance (HasLoc tm, HasLoc ty) => HasLoc (HsArg tm ty) where+  loc (HsValArg tm) = loc tm+  loc (HsTypeArg _ ty) = loc ty+  loc (HsArgPar sp)  = sp+-}++instance HasLoc (HsDataDefn GhcRn) where+  loc def@(HsDataDefn{}) = loc $ dd_cons def+    -- Only used for data family instances, so we only need rhs+    -- Most probably the rest will be unhelpful anyway+  loc _ = noSrcSpan++-- | The main worker class+class ToHie a where+  toHie :: a -> HieM [HieAST Type]++-- | Used to collect type info+class Data a => HasType a where+  getTypeNode :: a -> HieM [HieAST Type]++instance (ToHie a) => ToHie [a] where+  toHie = concatMapM toHie++instance (ToHie a) => ToHie (Bag a) where+  toHie = toHie . bagToList++instance (ToHie a) => ToHie (Maybe a) where+  toHie = maybe (pure []) toHie++instance ToHie (Context (Located NoExt)) where+  toHie _ = pure []++instance ToHie (TScoped NoExt) where+  toHie _ = pure []++instance ToHie (IEContext (Located ModuleName)) where+  toHie (IEC c (L (RealSrcSpan span) mname)) =+      pure $ [Node (NodeInfo S.empty [] idents) span []]+    where details = mempty{identInfo = S.singleton (IEThing c)}+          idents = M.singleton (Left mname) details+  toHie _ = pure []++instance ToHie (Context (Located Var)) where+  toHie c = case c of+      C context (L (RealSrcSpan span) name')+        -> do+        m <- asks name_remapping+        let name = M.findWithDefault name' (varName name') m+        pure+          [Node+            (NodeInfo S.empty [] $+              M.singleton (Right $ varName name)+                          (IdentifierDetails (Just $ varType name')+                                             (S.singleton context)))+            span+            []]+      _ -> pure []++instance ToHie (Context (Located Name)) where+  toHie c = case c of+      C context (L (RealSrcSpan span) name') -> do+        m <- asks name_remapping+        let name = case M.lookup name' m of+              Just var -> varName var+              Nothing -> name'+        pure+          [Node+            (NodeInfo S.empty [] $+              M.singleton (Right name)+                          (IdentifierDetails Nothing+                                             (S.singleton context)))+            span+            []]+      _ -> pure []++-- | Dummy instances - never called+instance ToHie (TScoped (LHsSigWcType GhcTc)) where+  toHie _ = pure []+instance ToHie (TScoped (LHsWcType GhcTc)) where+  toHie _ = pure []+instance ToHie (SigContext (LSig GhcTc)) where+  toHie _ = pure []+instance ToHie (TScoped Type) where+  toHie _ = pure []++instance HasType (LHsBind GhcRn) where+  getTypeNode (L spn bind) = makeNode bind spn++instance HasType (LHsBind GhcTc) where+  getTypeNode (L spn bind) = case bind of+      FunBind{fun_id = name} -> makeTypeNode bind spn (varType $ unLoc name)+      _ -> makeNode bind spn++instance HasType (LPat GhcRn) where+  getTypeNode (L spn pat) = makeNode pat spn++instance HasType (LPat GhcTc) where+  getTypeNode (L spn opat) = makeTypeNode opat spn (hsPatType opat)++instance HasType (LHsExpr GhcRn) where+  getTypeNode (L spn e) = makeNode e spn++-- | This instance tries to construct 'HieAST' nodes which include the type of+-- the expression. It is not yet possible to do this efficiently for all+-- expression forms, so we skip filling in the type for those inputs.+--+-- 'HsApp', for example, doesn't have any type information available directly on+-- the node. Our next recourse would be to desugar it into a 'CoreExpr' then+-- query the type of that. Yet both the desugaring call and the type query both+-- involve recursive calls to the function and argument! This is particularly+-- problematic when you realize that the HIE traversal will eventually visit+-- those nodes too and ask for their types again.+--+-- Since the above is quite costly, we just skip cases where computing the+-- expression's type is going to be expensive.+--+-- See #16233+instance HasType (LHsExpr GhcTc) where+  getTypeNode e@(L spn e') = lift $+    -- Some expression forms have their type immediately available+    let tyOpt = case e' of+          HsLit _ l -> Just (hsLitType l)+          HsOverLit _ o -> Just (overLitType o)++          HsLam     _ (MG { mg_ext = groupTy }) -> Just (matchGroupType groupTy)+          HsLamCase _ (MG { mg_ext = groupTy }) -> Just (matchGroupType groupTy)+          HsCase _  _ (MG { mg_ext = groupTy }) -> Just (mg_res_ty groupTy)++          ExplicitList  ty _ _   -> Just (mkListTy ty)+          ExplicitSum   ty _ _ _ -> Just (mkSumTy ty)+          HsDo          ty _ _   -> Just ty+          HsMultiIf     ty _     -> Just ty++          _ -> Nothing++    in+    case tyOpt of+      _ | skipDesugaring e' -> fallback+        | otherwise -> do+            hs_env <- Hsc $ \e w -> return (e,w)+            (_,mbe) <- liftIO $ deSugarExpr hs_env e+            maybe fallback (makeTypeNode e' spn . exprType) mbe+    where+      fallback = makeNode e' spn++      matchGroupType :: MatchGroupTc -> Type+      matchGroupType (MatchGroupTc args res) = mkFunTys args res++      -- | Skip desugaring of these expressions for performance reasons.+      --+      -- See impact on Haddock output (esp. missing type annotations or links)+      -- before marking more things here as 'False'. See impact on Haddock+      -- performance before marking more things as 'True'.+      skipDesugaring :: HsExpr a -> Bool+      skipDesugaring e = case e of+        HsVar{}        -> False+        HsUnboundVar{} -> False+        HsConLikeOut{} -> False+        HsRecFld{}     -> False+        HsOverLabel{}  -> False+        HsIPVar{}      -> False+        HsWrap{}       -> False+        _              -> True++instance ( ToHie (Context (Located (IdP a)))+         , ToHie (MatchGroup a (LHsExpr a))+         , ToHie (PScoped (LPat a))+         , ToHie (GRHSs a (LHsExpr a))+         , ToHie (LHsExpr a)+         , ToHie (Located (PatSynBind a a))+         , HasType (LHsBind a)+         , ModifyState (IdP a)+         , Data (HsBind a)+         ) => ToHie (BindContext (LHsBind a)) where+  toHie (BC context scope b@(L span bind)) =+    concatM $ getTypeNode b : case bind of+      FunBind{fun_id = name, fun_matches = matches} ->+        [ toHie $ C (ValBind context scope $ getRealSpan span) name+        , toHie matches+        ]+      PatBind{pat_lhs = lhs, pat_rhs = rhs} ->+        [ toHie $ PS (getRealSpan span) scope NoScope lhs+        , toHie rhs+        ]+      VarBind{var_rhs = expr} ->+        [ toHie expr+        ]+      AbsBinds{abs_exports = xs, abs_binds = binds} ->+        [ local (modifyState xs) $ -- Note [Name Remapping]+            toHie $ fmap (BC context scope) binds+        ]+      PatSynBind _ psb ->+        [ toHie $ L span psb -- PatSynBinds only occur at the top level+        ]+      XHsBindsLR _ -> []++instance ( ToHie (LMatch a body)+         ) => ToHie (MatchGroup a body) where+  toHie mg = concatM $ case mg of+    MG{ mg_alts = (L span alts) , mg_origin = FromSource } ->+      [ pure $ locOnly span+      , toHie alts+      ]+    MG{} -> []+    XMatchGroup _ -> []++instance ( ToHie (Context (Located (IdP a)))+         , ToHie (PScoped (LPat a))+         , ToHie (HsPatSynDir a)+         ) => ToHie (Located (PatSynBind a a)) where+    toHie (L sp psb) = concatM $ case psb of+      PSB{psb_id=var, psb_args=dets, psb_def=pat, psb_dir=dir} ->+        [ toHie $ C (Decl PatSynDec $ getRealSpan sp) var+        , toHie $ toBind dets+        , toHie $ PS Nothing lhsScope NoScope pat+        , toHie dir+        ]+        where+          lhsScope = combineScopes varScope detScope+          varScope = mkLScope var+          detScope = case dets of+            (PrefixCon args) -> foldr combineScopes NoScope $ map mkLScope args+            (InfixCon a b) -> combineScopes (mkLScope a) (mkLScope b)+            (RecCon r) -> foldr go NoScope r+          go (RecordPatSynField a b) c = combineScopes c+            $ combineScopes (mkLScope a) (mkLScope b)+          detSpan = case detScope of+            LocalScope a -> Just a+            _ -> Nothing+          toBind (PrefixCon args) = PrefixCon $ map (C Use) args+          toBind (InfixCon a b) = InfixCon (C Use a) (C Use b)+          toBind (RecCon r) = RecCon $ map (PSC detSpan) r+      XPatSynBind _ -> []++instance ( ToHie (MatchGroup a (LHsExpr a))+         ) => ToHie (HsPatSynDir a) where+  toHie dir = case dir of+    ExplicitBidirectional mg -> toHie mg+    _ -> pure []++instance ( a ~ GhcPass p+         , ToHie body+         , ToHie (HsMatchContext (NameOrRdrName (IdP a)))+         , ToHie (PScoped (LPat a))+         , ToHie (GRHSs a body)+         , Data (Match a body)+         ) => ToHie (LMatch (GhcPass p) body) where+  toHie (L span m ) = concatM $ makeNode m span : case m of+    Match{m_ctxt=mctx, m_pats = pats, m_grhss =  grhss } ->+      [ toHie mctx+      , let rhsScope = mkScope $ grhss_span grhss+          in toHie $ patScopes Nothing rhsScope NoScope pats+      , toHie grhss+      ]+    XMatch _ -> []++instance ( ToHie (Context (Located a))+         ) => ToHie (HsMatchContext a) where+  toHie (FunRhs{mc_fun=name}) = toHie $ C MatchBind name+  toHie (StmtCtxt a) = toHie a+  toHie _ = pure []++instance ( ToHie (HsMatchContext a)+         ) => ToHie (HsStmtContext a) where+  toHie (PatGuard a) = toHie a+  toHie (ParStmtCtxt a) = toHie a+  toHie (TransStmtCtxt a) = toHie a+  toHie _ = pure []++instance ( a ~ GhcPass p+         , ToHie (Context (Located (IdP a)))+         , ToHie (RContext (HsRecFields a (PScoped (LPat a))))+         , ToHie (LHsExpr a)+         , ToHie (TScoped (LHsSigWcType a))+         , ProtectSig a+         , ToHie (TScoped (ProtectedSig a))+         , HasType (LPat a)+         , Data (HsSplice a)+         ) => ToHie (PScoped (LPat (GhcPass p))) where+  toHie (PS rsp scope pscope lpat@(L ospan opat)) =+    concatM $ getTypeNode lpat : case opat of+      WildPat _ ->+        []+      VarPat _ lname ->+        [ toHie $ C (PatternBind scope pscope rsp) lname+        ]+      LazyPat _ p ->+        [ toHie $ PS rsp scope pscope p+        ]+      AsPat _ lname pat ->+        [ toHie $ C (PatternBind scope+                                 (combineScopes (mkLScope pat) pscope)+                                 rsp)+                    lname+        , toHie $ PS rsp scope pscope pat+        ]+      ParPat _ pat ->+        [ toHie $ PS rsp scope pscope pat+        ]+      BangPat _ pat ->+        [ toHie $ PS rsp scope pscope pat+        ]+      ListPat _ pats ->+        [ toHie $ patScopes rsp scope pscope pats+        ]+      TuplePat _ pats _ ->+        [ toHie $ patScopes rsp scope pscope pats+        ]+      SumPat _ pat _ _ ->+        [ toHie $ PS rsp scope pscope pat+        ]+      ConPatIn c dets ->+        [ toHie $ C Use c+        , toHie $ contextify dets+        ]+      ConPatOut {pat_con = con, pat_args = dets}->+        [ toHie $ C Use $ fmap conLikeName con+        , toHie $ contextify dets+        ]+      ViewPat _ expr pat ->+        [ toHie expr+        , toHie $ PS rsp scope pscope pat+        ]+      SplicePat _ sp ->+        [ toHie $ L ospan sp+        ]+      LitPat _ _ ->+        []+      NPat _ _ _ _ ->+        []+      NPlusKPat _ n _ _ _ _ ->+        [ toHie $ C (PatternBind scope pscope rsp) n+        ]+      SigPat sig pat ->+        [ toHie $ PS rsp scope pscope pat+        , let cscope = mkLScope pat in+            toHie $ TS (ResolvedScopes [cscope, scope, pscope])+                       (protectSig @a cscope sig)+              -- See Note [Scoping Rules for SigPat]+        ]+      CoPat _ _ _ _ ->+        []+      XPat _ -> []+    where+      contextify (PrefixCon args) = PrefixCon $ patScopes rsp scope pscope args+      contextify (InfixCon a b) = InfixCon a' b'+        where [a', b'] = patScopes rsp scope pscope [a,b]+      contextify (RecCon r) = RecCon $ RC RecFieldMatch $ contextify_rec r+      contextify_rec (HsRecFields fds a) = HsRecFields (map go scoped_fds) a+        where+          go (RS fscope (L spn (HsRecField lbl pat pun))) =+            L spn $ HsRecField lbl (PS rsp scope fscope pat) pun+          scoped_fds = listScopes pscope fds++instance ( ToHie body+         , ToHie (LGRHS a body)+         , ToHie (RScoped (LHsLocalBinds a))+         ) => ToHie (GRHSs a body) where+  toHie grhs = concatM $ case grhs of+    GRHSs _ grhss binds ->+     [ toHie grhss+     , toHie $ RS (mkScope $ grhss_span grhs) binds+     ]+    XGRHSs _ -> []++instance ( ToHie (Located body)+         , ToHie (RScoped (GuardLStmt a))+         , Data (GRHS a (Located body))+         ) => ToHie (LGRHS a (Located body)) where+  toHie (L span g) = concatM $ makeNode g span : case g of+    GRHS _ guards body ->+      [ toHie $ listScopes (mkLScope body) guards+      , toHie body+      ]+    XGRHS _ -> []++instance ( a ~ GhcPass p+         , ToHie (Context (Located (IdP a)))+         , HasType (LHsExpr a)+         , ToHie (PScoped (LPat a))+         , ToHie (MatchGroup a (LHsExpr a))+         , ToHie (LGRHS a (LHsExpr a))+         , ToHie (RContext (HsRecordBinds a))+         , ToHie (RFContext (Located (AmbiguousFieldOcc a)))+         , ToHie (ArithSeqInfo a)+         , ToHie (LHsCmdTop a)+         , ToHie (RScoped (GuardLStmt a))+         , ToHie (RScoped (LHsLocalBinds a))+         , ToHie (TScoped (LHsWcType (NoGhcTc a)))+         , ToHie (TScoped (LHsSigWcType (NoGhcTc a)))+         , Data (HsExpr a)+         , Data (HsSplice a)+         , Data (HsTupArg a)+         , Data (AmbiguousFieldOcc a)+         ) => ToHie (LHsExpr (GhcPass p)) where+  toHie e@(L mspan oexpr) = concatM $ getTypeNode e : case oexpr of+      HsVar _ (L _ var) ->+        [ toHie $ C Use (L mspan var)+             -- Patch up var location since typechecker removes it+        ]+      HsUnboundVar _ _ ->+        []+      HsConLikeOut _ con ->+        [ toHie $ C Use $ L mspan $ conLikeName con+        ]+      HsRecFld _ fld ->+        [ toHie $ RFC RecFieldOcc Nothing (L mspan fld)+        ]+      HsOverLabel _ _ _ -> []+      HsIPVar _ _ -> []+      HsOverLit _ _ -> []+      HsLit _ _ -> []+      HsLam _ mg ->+        [ toHie mg+        ]+      HsLamCase _ mg ->+        [ toHie mg+        ]+      HsApp _ a b ->+        [ toHie a+        , toHie b+        ]+      HsAppType _sig expr ->+        [ toHie expr+        -- , toHie $ TS (ResolvedScopes []) sig+        ]+      OpApp _ a b c ->+        [ toHie a+        , toHie b+        , toHie c+        ]+      NegApp _ a _ ->+        [ toHie a+        ]+      HsPar _ a ->+        [ toHie a+        ]+      SectionL _ a b ->+        [ toHie a+        , toHie b+        ]+      SectionR _ a b ->+        [ toHie a+        , toHie b+        ]+      ExplicitTuple _ args _ ->+        [ toHie args+        ]+      ExplicitSum _ _ _ expr ->+        [ toHie expr+        ]+      HsCase _ expr matches ->+        [ toHie expr+        , toHie matches+        ]+      HsIf _ _ a b c ->+        [ toHie a+        , toHie b+        , toHie c+        ]+      HsMultiIf _ grhss ->+        [ toHie grhss+        ]+      HsLet _ binds expr ->+        [ toHie $ RS (mkLScope expr) binds+        , toHie expr+        ]+      HsDo _ _ (L ispan stmts) ->+        [ pure $ locOnly ispan+        , toHie $ listScopes NoScope stmts+        ]+      ExplicitList _ _ exprs ->+        [ toHie exprs+        ]+      RecordCon {rcon_con_name = name, rcon_flds = binds}->+        [ toHie $ C Use name+        , toHie $ RC RecFieldAssign $ binds+        ]+      RecordUpd {rupd_expr = expr, rupd_flds = upds}->+        [ toHie expr+        , toHie $ map (RC RecFieldAssign) upds+        ]+      ExprWithTySig _ expr ->+        [ toHie expr+        -- , toHie $ TS (ResolvedScopes [mkLScope expr]) sig+        ]+      ArithSeq _ _ info ->+        [ toHie info+        ]+      HsSCC _ _ _ expr ->+        [ toHie expr+        ]+      HsCoreAnn _ _ _ expr ->+        [ toHie expr+        ]+      HsProc _ pat cmdtop ->+        [ toHie $ PS Nothing (mkLScope cmdtop) NoScope pat+        , toHie cmdtop+        ]+      HsStatic _ expr ->+        [ toHie expr+        ]+      HsArrApp _ a b _ _ ->+        [ toHie a+        , toHie b+        ]+      HsArrForm _ expr _ cmds ->+        [ toHie expr+        , toHie cmds+        ]+      HsTick _ _ expr ->+        [ toHie expr+        ]+      HsBinTick _ _ _ expr ->+        [ toHie expr+        ]+      HsTickPragma _ _ _ _ expr ->+        [ toHie expr+        ]+      HsWrap _ _ a ->+        [ toHie $ L mspan a+        ]+      HsBracket _ b ->+        [ toHie b+        ]+      HsRnBracketOut _ b p ->+        [ toHie b+        , toHie p+        ]+      HsTcBracketOut _ b p ->+        [ toHie b+        , toHie p+        ]+      HsSpliceE _ x ->+        [ toHie $ L mspan x+        ]+      EWildPat _ -> []+      EAsPat _ a b ->+        [ toHie $ C Use a+        , toHie b+        ]+      EViewPat _ a b ->+        [ toHie a+        , toHie b+        ]+      ELazyPat _ a ->+        [ toHie a+        ]+      XExpr _ -> []++instance ( a ~ GhcPass p+         , ToHie (LHsExpr a)+         , Data (HsTupArg a)+         ) => ToHie (LHsTupArg (GhcPass p)) where+  toHie (L span arg) = concatM $ makeNode arg span : case arg of+    Present _ expr ->+      [ toHie expr+      ]+    Missing _ -> []+    XTupArg _ -> []++instance ( a ~ GhcPass p+         , ToHie (PScoped (LPat a))+         , ToHie (LHsExpr a)+         , ToHie (SigContext (LSig a))+         , ToHie (RScoped (LHsLocalBinds a))+         , ToHie (RScoped (ApplicativeArg a))+         , ToHie (Located body)+         , Data (StmtLR a a (Located body))+         , Data (StmtLR a a (Located (HsExpr a)))+         ) => ToHie (RScoped (LStmt (GhcPass p) (Located body))) where+  toHie (RS scope (L span stmt)) = concatM $ makeNode stmt span : case stmt of+      LastStmt _ body _ _ ->+        [ toHie body+        ]+      BindStmt _ pat body _ _ ->+        [ toHie $ PS (getRealSpan $ getLoc body) scope NoScope pat+        , toHie body+        ]+      ApplicativeStmt _ stmts _ ->+        [ concatMapM (toHie . RS scope . snd) stmts+        ]+      BodyStmt _ body _ _ ->+        [ toHie body+        ]+      LetStmt _ binds ->+        [ toHie $ RS scope binds+        ]+      ParStmt _ parstmts _ _ ->+        [ concatMapM (\(ParStmtBlock _ stmts _ _) ->+                          toHie $ listScopes NoScope stmts)+                     parstmts+        ]+      TransStmt {trS_stmts = stmts, trS_using = using, trS_by = by} ->+        [ toHie $ listScopes scope stmts+        , toHie using+        , toHie by+        ]+      RecStmt {recS_stmts = stmts} ->+        [ toHie $ map (RS $ combineScopes scope (mkScope span)) stmts+        ]+      XStmtLR _ -> []++instance ( ToHie (LHsExpr a)+         , ToHie (PScoped (LPat a))+         , ToHie (BindContext (LHsBind a))+         , ToHie (SigContext (LSig a))+         , ToHie (RScoped (HsValBindsLR a a))+         , Data (HsLocalBinds a)+         ) => ToHie (RScoped (LHsLocalBinds a)) where+  toHie (RS scope (L sp binds)) = concatM $ makeNode binds sp : case binds of+      EmptyLocalBinds _ -> []+      HsIPBinds _ _ -> []+      HsValBinds _ valBinds ->+        [ toHie $ RS (combineScopes scope $ mkScope sp)+                      valBinds+        ]+      XHsLocalBindsLR _ -> []++instance ( ToHie (BindContext (LHsBind a))+         , ToHie (SigContext (LSig a))+         , ToHie (RScoped (XXValBindsLR a a))+         ) => ToHie (RScoped (HsValBindsLR a a)) where+  toHie (RS sc v) = concatM $ case v of+    ValBinds _ binds sigs ->+      [ toHie $ fmap (BC RegularBind sc) binds+      , toHie $ fmap (SC (SI BindSig Nothing)) sigs+      ]+    XValBindsLR x -> [ toHie $ RS sc x ]++instance ToHie (RScoped (NHsValBindsLR GhcTc)) where+  toHie (RS sc (NValBinds binds sigs)) = concatM $+    [ toHie (concatMap (map (BC RegularBind sc) . bagToList . snd) binds)+    , toHie $ fmap (SC (SI BindSig Nothing)) sigs+    ]+instance ToHie (RScoped (NHsValBindsLR GhcRn)) where+  toHie (RS sc (NValBinds binds sigs)) = concatM $+    [ toHie (concatMap (map (BC RegularBind sc) . bagToList . snd) binds)+    , toHie $ fmap (SC (SI BindSig Nothing)) sigs+    ]++instance ( ToHie (RContext (LHsRecField a arg))+         ) => ToHie (RContext (HsRecFields a arg)) where+  toHie (RC c (HsRecFields fields _)) = toHie $ map (RC c) fields++instance ( ToHie (RFContext (Located label))+         , ToHie arg+         , HasLoc arg+         , Data label+         , Data arg+         ) => ToHie (RContext (LHsRecField' label arg)) where+  toHie (RC c (L span recfld)) = concatM $ makeNode recfld span : case recfld of+    HsRecField label expr _ ->+      [ toHie $ RFC c (getRealSpan $ loc expr) label+      , toHie expr+      ]++removeDefSrcSpan :: Name -> Name+removeDefSrcSpan n = setNameLoc n noSrcSpan++instance ToHie (RFContext (LFieldOcc GhcRn)) where+  toHie (RFC c rhs (L nspan f)) = concatM $ case f of+    FieldOcc name _ ->+      [ toHie $ C (RecField c rhs) (L nspan $ removeDefSrcSpan name)+      ]+    XFieldOcc _ -> []++instance ToHie (RFContext (LFieldOcc GhcTc)) where+  toHie (RFC c rhs (L nspan f)) = concatM $ case f of+    FieldOcc var _ ->+      let var' = setVarName var (removeDefSrcSpan $ varName var)+      in [ toHie $ C (RecField c rhs) (L nspan var')+         ]+    XFieldOcc _ -> []++instance ToHie (RFContext (Located (AmbiguousFieldOcc GhcRn))) where+  toHie (RFC c rhs (L nspan afo)) = concatM $ case afo of+    Unambiguous name _ ->+      [ toHie $ C (RecField c rhs) $ L nspan $ removeDefSrcSpan name+      ]+    Ambiguous _name _ ->+      [ ]+    XAmbiguousFieldOcc _ -> []++instance ToHie (RFContext (Located (AmbiguousFieldOcc GhcTc))) where+  toHie (RFC c rhs (L nspan afo)) = concatM $ case afo of+    Unambiguous var _ ->+      let var' = setVarName var (removeDefSrcSpan $ varName var)+      in [ toHie $ C (RecField c rhs) (L nspan var')+         ]+    Ambiguous var _ ->+      let var' = setVarName var (removeDefSrcSpan $ varName var)+      in [ toHie $ C (RecField c rhs) (L nspan var')+         ]+    XAmbiguousFieldOcc _ -> []++instance ( a ~ GhcPass p+         , ToHie (PScoped (LPat a))+         , ToHie (BindContext (LHsBind a))+         , ToHie (LHsExpr a)+         , ToHie (SigContext (LSig a))+         , ToHie (RScoped (HsValBindsLR a a))+         , Data (StmtLR a a (Located (HsExpr a)))+         , Data (HsLocalBinds a)+         ) => ToHie (RScoped (ApplicativeArg (GhcPass p))) where+  toHie (RS sc (ApplicativeArgOne _ pat expr _)) = concatM+    [ toHie $ PS Nothing sc NoScope pat+    , toHie expr+    ]+  toHie (RS sc (ApplicativeArgMany _ stmts _ pat)) = concatM+    [ toHie $ listScopes NoScope stmts+    , toHie $ PS Nothing sc NoScope pat+    ]+  toHie (RS _ (XApplicativeArg _)) = pure []++instance (ToHie arg, ToHie rec) => ToHie (HsConDetails arg rec) where+  toHie (PrefixCon args) = toHie args+  toHie (RecCon rec) = toHie rec+  toHie (InfixCon a b) = concatM [ toHie a, toHie b]++instance ( ToHie (LHsCmd a)+         , Data  (HsCmdTop a)+         ) => ToHie (LHsCmdTop a) where+  toHie (L span top) = concatM $ makeNode top span : case top of+    HsCmdTop _ cmd ->+      [ toHie cmd+      ]+    XCmdTop _ -> []++instance ( a ~ GhcPass p+         , ToHie (PScoped (LPat a))+         , ToHie (BindContext (LHsBind a))+         , ToHie (LHsExpr a)+         , ToHie (MatchGroup a (LHsCmd a))+         , ToHie (SigContext (LSig a))+         , ToHie (RScoped (HsValBindsLR a a))+         , Data (HsCmd a)+         , Data (HsCmdTop a)+         , Data (StmtLR a a (Located (HsCmd a)))+         , Data (HsLocalBinds a)+         , Data (StmtLR a a (Located (HsExpr a)))+         ) => ToHie (LHsCmd (GhcPass p)) where+  toHie (L span cmd) = concatM $ makeNode cmd span : case cmd of+      HsCmdArrApp _ a b _ _ ->+        [ toHie a+        , toHie b+        ]+      HsCmdArrForm _ a _ _ cmdtops ->+        [ toHie a+        , toHie cmdtops+        ]+      HsCmdApp _ a b ->+        [ toHie a+        , toHie b+        ]+      HsCmdLam _ mg ->+        [ toHie mg+        ]+      HsCmdPar _ a ->+        [ toHie a+        ]+      HsCmdCase _ expr alts ->+        [ toHie expr+        , toHie alts+        ]+      HsCmdIf _ _ a b c ->+        [ toHie a+        , toHie b+        , toHie c+        ]+      HsCmdLet _ binds cmd' ->+        [ toHie $ RS (mkLScope cmd') binds+        , toHie cmd'+        ]+      HsCmdDo _ (L ispan stmts) ->+        [ pure $ locOnly ispan+        , toHie $ listScopes NoScope stmts+        ]+      HsCmdWrap _ _ _ -> []+      XCmd _ -> []++instance ToHie (TyClGroup GhcRn) where+  toHie (TyClGroup _ classes roles instances) = concatM+    [ toHie classes+    , toHie roles+    , toHie instances+    ]+  toHie (XTyClGroup _) = pure []++instance ToHie (LTyClDecl GhcRn) where+  toHie (L span decl) = concatM $ makeNode decl span : case decl of+      FamDecl {tcdFam = fdecl} ->+        [ toHie (L span fdecl)+        ]+      SynDecl {tcdLName = name, tcdTyVars = vars, tcdRhs = typ} ->+        [ toHie $ C (Decl SynDec $ getRealSpan span) name+        , toHie $ TS (ResolvedScopes [mkScope $ getLoc typ]) vars+        , toHie typ+        ]+      DataDecl {tcdLName = name, tcdTyVars = vars, tcdDataDefn = defn} ->+        [ toHie $ C (Decl DataDec $ getRealSpan span) name+        , toHie $ TS (ResolvedScopes [quant_scope, rhs_scope]) vars+        , toHie defn+        ]+        where+          quant_scope = mkLScope $ dd_ctxt defn+          rhs_scope = sig_sc `combineScopes` con_sc `combineScopes` deriv_sc+          sig_sc = maybe NoScope mkLScope $ dd_kindSig defn+          con_sc = foldr combineScopes NoScope $ map mkLScope $ dd_cons defn+          deriv_sc = mkLScope $ dd_derivs defn+      ClassDecl { tcdCtxt = context+                , tcdLName = name+                , tcdTyVars = vars+                , tcdFDs = deps+                , tcdSigs = sigs+                , tcdMeths = meths+                , tcdATs = typs+                , tcdATDefs = deftyps+                } ->+        [ toHie $ C (Decl ClassDec $ getRealSpan span) name+        , toHie context+        , toHie $ TS (ResolvedScopes [context_scope, rhs_scope]) vars+        , toHie deps+        , toHie $ map (SC $ SI ClassSig $ getRealSpan span) sigs+        , toHie $ fmap (BC InstanceBind ModuleScope) meths+        , toHie typs+        , concatMapM (pure . locOnly . getLoc) deftyps+        , toHie $ map (go . unLoc) deftyps+        ]+        where+          context_scope = mkLScope context+          rhs_scope = foldl1' combineScopes $ map mkScope+            [ loc deps, loc sigs, loc (bagToList meths), loc typs, loc deftyps]++          go :: TyFamDefltEqn GhcRn+             -> FamEqn GhcRn (TScoped (LHsQTyVars GhcRn)) (LHsType GhcRn)+          go (FamEqn a var pat b rhs) =+             FamEqn a var (TS (ResolvedScopes [mkLScope rhs]) pat) b rhs+          go (XFamEqn NoExt) = XFamEqn NoExt+      XTyClDecl _ -> []++instance ToHie (LFamilyDecl GhcRn) where+  toHie (L span decl) = concatM $ makeNode decl span : case decl of+      FamilyDecl _ info name vars _ sig inj ->+        [ toHie $ C (Decl FamDec $ getRealSpan span) name+        , toHie $ TS (ResolvedScopes [rhsSpan]) vars+        , toHie info+        , toHie $ RS injSpan sig+        , toHie inj+        ]+        where+          rhsSpan = sigSpan `combineScopes` injSpan+          sigSpan = mkScope $ getLoc sig+          injSpan = maybe NoScope (mkScope . getLoc) inj+      XFamilyDecl _ -> []++instance ToHie (FamilyInfo GhcRn) where+  toHie (ClosedTypeFamily (Just eqns)) = concatM $+    [ concatMapM (pure . locOnly . getLoc) eqns+    , toHie $ map go eqns+    ]+    where+      go (L l ib) = TS (ResolvedScopes [mkScope l]) ib+  toHie _ = pure []++instance ToHie (RScoped (LFamilyResultSig GhcRn)) where+  toHie (RS sc (L span sig)) = concatM $ makeNode sig span : case sig of+      NoSig _ ->+        []+      KindSig _ k ->+        [ toHie k+        ]+      TyVarSig _ bndr ->+        [ toHie $ TVS (ResolvedScopes [sc]) NoScope bndr+        ]+      XFamilyResultSig _ -> []++instance ToHie (Located (FunDep (Located Name))) where+  toHie (L span fd@(lhs, rhs)) = concatM $+    [ makeNode fd span+    , toHie $ map (C Use) lhs+    , toHie $ map (C Use) rhs+    ]++instance (ToHie pats, ToHie rhs, HasLoc pats, HasLoc rhs)+    => ToHie (TScoped (FamEqn GhcRn pats rhs)) where+  toHie (TS _ f) = toHie f++instance ( ToHie pats+         , ToHie rhs+         , HasLoc pats+         , HasLoc rhs+         ) => ToHie (FamEqn GhcRn pats rhs) where+  toHie fe@(FamEqn _ var pats _ rhs) = concatM $+    [ toHie $ C (Decl InstDec $ getRealSpan $ loc fe) var+    , toHie pats+    , toHie rhs+    ]+  toHie (XFamEqn _) = pure []++instance ToHie (LInjectivityAnn GhcRn) where+  toHie (L span ann) = concatM $ makeNode ann span : case ann of+      InjectivityAnn lhs rhs ->+        [ toHie $ C Use lhs+        , toHie $ map (C Use) rhs+        ]++instance ToHie (HsDataDefn GhcRn) where+  toHie (HsDataDefn _ _ ctx _ mkind cons derivs) = concatM+    [ toHie ctx+    , toHie mkind+    , toHie cons+    , toHie derivs+    ]+  toHie (XHsDataDefn _) = pure []++instance ToHie (HsDeriving GhcRn) where+  toHie (L span clauses) = concatM+    [ pure $ locOnly span+    , toHie clauses+    ]++instance ToHie (LHsDerivingClause GhcRn) where+  toHie (L span cl) = concatM $ makeNode cl span : case cl of+      HsDerivingClause _ strat (L ispan tys) ->+        [ toHie strat+        , pure $ locOnly ispan+        , toHie $ map (TS (ResolvedScopes [])) tys+        ]+      XHsDerivingClause _ -> []++instance ToHie (Located (DerivStrategy GhcRn)) where+  toHie (L span strat) = concatM $ makeNode strat span : case strat of+      StockStrategy -> []+      AnyclassStrategy -> []+      NewtypeStrategy -> []+      ViaStrategy s -> [ toHie $ TS (ResolvedScopes []) s ]++instance ToHie (Located OverlapMode) where+  toHie (L span _) = pure $ locOnly span++instance ToHie (LConDecl GhcRn) where+  toHie (L span decl) = concatM $ makeNode decl span : case decl of+      ConDeclGADT { con_names = names, con_qvars = qvars+                  , con_mb_cxt = ctx, con_args = args, con_res_ty = typ } ->+        [ toHie $ map (C (Decl ConDec $ getRealSpan span)) names+        , toHie $ TS (ResolvedScopes [ctxScope, rhsScope]) qvars+        , toHie ctx+        , toHie args+        , toHie typ+        ]+        where+          rhsScope = combineScopes argsScope tyScope+          ctxScope = maybe NoScope mkLScope ctx+          argsScope = condecl_scope args+          tyScope = mkLScope typ+      ConDeclH98 { con_name = name, con_ex_tvs = qvars+                 , con_mb_cxt = ctx, con_args = dets } ->+        [ toHie $ C (Decl ConDec $ getRealSpan span) name+        , toHie $ tvScopes (ResolvedScopes []) rhsScope qvars+        , toHie ctx+        , toHie dets+        ]+        where+          rhsScope = combineScopes ctxScope argsScope+          ctxScope = maybe NoScope mkLScope ctx+          argsScope = condecl_scope dets+      XConDecl _ -> []+    where condecl_scope args = case args of+            PrefixCon xs -> foldr combineScopes NoScope $ map mkLScope xs+            InfixCon a b -> combineScopes (mkLScope a) (mkLScope b)+            RecCon x -> mkLScope x++instance ToHie (Located [LConDeclField GhcRn]) where+  toHie (L span decls) = concatM $+    [ pure $ locOnly span+    , toHie decls+    ]++instance ( HasLoc thing+         , ToHie (TScoped thing)+         ) => ToHie (TScoped (HsImplicitBndrs GhcRn thing)) where+  toHie (TS sc (HsIB ibrn a)) = concatM $+      [ pure $ bindingsOnly $ map (C $ TyVarBind (mkScope span) sc) $ (hsib_vars ibrn)+      , toHie $ TS sc a+      ]+    where span = loc a+  toHie (TS _ (XHsImplicitBndrs _)) = pure []++instance ( HasLoc thing+         , ToHie (TScoped thing)+         ) => ToHie (TScoped (HsWildCardBndrs GhcRn thing)) where+  toHie (TS sc (HsWC names a)) = concatM $+      [ pure $ bindingsOnly $ map (C $ TyVarBind (mkScope span) sc) names+      , toHie $ TS sc a+      ]+    where span = loc a+  toHie (TS _ (XHsWildCardBndrs _)) = pure []++instance ToHie (SigContext (LSig GhcRn)) where+  toHie (SC (SI styp msp) (L sp sig)) = concatM $ makeNode sig sp : case sig of+      TypeSig _ names typ ->+        [ toHie $ map (C TyDecl) names+        , toHie $ TS (UnresolvedScope (map unLoc names) Nothing) typ+        ]+      PatSynSig _ names typ ->+        [ toHie $ map (C TyDecl) names+        , toHie $ TS (UnresolvedScope (map unLoc names) Nothing) typ+        ]+      ClassOpSig _ _ names typ ->+        [ case styp of+            ClassSig -> toHie $ map (C $ ClassTyDecl $ getRealSpan sp) names+            _  -> toHie $ map (C $ TyDecl) names+        , toHie $ TS (UnresolvedScope (map unLoc names) msp) typ+        ]+      IdSig _ _ -> []+      FixSig _ fsig ->+        [ toHie $ L sp fsig+        ]+      InlineSig _ name _ ->+        [ toHie $ (C Use) name+        ]+      SpecSig _ name typs _ ->+        [ toHie $ (C Use) name+        , toHie $ map (TS (ResolvedScopes [])) typs+        ]+      SpecInstSig _ _ typ ->+        [ toHie $ TS (ResolvedScopes []) typ+        ]+      MinimalSig _ _ form ->+        [ toHie form+        ]+      SCCFunSig _ _ name mtxt ->+        [ toHie $ (C Use) name+        , pure $ maybe [] (locOnly . getLoc) mtxt+        ]+      CompleteMatchSig _ _ (L ispan names) typ ->+        [ pure $ locOnly ispan+        , toHie $ map (C Use) names+        , toHie $ fmap (C Use) typ+        ]+      XSig _ -> []++instance ToHie (LHsType GhcRn) where+  toHie x = toHie $ TS (ResolvedScopes []) x++instance ToHie (TScoped (LHsType GhcRn)) where+  toHie (TS tsc (L span t)) = concatM $ makeNode t span : case t of+      HsForAllTy _ bndrs body ->+        [ toHie $ tvScopes tsc (mkScope $ getLoc body) bndrs+        , toHie body+        ]+      HsQualTy _ ctx body ->+        [ toHie ctx+        , toHie body+        ]+      HsTyVar _ _ var ->+        [ toHie $ C Use var+        ]+      HsAppTy _ a b ->+        [ toHie a+        , toHie b+        ]+      HsFunTy _ a b ->+        [ toHie a+        , toHie b+        ]+      HsListTy _ a ->+        [ toHie a+        ]+      HsTupleTy _ _ tys ->+        [ toHie tys+        ]+      HsSumTy _ tys ->+        [ toHie tys+        ]+      HsOpTy _ a op b ->+        [ toHie a+        , toHie $ C Use op+        , toHie b+        ]+      HsParTy _ a ->+        [ toHie a+        ]+      HsIParamTy _ ip ty ->+        [ toHie ip+        , toHie ty+        ]+      HsKindSig _ a b ->+        [ toHie a+        , toHie b+        ]+      HsSpliceTy _ a ->+        [ toHie $ L span a+        ]+      HsDocTy _ a _ ->+        [ toHie a+        ]+      HsBangTy _ _ ty ->+        [ toHie ty+        ]+      HsRecTy _ fields ->+        [ toHie fields+        ]+      HsExplicitListTy _ _ tys ->+        [ toHie tys+        ]+      HsExplicitTupleTy _ tys ->+        [ toHie tys+        ]+      HsTyLit _ _ -> []+      HsWildCardTy _ -> []+      HsStarTy _ _ -> []+      XHsType _ -> []++{-+instance (ToHie tm, ToHie ty) => ToHie (HsArg tm ty) where+  toHie (HsValArg tm) = toHie tm+  toHie (HsTypeArg _ ty) = toHie ty+  toHie (HsArgPar sp) = pure $ locOnly sp+-}++instance ToHie (TVScoped (LHsTyVarBndr GhcRn)) where+  toHie (TVS tsc sc (L span bndr)) = concatM $ makeNode bndr span : case bndr of+      UserTyVar _ var ->+        [ toHie $ C (TyVarBind sc tsc) var+        ]+      KindedTyVar _ var kind ->+        [ toHie $ C (TyVarBind sc tsc) var+        , toHie kind+        ]+      XTyVarBndr _ -> []++instance ToHie (TScoped (LHsQTyVars GhcRn)) where+  toHie (TS sc (HsQTvs (HsQTvsRn implicits _) vars)) = concatM $+    [ pure $ bindingsOnly bindings+    , toHie $ tvScopes sc NoScope vars+    ]+    where+      varLoc = loc vars+      bindings = map (C $ TyVarBind (mkScope varLoc) sc) implicits+  toHie (TS _ (XLHsQTyVars _)) = pure []++instance ToHie (LHsContext GhcRn) where+  toHie (L span tys) = concatM $+      [ pure $ locOnly span+      , toHie tys+      ]++instance ToHie (LConDeclField GhcRn) where+  toHie (L span field) = concatM $ makeNode field span : case field of+      ConDeclField _ fields typ _ ->+        [ toHie $ map (RFC RecFieldDecl (getRealSpan $ loc typ)) fields+        , toHie typ+        ]+      XConDeclField _ -> []++instance ToHie (LHsExpr a) => ToHie (ArithSeqInfo a) where+  toHie (From expr) = toHie expr+  toHie (FromThen a b) = concatM $+    [ toHie a+    , toHie b+    ]+  toHie (FromTo a b) = concatM $+    [ toHie a+    , toHie b+    ]+  toHie (FromThenTo a b c) = concatM $+    [ toHie a+    , toHie b+    , toHie c+    ]++instance ToHie (LSpliceDecl GhcRn) where+  toHie (L span decl) = concatM $ makeNode decl span : case decl of+      SpliceDecl _ splice _ ->+        [ toHie splice+        ]+      XSpliceDecl _ -> []++instance ToHie (HsBracket a) where+  toHie _ = pure []++instance ToHie PendingRnSplice where+  toHie _ = pure []++instance ToHie PendingTcSplice where+  toHie _ = pure []++instance ToHie (LBooleanFormula (Located Name)) where+  toHie (L span form) = concatM $ makeNode form span : case form of+      Var a ->+        [ toHie $ C Use a+        ]+      And forms ->+        [ toHie forms+        ]+      Or forms ->+        [ toHie forms+        ]+      Parens f ->+        [ toHie f+        ]++instance ToHie (Located HsIPName) where+  toHie (L span e) = makeNode e span++instance ( ToHie (LHsExpr a)+         , Data (HsSplice a)+         ) => ToHie (Located (HsSplice a)) where+  toHie (L span sp) = concatM $ makeNode sp span : case sp of+      HsTypedSplice _ _ _ expr ->+        [ toHie expr+        ]+      HsUntypedSplice _ _ _ expr ->+        [ toHie expr+        ]+      HsQuasiQuote _ _ _ ispan _ ->+        [ pure $ locOnly ispan+        ]+      HsSpliced _ _ _ ->+        []+      XSplice _ -> []++instance ToHie (LRoleAnnotDecl GhcRn) where+  toHie (L span annot) = concatM $ makeNode annot span : case annot of+      RoleAnnotDecl _ var roles ->+        [ toHie $ C Use var+        , concatMapM (pure . locOnly . getLoc) roles+        ]+      XRoleAnnotDecl _ -> []++instance ToHie (LInstDecl GhcRn) where+  toHie (L span decl) = concatM $ makeNode decl span : case decl of+      ClsInstD _ d ->+        [ toHie $ L span d+        ]+      DataFamInstD _ d ->+        [ toHie $ L span d+        ]+      TyFamInstD _ d ->+        [ toHie $ L span d+        ]+      XInstDecl _ -> []++instance ToHie (LClsInstDecl GhcRn) where+  toHie (L span decl) = concatM+    [ toHie $ TS (ResolvedScopes [mkScope span]) $ cid_poly_ty decl+    , toHie $ fmap (BC InstanceBind ModuleScope) $ cid_binds decl+    , toHie $ map (SC $ SI InstSig $ getRealSpan span) $ cid_sigs decl+    , pure $ concatMap (locOnly . getLoc) $ cid_tyfam_insts decl+    , toHie $ cid_tyfam_insts decl+    , pure $ concatMap (locOnly . getLoc) $ cid_datafam_insts decl+    , toHie $ cid_datafam_insts decl+    , toHie $ cid_overlap_mode decl+    ]++instance ToHie (LDataFamInstDecl GhcRn) where+  toHie (L sp (DataFamInstDecl d)) = toHie $ TS (ResolvedScopes [mkScope sp]) d++instance ToHie (LTyFamInstDecl GhcRn) where+  toHie (L sp (TyFamInstDecl d)) = toHie $ TS (ResolvedScopes [mkScope sp]) d++instance ToHie (Context a)+         => ToHie (PatSynFieldContext (RecordPatSynField a)) where+  toHie (PSC sp (RecordPatSynField a b)) = concatM $+    [ toHie $ C (RecField RecFieldDecl sp) a+    , toHie $ C Use b+    ]++instance ToHie (LDerivDecl GhcRn) where+  toHie (L span decl) = concatM $ makeNode decl span : case decl of+      DerivDecl _ typ strat overlap ->+        [ toHie $ TS (ResolvedScopes []) typ+        , toHie strat+        , toHie overlap+        ]+      XDerivDecl _ -> []++instance ToHie (LFixitySig GhcRn) where+  toHie (L span sig) = concatM $ makeNode sig span : case sig of+      FixitySig _ vars _ ->+        [ toHie $ map (C Use) vars+        ]+      XFixitySig _ -> []++instance ToHie (LDefaultDecl GhcRn) where+  toHie (L span decl) = concatM $ makeNode decl span : case decl of+      DefaultDecl _ typs ->+        [ toHie typs+        ]+      XDefaultDecl _ -> []++instance ToHie (LForeignDecl GhcRn) where+  toHie (L span decl) = concatM $ makeNode decl span : case decl of+      ForeignImport {fd_name = name, fd_sig_ty = sig, fd_fi = fi} ->+        [ toHie $ C (ValBind RegularBind ModuleScope $ getRealSpan span) name+        , toHie $ TS (ResolvedScopes []) sig+        , toHie fi+        ]+      ForeignExport {fd_name = name, fd_sig_ty = sig, fd_fe = fe} ->+        [ toHie $ C Use name+        , toHie $ TS (ResolvedScopes []) sig+        , toHie fe+        ]+      XForeignDecl _ -> []++instance ToHie ForeignImport where+  toHie (CImport (L a _) (L b _) _ _ (L c _)) = pure $ concat $+    [ locOnly a+    , locOnly b+    , locOnly c+    ]++instance ToHie ForeignExport where+  toHie (CExport (L a _) (L b _)) = pure $ concat $+    [ locOnly a+    , locOnly b+    ]++instance ToHie (LWarnDecls GhcRn) where+  toHie (L span decl) = concatM $ makeNode decl span : case decl of+      Warnings _ _ warnings ->+        [ toHie warnings+        ]+      XWarnDecls _ -> []++instance ToHie (LWarnDecl GhcRn) where+  toHie (L span decl) = concatM $ makeNode decl span : case decl of+      Warning _ vars _ ->+        [ toHie $ map (C Use) vars+        ]+      XWarnDecl _ -> []++instance ToHie (LAnnDecl GhcRn) where+  toHie (L span decl) = concatM $ makeNode decl span : case decl of+      HsAnnotation _ _ prov expr ->+        [ toHie prov+        , toHie expr+        ]+      XAnnDecl _ -> []++instance ToHie (Context (Located a)) => ToHie (AnnProvenance a) where+  toHie (ValueAnnProvenance a) = toHie $ C Use a+  toHie (TypeAnnProvenance a) = toHie $ C Use a+  toHie ModuleAnnProvenance = pure []++instance ToHie (LRuleDecls GhcRn) where+  toHie (L span decl) = concatM $ makeNode decl span : case decl of+      HsRules _ _ rules ->+        [ toHie rules+        ]+      XRuleDecls _ -> []++instance ToHie (LRuleDecl GhcRn) where+  toHie (L _ (XRuleDecl _)) = pure []+  toHie (L span r@(HsRule _ rname _ bndrs exprA exprB)) = concatM+        [ makeNode r span+        , pure $ locOnly $ getLoc rname+        , toHie $ map (RS $ mkScope span) bndrs+        , toHie exprA+        , toHie exprB+        ]++instance ToHie (RScoped (LRuleBndr GhcRn)) where+  toHie (RS sc (L span bndr)) = concatM $ makeNode bndr span : case bndr of+      RuleBndr _ var ->+        [ toHie $ C (ValBind RegularBind sc Nothing) var+        ]+      RuleBndrSig _ var typ ->+        [ toHie $ C (ValBind RegularBind sc Nothing) var+        , toHie $ TS (ResolvedScopes [sc]) typ+        ]+      XRuleBndr _ -> []++instance ToHie (LImportDecl GhcRn) where+  toHie (L span decl) = concatM $ makeNode decl span : case decl of+      ImportDecl { ideclName = name, ideclAs = as, ideclHiding = hidden } ->+        [ toHie $ IEC Import name+        , toHie $ fmap (IEC ImportAs) as+        , maybe (pure []) goIE hidden+        ]+      XImportDecl _ -> []+    where+      goIE (hiding, (L sp liens)) = concatM $+        [ pure $ locOnly sp+        , toHie $ map (IEC c) liens+        ]+        where+         c = if hiding then ImportHiding else Import++instance ToHie (IEContext (LIE GhcRn)) where+  toHie (IEC c (L span ie)) = concatM $ makeNode ie span : case ie of+      IEVar _ n ->+        [ toHie $ IEC c n+        ]+      IEThingAbs _ n ->+        [ toHie $ IEC c n+        ]+      IEThingAll _ n ->+        [ toHie $ IEC c n+        ]+      IEThingWith _ n _ ns flds ->+        [ toHie $ IEC c n+        , toHie $ map (IEC c) ns+        , toHie $ map (IEC c) flds+        ]+      IEModuleContents _ n ->+        [ toHie $ IEC c n+        ]+      IEGroup _ _ _ -> []+      IEDoc _ _ -> []+      IEDocNamed _ _ -> []+      XIE _ -> []++instance ToHie (IEContext (LIEWrappedName Name)) where+  toHie (IEC c (L span iewn)) = concatM $ makeNode iewn span : case iewn of+      IEName n ->+        [ toHie $ C (IEThing c) n+        ]+      IEPattern p ->+        [ toHie $ C (IEThing c) p+        ]+      IEType n ->+        [ toHie $ C (IEThing c) n+        ]++instance ToHie (IEContext (Located (FieldLbl Name))) where+  toHie (IEC c (L span lbl)) = concatM $ makeNode lbl span : case lbl of+      FieldLabel _ _ n ->+        [ toHie $ C (IEThing c) $ L span n+        ]+
+ src-ghc86/Development/IDE/GHC/HieBin.hs view
@@ -0,0 +1,388 @@+{-+Binary serialization for .hie files.+-}+{-# LANGUAGE ScopedTypeVariables #-}+module Development.IDE.GHC.HieBin ( readHieFile, readHieFileWithVersion, HieHeader, writeHieFile, HieName(..), toHieName, HieFileResult(..), hieMagic,NameCacheUpdater(..)) where++import Config                     ( cProjectVersion )+import Binary+import BinIface                   ( getDictFastString )+import FastMutInt+import FastString                 ( FastString )+import Module                     ( Module )+import Name+import NameCache+import Outputable+import PrelInfo+import SrcLoc+import UniqSupply                 ( takeUniqFromSupply )+import Util                       ( maybeRead )+import Unique+import UniqFM+import IfaceEnv++import qualified Data.Array as A+import Data.IORef+import Data.ByteString            ( ByteString )+import qualified Data.ByteString  as BS+import qualified Data.ByteString.Char8 as BSC+import Data.List                  ( mapAccumR )+import Data.Word                  ( Word8, Word32 )+import Control.Monad              ( replicateM, when )+import System.Directory           ( createDirectoryIfMissing )+import System.FilePath            ( takeDirectory )++import Development.IDE.GHC.HieTypes++-- | `Name`'s get converted into `HieName`'s before being written into @.hie@+-- files. See 'toHieName' and 'fromHieName' for logic on how to convert between+-- these two types.+data HieName+  = ExternalName !Module !OccName !SrcSpan+  | LocalName !OccName !SrcSpan+  | KnownKeyName !Unique+  deriving (Eq)++instance Ord HieName where+  compare (ExternalName a b c) (ExternalName d e f) = compare (a,b,c) (d,e,f)+  compare (LocalName a b) (LocalName c d) = compare (a,b) (c,d)+  compare (KnownKeyName a) (KnownKeyName b) = nonDetCmpUnique a b+    -- Not actually non determinstic as it is a KnownKey+  compare ExternalName{} _ = LT+  compare LocalName{} ExternalName{} = GT+  compare LocalName{} _ = LT+  compare KnownKeyName{} _ = GT++instance Outputable HieName where+  ppr (ExternalName m n sp) = text "ExternalName" <+> ppr m <+> ppr n <+> ppr sp+  ppr (LocalName n sp) = text "LocalName" <+> ppr n <+> ppr sp+  ppr (KnownKeyName u) = text "KnownKeyName" <+> ppr u+++data HieSymbolTable = HieSymbolTable+  { hie_symtab_next :: !FastMutInt+  , hie_symtab_map  :: !(IORef (UniqFM (Int, HieName)))+  }++data HieDictionary = HieDictionary+  { hie_dict_next :: !FastMutInt -- The next index to use+  , hie_dict_map  :: !(IORef (UniqFM (Int,FastString))) -- indexed by FastString+  }++initBinMemSize :: Int+initBinMemSize = 1024*1024++-- | The header for HIE files - Capital ASCII letters "HIE".+hieMagic :: [Word8]+hieMagic = [72,73,69]++hieMagicLen :: Int+hieMagicLen = length hieMagic++ghcVersion :: ByteString+ghcVersion = BSC.pack cProjectVersion++putBinLine :: BinHandle -> ByteString -> IO ()+putBinLine bh xs = do+  mapM_ (putByte bh) $ BS.unpack xs+  putByte bh 10 -- newline char++-- | Write a `HieFile` to the given `FilePath`, with a proper header and+-- symbol tables for `Name`s and `FastString`s+writeHieFile :: FilePath -> HieFile -> IO ()+writeHieFile hie_file_path hiefile = do+  bh0 <- openBinMem initBinMemSize++  -- Write the header: hieHeader followed by the+  -- hieVersion and the GHC version used to generate this file+  mapM_ (putByte bh0) hieMagic+  putBinLine bh0 $ BSC.pack $ show hieVersion+  putBinLine bh0 $ ghcVersion++  -- remember where the dictionary pointer will go+  dict_p_p <- tellBin bh0+  put_ bh0 dict_p_p++  -- remember where the symbol table pointer will go+  symtab_p_p <- tellBin bh0+  put_ bh0 symtab_p_p++  -- Make some intial state+  symtab_next <- newFastMutInt+  writeFastMutInt symtab_next 0+  symtab_map <- newIORef emptyUFM+  let hie_symtab = HieSymbolTable {+                      hie_symtab_next = symtab_next,+                      hie_symtab_map  = symtab_map }+  dict_next_ref <- newFastMutInt+  writeFastMutInt dict_next_ref 0+  dict_map_ref <- newIORef emptyUFM+  let hie_dict = HieDictionary {+                      hie_dict_next = dict_next_ref,+                      hie_dict_map  = dict_map_ref }++  -- put the main thing+  let bh = setUserData bh0 $ newWriteState (putName hie_symtab)+                                           (putName hie_symtab)+                                           (putFastString hie_dict)+  put_ bh hiefile++  -- write the symtab pointer at the front of the file+  symtab_p <- tellBin bh+  putAt bh symtab_p_p symtab_p+  seekBin bh symtab_p++  -- write the symbol table itself+  symtab_next' <- readFastMutInt symtab_next+  symtab_map'  <- readIORef symtab_map+  putSymbolTable bh symtab_next' symtab_map'++  -- write the dictionary pointer at the front of the file+  dict_p <- tellBin bh+  putAt bh dict_p_p dict_p+  seekBin bh dict_p++  -- write the dictionary itself+  dict_next <- readFastMutInt dict_next_ref+  dict_map  <- readIORef dict_map_ref+  putDictionary bh dict_next dict_map++  -- and send the result to the file+  createDirectoryIfMissing True (takeDirectory hie_file_path)+  writeBinMem bh hie_file_path+  return ()++data HieFileResult+  = HieFileResult+  { hie_file_result_version :: Integer+  , hie_file_result_ghc_version :: ByteString+  , hie_file_result :: HieFile+  }++type HieHeader = (Integer, ByteString)++-- | Read a `HieFile` from a `FilePath`. Can use+-- an existing `NameCache`. Allows you to specify+-- which versions of hieFile to attempt to read.+-- `Left` case returns the failing header versions.+readHieFileWithVersion :: (HieHeader -> Bool) -> NameCacheUpdater -> FilePath -> IO (Either HieHeader HieFileResult)+readHieFileWithVersion readVersion ncu file = do+  bh0 <- readBinMem file++  (hieVersion, ghcVersion) <- readHieFileHeader file bh0++  if readVersion (hieVersion, ghcVersion)+  then do+    hieFile <- readHieFileContents bh0 ncu+    return $ Right (HieFileResult hieVersion ghcVersion hieFile)+  else return $ Left (hieVersion, ghcVersion)+++-- | Read a `HieFile` from a `FilePath`. Can use+-- an existing `NameCache`.+readHieFile :: NameCacheUpdater -> FilePath -> IO HieFileResult+readHieFile ncu file = do++  bh0 <- readBinMem file++  (readHieVersion, ghcVersion) <- readHieFileHeader file bh0++  -- Check if the versions match+  when (readHieVersion /= hieVersion) $+    panic $ unwords ["readHieFile: hie file versions don't match for file:"+                    , file+                    , "Expected"+                    , show hieVersion+                    , "but got", show readHieVersion+                    ]+  hieFile <- readHieFileContents bh0 ncu+  return $ HieFileResult hieVersion ghcVersion hieFile++readBinLine :: BinHandle -> IO ByteString+readBinLine bh = BS.pack . reverse <$> loop []+  where+    loop acc = do+      char <- get bh :: IO Word8+      if char == 10 -- ASCII newline '\n'+      then return acc+      else loop (char : acc)++readHieFileHeader :: FilePath -> BinHandle -> IO HieHeader+readHieFileHeader file bh0 = do+  -- Read the header+  magic <- replicateM hieMagicLen (get bh0)+  version <- BSC.unpack <$> readBinLine bh0+  case maybeRead version of+    Nothing ->+      panic $ unwords ["readHieFileHeader: hieVersion isn't an Integer:"+                      , show version+                      ]+    Just readHieVersion -> do+      ghcVersion <- readBinLine bh0++      -- Check if the header is valid+      when (magic /= hieMagic) $+        panic $ unwords ["readHieFileHeader: headers don't match for file:"+                        , file+                        , "Expected"+                        , show hieMagic+                        , "but got", show magic+                        ]+      return (readHieVersion, ghcVersion)++readHieFileContents :: BinHandle -> NameCacheUpdater -> IO HieFile+readHieFileContents bh0 ncu = do++  dict  <- get_dictionary bh0++  -- read the symbol table so we are capable of reading the actual data+  bh1 <- do+      let bh1 = setUserData bh0 $ newReadState (error "getSymtabName")+                                               (getDictFastString dict)+      symtab <- get_symbol_table bh1+      let bh1' = setUserData bh1+               $ newReadState (getSymTabName symtab)+                              (getDictFastString dict)+      return bh1'++  -- load the actual data+  hiefile <- get bh1+  return hiefile+  where+    get_dictionary bin_handle = do+      dict_p <- get bin_handle+      data_p <- tellBin bin_handle+      seekBin bin_handle dict_p+      dict <- getDictionary bin_handle+      seekBin bin_handle data_p+      return dict++    get_symbol_table bh1 = do+      symtab_p <- get bh1+      data_p'  <- tellBin bh1+      seekBin bh1 symtab_p+      symtab <- getSymbolTable bh1 ncu+      seekBin bh1 data_p'+      return symtab++putFastString :: HieDictionary -> BinHandle -> FastString -> IO ()+putFastString HieDictionary { hie_dict_next = j_r,+                              hie_dict_map  = out_r}  bh f+  = do+    out <- readIORef out_r+    let unique = getUnique f+    case lookupUFM out unique of+        Just (j, _)  -> put_ bh (fromIntegral j :: Word32)+        Nothing -> do+           j <- readFastMutInt j_r+           put_ bh (fromIntegral j :: Word32)+           writeFastMutInt j_r (j + 1)+           writeIORef out_r $! addToUFM out unique (j, f)++putSymbolTable :: BinHandle -> Int -> UniqFM (Int,HieName) -> IO ()+putSymbolTable bh next_off symtab = do+  put_ bh next_off+  let names = A.elems (A.array (0,next_off-1) (nonDetEltsUFM symtab))+  mapM_ (putHieName bh) names++getSymbolTable :: BinHandle -> NameCacheUpdater -> IO SymbolTable+getSymbolTable bh ncu = do+  sz <- get bh+  od_names <- replicateM sz (getHieName bh)+  updateNameCache ncu $ \nc ->+    let arr = A.listArray (0,sz-1) names+        (nc', names) = mapAccumR fromHieName nc od_names+        in (nc',arr)++getSymTabName :: SymbolTable -> BinHandle -> IO Name+getSymTabName st bh = do+  i :: Word32 <- get bh+  return $ st A.! (fromIntegral i)++putName :: HieSymbolTable -> BinHandle -> Name -> IO ()+putName (HieSymbolTable next ref) bh name = do+  symmap <- readIORef ref+  case lookupUFM symmap name of+    Just (off, ExternalName mod occ (UnhelpfulSpan _))+      | isGoodSrcSpan (nameSrcSpan name) -> do+      let hieName = ExternalName mod occ (nameSrcSpan name)+      writeIORef ref $! addToUFM symmap name (off, hieName)+      put_ bh (fromIntegral off :: Word32)+    Just (off, LocalName _occ span)+      | notLocal (toHieName name) || nameSrcSpan name /= span -> do+      writeIORef ref $! addToUFM symmap name (off, toHieName name)+      put_ bh (fromIntegral off :: Word32)+    Just (off, _) -> put_ bh (fromIntegral off :: Word32)+    Nothing -> do+        off <- readFastMutInt next+        writeFastMutInt next (off+1)+        writeIORef ref $! addToUFM symmap name (off, toHieName name)+        put_ bh (fromIntegral off :: Word32)++  where+    notLocal :: HieName -> Bool+    notLocal LocalName{} = False+    notLocal _ = True+++-- ** Converting to and from `HieName`'s++toHieName :: Name -> HieName+toHieName name+  | isKnownKeyName name = KnownKeyName (nameUnique name)+  | isExternalName name = ExternalName (nameModule name)+                                       (nameOccName name)+                                       (nameSrcSpan name)+  | otherwise = LocalName (nameOccName name) (nameSrcSpan name)++fromHieName :: NameCache -> HieName -> (NameCache, Name)+fromHieName nc (ExternalName mod occ span) =+    let cache = nsNames nc+    in case lookupOrigNameCache cache mod occ of+         Just name+           | nameSrcSpan name == span -> (nc, name)+           | otherwise ->+             let name' = setNameLoc name span+                 new_cache = extendNameCache cache mod occ name'+             in ( nc{ nsNames = new_cache }, name' )+         Nothing ->+           let (uniq, us) = takeUniqFromSupply (nsUniqs nc)+               name       = mkExternalName uniq mod occ span+               new_cache  = extendNameCache cache mod occ name+           in ( nc{ nsUniqs = us, nsNames = new_cache }, name )+fromHieName nc (LocalName occ span) =+    let (uniq, us) = takeUniqFromSupply (nsUniqs nc)+        name       = mkInternalName uniq occ span+    in ( nc{ nsUniqs = us }, name )+fromHieName nc (KnownKeyName u) = case lookupKnownKeyName u of+    Nothing -> pprPanic "fromHieName:unknown known-key unique"+                        (ppr (unpkUnique u))+    Just n -> (nc, n)++-- ** Reading and writing `HieName`'s++putHieName :: BinHandle -> HieName -> IO ()+putHieName bh (ExternalName mod occ span) = do+  putByte bh 0+  put_ bh (mod, occ, span)+putHieName bh (LocalName occName span) = do+  putByte bh 1+  put_ bh (occName, span)+putHieName bh (KnownKeyName uniq) = do+  putByte bh 2+  put_ bh $ unpkUnique uniq++getHieName :: BinHandle -> IO HieName+getHieName bh = do+  t <- getByte bh+  case t of+    0 -> do+      (modu, occ, span) <- get bh+      return $ ExternalName modu occ span+    1 -> do+      (occ, span) <- get bh+      return $ LocalName occ span+    2 -> do+      (c,i) <- get bh+      return $ KnownKeyName $ mkUnique c i+    _ -> panic "HieBin.getHieName: invalid tag"
+ src-ghc86/Development/IDE/GHC/HieDebug.hs view
@@ -0,0 +1,145 @@+{-+Functions to validate and check .hie file ASTs generated by GHC.+-}+{-# LANGUAGE StandaloneDeriving #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE FlexibleContexts #-}+module Development.IDE.GHC.HieDebug where++import Prelude hiding ((<>))+import SrcLoc+import Module+import FastString+import Outputable++import Development.IDE.GHC.HieTypes+import Development.IDE.GHC.HieBin+import Development.IDE.GHC.HieUtils++import qualified Data.Map as M+import qualified Data.Set as S+import Data.Function    ( on )+import Data.List        ( sortOn )+import Data.Foldable    ( toList )++ppHies :: Outputable a => (HieASTs a) -> SDoc+ppHies (HieASTs asts) = M.foldrWithKey go "" asts+  where+    go k a rest = vcat $+      [ "File: " <> ppr k+      , ppHie a+      , rest+      ]++ppHie :: Outputable a => HieAST a -> SDoc+ppHie = go 0+  where+    go n (Node inf sp children) = hang header n rest+      where+        rest = vcat $ map (go (n+2)) children+        header = hsep+          [ "Node"+          , ppr sp+          , ppInfo inf+          ]++ppInfo :: Outputable a => NodeInfo a -> SDoc+ppInfo ni = hsep+  [ ppr $ toList $ nodeAnnotations ni+  , ppr $ nodeType ni+  , ppr $ M.toList $ nodeIdentifiers ni+  ]++type Diff a = a -> a -> [SDoc]++diffFile :: Diff HieFile+diffFile = diffAsts eqDiff `on` (getAsts . hie_asts)++diffAsts :: (Outputable a, Eq a) => Diff a -> Diff (M.Map FastString (HieAST a))+diffAsts f = diffList (diffAst f) `on` M.elems++diffAst :: (Outputable a, Eq a) => Diff a -> Diff (HieAST a)+diffAst diffType (Node info1 span1 xs1) (Node info2 span2 xs2) =+    infoDiff ++ spanDiff ++ diffList (diffAst diffType) xs1 xs2+  where+    spanDiff+      | span1 /= span2 = [hsep ["Spans", ppr span1, "and", ppr span2, "differ"]]+      | otherwise = []+    infoDiff+      = (diffList eqDiff `on` (S.toAscList . nodeAnnotations)) info1 info2+     ++ (diffList diffType `on` nodeType) info1 info2+     ++ (diffIdents `on` nodeIdentifiers) info1 info2+    diffIdents a b = (diffList diffIdent `on` normalizeIdents) a b+    diffIdent (a,b) (c,d) = diffName a c+                         ++ eqDiff b d+    diffName (Right a) (Right b) = case (a,b) of+      (ExternalName m o _, ExternalName m' o' _) -> eqDiff (m,o) (m',o')+      (LocalName o _, ExternalName _ o' _) -> eqDiff o o'+      _ -> eqDiff a b+    diffName a b = eqDiff a b++type DiffIdent = Either ModuleName HieName++normalizeIdents :: NodeIdentifiers a -> [(DiffIdent,IdentifierDetails a)]+normalizeIdents = sortOn fst . map (first toHieName) . M.toList+  where+    first f (a,b) = (fmap f a, b)++diffList :: Diff a -> Diff [a]+diffList f xs ys+  | length xs == length ys = concat $ zipWith f xs ys+  | otherwise = ["length of lists doesn't match"]++eqDiff :: (Outputable a, Eq a) => Diff a+eqDiff a b+  | a == b = []+  | otherwise = [hsep [ppr a, "and", ppr b, "do not match"]]++validAst :: HieAST a -> Either SDoc ()+validAst (Node _ span children) = do+  checkContainment children+  checkSorted children+  mapM_ validAst children+  where+    checkSorted [] = return ()+    checkSorted [_] = return ()+    checkSorted (x:y:xs)+      | nodeSpan x `leftOf` nodeSpan y = checkSorted (y:xs)+      | otherwise = Left $ hsep+          [ ppr $ nodeSpan x+          , "is not to the left of"+          , ppr $ nodeSpan y+          ]+    checkContainment [] = return ()+    checkContainment (x:xs)+      | span `containsSpan` (nodeSpan x) = checkContainment xs+      | otherwise = Left $ hsep+          [ ppr $ span+          , "does not contain"+          , ppr $ nodeSpan x+          ]++-- | Look for any identifiers which occur outside of their supposed scopes.+-- Returns a list of error messages.+validateScopes :: M.Map FastString (HieAST a) -> [SDoc]+validateScopes asts = M.foldrWithKey (\k a b -> valid k a ++ b) [] refMap+  where+    refMap = generateReferencesMap asts+    valid (Left _) _ = []+    valid (Right n) refs = concatMap inScope refs+      where+        mapRef = foldMap getScopeFromContext . identInfo . snd+        scopes = case foldMap mapRef refs of+          Just xs -> xs+          Nothing -> []+        inScope (sp, dets)+          |  definedInAsts asts n+          && any isOccurrence (identInfo dets)+            = case scopes of+              [] -> []+              _ -> if any (`scopeContainsSpan` sp) scopes+                   then []+                   else return $ hsep $+                     [ "Name", ppr n, "at position", ppr sp+                     , "doesn't occur in calculated scope", ppr scopes]+          | otherwise = []
+ src-ghc86/Development/IDE/GHC/HieTypes.hs view
@@ -0,0 +1,534 @@+{-+Types for the .hie file format are defined here.++For more information see https://gitlab.haskell.org/ghc/ghc/wikis/hie-files+-}+{-# LANGUAGE DeriveTraversable #-}+{-# LANGUAGE DeriveDataTypeable #-}+{-# LANGUAGE TypeSynonymInstances #-}+{-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE ScopedTypeVariables #-}+{-# OPTIONS_GHC -Wno-orphans #-}+module Development.IDE.GHC.HieTypes where++import Config+import Binary+import FastString                 ( FastString )+import IfaceType+import Module                     ( ModuleName, Module )+import Name                       ( Name )+import Outputable hiding ( (<>) )+import SrcLoc+import Avail++import qualified Data.Array as A+import qualified Data.Map as M+import qualified Data.Set as S+import Data.ByteString            ( ByteString )+import Data.Data                  ( Typeable, Data )+import Data.Semigroup             ( Semigroup(..) )+import Data.Word                  ( Word8 )+import Control.Applicative        ( (<|>) )++type Span = RealSrcSpan++instance Binary RealSrcSpan where+  put_ bh ss = do+            put_ bh (srcSpanFile ss)+            put_ bh (srcSpanStartLine ss)+            put_ bh (srcSpanStartCol ss)+            put_ bh (srcSpanEndLine ss)+            put_ bh (srcSpanEndCol ss)++  get bh = do+            f <- get bh+            sl <- get bh+            sc <- get bh+            el <- get bh+            ec <- get bh+            return (mkRealSrcSpan (mkRealSrcLoc f sl sc)+                                  (mkRealSrcLoc f el ec))++instance (A.Ix a, Binary a, Binary b) => Binary (A.Array a b) where+    put_ bh arr = do+        put_ bh $ A.bounds arr+        put_ bh $ A.elems arr+    get bh = do+        bounds <- get bh+        xs <- get bh+        return $ A.listArray bounds xs++-- | Current version of @.hie@ files+hieVersion :: Integer+hieVersion = read (cProjectVersionInt ++ cProjectPatchLevel) :: Integer++{- |+GHC builds up a wealth of information about Haskell source as it compiles it.+@.hie@ files are a way of persisting some of this information to disk so that+external tools that need to work with haskell source don't need to parse,+typecheck, and rename all over again. These files contain:++  * a simplified AST++       * nodes are annotated with source positions and types+       * identifiers are annotated with scope information++  * the raw bytes of the initial Haskell source++Besides saving compilation cycles, @.hie@ files also offer a more stable+interface than the GHC API.+-}+data HieFile = HieFile+    { hie_hs_file :: FilePath+    -- ^ Initial Haskell source file path++    , hie_module :: Module+    -- ^ The module this HIE file is for++    , hie_types :: A.Array TypeIndex HieTypeFlat+    -- ^ Types referenced in the 'hie_asts'.+    --+    -- See Note [Efficient serialization of redundant type info]++    , hie_asts :: HieASTs TypeIndex+    -- ^ Type-annotated abstract syntax trees++    , hie_exports :: [AvailInfo]+    -- ^ The names that this module exports++    , hie_hs_src :: ByteString+    -- ^ Raw bytes of the initial Haskell source+    }+instance Binary HieFile where+  put_ bh hf = do+    put_ bh $ hie_hs_file hf+    put_ bh $ hie_module hf+    put_ bh $ hie_types hf+    put_ bh $ hie_asts hf+    put_ bh $ hie_exports hf+    put_ bh $ hie_hs_src hf++  get bh = HieFile+    <$> get bh+    <*> get bh+    <*> get bh+    <*> get bh+    <*> get bh+    <*> get bh+++{-+Note [Efficient serialization of redundant type info]+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~++The type information in .hie files is highly repetitive and redundant. For+example, consider the expression++    const True 'a'++There is a lot of shared structure between the types of subterms:++  * const True 'a' ::                 Bool+  * const True     ::         Char -> Bool+  * const          :: Bool -> Char -> Bool++Since all 3 of these types need to be stored in the .hie file, it is worth+making an effort to deduplicate this shared structure. The trick is to define+a new data type that is a flattened version of 'Type':++    data HieType a = HAppTy a a  -- data Type = AppTy Type Type+                   | HFunTy a a  --           | FunTy Type Type+                   | ...++    type TypeIndex = Int++Types in the final AST are stored in an 'A.Array TypeIndex (HieType TypeIndex)',+where the 'TypeIndex's in the 'HieType' are references to other elements of the+array. Types recovered from GHC are deduplicated and stored in this compressed+form with sharing of subtrees.+-}++type TypeIndex = Int++-- | A flattened version of 'Type'.+--+-- See Note [Efficient serialization of redundant type info]+data HieType a+  = HTyVarTy Name+  | HAppTy a a+  | HTyConApp IfaceTyCon (HieArgs a)+  | HForAllTy ((Name, a),ArgFlag) a+  | HFunTy  a a+  | HQualTy a a           -- ^ type with constraint: @t1 => t2@ (see 'IfaceDFunTy')+  | HLitTy IfaceTyLit+  | HCastTy a+  | HCoercionTy+    deriving (Functor, Foldable, Traversable, Eq)++type HieTypeFlat = HieType TypeIndex++-- | Roughly isomorphic to the original core 'Type'.+newtype HieTypeFix = Roll (HieType (HieTypeFix))++instance Binary (HieType TypeIndex) where+  put_ bh (HTyVarTy n) = do+    putByte bh 0+    put_ bh n+  put_ bh (HAppTy a b) = do+    putByte bh 1+    put_ bh a+    put_ bh b+  put_ bh (HTyConApp n xs) = do+    putByte bh 2+    put_ bh n+    put_ bh xs+  put_ bh (HForAllTy bndr a) = do+    putByte bh 3+    put_ bh bndr+    put_ bh a+  put_ bh (HFunTy a b) = do+    putByte bh 4+    put_ bh a+    put_ bh b+  put_ bh (HQualTy a b) = do+    putByte bh 5+    put_ bh a+    put_ bh b+  put_ bh (HLitTy l) = do+    putByte bh 6+    put_ bh l+  put_ bh (HCastTy a) = do+    putByte bh 7+    put_ bh a+  put_ bh (HCoercionTy) = putByte bh 8++  get bh = do+    (t :: Word8) <- get bh+    case t of+      0 -> HTyVarTy <$> get bh+      1 -> HAppTy <$> get bh <*> get bh+      2 -> HTyConApp <$> get bh <*> get bh+      3 -> HForAllTy <$> get bh <*> get bh+      4 -> HFunTy <$> get bh <*> get bh+      5 -> HQualTy <$> get bh <*> get bh+      6 -> HLitTy <$> get bh+      7 -> HCastTy <$> get bh+      8 -> return HCoercionTy+      _ -> panic "Binary (HieArgs Int): invalid tag"+++-- | A list of type arguments along with their respective visibilities (ie. is+-- this an argument that would return 'True' for 'isVisibleArgFlag'?).+newtype HieArgs a = HieArgs [(Bool,a)]+  deriving (Functor, Foldable, Traversable, Eq)++instance Binary (HieArgs TypeIndex) where+  put_ bh (HieArgs xs) = put_ bh xs+  get bh = HieArgs <$> get bh++-- | Mapping from filepaths (represented using 'FastString') to the+-- corresponding AST+newtype HieASTs a = HieASTs { getAsts :: (M.Map FastString (HieAST a)) }+  deriving (Functor, Foldable, Traversable)++instance Binary (HieASTs TypeIndex) where+  put_ bh asts = put_ bh $ M.toAscList $ getAsts asts+  get bh = HieASTs <$> fmap M.fromDistinctAscList (get bh)+++data HieAST a =+  Node+    { nodeInfo :: NodeInfo a+    , nodeSpan :: Span+    , nodeChildren :: [HieAST a]+    } deriving (Functor, Foldable, Traversable)++instance Binary (HieAST TypeIndex) where+  put_ bh ast = do+    put_ bh $ nodeInfo ast+    put_ bh $ nodeSpan ast+    put_ bh $ nodeChildren ast++  get bh = Node+    <$> get bh+    <*> get bh+    <*> get bh+++-- | The information stored in one AST node.+--+-- The type parameter exists to provide flexibility in representation of types+-- (see Note [Efficient serialization of redundant type info]).+data NodeInfo a = NodeInfo+    { nodeAnnotations :: S.Set (FastString,FastString)+    -- ^ (name of the AST node constructor, name of the AST node Type)++    , nodeType :: [a]+    -- ^ The Haskell types of this node, if any.++    , nodeIdentifiers :: NodeIdentifiers a+    -- ^ All the identifiers and their details+    } deriving (Functor, Foldable, Traversable)++instance Binary (NodeInfo TypeIndex) where+  put_ bh ni = do+    put_ bh $ S.toAscList $ nodeAnnotations ni+    put_ bh $ nodeType ni+    put_ bh $ M.toList $ nodeIdentifiers ni+  get bh = NodeInfo+    <$> fmap (S.fromDistinctAscList) (get bh)+    <*> get bh+    <*> fmap (M.fromList) (get bh)++type Identifier = Either ModuleName Name++type NodeIdentifiers a = M.Map Identifier (IdentifierDetails a)++-- | Information associated with every identifier+--+-- We need to include types with identifiers because sometimes multiple+-- identifiers occur in the same span(Overloaded Record Fields and so on)+data IdentifierDetails a = IdentifierDetails+  { identType :: Maybe a+  , identInfo :: S.Set ContextInfo+  } deriving (Eq, Functor, Foldable, Traversable)++instance Outputable a => Outputable (IdentifierDetails a) where+  ppr x = text "IdentifierDetails" <+> ppr (identType x) <+> ppr (identInfo x)++instance Semigroup (IdentifierDetails a) where+  d1 <> d2 = IdentifierDetails (identType d1 <|> identType d2)+                               (S.union (identInfo d1) (identInfo d2))++instance Monoid (IdentifierDetails a) where+  mempty = IdentifierDetails Nothing S.empty++instance Binary (IdentifierDetails TypeIndex) where+  put_ bh dets = do+    put_ bh $ identType dets+    put_ bh $ S.toAscList $ identInfo dets+  get bh =  IdentifierDetails+    <$> get bh+    <*> fmap (S.fromDistinctAscList) (get bh)+++-- | Different contexts under which identifiers exist+data ContextInfo+  = Use                -- ^ regular variable+  | MatchBind+  | IEThing IEType     -- ^ import/export+  | TyDecl++  -- | Value binding+  | ValBind+      BindType     -- ^ whether or not the binding is in an instance+      Scope        -- ^ scope over which the value is bound+      (Maybe Span) -- ^ span of entire binding++  -- | Pattern binding+  --+  -- This case is tricky because the bound identifier can be used in two+  -- distinct scopes. Consider the following example (with @-XViewPatterns@)+  --+  -- @+  -- do (b, a, (a -> True)) <- bar+  --    foo a+  -- @+  --+  -- The identifier @a@ has two scopes: in the view pattern @(a -> True)@ and+  -- in the rest of the @do@-block in @foo a@.+  | PatternBind+      Scope        -- ^ scope /in the pattern/ (the variable bound can be used+                   -- further in the pattern)+      Scope        -- ^ rest of the scope outside the pattern+      (Maybe Span) -- ^ span of entire binding++  | ClassTyDecl (Maybe Span)++  -- | Declaration+  | Decl+      DeclType     -- ^ type of declaration+      (Maybe Span) -- ^ span of entire binding++  -- | Type variable+  | TyVarBind Scope TyVarScope++  -- | Record field+  | RecField RecFieldContext (Maybe Span)+    deriving (Eq, Ord, Show)++instance Outputable ContextInfo where+  ppr = text . show++instance Binary ContextInfo where+  put_ bh Use = putByte bh 0+  put_ bh (IEThing t) = do+    putByte bh 1+    put_ bh t+  put_ bh TyDecl = putByte bh 2+  put_ bh (ValBind bt sc msp) = do+    putByte bh 3+    put_ bh bt+    put_ bh sc+    put_ bh msp+  put_ bh (PatternBind a b c) = do+    putByte bh 4+    put_ bh a+    put_ bh b+    put_ bh c+  put_ bh (ClassTyDecl sp) = do+    putByte bh 5+    put_ bh sp+  put_ bh (Decl a b) = do+    putByte bh 6+    put_ bh a+    put_ bh b+  put_ bh (TyVarBind a b) = do+    putByte bh 7+    put_ bh a+    put_ bh b+  put_ bh (RecField a b) = do+    putByte bh 8+    put_ bh a+    put_ bh b+  put_ bh MatchBind = putByte bh 9++  get bh = do+    (t :: Word8) <- get bh+    case t of+      0 -> return Use+      1 -> IEThing <$> get bh+      2 -> return TyDecl+      3 -> ValBind <$> get bh <*> get bh <*> get bh+      4 -> PatternBind <$> get bh <*> get bh <*> get bh+      5 -> ClassTyDecl <$> get bh+      6 -> Decl <$> get bh <*> get bh+      7 -> TyVarBind <$> get bh <*> get bh+      8 -> RecField <$> get bh <*> get bh+      9 -> return MatchBind+      _ -> panic "Binary ContextInfo: invalid tag"+++-- | Types of imports and exports+data IEType+  = Import+  | ImportAs+  | ImportHiding+  | Export+    deriving (Eq, Enum, Ord, Show)++instance Binary IEType where+  put_ bh b = putByte bh (fromIntegral (fromEnum b))+  get bh = do x <- getByte bh; pure $! (toEnum (fromIntegral x))+++data RecFieldContext+  = RecFieldDecl+  | RecFieldAssign+  | RecFieldMatch+  | RecFieldOcc+    deriving (Eq, Enum, Ord, Show)++instance Binary RecFieldContext where+  put_ bh b = putByte bh (fromIntegral (fromEnum b))+  get bh = do x <- getByte bh; pure $! (toEnum (fromIntegral x))+++data BindType+  = RegularBind+  | InstanceBind+    deriving (Eq, Ord, Show, Enum)++instance Binary BindType where+  put_ bh b = putByte bh (fromIntegral (fromEnum b))+  get bh = do x <- getByte bh; pure $! (toEnum (fromIntegral x))+++data DeclType+  = FamDec     -- ^ type or data family+  | SynDec     -- ^ type synonym+  | DataDec    -- ^ data declaration+  | ConDec     -- ^ constructor declaration+  | PatSynDec  -- ^ pattern synonym+  | ClassDec   -- ^ class declaration+  | InstDec    -- ^ instance declaration+    deriving (Eq, Ord, Show, Enum)++instance Binary DeclType where+  put_ bh b = putByte bh (fromIntegral (fromEnum b))+  get bh = do x <- getByte bh; pure $! (toEnum (fromIntegral x))+++data Scope+  = NoScope+  | LocalScope Span+  | ModuleScope+    deriving (Eq, Ord, Show, Typeable, Data)++instance Outputable Scope where+  ppr NoScope = text "NoScope"+  ppr (LocalScope sp) = text "LocalScope" <+> ppr sp+  ppr ModuleScope = text "ModuleScope"++instance Binary Scope where+  put_ bh NoScope = putByte bh 0+  put_ bh (LocalScope span) = do+    putByte bh 1+    put_ bh span+  put_ bh ModuleScope = putByte bh 2++  get bh = do+    (t :: Word8) <- get bh+    case t of+      0 -> return NoScope+      1 -> LocalScope <$> get bh+      2 -> return ModuleScope+      _ -> panic "Binary Scope: invalid tag"+++-- | Scope of a type variable.+--+-- This warrants a data type apart from 'Scope' because of complexities+-- introduced by features like @-XScopedTypeVariables@ and @-XInstanceSigs@. For+-- example, consider:+--+-- @+-- foo, bar, baz :: forall a. a -> a+-- @+--+-- Here @a@ is in scope in all the definitions of @foo@, @bar@, and @baz@, so we+-- need a list of scopes to keep track of this. Furthermore, this list cannot be+-- computed until we resolve the binding sites of @foo@, @bar@, and @baz@.+--+-- Consequently, @a@ starts with an @'UnresolvedScope' [foo, bar, baz] Nothing@+-- which later gets resolved into a 'ResolvedScopes'.+data TyVarScope+  = ResolvedScopes [Scope]++  -- | Unresolved scopes should never show up in the final @.hie@ file+  | UnresolvedScope+        [Name]        -- ^ names of the definitions over which the scope spans+        (Maybe Span)  -- ^ the location of the instance/class declaration for+                      -- the case where the type variable is declared in a+                      -- method type signature+    deriving (Eq, Ord)++instance Show TyVarScope where+  show (ResolvedScopes sc) = show sc+  show _ = error "UnresolvedScope"++instance Binary TyVarScope where+  put_ bh (ResolvedScopes xs) = do+    putByte bh 0+    put_ bh xs+  put_ bh (UnresolvedScope ns span) = do+    putByte bh 1+    put_ bh ns+    put_ bh span++  get bh = do+    (t :: Word8) <- get bh+    case t of+      0 -> ResolvedScopes <$> get bh+      1 -> UnresolvedScope <$> get bh <*> get bh+      _ -> panic "Binary TyVarScope: invalid tag"
+ src-ghc86/Development/IDE/GHC/HieUtils.hs view
@@ -0,0 +1,451 @@+{-# LANGUAGE ScopedTypeVariables #-}+{-# LANGUAGE TupleSections #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE FlexibleInstances #-}+module Development.IDE.GHC.HieUtils where++import CoreMap+import DynFlags                   ( DynFlags )+import FastString                 ( FastString, mkFastString )+import IfaceType+import Name hiding (varName)+import Outputable                 ( renderWithStyle, ppr, defaultUserStyle )+import SrcLoc+import ToIface+import TyCon+import TyCoRep+import Type+import Var+import VarEnv++import Development.IDE.GHC.HieTypes++import qualified Data.Map as M+import qualified Data.Set as S+import qualified Data.IntMap.Strict as IM+import qualified Data.Array as A+import Data.Data                  ( typeOf, typeRepTyCon, Data(toConstr) )+import Data.Maybe                 ( maybeToList )+import Data.Monoid+import Data.Traversable           ( for )+import Control.Monad.Trans.State.Strict hiding (get)+++generateReferencesMap+  :: Foldable f+  => f (HieAST a)+  -> M.Map Identifier [(Span, IdentifierDetails a)]+generateReferencesMap = foldr (\ast m -> M.unionWith (++) (go ast) m) M.empty+  where+    go ast = M.unionsWith (++) (this : map go (nodeChildren ast))+      where+        this = fmap (pure . (nodeSpan ast,)) $ nodeIdentifiers $ nodeInfo ast++renderHieType :: DynFlags -> HieTypeFix -> String+renderHieType df ht = renderWithStyle df (ppr $ hieTypeToIface ht) sty+  where sty = defaultUserStyle df++resolveVisibility :: Type -> [Type] -> [(Bool,Type)]+resolveVisibility kind ty_args+  = go (mkEmptyTCvSubst in_scope) kind ty_args+  where+    in_scope = mkInScopeSet (tyCoVarsOfTypes ty_args)++    go _   _                   []     = []+    go env ty                  ts+      | Just ty' <- coreView ty+      = go env ty' ts+    go env (ForAllTy (TvBndr tv vis) res) (t:ts)+      | isVisibleArgFlag vis = (True , t) : ts'+      | otherwise            = (False, t) : ts'+      where+        ts' = go (extendTvSubst env tv t) res ts++    go env (FunTy _ res) (t:ts) -- No type-class args in tycon apps+      = (True,t) : (go env res ts)++    go env (TyVarTy tv) ts+      | Just ki <- lookupTyVar env tv = go env ki ts+    go env kind (t:ts) = (True, t) : (go env kind ts) -- Ill-kinded++foldType :: (HieType a -> a) -> HieTypeFix -> a+foldType f (Roll t) = f $ fmap (foldType f) t++hieTypeToIface :: HieTypeFix -> IfaceType+hieTypeToIface = foldType go+  where+    go (HTyVarTy n) = IfaceTyVar $ occNameFS $ getOccName n+    go (HAppTy a b) = IfaceAppTy a b+    go (HLitTy l) = IfaceLitTy l+    go (HForAllTy ((n,k),af) t) = let b = (occNameFS $ getOccName n, k)+                                  in IfaceForAllTy (TvBndr b af) t+    go (HFunTy a b) = IfaceFunTy a b+    go (HQualTy pred b) = IfaceDFunTy pred b+    go (HCastTy a) = a+    go HCoercionTy = IfaceTyVar "<coercion type>"+    go (HTyConApp a xs) = IfaceTyConApp a (hieToIfaceArgs xs)++    -- This isn't fully faithful - we can't produce the 'Inferred' case+    hieToIfaceArgs :: HieArgs IfaceType -> IfaceTcArgs+    hieToIfaceArgs (HieArgs xs) = go' xs+      where+        go' [] = ITC_Nil+        go' ((True ,x):xs) = ITC_Vis x $ go' xs+        go' ((False,x):xs) = ITC_Invis x $ go' xs++data HieTypeState+  = HTS+    { tyMap      :: !(TypeMap TypeIndex)+    , htyTable   :: !(IM.IntMap HieTypeFlat)+    , freshIndex :: !TypeIndex+    }++initialHTS :: HieTypeState+initialHTS = HTS emptyTypeMap IM.empty 0++freshTypeIndex :: State HieTypeState TypeIndex+freshTypeIndex = do+  index <- gets freshIndex+  modify' $ \hts -> hts { freshIndex = index+1 }+  return index++compressTypes+  :: HieASTs Type+  -> (HieASTs TypeIndex, A.Array TypeIndex HieTypeFlat)+compressTypes asts = (a, arr)+  where+    (a, (HTS _ m i)) = flip runState initialHTS $+      for asts $ \typ -> do+        i <- getTypeIndex typ+        return i+    arr = A.array (0,i-1) (IM.toList m)++recoverFullType :: TypeIndex -> A.Array TypeIndex HieTypeFlat -> HieTypeFix+recoverFullType i m = go i+  where+    go i = Roll $ fmap go (m A.! i)++getTypeIndex :: Type -> State HieTypeState TypeIndex+getTypeIndex t+  | otherwise = do+      tm <- gets tyMap+      case lookupTypeMap tm t of+        Just i -> return i+        Nothing -> do+          ht <- go t+          extendHTS t ht+  where+    extendHTS t ht = do+      i <- freshTypeIndex+      modify' $ \(HTS tm tt fi) ->+        HTS (extendTypeMap tm t i) (IM.insert i ht tt) fi+      return i++    go (TyVarTy v) = return $ HTyVarTy $ varName v+    go (AppTy a b) = do+      ai <- getTypeIndex a+      bi <- getTypeIndex b+      return $ HAppTy ai bi+    go (TyConApp f xs) = do+      let visArgs = HieArgs $ resolveVisibility (tyConKind f) xs+      is <- mapM getTypeIndex visArgs+      return $ HTyConApp (toIfaceTyCon f) is+    go (ForAllTy (TvBndr v a) t) = do+      k <- getTypeIndex (varType v)+      i <- getTypeIndex t+      return $ HForAllTy ((varName v,k),a) i+    go (FunTy a b) = do+      ai <- getTypeIndex a+      bi <- getTypeIndex b+      return $ if isPredTy a+                  then HQualTy ai bi+                  else HFunTy ai bi+    go (LitTy a) = return $ HLitTy $ toIfaceTyLit a+    go (CastTy t _) = do+      i <- getTypeIndex t+      return $ HCastTy i+    go (CoercionTy _) = return HCoercionTy++resolveTyVarScopes :: M.Map FastString (HieAST a) -> M.Map FastString (HieAST a)+resolveTyVarScopes asts = M.map go asts+  where+    go ast = resolveTyVarScopeLocal ast asts++resolveTyVarScopeLocal :: HieAST a -> M.Map FastString (HieAST a) -> HieAST a+resolveTyVarScopeLocal ast asts = go ast+  where+    resolveNameScope dets = dets{identInfo =+      S.map resolveScope (identInfo dets)}+    resolveScope (TyVarBind sc (UnresolvedScope names Nothing)) =+      TyVarBind sc $ ResolvedScopes+        [ LocalScope binding+        | name <- names+        , Just binding <- [getNameBinding name asts]+        ]+    resolveScope (TyVarBind sc (UnresolvedScope names (Just sp))) =+      TyVarBind sc $ ResolvedScopes+        [ LocalScope binding+        | name <- names+        , Just binding <- [getNameBindingInClass name sp asts]+        ]+    resolveScope scope = scope+    go (Node info span children) = Node info' span $ map go children+      where+        info' = info { nodeIdentifiers = idents }+        idents = M.map resolveNameScope $ nodeIdentifiers info++getNameBinding :: Name -> M.Map FastString (HieAST a) -> Maybe Span+getNameBinding n asts = do+  (_,msp) <- getNameScopeAndBinding n asts+  msp++getNameScope :: Name -> M.Map FastString (HieAST a) -> Maybe [Scope]+getNameScope n asts = do+  (scopes,_) <- getNameScopeAndBinding n asts+  return scopes++getNameBindingInClass+  :: Name+  -> Span+  -> M.Map FastString (HieAST a)+  -> Maybe Span+getNameBindingInClass n sp asts = do+  ast <- M.lookup (srcSpanFile sp) asts+  getFirst $ foldMap First $ do+    child <- flattenAst ast+    dets <- maybeToList+      $ M.lookup (Right n) $ nodeIdentifiers $ nodeInfo child+    let binding = foldMap (First . getBindSiteFromContext) (identInfo dets)+    return (getFirst binding)++getNameScopeAndBinding+  :: Name+  -> M.Map FastString (HieAST a)+  -> Maybe ([Scope], Maybe Span)+getNameScopeAndBinding n asts = case nameSrcSpan n of+  RealSrcSpan sp -> do -- @Maybe+    ast <- M.lookup (srcSpanFile sp) asts+    defNode <- selectLargestContainedBy sp ast+    getFirst $ foldMap First $ do -- @[]+      node <- flattenAst defNode+      dets <- maybeToList+        $ M.lookup (Right n) $ nodeIdentifiers $ nodeInfo node+      scopes <- maybeToList $ foldMap getScopeFromContext (identInfo dets)+      let binding = foldMap (First . getBindSiteFromContext) (identInfo dets)+      return $ Just (scopes, getFirst binding)+  _ -> Nothing++getScopeFromContext :: ContextInfo -> Maybe [Scope]+getScopeFromContext (ValBind _ sc _) = Just [sc]+getScopeFromContext (PatternBind a b _) = Just [a, b]+getScopeFromContext (ClassTyDecl _) = Just [ModuleScope]+getScopeFromContext (Decl _ _) = Just [ModuleScope]+getScopeFromContext (TyVarBind a (ResolvedScopes xs)) = Just $ a:xs+getScopeFromContext (TyVarBind a _) = Just [a]+getScopeFromContext _ = Nothing++getBindSiteFromContext :: ContextInfo -> Maybe Span+getBindSiteFromContext (ValBind _ _ sp) = sp+getBindSiteFromContext (PatternBind _ _ sp) = sp+getBindSiteFromContext _ = Nothing++flattenAst :: HieAST a -> [HieAST a]+flattenAst n =+  n : concatMap flattenAst (nodeChildren n)++smallestContainingSatisfying+  :: Span+  -> (HieAST a -> Bool)+  -> HieAST a+  -> Maybe (HieAST a)+smallestContainingSatisfying sp cond node+  | nodeSpan node `containsSpan` sp = getFirst $ mconcat+      [ foldMap (First . smallestContainingSatisfying sp cond) $+          nodeChildren node+      , First $ if cond node then Just node else Nothing+      ]+  | sp `containsSpan` nodeSpan node = Nothing+  | otherwise = Nothing++selectLargestContainedBy :: Span -> HieAST a -> Maybe (HieAST a)+selectLargestContainedBy sp node+  | sp `containsSpan` nodeSpan node = Just node+  | nodeSpan node `containsSpan` sp =+      getFirst $ foldMap (First . selectLargestContainedBy sp) $+        nodeChildren node+  | otherwise = Nothing++selectSmallestContaining :: Span -> HieAST a -> Maybe (HieAST a)+selectSmallestContaining sp node+  | nodeSpan node `containsSpan` sp = getFirst $ mconcat+      [ foldMap (First . selectSmallestContaining sp) $ nodeChildren node+      , First (Just node)+      ]+  | sp `containsSpan` nodeSpan node = Nothing+  | otherwise = Nothing++definedInAsts :: M.Map FastString (HieAST a) -> Name -> Bool+definedInAsts asts n = case nameSrcSpan n of+  RealSrcSpan sp -> srcSpanFile sp `elem` M.keys asts+  _ -> False++isOccurrence :: ContextInfo -> Bool+isOccurrence Use = True+isOccurrence _ = False++scopeContainsSpan :: Scope -> Span -> Bool+scopeContainsSpan NoScope _ = False+scopeContainsSpan ModuleScope _ = True+scopeContainsSpan (LocalScope a) b = a `containsSpan` b++-- | One must contain the other. Leaf nodes cannot contain anything+combineAst :: HieAST Type -> HieAST Type -> HieAST Type+combineAst a@(Node aInf aSpn xs) b@(Node bInf bSpn ys)+  | aSpn == bSpn = Node (aInf `combineNodeInfo` bInf) aSpn (mergeAsts xs ys)+  | aSpn `containsSpan` bSpn = combineAst b a+combineAst a (Node xs span children) = Node xs span (insertAst a children)++-- | Insert an AST in a sorted list of disjoint Asts+insertAst :: HieAST Type -> [HieAST Type] -> [HieAST Type]+insertAst x = mergeAsts [x]++-- | Merge two nodes together.+--+-- Precondition and postcondition: elements in 'nodeType' are ordered.+combineNodeInfo :: NodeInfo Type -> NodeInfo Type -> NodeInfo Type+(NodeInfo as ai ad) `combineNodeInfo` (NodeInfo bs bi bd) =+  NodeInfo (S.union as bs) (mergeSorted ai bi) (M.unionWith (<>) ad bd)+  where+    mergeSorted :: [Type] -> [Type] -> [Type]+    mergeSorted la@(a:as) lb@(b:bs) = case nonDetCmpType a b of+                                        LT -> a : mergeSorted as lb+                                        EQ -> a : mergeSorted as bs+                                        GT -> b : mergeSorted la bs+    mergeSorted as [] = as+    mergeSorted [] bs = bs+++{- | Merge two sorted, disjoint lists of ASTs, combining when necessary.++In the absence of position-altering pragmas (ex: @# line "file.hs" 3@),+different nodes in an AST tree should either have disjoint spans (in+which case you can say for sure which one comes first) or one span+should be completely contained in the other (in which case the contained+span corresponds to some child node).++However, since Haskell does have position-altering pragmas it /is/+possible for spans to be overlapping. Here is an example of a source file+in which @foozball@ and @quuuuuux@ have overlapping spans:++@+module Baz where++# line 3 "Baz.hs"+foozball :: Int+foozball = 0++# line 3 "Baz.hs"+bar, quuuuuux :: Int+bar = 1+quuuuuux = 2+@++In these cases, we just do our best to produce sensible `HieAST`'s. The blame+should be laid at the feet of whoever wrote the line pragmas in the first place+(usually the C preprocessor...).+-}+mergeAsts :: [HieAST Type] -> [HieAST Type] -> [HieAST Type]+mergeAsts xs [] = xs+mergeAsts [] ys = ys+mergeAsts xs@(a:as) ys@(b:bs)+  | span_a `containsSpan`   span_b = mergeAsts (combineAst a b : as) bs+  | span_b `containsSpan`   span_a = mergeAsts as (combineAst a b : bs)+  | span_a `rightOf`        span_b = b : mergeAsts xs bs+  | span_a `leftOf`         span_b = a : mergeAsts as ys++  -- These cases are to work around ASTs that are not fully disjoint+  | span_a `startsRightOf`  span_b = b : mergeAsts as ys+  | otherwise                      = a : mergeAsts as ys+  where+    span_a = nodeSpan a+    span_b = nodeSpan b++rightOf :: Span -> Span -> Bool+rightOf s1 s2+  = (srcSpanStartLine s1, srcSpanStartCol s1)+       >= (srcSpanEndLine s2, srcSpanEndCol s2)+    && (srcSpanFile s1 == srcSpanFile s2)++leftOf :: Span -> Span -> Bool+leftOf s1 s2+  = (srcSpanEndLine s1, srcSpanEndCol s1)+       <= (srcSpanStartLine s2, srcSpanStartCol s2)+    && (srcSpanFile s1 == srcSpanFile s2)++startsRightOf :: Span -> Span -> Bool+startsRightOf s1 s2+  = (srcSpanStartLine s1, srcSpanStartCol s1)+       >= (srcSpanStartLine s2, srcSpanStartCol s2)++-- | combines and sorts ASTs using a merge sort+mergeSortAsts :: [HieAST Type] -> [HieAST Type]+mergeSortAsts = go . map pure+  where+    go [] = []+    go [xs] = xs+    go xss = go (mergePairs xss)+    mergePairs [] = []+    mergePairs [xs] = [xs]+    mergePairs (xs:ys:xss) = mergeAsts xs ys : mergePairs xss++simpleNodeInfo :: FastString -> FastString -> NodeInfo a+simpleNodeInfo cons typ = NodeInfo (S.singleton (cons, typ)) [] M.empty++locOnly :: SrcSpan -> [HieAST a]+locOnly (RealSrcSpan span) =+  [Node e span []]+    where e = NodeInfo S.empty [] M.empty+locOnly _ = []++mkScope :: SrcSpan -> Scope+mkScope (RealSrcSpan sp) = LocalScope sp+mkScope _ = NoScope++mkLScope :: Located a -> Scope+mkLScope = mkScope . getLoc++combineScopes :: Scope -> Scope -> Scope+combineScopes ModuleScope _ = ModuleScope+combineScopes _ ModuleScope = ModuleScope+combineScopes NoScope x = x+combineScopes x NoScope = x+combineScopes (LocalScope a) (LocalScope b) =+  mkScope $ combineSrcSpans (RealSrcSpan a) (RealSrcSpan b)++{-# INLINEABLE makeNode #-}+makeNode+  :: (Applicative m, Data a)+  => a                       -- ^ helps fill in 'nodeAnnotations' (with 'Data')+  -> SrcSpan                 -- ^ return an empty list if this is unhelpful+  -> m [HieAST b]+makeNode x spn = pure $ case spn of+  RealSrcSpan span -> [Node (simpleNodeInfo cons typ) span []]+  _ -> []+  where+    cons = mkFastString . show . toConstr $ x+    typ = mkFastString . show . typeRepTyCon . typeOf $ x++{-# INLINEABLE makeTypeNode #-}+makeTypeNode+  :: (Applicative m, Data a)+  => a                       -- ^ helps fill in 'nodeAnnotations' (with 'Data')+  -> SrcSpan                 -- ^ return an empty list if this is unhelpful+  -> Type                    -- ^ type to associate with the node+  -> m [HieAST Type]+makeTypeNode x spn etyp = pure $ case spn of+  RealSrcSpan span ->+    [Node (NodeInfo (S.singleton (cons,typ)) [etyp] M.empty) span []]+  _ -> []+  where+    cons = mkFastString . show . toConstr $ x+    typ = mkFastString . show . typeRepTyCon . typeOf $ x
+ src-ghc88/Development/IDE/GHC/HieBin.hs view
@@ -0,0 +1,389 @@+{-+Binary serialization for .hie files.+-}+{- HLINT ignore -}+{-# LANGUAGE ScopedTypeVariables #-}+module Development.IDE.GHC.HieBin ( readHieFile, readHieFileWithVersion, HieHeader, writeHieFile, HieName(..), toHieName, HieFileResult(..), hieMagic,NameCacheUpdater(..)) where++import Config                     ( cProjectVersion )+import Binary+import BinIface                   ( getDictFastString )+import FastMutInt+import FastString                 ( FastString )+import Module                     ( Module )+import Name+import NameCache+import Outputable+import PrelInfo+import SrcLoc+import UniqSupply                 ( takeUniqFromSupply )+import Util                       ( maybeRead )+import Unique+import UniqFM+import IfaceEnv++import qualified Data.Array as A+import Data.IORef+import Data.ByteString            ( ByteString )+import qualified Data.ByteString  as BS+import qualified Data.ByteString.Char8 as BSC+import Data.List                  ( mapAccumR )+import Data.Word                  ( Word8, Word32 )+import Control.Monad              ( replicateM, when )+import System.Directory           ( createDirectoryIfMissing )+import System.FilePath            ( takeDirectory )++import HieTypes++-- | `Name`'s get converted into `HieName`'s before being written into @.hie@+-- files. See 'toHieName' and 'fromHieName' for logic on how to convert between+-- these two types.+data HieName+  = ExternalName !Module !OccName !SrcSpan+  | LocalName !OccName !SrcSpan+  | KnownKeyName !Unique+  deriving (Eq)++instance Ord HieName where+  compare (ExternalName a b c) (ExternalName d e f) = compare (a,b,c) (d,e,f)+  compare (LocalName a b) (LocalName c d) = compare (a,b) (c,d)+  compare (KnownKeyName a) (KnownKeyName b) = nonDetCmpUnique a b+    -- Not actually non determinstic as it is a KnownKey+  compare ExternalName{} _ = LT+  compare LocalName{} ExternalName{} = GT+  compare LocalName{} _ = LT+  compare KnownKeyName{} _ = GT++instance Outputable HieName where+  ppr (ExternalName m n sp) = text "ExternalName" <+> ppr m <+> ppr n <+> ppr sp+  ppr (LocalName n sp) = text "LocalName" <+> ppr n <+> ppr sp+  ppr (KnownKeyName u) = text "KnownKeyName" <+> ppr u+++data HieSymbolTable = HieSymbolTable+  { hie_symtab_next :: !FastMutInt+  , hie_symtab_map  :: !(IORef (UniqFM (Int, HieName)))+  }++data HieDictionary = HieDictionary+  { hie_dict_next :: !FastMutInt -- The next index to use+  , hie_dict_map  :: !(IORef (UniqFM (Int,FastString))) -- indexed by FastString+  }++initBinMemSize :: Int+initBinMemSize = 1024*1024++-- | The header for HIE files - Capital ASCII letters "HIE".+hieMagic :: [Word8]+hieMagic = [72,73,69]++hieMagicLen :: Int+hieMagicLen = length hieMagic++ghcVersion :: ByteString+ghcVersion = BSC.pack cProjectVersion++putBinLine :: BinHandle -> ByteString -> IO ()+putBinLine bh xs = do+  mapM_ (putByte bh) $ BS.unpack xs+  putByte bh 10 -- newline char++-- | Write a `HieFile` to the given `FilePath`, with a proper header and+-- symbol tables for `Name`s and `FastString`s+writeHieFile :: FilePath -> HieFile -> IO ()+writeHieFile hie_file_path hiefile = do+  bh0 <- openBinMem initBinMemSize++  -- Write the header: hieHeader followed by the+  -- hieVersion and the GHC version used to generate this file+  mapM_ (putByte bh0) hieMagic+  putBinLine bh0 $ BSC.pack $ show hieVersion+  putBinLine bh0 $ ghcVersion++  -- remember where the dictionary pointer will go+  dict_p_p <- tellBin bh0+  put_ bh0 dict_p_p++  -- remember where the symbol table pointer will go+  symtab_p_p <- tellBin bh0+  put_ bh0 symtab_p_p++  -- Make some intial state+  symtab_next <- newFastMutInt+  writeFastMutInt symtab_next 0+  symtab_map <- newIORef emptyUFM+  let hie_symtab = HieSymbolTable {+                      hie_symtab_next = symtab_next,+                      hie_symtab_map  = symtab_map }+  dict_next_ref <- newFastMutInt+  writeFastMutInt dict_next_ref 0+  dict_map_ref <- newIORef emptyUFM+  let hie_dict = HieDictionary {+                      hie_dict_next = dict_next_ref,+                      hie_dict_map  = dict_map_ref }++  -- put the main thing+  let bh = setUserData bh0 $ newWriteState (putName hie_symtab)+                                           (putName hie_symtab)+                                           (putFastString hie_dict)+  put_ bh hiefile++  -- write the symtab pointer at the front of the file+  symtab_p <- tellBin bh+  putAt bh symtab_p_p symtab_p+  seekBin bh symtab_p++  -- write the symbol table itself+  symtab_next' <- readFastMutInt symtab_next+  symtab_map'  <- readIORef symtab_map+  putSymbolTable bh symtab_next' symtab_map'++  -- write the dictionary pointer at the front of the file+  dict_p <- tellBin bh+  putAt bh dict_p_p dict_p+  seekBin bh dict_p++  -- write the dictionary itself+  dict_next <- readFastMutInt dict_next_ref+  dict_map  <- readIORef dict_map_ref+  putDictionary bh dict_next dict_map++  -- and send the result to the file+  createDirectoryIfMissing True (takeDirectory hie_file_path)+  writeBinMem bh hie_file_path+  return ()++data HieFileResult+  = HieFileResult+  { hie_file_result_version :: Integer+  , hie_file_result_ghc_version :: ByteString+  , hie_file_result :: HieFile+  }++type HieHeader = (Integer, ByteString)++-- | Read a `HieFile` from a `FilePath`. Can use+-- an existing `NameCache`. Allows you to specify+-- which versions of hieFile to attempt to read.+-- `Left` case returns the failing header versions.+readHieFileWithVersion :: (HieHeader -> Bool) -> NameCacheUpdater -> FilePath -> IO (Either HieHeader HieFileResult)+readHieFileWithVersion readVersion ncu file = do+  bh0 <- readBinMem file++  (hieVersion, ghcVersion) <- readHieFileHeader file bh0++  if readVersion (hieVersion, ghcVersion)+  then do+    hieFile <- readHieFileContents bh0 ncu+    return $ Right (HieFileResult hieVersion ghcVersion hieFile)+  else return $ Left (hieVersion, ghcVersion)+++-- | Read a `HieFile` from a `FilePath`. Can use+-- an existing `NameCache`.+readHieFile :: NameCacheUpdater -> FilePath -> IO HieFileResult+readHieFile ncu file = do++  bh0 <- readBinMem file++  (readHieVersion, ghcVersion) <- readHieFileHeader file bh0++  -- Check if the versions match+  when (readHieVersion /= hieVersion) $+    panic $ unwords ["readHieFile: hie file versions don't match for file:"+                    , file+                    , "Expected"+                    , show hieVersion+                    , "but got", show readHieVersion+                    ]+  hieFile <- readHieFileContents bh0 ncu+  return $ HieFileResult hieVersion ghcVersion hieFile++readBinLine :: BinHandle -> IO ByteString+readBinLine bh = BS.pack . reverse <$> loop []+  where+    loop acc = do+      char <- get bh :: IO Word8+      if char == 10 -- ASCII newline '\n'+      then return acc+      else loop (char : acc)++readHieFileHeader :: FilePath -> BinHandle -> IO HieHeader+readHieFileHeader file bh0 = do+  -- Read the header+  magic <- replicateM hieMagicLen (get bh0)+  version <- BSC.unpack <$> readBinLine bh0+  case maybeRead version of+    Nothing ->+      panic $ unwords ["readHieFileHeader: hieVersion isn't an Integer:"+                      , show version+                      ]+    Just readHieVersion -> do+      ghcVersion <- readBinLine bh0++      -- Check if the header is valid+      when (magic /= hieMagic) $+        panic $ unwords ["readHieFileHeader: headers don't match for file:"+                        , file+                        , "Expected"+                        , show hieMagic+                        , "but got", show magic+                        ]+      return (readHieVersion, ghcVersion)++readHieFileContents :: BinHandle -> NameCacheUpdater -> IO HieFile+readHieFileContents bh0 ncu = do++  dict  <- get_dictionary bh0++  -- read the symbol table so we are capable of reading the actual data+  bh1 <- do+      let bh1 = setUserData bh0 $ newReadState (error "getSymtabName")+                                               (getDictFastString dict)+      symtab <- get_symbol_table bh1+      let bh1' = setUserData bh1+               $ newReadState (getSymTabName symtab)+                              (getDictFastString dict)+      return bh1'++  -- load the actual data+  hiefile <- get bh1+  return hiefile+  where+    get_dictionary bin_handle = do+      dict_p <- get bin_handle+      data_p <- tellBin bin_handle+      seekBin bin_handle dict_p+      dict <- getDictionary bin_handle+      seekBin bin_handle data_p+      return dict++    get_symbol_table bh1 = do+      symtab_p <- get bh1+      data_p'  <- tellBin bh1+      seekBin bh1 symtab_p+      symtab <- getSymbolTable bh1 ncu+      seekBin bh1 data_p'+      return symtab++putFastString :: HieDictionary -> BinHandle -> FastString -> IO ()+putFastString HieDictionary { hie_dict_next = j_r,+                              hie_dict_map  = out_r}  bh f+  = do+    out <- readIORef out_r+    let unique = getUnique f+    case lookupUFM out unique of+        Just (j, _)  -> put_ bh (fromIntegral j :: Word32)+        Nothing -> do+           j <- readFastMutInt j_r+           put_ bh (fromIntegral j :: Word32)+           writeFastMutInt j_r (j + 1)+           writeIORef out_r $! addToUFM out unique (j, f)++putSymbolTable :: BinHandle -> Int -> UniqFM (Int,HieName) -> IO ()+putSymbolTable bh next_off symtab = do+  put_ bh next_off+  let names = A.elems (A.array (0,next_off-1) (nonDetEltsUFM symtab))+  mapM_ (putHieName bh) names++getSymbolTable :: BinHandle -> NameCacheUpdater -> IO SymbolTable+getSymbolTable bh ncu = do+  sz <- get bh+  od_names <- replicateM sz (getHieName bh)+  updateNameCache ncu $ \nc ->+    let arr = A.listArray (0,sz-1) names+        (nc', names) = mapAccumR fromHieName nc od_names+        in (nc',arr)++getSymTabName :: SymbolTable -> BinHandle -> IO Name+getSymTabName st bh = do+  i :: Word32 <- get bh+  return $ st A.! (fromIntegral i)++putName :: HieSymbolTable -> BinHandle -> Name -> IO ()+putName (HieSymbolTable next ref) bh name = do+  symmap <- readIORef ref+  case lookupUFM symmap name of+    Just (off, ExternalName mod occ (UnhelpfulSpan _))+      | isGoodSrcSpan (nameSrcSpan name) -> do+      let hieName = ExternalName mod occ (nameSrcSpan name)+      writeIORef ref $! addToUFM symmap name (off, hieName)+      put_ bh (fromIntegral off :: Word32)+    Just (off, LocalName _occ span)+      | notLocal (toHieName name) || nameSrcSpan name /= span -> do+      writeIORef ref $! addToUFM symmap name (off, toHieName name)+      put_ bh (fromIntegral off :: Word32)+    Just (off, _) -> put_ bh (fromIntegral off :: Word32)+    Nothing -> do+        off <- readFastMutInt next+        writeFastMutInt next (off+1)+        writeIORef ref $! addToUFM symmap name (off, toHieName name)+        put_ bh (fromIntegral off :: Word32)++  where+    notLocal :: HieName -> Bool+    notLocal LocalName{} = False+    notLocal _ = True+++-- ** Converting to and from `HieName`'s++toHieName :: Name -> HieName+toHieName name+  | isKnownKeyName name = KnownKeyName (nameUnique name)+  | isExternalName name = ExternalName (nameModule name)+                                       (nameOccName name)+                                       (nameSrcSpan name)+  | otherwise = LocalName (nameOccName name) (nameSrcSpan name)++fromHieName :: NameCache -> HieName -> (NameCache, Name)+fromHieName nc (ExternalName mod occ span) =+    let cache = nsNames nc+    in case lookupOrigNameCache cache mod occ of+         Just name+           | nameSrcSpan name == span -> (nc, name)+           | otherwise ->+             let name' = setNameLoc name span+                 new_cache = extendNameCache cache mod occ name'+             in ( nc{ nsNames = new_cache }, name' )+         Nothing ->+           let (uniq, us) = takeUniqFromSupply (nsUniqs nc)+               name       = mkExternalName uniq mod occ span+               new_cache  = extendNameCache cache mod occ name+           in ( nc{ nsUniqs = us, nsNames = new_cache }, name )+fromHieName nc (LocalName occ span) =+    let (uniq, us) = takeUniqFromSupply (nsUniqs nc)+        name       = mkInternalName uniq occ span+    in ( nc{ nsUniqs = us }, name )+fromHieName nc (KnownKeyName u) = case lookupKnownKeyName u of+    Nothing -> pprPanic "fromHieName:unknown known-key unique"+                        (ppr (unpkUnique u))+    Just n -> (nc, n)++-- ** Reading and writing `HieName`'s++putHieName :: BinHandle -> HieName -> IO ()+putHieName bh (ExternalName mod occ span) = do+  putByte bh 0+  put_ bh (mod, occ, span)+putHieName bh (LocalName occName span) = do+  putByte bh 1+  put_ bh (occName, span)+putHieName bh (KnownKeyName uniq) = do+  putByte bh 2+  put_ bh $ unpkUnique uniq++getHieName :: BinHandle -> IO HieName+getHieName bh = do+  t <- getByte bh+  case t of+    0 -> do+      (modu, occ, span) <- get bh+      return $ ExternalName modu occ span+    1 -> do+      (occ, span) <- get bh+      return $ LocalName occ span+    2 -> do+      (c,i) <- get bh+      return $ KnownKeyName $ mkUnique c i+    _ -> panic "HieBin.getHieName: invalid tag"
src/Development/IDE/Core/Compile.hs view
@@ -12,6 +12,7 @@   , RunSimplifier(..)   , compileModule   , parseModule+  , parseHeader   , typecheckModule   , computePackageDeps   , addRelativeImport@@ -24,6 +25,9 @@   , loadInterface   , loadDepModule   , loadModuleHome+  , setupFinderCache+  , getDocsBatch+  , lookupName   ) where  import Development.IDE.Core.RuleTypes@@ -37,13 +41,12 @@ import qualified GHC.LanguageExtensions.Type as GHC import Development.IDE.Types.Options import Development.IDE.Types.Location-import Outputable  #if MIN_GHC_API_VERSION(8,6,0)-import           DynamicLoading (initializePlugins)+import DynamicLoading (initializePlugins)+import LoadIface (loadModuleInterface) #endif -import           GHC hiding (parseModule, typecheckModule) import qualified Parser import           Lexer #if MIN_GHC_API_VERSION(8,10,0)@@ -52,18 +55,16 @@ #endif  import           Finder+import           Development.IDE.GHC.Compat hiding (parseModule, typecheckModule) import qualified Development.IDE.GHC.Compat     as GHC import qualified Development.IDE.GHC.Compat     as Compat import           GhcMonad import           GhcPlugins                     as GHC hiding (fst3, (<>)) import qualified HeaderInfo                     as Hdr import           HscMain                        (hscInteractive, hscSimplify)-import           LoadIface                      (readIface)-import qualified Maybes import           MkIface-import           NameCache import           StringBuffer                   as SB-import           TcRnMonad (initIfaceLoad, tcg_th_coreplugins)+import           TcRnMonad (tct_id, TcTyThing(AGlobal, ATcId), initTc, initIfaceLoad, tcg_th_coreplugins) import           TcIface                        (typecheckIface) import           TidyPgm @@ -80,10 +81,11 @@ import           System.FilePath import           System.Directory import           System.IO.Extra-import Data.Either.Extra (maybeToEither) import Control.DeepSeq (rnf) import Control.Exception (evaluate) import Exception (ExceptionMonad)+import TcEnv (tcLookup)+import Data.Time (UTCTime)   -- | Given a string buffer, return the string (after preprocessing) and the 'ParsedModule'.@@ -92,13 +94,14 @@     -> HscEnv     -> [PackageName]     -> FilePath+    -> UTCTime     -> Maybe SB.StringBuffer     -> IO (IdeResult (StringBuffer, ParsedModule))-parseModule IdeOptions{..} env comp_pkgs filename mbContents =+parseModule IdeOptions{..} env comp_pkgs filename modTime mbContents =     fmap (either (, Nothing) id) $     evalGhcEnv env $ runExceptT $ do         (contents, dflags) <- preprocessor filename mbContents-        (diag, modu) <- parseFileContents optPreprocessor dflags comp_pkgs filename contents+        (diag, modu) <- parseFileContents optPreprocessor dflags comp_pkgs filename modTime contents         return (diag, Just (contents, modu))  @@ -116,24 +119,16 @@  typecheckModule :: IdeDefer                 -> HscEnv-                -> [(ModSummary, (ModIface, Maybe Linkable))]                 -> ParsedModule                 -> IO (IdeResult (HscEnv, TcModuleResult))-typecheckModule (IdeDefer defer) hsc depsIn pm = do+typecheckModule (IdeDefer defer) hsc pm = do     fmap (either (, Nothing) (second Just . sequence) . sequence) $       runGhcEnv hsc $       catchSrcErrors "typecheck" $ do-        -- Currently GetDependencies returns things in topological order so A comes before B if A imports B.-        -- We need to reverse this as GHC gets very unhappy otherwise and complains about broken interfaces.-        -- Long-term we might just want to change the order returned by GetDependencies-        let deps = reverse depsIn -        setupFinderCache (map fst deps)-         let modSummary = pm_mod_summary pm             dflags = ms_hspp_opts modSummary -        mapM_ (uncurry loadDepModule . snd) deps         modSummary' <- initPlugins modSummary         (warnings, tcm) <- withWarnings "typecheck" $ \tweak ->             GHC.typecheckModule $ enableTopLevelWarnings@@ -416,10 +411,12 @@ getModSummaryFromBuffer     :: GhcMonad m     => FilePath+    -> UTCTime     -> DynFlags     -> GHC.ParsedSource+    -> StringBuffer     -> ExceptT [FileDiagnostic] m ModSummary-getModSummaryFromBuffer fp dflags parsed = do+getModSummaryFromBuffer fp modTime dflags parsed contents = do   (modName, imports) <- liftEither $ getImportsParsed dflags parsed    modLoc <- liftIO $ mkHomeModLocation dflags modName fp@@ -427,15 +424,17 @@   return $ ModSummary     { ms_mod          = mkModule (fsToUnitId unitId) modName     , ms_location     = modLoc-    , ms_hs_date      = error "Rules should not depend on ms_hs_date"-        -- When we are working with a virtual file we do not have a file date.-        -- To avoid silent issues where something is not processed because the date-        -- has not changed, we make sure that things blow up if they depend on the-        -- date.+    , ms_hs_date      = modTime     , ms_textual_imps = [imp | (False, imp) <- imports]     , ms_hspp_file    = fp     , ms_hspp_opts    = dflags-    , ms_hspp_buf     = Nothing+        -- NOTE: It's /vital/ we set the 'StringBuffer' here, to give any+        -- registered GHC plugins access to the /updated/ in-memory content+        -- of a module being edited. Without this line, any plugin wishing to+        -- parse an input module and perform operations on the /current/ state+        -- of a file wouldn't work properly, as it would \"see\" a stale view of+        -- the file (i.e., the on-disk content of the latter).+    , ms_hspp_buf     = Just contents      -- defaults:     , ms_hsc_src      = sourceType@@ -455,9 +454,10 @@ getModSummaryFromImports   :: (HasDynFlags m, ExceptionMonad m, MonadIO m)   => FilePath+  -> UTCTime   -> Maybe SB.StringBuffer   -> ExceptT [FileDiagnostic] m ModSummary-getModSummaryFromImports fp contents = do+getModSummaryFromImports fp modTime contents = do     (contents, dflags) <- preprocessor fp contents     (srcImports, textualImports, L _ moduleName) <-         ExceptT $ liftIO $ first (diagFromErrMsgs "parser" dflags) <$> GHC.getHeaderImports dflags contents fp fp@@ -476,12 +476,10 @@ #if MIN_GHC_API_VERSION(8,8,0)                 , ms_hie_date     = Nothing #endif-                , ms_hs_date      = error "Rules should not depend on ms_hs_date"-        -- When we are working with a virtual file we do not have a file date.-        -- To avoid silent issues where something is not processed because the date-        -- has not changed, we make sure that things blow up if they depend on the date.+                , ms_hs_date      = modTime                 , ms_hsc_src      = sourceType-                , ms_hspp_buf     = Nothing+                -- The contents are used by the GetModSummary rule+                , ms_hspp_buf     = Just contents                 , ms_hspp_file    = fp                 , ms_hspp_opts    = dflags                 , ms_iface_date   = Nothing@@ -493,7 +491,40 @@                 }     return summary +-- | Parse only the module header+parseHeader+       :: GhcMonad m+       => DynFlags -- ^ flags to use+       -> FilePath  -- ^ the filename (for source locations)+       -> SB.StringBuffer -- ^ Haskell module source text (full Unicode is supported)+       -> ExceptT [FileDiagnostic] m ([FileDiagnostic], Located(HsModule GhcPs))+parseHeader dflags filename contents = do+   let loc  = mkRealSrcLoc (mkFastString filename) 1 1+   case unP Parser.parseHeader (mkPState dflags contents loc) of+#if MIN_GHC_API_VERSION(8,10,0)+     PFailed pst ->+        throwE $ diagFromErrMsgs "parser" dflags $ getErrorMessages pst dflags+#else+     PFailed _ locErr msgErr ->+        throwE $ diagFromErrMsg "parser" dflags $ mkPlainErrMsg dflags locErr msgErr+#endif+     POk pst rdr_module -> do+        let (warns, errs) = getMessages pst dflags+        -- Just because we got a `POk`, it doesn't mean there+        -- weren't errors! To clarify, the GHC parser+        -- distinguishes between fatal and non-fatal+        -- errors. Non-fatal errors are the sort that don't+        -- prevent parsing from continuing (that is, a parse+        -- tree can still be produced despite the error so that+        -- further errors/warnings can be collected). Fatal+        -- errors are those from which a parse tree just can't+        -- be produced.+        unless (null errs) $+            throwE $ diagFromErrMsgs "parser" dflags errs +        let warnings = diagFromErrMsgs "parser" dflags warns+        return (warnings, rdr_module)+ -- | Given a buffer, flags, and file path, produce a -- parsed module (or errors) and any parse warnings. Does not run any preprocessors parseFileContents@@ -502,9 +533,10 @@        -> DynFlags -- ^ flags to use        -> [PackageName] -- ^ The package imports to ignore        -> FilePath  -- ^ the filename (for source locations)+       -> UTCTime   -- ^ the modification timestamp        -> SB.StringBuffer -- ^ Haskell module source text (full Unicode is supported)        -> ExceptT [FileDiagnostic] m ([FileDiagnostic], ParsedModule)-parseFileContents customPreprocessor dflags comp_pkgs filename contents = do+parseFileContents customPreprocessor dflags comp_pkgs filename modTime contents = do    let loc  = mkRealSrcLoc (mkFastString filename) 1 1    case unP Parser.parseModule (mkPState dflags contents loc) of #if MIN_GHC_API_VERSION(8,10,0)@@ -531,14 +563,14 @@                -- errors are those from which a parse tree just can't                -- be produced.                unless (null errs) $-                 throwE $ diagFromErrMsgs "parser" dflags $ snd $ getMessages pst dflags+                 throwE $ diagFromErrMsgs "parser" dflags errs                 -- Ok, we got here. It's safe to continue.                let IdePreprocessedSource preproc_warns errs parsed = customPreprocessor rdr_module                unless (null errs) $ throwE $ diagFromStrings "parser" DsError errs                let parsed' = removePackageImports comp_pkgs parsed                let preproc_warnings = diagFromStrings "parser" DsWarning preproc_warns-               ms <- getModSummaryFromBuffer filename dflags parsed'+               ms <- getModSummaryFromBuffer filename modTime dflags parsed' contents                let pm =                      ParsedModule {                          pm_mod_summary = ms@@ -564,35 +596,92 @@     do_one_import l = l #endif -loadHieFile :: FilePath -> IO GHC.HieFile-loadHieFile f = do-        u <- mkSplitUniqSupply 'a'-        let nameCache = initNameCache u []-        fmap (GHC.hie_file_result . fst) $ GHC.readHieFile nameCache f+loadHieFile :: Compat.NameCacheUpdater -> FilePath -> IO GHC.HieFile+loadHieFile ncu f = do+  GHC.hie_file_result <$> GHC.readHieFile ncu f --- | Retuns an up-to-date module interface if available.+-- | Retuns an up-to-date module interface, regenerating if needed. --   Assumes file exists. --   Requires the 'HscEnv' to be set up with dependencies loadInterface-  :: HscEnv+  :: MonadIO m => HscEnv   -> ModSummary-  -> [HiFileResult]-  -> IO (Either String ModIface)-loadInterface session ms deps = do-  let hiFile = case ms_hsc_src ms of-                HsBootFile -> addBootSuffix (ml_hi_file $ ms_location ms)-                _ -> ml_hi_file $ ms_location ms-  r <- initIfaceLoad session $ readIface (ms_mod ms) hiFile-  case r of-    Maybes.Succeeded iface -> do-      session' <- foldM (\e d -> loadDepModuleIO (hirModIface d) Nothing e) session deps-      (reason, iface') <- checkOldIface session' ms SourceUnmodified (Just iface)-      return $ maybeToEither (showReason reason) iface'-    Maybes.Failed err -> do-      let errMsg = showSDoc (hsc_dflags session) err-      return $ Left errMsg+  -> SourceModified+  -> m ([FileDiagnostic], Maybe HiFileResult) -- ^ Action to regenerate an interface+  -> m ([FileDiagnostic], Maybe HiFileResult)+loadInterface session ms sourceMod regen = do+    res <- liftIO $ checkOldIface session ms sourceMod Nothing+    case res of+          (UpToDate, Just x)+            -- If the module used TH splices when it was last+            -- compiled, then the recompilation check is not+            -- accurate enough (https://gitlab.haskell.org/ghc/ghc/-/issues/481)+            -- and we must ignore+            -- it.  However, if the module is stable (none of+            -- the modules it depends on, directly or+            -- indirectly, changed), then we *can* skip+            -- recompilation. This is why the SourceModified+            -- type contains SourceUnmodifiedAndStable, and+            -- it's pretty important: otherwise ghc --make+            -- would always recompile TH modules, even if+            -- nothing at all has changed. Stability is just+            -- the same check that make is doing for us in+            -- one-shot mode.+            | not (mi_used_th x) || SourceUnmodifiedAndStable == sourceMod+            -> return ([], Just $ HiFileResult ms x)+          (_reason, _) -> regen -showReason :: RecompileRequired -> String-showReason MustCompile = "Stale"-showReason (RecompBecause reason) = "Stale (" ++ reason ++ ")"-showReason UpToDate = "Up to date"+-- | Non-interactive, batch version of 'InteractiveEval.getDocs'.+--   The interactive paths create problems in ghc-lib builds+--- and leads to fun errors like "Cannot continue after interface file error".+getDocsBatch :: GhcMonad m+        => Module  -- ^ a moudle where the names are in scope+        -> [Name]+        -> m [Either String (Maybe HsDocString, Map.Map Int HsDocString)]+getDocsBatch _mod _names =+#if MIN_GHC_API_VERSION(8,6,0)+  withSession $ \hsc_env -> liftIO $ do+    ((_warns,errs), res) <- initTc hsc_env HsSrcFile False _mod fakeSpan $ forM _names $ \name ->+        case nameModule_maybe name of+            Nothing -> return (Left $ NameHasNoModule name)+            Just mod -> do+             ModIface { mi_doc_hdr = mb_doc_hdr+                      , mi_decl_docs = DeclDocMap dmap+                      , mi_arg_docs = ArgDocMap amap+                      } <- loadModuleInterface "getModuleInterface" mod+             if isNothing mb_doc_hdr && Map.null dmap && Map.null amap+               then pure (Left (NoDocsInIface mod $ compiled name))+               else pure (Right ( Map.lookup name dmap+                                , Map.findWithDefault Map.empty name amap))+    case res of+        Just x -> return $ map (first prettyPrint) x+        Nothing -> throwErrors errs+  where+    throwErrors = liftIO . throwIO . mkSrcErr+    compiled n =+      -- TODO: Find a more direct indicator.+      case nameSrcLoc n of+        RealSrcLoc {} -> False+        UnhelpfulLoc {} -> True+#else+    return []+#endif++fakeSpan :: RealSrcSpan+fakeSpan = realSrcLocSpan $ mkRealSrcLoc (fsLit "<ghcide>") 1 1++-- | Non-interactive, batch version of 'InteractiveEval.lookupNames'.+--   The interactive paths create problems in ghc-lib builds+--- and leads to fun errors like "Cannot continue after interface file error".+lookupName :: GhcMonad m+           => Module -- ^ A module where the Names are in scope+           -> Name+           -> m (Maybe TyThing)+lookupName mod name = withSession $ \hsc_env -> liftIO $ do+    (_messages, res) <- initTc hsc_env HsSrcFile False mod fakeSpan $ do+        tcthing <- tcLookup name+        case tcthing of+            AGlobal thing    -> return thing+            ATcId{tct_id=id} -> return (AnId id)+            _ -> panic "tcRnLookupName'"+    return res
src/Development/IDE/Core/Debouncer.hs view
@@ -39,6 +39,11 @@ -- Events are run unmasked so it is up to the user of `registerEvent` -- to mask if required. asyncRegisterEvent :: (Eq k, Hashable k) => Var (HashMap k (Async ())) -> Seconds -> k -> IO () -> IO ()+asyncRegisterEvent d 0 k fire = do+    modifyVar_ d $ \m -> mask_ $ do+        whenJust (Map.lookup k m) cancel+        pure $ Map.delete k m+    fire asyncRegisterEvent d delay k fire = modifyVar_ d $ \m -> mask_ $ do     whenJust (Map.lookup k m) cancel     a <- asyncWithUnmask $ \unmask -> unmask $ do
src/Development/IDE/Core/FileStore.hs view
@@ -7,8 +7,10 @@     getFileContents,     getVirtualFile,     setBufferModified,+    setFileModified,     setSomethingModified,     fileStoreRules,+    modificationTime,     VFSHandle,     makeVFSHandle,     makeLSPVFSHandle@@ -26,16 +28,20 @@ import           Control.Exception import           GHC.Generics import Data.Either.Extra+import Data.Int (Int64)+import Data.Time import System.IO.Error import qualified Data.ByteString.Char8 as BS import Development.IDE.Types.Diagnostics import Development.IDE.Types.Location+import Development.IDE.Core.OfInterest (kick)+import Development.IDE.Core.RuleTypes import qualified Data.Rope.UTF16 as Rope  #ifdef mingw32_HOST_OS-import Data.Time import qualified System.Directory as Dir #else+import Data.Time.Clock.System (systemToUTCTime, SystemTime(MkSystemTime)) import Foreign.Ptr import Foreign.C.String import Foreign.C.Types@@ -44,6 +50,8 @@ import qualified System.Posix.Error as Posix #endif +import qualified Development.IDE.Types.Logger as L+ import Language.Haskell.LSP.Core import Language.Haskell.LSP.VFS @@ -93,7 +101,7 @@  getModificationTimeRule :: VFSHandle -> Rules () getModificationTimeRule vfs =-    defineEarlyCutoff $ \GetModificationTime file -> do+    defineEarlyCutoff $ \(GetModificationTime_ missingFileDiags) file -> do         let file' = fromNormalizedFilePath file         let wrap time@(l,s) = (Just $ BS.pack $ show time, ([], Just $ ModificationTime l s))         alwaysRerun@@ -105,7 +113,10 @@               `catch` \(e :: IOException) -> do                 let err | isDoesNotExistError e = "File does not exist: " ++ file'                         | otherwise = "IO error while reading " ++ file' ++ ", " ++ displayException e-                return (Nothing, ([ideErrorText file $ T.pack err], Nothing))+                    diag = ideErrorText file (T.pack err)+                if isDoesNotExistError e && not missingFileDiags+                    then return (Nothing, ([], Nothing))+                    else return (Nothing, ([diag], Nothing))   where     -- Dir.getModificationTime is surprisingly slow since it performs     -- a ton of conversions. Since we do not actually care about@@ -116,7 +127,7 @@     -- We might also want to try speeding this up on Windows at some point.     -- TODO leverage DidChangeWatchedFile lsp notifications on clients that     -- support them, as done for GetFileExists-    getModTime :: FilePath -> IO (Int,Int)+    getModTime :: FilePath -> IO (Int64, Int64)     getModTime f = #ifdef mingw32_HOST_OS         do time <- Dir.getModificationTime f@@ -128,15 +139,24 @@         alloca $ \secPtr ->         alloca $ \nsecPtr -> do             Posix.throwErrnoPathIfMinus1Retry_ "getmodtime" f $ c_getModTime f' secPtr nsecPtr-            sec <- peek secPtr-            nsec <- peek nsecPtr-            pure (fromEnum sec, fromIntegral nsec)+            CTime sec <- peek secPtr+            CLong nsec <- peek nsecPtr+            pure (sec, nsec)  -- Sadly even unix’s getFileStatus + modificationTimeHiRes is still about twice as slow -- as doing the FFI call ourselves :(. foreign import ccall "getmodtime" c_getModTime :: CString -> Ptr CTime -> Ptr CLong -> IO Int #endif +modificationTime :: FileVersion -> Maybe UTCTime+modificationTime VFSVersion{} = Nothing+modificationTime (ModificationTime large small) =+#ifdef mingw32_HOST_OS+    Just (UTCTime (ModifiedJulianDay $ fromIntegral large) (picosecondsToDiffTime $ fromIntegral small))+#else+    Just (systemToUTCTime $ MkSystemTime large (fromIntegral small))+#endif+ getFileContentsRule :: VFSHandle -> Rules () getFileContentsRule vfs =     define $ \GetFileContents file -> do@@ -155,9 +175,13 @@       (\(e :: IOException) -> ideErrorText fp $ T.pack $ show e)       <$> try act --getFileContents :: NormalizedFilePath -> Action (FileVersion, Maybe T.Text)-getFileContents = use_ GetFileContents+-- | Returns the modification time and the contents.+--   For VFS paths, the modification time is the current time.+getFileContents :: NormalizedFilePath -> Action (UTCTime, Maybe T.Text)+getFileContents f = do+    (fv, txt) <- use_ GetFileContents f+    modTime <- maybe (liftIO getCurrentTime) return $ modificationTime fv+    return (modTime, txt)  fileStoreRules :: VFSHandle -> Rules () fileStoreRules vfs = do@@ -174,8 +198,22 @@     VFSHandle{..} <- getIdeGlobalState state     whenJust setVirtualFileContents $ \set ->         set (filePathToUri' absFile) contents-    void $ shakeRun state []+    void $ shakeRestart state [kick] +-- | Note that some buffer for a specific file has been modified but not+-- with what changes.+setFileModified :: IdeState -> NormalizedFilePath -> IO ()+setFileModified state nfp = do+    VFSHandle{..} <- getIdeGlobalState state+    when (isJust setVirtualFileContents) $+        fail "setSomethingModified can't be called on this type of VFSHandle"+    let da = mkDelayedAction "FileStoreTC" L.Info $ do+          ShakeExtras{progressUpdate} <- getShakeExtras+          liftIO $ progressUpdate KickStarted+          void $ use GetSpanInfo nfp+          liftIO $ progressUpdate KickCompleted+    shakeRestart state [da]+ -- | Note that some buffer somewhere has been modified, but don't say what. --   Only valid if the virtual file system was initialised by LSP, as that --   independently tracks which files are modified.@@ -184,4 +222,4 @@     VFSHandle{..} <- getIdeGlobalState state     when (isJust setVirtualFileContents) $         fail "setSomethingModified can't be called on this type of VFSHandle"-    void $ shakeRun state []+    void $ shakeRestart state [kick]
src/Development/IDE/Core/OfInterest.hs view
@@ -9,6 +9,7 @@ module Development.IDE.Core.OfInterest(     ofInterestRules,     getFilesOfInterest, setFilesOfInterest, modifyFilesOfInterest,+    kick     ) where  import Control.Concurrent.Extra@@ -23,13 +24,13 @@ import qualified Data.HashSet as HashSet import qualified Data.Text as T import Data.Tuple.Extra-import Data.Functor import Development.Shake  import Development.IDE.Types.Location import Development.IDE.Types.Logger+import Development.IDE.Core.RuleTypes import Development.IDE.Core.Shake-+import Control.Monad  newtype OfInterestVar = OfInterestVar (Var (HashSet NormalizedFilePath)) instance IsIdeGlobal OfInterestVar@@ -79,4 +80,15 @@     OfInterestVar var <- getIdeGlobalState state     files <- modifyVar var $ pure . dupe . f     logDebug (ideLogger state) $ "Set files of interest to: " <> T.pack (show $ HashSet.toList files)-    void $ shakeRun state []+    let das = map (\nfp -> mkDelayedAction "OfInterest" Debug (use GetSpanInfo nfp)) (HashSet.toList files)+    shakeRestart state das++-- | Typecheck all the files of interest.+--   Could be improved+kick :: DelayedAction ()+kick = mkDelayedAction "kick" Debug $ do+    files <- getFilesOfInterest+    ShakeExtras{progressUpdate} <- getShakeExtras+    liftIO $ progressUpdate KickStarted+    void $ uses TypeCheck $ HashSet.toList files+    liftIO $ progressUpdate KickCompleted
src/Development/IDE/Core/RuleTypes.hs view
@@ -14,6 +14,7 @@ import           Control.DeepSeq import Data.Binary import           Development.IDE.Import.DependencyInformation+import Development.IDE.GHC.Compat import Development.IDE.GHC.Util import           Data.Hashable import           Data.Typeable@@ -21,12 +22,12 @@ import           Development.Shake import           GHC.Generics                             (Generic) -import           GHC import Module (InstalledUnitId)-import HscTypes (CgGuts, Linkable, HomeModInfo, ModDetails)+import HscTypes (hm_iface, CgGuts, Linkable, HomeModInfo, ModDetails)  import           Development.IDE.Spans.Type import           Development.IDE.Import.FindImports (ArtifactsLocation)+import Data.ByteString (ByteString)   -- NOTATION@@ -67,6 +68,15 @@     , hirModIface :: !ModIface     } +tmr_hiFileResult :: TcModuleResult -> HiFileResult+tmr_hiFileResult tmr = HiFileResult modSummary modIface+  where+    modIface = hm_iface . tmrModInfo $ tmr+    modSummary = tmrModSummary tmr++hiFileFingerPrint :: HiFileResult -> ByteString+hiFileFingerPrint = fingerprintToBS . getModuleHash . hirModIface+ instance NFData HiFileResult where     rnf = rwhnf @@ -88,6 +98,9 @@ -- | A GHC session that we reuse. type instance RuleResult GhcSession = HscEnvEq +-- | A GHC session preloaded with all the dependencies+type instance RuleResult GhcSessionDeps = HscEnvEq+ -- | Resolve the imports in a module to the file path of a module -- in the same package or the package id of another package. type instance RuleResult GetLocatedImports = ([(Located ModuleName, Maybe ArtifactsLocation)], S.Set InstalledUnitId)@@ -97,10 +110,11 @@ -- we can only report diagnostics for the current file. type instance RuleResult ReportImportCycles = () --- | Read the module interface file-type instance RuleResult GetHiFile = HiFileResult+-- | Read the module interface file from disk. Throws an error for VFS files.+--   This is an internal rule, use 'GetModIface' instead.+type instance RuleResult GetModIfaceFromDisk = HiFileResult --- | Get a module interface, either from an interface file or a typechecked module+-- | Get a module interface details, either from an interface file or a typechecked module type instance RuleResult GetModIface = HiFileResult  type instance RuleResult IsFileOfInterest = Bool@@ -109,6 +123,10 @@ -- without needing to parse the entire source type instance RuleResult GetModSummary = ModSummary +-- | Generate a ModSummary with the timestamps elided,+--   for more successful early cutoff+type instance RuleResult GetModSummaryWithoutTimestamps = ModSummary+ data GetParsedModule = GetParsedModule     deriving (Eq, Show, Typeable, Generic) instance Hashable GetParsedModule@@ -169,11 +187,16 @@ instance NFData   GhcSession instance Binary   GhcSession -data GetHiFile = GetHiFile+data GhcSessionDeps = GhcSessionDeps deriving (Eq, Show, Typeable, Generic)+instance Hashable GhcSessionDeps+instance NFData   GhcSessionDeps+instance Binary   GhcSessionDeps++data GetModIfaceFromDisk = GetModIfaceFromDisk     deriving (Eq, Show, Typeable, Generic)-instance Hashable GetHiFile-instance NFData   GetHiFile-instance Binary   GetHiFile+instance Hashable GetModIfaceFromDisk+instance NFData   GetModIfaceFromDisk+instance Binary   GetModIfaceFromDisk  data GetModIface = GetModIface     deriving (Eq, Show, Typeable, Generic)@@ -186,6 +209,12 @@ instance Hashable IsFileOfInterest instance NFData   IsFileOfInterest instance Binary   IsFileOfInterest++data GetModSummaryWithoutTimestamps = GetModSummaryWithoutTimestamps+    deriving (Eq, Show, Typeable, Generic)+instance Hashable GetModSummaryWithoutTimestamps+instance NFData   GetModSummaryWithoutTimestamps+instance Binary   GetModSummaryWithoutTimestamps  data GetModSummary = GetModSummary     deriving (Eq, Show, Typeable, Generic)
src/Development/IDE/Core/Rules.hs view
@@ -12,15 +12,18 @@ -- module Development.IDE.Core.Rules(     IdeState, GetDependencies(..), GetParsedModule(..), TransitiveDependencies(..),-    Priority(..), GhcSessionIO(..), GhcSessionFun(..),+    Priority(..), GhcSessionIO(..),     priorityTypeCheck,     priorityGenerateCore,     priorityFilesOfInterest,     runAction, useE, useNoFileE, usesE,-    toIdeResult, defineNoFile,+    toIdeResult,+    defineNoFile,+    defineEarlyCutOffNoFile,     mainRule,     getAtPoint,     getDefinition,+    getTypeDefinition,     getDependencies,     getParsedModule,     generateCore,@@ -29,7 +32,7 @@ import Fingerprint  import Data.Binary hiding (get, put)-import Data.Bifunctor (first, second)+import Data.Tuple.Extra import Control.Monad.Extra import Control.Monad.Trans.Class import Control.Monad.Trans.Maybe@@ -40,19 +43,19 @@ import Development.IDE.Import.DependencyInformation import Development.IDE.Import.FindImports import           Development.IDE.Core.FileExists-import           Development.IDE.Core.FileStore        (getFileContents)-import           Development.IDE.Types.Diagnostics+import           Development.IDE.Core.FileStore        (modificationTime, getFileContents)+import           Development.IDE.Types.Diagnostics as Diag import Development.IDE.Types.Location import Development.IDE.GHC.Compat hiding (parseModule, typecheckModule) import Development.IDE.GHC.Util import Development.IDE.GHC.WithDynFlags import Data.Either.Extra+import qualified Development.IDE.Types.Logger as L import Data.Maybe import           Data.Foldable import qualified Data.IntMap.Strict as IntMap import Data.IntMap.Strict (IntMap) import Data.List-import Data.Ord import qualified Data.Set                                 as Set import qualified Data.Text                                as T import           Development.IDE.GHC.Error@@ -60,6 +63,7 @@ import Development.IDE.Core.RuleTypes import Development.IDE.Spans.Type import qualified Data.ByteString.Char8 as BS+import Development.IDE.Core.PositionMapping  import qualified GHC.LanguageExtensions as LangExt import HscTypes@@ -74,8 +78,15 @@ import Control.Monad.Trans.Except (runExceptT) import Data.ByteString (ByteString) import Control.Concurrent.Async (concurrently)+import System.Time.Extra+import Control.Monad.Reader+import System.Directory ( getModificationTime )+import Control.Exception  import Control.Monad.State+import FastString (FastString(uniq))+import qualified HeaderInfo as Hdr+import Data.Time (UTCTime(..))  -- | This is useful for rules to convert rules that can only produce errors or -- a result into the more general IdeResult type that supports producing@@ -85,21 +96,26 @@  -- | useE is useful to implement functions that aren’t rules but need shortcircuiting -- e.g. getDefinition.-useE :: IdeRule k v => k -> NormalizedFilePath -> MaybeT Action v-useE k = MaybeT . use k+useE :: IdeRule k v => k -> NormalizedFilePath -> MaybeT IdeAction (v, PositionMapping)+useE k = MaybeT . useWithStaleFast k -useNoFileE :: IdeRule k v => k -> MaybeT Action v-useNoFileE k = useE k emptyFilePath+useNoFileE :: IdeRule k v => IdeState -> k -> MaybeT IdeAction v+useNoFileE _ide k = fst <$> useE k emptyFilePath -usesE :: IdeRule k v => k -> [NormalizedFilePath] -> MaybeT Action [v]-usesE k = MaybeT . fmap sequence . uses k+usesE :: IdeRule k v => k -> [NormalizedFilePath] -> MaybeT IdeAction [(v,PositionMapping)]+usesE k = MaybeT . fmap sequence . mapM (useWithStaleFast k)  defineNoFile :: IdeRule k v => (k -> Action v) -> Rules () defineNoFile f = define $ \k file -> do     if file == emptyFilePath then do res <- f k; return ([], Just res) else         fail $ "Rule " ++ show k ++ " should always be called with the empty string for a file" +defineEarlyCutOffNoFile :: IdeRule k v => (k -> Action (ByteString, v)) -> Rules ()+defineEarlyCutOffNoFile f = defineEarlyCutoff $ \k file -> do+    if file == emptyFilePath then do (hash, res) <- f k; return (Just hash, ([], Just res)) else+        fail $ "Rule " ++ show k ++ " should always be called with the empty string for a file" + ------------------------------------------------------------ -- Exposed API @@ -109,56 +125,80 @@ getDependencies file = fmap transitiveModuleDeps <$> use GetDependencies file  -- | Try to get hover text for the name under point.-getAtPoint :: NormalizedFilePath -> Position -> Action (Maybe (Maybe Range, [T.Text]))+getAtPoint :: NormalizedFilePath -> Position -> IdeAction (Maybe (Maybe Range, [T.Text])) getAtPoint file pos = fmap join $ runMaybeT $ do-  opts <- lift getIdeOptions-  spans <- useE GetSpanInfo file-  return $ AtPoint.atPoint opts spans pos+  ide <- ask+  opts <- liftIO $ getIdeOptionsIO ide+  (spans, mapping) <- useE  GetSpanInfo file+  !pos' <- MaybeT (return $ fromCurrentPosition mapping pos)+  return $ AtPoint.atPoint opts spans pos'  -- | Goto Definition.-getDefinition :: NormalizedFilePath -> Position -> Action (Maybe Location)-getDefinition file pos = fmap join $ runMaybeT $ do-    opts <- lift getIdeOptions-    spans <- useE GetSpanInfo file-    lift $ AtPoint.gotoDefinition (getHieFile file) opts (spansExprs spans) pos+getDefinition :: NormalizedFilePath -> Position -> IdeAction (Maybe Location)+getDefinition file pos = runMaybeT $ do+    ide <- ask+    opts <- liftIO $ getIdeOptionsIO ide+    (spans,mapping) <- useE GetSpanInfo file+    !pos' <- MaybeT (return $ fromCurrentPosition mapping pos)+    AtPoint.gotoDefinition (getHieFile ide file) opts (spansExprs spans) pos' +getTypeDefinition :: NormalizedFilePath -> Position -> IdeAction (Maybe [Location])+getTypeDefinition file pos = runMaybeT $ do+    ide <- ask+    opts <- liftIO $ getIdeOptionsIO ide+    (spans,mapping) <- useE GetSpanInfo file+    !pos' <- MaybeT (return $ fromCurrentPosition mapping pos)+    AtPoint.gotoTypeDefinition (getHieFile ide file) opts (spansExprs spans) pos'+ getHieFile-  :: NormalizedFilePath -- ^ file we're editing+  :: ShakeExtras+  -> NormalizedFilePath -- ^ file we're editing   -> Module -- ^ module dep we want info for-  -> Action (Maybe (HieFile, FilePath)) -- ^ hie stuff for the module-getHieFile file mod = do-  TransitiveDependencies {transitiveNamedModuleDeps} <- use_ GetDependencies file+  -> MaybeT IdeAction (HieFile, FilePath) -- ^ hie stuff for the module+getHieFile ide file mod = do+  TransitiveDependencies {transitiveNamedModuleDeps} <- fst <$> useE GetDependencies file   case find (\x -> nmdModuleName x == moduleName mod) transitiveNamedModuleDeps of     Just NamedModuleDep{nmdFilePath=nfp} -> do         let modPath = fromNormalizedFilePath nfp-        (_diags, hieFile) <- getHomeHieFile nfp-        return $ (, modPath) <$> hieFile-    _ -> getPackageHieFile mod file-+        hieFile <- getHomeHieFile nfp+        return (hieFile, modPath)+    _ -> getPackageHieFile ide mod file -getHomeHieFile :: NormalizedFilePath -> Action ([a], Maybe HieFile)+getHomeHieFile :: NormalizedFilePath -> MaybeT IdeAction HieFile getHomeHieFile f = do-  ms <- use_ GetModSummary f+  ms <- fst <$> useE GetModSummaryWithoutTimestamps f   let normal_hie_f = toNormalizedFilePath' hie_f       hie_f = ml_hie_file $ ms_location ms-  mbHieTimestamp <- use GetModificationTime normal_hie_f-  srcTimestamp   <- use_ GetModificationTime f++  mbHieTimestamp <- either (\(_ :: IOException) -> Nothing) Just <$> (liftIO $ try $ getModificationTime hie_f)+  srcTimestamp   <- MaybeT (either (\(_ :: IOException) -> Nothing) Just <$> (liftIO $ try $ getModificationTime $ fromNormalizedFilePath f))+  liftIO $ print (mbHieTimestamp, srcTimestamp, hie_f, normal_hie_f)   let isUpToDate-        | Just d <- mbHieTimestamp = comparing modificationTime d srcTimestamp == GT+        | Just d <- mbHieTimestamp = d > srcTimestamp         | otherwise = False -  unless isUpToDate $-       void $ use_ TypeCheck f+  if isUpToDate+    then do+      ncu <- mkUpdater+      hf <- liftIO $ whenMaybe isUpToDate (loadHieFile ncu hie_f)+      MaybeT $ return hf+    else do+      wait <- lift $ delayedAction $ mkDelayedAction "OutOfDateHie" L.Info $ do+        hsc <- hscEnv <$> use_ GhcSession f+        pm <- use_ GetParsedModule f+        typeCheckRuleDefinition hsc pm DoGenerateInterfaceFiles+      _ <- MaybeT $ liftIO $ timeout 1 wait+      ncu <- mkUpdater+      liftIO $ loadHieFile ncu hie_f -  hf <- liftIO $ whenMaybe isUpToDate (loadHieFile hie_f)-  return ([], hf) -getPackageHieFile :: Module             -- ^ Package Module to load .hie file for+getPackageHieFile :: ShakeExtras+                  -> Module             -- ^ Package Module to load .hie file for                   -> NormalizedFilePath -- ^ Path of home module importing the package module-                  -> Action (Maybe (HieFile, FilePath))-getPackageHieFile mod file = do-    pkgState  <- hscEnv <$> use_ GhcSession file-    IdeOptions {..} <- getIdeOptions+                  -> MaybeT IdeAction (HieFile, FilePath)+getPackageHieFile ide mod file = do+    pkgState  <- hscEnv . fst <$> useE GhcSession file+    IdeOptions {..} <- liftIO $ getIdeOptionsIO ide     let unitId = moduleUnitId mod     case lookupPackageConfig unitId pkgState of         Just pkgConfig -> do@@ -166,12 +206,13 @@             hieFile <- liftIO $ optLocateHieFile optPkgLocationOpts pkgConfig mod             path    <- liftIO $ optLocateSrcFile optPkgLocationOpts pkgConfig mod             case (hieFile, path) of-                (Just hiePath, Just modPath) ->+                (Just hiePath, Just modPath) -> do                     -- deliberately loaded outside the Shake graph                     -- to avoid dependencies on non-workspace files-                        liftIO $ Just . (, modPath) <$> loadHieFile hiePath-                _ -> return Nothing-        _ -> return Nothing+                        ncu <- mkUpdater+                        MaybeT $ liftIO $ Just . (, modPath) <$> loadHieFile ncu hiePath+                _ -> MaybeT $ return Nothing+        _ -> MaybeT $ return Nothing  -- | Parse the contents of a daml file. getParsedModule :: NormalizedFilePath -> Action (Maybe ParsedModule)@@ -198,33 +239,52 @@         -- parsed module         comp_pkgs = mapMaybe (fmap fst . mkImportDirs (hsc_dflags hsc)) (deps sess)     opt <- getIdeOptions-    (_, contents) <- getFileContents file+    (modTime, contents) <- getFileContents file      let dflags    = hsc_dflags hsc-        mainParse = getParsedModuleDefinition hsc opt comp_pkgs file contents+        mainParse = getParsedModuleDefinition hsc opt comp_pkgs file modTime contents      -- Parse again (if necessary) to capture Haddock parse errors     if gopt Opt_Haddock dflags         then             liftIO mainParse         else do-            let hscHaddock = hsc{hsc_dflags = gopt_set dflags Opt_Haddock}-                haddockParse = do+            let haddockParse = do                     (_, (!diagsHaddock, _)) <--                        getParsedModuleDefinition hscHaddock opt comp_pkgs file contents+                        getParsedModuleDefinition (withOptHaddock hsc) opt comp_pkgs file modTime contents                     return diagsHaddock              ((fingerPrint, (diags, res)), diagsHaddock) <-                 -- parse twice, with and without Haddocks, concurrently-                -- we cannot ignore Haddock parse errors because files of-                -- non-interest are always parsed with Haddocks+                -- we want warnings if parsing with Haddock fails+                -- but if we parse with Haddock we lose annotations                 liftIO $ concurrently mainParse haddockParse -            return (fingerPrint, (mergeDiagnostics diags diagsHaddock, res))+            return (fingerPrint, (mergeParseErrorsHaddock diags diagsHaddock, res)) -getParsedModuleDefinition :: HscEnv -> IdeOptions -> [PackageName] -> NormalizedFilePath -> Maybe T.Text -> IO (Maybe ByteString, ([FileDiagnostic], Maybe ParsedModule))-getParsedModuleDefinition packageState opt comp_pkgs file contents = do-    (diag, res) <- parseModule opt packageState comp_pkgs (fromNormalizedFilePath file) (fmap textToStringBuffer contents)++withOptHaddock :: HscEnv -> HscEnv+withOptHaddock hsc = hsc{hsc_dflags = gopt_set (hsc_dflags hsc) Opt_Haddock}+++-- | Given some normal parse errors (first) and some from Haddock (second), merge them.+--   Ignore Haddock errors that are in both. Demote Haddock-only errors to warnings.+mergeParseErrorsHaddock :: [FileDiagnostic] -> [FileDiagnostic] -> [FileDiagnostic]+mergeParseErrorsHaddock normal haddock = normal +++    [ (a,b,c{_severity = Just DsWarning, _message = fixMessage $ _message c})+    | (a,b,c) <- haddock, Diag._range c `Set.notMember` locations]+  where+    locations = Set.fromList $ map (Diag._range . thd3) normal++    fixMessage x | "parse error " `T.isPrefixOf` x = "Haddock " <> x+                 | otherwise = "Haddock: " <> x+++getParsedModuleDefinition :: HscEnv -> IdeOptions -> [PackageName] -> NormalizedFilePath -> UTCTime -> Maybe T.Text -> IO (Maybe ByteString, ([FileDiagnostic], Maybe ParsedModule))+getParsedModuleDefinition packageState opt comp_pkgs file modTime contents = do+    let fp = fromNormalizedFilePath file+        buffer = textToStringBuffer <$> contents+    (diag, res) <- parseModule opt packageState comp_pkgs fp modTime buffer     case res of         Nothing -> pure (Nothing, (diag, Nothing))         Just (contents, modu) -> do@@ -236,7 +296,7 @@ getLocatedImportsRule :: Rules () getLocatedImportsRule =     define $ \GetLocatedImports file -> do-        ms <- use_ GetModSummary file+        ms <- use_ GetModSummaryWithoutTimestamps file         let imports = [(False, imp) | imp <- ms_textual_imps ms] ++ [(True, imp) | imp <- ms_srcimps ms]         env_eq <- use_ GhcSession file         let env = hscEnv env_eq@@ -282,7 +342,7 @@       -- If we have, just return its Id but don't update any of the state.       -- Otherwise, we need to process its imports.       checkAlreadyProcessed f $ do-          al <- lift $ modSummaryToArtifactsLocation f <$> use_ GetModSummary f+          al <- lift $ modSummaryToArtifactsLocation f <$> use_ GetModSummaryWithoutTimestamps f           -- Get a fresh FilePathId for the new file           fId <- getFreshFid al           -- Adding an edge to the bootmap so we can make sure to@@ -393,7 +453,7 @@             where loc = srcSpanToLocation (getLoc imp)                   fp = toNormalizedFilePath' $ srcSpanToFilename (getLoc imp)           getModuleName file = do-           ms <- use_ GetModSummary file+           ms <- use_ GetModSummaryWithoutTimestamps file            pure (moduleNameString . moduleName . ms_mod $ ms)           showCycle mods  = T.intercalate ", " (map T.pack mods) @@ -414,31 +474,31 @@ getSpanInfoRule =     define $ \GetSpanInfo file -> do         tc <- use_ TypeCheck file-        packageState <- hscEnv <$> use_ GhcSession file-        deps <- maybe (TransitiveDependencies [] [] []) fst <$> useWithStale GetDependencies file-        let tdeps = transitiveModuleDeps deps+        packageState <- hscEnv <$> use_ GhcSessionDeps file  -- When possible, rely on the haddocks embedded in our interface files -- This creates problems on ghc-lib, see comment on 'getDocumentationTryGhc' #if MIN_GHC_API_VERSION(8,6,0) && !defined(GHC_LIB)         let parsedDeps = [] #else-        parsedDeps <- uses_ GetParsedModule tdeps+        deps <- maybe (TransitiveDependencies [] [] []) fst <$> useWithStale GetDependencies file+        let tdeps = transitiveModuleDeps deps+        parsedDeps <- mapMaybe (fmap fst) <$> usesWithStale GetParsedModule tdeps #endif -        ifaces <- uses_ GetModIface tdeps         (fileImports, _) <- use_ GetLocatedImports file         let imports = second (fmap artifactFilePath) <$> fileImports-        x <- liftIO $ getSrcSpanInfos packageState imports tc parsedDeps (map hirModIface ifaces)+        x <- liftIO $ getSrcSpanInfos packageState imports tc parsedDeps         return ([], Just x)  -- Typechecks a module. typeCheckRule :: Rules () typeCheckRule = define $ \TypeCheck file -> do     pm <- use_ GetParsedModule file+    hsc  <- hscEnv <$> use_ GhcSessionDeps file     -- do not generate interface files as this rule is called     -- for files of interest on every keystroke-    typeCheckRuleDefinition file pm SkipGenerationOfInterfaceFiles+    typeCheckRuleDefinition hsc pm SkipGenerationOfInterfaceFiles  data GenerateInterfaceFiles     = DoGenerateInterfaceFiles@@ -450,29 +510,16 @@ -- garbage collect all the intermediate typechecked modules rather than -- retain the information forever in the shake graph. typeCheckRuleDefinition-    :: NormalizedFilePath     -- ^ Path to source file+    :: HscEnv     -> ParsedModule     -> GenerateInterfaceFiles -- ^ Should generate .hi and .hie files ?     -> Action (IdeResult TcModuleResult)-typeCheckRuleDefinition file pm generateArtifacts = do-  deps <- use_ GetDependencies file-  hsc  <- hscEnv <$> use_ GhcSession file-  -- Figure out whether we need TemplateHaskell or QuasiQuotes support-  let graph_needs_th_qq = needsTemplateHaskellOrQQ $ hsc_mod_graph hsc-      file_uses_th_qq   = uses_th_qq $ ms_hspp_opts (pm_mod_summary pm)-      any_uses_th_qq    = graph_needs_th_qq || file_uses_th_qq-  mirs      <- uses_ GetModIface (transitiveModuleDeps deps)-  bytecodes <- if any_uses_th_qq-    then -- If we use TH or QQ, we must obtain the bytecode-      fmap Just <$> uses_ GenerateByteCode (transitiveModuleDeps deps)-    else-      pure $ repeat Nothing-+typeCheckRuleDefinition hsc pm generateArtifacts = do   setPriority priorityTypeCheck   IdeOptions { optDefer = defer } <- getIdeOptions    addUsageDependencies $ liftIO $ do-    res <- typecheckModule defer hsc (zipWith unpack mirs bytecodes) pm+    res <- typecheckModule defer hsc pm     case res of       (diags, Just (hsc,tcm)) | DoGenerateInterfaceFiles <- generateArtifacts -> do         diagsHie <- generateAndWriteHieFile hsc (tmrModule tcm)@@ -481,10 +528,6 @@       (diags, res) ->         return (diags, snd <$> res)  where-  unpack HiFileResult{..} bc = (hirModSummary, (hirModIface, bc))-  uses_th_qq dflags =-    xopt LangExt.TemplateHaskell dflags || xopt LangExt.QuasiQuotes dflags-   addUsageDependencies :: Action (a, Maybe TcModuleResult) -> Action (a, Maybe TcModuleResult)   addUsageDependencies a = do     r@(_, mtc) <- a@@ -522,33 +565,36 @@ -- A local rule type to get caching. We want to use newCache, but it has -- thread killed exception issues, so we lift it to a full rule. -- https://github.com/digital-asset/daml/pull/2808#issuecomment-529639547-type instance RuleResult GhcSessionIO = GhcSessionFun+type instance RuleResult GhcSessionIO = IdeGhcSession  data GhcSessionIO = GhcSessionIO deriving (Eq, Show, Typeable, Generic) instance Hashable GhcSessionIO instance NFData   GhcSessionIO instance Binary   GhcSessionIO -newtype GhcSessionFun = GhcSessionFun (FilePath -> Action (IdeResult HscEnvEq))-instance Show GhcSessionFun where show _ = "GhcSessionFun"-instance NFData GhcSessionFun where rnf !_ = ()-- loadGhcSession :: Rules () loadGhcSession = do-    defineNoFile $ \GhcSessionIO -> do+    -- This function should always be rerun because it tracks changes+    -- to the version of the collection of HscEnv's.+    defineEarlyCutOffNoFile $ \GhcSessionIO -> do+        alwaysRerun         opts <- getIdeOptions-        GhcSessionFun <$> optGhcSession opts-    -- This function should always be rerun because it consults a cache to-    -- see what HscEnv needs to be used for the file, which can change.-    -- However, it should also cut-off early if it's the same HscEnv as-    -- last time+        res <- optGhcSession opts++        let fingerprint = hash (sessionVersion res)+        return (BS.pack (show fingerprint), res)+     defineEarlyCutoff $ \GhcSession file -> do-        GhcSessionFun fun <- useNoFile_ GhcSessionIO-        alwaysRerun-        val <- fun $ fromNormalizedFilePath file+        IdeGhcSession{loadSessionFun} <- useNoFile_ GhcSessionIO+        (val,deps) <- liftIO $ loadSessionFun $ fromNormalizedFilePath file -        -- TODO: What was this doing before?+        -- add the deps to the Shake graph+        let addDependency fp = do+                let nfp = toNormalizedFilePath' fp+                itExists <- getFileExists nfp+                when itExists $ void $ use_ GetModificationTime nfp+        mapM_ addDependency deps+         opts <- getIdeOptions         let cutoffHash =               case optShakeFiles opts of@@ -560,92 +606,178 @@                 Nothing -> BS.pack (show (hash (snd val)))         return (Just cutoffHash, val) -getHiFileRule :: Rules ()-getHiFileRule = defineEarlyCutoff $ \GetHiFile f -> do-  -- get all dependencies interface files, to check for freshness-  (deps,_) <- use_ GetLocatedImports f-  depHis  <- traverse (use GetHiFile) (mapMaybe (fmap artifactFilePath . snd) deps)+    define $ \GhcSessionDeps file -> ghcSessionDepsDefinition file +ghcSessionDepsDefinition :: NormalizedFilePath -> Action (IdeResult HscEnvEq)+ghcSessionDepsDefinition file = do+        hsc <- hscEnv <$> use_ GhcSession file+        (ms,_) <- useWithStale_ GetModSummaryWithoutTimestamps file+        (deps,_) <- useWithStale_ GetDependencies file+        let tdeps = transitiveModuleDeps deps+        ifaces <- uses_ GetModIface tdeps++        -- Figure out whether we need TemplateHaskell or QuasiQuotes support+        let graph_needs_th_qq = needsTemplateHaskellOrQQ $ hsc_mod_graph hsc+            file_uses_th_qq   = uses_th_qq $ ms_hspp_opts ms+            any_uses_th_qq    = graph_needs_th_qq || file_uses_th_qq++        bytecodes <- if any_uses_th_qq+            then -- If we use TH or QQ, we must obtain the bytecode+            fmap Just <$> uses_ GenerateByteCode (transitiveModuleDeps deps)+            else+            pure $ repeat Nothing++        -- Currently GetDependencies returns things in topological order so A comes before B if A imports B.+        -- We need to reverse this as GHC gets very unhappy otherwise and complains about broken interfaces.+        -- Long-term we might just want to change the order returned by GetDependencies+        let inLoadOrder = reverse (zipWith unpack ifaces bytecodes)++        (session',_) <- liftIO $ runGhcEnv hsc $ do+            setupFinderCache (map hirModSummary ifaces)+            mapM_ (uncurry loadDepModule) inLoadOrder++        res <- liftIO $ newHscEnvEq session' []+        return ([], Just res)+ where+  unpack HiFileResult{..} bc = (hirModIface, bc)+  uses_th_qq dflags =+    xopt LangExt.TemplateHaskell dflags || xopt LangExt.QuasiQuotes dflags++getModIfaceFromDiskRule :: Rules ()+getModIfaceFromDiskRule = defineEarlyCutoff $ \GetModIfaceFromDisk f -> do   ms <- use_ GetModSummary f-  let hiFile = toNormalizedFilePath'-             $ case ms_hsc_src ms of-                HsBootFile -> addBootSuffix (ml_hi_file $ ms_location ms)-                _ -> ml_hi_file $ ms_location ms+  (diags_session, mb_session) <- ghcSessionDepsDefinition f+  case mb_session of+      Nothing -> return (Nothing, (diags_session, Nothing))+      Just session -> do+        sourceModified <- use_ IsHiFileStable f+        r <- loadInterface (hscEnv session) ms sourceModified (regenerateHiFile session f)+        case r of+            (diags, Just x) -> do+                let fp = Just (hiFileFingerPrint x)+                return (fp, (diags <> diags_session, Just x))+            (diags, Nothing) -> return (Nothing, (diags ++ diags_session, Nothing)) -  case sequence depHis of-    Nothing -> pure (Nothing, ([], Nothing))-    Just deps -> do-      gotHiFile <- getFileExists hiFile-      if not gotHiFile-        then pure (Nothing, ([], Nothing))-        else do-          hiVersion  <- use_ GetModificationTime hiFile-          modVersion <- use_ GetModificationTime f-          let sourceModified = modificationTime hiVersion < modificationTime modVersion-          if sourceModified-            then do-              pure (Nothing, ([], Nothing))-            else do-              session <- hscEnv <$> use_ GhcSession f-              r <- liftIO $ loadInterface session ms deps-              case r of-                Right iface -> do-                  let result = HiFileResult ms iface-                  return (Just (fingerprintToBS (getModuleHash iface)), ([], Just result))-                Left err -> do-                  let diag = ideErrorWithSource (Just "interface file loading") (Just DsError) f . T.pack $ err-                  return (Nothing, (pure diag, Nothing))+isHiFileStableRule :: Rules ()+isHiFileStableRule = define $ \IsHiFileStable f -> do+    ms <- use_ GetModSummaryWithoutTimestamps f+    let hiFile = toNormalizedFilePath'+                $ case ms_hsc_src ms of+                    HsBootFile -> addBootSuffix (ml_hi_file $ ms_location ms)+                    _ -> ml_hi_file $ ms_location ms+    mbHiVersion <- use  GetModificationTime_{missingFileDiagnostics=False} hiFile+    modVersion  <- use_ GetModificationTime f+    sourceModified <- case mbHiVersion of+        Nothing -> pure SourceModified+        Just x ->+            if modificationTime x < modificationTime modVersion+                then pure SourceModified+                else do+                    (fileImports, _) <- use_ GetLocatedImports f+                    let imports = fmap artifactFilePath . snd <$> fileImports+                    deps <- uses_ IsHiFileStable (catMaybes imports)+                    pure $ if all (== SourceUnmodifiedAndStable) deps+                        then SourceUnmodifiedAndStable+                        else SourceUnmodified+    return ([], Just sourceModified)  getModSummaryRule :: Rules ()-getModSummaryRule = define $ \GetModSummary f -> do-    dflags <- hsc_dflags . hscEnv <$> use_ GhcSession f-    (_, mFileContent) <- getFileContents f-    modS <- liftIO $ evalWithDynFlags dflags $ runExceptT $-        getModSummaryFromImports (fromNormalizedFilePath f) (textToStringBuffer <$> mFileContent)-    return $ either (,Nothing) (([], ) . Just) modS+getModSummaryRule = do+    defineEarlyCutoff $ \GetModSummary f -> do+        dflags <- hsc_dflags . hscEnv <$> use_ GhcSession f+        (modTime, mFileContent) <- getFileContents f+        let fp = fromNormalizedFilePath f+        modS <- liftIO $ evalWithDynFlags dflags $ runExceptT $+                getModSummaryFromImports fp modTime (textToStringBuffer <$> mFileContent)+        case modS of+            Right ms -> do+                let fingerPrint = hash (computeFingerprint f dflags ms, hashUTC modTime)+                return ( Just (BS.pack $ show fingerPrint) , ([], Just ms))+            Left diags -> return (Nothing, (diags, Nothing)) +    defineEarlyCutoff $ \GetModSummaryWithoutTimestamps f -> do+        ms <- use GetModSummary f+        case ms of+            Just msWithTimestamps -> do+                let ms = msWithTimestamps { ms_hs_date = error "use GetModSummary instead of GetModSummaryWithoutTimestamps" }+                dflags <- hsc_dflags . hscEnv <$> use_ GhcSession f+                -- include the mod time in the fingerprint+                let fp = BS.pack $ show $ hash (computeFingerprint f dflags ms)+                return (Just fp, ([], Just ms))+            Nothing -> return (Nothing, ([], Nothing))+    where+        -- Compute a fingerprint from the contents of `ModSummary`,+        -- eliding the timestamps and other non relevant fields.+        computeFingerprint f dflags ModSummary{..} =+            let fingerPrint =+                    ( moduleNameString (moduleName ms_mod)+                    , ms_hspp_file+                    , map unLoc opts+                    , ml_hs_file ms_location+                    , fingerPrintImports ms_srcimps+                    , fingerPrintImports ms_textual_imps+                    )+                fingerPrintImports = map (fmap uniq *** (moduleNameString . unLoc))+                opts = Hdr.getOptions dflags (fromJust ms_hspp_buf) (fromNormalizedFilePath f)+            in fingerPrint++        hashUTC UTCTime{..} = (fromEnum utctDay, fromEnum utctDayTime)+ getModIfaceRule :: Rules ()-getModIfaceRule = define $ \GetModIface f -> do+getModIfaceRule = defineEarlyCutoff $ \GetModIface f -> do+#if MIN_GHC_API_VERSION(8,6,0) && !defined(GHC_LIB)     fileOfInterest <- use_ IsFileOfInterest f-    let useHiFile =-          -- Never load interface files for files of interest-          not fileOfInterest-    mbHiFile <- if useHiFile then use GetHiFile f else return Nothing-    case mbHiFile of-        Just x ->-            return ([], Just x)-        Nothing-          | fileOfInterest -> do-            -- For files of interest only, create a Shake dependency on typecheck+    if fileOfInterest+        then do+            -- Never load from disk for files of interest             tmr <- use TypeCheck f-            return ([], extract tmr)-          | otherwise -> do-            -- the interface file does not exist or is out of date.+            let !hiFile = extractHiFileResult tmr+            let fp = hiFileFingerPrint <$> hiFile+            return (fp, ([], hiFile))+        else do+            hiFile <- use GetModIfaceFromDisk f+            let fp = hiFileFingerPrint <$> hiFile+            return (fp, ([], hiFile))+#else+    tm <- use TypeCheck f+    let !hiFile = extractHiFileResult tm+    let fp = hiFileFingerPrint <$> hiFile+    return (fp, ([], tmr_hiFileResult <$> tm))+#endif++regenerateHiFile :: HscEnvEq -> NormalizedFilePath -> Action ([FileDiagnostic], Maybe HiFileResult)+regenerateHiFile sess f = do+    let hsc = hscEnv sess+        -- After parsing the module remove all package imports referring to+        -- these packages as we have already dealt with what they map to.+        comp_pkgs = mapMaybe (fmap fst . mkImportDirs (hsc_dflags hsc)) (deps sess)+    opt <- getIdeOptions+    (modTime, contents) <- getFileContents f++    -- Embed haddocks in the interface file+    (_, (diags, mb_pm)) <- liftIO $ getParsedModuleDefinition (withOptHaddock hsc) opt comp_pkgs f modTime contents+    (diags, mb_pm) <- case mb_pm of+        Just _ -> return (diags, mb_pm)+        Nothing -> do+            -- if parsing fails, try parsing again with Haddock turned off+            (_, (diagsNoHaddock, mb_pm)) <- liftIO $ getParsedModuleDefinition hsc opt comp_pkgs f modTime contents+            return (mergeParseErrorsHaddock diagsNoHaddock diags, mb_pm)+    case mb_pm of+        Nothing -> return (diags, Nothing)+        Just pm -> do             -- Invoke typechecking directly to update it without incurring a dependency             -- on the parsed module and the typecheck rules-            sess <- use_ GhcSession f-            let hsc = hscEnv sess-                -- After parsing the module remove all package imports referring to-                -- these packages as we have already dealt with what they map to.-                comp_pkgs = mapMaybe (fmap fst . mkImportDirs (hsc_dflags hsc)) (deps sess)-            opt <- getIdeOptions-            (_, contents) <- getFileContents f-            -- Embed --haddocks in the interface file-            hsc <- pure hsc{hsc_dflags = gopt_set (hsc_dflags hsc) Opt_Haddock}-            (_, (diags, mb_pm)) <- liftIO $ getParsedModuleDefinition hsc opt comp_pkgs f contents-            case mb_pm of-                Nothing -> return (diags, Nothing)-                Just pm -> do-                    (diags', tmr) <- typeCheckRuleDefinition f pm DoGenerateInterfaceFiles-                    -- Bang pattern is important to avoid leaking 'tmr'-                    let !res = extract tmr-                    return (diags <> diags', res)-    where-      extract Nothing = Nothing-      extract (Just tmr) =-        -- Bang patterns are important to force the inner fields-        Just $! HiFileResult (tmrModSummary tmr) (hm_iface $ tmrModInfo tmr)+            (diags', tmr) <- typeCheckRuleDefinition hsc pm DoGenerateInterfaceFiles+            -- Bang pattern is important to avoid leaking 'tmr'+            let !res = extractHiFileResult tmr+            return (diags <> diags', res) +extractHiFileResult :: Maybe TcModuleResult -> Maybe HiFileResult+extractHiFileResult Nothing = Nothing+extractHiFileResult (Just tmr) =+    -- Bang patterns are important to force the inner fields+    Just $! tmr_hiFileResult tmr+ isFileOfInterestRule :: Rules () isFileOfInterestRule = defineEarlyCutoff $ \IsFileOfInterest f -> do     filesOfInterest <- getFilesOfInterest@@ -665,7 +797,19 @@     generateCoreRule     generateByteCodeRule     loadGhcSession-    getHiFileRule+    getModIfaceFromDiskRule     getModIfaceRule     isFileOfInterestRule     getModSummaryRule+    isHiFileStableRule++-- | Given the path to a module src file, this rule returns True if the+-- corresponding `.hi` file is stable, that is, if it is newer+--   than the src file, and all its dependencies are stable too.+data IsHiFileStable = IsHiFileStable+    deriving (Eq, Show, Typeable, Generic)+instance Hashable IsHiFileStable+instance NFData   IsHiFileStable+instance Binary   IsHiFileStable++type instance RuleResult IsHiFileStable = SourceModified
src/Development/IDE/Core/Service.hs view
@@ -3,44 +3,38 @@  {-# LANGUAGE TypeFamilies               #-} {-# LANGUAGE FlexibleInstances #-}+{-# LANGUAGE RankNTypes #-}  -- | A Shake implementation of the compiler service, built --   using the "Shaker" abstraction layer for in-memory use. -- module Development.IDE.Core.Service(-    getIdeOptions,+    getIdeOptions, getIdeOptionsIO,     IdeState, initialise, shutdown,     runAction,-    runActionSync,     writeProfile,     getDiagnostics, unsafeClearDiagnostics,     ideLogger,     updatePositionMapping,     ) where -import           Control.Concurrent.Extra-import           Control.Concurrent.Async import Data.Maybe import Development.IDE.Types.Options (IdeOptions(..))-import Control.Monad import Development.IDE.Core.Debouncer import           Development.IDE.Core.FileStore  (VFSHandle, fileStoreRules) import           Development.IDE.Core.FileExists (fileExistsRules) import           Development.IDE.Core.OfInterest-import Development.IDE.Types.Logger+import Development.IDE.Types.Logger as Logger import           Development.Shake-import Data.Either.Extra import qualified Language.Haskell.LSP.Messages as LSP import qualified Language.Haskell.LSP.Types as LSP import qualified Language.Haskell.LSP.Types.Capabilities as LSP  import           Development.IDE.Core.Shake+import Control.Monad   -newtype GlobalIdeOptions = GlobalIdeOptions IdeOptions-instance IsIdeGlobal GlobalIdeOptions- ------------------------------------------------------------ -- Exposed API @@ -49,19 +43,24 @@            -> Rules ()            -> IO LSP.LspId            -> (LSP.FromServerMessage -> IO ())+           -> WithProgressFunc+           -> WithIndefiniteProgressFunc            -> Logger            -> Debouncer LSP.NormalizedUri            -> IdeOptions            -> VFSHandle            -> IO IdeState-initialise caps mainRule getLspId toDiags logger debouncer options vfs =+initialise caps mainRule getLspId toDiags wProg wIndefProg logger debouncer options vfs =     shakeOpen         getLspId         toDiags+        wProg+        wIndefProg         logger         debouncer         (optShakeProfiling options)         (optReportProgress options)+        (optTesting options)         shakeOptions           { shakeThreads = optThreads options           , shakeFiles   = fromMaybe "/dev/null" (optShakeFiles options)@@ -82,26 +81,6 @@ -- This will return as soon as the result of the action is -- available.  There might still be other rules running at this point, -- e.g., the ofInterestRule.-runAction :: IdeState -> Action a -> IO a-runAction ide action = do-    bar <- newBarrier-    res <- shakeRun ide [do v <- action; liftIO $ signalBarrier bar v; return v]-    -- shakeRun might throw an exception (either through action or a default rule),-    -- in which case action may not complete successfully, and signalBarrier might not be called.-    -- Therefore we wait for either res (which propagates the exception) or the barrier.-    -- Importantly, if the barrier does finish, cancelling res only kills waiting for the result,-    -- it doesn't kill the actual work-    fmap fromEither $ race (head <$> res) $ waitBarrier bar----- | `runActionSync` is similar to `runAction` but it will--- wait for all rules (so in particular the `ofInterestRule`) to--- finish running. This is mainly useful in tests, where you want--- to wait for all rules to fire so you can check diagnostics.-runActionSync :: IdeState -> Action a -> IO a-runActionSync s act = fmap head $ join $ shakeRun s [act]--getIdeOptions :: Action IdeOptions-getIdeOptions = do-    GlobalIdeOptions x <- getIdeGlobalAction-    return x+runAction :: String -> IdeState -> Action a -> IO a+runAction herald ide act =+  join $ shakeEnqueue ide (mkDelayedAction herald Logger.Info act)
src/Development/IDE/Core/Shake.hs view
@@ -2,8 +2,11 @@ -- SPDX-License-Identifier: Apache-2.0  {-# LANGUAGE ExistentialQuantification  #-}+{-# LANGUAGE RankNTypes #-}+{-# LANGUAGE RecursiveDo #-} {-# LANGUAGE TypeFamilies               #-} {-# LANGUAGE ConstraintKinds            #-}+{-# LANGUAGE PatternSynonyms            #-}  -- | A Shake implementation of the compiler service. --@@ -21,29 +24,45 @@ module Development.IDE.Core.Shake(     IdeState, shakeExtras,     ShakeExtras(..), getShakeExtras, getShakeExtrasRules,-    IdeRule, IdeResult, GetModificationTime(..),+    IdeRule, IdeResult,+    GetModificationTime(GetModificationTime, GetModificationTime_, missingFileDiagnostics),     shakeOpen, shakeShut,-    shakeRun,+    shakeRestart,+    shakeEnqueue,     shakeProfile,-    use, useWithStale, useNoFile, uses, usesWithStale,+    use, useNoFile, uses, useWithStaleFast, useWithStaleFast', delayedAction,+    FastResult(..),     use_, useNoFile_, uses_,+    useWithStale, usesWithStale,+    useWithStale_, usesWithStale_,     define, defineEarlyCutoff, defineOnDisk, needOnDisk, needOnDisks,     getDiagnostics, unsafeClearDiagnostics,     getHiddenDiagnostics,     IsIdeGlobal, addIdeGlobal, addIdeGlobalExtras, getIdeGlobalState, getIdeGlobalAction,+    getIdeGlobalExtras,+    getIdeOptions,+    getIdeOptionsIO,+    GlobalIdeOptions(..),     garbageCollect,     setPriority,     sendEvent,     ideLogger,     actionLogger,-    FileVersion(..), modificationTime,+    FileVersion(..),     Priority(..),     updatePositionMapping,     deleteValue,     OnDiskRule(..),+    WithProgressFunc, WithIndefiniteProgressFunc,+    ProgressEvent(..),+    DelayedAction, mkDelayedAction,+    IdeAction(..), runIdeAction,+    mkUpdater,+    -- Exposed for testing.+    Q(..),     ) where -import           Development.Shake hiding (ShakeValue, doesFileExist)+import           Development.Shake hiding (ShakeValue, doesFileExist, Info) import           Development.Shake.Database import           Development.Shake.Classes import           Development.Shake.Rule@@ -56,12 +75,13 @@ import           Data.List.Extra (partition, takeEnd) import qualified Data.Set as Set import qualified Data.Text as T-import Data.Traversable (for) import Data.Tuple.Extra import Data.Unique import Development.IDE.Core.Debouncer+import Development.IDE.GHC.Compat ( NameCacheUpdater(..), upNameCache ) import Development.IDE.Core.PositionMapping import Development.IDE.Types.Logger hiding (Priority)+import qualified Development.IDE.Types.Logger as Logger import Language.Haskell.LSP.Diagnostics import qualified Data.SortedList as SL import           Development.IDE.Types.Diagnostics@@ -69,10 +89,13 @@ import Development.IDE.Types.Options import           Control.Concurrent.Async import           Control.Concurrent.Extra-import           Control.Exception.Extra+import           Control.Concurrent.STM.TQueue (flushTQueue, writeTQueue, readTQueue, newTQueue, TQueue)+import           Control.Concurrent.STM (readTVar, writeTVar, newTVarIO, TVar, atomically) import           Control.DeepSeq+import           Control.Exception.Extra import           System.Time.Extra import           Data.Typeable+import qualified Language.Haskell.LSP.Core as LSP import qualified Language.Haskell.LSP.Messages as LSP import qualified Language.Haskell.LSP.Types as LSP import           System.FilePath hiding (makeRelative)@@ -81,9 +104,19 @@ import           Data.Time import           GHC.Generics import           System.IO.Unsafe-import           Numeric.Extra import Language.Haskell.LSP.Types+import Data.Foldable (traverse_)+import qualified Control.Monad.STM as STM+import Control.Monad.IO.Class+import Control.Monad.Reader+import Control.Monad.Trans.Maybe+import Data.Traversable +import Data.IORef+import NameCache+import UniqSupply+import PrelInfo+import Data.Int (Int64)  -- information we stash inside the shakeExtra field data ShakeExtras = ShakeExtras@@ -104,8 +137,29 @@     -- accumlation of all previous mappings.     ,inProgress :: Var (HMap.HashMap NormalizedFilePath Int)     -- ^ How many rules are running for each file+    ,progressUpdate :: ProgressEvent -> IO ()+    -- ^ The generator for unique Lsp identifiers+    ,ideTesting :: IdeTesting+    -- ^ Whether to enable additional lsp messages used by the test suite for checking invariants+    ,session :: MVar ShakeSession+    -- ^ Used in the GhcSession rule to forcefully restart the session after adding a new component+    ,withProgress           :: WithProgressFunc+    -- ^ Report progress about some long running operation (on top of the progress shown by 'lspShakeProgress')+    ,withIndefiniteProgress :: WithIndefiniteProgressFunc+    -- ^ Same as 'withProgress', but for processes that do not report the percentage complete+    ,restartShakeSession :: [DelayedAction ()] -> IO ()+    , ideNc :: IORef NameCache     } +type WithProgressFunc = forall a.+    T.Text -> LSP.ProgressCancellable -> ((LSP.Progress -> IO ()) -> IO a) -> IO a+type WithIndefiniteProgressFunc = forall a.+    T.Text -> LSP.ProgressCancellable -> IO a -> IO a++data ProgressEvent+    = KickStarted+    | KickCompleted+ getShakeExtras :: Action ShakeExtras getShakeExtras = do     Just x <- getShakeExtra @ShakeExtras@@ -163,15 +217,19 @@ instance Hashable Key where     hashWithSalt salt (Key key) = hashWithSalt salt (typeOf key, key) --- | The result of an IDE operation. Warnings and errors are in the Diagnostic,---   and a value is in the Maybe. For operations that throw an error you---   expect a non-empty list of diagnostics, at least one of which is an error,---   and a Nothing. For operations that succeed you expect perhaps some warnings---   and a Just. For operations that depend on other failing operations you may---   get empty diagnostics and a Nothing, to indicate this phase throws no fresh---   errors but still failed.---+newtype GlobalIdeOptions = GlobalIdeOptions IdeOptions+instance IsIdeGlobal GlobalIdeOptions +getIdeOptions :: Action IdeOptions+getIdeOptions = do+    GlobalIdeOptions x <- getIdeGlobalAction+    return x++getIdeOptionsIO :: ShakeExtras -> IO IdeOptions+getIdeOptionsIO ide = do+    GlobalIdeOptions x <- getIdeGlobalExtras ide+    return x+ data Value v     = Succeeded TextDocumentVersion v     | Stale TextDocumentVersion v@@ -189,15 +247,21 @@  -- | Return the most recent, potentially stale, value and a PositionMapping -- for the version of that value.-lastValue :: NormalizedFilePath -> Value v -> Action (Maybe (v, PositionMapping))-lastValue file v = do-    ShakeExtras{positionMapping} <- getShakeExtras+lastValueIO :: ShakeExtras -> NormalizedFilePath -> Value v -> IO (Maybe (v, PositionMapping))+lastValueIO ShakeExtras{positionMapping} file v = do     allMappings <- liftIO $ readVar positionMapping     pure $ case v of         Succeeded ver v -> Just (v, mappingForVersion allMappings file ver)         Stale ver v -> Just (v, mappingForVersion allMappings file ver)         Failed -> Nothing +-- | Return the most recent, potentially stale, value and a PositionMapping+-- for the version of that value.+lastValue :: NormalizedFilePath -> Value v -> Action (Maybe (v, PositionMapping))+lastValue file v = do+    s <- getShakeExtras+    liftIO $ lastValueIO s file v+ valueVersion :: Value v -> Maybe TextDocumentVersion valueVersion = \case     Succeeded ver _ -> Just ver@@ -222,27 +286,36 @@   , NFData v   ) +-- | A live Shake session with the ability to enqueue Actions for running.+--   Keeps the 'ShakeDatabase' open, so at most one 'ShakeSession' per database.+data ShakeSession = ShakeSession+  { cancelShakeSession :: !(IO [DelayedActionInternal])+    -- ^ Closes the Shake session and returns the pending user actions+  , runInShakeSession  :: !(forall a . DelayedAction a -> IO (IO a))+    -- ^ Enqueue an action in the Shake session.+  }+ -- | A Shake database plus persistent store. Can be thought of as storing --   mappings from @(FilePath, k)@ to @RuleResult k@. data IdeState = IdeState-    {shakeDb :: ShakeDatabase-    ,shakeAbort :: MVar (IO ()) -- close whoever was running last-    ,shakeClose :: IO ()-    ,shakeExtras :: ShakeExtras+    {shakeDb         :: ShakeDatabase+    ,shakeSession    :: MVar ShakeSession+    ,shakeClose      :: IO ()+    ,shakeExtras     :: ShakeExtras     ,shakeProfileDir :: Maybe FilePath+    ,stopProgressReporting :: IO ()     }  + -- This is debugging code that generates a series of profiles, if the Boolean is true-shakeRunDatabaseProfile :: Maybe FilePath -> ShakeDatabase -> [Action a] -> IO ([a], Maybe FilePath)-shakeRunDatabaseProfile mbProfileDir shakeDb acts = do-        (time, (res,_)) <- duration $ shakeRunDatabase shakeDb acts-        proFile <- for mbProfileDir $ \dir -> do+shakeDatabaseProfile :: Maybe FilePath -> ShakeDatabase -> IO (Maybe FilePath)+shakeDatabaseProfile mbProfileDir shakeDb =+        for mbProfileDir $ \dir -> do                 count <- modifyVar profileCounter $ \x -> let !y = x+1 in return (y,y)-                let file = "ide-" ++ profileStartTime ++ "-" ++ takeEnd 5 ("0000" ++ show count) ++ "-" ++ showDP 2 time <.> "html"+                let file = "ide-" ++ profileStartTime ++ "-" ++ takeEnd 5 ("0000" ++ show count) <.> "html"                 shakeProfileDatabase shakeDb $ dir </> file                 return (dir </> file)-        return (res, proFile)  {-# NOINLINE profileStartTime #-} profileStartTime :: String@@ -297,140 +370,290 @@ -- | Open a 'IdeState', should be shut using 'shakeShut'. shakeOpen :: IO LSP.LspId           -> (LSP.FromServerMessage -> IO ()) -- ^ diagnostic handler+          -> WithProgressFunc+          -> WithIndefiniteProgressFunc           -> Logger           -> Debouncer NormalizedUri           -> Maybe FilePath           -> IdeReportProgress+          -> IdeTesting           -> ShakeOptions           -> Rules ()           -> IO IdeState-shakeOpen getLspId eventer logger debouncer shakeProfileDir (IdeReportProgress reportProgress) opts rules = do+shakeOpen getLspId eventer withProgress withIndefiniteProgress logger debouncer+  shakeProfileDir (IdeReportProgress reportProgress) ideTesting@(IdeTesting testing) opts rules = mdo+     inProgress <- newVar HMap.empty-    shakeExtras <- do+    us <- mkSplitUniqSupply 'r'+    ideNc <- newIORef (initNameCache us knownKeyNames)+    (shakeExtras, stopProgressReporting) <- do         globals <- newVar HMap.empty         state <- newVar HMap.empty         diagnostics <- newVar mempty         hiddenDiagnostics <- newVar mempty         publishedDiagnostics <- newVar mempty         positionMapping <- newVar HMap.empty-        pure ShakeExtras{..}-    (shakeDb, shakeClose) <-+        let restartShakeSession = shakeRestart ideState+        let session = shakeSession+        mostRecentProgressEvent <- newTVarIO KickCompleted+        let progressUpdate = atomically . writeTVar mostRecentProgressEvent+        progressAsync <- async $+            when reportProgress $+                progressThread mostRecentProgressEvent inProgress++        pure (ShakeExtras{..}, cancel progressAsync)+    (shakeDbM, shakeClose) <-         shakeOpenDatabase-            opts-                { shakeExtra = addShakeExtra shakeExtras $ shakeExtra opts-                -- we don't actually use the progress value, but Shake conveniently spawns/kills this thread whenever-                -- we call into Shake, so abuse it for that purpose-                , shakeProgress = const $ if reportProgress then lspShakeProgress getLspId eventer inProgress else pure ()-                }+            opts { shakeExtra = addShakeExtra shakeExtras $ shakeExtra opts }             rules-    shakeAbort <- newMVar $ return ()-    shakeDb <- shakeDb-    return IdeState{..}--lspShakeProgress :: Hashable a => IO LSP.LspId -> (LSP.FromServerMessage -> IO ()) -> Var (HMap.HashMap a Int) -> IO ()-lspShakeProgress getLspId sendMsg inProgress = do-    -- first sleep a bit, so we only show progress messages if it's going to take-    -- a "noticable amount of time" (we often expect a thread kill to arrive before the sleep finishes)-    sleep 0.1-    lspId <- getLspId-    u <- ProgressTextToken . T.pack . show . hashUnique <$> newUnique-    sendMsg $ LSP.ReqWorkDoneProgressCreate $ LSP.fmServerWorkDoneProgressCreateRequest-      lspId $ LSP.WorkDoneProgressCreateParams-      { _token = u }-    bracket_ (start u) (stop u) (loop u Nothing)+    shakeDb <- shakeDbM+    initSession <- newSession shakeExtras shakeDb [] []+    shakeSession <- newMVar initSession+    let ideState = IdeState{..}+    return ideState     where-        start id = sendMsg $ LSP.NotWorkDoneProgressBegin $ LSP.fmServerWorkDoneProgressBeginNotification-            LSP.ProgressParams-                { _token = id-                , _value = WorkDoneProgressBeginParams-                  { _title = "Processing"-                  , _cancellable = Nothing-                  , _message = Nothing-                  , _percentage = Nothing-                  }-                }-        stop id = sendMsg $ LSP.NotWorkDoneProgressEnd $ LSP.fmServerWorkDoneProgressEndNotification-            LSP.ProgressParams-                { _token = id-                , _value = WorkDoneProgressEndParams-                  { _message = Nothing-                  }-                }-        sample = 0.1-        loop id prev = do-            sleep sample-            current <- readVar inProgress-            let done = length $ filter (== 0) $ HMap.elems current-            let todo = HMap.size current-            let next = Just $ T.pack $ show done <> "/" <> show todo-            when (next /= prev) $-                sendMsg $ LSP.NotWorkDoneProgressReport $ LSP.fmServerWorkDoneProgressReportNotification-                    LSP.ProgressParams-                        { _token = id-                        , _value = LSP.WorkDoneProgressReportParams-                        { _cancellable = Nothing-                        , _message = next-                        , _percentage = Nothing-                        }-                        }-            loop id next+        -- The progress thread is a state machine with two states:+        --   1. Idle+        --   2. Reporting a kick event+        -- And two transitions, modelled by 'ProgressEvent':+        --   1. KickCompleted - transitions from Reporting into Idle+        --   2. KickStarted - transitions from Idle into Reporting+        progressThread mostRecentProgressEvent inProgress = progressLoopIdle+          where+            progressLoopIdle = do+                atomically $ do+                    v <- readTVar mostRecentProgressEvent+                    case v of+                        KickCompleted -> STM.retry+                        KickStarted -> return ()+                asyncReporter <- async lspShakeProgress+                progressLoopReporting asyncReporter+            progressLoopReporting asyncReporter = do+                atomically $ do+                    v <- readTVar mostRecentProgressEvent+                    case v of+                        KickStarted -> STM.retry+                        KickCompleted -> return ()+                cancel asyncReporter+                progressLoopIdle +            lspShakeProgress = do+                -- first sleep a bit, so we only show progress messages if it's going to take+                -- a "noticable amount of time" (we often expect a thread kill to arrive before the sleep finishes)+                unless testing $ sleep 0.1+                lspId <- getLspId+                u <- ProgressTextToken . T.pack . show . hashUnique <$> newUnique+                eventer $ LSP.ReqWorkDoneProgressCreate $+                  LSP.fmServerWorkDoneProgressCreateRequest lspId $+                    LSP.WorkDoneProgressCreateParams { _token = u }+                bracket_ (start u) (stop u) (loop u Nothing)+                where+                    start id = eventer $ LSP.NotWorkDoneProgressBegin $+                      LSP.fmServerWorkDoneProgressBeginNotification+                        LSP.ProgressParams+                            { _token = id+                            , _value = WorkDoneProgressBeginParams+                              { _title = "Processing"+                              , _cancellable = Nothing+                              , _message = Nothing+                              , _percentage = Nothing+                              }+                            }+                    stop id = eventer $ LSP.NotWorkDoneProgressEnd $+                      LSP.fmServerWorkDoneProgressEndNotification+                        LSP.ProgressParams+                            { _token = id+                            , _value = WorkDoneProgressEndParams+                              { _message = Nothing+                              }+                            }+                    sample = 0.1+                    loop id prev = do+                        sleep sample+                        current <- readVar inProgress+                        let done = length $ filter (== 0) $ HMap.elems current+                        let todo = HMap.size current+                        let next = Just $ T.pack $ show done <> "/" <> show todo+                        when (next /= prev) $+                            eventer $ LSP.NotWorkDoneProgressReport $+                              LSP.fmServerWorkDoneProgressReportNotification+                                LSP.ProgressParams+                                    { _token = id+                                    , _value = LSP.WorkDoneProgressReportParams+                                    { _cancellable = Nothing+                                    , _message = next+                                    , _percentage = Nothing+                                    }+                                    }+                        loop id next+ shakeProfile :: IdeState -> FilePath -> IO () shakeProfile IdeState{..} = shakeProfileDatabase shakeDb  shakeShut :: IdeState -> IO ()-shakeShut IdeState{..} = withMVar shakeAbort $ \stop -> do+shakeShut IdeState{..} = withMVar shakeSession $ \runner -> do     -- Shake gets unhappy if you try to close when there is a running     -- request so we first abort that.-    stop+    void $ cancelShakeSession runner     shakeClose+    stopProgressReporting + -- | This is a variant of withMVar where the first argument is run unmasked and if it throws -- an exception, the previous value is restored while the second argument is executed masked.-withMVar' :: MVar a -> (a -> IO ()) -> IO (a, c) -> IO c+withMVar' :: MVar a -> (a -> IO b) -> (b -> IO (a, c)) -> IO c withMVar' var unmasked masked = mask $ \restore -> do     a <- takeMVar var-    restore (unmasked a) `onException` putMVar var a-    (a', c) <- masked+    b <- restore (unmasked a) `onException` putMVar var a+    (a', c) <- masked b     putMVar var a'     pure c --- | Spawn immediately. If you are already inside a call to shakeRun that will be aborted with an exception.-shakeRun :: IdeState -> [Action a] -> IO (IO [a])-shakeRun IdeState{shakeExtras=ShakeExtras{..}, ..} acts =++mkDelayedAction :: String -> Logger.Priority -> Action a -> DelayedAction a+mkDelayedAction = DelayedAction++data DelayedAction a = DelayedAction+  { actionName :: String -- ^ Name we use for debugging+  , actionPriority :: Logger.Priority -- ^ Priority with which to log the action+  , getAction :: Action a -- ^ The payload+  }++type DelayedActionInternal = DelayedAction ()++instance Show (DelayedAction a) where+    show d = "DelayedAction: " ++ actionName d++-- | These actions are run asynchronously after the current action is+-- finished running. For example, to trigger a key build after a rule+-- has already finished as is the case with useWithStaleFast+delayedAction :: DelayedAction a -> IdeAction (IO a)+delayedAction a = do+  sq <- asks session+  liftIO $ shakeEnqueueSession sq a++-- | Restart the current 'ShakeSession' with the given system actions.+--   Any computation running in the current session will be aborted,+--   but user actions (added via 'shakeEnqueue') will be requeued.+--   Progress is reported only on the system actions.+shakeRestart :: IdeState -> [DelayedAction a] -> IO ()+shakeRestart IdeState{..} systemActs =     withMVar'-        shakeAbort-        (\stop -> do-              (stopTime,_) <- duration stop-              logDebug logger $ T.pack $ "Starting shakeRun (aborting the previous one took " ++ showDuration stopTime ++ ")"+        shakeSession+        (\runner -> do+              (stopTime,queue) <- duration (cancelShakeSession runner)+              res <- shakeDatabaseProfile shakeProfileDir shakeDb+              let profile = case res of+                      Just fp -> ", profile saved at " <> fp+                      _ -> ""+              logDebug (logger shakeExtras) $ T.pack $+                  "Restarting build session (aborting the previous one took " +++                  showDuration stopTime ++ profile ++ ")"+              return queue         )         -- It is crucial to be masked here, otherwise we can get killed-        -- between spawning the new thread and updating shakeAbort.+        -- between spawning the new thread and updating shakeSession.         -- See https://github.com/digital-asset/ghcide/issues/79-        (do-              start <- offsetTime-              aThread <- asyncWithUnmask $ \restore -> do-                   res <- try (restore $ shakeRunDatabaseProfile shakeProfileDir shakeDb acts)-                   runTime <- start-                   let res' = case res of-                            Left e -> "exception: " <> displayException e-                            Right _ -> "completed"-                       profile = case res of-                            Right (_, Just fp) ->-                                let link = case filePathToUri' $ toNormalizedFilePath' fp of-                                                NormalizedUri _ x -> x-                                in ", profile saved at " <> T.unpack link-                            _ -> ""-                   let logMsg = logDebug logger $ T.pack $-                        "Finishing shakeRun (took " ++ showDuration runTime ++ ", " ++ res' ++ profile ++ ")"-                   return (fst <$> res, logMsg)-              let wrapUp (res, _) = do-                    either (throwIO @SomeException) return res-              _ <- async $ do-                  (_, logMsg) <- wait aThread-                  logMsg-              pure (cancel aThread, wrapUp =<< wait aThread))+        (\cancelled -> do+          (_b, dai) <- unzip <$> mapM instantiateDelayedAction systemActs+          (,()) <$> newSession shakeExtras shakeDb dai cancelled) +-- | Enqueue an action in the existing 'ShakeSession'.+--   Returns a computation to block until the action is run, propagating exceptions.+--   Assumes a 'ShakeSession' is available.+--+--   Appropriate for user actions other than edits.+shakeEnqueue :: IdeState -> DelayedAction a -> IO (IO a)+shakeEnqueue IdeState{shakeSession} act = shakeEnqueueSession shakeSession act++shakeEnqueueSession :: MVar ShakeSession -> DelayedAction a -> IO (IO a)+shakeEnqueueSession sess act = withMVar sess $ \s -> runInShakeSession s act++-- | Set up a new 'ShakeSession' with a set of initial system and user actions+-- Will crash if there is an existing 'ShakeSession' running.+-- Progress is reported only on the system actions.+-- Only user actions will get re-enqueued+newSession :: ShakeExtras -> ShakeDatabase -> [DelayedActionInternal] -> [DelayedActionInternal] -> IO ShakeSession+newSession ShakeExtras{..} shakeDb systemActs userActs = do+    -- A work queue for actions added via 'runInShakeSession'+    actionQueue :: TQueue DelayedActionInternal <- atomically $ do+        q <- newTQueue+        traverse_ (writeTQueue q) userActs+        return q+    actionInProgress :: TVar (Maybe DelayedActionInternal) <- newTVarIO Nothing++    let+        -- A daemon-like action used to inject additional work+        -- Runs actions from the work queue sequentially+        pumpAction =+            forever $ do+                join $ liftIO $ atomically $ do+                    act <- readTQueue actionQueue+                    writeTVar actionInProgress $ Just act+                    return (logDelayedAction logger act)+                liftIO $ atomically $ writeTVar actionInProgress Nothing++        workRun restore = do+          let systemActs' = pumpAction : map getAction systemActs+          res <- try @SomeException+                 (restore $ shakeRunDatabase shakeDb systemActs')+          let res' = case res of+                      Left e -> "exception: " <> displayException e+                      Right _ -> "completed"+              -- Wrap up in a thread to avoid calling interruptible+              -- operations inside the masked section+          let wrapUp = logDebug logger $ T.pack $ "Finishing build session(" ++ res' ++ ")"+          return wrapUp++    -- Do the work in a background thread+    workThread <- asyncWithUnmask workRun++    -- run the wrap up unmasked+    _ <- async $ join $ wait workThread+++    -- 'runInShakeSession' is used to append work in this Shake session+    --  The session stays open until 'cancelShakeSession' is called+    let runInShakeSession :: forall a . DelayedAction a -> IO (IO a)+        runInShakeSession da = do+          (b, dai) <- instantiateDelayedAction da+          atomically $ writeTQueue actionQueue dai+          return (waitBarrier b >>= either throwIO return)++    --  Cancelling is required to flush the Shake database when either+    --  the filesystem or the Ghc configuration have changed+        cancelShakeSession :: IO [DelayedActionInternal]+        cancelShakeSession = do+            cancel workThread+            atomically $ do+                q <- flushTQueue actionQueue+                c <- readTVar actionInProgress+                return (maybe [] pure c ++ q)++    pure (ShakeSession{..})++instantiateDelayedAction :: DelayedAction a -> IO (Barrier (Either SomeException a), DelayedActionInternal)+instantiateDelayedAction (DelayedAction s p a) = do+  b <- newBarrier+  let a' = do+        -- work gets reenqueued when the Shake session is restarted+        -- it can happen that a work item finished just as it was reenqueud+        -- in that case, skipping the work is fine+        alreadyDone <- liftIO $ isJust <$> waitBarrierMaybe b+        unless alreadyDone $ do+          x <- actionCatch @SomeException (Right <$> a) (pure . Left)+          liftIO $ signalBarrier b x+  let d = DelayedAction s p a'+  return (b, d)++logDelayedAction :: Logger -> DelayedActionInternal -> Action ()+logDelayedAction l d  = do+    start <- liftIO offsetTime+    getAction d+    runTime <- liftIO start+    liftIO $ logPriority l (actionPriority d) $ T.pack $+        "finish: " ++ actionName d ++ " (took " ++ showDuration runTime ++ ")"+ getDiagnostics :: IdeState -> IO [FileDiagnostic] getDiagnostics IdeState{shakeExtras = ShakeExtras{diagnostics}} = do     val <- readVar diagnostics@@ -475,6 +698,71 @@     => k -> NormalizedFilePath -> Action (Maybe (v, PositionMapping)) useWithStale key file = head <$> usesWithStale key [file] +useWithStale_ :: IdeRule k v+    => k -> NormalizedFilePath -> Action (v, PositionMapping)+useWithStale_ key file = head <$> usesWithStale_ key [file]++usesWithStale_ :: IdeRule k v => k -> [NormalizedFilePath] -> Action [(v, PositionMapping)]+usesWithStale_ key files = do+    res <- usesWithStale key files+    case sequence res of+        Nothing -> liftIO $ throwIO $ BadDependency (show key)+        Just v -> return v++newtype IdeAction a = IdeAction { runIdeActionT  :: (ReaderT ShakeExtras IO) a }+    deriving (MonadReader ShakeExtras, MonadIO, Functor, Applicative, Monad)++-- | IdeActions are used when we want to return a result immediately, even if it+-- is stale Useful for UI actions like hover, completion where we don't want to+-- block.+runIdeAction :: String -> ShakeExtras -> IdeAction a -> IO a+runIdeAction _herald s i = runReaderT (runIdeActionT i) s++askShake :: IdeAction ShakeExtras+askShake = ask++mkUpdater :: MaybeT IdeAction NameCacheUpdater+mkUpdater = do+  ref <- lift $ ideNc <$> askShake+  pure $ NCU (upNameCache ref)++-- | A (maybe) stale result now, and an up to date one later+data FastResult a = FastResult { stale :: Maybe (a,PositionMapping), uptoDate :: IO (Maybe a)  }++-- | Lookup value in the database and return with the stale value immediately+-- Will queue an action to refresh the value.+-- Might block the first time the rule runs, but never blocks after that.+useWithStaleFast :: IdeRule k v => k -> NormalizedFilePath -> IdeAction (Maybe (v, PositionMapping))+useWithStaleFast key file = stale <$> useWithStaleFast' key file++-- | Same as useWithStaleFast but lets you wait for an up to date result+useWithStaleFast' :: IdeRule k v => k -> NormalizedFilePath -> IdeAction (FastResult v)+useWithStaleFast' key file = do+  -- This lookup directly looks up the key in the shake database and+  -- returns the last value that was computed for this key without+  -- checking freshness.++  -- Async trigger the key to be built anyway because we want to+  -- keep updating the value in the key.+  wait <- delayedAction $ mkDelayedAction ("C:" ++ show key) Debug $ use key file++  s@ShakeExtras{state} <- askShake+  r <- liftIO $ getValues state key file+  liftIO $ case r of+    -- block for the result if we haven't computed before+    Nothing -> do+      a <- wait+      r <- getValues state key file+      case r of+        Nothing -> return $ FastResult Nothing (pure a)+        Just v -> do+          res <- lastValueIO s file v+          pure $ FastResult res (pure a)+    -- Otherwise, use the computed value even if it's out of date.+    Just v -> do+      res <- lastValueIO s file v+      pure $ FastResult res wait+ useNoFile :: IdeRule k v => k -> Action (Maybe v) useNoFile key = use key emptyFilePath @@ -506,7 +794,14 @@ newtype Q k = Q (k, NormalizedFilePath)     deriving (Eq,Hashable,NFData, Generic) -instance Binary k => Binary (Q k)+instance Binary k => Binary (Q k) where+    put (Q (k, fp)) = put (k, fp)+    get = do+        (k, fp) <- get+        -- The `get` implementation of NormalizedFilePath+        -- does not handle empty file paths so we+        -- need to handle this ourselves here.+        pure (Q (k, toNormalizedFilePath' fp))  instance Show k => Show (Q k) where     show (Q (k, file)) = show k ++ "; " ++ fromNormalizedFilePath file@@ -536,14 +831,6 @@     zipWithM lastValue files values  -withProgress :: (Eq a, Hashable a) => Var (HMap.HashMap a Int) -> a -> Action b -> Action b-withProgress var file = actionBracket (f succ) (const $ f pred) . const-    -- This functions are deliberately eta-expanded to avoid space leaks.-    -- Do not remove the eta-expansion without profiling a session with at-    -- least 1000 modifications.-    where f shift = modifyVar_ var $ \x -> evaluate $ HMap.alter (\x -> Just $! shift (fromMaybe 0 x)) file x-- defineEarlyCutoff     :: IdeRule k v     => (k -> NormalizedFilePath -> Action (Maybe BS.ByteString, IdeResult v))@@ -551,7 +838,7 @@ defineEarlyCutoff op = addBuiltinRule noLint noIdentity $ \(Q (key, file)) (old :: Maybe BS.ByteString) mode -> do     extras@ShakeExtras{state, inProgress} <- getShakeExtras     -- don't do progress for GetFileExists, as there are lots of non-nodes for just that one key-    (if show key == "GetFileExists" then id else withProgress inProgress file) $ do+    (if show key == "GetFileExists" then id else withProgressVar inProgress file) $ do         val <- case old of             Just old | mode == RunDependenciesSame -> do                 v <- liftIO $ getValues state key file@@ -590,8 +877,17 @@                     (if eq then ChangedRecomputeSame else ChangedRecomputeDiff)                     (encodeShakeValue bs) $                     A res+  where+    withProgressVar :: (Eq a, Hashable a) => Var (HMap.HashMap a Int) -> a -> Action b -> Action b+    withProgressVar var file = actionBracket (f succ) (const $ f pred) . const+        -- This functions are deliberately eta-expanded to avoid space leaks.+        -- Do not remove the eta-expansion without profiling a session with at+        -- least 1000 modifications.+        where f shift = modifyVar_ var $ \x -> evaluate $ HMap.insertWith (\_ x -> shift x) file (shift 0) x  ++ -- | Rule type, input file data QDisk k = QDisk k NormalizedFilePath   deriving (Eq, Generic)@@ -697,12 +993,12 @@       | otherwise -> error $ "Failed to parse shake value " <> show bs  -updateFileDiagnostics ::-     NormalizedFilePath+updateFileDiagnostics :: MonadIO m+  => NormalizedFilePath   -> Key   -> ShakeExtras   -> [(ShowDiagnostic,Diagnostic)] -- ^ current results-  -> Action ()+  -> m () updateFileDiagnostics fp k ShakeExtras{diagnostics, hiddenDiagnostics, publishedDiagnostics, state, debouncer, eventer} current = liftIO $ do     modTime <- (currentValue =<<) <$> getValues state GetModificationTime fp     let (currentShown, currentHidden) = partition ((== ShowDiag) . fst) current@@ -759,20 +1055,37 @@     return logger  -data GetModificationTime = GetModificationTime-    deriving (Eq, Show, Generic)-instance Hashable GetModificationTime+-- The Shake key type for getModificationTime queries+data GetModificationTime = GetModificationTime_+    { missingFileDiagnostics :: Bool+      -- ^ If false, missing file diagnostics are not reported+    }+    deriving (Show, Generic)++instance Eq GetModificationTime where+    -- Since the diagnostics are not part of the answer, the query identity is+    -- independent from the 'missingFileDiagnostics' field+    _ == _ = True++instance Hashable GetModificationTime where+    -- Since the diagnostics are not part of the answer, the query identity is+    -- independent from the 'missingFileDiagnostics' field+    hashWithSalt salt _ = salt+ instance NFData   GetModificationTime instance Binary   GetModificationTime +pattern GetModificationTime :: GetModificationTime+pattern GetModificationTime = GetModificationTime_ {missingFileDiagnostics=True}+ -- | Get the modification time of a file. type instance RuleResult GetModificationTime = FileVersion  data FileVersion     = VFSVersion !Int     | ModificationTime-      !Int   -- ^ Large unit (platform dependent, do not make assumptions)-      !Int   -- ^ Small unit (platform dependent, do not make assumptions)+      !Int64   -- ^ Large unit (platform dependent, do not make assumptions)+      !Int64   -- ^ Small unit (platform dependent, do not make assumptions)     deriving (Show, Generic)  instance NFData FileVersion@@ -780,10 +1093,6 @@ vfsVersion :: FileVersion -> Maybe Int vfsVersion (VFSVersion i) = Just i vfsVersion ModificationTime{} = Nothing--modificationTime :: FileVersion -> Maybe (Int, Int)-modificationTime VFSVersion{} = Nothing-modificationTime (ModificationTime large small) = Just (large, small)  getDiagnosticsFromStore :: StoreItem -> [Diagnostic] getDiagnosticsFromStore (StoreItem _ diags) = concatMap SL.fromSortedList $ Map.elems diags
src/Development/IDE/GHC/Compat.hs view
@@ -2,21 +2,24 @@ -- SPDX-License-Identifier: Apache-2.0  {-# LANGUAGE CPP #-}+{-# LANGUAGE ConstraintKinds #-}+{-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE PatternSynonyms #-}+{-# OPTIONS -Wno-dodgy-imports #-} #include "ghc-api-version.h"  -- | Attempt at hiding the GHC version differences we can. module Development.IDE.GHC.Compat(     getHeaderImports,     HieFileResult(..),-    HieFile,+    HieFile(..),+    NameCacheUpdater(..),     hieExportNames,-    hie_module,     mkHieFile,     writeHieFile,     readHieFile,     supportsHieFiles,-    setDefaultHieDir,+    setHieDir,     dontWriteHieFiles, #if !MIN_GHC_API_VERSION(8,8,0)     ml_hie_file,@@ -32,15 +35,35 @@     pattern InstD,     pattern TyClD,     pattern ValD,+    pattern SigD,+    pattern TypeSig,     pattern ClassOpSig,     pattern IEThingAll,     pattern IEThingWith,+    pattern VarPat,+    pattern PatSynBind,     GHC.ModLocation,     Module.addBootSuffix,     pattern ModLocation,     getConArgs, -    module GHC+    HasSrcSpan,+    getLoc,++    upNameCache,++    module GHC,+#if MIN_GHC_API_VERSION(8,6,0)++#if MIN_GHC_API_VERSION(8,8,0)+    module HieTypes,+    module HieUtils,+#else+    module Development.IDE.GHC.HieTypes,+    module Development.IDE.GHC.HieUtils,+#endif++#endif     ) where  import StringBuffer@@ -49,10 +72,28 @@ import Fingerprint (Fingerprint) import qualified Module import Packages+import Data.IORef+import HscTypes+import NameCache  import qualified GHC import GHC hiding (-      ClassOpSig, DerivD, ForD, IEThingAll, IEThingWith, InstD, TyClD, ValD, ModLocation+      ClassOpSig,+      DerivD,+      ForD,+      IEThingAll,+      IEThingWith,+      InstD,+      TyClD,+      ValD,+      SigD,+      TypeSig,+      VarPat,+      ModLocation,+      HasSrcSpan,+      PatSynBind,+      lookupName,+      getLoc #if MIN_GHC_API_VERSION(8,6,0)     , getConArgs #endif@@ -62,39 +103,38 @@ import ErrUtils (ErrorMessages) import FastString (FastString) -#if MIN_GHC_API_VERSION(8,10,0)-import HscTypes (mi_mod_hash)-#endif+#if MIN_GHC_API_VERSION(8,6,0)+import Development.IDE.GHC.HieAst (mkHieFile)+import Development.IDE.GHC.HieBin  #if MIN_GHC_API_VERSION(8,8,0)-import Control.Applicative ((<|>))-import Development.IDE.GHC.HieAst (mkHieFile)-import HieBin+import HieUtils import HieTypes--supportsHieFiles :: Bool-supportsHieFiles = True+#else+import Development.IDE.GHC.HieUtils+import Development.IDE.GHC.HieTypes+import System.FilePath ((-<.>))+#endif -hieExportNames :: HieFile -> [(SrcSpan, Name)]-hieExportNames = nameListFromAvails . hie_exports+#endif -#else+#if !MIN_GHC_API_VERSION(8,8,0)  #if MIN_GHC_API_VERSION(8,6,0)-import BinIface-import Data.IORef+import GhcPlugins (srcErrorMessages)+#else+import System.IO.Error import IfaceEnv-#endif- import Binary-import Control.Exception (catch) import Data.ByteString (ByteString)-import GhcPlugins hiding (ModLocation)-import NameCache+import GhcPlugins (Hsc, srcErrorMessages) import TcRnTypes+import MkIface+#endif++import Control.Exception (catch) import System.IO import Foreign.ForeignPtr-import MkIface   hPutStringBuffer :: Handle -> StringBuffer -> IO ()@@ -104,6 +144,27 @@  #endif +#if MIN_GHC_API_VERSION(8,6,0)+supportsHieFiles :: Bool+supportsHieFiles = True++hieExportNames :: HieFile -> [(SrcSpan, Name)]+hieExportNames = nameListFromAvails . hie_exports++#if !MIN_GHC_API_VERSION(8,8,0)+ml_hie_file :: GHC.ModLocation -> FilePath+ml_hie_file ml = ml_hi_file ml -<.> ".hie"+#endif++#endif++upNameCache :: IORef NameCache -> (NameCache -> (NameCache, c)) -> IO c+#if !MIN_GHC_API_VERSION(8,8,0)+upNameCache ref upd_fn+  = atomicModifyIORef' ref upd_fn+#else+upNameCache = updNameCache+#endif #if !MIN_GHC_API_VERSION(8,6,0) includePathsGlobal, includePathsQuote :: [String] -> [String] includePathsGlobal = id@@ -159,6 +220,22 @@     GHC.TyClD x #endif +pattern SigD :: Sig p -> HsDecl p+pattern SigD x <-+#if MIN_GHC_API_VERSION(8,6,0)+    GHC.SigD _ x+#else+    GHC.SigD x+#endif++pattern TypeSig :: [Located (IdP p)] -> LHsSigWcType p -> Sig p+pattern TypeSig x y <-+#if MIN_GHC_API_VERSION(8,6,0)+    GHC.TypeSig _ x y+#else+    GHC.TypeSig x y+#endif+ pattern ClassOpSig :: Bool -> [Located (IdP pass)] -> LHsSigType pass -> Sig pass pattern ClassOpSig a b c <- #if MIN_GHC_API_VERSION(8,6,0)@@ -191,10 +268,26 @@     GHC.IEThingAll a #endif -setDefaultHieDir :: FilePath -> DynFlags -> DynFlags-setDefaultHieDir _f d =+pattern VarPat :: Located (IdP p) -> Pat p+pattern VarPat x <-+#if MIN_GHC_API_VERSION(8,6,0)+    GHC.VarPat _ x+#else+    GHC.VarPat x+#endif++pattern PatSynBind :: GHC.PatSynBind p p -> HsBind p+pattern PatSynBind x <-+#if MIN_GHC_API_VERSION(8,6,0)+    GHC.PatSynBind _ x+#else+    GHC.PatSynBind x+#endif++setHieDir :: FilePath -> DynFlags -> DynFlags+setHieDir _f d = #if MIN_GHC_API_VERSION(8,8,0)-    d { hieDir     = hieDir d <|> Just _f}+    d { hieDir     = Just _f} #else     d #endif@@ -211,7 +304,7 @@ nameListFromAvails as =   map (\n -> (nameSrcSpan n, n)) (concatMap availNames as) -#if !MIN_GHC_API_VERSION(8,8,0)+#if !MIN_GHC_API_VERSION(8,6,0) -- Reimplementations of functions for HIE files for GHC 8.6  mkHieFile :: ModSummary -> TcGblEnv -> RenamedSource -> ByteString -> Hsc HieFile@@ -240,31 +333,16 @@ data HieFileResult = HieFileResult { hie_file_result :: HieFile }  writeHieFile :: FilePath -> HieFile -> IO ()-readHieFile :: NameCache -> FilePath -> IO (HieFileResult, ())+readHieFile :: NameCacheUpdater -> FilePath -> IO HieFileResult supportsHieFiles :: Bool -#if MIN_GHC_API_VERSION(8,6,0)--writeHieFile fp hie = do-  bh <- openBinMem (1024 * 1024)-  putWithUserData (const $ return ()) bh hie-  writeBinMem bh fp--readHieFile nc fp = do-  bh <- readBinMem fp-  nc' <- newIORef nc-  hie_file <- getWithUserData (NCU (atomicModifyIORef' nc')) bh-  return (HieFileResult hie_file, ())--supportsHieFiles = True--#else+#if MIN_GHC_API_VERSION(8,4,0)  supportsHieFiles = False  writeHieFile _ _ = return () -readHieFile _ _ = return undefined+readHieFile _ fp = ioError $ mkIOError doesNotExistErrorType "" Nothing (Just fp)  #endif @@ -285,7 +363,20 @@        ) #if MIN_GHC_API_VERSION(8,8,0) getHeaderImports = Hdr.getImports++type HasSrcSpan = GHC.HasSrcSpan+getLoc :: HasSrcSpan a => a -> SrcSpan+getLoc = GHC.getLoc+ #else++class HasSrcSpan a where+    getLoc :: a -> SrcSpan+instance HasSrcSpan Name where+    getLoc = nameSrcSpan+instance HasSrcSpan (GenLocated SrcSpan a) where+    getLoc = GHC.getLoc+ getHeaderImports a b c d =     catch (Right <$> Hdr.getImports a b c d)           (return . Left . srcErrorMessages)
src/Development/IDE/GHC/Error.hs view
@@ -9,7 +9,6 @@   , diagFromStrings   , diagFromGhcException   , catchSrcErrors-  , mergeDiagnostics    -- * utilities working with spans   , srcSpanToLocation@@ -63,26 +62,6 @@  diagFromErrMsgs :: T.Text -> DynFlags -> Bag ErrMsg -> [FileDiagnostic] diagFromErrMsgs diagSource dflags = concatMap (diagFromErrMsg diagSource dflags) . bagToList---- | Merges two sorted lists of diagnostics, removing duplicates.---   Assumes all the diagnostics are for the same file.-mergeDiagnostics :: [FileDiagnostic] -> [FileDiagnostic] -> [FileDiagnostic]-mergeDiagnostics aa [] = aa-mergeDiagnostics [] bb = bb-mergeDiagnostics (a@(_,_,ad@Diagnostic{_range = ar}):aa) (b@(_,_,bd@Diagnostic{_range=br}):bb)-  | ar < br-  = a : mergeDiagnostics aa (b:bb)-  | br < ar-  = b : mergeDiagnostics (a:aa) bb-  | _severity ad == _severity bd-  && _source ad == _source bd-  && _message ad == _message bd-  && _code ad == _code bd-  && _relatedInformation ad == _relatedInformation bd-  && _tags ad == _tags bd-  = a : mergeDiagnostics aa bb-  | otherwise-  = a : b : mergeDiagnostics aa bb  -- | Convert a GHC SrcSpan to a DAML compiler Range srcSpanToRange :: SrcSpan -> Range
src/Development/IDE/GHC/Orphans.hs view
@@ -70,3 +70,8 @@  instance NFData HieFile where     rnf = rwhnf++deriving instance Eq SourceModified+deriving instance Show SourceModified+instance NFData SourceModified where+    rnf = rwhnf
src/Development/IDE/GHC/Util.hs view
@@ -4,7 +4,8 @@ -- | General utility functions, mostly focused around GHC operations. module Development.IDE.GHC.Util(     -- * HcsEnv and environment-    HscEnvEq(GhcVersionMismatch, compileTime, runTime), hscEnv, newHscEnvEq,+    HscEnvEq,+    hscEnv, newHscEnvEq,     modifyDynFlags,     evalGhcEnv,     runGhcEnv,@@ -16,6 +17,7 @@     ParseResult(..), runParser,     lookupPackageConfig,     textToStringBuffer,+    bytestringToStringBuffer,     stringBufferToByteString,     moduleImportPath,     cgGutsToCoreModule,@@ -24,8 +26,8 @@     -- * General utilities     readFileUtf8,     hDuplicateTo',-    setDefaultHieDir,-    dontWriteHieFiles+    setHieDir,+    dontWriteHieFiles,     ) where  import Control.Concurrent@@ -38,7 +40,6 @@ import GhcMonad import Control.Exception import Data.IORef-import Data.Version (showVersion, Version) import FileCleanup import Foreign.Ptr import Foreign.ForeignPtr@@ -113,6 +114,9 @@ stringBufferToByteString :: StringBuffer -> ByteString stringBufferToByteString StringBuffer{..} = PS buf cur len +bytestringToStringBuffer :: ByteString -> StringBuffer+bytestringToStringBuffer (PS buf cur len) = StringBuffer{..}+ -- | Pretty print a GHC value using 'unsafeGlobalDynFlags '. prettyPrint :: Outputable a => a -> String prettyPrint = showSDoc unsafeGlobalDynFlags . ppr@@ -170,9 +174,6 @@                [(InstalledUnitId, DynFlags)] -- In memory components for this HscEnv                -- This is only used at the moment for the import dirs in                -- the DynFlags-    | GhcVersionMismatch { compileTime :: !Version-                         , runTime     :: !Version-                         }  -- | Unwrap an 'HsEnvEq'. hscEnv :: HscEnvEq -> HscEnv@@ -180,18 +181,8 @@  hscEnv' :: HscEnvEq -> Either String HscEnv hscEnv' (HscEnvEq _ x _) = Right x-hscEnv' GhcVersionMismatch{..} = Left $-    unwords-        ["ghcide compiled against GHC"-        ,showVersion compileTime-        ,"but currently using"-        ,showVersion runTime-        ,". This is unsupported, ghcide must be compiled with the same GHC version as the project."-        ]- deps :: HscEnvEq -> [(InstalledUnitId, DynFlags)] deps (HscEnvEq _ _ u) = u-deps GhcVersionMismatch{} = []  -- | Wrap an 'HscEnv' into an 'HscEnvEq'. newHscEnvEq :: HscEnv -> [(InstalledUnitId, DynFlags)] -> IO HscEnvEq@@ -199,20 +190,15 @@  instance Show HscEnvEq where   show (HscEnvEq a _ _) = "HscEnvEq " ++ show (hashUnique a)-  show GhcVersionMismatch{..} = "GhcVersionMismatch " <> show (compileTime, runTime)  instance Eq HscEnvEq where   HscEnvEq a _ _ == HscEnvEq b _ _ = a == b-  GhcVersionMismatch a b == GhcVersionMismatch c d = a == c && b == d-  _ == _ = False  instance NFData HscEnvEq where   rnf (HscEnvEq a b c) = rnf (hashUnique a) `seq` b `seq` c `seq` ()-  rnf GhcVersionMismatch{} = rnf runTime  instance Hashable HscEnvEq where   hashWithSalt s (HscEnvEq a _b _c) = hashWithSalt s a-  hashWithSalt salt GhcVersionMismatch{..} = hashWithSalt salt (compileTime, runTime)  -- Fake instance needed to persuade Shake to accept this type as a key. -- No harm done as ghcide never persists these keys currently
src/Development/IDE/LSP/HoverDefinition.hs view
@@ -6,17 +6,18 @@ module Development.IDE.LSP.HoverDefinition     ( setHandlersHover     , setHandlersDefinition+    , setHandlersTypeDefinition     -- * For haskell-language-server     , hover     , gotoDefinition+    , gotoTypeDefinition     ) where  import           Development.IDE.Core.Rules-import           Development.IDE.Core.Service+import           Development.IDE.Core.Shake import           Development.IDE.LSP.Server import           Development.IDE.Types.Location import           Development.IDE.Types.Logger-import           Development.Shake import qualified Language.Haskell.LSP.Core       as LSP import           Language.Haskell.LSP.Messages import           Language.Haskell.LSP.Types@@ -25,23 +26,27 @@  gotoDefinition :: IdeState -> TextDocumentPositionParams -> IO (Either ResponseError LocationResponseParams) hover          :: IdeState -> TextDocumentPositionParams -> IO (Either ResponseError (Maybe Hover))+gotoTypeDefinition :: IdeState -> TextDocumentPositionParams -> IO (Either ResponseError LocationResponseParams) gotoDefinition = request "Definition" getDefinition (MultiLoc []) SingleLoc+gotoTypeDefinition = request "TypeDefinition" getTypeDefinition (MultiLoc []) MultiLoc hover          = request "Hover"      getAtPoint     Nothing      foundHover  foundHover :: (Maybe Range, [T.Text]) -> Maybe Hover foundHover (mbRange, contents) =   Just $ Hover (HoverContents $ MarkupContent MkMarkdown $ T.intercalate sectionSeparator contents) mbRange -setHandlersDefinition, setHandlersHover :: PartialHandlers c+setHandlersDefinition, setHandlersHover, setHandlersTypeDefinition :: PartialHandlers c setHandlersDefinition = PartialHandlers $ \WithMessage{..} x ->   return x{LSP.definitionHandler = withResponse RspDefinition $ const gotoDefinition}+setHandlersTypeDefinition = PartialHandlers $ \WithMessage{..} x ->+  return x{LSP.typeDefinitionHandler = withResponse RspDefinition $ const gotoTypeDefinition} setHandlersHover      = PartialHandlers $ \WithMessage{..} x ->   return x{LSP.hoverHandler      = withResponse RspHover      $ const hover}  -- | Respond to and log a hover or go-to-definition request request   :: T.Text-  -> (NormalizedFilePath -> Position -> Action (Maybe a))+  -> (NormalizedFilePath -> Position -> IdeAction (Maybe a))   -> b   -> (a -> b)   -> IdeState@@ -53,10 +58,10 @@         Nothing   -> pure Nothing     pure $ Right $ maybe notFound found mbResult -logAndRunRequest :: T.Text -> (NormalizedFilePath -> Position -> Action b) -> IdeState -> Position -> String -> IO b+logAndRunRequest :: T.Text -> (NormalizedFilePath -> Position -> IdeAction b) -> IdeState -> Position -> String -> IO b logAndRunRequest label getResults ide pos path = do   let filePath = toNormalizedFilePath' path   logInfo (ideLogger ide) $     label <> " request at position " <> T.pack (showPosition pos) <>     " in file: " <> T.pack path-  runAction ide $ getResults filePath pos+  runIdeAction (T.unpack label) (shakeExtras ide) (getResults filePath pos)
src/Development/IDE/LSP/LanguageServer.hs view
@@ -2,6 +2,7 @@ -- SPDX-License-Identifier: Apache-2.0  {-# LANGUAGE ExistentialQuantification  #-}+{-# LANGUAGE RankNTypes                 #-}  -- WARNING: A copy of DA.Daml.LanguageServer, try to keep them in sync -- This version removes the daml: handling@@ -44,7 +45,8 @@     -> PartialHandlers config     -> (InitializeRequest -> Either T.Text config)     -> (DidChangeConfigurationNotification -> Either T.Text config)-    -> (IO LspId -> (FromServerMessage -> IO ()) -> VFSHandle -> ClientCapabilities -> IO IdeState)+    -> (IO LspId -> (FromServerMessage -> IO ()) -> VFSHandle -> ClientCapabilities+        -> WithProgressFunc -> WithIndefiniteProgressFunc -> IO IdeState)     -> IO () runLanguageServer options userHandlers onInitialConfig onConfigChange getIdeState = do     -- Move stdout to another file descriptor and duplicate stderr@@ -101,7 +103,7 @@     let PartialHandlers parts =             initializeRequestHandler <>             setHandlersIgnore <> -- least important-            setHandlersDefinition <> setHandlersHover <>+            setHandlersDefinition <> setHandlersHover <> setHandlersTypeDefinition <>             setHandlersOutline <>             userHandlers <>             setHandlersNotifications <> -- absolutely critical, join them with user notifications@@ -131,6 +133,7 @@         handleInit exitClientMsg clearReqId waitForCancel clientMsgChan lspFuncs@LSP.LspFuncs{..} = do              ide <- getIdeState getNextReqId sendFunc (makeLSPVFSHandle lspFuncs) clientCapabilities+                               withProgress withIndefiniteProgress              _ <- flip forkFinally (const exitClientMsg) $ forever $ do                 msg <- readChan clientMsgChan
src/Development/IDE/LSP/Notifications.hs view
@@ -24,7 +24,7 @@ import qualified Data.HashSet                     as S import qualified Data.Text                        as Text -import           Development.IDE.Core.FileStore   (setSomethingModified)+import           Development.IDE.Core.FileStore   (setSomethingModified, setFileModified) import           Development.IDE.Core.FileExists  (modifyFileExists) import           Development.IDE.Core.OfInterest @@ -39,17 +39,18 @@             updatePositionMapping ide (VersionedTextDocumentIdentifier _uri (Just _version)) (List [])             whenUriFile _uri $ \file -> do                 modifyFilesOfInterest ide (S.insert file)+                setFileModified ide file                 logInfo (ideLogger ide) $ "Opened text document: " <> getUri _uri      ,LSP.didChangeTextDocumentNotificationHandler = withNotification (LSP.didChangeTextDocumentNotificationHandler x) $         \_ ide (DidChangeTextDocumentParams identifier@VersionedTextDocumentIdentifier{_uri} changes) -> do             updatePositionMapping ide identifier changes-            setSomethingModified ide+            whenUriFile _uri $ \file -> setFileModified ide file             logInfo (ideLogger ide) $ "Modified text document: " <> getUri _uri      ,LSP.didSaveTextDocumentNotificationHandler = withNotification (LSP.didSaveTextDocumentNotificationHandler x) $         \_ ide (DidSaveTextDocumentParams TextDocumentIdentifier{_uri}) -> do-            setSomethingModified ide+            whenUriFile _uri $ \file -> setFileModified ide file             logInfo (ideLogger ide) $ "Saved text document: " <> getUri _uri      ,LSP.didCloseTextDocumentNotificationHandler = withNotification (LSP.didCloseTextDocumentNotificationHandler x) $
src/Development/IDE/LSP/Outline.hs view
@@ -40,7 +40,7 @@ moduleOutline _lsp ideState DocumentSymbolParams { _textDocument = TextDocumentIdentifier uri }   = case uriToFilePath uri of     Just (toNormalizedFilePath' -> fp) -> do-      mb_decls <- runAction ideState $ use GetParsedModule fp+      mb_decls <- fmap fst <$> runIdeAction "Outline" (shakeExtras ideState) (useWithStaleFast GetParsedModule fp)       pure $ Right $ case mb_decls of         Nothing -> DSDocumentSymbols (List [])         Just ParsedModule { pm_parsed_source = L _ltop HsModule { hsmodName, hsmodDecls, hsmodImports } }
src/Development/IDE/Plugin/CodeAction.hs view
@@ -17,8 +17,7 @@     , executeAddSignatureCommand     ) where -import           Language.Haskell.LSP.Types-import Control.Monad (join)+import Control.Monad (join, guard) import Development.IDE.Plugin import Development.IDE.GHC.Compat import Development.IDE.Core.Rules@@ -38,21 +37,27 @@ import qualified Language.Haskell.LSP.Core as LSP import Language.Haskell.LSP.VFS import Language.Haskell.LSP.Messages+import Language.Haskell.LSP.Types import qualified Data.Rope.UTF16 as Rope import Data.Aeson.Types (toJSON, fromJSON, Value(..), Result(..))-import Control.Monad.Trans.Maybe import Data.Char import Data.Maybe import Data.List.Extra import qualified Data.Text as T import Data.Tuple.Extra ((&&&)) import HscTypes+import SrcLoc (sortLocated) import Parser import Text.Regex.TDFA ((=~), (=~~)) import Text.Regex.TDFA.Text() import Outputable (ppr, showSDocUnsafe) import DynFlags (xFlags, FlagSpec(..)) import GHC.LanguageExtensions.Type (Extension)+import Data.Function+import Control.Arrow ((>>>))+import Data.Functor+import Control.Applicative ((<|>))+import Safe (atMay)  plugin :: Plugin c plugin = codeActionPluginWithRules rules codeAction <> Plugin mempty setHandlersCodeLens@@ -69,16 +74,15 @@     -> CodeActionContext     -> IO (Either ResponseError [CAResult]) codeAction lsp state (TextDocumentIdentifier uri) _range CodeActionContext{_diagnostics=List xs} = do-    -- disable logging as its quite verbose-    -- logInfo (ideLogger ide) $ T.pack $ "Code action req: " ++ show arg     contents <- LSP.getVirtualFileFunc lsp $ toNormalizedUri uri     let text = Rope.toText . (_text :: VirtualFile -> Rope.Rope) <$> contents         mbFile = toNormalizedFilePath' <$> uriToFilePath uri-    (ideOptions, parsedModule, join -> env) <- runAction state $+    (ideOptions, parsedModule, join -> env) <- runAction "CodeAction" state $       (,,) <$> getIdeOptions             <*> getParsedModule `traverse` mbFile             <*> use GhcSession `traverse` mbFile-    pkgExports <- runAction state $ (useNoFile_ . PackageExports) `traverse` env+    -- This is quite expensive 0.6-0.7s on GHC+    pkgExports <- runAction "CodeAction:PackageExports" state $ (useNoFile_ . PackageExports) `traverse` env     let dflags = hsc_dflags . hscEnv <$> env     pure $ Right         [ CACodeAction $ CodeAction title (Just CodeActionQuickFix) (Just $ List [x]) (Just edit) Nothing@@ -96,7 +100,7 @@     commandId <- makeLspCommandId "typesignature.add"     fmap (Right . List) $ case uriToFilePath' uri of       Just (toNormalizedFilePath' -> filePath) -> do-        _ <- runAction ideState $ runMaybeT $ useE TypeCheck filePath+        _ <- runAction "codeLens" ideState (use TypeCheck filePath)         diag <- getDiagnostics ideState         hDiag <- getHiddenDiagnostics ideState         pure@@ -143,10 +147,15 @@     , suggestModuleTypo diag     , suggestReplaceIdentifier text diag     , suggestSignature True diag+    , suggestConstraint text diag+    , removeRedundantConstraints text diag+    , suggestAddTypeAnnotationToSatisfyContraints text diag     ] ++ concat     [  suggestNewDefinition ideOptions pm text diag     ++ suggestRemoveRedundantImport pm text diag     ++ suggestNewImport packageExports pm diag+    ++ suggestDeleteTopBinding pm diag+    ++ suggestExportUnusedTopBinding text pm diag     | Just pm <- [parsedModule]]  @@ -169,6 +178,144 @@         = [("Remove import", [TextEdit (extendToWholeLineIfPossible contents _range) ""])]     | otherwise = [] +suggestDeleteTopBinding :: ParsedModule -> Diagnostic -> [(T.Text, [TextEdit])]+suggestDeleteTopBinding ParsedModule{pm_parsed_source = L _ HsModule{hsmodDecls}} Diagnostic{_range=_range,..}+-- Foo.hs:4:1: warning: [-Wunused-top-binds] Defined but not used: ‘f’+    | Just [name] <- matchRegex _message ".*Defined but not used: ‘([^ ]+)’"+    , let allTopLevel = filter (isTopLevel . fst)+                        . map (\(L l b) -> (srcSpanToRange l, b))+                        . sortLocated+                        $ hsmodDecls+          sameName = filter (matchesBindingName (T.unpack name) . snd) allTopLevel+    , not (null sameName)+            = [("Delete ‘" <> name <> "’", flip TextEdit "" . toNextBinding allTopLevel . fst <$> sameName )]+    | otherwise = []+    where+      isTopLevel l = (_character . _start) l == 0++      forwardLines lines r = r {_end = (_end r) {_line = (_line . _end $ r) + lines, _character = 0}}++      toNextBinding bindings r@Range { _end = Position {_line = l} }+        | Just (Range { _start = Position {_line = l'}}, _) <- find ((> l) . _line . _start . fst) bindings+        = forwardLines (l' - l) r+      toNextBinding _ r  = r++      matchesBindingName :: String -> HsDecl GhcPs -> Bool+      matchesBindingName b (ValD FunBind {fun_id=L _ x}) = showSDocUnsafe (ppr x) == b+      matchesBindingName b (SigD (TypeSig (L _ x:_) _)) = showSDocUnsafe (ppr x) == b+      matchesBindingName _ _ = False++data ExportsAs = ExportName | ExportPattern | ExportAll+  deriving (Eq)++suggestExportUnusedTopBinding :: Maybe T.Text -> ParsedModule -> Diagnostic -> [(T.Text, [TextEdit])]+suggestExportUnusedTopBinding srcOpt ParsedModule{pm_parsed_source = L _ HsModule{..}} Diagnostic{..}+-- Foo.hs:4:1: warning: [-Wunused-top-binds] Defined but not used: ‘f’+-- Foo.hs:5:1: warning: [-Wunused-top-binds] Defined but not used: type constructor or class ‘F’+-- Foo.hs:6:1: warning: [-Wunused-top-binds] Defined but not used: data constructor ‘Bar’+  | Just source <- srcOpt+  , Just [name] <- matchRegex _message ".*Defined but not used: ‘([^ ]+)’"+                   <|> matchRegex _message ".*Defined but not used: type constructor or class ‘([^ ]+)’"+                   <|> matchRegex _message ".*Defined but not used: data constructor ‘([^ ]+)’"+  , Just (exportType, _) <- find (matchWithDiagnostic _range . snd)+                            . mapMaybe+                                (\(L l b) -> if isTopLevel $ srcSpanToRange l+                                                then exportsAs b else Nothing)+                            $ hsmodDecls+  , Just pos <- _end . getLocatedRange <$> hsmodExports+  , Just needComma <- needsComma source <$> hsmodExports+  , let exportName = (if needComma then "," else "") <> printExport exportType name +        insertPos = pos {_character = pred $ _character pos}+  = [("Export ‘" <> name <> "’", [TextEdit (Range insertPos insertPos) exportName])]+  | otherwise = []+  where+    -- we get the last export and the closing bracket and check for comma in that range+    needsComma :: T.Text -> Located [LIE GhcPs] -> Bool+    needsComma _ (L _ []) = False+    needsComma source x@(L _ exports) =+      let closeParan = _end $ getLocatedRange x+          lastExport = _end . getLocatedRange $ last exports+      in not $ T.isInfixOf "," $ textInRange (Range lastExport closeParan) source++    getLocatedRange :: Located a -> Range+    getLocatedRange = srcSpanToRange . getLoc++    matchWithDiagnostic :: Range -> Located (IdP GhcPs) -> Bool+    matchWithDiagnostic Range{_start=l,_end=r} x =+      let loc = _start . getLocatedRange $ x+       in loc >= l && loc <= r++    printExport :: ExportsAs -> T.Text -> T.Text+    printExport ExportName x = x+    printExport ExportPattern x = "pattern " <> x+    printExport ExportAll x = x <> "(..)"++    isTopLevel :: Range -> Bool+    isTopLevel l = (_character . _start) l == 0++    exportsAs :: HsDecl p -> Maybe (ExportsAs, Located (IdP p))+    exportsAs (ValD FunBind {fun_id})          = Just (ExportName, fun_id)+    exportsAs (ValD (PatSynBind PSB {psb_id})) = Just (ExportPattern, psb_id)+    exportsAs (TyClD SynDecl{tcdLName})      = Just (ExportName, tcdLName)+    exportsAs (TyClD DataDecl{tcdLName})     = Just (ExportAll, tcdLName)+    exportsAs (TyClD ClassDecl{tcdLName})    = Just (ExportAll, tcdLName)+    exportsAs (TyClD FamDecl{tcdFam})        = Just (ExportAll, fdLName tcdFam)+    exportsAs _                                = Nothing++suggestAddTypeAnnotationToSatisfyContraints :: Maybe T.Text -> Diagnostic -> [(T.Text, [TextEdit])]+suggestAddTypeAnnotationToSatisfyContraints sourceOpt Diagnostic{_range=_range,..}+-- File.hs:52:41: warning:+--     * Defaulting the following constraint to type ‘Integer’+--        Num p0 arising from the literal ‘1’+--     * In the expression: 1+--       In an equation for ‘f’: f = 1+-- File.hs:52:41: warning:+--     * Defaulting the following constraints to type ‘[Char]’+--        (Show a0)+--          arising from a use of ‘traceShow’+--          at A.hs:228:7-25+--        (IsString a0)+--          arising from the literal ‘"debug"’+--          at A.hs:228:17-23+--     * In the expression: traceShow "debug" a+--       In an equation for ‘f’: f a = traceShow "debug" a+-- File.hs:52:41: warning:+--     * Defaulting the following constraints to type ‘[Char]’+--         (Show a0)+--          arising from a use of ‘traceShow’+--          at A.hs:255:28-43+--        (IsString a0)+--          arising from the literal ‘"test"’+--          at /Users/serhiip/workspace/ghcide/src/Development/IDE/Plugin/CodeAction.hs:255:38-43+--     * In the fourth argument of ‘seq’, namely ‘(traceShow "test")’+--       In the expression: seq "test" seq "test" (traceShow "test")+--       In an equation for ‘f’:+--          f = seq "test" seq "test" (traceShow "test")+    | Just [ty, lit] <- matchRegex _message (pat False False True)+                        <|> matchRegex _message (pat False False False)+            = codeEdit ty lit (makeAnnotatedLit ty lit)+    | Just source <- sourceOpt+    , Just [ty, lit] <- matchRegex _message (pat True True False)+            = let lit' = makeAnnotatedLit ty lit;+                  tir = textInRange _range source+              in codeEdit ty lit (T.replace lit lit' tir)+    | otherwise = []+    where+      makeAnnotatedLit ty lit = "(" <> lit <> " :: " <> ty <> ")"+      pat multiple at inThe = T.concat [ ".*Defaulting the following constraint"+                                       , if multiple then "s" else ""+                                       , " to type ‘([^ ]+)’ "+                                       , ".*arising from the literal ‘(.+)’"+                                       , if inThe then ".+In the.+argument" else ""+                                       , if at then ".+at" else ""+                                       , ".+In the expression"+                                       ]+      codeEdit ty lit replacement =+        let title = "Add type annotation ‘" <> ty <> "’ to ‘" <> lit <> "’"+            edits = [TextEdit _range replacement]+        in  [( title, edits )]++ suggestReplaceIdentifier :: Maybe T.Text -> Diagnostic -> [(T.Text, [TextEdit])] suggestReplaceIdentifier contents Diagnostic{_range=_range,..} -- File.hs:52:41: error:@@ -255,7 +402,11 @@  -- | All the GHC extensions ghcExtensions :: Map.HashMap T.Text Extension-ghcExtensions = Map.fromList . map ( ( T.pack . flagSpecName ) &&& flagSpecFlag ) $ xFlags+ghcExtensions = Map.fromList . filter notStrictFlag . map ( ( T.pack . flagSpecName ) &&& flagSpecFlag ) $ xFlags+  where+    -- Strict often causes false positives, as in Data.Map.Strict imports.+    -- See discussion at https://github.com/digital-asset/ghcide/pull/638+    notStrictFlag (name, _) = name /= "Strict"  suggestModuleTypo :: Diagnostic -> [(T.Text, [TextEdit])] suggestModuleTypo Diagnostic{_range=_range,..}@@ -359,6 +510,217 @@             = 0  suggestSignature _ _ = []++-- | Suggests a constraint for a declaration for which a constraint is missing.+suggestConstraint :: Maybe T.Text -> Diagnostic -> [(T.Text, [TextEdit])]+suggestConstraint mContents diag@Diagnostic {..}+  | Just contents <- mContents+  , Just missingConstraint <- findMissingConstraint _message+  = let codeAction = if _message =~ ("the type signature for:" :: String)+                        then suggestFunctionConstraint+                        else suggestInstanceConstraint+     in codeAction contents diag missingConstraint+  | otherwise = []+    where+      findMissingConstraint :: T.Text -> Maybe T.Text+      findMissingConstraint t =+        let regex = "(No instance for|Could not deduce) \\((.+)\\) arising from a use of"+         in matchRegex t regex <&> last++normalizeConstraints :: T.Text -> T.Text -> T.Text+normalizeConstraints existingConstraints constraint =+  let constraintsInit = if "(" `T.isPrefixOf` existingConstraints+                           then T.dropEnd 1 existingConstraints+                           else "(" <> existingConstraints+   in constraintsInit <> ", " <> constraint <> ")"++-- | Suggests a constraint for an instance declaration for which a constraint is missing.+suggestInstanceConstraint :: T.Text -> Diagnostic -> T.Text -> [(T.Text, [TextEdit])]+suggestInstanceConstraint contents Diagnostic {..} missingConstraint+-- Suggests a constraint for an instance declaration with no existing constraints.+-- • No instance for (Eq a) arising from a use of ‘==’+--   Possible fix: add (Eq a) to the context of the instance declaration+-- • In the expression: x == y+--   In an equation for ‘==’: (Wrap x) == (Wrap y) = x == y+--   In the instance declaration for ‘Eq (Wrap a)’+  | Just [instanceDeclaration] <- matchRegex _message "In the instance declaration for ‘([^`]*)’"+  = let instanceLine = contents+          & T.splitOn ("instance " <> instanceDeclaration)+          & head & T.lines & length+        startOfConstraint = Position instanceLine (length ("instance " :: String))+        range = Range startOfConstraint startOfConstraint+        newConstraint = missingConstraint <> " => "+     in [(actionTitle missingConstraint, [TextEdit range newConstraint])]++-- Suggests a constraint for an instance declaration with one or more existing constraints.+-- • Could not deduce (Eq b) arising from a use of ‘==’+--   from the context: Eq a+--     bound by the instance declaration at /path/to/Main.hs:7:10-32+--   Possible fix: add (Eq b) to the context of the instance declaration+-- • In the second argument of ‘(&&)’, namely ‘x' == y'’+--   In the expression: x == y && x' == y'+--   In an equation for ‘==’:+--       (Pair x x') == (Pair y y') = x == y && x' == y'+  | Just [instanceLineStr, constraintFirstCharStr]+    <- matchRegex _message "bound by the instance declaration at .+:([0-9]+):([0-9]+)"+  = let existingConstraints = findExistingConstraints _message+        newConstraints = normalizeConstraints existingConstraints missingConstraint+        instanceLine = readPositionNumber instanceLineStr+        constraintFirstChar = readPositionNumber constraintFirstCharStr+        startOfConstraint = Position instanceLine constraintFirstChar+        endOfConstraint = Position instanceLine $+          constraintFirstChar + T.length existingConstraints+        range = Range startOfConstraint endOfConstraint+     in [(actionTitle missingConstraint, [TextEdit range newConstraints])]+  | otherwise = []+    where+      findExistingConstraints :: T.Text -> T.Text+      findExistingConstraints t =+        T.replace "from the context: " "" . T.strip $ T.lines t !! 1++      readPositionNumber :: T.Text -> Int+      readPositionNumber = T.unpack >>> read >>> pred++      actionTitle :: T.Text -> T.Text+      actionTitle constraint = "Add `" <> constraint+        <> "` to the context of the instance declaration"++findTypeSignatureName :: T.Text -> Maybe T.Text+findTypeSignatureName t = matchRegex t "([^ ]+) :: " <&> head++findTypeSignatureLine :: T.Text -> T.Text -> Int+findTypeSignatureLine contents typeSignatureName =+  T.splitOn (typeSignatureName <> " :: ") contents & head & T.lines & length++-- | Suggests a constraint for a type signature for which a constraint is missing.+suggestFunctionConstraint :: T.Text -> Diagnostic -> T.Text -> [(T.Text, [TextEdit])]+suggestFunctionConstraint contents Diagnostic{..} missingConstraint+-- Suggests a constraint for a type signature with any number of existing constraints.+-- • No instance for (Eq a) arising from a use of ‘==’+--   Possible fix:+--     add (Eq a) to the context of+--       the type signature for:+--         eq :: forall a. a -> a -> Bool+-- • In the expression: x == y+--   In an equation for ‘eq’: eq x y = x == y++-- • Could not deduce (Eq b) arising from a use of ‘==’+--   from the context: Eq a+--     bound by the type signature for:+--                eq :: forall a b. Eq a => Pair a b -> Pair a b -> Bool+--     at Main.hs:5:1-42+--   Possible fix:+--     add (Eq b) to the context of+--       the type signature for:+--         eq :: forall a b. Eq a => Pair a b -> Pair a b -> Bool+-- • In the second argument of ‘(&&)’, namely ‘y == y'’+--   In the expression: x == x' && y == y'+--   In an equation for ‘eq’:+--       eq (Pair x y) (Pair x' y') = x == x' && y == y'+  | Just typeSignatureName <- findTypeSignatureName _message+  = let mExistingConstraints = findExistingConstraints _message+        newConstraint = buildNewConstraints missingConstraint mExistingConstraints+        typeSignatureLine = findTypeSignatureLine contents typeSignatureName+        typeSignatureFirstChar = T.length $ typeSignatureName <> " :: "+        startOfConstraint = Position typeSignatureLine typeSignatureFirstChar+        endOfConstraint = Position typeSignatureLine $+          typeSignatureFirstChar + maybe 0 T.length mExistingConstraints+        range = Range startOfConstraint endOfConstraint+     in [(actionTitle missingConstraint typeSignatureName, [TextEdit range newConstraint])]+  | otherwise = []+    where+      findExistingConstraints :: T.Text -> Maybe T.Text+      findExistingConstraints message =+        if message =~ ("from the context:" :: String)+           then fmap (T.strip . head) $ matchRegex message "\\. ([^=]+)"+           else Nothing++      buildNewConstraints :: T.Text -> Maybe T.Text -> T.Text+      buildNewConstraints constraint mExistingConstraints =+        case mExistingConstraints of+          Just existingConstraints -> normalizeConstraints existingConstraints constraint+          Nothing -> constraint <> " => "++      actionTitle :: T.Text -> T.Text -> T.Text+      actionTitle constraint typeSignatureName = "Add `" <> constraint+        <> "` to the context of the type signature for `" <> typeSignatureName <> "`"++-- | Suggests the removal of a redundant constraint for a type signature.+removeRedundantConstraints :: Maybe T.Text -> Diagnostic -> [(T.Text, [TextEdit])]+removeRedundantConstraints mContents Diagnostic{..}+-- • Redundant constraint: Eq a+-- • In the type signature for:+--      foo :: forall a. Eq a => a -> a+-- • Redundant constraints: (Monoid a, Show a)+-- • In the type signature for:+--      foo :: forall a. (Num a, Monoid a, Eq a, Show a) => a -> Bool+  | Just contents <- mContents+  -- Account for both "Redundant constraint" and "Redundant constraints".+  , True <- "Redundant constraint" `T.isInfixOf` _message+  , Just typeSignatureName <- findTypeSignatureName _message+  , Just redundantConstraintList <- findRedundantConstraints _message+  , Just constraints <- findConstraints contents typeSignatureName+  = let constraintList = parseConstraints constraints+        newConstraints = buildNewConstraints constraintList redundantConstraintList+        typeSignatureLine = findTypeSignatureLine contents typeSignatureName+        typeSignatureFirstChar = T.length $ typeSignatureName <> " :: "+        startOfConstraint = Position typeSignatureLine typeSignatureFirstChar+        endOfConstraint = Position typeSignatureLine $+          typeSignatureFirstChar + T.length (constraints <> " => ")+        range = Range startOfConstraint endOfConstraint+     in [(actionTitle redundantConstraintList typeSignatureName, [TextEdit range newConstraints])]+  | otherwise = []+    where+      parseConstraints :: T.Text -> [T.Text]+      parseConstraints t = t+        & (T.strip >>> stripConstraintsParens >>> T.splitOn ",")+        <&> T.strip++      stripConstraintsParens :: T.Text -> T.Text+      stripConstraintsParens constraints =+        if "(" `T.isPrefixOf` constraints+           then constraints & T.drop 1 & T.dropEnd 1 & T.strip+           else constraints++      findRedundantConstraints :: T.Text -> Maybe [T.Text]+      findRedundantConstraints t = t+        & T.lines+        & head+        & T.strip+        & (`matchRegex` "Redundant constraints?: (.+)")+        <&> (head >>> parseConstraints)++      -- If the type signature is not formatted as expected (arbitrary number of spaces,+      -- line feeds...), just fail.+      findConstraints :: T.Text -> T.Text -> Maybe T.Text+      findConstraints contents typeSignatureName = do+        constraints <- contents+          & T.splitOn (typeSignatureName <> " :: ")+          & (`atMay` 1)+          >>= (T.splitOn " => " >>> (`atMay` 0))+        guard $ not $ "\n" `T.isInfixOf` constraints || T.strip constraints /= constraints+        return constraints++      formatConstraints :: [T.Text] -> T.Text+      formatConstraints [] = ""+      formatConstraints [constraint] = constraint+      formatConstraints constraintList = constraintList+        & T.intercalate ", "+        & \cs -> "(" <> cs <> ")"++      formatConstraintsWithArrow :: [T.Text] -> T.Text+      formatConstraintsWithArrow [] = ""+      formatConstraintsWithArrow cs = cs & formatConstraints & (<> " => ")++      buildNewConstraints :: [T.Text] -> [T.Text] -> T.Text+      buildNewConstraints constraintList redundantConstraintList =+        formatConstraintsWithArrow $ constraintList \\ redundantConstraintList++      actionTitle :: [T.Text] -> T.Text -> T.Text+      actionTitle constraintList typeSignatureName =+        "Remove redundant constraint" <> (if length constraintList == 1 then "" else "s") <> " `"+        <> formatConstraints constraintList+        <> "` from the context of the type signature for `" <> typeSignatureName <> "`"  ------------------------------------------------------------------------------------------------- 
src/Development/IDE/Plugin/Completions.hs view
@@ -18,23 +18,48 @@ import Development.IDE.Core.Service import Development.IDE.Plugin.Completions.Logic import Development.IDE.Types.Location+import Development.IDE.Types.Options+import Development.IDE.Core.Compile import Development.IDE.Core.PositionMapping import Development.IDE.Core.RuleTypes import Development.IDE.Core.Shake+import Development.IDE.GHC.Compat (hsmodExports, ParsedModule(..), ModSummary (ms_hspp_buf))+ import Development.IDE.GHC.Util import Development.IDE.LSP.Server+import Control.Monad.Trans.Except (runExceptT)+import HscTypes (HscEnv(hsc_dflags))+import Data.Maybe+import Data.Functor ((<&>))  #if !MIN_GHC_API_VERSION(8,6,0) || defined(GHC_LIB)-import Data.Maybe import Development.IDE.Import.DependencyInformation #endif  plugin :: Plugin c plugin = Plugin produceCompletions setHandlersCompletion + produceCompletions :: Rules ()-produceCompletions =+produceCompletions = do     define $ \ProduceCompletions file -> do+        local <- useWithStale LocalCompletions file+        nonLocal <- useWithStale NonLocalCompletions file+        let extract = fmap fst+        return ([], extract local <> extract nonLocal)+    define $ \LocalCompletions file -> do+        pm <- useWithStale GetParsedModule file+        case pm of+            Just (pm, _) -> do+                let cdata = localCompletionsForParsedModule pm+                return ([], Just cdata)+            _ -> return ([], Nothing)+    define $ \NonLocalCompletions file -> do+        -- For non local completions we avoid depending on the parsed module,+        -- synthetizing a fake module with an empty body from the buffer+        -- in the ModSummary, which preserves all the imports+        ms <- fmap fst <$> useWithStale GetModSummaryWithoutTimestamps file+        sess <- fmap fst <$> useWithStale GhcSessionDeps file  -- When possible, rely on the haddocks embedded in our interface files -- This creates problems on ghc-lib, see comment on 'getDocumentationTryGhc'@@ -44,18 +69,42 @@         deps <- maybe (TransitiveDependencies [] [] []) fst <$> useWithStale GetDependencies file         parsedDeps <- mapMaybe (fmap fst) <$> usesWithStale GetParsedModule (transitiveModuleDeps deps) #endif-        tm <- fmap fst <$> useWithStale TypeCheck file-        packageState <- fmap (hscEnv . fst) <$> useWithStale GhcSession file-        case (tm, packageState) of-            (Just tm', Just packageState') -> do-                cdata <- liftIO $ cacheDataProducer packageState'-                                                    (tmrModule tm') parsedDeps-                return ([], Just cdata)-            _ -> return ([], Nothing) +        case (ms, sess) of+            (Just ms, Just sess) -> do+                -- After parsing the module remove all package imports referring to+                -- these packages as we have already dealt with what they map to.+                let env = hscEnv sess+                    buf = fromJust $ ms_hspp_buf ms+                    f = fromNormalizedFilePath file+                    dflags = hsc_dflags env+                pm <- liftIO $ evalGhcEnv env $ runExceptT $ parseHeader dflags f buf+                case pm of+                    Right (_diags, hsMod) -> do+                        let hsModNoExports = hsMod <&> \x -> x{hsmodExports = Nothing}+                            pm = ParsedModule+                                    { pm_mod_summary = ms+                                    , pm_parsed_source = hsModNoExports+                                    , pm_extra_src_files = [] -- src imports not allowed+                                    , pm_annotations = mempty+                                    }+                        tm <- liftIO $ typecheckModule (IdeDefer True) env pm+                        case tm of+                            (_, Just (_,TcModuleResult{..})) -> do+                                cdata <- liftIO $ cacheDataProducer env tmrModule parsedDeps+                                -- Do not return diags from parsing as they would duplicate+                                -- the diagnostics from typechecking+                                return ([], Just cdata)+                            (_diag, _) ->+                                return ([], Nothing)+                    Left _diag ->+                        return ([], Nothing)+            _ -> return ([], Nothing)  -- | Produce completions info for a file type instance RuleResult ProduceCompletions = CachedCompletions+type instance RuleResult LocalCompletions = CachedCompletions+type instance RuleResult NonLocalCompletions = CachedCompletions  data ProduceCompletions = ProduceCompletions     deriving (Eq, Show, Typeable, Generic)@@ -63,7 +112,19 @@ instance NFData   ProduceCompletions instance Binary   ProduceCompletions +data LocalCompletions = LocalCompletions+    deriving (Eq, Show, Typeable, Generic)+instance Hashable LocalCompletions+instance NFData   LocalCompletions+instance Binary   LocalCompletions +data NonLocalCompletions = NonLocalCompletions+    deriving (Eq, Show, Typeable, Generic)+instance Hashable NonLocalCompletions+instance NFData   NonLocalCompletions+instance Binary   NonLocalCompletions++ -- | Generate code actions. getCompletionsLSP     :: LSP.LspFuncs c@@ -78,10 +139,10 @@     fmap Right $ case (contents, uriToFilePath' uri) of       (Just cnts, Just path) -> do         let npath = toNormalizedFilePath' path-        (ideOpts, compls) <- runAction ide $ do-            opts <- getIdeOptions-            compls <- useWithStale ProduceCompletions npath-            pm <- useWithStale GetParsedModule npath+        (ideOpts, compls) <- runIdeAction "Completion" (shakeExtras ide) $ do+            opts <- liftIO $ getIdeOptionsIO $ shakeExtras ide+            compls <- useWithStaleFast ProduceCompletions npath+            pm <- useWithStaleFast GetParsedModule npath             pure (opts, liftA2 (,) compls pm)         case compls of           Just ((cci', _), (pm, mapping)) -> do@@ -91,6 +152,7 @@               (Just (VFS.PosPrefixInfo _ "" _ _), Just CompletionContext { _triggerCharacter = Just "."})                 -> return (Completions $ List [])               (Just pfix', _) -> do+                  -- TODO pass the real capabilities here (or remove the logic for snippets)                 let fakeClientCapabilities = ClientCapabilities Nothing Nothing Nothing Nothing                 Completions . List <$> getCompletions ideOpts cci' pm pfix' fakeClientCapabilities (WithSnippets True)               _ -> return (Completions $ List [])
src/Development/IDE/Plugin/Completions/Logic.hs view
@@ -4,8 +4,9 @@ module Development.IDE.Plugin.Completions.Logic (   CachedCompletions , cacheDataProducer+, localCompletionsForParsedModule , WithSnippets(..)-,getCompletions+, getCompletions ) where  import Control.Applicative@@ -17,7 +18,6 @@ import qualified Data.Text as T import qualified Text.Fuzzy as Fuzzy -import GHC import HscTypes import Name import RdrName@@ -36,12 +36,16 @@ import Language.Haskell.LSP.Types import Language.Haskell.LSP.Types.Capabilities import qualified Language.Haskell.LSP.VFS as VFS+import Development.IDE.Core.Compile import Development.IDE.Plugin.Completions.Types import Development.IDE.Spans.Documentation+import Development.IDE.GHC.Compat as GHC import Development.IDE.GHC.Error import Development.IDE.Types.Options import Development.IDE.Spans.Common import Development.IDE.GHC.Util+import Outputable (Outputable)+import qualified Data.Set as Set  -- From haskell-ide-engine/hie-plugin-api/Haskell/Ide/Engine/Context.hs @@ -130,59 +134,72 @@   | isDataOcc oc = CiConstructor   | otherwise    = CiVariable ++showModName :: ModuleName -> T.Text+showModName = T.pack . moduleNameString+ mkCompl :: IdeOptions -> CompItem -> CompletionItem-mkCompl IdeOptions{..} CI{origName,importedFrom,thingType,label,isInfix,docs} =+mkCompl IdeOptions{..} CI{compKind,insertText, importedFrom,typeText,label,docs} =   CompletionItem label kind (List []) ((colon <>) <$> typeText)     (Just $ CompletionDocMarkup $ MarkupContent MkMarkdown $ T.intercalate sectionSeparator docs')     Nothing Nothing Nothing Nothing (Just insertText) (Just Snippet)     Nothing Nothing Nothing Nothing Nothing-  where kind = Just $ occNameToComKind typeText $ occName origName-        insertText = case isInfix of+  where kind = Just compKind+        docs' = ("*Defined in '" <> importedFrom <> "'*\n") : spanDocToMarkdown docs+        colon = if optNewColonConvention then ": " else ":: "++mkNameCompItem :: Name -> ModuleName -> Maybe Type -> Maybe Backtick -> SpanDoc -> CompItem+mkNameCompItem origName origMod thingType isInfix docs = CI{..}+  where+    compKind = occNameToComKind typeText $ occName origName+    importedFrom = showModName origMod+    isTypeCompl = isTcOcc $ occName origName+    label = T.pack $ showGhc origName+    insertText = case isInfix of             Nothing -> case getArgText <$> thingType of                             Nothing -> label                             Just argText -> label <> " " <> argText             Just LeftSide -> label <> "`"              Just Surrounded -> label-        typeText+    typeText           | Just t <- thingType = Just . stripForall $ T.pack (showGhc t)           | otherwise = Nothing-        docs' = ("*Defined in '" <> importedFrom <> "'*\n") : spanDocToMarkdown docs-        colon = if optNewColonConvention then ": " else ":: " -stripForall :: T.Text -> T.Text-stripForall t-  | T.isPrefixOf "forall" t =-    -- We drop 2 to remove the '.' and the space after it-    T.drop 2 (T.dropWhile (/= '.') t)-  | otherwise               = t -getArgText :: Type -> T.Text-getArgText typ = argText-  where-    argTypes = getArgs typ-    argText :: T.Text-    argText =  mconcat $ List.intersperse " " $ zipWithFrom snippet 1 argTypes-    snippet :: Int -> Type -> T.Text-    snippet i t = T.pack $ "${" <> show i <> ":" <> showGhc t <> "}"-    getArgs :: Type -> [Type]-    getArgs t-      | isPredTy t = []-      | isDictTy t = []-      | isForAllTy t = getArgs $ snd (splitForAllTys t)-      | isFunTy t =-        let (args, ret) = splitFunTys t-          in if isForAllTy ret-              then getArgs ret-              else Prelude.filter (not . isDictTy) args-      | isPiTy t = getArgs $ snd (splitPiTys t)+    stripForall :: T.Text -> T.Text+    stripForall t+      | T.isPrefixOf "forall" t =+        -- We drop 2 to remove the '.' and the space after it+        T.drop 2 (T.dropWhile (/= '.') t)+      | otherwise               = t++    getArgText :: Type -> T.Text+    getArgText typ = argText+      where+        argTypes = getArgs typ+        argText :: T.Text+        argText =  mconcat $ List.intersperse " " $ zipWithFrom snippet 1 argTypes+        snippet :: Int -> Type -> T.Text+        snippet i t = T.pack $ "${" <> show i <> ":" <> showGhc t <> "}"+        getArgs :: Type -> [Type]+        getArgs t+          | isPredTy t = []+          | isDictTy t = []+          | isForAllTy t = getArgs $ snd (splitForAllTys t)+          | isFunTy t =+            let (args, ret) = splitFunTys t+              in if isForAllTy ret+                  then getArgs ret+                  else Prelude.filter (not . isDictTy) args+          | isPiTy t = getArgs $ snd (splitPiTys t) #if MIN_GHC_API_VERSION(8,10,0)-      | Just (Pair _ t) <- coercionKind <$> isCoercionTy_maybe t-      = getArgs t+          | Just (Pair _ t) <- coercionKind <$> isCoercionTy_maybe t+          = getArgs t #else-      | isCoercionTy t = maybe [] (getArgs . snd) (splitCoercionType_maybe t)+          | isCoercionTy t = maybe [] (getArgs . snd) (splitCoercionType_maybe t) #endif-      | otherwise = []+          | otherwise = []  mkModCompl :: T.Text -> CompletionItem mkModCompl label =@@ -214,15 +231,13 @@ cacheDataProducer packageState tm deps = do   let parsedMod = tm_parsed_module tm       dflags = hsc_dflags packageState-      curMod = moduleName $ ms_mod $ pm_mod_summary parsedMod+      curMod = ms_mod $ pm_mod_summary parsedMod+      curModName = moduleName curMod       Just (_,limports,_,_) = tm_renamed_source tm        iDeclToModName :: ImportDecl name -> ModuleName       iDeclToModName = unLoc . ideclName -      showModName :: ModuleName -> T.Text-      showModName = T.pack . moduleNameString-       asNamespace :: ImportDecl name -> ModuleName       asNamespace imp = maybe (iDeclToModName imp) GHC.unLoc (ideclAs imp)       -- Full canonical names of imported modules@@ -250,11 +265,11 @@         case lookupTypeEnv typeEnv n of           Just tt -> case safeTyThingId tt of             Just var -> (\x -> ([x],mempty)) <$> varToCompl var-            Nothing -> (\x -> ([x],mempty)) <$> toCompItem curMod n-          Nothing -> (\x -> ([x],mempty)) <$> toCompItem curMod n+            Nothing -> (\x -> ([x],mempty)) <$> toCompItem curMod curModName n+          Nothing -> (\x -> ([x],mempty)) <$> toCompItem curMod curModName n       getComplsForOne (GRE n _ False prov) =         flip foldMapM (map is_decl prov) $ \spec -> do-          compItem <- toCompItem (is_mod spec) n+          compItem <- toCompItem curMod (is_mod spec) n           let unqual                 | is_qual spec = []                 | otherwise = [compItem]@@ -269,23 +284,16 @@       varToCompl var = do         let typ = Just $ varType var             name = Var.varName var-            label = T.pack $ showGhc name-        docs <- evalGhcEnv packageState $ getDocumentationTryGhc (tm_parsed_module tm : deps) name-        return $ CI name (showModName curMod) typ label Nothing docs+        docs <- evalGhcEnv packageState $ getDocumentationTryGhc curMod (tm_parsed_module tm : deps) name+        return $ mkNameCompItem name curModName typ Nothing docs -      toCompItem :: ModuleName -> Name -> IO CompItem-      toCompItem mn n = do-        docs <- evalGhcEnv packageState $ getDocumentationTryGhc (tm_parsed_module tm : deps) n--- lookupName uses runInteractiveHsc, i.e., GHCi stuff which does not work with GHCi--- and leads to fun errors like "Cannot continue after interface file error".-#ifdef GHC_LIB-        let ty = Right Nothing-#else+      toCompItem :: Module -> ModuleName -> Name -> IO CompItem+      toCompItem m mn n = do+        docs <- evalGhcEnv packageState $ getDocumentationTryGhc curMod (tm_parsed_module tm : deps) n         ty <- evalGhcEnv packageState $ catchSrcErrors "completion" $ do-                name' <- lookupName n+                name' <- lookupName m n                 return $ name' >>= safeTyThingType-#endif-        return $ CI n (showModName mn) (either (const Nothing) id ty) (T.pack $ showGhc n) Nothing docs+        return $ mkNameCompItem n mn (either (const Nothing) id ty) Nothing docs    (unquals,quals) <- getCompls rdrElts @@ -296,6 +304,61 @@     , importableModules = moduleNames     } +-- | Produces completions from the top level declarations of a module.+localCompletionsForParsedModule :: ParsedModule -> CachedCompletions+localCompletionsForParsedModule pm@ParsedModule{pm_parsed_source = L _ HsModule{hsmodDecls, hsmodName}} =+    CC { allModNamesAsNS = mempty+       , unqualCompls = compls+       , qualCompls = mempty+       , importableModules = mempty+        }+  where+    typeSigIds = Set.fromList+        [ id+            | L _ (SigD (TypeSig ids _)) <- hsmodDecls+            , L _ id <- ids+            ]+    hasTypeSig = (`Set.member` typeSigIds) . unLoc++    compls = concat+        [ case decl of+            SigD (TypeSig ids typ) ->+                [mkComp id CiFunction (Just $ ppr typ) | id <- ids]+            ValD FunBind{fun_id} ->+                [ mkComp fun_id CiFunction Nothing+                | not (hasTypeSig fun_id)+                ]+            ValD PatBind{pat_lhs} ->+                [mkComp id CiVariable Nothing+                | VarPat id <- listify (\(_ :: Pat GhcPs) -> True) pat_lhs]+            TyClD ClassDecl{tcdLName, tcdSigs} ->+                mkComp tcdLName CiClass Nothing :+                [ mkComp id CiFunction (Just $ ppr typ)+                | L _ (TypeSig ids typ) <- tcdSigs+                , id <- ids]+            TyClD x ->+                [mkComp id cl Nothing+                | id <- listify (\(_ :: Located(IdP GhcPs)) -> True) x+                , let cl = occNameToComKind Nothing (rdrNameOcc $ unLoc id)]+            ForD ForeignImport{fd_name,fd_sig_ty} ->+                [mkComp fd_name CiVariable (Just $ ppr fd_sig_ty)]+            ForD ForeignExport{fd_name,fd_sig_ty} ->+                [mkComp fd_name CiVariable (Just $ ppr fd_sig_ty)]+            _ -> []+            | L _ decl <- hsmodDecls+        ]++    mkComp n ctyp ty =+        CI ctyp pn thisModName ty pn Nothing doc (ctyp `elem` [CiStruct, CiClass])+      where+        pn = ppr n+        doc = SpanDocText (getDocumentation [pm] n) (SpanDocUris Nothing Nothing)++    thisModName = ppr hsmodName++    ppr :: Outputable a => a -> T.Text+    ppr = T.pack . prettyPrint+ newtype WithSnippets = WithSnippets Bool  toggleSnippets :: ClientCapabilities -> WithSnippets -> CompletionItem -> CompletionItem@@ -340,7 +403,6 @@        filtCompls = map Fuzzy.original $ Fuzzy.filter prefixText ctxCompls "" "" label False         where-          isTypeCompl = isTcOcc . occName . origName           -- completions specific to the current context           ctxCompls' = case getCContext pos pm of                         Nothing -> compls
src/Development/IDE/Plugin/Completions/Types.hs view
@@ -5,34 +5,27 @@ import           Control.DeepSeq import qualified Data.Map  as Map import qualified Data.Text as T-import           GHC  import Development.IDE.Spans.Common+import Language.Haskell.LSP.Types (CompletionItemKind)  -- From haskell-ide-engine/src/Haskell/Ide/Engine/LSP/Completions.hs -data Backtick = Surrounded | LeftSide deriving Show+data Backtick = Surrounded | LeftSide+  deriving (Eq, Ord, Show)+ data CompItem = CI-  { origName     :: Name           -- ^ Original name, such as Maybe, //, or find.+  { compKind     :: CompletionItemKind+  , insertText   :: T.Text         -- ^ Snippet for the completion   , importedFrom :: T.Text         -- ^ From where this item is imported from.-  , thingType    :: Maybe Type     -- ^ Available type information.+  , typeText     :: Maybe T.Text   -- ^ Available type information.   , label        :: T.Text         -- ^ Label to display to the user.   , isInfix      :: Maybe Backtick -- ^ Did the completion happen                                    -- in the context of an infix notation.   , docs         :: SpanDoc        -- ^ Available documentation.+  , isTypeCompl  :: Bool   }-instance Show CompItem where-  show CI { .. } = "CompItem { origName = \"" ++ showGhc origName ++ "\""-                   ++ ", importedFrom = " ++ show importedFrom-                   ++ ", thingType = " ++ show (fmap showGhc thingType)-                   ++ ", label = " ++ show label-                   ++ ", isInfix = " ++ show isInfix -                   ++ ", docs = " ++ show docs-                   ++ " } "-instance Eq CompItem where-  ci1 == ci2 = origName ci1 == origName ci2-instance Ord CompItem where-  compare ci1 ci2 = origName ci1 `compare` origName ci2+  deriving (Eq, Show)  -- Associates a module's qualifier with its members newtype QualCompls@@ -56,3 +49,10 @@  instance NFData CachedCompletions where     rnf = rwhnf++instance Monoid CachedCompletions where+    mempty = CC mempty mempty mempty mempty++instance Semigroup CachedCompletions where+    CC a b c d <> CC a' b' c' d' =+        CC (a<>a') (b<>b') (c<>c') (d<>d')
src/Development/IDE/Spans/AtPoint.hs view
@@ -6,6 +6,7 @@ module Development.IDE.Spans.AtPoint (     atPoint   , gotoDefinition+  , gotoTypeDefinition   ) where  import           Development.IDE.GHC.Error@@ -16,10 +17,9 @@ import Development.IDE.GHC.Compat import Development.IDE.Types.Options import Development.IDE.Spans.Type as SpanInfo-import Development.IDE.Spans.Common (spanDocToMarkdown)+import Development.IDE.Spans.Common (showName, spanDocToMarkdown)  -- GHC API imports-import DynFlags import FastString import Name import Outputable hiding ((<>))@@ -29,21 +29,32 @@  import Control.Monad.Extra import Control.Monad.Trans.Maybe+import Control.Monad.Trans.Class import Control.Monad.IO.Class import           Data.Maybe import           Data.List import qualified Data.Text as T +gotoTypeDefinition+  :: MonadIO m+  => (Module -> MaybeT m (HieFile, FilePath))+  -> IdeOptions+  -> [SpanInfo]+  -> Position+  -> MaybeT m [Location]+gotoTypeDefinition getHieFile ideOpts srcSpans pos+  = typeLocationsAtPoint getHieFile ideOpts pos srcSpans+ -- | Locate the definition of the name at a given position. gotoDefinition   :: MonadIO m-  => (Module -> m (Maybe (HieFile, FilePath)))+  => (Module -> MaybeT m (HieFile, FilePath))   -> IdeOptions   -> [SpanInfo]   -> Position-  -> m (Maybe Location)+  -> MaybeT m Location gotoDefinition getHieFile ideOpts srcSpans pos =-  listToMaybe <$> locationsAtPoint getHieFile ideOpts pos srcSpans+  MaybeT . pure . listToMaybe =<< locationsAtPoint getHieFile ideOpts pos srcSpans  -- | Synopsis for the name at a given position. atPoint@@ -54,7 +65,10 @@ atPoint IdeOptions{..} (SpansInfo srcSpans cntsSpans) pos = do     firstSpan <- listToMaybe $ deEmpasizeGeneratedEqShow $ spansAtPoint pos srcSpans     let constraintsAtPoint = mapMaybe spaninfoType (spansAtPoint pos cntsSpans)-    return (Just (range firstSpan), hoverInfo firstSpan constraintsAtPoint)+        -- Filter out the empty lines so we don't end up with a bunch of+        -- horizontal separators with nothing inside of them+        text = filter (not . T.null) $ hoverInfo firstSpan constraintsAtPoint+    return (Just (range firstSpan), text)   where     -- Hover info for types, classes, type variables     hoverInfo SpanInfo{spaninfoType = Nothing , spaninfoDocs = docs ,  ..} _ =@@ -115,41 +129,75 @@         Just name -> any (`isInfixOf` getOccString name) ["==", "showsPrec"]         Nothing -> False +++typeLocationsAtPoint+  :: forall m+   . MonadIO m+  => (Module -> MaybeT m (HieFile, FilePath))+  -> IdeOptions+  -> Position+  -> [SpanInfo]+  -> MaybeT m [Location]+typeLocationsAtPoint getHieFile = querySpanInfoAt getTypeSpan+  where getTypeSpan :: SpanInfo -> m (Maybe SrcSpan)+        getTypeSpan SpanInfo { spaninfoType = Just t } =+          case splitTyConApp_maybe t of+            Nothing -> return Nothing+            Just (getName -> name, _) ->+              nameToLocation getHieFile name+        getTypeSpan _ = return Nothing+ locationsAtPoint   :: forall m    . MonadIO m-  => (Module -> m (Maybe (HieFile, FilePath)))+  => (Module -> MaybeT m (HieFile, FilePath))   -> IdeOptions   -> Position   -> [SpanInfo]-  -> m [Location]-locationsAtPoint getHieFile _ideOptions pos =-    fmap (map srcSpanToLocation) . mapMaybeM (getSpan . spaninfoSource) . spansAtPoint pos+  -> MaybeT m [Location]+locationsAtPoint getHieFile = querySpanInfoAt (getSpan . spaninfoSource)   where getSpan :: SpanSource -> m (Maybe SrcSpan)         getSpan NoSource = pure Nothing         getSpan (SpanS sp) = pure $ Just sp         getSpan (Lit _) = pure Nothing-        getSpan (Named name) = case nameSrcSpan name of-            sp@(RealSrcSpan _) -> pure $ Just sp-            sp@(UnhelpfulSpan _) -> runMaybeT $ do-                guard (sp /= wiredInSrcSpan)-                -- This case usually arises when the definition is in an external package (DAML only).-                -- In this case the interface files contain garbage source spans-                -- so we instead read the .hie files to get useful source spans.-                mod <- MaybeT $ return $ nameModule_maybe name-                (hieFile, srcPath) <- MaybeT $ getHieFile mod-                avail <- MaybeT $ pure $ find (eqName name . snd) $ hieExportNames hieFile-                -- The location will point to the source file used during compilation.-                -- This file might no longer exists and even if it does the path will be relative-                -- to the compilation directory which we don’t know.-                let span = setFileName srcPath $ fst avail-                pure span-        -- We ignore uniques and source spans and only compare the name and the module.-        eqName :: Name -> Name -> Bool-        eqName n n' = nameOccName n == nameOccName n' && nameModule_maybe n == nameModule_maybe n'-        setFileName f (RealSrcSpan span) = RealSrcSpan (span { srcSpanFile = mkFastString f })-        setFileName _ span@(UnhelpfulSpan _) = span+        getSpan (Named name) = nameToLocation getHieFile name +querySpanInfoAt :: forall m+   . MonadIO m+  => (SpanInfo -> m (Maybe SrcSpan))+  -> IdeOptions+  -> Position+  -> [SpanInfo]+  -> MaybeT m [Location]+querySpanInfoAt getSpan _ideOptions pos =+    lift . fmap (map srcSpanToLocation) . mapMaybeM getSpan . spansAtPoint pos++-- | Given a 'Name' attempt to find the location where it is defined.+nameToLocation :: Monad f => (Module -> MaybeT f (HieFile, String)) -> Name -> f (Maybe SrcSpan)+nameToLocation getHieFile name =+  case nameSrcSpan name of+    sp@(RealSrcSpan _) -> pure $ Just sp+    sp@(UnhelpfulSpan _) -> runMaybeT $ do+      guard (sp /= wiredInSrcSpan)+      -- This case usually arises when the definition is in an external package (DAML only).+      -- In this case the interface files contain garbage source spans+      -- so we instead read the .hie files to get useful source spans.+      mod <- MaybeT $ return $ nameModule_maybe name+      (hieFile, srcPath) <- getHieFile mod+      avail <- MaybeT $ pure $ find (eqName name . snd) $ hieExportNames hieFile+      -- The location will point to the source file used during compilation.+      -- This file might no longer exists and even if it does the path will be relative+      -- to the compilation directory which we don’t know.+      let span = setFileName srcPath $ fst avail+      pure span+  where+    -- We ignore uniques and source spans and only compare the name and the module.+    eqName :: Name -> Name -> Bool+    eqName n n' = nameOccName n == nameOccName n' && nameModule_maybe n == nameModule_maybe n'+    setFileName f (RealSrcSpan span) = RealSrcSpan (span { srcSpanFile = mkFastString f })+    setFileName _ span@(UnhelpfulSpan _) = span+ -- | Filter out spans which do not enclose a given point spansAtPoint :: Position -> [SpanInfo] -> [SpanInfo] spansAtPoint pos = filter atp where@@ -166,11 +214,6 @@                                               -- last character so we use > instead of >=       endsAfterPosition = endLineCmp == GT || (endLineCmp == EQ && spaninfoEndCol > cha) -showName :: Outputable a => a -> T.Text-showName = T.pack . prettyprint-  where-    prettyprint x = renderWithStyle unsafeGlobalDynFlags (ppr x) style-    style = mkUserStyle unsafeGlobalDynFlags neverQualify AllTheWay  getModuleNameAsText :: Name -> Maybe T.Text getModuleNameAsText n = do
src/Development/IDE/Spans/Calculate.hs view
@@ -18,26 +18,24 @@ import           Data.Maybe import           DataCon import           Desugar-import           GHC import           GhcMonad import           HscTypes import           FastString (mkFastString) import           OccName import           Development.IDE.Types.Location import           Development.IDE.Spans.Type-#ifdef GHC_LIB-import           Development.IDE.GHC.Error (zeroSpan)-#else import           Development.IDE.GHC.Error (zeroSpan, catchSrcErrors)-#endif import           Prelude hiding (mod) import           TcHsSyn import           Var import Development.IDE.Core.Compile import qualified Development.IDE.GHC.Compat as Compat+import Development.IDE.GHC.Compat import Development.IDE.GHC.Util import Development.IDE.Spans.Common import Development.IDE.Spans.Documentation+import Data.List.Extra (nubOrd)+import qualified Data.Map.Strict as Map  -- A lot of things gained an extra X argument in GHC 8.6, which we mostly ignore -- this U ignores that arg in 8.6, but is hidden in 8.4@@ -52,21 +50,19 @@     :: HscEnv     -> [(Located ModuleName, Maybe NormalizedFilePath)] -- ^ Dependencies in topological order     -> TcModuleResult-    -> [ParsedModule]   -- ^ Dependencies parsed, optional-    -> [ModIface]       -- ^ Dependencies module interfaces, required+    -> [ParsedModule]   -- ^ Dependencies parsed, optional if the 'HscEnv' already contains docs     -> IO SpansInfo-getSrcSpanInfos env imports tc parsedDeps deps =+getSrcSpanInfos env imports tc parsedDeps =     evalGhcEnv env $-        getSpanInfo imports (tmrModule tc) parsedDeps deps+        getSpanInfo imports tc parsedDeps  -- | Get ALL source spans in the module. getSpanInfo :: GhcMonad m             => [(Located ModuleName, Maybe NormalizedFilePath)] -- ^ imports-            -> TypecheckedModule+            -> TcModuleResult             -> [ParsedModule]-            -> [ModIface]             -> m SpansInfo-getSpanInfo mods tcm@TypecheckedModule{..} parsedDeps deps =+getSpanInfo mods TcModuleResult{tmrModInfo, tmrModule = tcm@TypecheckedModule{..}} parsedDeps =   do let tcs = tm_typechecked_source          bs  = listifyAllSpans  tcs :: [LHsBind GhcTc]          es  = listifyAllSpans  tcs :: [LHsExpr GhcTc]@@ -74,30 +70,52 @@          ts  = listifyAllSpans tm_renamed_source :: [LHsType GhcRn]          allModules = tm_parsed_module : parsedDeps          funBinds = funBindMap tm_parsed_module+         thisMod = ms_mod $ pm_mod_summary tm_parsed_module+         modIface = hm_iface tmrModInfo -     -- Load all modules in HPT to make their interface documentation available-     mapM_ (`loadDepModule` Nothing) (reverse deps)-     forM_ (modInfoIface tm_checked_module_info) $ \modIface ->-       modifySession (loadModuleHome $ HomeModInfo modIface (snd tm_internals_) Nothing)+     -- Load this module in HPT to make its interface documentation available+     modifySession (loadModuleHome $ HomeModInfo modIface (snd tm_internals_) Nothing) -     bts <- mapM (getTypeLHsBind allModules funBinds) bs   -- binds-     ets <- mapM (getTypeLHsExpr allModules) es -- expressions-     pts <- mapM (getTypeLPat allModules)    ps -- patterns-     tts <- mapM (getLHsType allModules)     ts -- types+     bts <- mapM (getTypeLHsBind funBinds) bs   -- binds+     ets <- mapM getTypeLHsExpr es -- expressions+     pts <- mapM getTypeLPat  ps -- patterns+     tts <- concat <$> mapM getLHsType ts -- types++     -- Batch extraction of kinds+     let typeNames = nubOrd [ n | (Named n, _) <- tts]+     kinds <- Map.fromList . zip typeNames  <$> mapM (lookupKind thisMod) typeNames+     let withKind (Named n, x) =+            (Named n, x, join $ Map.lookup n kinds)+         withKind (other, x) =+            (other, x, Nothing)+     tts <- pure $ map withKind tts+      let imports = importInfo mods      let exports = getExports tcm-     let exprs = addEmptyInfo exports ++ addEmptyInfo imports ++ concat bts ++ concat tts ++ catMaybes (ets ++ pts)+     let exprs = addEmptyInfo exports ++ addEmptyInfo imports ++ concat bts ++ tts ++ catMaybes (ets ++ pts)      let constraints = map constraintToInfo (concatMap getConstraintsLHsBind bs)-     return $ SpansInfo (mapMaybe toSpanInfo (sortBy cmp exprs))-                        (mapMaybe toSpanInfo (sortBy cmp constraints))-  where cmp (_,a,_,_) (_,b,_,_)+         sortedExprs = sortBy cmp exprs+         sortedConstraints = sortBy cmp constraints++    -- Batch extraction of Haddocks+     let names = nubOrd [ s | (Named s,_,_) <- sortedExprs ++ sortedConstraints]+     docs <- Map.fromList . zip names <$> getDocumentationsTryGhc thisMod allModules names+     let withDocs (Named n, x, y) = (Named n, x, y, Map.findWithDefault emptySpanDoc n docs)+         withDocs (other, x, y) = (other, x, y, emptySpanDoc)++     return $ SpansInfo (mapMaybe (toSpanInfo . withDocs) sortedExprs)+                        (mapMaybe (toSpanInfo . withDocs) sortedConstraints)+  where cmp (_,a,_) (_,b,_)           | a `isSubspanOf` b = LT           | b `isSubspanOf` a = GT           | otherwise         = compare (srcSpanStart a) (srcSpanStart b) -        addEmptyInfo = map (\(a,b) -> (a,b,Nothing,emptySpanDoc))-        constraintToInfo (sp, ty) = (SpanS sp, sp, Just ty, emptySpanDoc)+        addEmptyInfo = map (\(a,b) -> (a,b,Nothing))+        constraintToInfo (sp, ty) = (SpanS sp, sp, Just ty) +lookupKind :: GhcMonad m => Module -> Name -> m (Maybe Type)+lookupKind mod =+    fmap (either (const Nothing) (safeTyThingType =<<)) . catchSrcErrors "span" . lookupName mod -- | The locations in the typechecked module are slightly messed up in some cases (e.g. HsMatchContext always -- points to the first match) whereas the parsed module has the correct locations. -- Therefore we build up a map from OccName to the corresponding definition in the parsed module@@ -120,27 +138,24 @@ ieLNames :: IE pass -> [Located (IdP pass)] ieLNames (IEVar       U n   )     = [ieLWrappedName n] ieLNames (IEThingAbs  U n   )     = [ieLWrappedName n]-ieLNames (IEThingAll  U n   )     = [ieLWrappedName n]-ieLNames (IEThingWith U n _ ns _) = ieLWrappedName n : map ieLWrappedName ns+ieLNames (IEThingAll    n   )     = [ieLWrappedName n]+ieLNames (IEThingWith   n _ ns _) = ieLWrappedName n : map ieLWrappedName ns ieLNames _ = []  -- | Get the name and type of a binding.-getTypeLHsBind :: (GhcMonad m)-               => [ParsedModule]-               -> OccEnv (HsBind GhcPs)+getTypeLHsBind :: (Monad m)+               => OccEnv (HsBind GhcPs)                -> LHsBind GhcTc-               -> m [(SpanSource, SrcSpan, Maybe Type, SpanDoc)]-getTypeLHsBind deps funBinds (L _spn FunBind{fun_id = pid})+               -> m [(SpanSource, SrcSpan, Maybe Type)]+getTypeLHsBind funBinds (L _spn FunBind{fun_id = pid})   | Just FunBind {fun_matches = MG{mg_alts=L _ matches}} <- lookupOccEnv funBinds (occName $ unLoc pid) = do   let name = getName (unLoc pid)-  docs <- getDocumentationTryGhc deps name-  return [(Named name, getLoc mc_fun, Just (varType (unLoc pid)), docs) | match <- matches, FunRhs{mc_fun = mc_fun} <- [m_ctxt $ unLoc match] ]+  return [(Named name, getLoc mc_fun, Just (varType (unLoc pid))) | match <- matches, FunRhs{mc_fun = mc_fun} <- [m_ctxt $ unLoc match] ] -- In theory this shouldn’t ever fail but if it does, we can at least show the first clause.-getTypeLHsBind deps _ (L _spn FunBind{fun_id = pid,fun_matches = MG{}}) = do+getTypeLHsBind _ (L _spn FunBind{fun_id = pid,fun_matches = MG{}}) = do   let name = getName (unLoc pid)-  docs <- getDocumentationTryGhc deps name-  return [(Named name, getLoc pid, Just (varType (unLoc pid)), docs)]-getTypeLHsBind _ _ _ = return []+  return [(Named name, getLoc pid, Just (varType (unLoc pid)))]+getTypeLHsBind _ _ = return []  -- | Get information about constraints getConstraintsLHsBind :: LHsBind GhcTc@@ -151,19 +166,15 @@  -- | Get the name and type of an expression. getTypeLHsExpr :: (GhcMonad m)-               => [ParsedModule]-               -> LHsExpr GhcTc-               -> m (Maybe (SpanSource, SrcSpan, Maybe Type, SpanDoc))-getTypeLHsExpr deps e = do+               => LHsExpr GhcTc+               -> m (Maybe (SpanSource, SrcSpan, Maybe Type))+getTypeLHsExpr e = do   hs_env <- getSession   (_, mbe) <- liftIO (deSugarExpr hs_env e)   case mbe of     Just expr -> do       let ss = getSpanSource (unLoc e)-      docs <- case ss of-                Named n -> getDocumentationTryGhc deps n-                _       -> return emptySpanDoc-      return $ Just (ss, getLoc e, Just (CoreUtils.exprType expr), docs)+      return $ Just (ss, getLoc e, Just (CoreUtils.exprType expr))     Nothing -> return Nothing   where     getSpanSource :: HsExpr GhcTc -> SpanSource@@ -206,43 +217,27 @@     isLitChild e = isLit e  -- | Get the name and type of a pattern.-getTypeLPat :: (GhcMonad m)-            => [ParsedModule]-            -> Pat GhcTc-            -> m (Maybe (SpanSource, SrcSpan, Maybe Type, SpanDoc))-getTypeLPat deps pat = do+getTypeLPat :: (Monad m)+            => Pat GhcTc+            -> m (Maybe (SpanSource, SrcSpan, Maybe Type))+getTypeLPat pat = do   let (src, spn) = getSpanSource pat-  docs <- case src of-            Named n -> getDocumentationTryGhc deps n-            _       -> return emptySpanDoc-  return $ Just (src, spn, Just (hsPatType pat), docs)+  return $ Just (src, spn, Just (hsPatType pat))   where     getSpanSource :: Pat GhcTc -> (SpanSource, SrcSpan)-    getSpanSource (VarPat U (L spn vid)) = (Named (getName vid), spn)+    getSpanSource (VarPat (L spn vid)) = (Named (getName vid), spn)     getSpanSource (ConPatOut (L spn (RealDataCon dc)) _ _ _ _ _ _) =       (Named (dataConName dc), spn)     getSpanSource _ = (NoSource, noSrcSpan)  getLHsType-    :: GhcMonad m-    => [ParsedModule]-    -> LHsType GhcRn-    -> m [(SpanSource, SrcSpan, Maybe Type, SpanDoc)]-getLHsType deps (L spn (HsTyVar U _ v)) = do+    :: Monad m+    => LHsType GhcRn+    -> m [(SpanSource, SrcSpan)]+getLHsType (L spn (HsTyVar U _ v)) = do   let n = unLoc v-  docs <- getDocumentationTryGhc deps n-#ifdef GHC_LIB-  let ty = Right Nothing-#else-  ty <- catchSrcErrors "completion" $ do-          name' <- lookupName n-          return $ name' >>= safeTyThingType-#endif-  let ty' = case ty of-              Right (Just x) -> Just x-              _ -> Nothing-  pure [(Named n, spn, ty', docs)]-getLHsType _ _ = pure []+  pure [(Named n, spn)]+getLHsType _ = pure []  importInfo :: [(Located ModuleName, Maybe NormalizedFilePath)]            -> [(SpanSource, SrcSpan)]
src/Development/IDE/Spans/Common.hs view
@@ -3,13 +3,13 @@  module Development.IDE.Spans.Common (   showGhc+, showName , listifyAllSpans , listifyAllSpans' , safeTyThingId-#ifndef GHC_LIB , safeTyThingType-#endif , SpanDoc(..)+, SpanDocUris(..) , emptySpanDoc , spanDocToMarkdown , spanDocToMarkdownForTest@@ -17,17 +17,16 @@  import Data.Data import qualified Data.Generics+import Data.Maybe import qualified Data.Text as T import Data.List.Extra  import GHC-import Outputable+import Outputable hiding ((<>)) import DynFlags import ConLike import DataCon-#ifndef GHC_LIB import Var-#endif  import qualified Documentation.Haddock.Parser as H import qualified Documentation.Haddock.Types as H@@ -35,6 +34,12 @@ showGhc :: Outputable a => a -> String showGhc = showPpr unsafeGlobalDynFlags +showName :: Outputable a => a -> T.Text+showName = T.pack . prettyprint+  where+    prettyprint x = renderWithStyle unsafeGlobalDynFlags (ppr x) style+    style = mkUserStyle unsafeGlobalDynFlags neverQualify AllTheWay+ -- | Get ALL source spans in the source. listifyAllSpans :: (Typeable a, Data m) => m -> [Located a] listifyAllSpans tcs =@@ -47,14 +52,12 @@                    => TypecheckedSource -> [Pat a] listifyAllSpans' tcs = Data.Generics.listify (const True) tcs -#ifndef GHC_LIB -- From haskell-ide-engine/src/Haskell/Ide/Engine/Support/HieExtras.hs safeTyThingType :: TyThing -> Maybe Type safeTyThingType thing   | Just i <- safeTyThingId thing = Just (varType i) safeTyThingType (ATyCon tycon)    = Just (tyConKind tycon) safeTyThingType _                 = Nothing-#endif  safeTyThingId :: TyThing -> Maybe Id safeTyThingId (AnId i)                    = Just i@@ -63,22 +66,38 @@  -- Possible documentation for an element in the code data SpanDoc-  = SpanDocString HsDocString-  | SpanDocText   [T.Text]-  deriving Show+  = SpanDocString HsDocString SpanDocUris+  | SpanDocText   [T.Text] SpanDocUris+  deriving (Eq, Show) +data SpanDocUris =+  SpanDocUris+  { spanDocUriDoc :: Maybe T.Text -- ^ The haddock html page+  , spanDocUriSrc :: Maybe T.Text -- ^ The hyperlinked source html page+  } deriving (Eq, Show)+ emptySpanDoc :: SpanDoc-emptySpanDoc = SpanDocText []+emptySpanDoc = SpanDocText [] (SpanDocUris Nothing Nothing)  spanDocToMarkdown :: SpanDoc -> [T.Text] #if MIN_GHC_API_VERSION(8,6,0)-spanDocToMarkdown (SpanDocString docs)+spanDocToMarkdown (SpanDocString docs uris)   = [T.pack $ haddockToMarkdown $ H.toRegular $ H._doc $ H.parseParas Nothing $ unpackHDS docs]+    <> ["\n"] <> spanDocUrisToMarkdown uris+  -- Append the extra newlines since this is markdown --- to get a visible newline,+  -- you need to have two newlines #else-spanDocToMarkdown (SpanDocString _)-  = []+spanDocToMarkdown (SpanDocString _ uris)+  = spanDocUrisToMarkdown uris #endif-spanDocToMarkdown (SpanDocText txt) = txt+spanDocToMarkdown (SpanDocText txt uris) = txt <> ["\n"] <> spanDocUrisToMarkdown uris++spanDocUrisToMarkdown :: SpanDocUris -> [T.Text]+spanDocUrisToMarkdown (SpanDocUris mdoc msrc) = catMaybes+  [ linkify "Documentation" <$> mdoc+  , linkify "Source" <$> msrc+  ]+  where linkify title uri = "[" <> title <> "](" <> uri <> ")"  spanDocToMarkdownForTest :: String -> String spanDocToMarkdownForTest
src/Development/IDE/Spans/Documentation.hs view
@@ -1,3 +1,4 @@+{-# LANGUAGE RankNTypes #-} -- Copyright (c) 2019 The DAML Authors. All rights reserved. -- SPDX-License-Identifier: Apache-2.0 @@ -7,41 +8,76 @@ module Development.IDE.Spans.Documentation (     getDocumentation   , getDocumentationTryGhc+  , getDocumentationsTryGhc   ) where  import           Control.Monad+import           Data.Foldable import           Data.List.Extra import qualified Data.Map as M import           Data.Maybe import qualified Data.Text as T+#if MIN_GHC_API_VERSION(8,6,0)+import           Development.IDE.Core.Compile+#endif import           Development.IDE.GHC.Compat import           Development.IDE.GHC.Error import           Development.IDE.Spans.Common+import           System.Directory+import           System.FilePath+ import           FastString-import SrcLoc+import           SrcLoc (RealLocated)+import           GhcMonad+import           Packages+import           Name +getDocumentationTryGhc :: GhcMonad m => Module -> [ParsedModule] -> Name -> m SpanDoc+getDocumentationTryGhc mod deps n = head <$> getDocumentationsTryGhc mod deps [n] -getDocumentationTryGhc-  :: GhcMonad m-  => [ParsedModule]-  -> Name-  -> m SpanDoc--- getDocs goes through the GHCi codepaths which cause problems on ghc-lib.--- See https://github.com/digital-asset/daml/issues/4152 for more details.-#if MIN_GHC_API_VERSION(8,6,0) && !defined(GHC_LIB)-getDocumentationTryGhc sources name = do-  res <- catchSrcErrors "docs" $ getDocs name+getDocumentationsTryGhc :: GhcMonad m => Module -> [ParsedModule] -> [Name] -> m [SpanDoc]++-- Interfaces are only generated for GHC >= 8.6.+-- In older versions, interface files do not embed Haddocks anyway+#if MIN_GHC_API_VERSION(8,6,0)+getDocumentationsTryGhc mod sources names = do+  res <- catchSrcErrors "docs" $ getDocsBatch mod names   case res of-    Right (Right (Just docs, _)) -> return $ SpanDocString docs-    _ -> return $ SpanDocText $ getDocumentation sources name+      Left _ -> mapM mkSpanDocText names+      Right res -> zipWithM unwrap res names+  where+    unwrap (Right (Just docs, _)) n = SpanDocString <$> pure docs <*> getUris n+    unwrap _ n = mkSpanDocText n+ #else-getDocumentationTryGhc sources name = do-  return $ SpanDocText $ getDocumentation sources name+getDocumentationsTryGhc _ sources names = mapM mkSpanDocText names+  where #endif+    mkSpanDocText name =+      pure (SpanDocText (getDocumentation sources name)) <*> getUris name +    -- Get the uris to the documentation and source html pages if they exist+    getUris name = do+      df <- getSessionDynFlags+      (docFp, srcFp) <-+        case nameModule_maybe name of+          Just mod -> liftIO $ do+            doc <- fmap (fmap T.pack) $ lookupDocHtmlForModule df mod+            src <- fmap (fmap T.pack) $ lookupSrcHtmlForModule df mod+            return (doc, src)+          Nothing -> pure (Nothing, Nothing)+      let docUri = docFp >>= \fp -> pure $ "file://" <> fp <> "#" <> selector <> showName name+          srcUri = srcFp >>= \fp -> pure $ "file://" <> fp <> "#" <> showName name+          selector+            | isValName name = "v:"+            | otherwise = "t:"+      return $ SpanDocUris docUri srcUri++ getDocumentation- :: [ParsedModule] -- ^ All of the possible modules it could be defined in.- ->  Name -- ^ The name you want documentation for.+ :: HasSrcSpan name+ => [ParsedModule] -- ^ All of the possible modules it could be defined in.+ ->  name -- ^ The name you want documentation for.  -> [T.Text] -- This finds any documentation between the name you want -- documentation for and the one before it. This is only an@@ -52,7 +88,7 @@ -- more accurately. getDocumentation sources targetName = fromMaybe [] $ do   -- Find the module the target is defined in.-  targetNameSpan <- realSpan $ nameSrcSpan targetName+  targetNameSpan <- realSpan $ getLoc targetName   tc <-     find ((==) (Just $ srcSpanFile targetNameSpan) . annotationFileName)       $ reverse sources -- TODO : Is reversing the list here really neccessary?@@ -113,3 +149,34 @@                             then Just $ T.pack s                             else Nothing     _ -> Nothing++-- These are taken from haskell-ide-engine's Haddock plugin++-- | Given a module finds the local @doc/html/Foo-Bar-Baz.html@ page.+-- An example for a cabal installed module:+-- @~/.cabal/store/ghc-8.10.1/vctr-0.12.1.2-98e2e861/share/doc/html/Data-Vector-Primitive.html@+lookupDocHtmlForModule :: DynFlags -> Module -> IO (Maybe FilePath)+lookupDocHtmlForModule =+  lookupHtmlForModule (\pkgDocDir modDocName -> pkgDocDir </> modDocName <.> "html")++-- | Given a module finds the hyperlinked source @doc/html/src/Foo.Bar.Baz.html@ page.+-- An example for a cabal installed module:+-- @~/.cabal/store/ghc-8.10.1/vctr-0.12.1.2-98e2e861/share/doc/html/src/Data.Vector.Primitive.html@+lookupSrcHtmlForModule :: DynFlags -> Module -> IO (Maybe FilePath)+lookupSrcHtmlForModule =+  lookupHtmlForModule (\pkgDocDir modDocName -> pkgDocDir </> "src" </> modDocName <.> "html")++lookupHtmlForModule :: (FilePath -> FilePath -> FilePath) -> DynFlags -> Module -> IO (Maybe FilePath)+lookupHtmlForModule mkDocPath df m = do+  let mfs = go <$> (listToMaybe =<< lookupHtmls df ui)+  htmls <- filterM doesFileExist (concat . maybeToList $ mfs)+  return $ listToMaybe htmls+  where+    -- The file might use "." or "-" as separator+    go pkgDocDir = [mkDocPath pkgDocDir mn | mn <- [mndot,mndash]]+    ui = moduleUnitId m+    mndash = map (\x -> if x == '.' then '-' else x) mndot+    mndot = moduleNameString $ moduleName m++lookupHtmls :: DynFlags -> UnitId -> Maybe [FilePath]+lookupHtmls df ui = haddockHTMLs <$> lookupPackage df ui
src/Development/IDE/Types/Diagnostics.hs view
@@ -32,6 +32,15 @@  import Development.IDE.Types.Location ++-- | The result of an IDE operation. Warnings and errors are in the Diagnostic,+--   and a value is in the Maybe. For operations that throw an error you+--   expect a non-empty list of diagnostics, at least one of which is an error,+--   and a Nothing. For operations that succeed you expect perhaps some warnings+--   and a Just. For operations that depend on other failing operations you may+--   get empty diagnostics and a Nothing, to indicate this phase throws no fresh+--   errors but still failed.+-- --   A rule on a file should only return diagnostics for that given file. It should --   not propagate diagnostic errors through multiple phases. type IdeResult v = ([FileDiagnostic], Maybe v)
src/Development/IDE/Types/Location.hs view
@@ -69,7 +69,7 @@  -- A dummy range to use when range is unknown noRange :: Range-noRange =  Range (Position 0 0) (Position 100000 0)+noRange =  Range (Position 0 0) (Position 1 0)  showPosition :: Position -> String showPosition Position{..} = show (_line + 1) ++ ":" ++ show (_character + 1)
src/Development/IDE/Types/Options.hs view
@@ -9,10 +9,12 @@   , IdePreprocessedSource(..)   , IdeReportProgress(..)   , IdeDefer(..)+  , IdeTesting(..)   , clientSupportsProgress   , IdePkgLocationOptions(..)   , defaultIdeOptions   , IdeResult+  , IdeGhcSession(..)   ) where  import Development.Shake@@ -22,12 +24,23 @@ import qualified Language.Haskell.LSP.Types.Capabilities as LSP import qualified Data.Text as T import Development.IDE.Types.Diagnostics+import Control.DeepSeq (NFData(..)) +data IdeGhcSession = IdeGhcSession+  { loadSessionFun :: FilePath -> IO (IdeResult HscEnvEq, [FilePath])+  -- ^ Returns the Ghc session and the cradle dependencies+  , sessionVersion :: !Int+  -- ^ Used as Shake key, versions must be unique and not reused+  }++instance Show IdeGhcSession where show _ = "IdeGhcSession"+instance NFData IdeGhcSession where rnf !_ = ()+ data IdeOptions = IdeOptions   { optPreprocessor :: GHC.ParsedSource -> IdePreprocessedSource     -- ^ Preprocessor to run over all parsed source trees, generating a list of warnings     --   and a list of errors, along with a new parse tree.-  , optGhcSession :: Action (FilePath -> Action (IdeResult HscEnvEq))+  , optGhcSession :: Action IdeGhcSession     -- ^ Setup a GHC session for a given file, e.g. @Foo.hs@.     --   For the same 'ComponentOptions' from hie-bios, the resulting function will be applied once per file.     --   It is desirable that many files get the same 'HscEnvEq', so that more IDE features work.@@ -43,7 +56,7 @@   -- meaning we keep everything in memory but the daml CLI compiler uses this for incremental builds.   , optShakeProfiling :: Maybe FilePath     -- ^ Set to 'Just' to create a directory of profiling reports.-  , optTesting :: Bool+  , optTesting :: IdeTesting     -- ^ Whether to enable additional lsp messages used by the test suite for checking invariants   , optReportProgress :: IdeReportProgress     -- ^ Whether to report progress during long operations.@@ -73,12 +86,13 @@  newtype IdeReportProgress = IdeReportProgress Bool newtype IdeDefer          = IdeDefer          Bool+newtype IdeTesting        = IdeTesting        Bool  clientSupportsProgress :: LSP.ClientCapabilities -> IdeReportProgress clientSupportsProgress caps = IdeReportProgress $ Just True ==     (LSP._workDoneProgress =<< LSP._window (caps :: LSP.ClientCapabilities)) -defaultIdeOptions :: Action (FilePath -> Action (IdeResult HscEnvEq)) -> IdeOptions+defaultIdeOptions :: Action IdeGhcSession -> IdeOptions defaultIdeOptions session = IdeOptions     {optPreprocessor = IdePreprocessedSource [] []     ,optGhcSession = session@@ -92,7 +106,7 @@     ,optNewColonConvention = False     ,optKeywords = haskellKeywords     ,optDefer = IdeDefer True-    ,optTesting = False+    ,optTesting = IdeTesting False     }  
test/data/hover/Bar.hs view
@@ -1,3 +1,4 @@ module Bar (Bar(..)) where +-- | Bar Haddock data Bar = Bar
test/data/hover/Foo.hs view
@@ -2,4 +2,5 @@  import Bar +-- | foo Haddock foo = Bar
test/exe/Main.hs view
@@ -3,2494 +3,3300 @@  {-# LANGUAGE AllowAmbiguousTypes   #-} {-# LANGUAGE DuplicateRecordFields #-}-{-# LANGUAGE PatternSynonyms #-}-{-# LANGUAGE CPP #-}-#include "ghc-api-version.h"--module Main (main) where--import Control.Applicative.Combinators-import Control.Exception (bracket, catch)-import qualified Control.Lens as Lens-import Control.Monad-import Control.Monad.IO.Class (liftIO)-import Data.Aeson (FromJSON, Value)-import Data.Foldable-import Data.List.Extra-import Data.Rope.UTF16 (Rope)-import qualified Data.Rope.UTF16 as Rope-import Development.IDE.Core.PositionMapping (fromCurrent, toCurrent)-import Development.IDE.GHC.Util-import qualified Data.Text as T-import Data.Typeable-import Development.IDE.Spans.Common-import Development.IDE.Test-import Development.IDE.Test.Runfiles-import Development.IDE.Types.Location-import Development.Shake (getDirectoryFilesIO)-import Language.Haskell.LSP.Test-import Language.Haskell.LSP.Messages-import Language.Haskell.LSP.Types-import Language.Haskell.LSP.Types.Capabilities-import qualified Language.Haskell.LSP.Types.Lens as Lsp (diagnostics, params, message)-import Language.Haskell.LSP.VFS (applyChange)-import Network.URI-import System.Environment.Blank (getEnv, setEnv, unsetEnv)-import System.FilePath-import System.IO.Extra-import System.Directory-import Test.QuickCheck-import Test.QuickCheck.Instances ()-import Test.Tasty-import Test.Tasty.ExpectedFailure-import Test.Tasty.Ingredients.Rerun-import Test.Tasty.HUnit-import Test.Tasty.QuickCheck-import Data.Maybe--main :: IO ()-main = do-  -- We mess with env vars so run single-threaded.-  setEnv "TASTY_NUM_THREADS" "1" True-  defaultMainWithRerun $ testGroup "HIE"-    [ testSession "open close" $ do-        doc <- createDoc "Testing.hs" "haskell" ""-        void (skipManyTill anyMessage message :: Session WorkDoneProgressCreateRequest)-        void (skipManyTill anyMessage message :: Session WorkDoneProgressBeginNotification)-        closeDoc doc-        void (skipManyTill anyMessage message :: Session WorkDoneProgressEndNotification)-    , initializeResponseTests-    , completionTests-    , cppTests-    , diagnosticTests-    , codeActionTests-    , codeLensesTests-    , outlineTests-    , findDefinitionAndHoverTests-    , pluginTests-    , preprocessorTests-    , thTests-    , safeTests-    , unitTests-    , haddockTests-    , positionMappingTests-    , watchedFilesTests-    , cradleTests-    , dependentFileTest-    ]--initializeResponseTests :: TestTree-initializeResponseTests = withResource acquire release tests where--  -- these tests document and monitor the evolution of the-  -- capabilities announced by the server in the initialize-  -- response. Currently the server advertises almost no capabilities-  -- at all, in some cases failing to announce capabilities that it-  -- actually does provide! Hopefully this will change ...-  tests :: IO InitializeResponse -> TestTree-  tests getInitializeResponse =-    testGroup "initialize response capabilities"-    [ chk "   text doc sync"             _textDocumentSync  tds-    , chk "   hover"                         _hoverProvider (Just True)-    , chk "   completion"               _completionProvider (Just $ CompletionOptions (Just False) (Just ["."]) Nothing)-    , chk "NO signature help"        _signatureHelpProvider  Nothing-    , chk "   goto definition"          _definitionProvider (Just True)-    , chk "NO goto type definition" _typeDefinitionProvider (Just $ GotoOptionsStatic False)-    , chk "NO goto implementation"  _implementationProvider (Just $ GotoOptionsStatic False)-    , chk "NO find references"          _referencesProvider  Nothing-    , chk "NO doc highlight"     _documentHighlightProvider  Nothing-    , chk "   doc symbol"           _documentSymbolProvider  (Just True)-    , chk "NO workspace symbol"    _workspaceSymbolProvider  Nothing-    , chk "   code action"             _codeActionProvider $ Just $ CodeActionOptionsStatic True-    , chk "   code lens"                 _codeLensProvider $ Just $ CodeLensOptions Nothing-    , chk "NO doc formatting"   _documentFormattingProvider  Nothing-    , chk "NO doc range formatting"-                           _documentRangeFormattingProvider  Nothing-    , chk "NO doc formatting on typing"-                          _documentOnTypeFormattingProvider  Nothing-    , chk "NO renaming"                     _renameProvider (Just $ RenameOptionsStatic False)-    , chk "NO doc link"               _documentLinkProvider  Nothing-    , chk "NO color"                         _colorProvider (Just $ ColorOptionsStatic False)-    , chk "NO folding range"          _foldingRangeProvider (Just $ FoldingRangeOptionsStatic False)-    , che "   execute command"      _executeCommandProvider (Just $ ExecuteCommandOptions $ List ["typesignature.add"])-    , chk "   workspace"                         _workspace (Just $ WorkspaceOptions (Just WorkspaceFolderOptions{_supported = Just True, _changeNotifications = Just ( WorkspaceFolderChangeNotificationsBool True )}))-    , chk "NO experimental"                   _experimental  Nothing-    ] where--      tds = Just (TDSOptions (TextDocumentSyncOptions-                              { _openClose = Just True-                              , _change    = Just TdSyncIncremental-                              , _willSave  = Nothing-                              , _willSaveWaitUntil = Nothing-                              , _save = Just (SaveOptions {_includeText = Nothing})}))--      chk :: (Eq a, Show a) => TestName -> (InitializeResponseCapabilitiesInner -> a) -> a -> TestTree-      chk title getActual expected =-        testCase title $ getInitializeResponse >>= \ir -> expected @=? (getActual . innerCaps) ir--      che :: TestName -> (InitializeResponseCapabilitiesInner -> Maybe ExecuteCommandOptions) -> Maybe ExecuteCommandOptions -> TestTree-      che title getActual _expected = testCase title doTest-        where-            doTest = do-                ir <- getInitializeResponse-                let Just ExecuteCommandOptions {_commands = List [command]} = getActual $ innerCaps ir-                True @=? T.isSuffixOf "typesignature.add" command---  innerCaps :: InitializeResponse -> InitializeResponseCapabilitiesInner-  innerCaps (ResponseMessage _ _ (Right (InitializeResponseCapabilities c))) = c-  innerCaps  _ = error "this test only expects inner capabilities"--  acquire :: IO InitializeResponse-  acquire = run initializeResponse--  release :: InitializeResponse -> IO ()-  release = const $ pure ()---diagnosticTests :: TestTree-diagnosticTests = testGroup "diagnostics"-  [ testSessionWait "fix syntax error" $ do-      let content = T.unlines [ "module Testing wher" ]-      doc <- createDoc "Testing.hs" "haskell" content-      expectDiagnostics [("Testing.hs", [(DsError, (0, 15), "parse error")])]-      let change = TextDocumentContentChangeEvent-            { _range = Just (Range (Position 0 15) (Position 0 19))-            , _rangeLength = Nothing-            , _text = "where"-            }-      changeDoc doc [change]-      expectDiagnostics [("Testing.hs", [])]-  , testSessionWait "introduce syntax error" $ do-      let content = T.unlines [ "module Testing where" ]-      doc <- createDoc "Testing.hs" "haskell" content-      void $ skipManyTill anyMessage (message :: Session WorkDoneProgressCreateRequest)-      void $ skipManyTill anyMessage (message :: Session WorkDoneProgressBeginNotification)-      let change = TextDocumentContentChangeEvent-            { _range = Just (Range (Position 0 15) (Position 0 18))-            , _rangeLength = Nothing-            , _text = "wher"-            }-      changeDoc doc [change]-      expectDiagnostics [("Testing.hs", [(DsError, (0, 15), "parse error")])]-  , testSessionWait "variable not in scope" $ do-      let content = T.unlines-            [ "module Testing where"-            , "foo :: Int -> Int -> Int"-            , "foo a b = a + ab"-            , "bar :: Int -> Int -> Int"-            , "bar a b = cd + b"-            ]-      _ <- createDoc "Testing.hs" "haskell" content-      expectDiagnostics-        [ ( "Testing.hs"-          , [ (DsError, (2, 14), "Variable not in scope: ab")-            , (DsError, (4, 10), "Variable not in scope: cd")-            ]-          )-        ]-  , testSessionWait "type error" $ do-      let content = T.unlines-            [ "module Testing where"-            , "foo :: Int -> String -> Int"-            , "foo a b = a + b"-            ]-      _ <- createDoc "Testing.hs" "haskell" content-      expectDiagnostics-        [ ( "Testing.hs"-          , [(DsError, (2, 14), "Couldn't match type '[Char]' with 'Int'")]-          )-        ]-  , testSessionWait "typed hole" $ do-      let content = T.unlines-            [ "module Testing where"-            , "foo :: Int -> String"-            , "foo a = _ a"-            ]-      _ <- createDoc "Testing.hs" "haskell" content-      expectDiagnostics-        [ ( "Testing.hs"-          , [(DsError, (2, 8), "Found hole: _ :: Int -> String")]-          )-        ]--  , testGroup "deferral" $-    let sourceA a = T.unlines-          [ "module A where"-          , "a :: Int"-          , "a = " <> a]-        sourceB = T.unlines-          [ "module B where"-          , "import A"-          , "b :: Float"-          , "b = True"]-        bMessage = "Couldn't match expected type 'Float' with actual type 'Bool'"-        expectedDs aMessage =-          [ ("A.hs", [(DsError, (2,4), aMessage)])-          , ("B.hs", [(DsError, (3,4), bMessage)])]-        deferralTest title binding msg = testSessionWait title $ do-          _ <- createDoc "A.hs" "haskell" $ sourceA binding-          _ <- createDoc "B.hs" "haskell"   sourceB-          expectDiagnostics $ expectedDs msg-    in-    [ deferralTest "type error"          "True"    "Couldn't match expected type"-    , deferralTest "typed hole"          "_"       "Found hole"-    , deferralTest "out of scope var"    "unbound" "Variable not in scope"-    ]--  , testSessionWait "remove required module" $ do-      let contentA = T.unlines [ "module ModuleA where" ]-      docA <- createDoc "ModuleA.hs" "haskell" contentA-      let contentB = T.unlines-            [ "module ModuleB where"-            , "import ModuleA"-            ]-      _ <- createDoc "ModuleB.hs" "haskell" contentB-      let change = TextDocumentContentChangeEvent-            { _range = Just (Range (Position 0 0) (Position 0 20))-            , _rangeLength = Nothing-            , _text = ""-            }-      changeDoc docA [change]-      expectDiagnostics [("ModuleB.hs", [(DsError, (1, 0), "Could not find module")])]-  , testSessionWait "add missing module" $ do-      let contentB = T.unlines-            [ "module ModuleB where"-            , "import ModuleA"-            ]-      _ <- createDoc "ModuleB.hs" "haskell" contentB-      expectDiagnostics [("ModuleB.hs", [(DsError, (1, 7), "Could not find module")])]-      let contentA = T.unlines [ "module ModuleA where" ]-      _ <- createDoc "ModuleA.hs" "haskell" contentA-      expectDiagnostics [("ModuleB.hs", [])]-  , testSessionWait "add missing module (non workspace)" $ do-      let contentB = T.unlines-            [ "module ModuleB where"-            , "import ModuleA"-            ]-      _ <- createDoc "/tmp/ModuleB.hs" "haskell" contentB-      expectDiagnostics [("/tmp/ModuleB.hs", [(DsError, (1, 7), "Could not find module")])]-      let contentA = T.unlines [ "module ModuleA where" ]-      _ <- createDoc "/tmp/ModuleA.hs" "haskell" contentA-      expectDiagnostics [("/tmp/ModuleB.hs", [])]-  , testSessionWait "cyclic module dependency" $ do-      let contentA = T.unlines-            [ "module ModuleA where"-            , "import ModuleB"-            ]-      let contentB = T.unlines-            [ "module ModuleB where"-            , "import ModuleA"-            ]-      _ <- createDoc "ModuleA.hs" "haskell" contentA-      _ <- createDoc "ModuleB.hs" "haskell" contentB-      expectDiagnostics-        [ ( "ModuleA.hs"-          , [(DsError, (1, 7), "Cyclic module dependency between ModuleA, ModuleB")]-          )-        , ( "ModuleB.hs"-          , [(DsError, (1, 7), "Cyclic module dependency between ModuleA, ModuleB")]-          )-        ]-  , testSessionWait "cyclic module dependency with hs-boot" $ do-      let contentA = T.unlines-            [ "module ModuleA where"-            , "import {-# SOURCE #-} ModuleB"-            ]-      let contentB = T.unlines-            [ "module ModuleB where"-            , "import ModuleA"-            ]-      let contentBboot = T.unlines-            [ "module ModuleB where"-            ]-      _ <- createDoc "ModuleA.hs" "haskell" contentA-      _ <- createDoc "ModuleB.hs" "haskell" contentB-      _ <- createDoc "ModuleB.hs-boot" "haskell" contentBboot-      expectDiagnostics []-  , testSessionWait "correct reference used with hs-boot" $ do-      let contentB = T.unlines-            [ "module ModuleB where"-            , "import {-# SOURCE #-} ModuleA"-            ]-      let contentA = T.unlines-            [ "module ModuleA where"-            , "import ModuleB"-            , "x = 5"-            ]-      let contentAboot = T.unlines-            [ "module ModuleA where"-            ]-      let contentC = T.unlines-            [ "module ModuleC where"-            , "import ModuleA"-            -- this reference will fail if it gets incorrectly-            -- resolved to the hs-boot file-            , "y = x"-            ]-      _ <- createDoc "ModuleB.hs" "haskell" contentB-      _ <- createDoc "ModuleA.hs" "haskell" contentA-      _ <- createDoc "ModuleA.hs-boot" "haskell" contentAboot-      _ <- createDoc "ModuleC.hs" "haskell" contentC-      expectDiagnostics []-  , testSessionWait "redundant import" $ do-      let contentA = T.unlines ["module ModuleA where"]-      let contentB = T.unlines-            [ "{-# OPTIONS_GHC -Wunused-imports #-}"-            , "module ModuleB where"-            , "import ModuleA"-            ]-      _ <- createDoc "ModuleA.hs" "haskell" contentA-      _ <- createDoc "ModuleB.hs" "haskell" contentB-      expectDiagnostics-        [ ( "ModuleB.hs"-          , [(DsWarning, (2, 0), "The import of 'ModuleA' is redundant")]-          )-        ]-  , testSessionWait "package imports" $ do-      let thisDataListContent = T.unlines-            [ "module Data.List where"-            , "x :: Integer"-            , "x = 123"-            ]-      let mainContent = T.unlines-            [ "{-# LANGUAGE PackageImports #-}"-            , "module Main where"-            , "import qualified \"this\" Data.List as ThisList"-            , "import qualified \"base\" Data.List as BaseList"-            , "useThis = ThisList.x"-            , "useBase = BaseList.map"-            , "wrong1 = ThisList.map"-            , "wrong2 = BaseList.x"-            ]-      _ <- createDoc "Data/List.hs" "haskell" thisDataListContent-      _ <- createDoc "Main.hs" "haskell" mainContent-      expectDiagnostics-        [ ( "Main.hs"-          , [(DsError, (6, 9), "Not in scope: \8216ThisList.map\8217")-            ,(DsError, (7, 9), "Not in scope: \8216BaseList.x\8217")-            ]-          )-        ]-  , testSessionWait "unqualified warnings" $ do-      let fooContent = T.unlines-            [ "{-# OPTIONS_GHC -Wredundant-constraints #-}"-            , "module Foo where"-            , "foo :: Ord a => a -> Int"-            , "foo a = 1"-            ]-      _ <- createDoc "Foo.hs" "haskell" fooContent-      expectDiagnostics-        [ ( "Foo.hs"-      -- The test is to make sure that warnings contain unqualified names-      -- where appropriate. The warning should use an unqualified name 'Ord', not-      -- sometihng like 'GHC.Classes.Ord'. The choice of redundant-constraints to-      -- test this is fairly arbitrary.-          , [(DsWarning, (2, 0), "Redundant constraint: Ord a")-            ]-          )-        ]-    , testSessionWait "lower-case drive" $ do-          let aContent = T.unlines-                [ "module A.A where"-                , "import A.B ()"-                ]-              bContent = T.unlines-                [ "{-# OPTIONS_GHC -Wall #-}"-                , "module A.B where"-                , "import Data.List"-                ]-          uriB <- getDocUri "A/B.hs"-          Just pathB <- pure $ uriToFilePath uriB-          uriB <- pure $-              let (drive, suffix) = splitDrive pathB-              in filePathToUri (joinDrive (lower drive) suffix)-          liftIO $ createDirectoryIfMissing True (takeDirectory pathB)-          liftIO $ writeFileUTF8 pathB $ T.unpack bContent-          uriA <- getDocUri "A/A.hs"-          Just pathA <- pure $ uriToFilePath uriA-          uriA <- pure $-              let (drive, suffix) = splitDrive pathA-              in filePathToUri (joinDrive (lower drive) suffix)-          let itemA = TextDocumentItem uriA "haskell" 0 aContent-          let a = TextDocumentIdentifier uriA-          sendNotification TextDocumentDidOpen (DidOpenTextDocumentParams itemA)-          diagsNot <- skipManyTill anyMessage diagnostic-          let PublishDiagnosticsParams fileUri diags = _params (diagsNot :: PublishDiagnosticsNotification)-          -- Check that if we put a lower-case drive in for A.A-          -- the diagnostics for A.B will also be lower-case.-          liftIO $ fileUri @?= uriB-          let msg = _message (head (toList diags) :: Diagnostic)-          liftIO $ unless ("redundant" `T.isInfixOf` msg) $-              assertFailure ("Expected redundant import but got " <> T.unpack msg)-          closeDoc a-  , testSessionWait "haddock parse error" $ do-      let fooContent = T.unlines-            [ "module Foo where"-            , "foo :: Int"-            , "foo = 1 {-|-}"-            ]-      _ <- createDoc "Foo.hs" "haskell" fooContent-      expectDiagnostics-        [ ( "Foo.hs"-          , [(DsError, (2, 8), "Parse error on input")-            ]-          )-        ]-  , testSessionWait "strip file path" $ do-      let-          name = "Testing"-          content = T.unlines-            [ "module " <> name <> " where"-            , "value :: Maybe ()"-            , "value = [()]"-            ]-      _ <- createDoc (T.unpack name <> ".hs") "haskell" content-      notification <- skipManyTill anyMessage diagnostic-      let-          offenders =-            Lsp.params .-            Lsp.diagnostics .-            Lens.folded .-            Lsp.message .-            Lens.filtered (T.isInfixOf ("/" <> name <> ".hs:"))-          failure msg = liftIO $ assertFailure $ "Expected file path to be stripped but got " <> T.unpack msg-      Lens.mapMOf_ offenders failure notification-  ]--codeActionTests :: TestTree-codeActionTests = testGroup "code actions"-  [ renameActionTests-  , typeWildCardActionTests-  , removeImportTests-  , extendImportTests-  , suggestImportTests-  , addExtensionTests-  , fixConstructorImportTests-  , importRenameActionTests-  , fillTypedHoleTests-  , addSigActionTests-  , insertNewDefinitionTests-  ]--codeLensesTests :: TestTree-codeLensesTests = testGroup "code lenses"-  [ addSigLensesTests-  ]--watchedFilesTests :: TestTree-watchedFilesTests = testGroup "watched files"-  [ testSession' "workspace files" $ \sessionDir -> do-      liftIO $ writeFile (sessionDir </> "hie.yaml") "cradle: {direct: {arguments: [\"-isrc\"]}}"-      _doc <- createDoc "A.hs" "haskell" "{-#LANGUAGE NoImplicitPrelude #-}\nmodule A where\nimport WatchedFilesMissingModule"-      watchedFileRegs <- getWatchedFilesSubscriptionsUntil @PublishDiagnosticsNotification--      -- Expect 4 subscriptions (A does not get any because it's VFS):-      --  - /path-to-workspace/WatchedFilesMissingModule.hs-      --  - /path-to-workspace/WatchedFilesMissingModule.lhs-      --  - /path-to-workspace/src/WatchedFilesMissingModule.hs-      --  - /path-to-workspace/src/WatchedFilesMissingModule.lhs-      liftIO $ length watchedFileRegs @?= 4--  , testSession' "non workspace file" $ \sessionDir -> do-      liftIO $ writeFile (sessionDir </> "hie.yaml") "cradle: {direct: {arguments: [\"-i/tmp\"]}}"-      _doc <- createDoc "A.hs" "haskell" "{-# LANGUAGE NoImplicitPrelude#-}\nmodule A where\nimport WatchedFilesMissingModule"-      watchedFileRegs <- getWatchedFilesSubscriptionsUntil @PublishDiagnosticsNotification--      -- Expect 2 subscriptions (/tmp does not get any as it is out of the workspace):-      --  - /path-to-workspace/WatchedFilesMissingModule.hs-      --  - /path-to-workspace/WatchedFilesMissingModule.lhs-      liftIO $ length watchedFileRegs @?= 2--  -- TODO add a test for didChangeWorkspaceFolder-  ]--renameActionTests :: TestTree-renameActionTests = testGroup "rename actions"-  [ testSession "change to local variable name" $ do-      let content = T.unlines-            [ "module Testing where"-            , "foo :: Int -> Int"-            , "foo argName = argNme"-            ]-      doc <- createDoc "Testing.hs" "haskell" content-      _ <- waitForDiagnostics-      action <- findCodeAction doc (Range (Position 2 14) (Position 2 20)) "Replace with ‘argName’"-      executeCodeAction action-      contentAfterAction <- documentContents doc-      let expectedContentAfterAction = T.unlines-            [ "module Testing where"-            , "foo :: Int -> Int"-            , "foo argName = argName"-            ]-      liftIO $ expectedContentAfterAction @=? contentAfterAction-  , testSession "change to name of imported function" $ do-      let content = T.unlines-            [ "module Testing where"-            , "import Data.Maybe (maybeToList)"-            , "foo :: Maybe a -> [a]"-            , "foo = maybToList"-            ]-      doc <- createDoc "Testing.hs" "haskell" content-      _ <- waitForDiagnostics-      action <- findCodeAction doc (Range (Position 3 6) (Position 3 16))  "Replace with ‘maybeToList’"-      executeCodeAction action-      contentAfterAction <- documentContents doc-      let expectedContentAfterAction = T.unlines-            [ "module Testing where"-            , "import Data.Maybe (maybeToList)"-            , "foo :: Maybe a -> [a]"-            , "foo = maybeToList"-            ]-      liftIO $ expectedContentAfterAction @=? contentAfterAction-  , testSession "suggest multiple local variable names" $ do-      let content = T.unlines-            [ "module Testing where"-            , "foo :: Char -> Char -> Char -> Char"-            , "foo argument1 argument2 argument3 = argumentX"-            ]-      doc <- createDoc "Testing.hs" "haskell" content-      _ <- waitForDiagnostics-      _ <- findCodeActions doc (Range (Position 2 36) (Position 2 45))-                           ["Replace with ‘argument1’", "Replace with ‘argument2’", "Replace with ‘argument3’"]-      return()-  , testSession "change infix function" $ do-      let content = T.unlines-            [ "module Testing where"-            , "monus :: Int -> Int"-            , "monus x y = max 0 (x - y)"-            , "foo x y = x `monnus` y"-            ]-      doc <- createDoc "Testing.hs" "haskell" content-      _ <- waitForDiagnostics-      actionsOrCommands <- getCodeActions doc (Range (Position 3 12) (Position 3 20))-      [fixTypo] <- pure [action | CACodeAction action@CodeAction{ _title = actionTitle } <- actionsOrCommands, "monus" `T.isInfixOf` actionTitle ]-      executeCodeAction fixTypo-      contentAfterAction <- documentContents doc-      let expectedContentAfterAction = T.unlines-            [ "module Testing where"-            , "monus :: Int -> Int"-            , "monus x y = max 0 (x - y)"-            , "foo x y = x `monus` y"-            ]-      liftIO $ expectedContentAfterAction @=? contentAfterAction-  ]--typeWildCardActionTests :: TestTree-typeWildCardActionTests = testGroup "type wildcard actions"-  [ testSession "global signature" $ do-      let content = T.unlines-            [ "module Testing where"-            , "func :: _"-            , "func x = x"-            ]-      doc <- createDoc "Testing.hs" "haskell" content-      _ <- waitForDiagnostics-      actionsOrCommands <- getCodeActions doc (Range (Position 2 1) (Position 2 10))-      let [addSignature] = [action | CACodeAction action@CodeAction { _title = actionTitle } <- actionsOrCommands-                                   , "Use type signature" `T.isInfixOf` actionTitle-                           ]-      executeCodeAction addSignature-      contentAfterAction <- documentContents doc-      let expectedContentAfterAction = T.unlines-            [ "module Testing where"-            , "func :: (p -> p)"-            , "func x = x"-            ]-      liftIO $ expectedContentAfterAction @=? contentAfterAction-  , testSession "multi-line message" $ do-      let content = T.unlines-            [ "module Testing where"-            , "func :: _"-            , "func x y = x + y"-            ]-      doc <- createDoc "Testing.hs" "haskell" content-      _ <- waitForDiagnostics-      actionsOrCommands <- getCodeActions doc (Range (Position 2 1) (Position 2 10))-      let [addSignature] = [action | CACodeAction action@CodeAction { _title = actionTitle } <- actionsOrCommands-                                    , "Use type signature" `T.isInfixOf` actionTitle-                              ]-      executeCodeAction addSignature-      contentAfterAction <- documentContents doc-      let expectedContentAfterAction = T.unlines-            [ "module Testing where"-            , "func :: (Integer -> Integer -> Integer)"-            , "func x y = x + y"-            ]-      liftIO $ expectedContentAfterAction @=? contentAfterAction-  , testSession "local signature" $ do-      let content = T.unlines-            [ "module Testing where"-            , "func :: Int -> Int"-            , "func x ="-            , "  let y :: _"-            , "      y = x * 2"-            , "  in y"-            ]-      doc <- createDoc "Testing.hs" "haskell" content-      _ <- waitForDiagnostics-      actionsOrCommands <- getCodeActions doc (Range (Position 4 1) (Position 4 10))-      let [addSignature] = [action | CACodeAction action@CodeAction { _title = actionTitle } <- actionsOrCommands-                                    , "Use type signature" `T.isInfixOf` actionTitle-                              ]-      executeCodeAction addSignature-      contentAfterAction <- documentContents doc-      let expectedContentAfterAction = T.unlines-            [ "module Testing where"-            , "func :: Int -> Int"-            , "func x ="-            , "  let y :: (Int)"-            , "      y = x * 2"-            , "  in y"-            ]-      liftIO $ expectedContentAfterAction @=? contentAfterAction-  ]--removeImportTests :: TestTree-removeImportTests = testGroup "remove import actions"-  [ testSession "redundant" $ do-      let contentA = T.unlines-            [ "module ModuleA where"-            ]-      _docA <- createDoc "ModuleA.hs" "haskell" contentA-      let contentB = T.unlines-            [ "{-# OPTIONS_GHC -Wunused-imports #-}"-            , "module ModuleB where"-            , "import ModuleA"-            , "stuffB :: Integer"-            , "stuffB = 123"-            ]-      docB <- createDoc "ModuleB.hs" "haskell" contentB-      _ <- waitForDiagnostics-      [CACodeAction action@CodeAction { _title = actionTitle }]-          <- getCodeActions docB (Range (Position 2 0) (Position 2 5))-      liftIO $ "Remove import" @=? actionTitle-      executeCodeAction action-      contentAfterAction <- documentContents docB-      let expectedContentAfterAction = T.unlines-            [ "{-# OPTIONS_GHC -Wunused-imports #-}"-            , "module ModuleB where"-            , "stuffB :: Integer"-            , "stuffB = 123"-            ]-      liftIO $ expectedContentAfterAction @=? contentAfterAction-  , testSession "qualified redundant" $ do-      let contentA = T.unlines-            [ "module ModuleA where"-            ]-      _docA <- createDoc "ModuleA.hs" "haskell" contentA-      let contentB = T.unlines-            [ "{-# OPTIONS_GHC -Wunused-imports #-}"-            , "module ModuleB where"-            , "import qualified ModuleA"-            , "stuffB :: Integer"-            , "stuffB = 123"-            ]-      docB <- createDoc "ModuleB.hs" "haskell" contentB-      _ <- waitForDiagnostics-      [CACodeAction action@CodeAction { _title = actionTitle }]-          <- getCodeActions docB (Range (Position 2 0) (Position 2 5))-      liftIO $ "Remove import" @=? actionTitle-      executeCodeAction action-      contentAfterAction <- documentContents docB-      let expectedContentAfterAction = T.unlines-            [ "{-# OPTIONS_GHC -Wunused-imports #-}"-            , "module ModuleB where"-            , "stuffB :: Integer"-            , "stuffB = 123"-            ]-      liftIO $ expectedContentAfterAction @=? contentAfterAction-  , testSession "redundant binding" $ do-      let contentA = T.unlines-            [ "module ModuleA where"-            , "stuffA = False"-            , "stuffB :: Integer"-            , "stuffB = 123"-            , "stuffC = ()"-            ]-      _docA <- createDoc "ModuleA.hs" "haskell" contentA-      let contentB = T.unlines-            [ "{-# OPTIONS_GHC -Wunused-imports #-}"-            , "module ModuleB where"-            , "import ModuleA (stuffA, stuffB, stuffC, stuffA)"-            , "main = print stuffB"-            ]-      docB <- createDoc "ModuleB.hs" "haskell" contentB-      _ <- waitForDiagnostics-      [CACodeAction action@CodeAction { _title = actionTitle }]-          <- getCodeActions docB (Range (Position 2 0) (Position 2 5))-      liftIO $ "Remove stuffA, stuffC from import" @=? actionTitle-      executeCodeAction action-      contentAfterAction <- documentContents docB-      let expectedContentAfterAction = T.unlines-            [ "{-# OPTIONS_GHC -Wunused-imports #-}"-            , "module ModuleB where"-            , "import ModuleA (stuffB)"-            , "main = print stuffB"-            ]-      liftIO $ expectedContentAfterAction @=? contentAfterAction-  , testSession "redundant operator" $ do-      let contentA = T.unlines-            [ "module ModuleA where"-            , "a !! b = a"-            , "a <?> b = a"-            , "stuffB :: Integer"-            , "stuffB = 123"-            ]-      _docA <- createDoc "ModuleA.hs" "haskell" contentA-      let contentB = T.unlines-            [ "{-# OPTIONS_GHC -Wunused-imports #-}"-            , "module ModuleB where"-            , "import qualified ModuleA as A ((<?>), stuffB, (!!))"-            , "main = print A.stuffB"-            ]-      docB <- createDoc "ModuleB.hs" "haskell" contentB-      _ <- waitForDiagnostics-      [CACodeAction action@CodeAction { _title = actionTitle }]-          <- getCodeActions docB (Range (Position 2 0) (Position 2 5))-      liftIO $ "Remove !!, <?> from import" @=? actionTitle-      executeCodeAction action-      contentAfterAction <- documentContents docB-      let expectedContentAfterAction = T.unlines-            [ "{-# OPTIONS_GHC -Wunused-imports #-}"-            , "module ModuleB where"-            , "import qualified ModuleA as A (stuffB)"-            , "main = print A.stuffB"-            ]-      liftIO $ expectedContentAfterAction @=? contentAfterAction-  , testSession "redundant all import" $ do-      let contentA = T.unlines-            [ "module ModuleA where"-            , "data A = A"-            , "stuffB :: Integer"-            , "stuffB = 123"-            ]-      _docA <- createDoc "ModuleA.hs" "haskell" contentA-      let contentB = T.unlines-            [ "{-# OPTIONS_GHC -Wunused-imports #-}"-            , "module ModuleB where"-            , "import ModuleA (A(..), stuffB)"-            , "main = print stuffB"-            ]-      docB <- createDoc "ModuleB.hs" "haskell" contentB-      _ <- waitForDiagnostics-      [CACodeAction action@CodeAction { _title = actionTitle }]-          <- getCodeActions docB (Range (Position 2 0) (Position 2 5))-      liftIO $ "Remove A from import" @=? actionTitle-      executeCodeAction action-      contentAfterAction <- documentContents docB-      let expectedContentAfterAction = T.unlines-            [ "{-# OPTIONS_GHC -Wunused-imports #-}"-            , "module ModuleB where"-            , "import ModuleA (stuffB)"-            , "main = print stuffB"-            ]-      liftIO $ expectedContentAfterAction @=? contentAfterAction-  , testSession "redundant constructor import" $ do-      let contentA = T.unlines-            [ "module ModuleA where"-            , "data D = A | B"-            , "data E = F"-            ]-      _docA <- createDoc "ModuleA.hs" "haskell" contentA-      let contentB = T.unlines-            [ "{-# OPTIONS_GHC -Wunused-imports #-}"-            , "module ModuleB where"-            , "import ModuleA (D(A,B), E(F))"-            , "main = B"-            ]-      docB <- createDoc "ModuleB.hs" "haskell" contentB-      _ <- waitForDiagnostics-      [CACodeAction action@CodeAction { _title = actionTitle }]-          <- getCodeActions docB (Range (Position 2 0) (Position 2 5))-      liftIO $ "Remove A, E, F from import" @=? actionTitle-      executeCodeAction action-      contentAfterAction <- documentContents docB-      let expectedContentAfterAction = T.unlines-            [ "{-# OPTIONS_GHC -Wunused-imports #-}"-            , "module ModuleB where"-            , "import ModuleA (D(B))"-            , "main = B"-            ]-      liftIO $ expectedContentAfterAction @=? contentAfterAction-  ]--extendImportTests :: TestTree-extendImportTests = testGroup "extend import actions"-  [ testSession "extend single line import with value" $ template-      (T.unlines-            [ "module ModuleA where"-            , "stuffA :: Double"-            , "stuffA = 0.00750"-            , "stuffB :: Integer"-            , "stuffB = 123"-            ])-      (T.unlines-            [ "module ModuleB where"-            , "import ModuleA as A (stuffB)"-            , "main = print (stuffA, stuffB)"-            ])-      (Range (Position 3 17) (Position 3 18))-      "Add stuffA to the import list of ModuleA"-      (T.unlines-            [ "module ModuleB where"-            , "import ModuleA as A (stuffA, stuffB)"-            , "main = print (stuffA, stuffB)"-            ])-  , testSession "extend single line import with operator" $ template-      (T.unlines-            [ "module ModuleA where"-            , "(.*) :: Integer -> Integer -> Integer"-            , "x .* y = x * y"-            , "stuffB :: Integer"-            , "stuffB = 123"-            ])-      (T.unlines-            [ "module ModuleB where"-            , "import ModuleA as A (stuffB)"-            , "main = print (stuffB .* stuffB)"-            ])-      (Range (Position 3 17) (Position 3 18))-      "Add .* to the import list of ModuleA"-      (T.unlines-            [ "module ModuleB where"-            , "import ModuleA as A ((.*), stuffB)"-            , "main = print (stuffB .* stuffB)"-            ])-  , testSession "extend single line import with type" $ template-      (T.unlines-            [ "module ModuleA where"-            , "type A = Double"-            ])-      (T.unlines-            [ "module ModuleB where"-            , "import ModuleA ()"-            , "b :: A"-            , "b = 0"-            ])-      (Range (Position 2 5) (Position 2 5))-      "Add A to the import list of ModuleA"-      (T.unlines-            [ "module ModuleB where"-            , "import ModuleA (A)"-            , "b :: A"-            , "b = 0"-            ])-  ,  (`xfail` "known broken") $ testSession "extend single line import with constructor" $ template-      (T.unlines-            [ "module ModuleA where"-            , "data A = Constructor"-            ])-      (T.unlines-            [ "module ModuleB where"-            , "import ModuleA (A)"-            , "b :: A"-            , "b = Constructor"-            ])-      (Range (Position 2 5) (Position 2 5))-      "Add Constructor to the import list of ModuleA"-      (T.unlines-            [ "module ModuleB where"-            , "import ModuleA (A(Constructor))"-            , "b :: A"-            , "b = Constructor"-            ])-  , testSession "extend single line qualified import with value" $ template-      (T.unlines-            [ "module ModuleA where"-            , "stuffA :: Double"-            , "stuffA = 0.00750"-            , "stuffB :: Integer"-            , "stuffB = 123"-            ])-      (T.unlines-            [ "module ModuleB where"-            , "import qualified ModuleA as A (stuffB)"-            , "main = print (A.stuffA, A.stuffB)"-            ])-      (Range (Position 3 17) (Position 3 18))-      "Add stuffA to the import list of ModuleA"-      (T.unlines-            [ "module ModuleB where"-            , "import qualified ModuleA as A (stuffA, stuffB)"-            , "main = print (A.stuffA, A.stuffB)"-            ])-  , testSession "extend multi line import with value" $ template-      (T.unlines-            [ "module ModuleA where"-            , "stuffA :: Double"-            , "stuffA = 0.00750"-            , "stuffB :: Integer"-            , "stuffB = 123"-            ])-      (T.unlines-            [ "module ModuleB where"-            , "import ModuleA (stuffB"-            , "               )"-            , "main = print (stuffA, stuffB)"-            ])-      (Range (Position 3 17) (Position 3 18))-      "Add stuffA to the import list of ModuleA"-      (T.unlines-            [ "module ModuleB where"-            , "import ModuleA (stuffA, stuffB"-            , "               )"-            , "main = print (stuffA, stuffB)"-            ])-  ]-  where-    template contentA contentB range expectedAction expectedContentB = do-      _docA <- createDoc "ModuleA.hs" "haskell" contentA-      docB <- createDoc "ModuleB.hs" "haskell" contentB-      _ <- waitForDiagnostics-      CACodeAction action@CodeAction { _title = actionTitle } : _-                  <- sortOn (\(CACodeAction CodeAction{_title=x}) -> x) <$>-                     getCodeActions docB range-      liftIO $ expectedAction @=? actionTitle-      executeCodeAction action-      contentAfterAction <- documentContents docB-      liftIO $ expectedContentB @=? contentAfterAction--suggestImportTests :: TestTree-suggestImportTests = testGroup "suggest import actions"-  [ testGroup "Dont want suggestion"-    [ -- extend import-      test False ["Data.List.NonEmpty ()"] "f = nonEmpty" []                "import Data.List.NonEmpty (nonEmpty)"-      -- data constructor-    , test False []                        "f = First"    []                "import Data.Monoid (First)"-      -- internal module-    , test False []         "f :: Typeable a => a"        ["f = undefined"] "import Data.Typeable.Internal (Typeable)"-      -- package not in scope-    , test False []         "f = quickCheck"              []                "import Test.QuickCheck (quickCheck)"-    ]-  , testGroup "want suggestion"-    [ test True []          "f = nonEmpty"                []                "import Data.List.NonEmpty (nonEmpty)"-    , test True []          "f = (:|)"                    []                "import Data.List.NonEmpty (NonEmpty((:|)))"-    , test True []          "f :: Natural"                ["f = undefined"] "import Numeric.Natural (Natural)"-    , test True []          "f :: NonEmpty ()"            ["f = () :| []"]  "import Data.List.NonEmpty (NonEmpty)"-    , test True []          "f = First"                   []                "import Data.Monoid (First(First))"-    , test True []          "f = Endo"                    []                "import Data.Monoid (Endo(Endo))"-    , test True []          "f = Version"                 []                "import Data.Version (Version(Version))"-    , test True []          "f ExitSuccess = ()"          []                "import System.Exit (ExitCode(ExitSuccess))"-    , test True []          "f = AssertionFailed"         []                "import Control.Exception (AssertionFailed(AssertionFailed))"-    , test True ["Prelude"] "f = nonEmpty"                []                "import Data.List.NonEmpty (nonEmpty)"-    , test True []          "f :: Alternative f => f ()"  ["f = undefined"] "import Control.Applicative (Alternative)"-    , test True []          "f = empty"                   []                "import Control.Applicative (Alternative(empty))"-    , test True []          "f = (&)"                     []                "import Data.Function ((&))"-    , test True []          "f = NE.nonEmpty"             []                "import qualified Data.List.NonEmpty as NE"-    , test True []          "f :: Typeable a => a"        ["f = undefined"] "import Data.Typeable (Typeable)"-    , test True []          "f = pack"                    []                "import Data.Text (pack)"-    , test True []          "f :: Text"                   ["f = undefined"] "import Data.Text (Text)"-    , test True []          "f = [] & id"                 []                "import Data.Function ((&))"-    , test True []          "f = (&) [] id"               []                "import Data.Function ((&))"-    ]-  ]-  where-    test wanted imps def other newImp = testSession' (T.unpack def) $ \dir -> do-      let before = T.unlines $ "module A where" : ["import " <> x | x <- imps] ++ def : other-          after  = T.unlines $ "module A where" : ["import " <> x | x <- imps] ++ [newImp] ++ def : other-          cradle = "cradle: {direct: {arguments: [-hide-all-packages, -package, base, -package, text, -package-env, -]}}"-      liftIO $ writeFileUTF8 (dir </> "hie.yaml") cradle-      doc <- createDoc "Test.hs" "haskell" before-      _diags <- waitForDiagnostics-      let defLine = length imps + 1-          range = Range (Position defLine 0) (Position defLine maxBound)-      actions <- getCodeActions doc range-      if wanted-         then do-             action <- liftIO $ pickActionWithTitle newImp actions-             executeCodeAction action-             contentAfterAction <- documentContents doc-             liftIO $ after @=? contentAfterAction-          else-              liftIO $ [_title | CACodeAction CodeAction{_title} <- actions, _title == newImp ] @?= []---addExtensionTests :: TestTree-addExtensionTests = testGroup "add language extension actions"-  [ testSession "add NamedFieldPuns language extension" $ template-      (T.unlines-            [ "module Module where"-            , ""-            , "data A = A { getA :: Bool }"-            , ""-            , "f :: A -> Bool"-            , "f A { getA } = getA"-            ])-      (Range (Position 0 0) (Position 0 0))-      "Add NamedFieldPuns extension"-      (T.unlines-            [ "{-# LANGUAGE NamedFieldPuns #-}"-            , "module Module where"-            , ""-            , "data A = A { getA :: Bool }"-            , ""-            , "f :: A -> Bool"-            , "f A { getA } = getA"-            ])-  , testSession "add RecordWildCards language extension" $ template-      (T.unlines-            [ "module Module where"-            , ""-            , "data A = A { getA :: Bool }"-            , ""-            , "f :: A -> Bool"-            , "f A { .. } = getA"-            ])-      (Range (Position 0 0) (Position 0 0))-      "Add RecordWildCards extension"-      (T.unlines-            [ "{-# LANGUAGE RecordWildCards #-}"-            , "module Module where"-            , ""-            , "data A = A { getA :: Bool }"-            , ""-            , "f :: A -> Bool"-            , "f A { .. } = getA"-            ])-  ]-    where-      template initialContent range expectedAction expectedContents = do-        doc <- createDoc "Module.hs" "haskell" initialContent-        _ <- waitForDiagnostics-        CACodeAction action@CodeAction { _title = actionTitle } : _-                    <- sortOn (\(CACodeAction CodeAction{_title=x}) -> x) <$>-                       getCodeActions doc range-        liftIO $ expectedAction @=? actionTitle-        executeCodeAction action-        contentAfterAction <- documentContents doc-        liftIO $ expectedContents @=? contentAfterAction---insertNewDefinitionTests :: TestTree-insertNewDefinitionTests = testGroup "insert new definition actions"-  [ testSession "insert new function definition" $ do-      let txtB =-            ["foo True = select [True]"-            , ""-            ,"foo False = False"-            ]-          txtB' =-            [""-            ,"someOtherCode = ()"-            ]-      docB <- createDoc "ModuleB.hs" "haskell" (T.unlines $ txtB ++ txtB')-      _ <- waitForDiagnostics-      CACodeAction action@CodeAction { _title = actionTitle } : _-                  <- sortOn (\(CACodeAction CodeAction{_title=x}) -> x) <$>-                     getCodeActions docB (R 1 0 1 50)-      liftIO $ actionTitle @?= "Define select :: [Bool] -> Bool"-      executeCodeAction action-      contentAfterAction <- documentContents docB-      liftIO $ contentAfterAction @?= T.unlines (txtB ++-        [ ""-        , "select :: [Bool] -> Bool"-        , "select = error \"not implemented\""-        ]-        ++ txtB')-  , testSession "define a hole" $ do-      let txtB =-            ["foo True = _select [True]"-            , ""-            ,"foo False = False"-            ]-          txtB' =-            [""-            ,"someOtherCode = ()"-            ]-      docB <- createDoc "ModuleB.hs" "haskell" (T.unlines $ txtB ++ txtB')-      _ <- waitForDiagnostics-      CACodeAction action@CodeAction { _title = actionTitle } : _-                  <- sortOn (\(CACodeAction CodeAction{_title=x}) -> x) <$>-                     getCodeActions docB (R 1 0 1 50)-      liftIO $ actionTitle @?= "Define select :: [Bool] -> Bool"-      executeCodeAction action-      contentAfterAction <- documentContents docB-      liftIO $ contentAfterAction @?= T.unlines (-        ["foo True = select [True]"-        , ""-        ,"foo False = False"-        , ""-        , "select :: [Bool] -> Bool"-        , "select = error \"not implemented\""-        ]-        ++ txtB')-  ]--fixConstructorImportTests :: TestTree-fixConstructorImportTests = testGroup "fix import actions"-  [ testSession "fix constructor import" $ template-      (T.unlines-            [ "module ModuleA where"-            , "data A = Constructor"-            ])-      (T.unlines-            [ "module ModuleB where"-            , "import ModuleA(Constructor)"-            ])-      (Range (Position 1 10) (Position 1 11))-      "Fix import of A(Constructor)"-      (T.unlines-            [ "module ModuleB where"-            , "import ModuleA(A(Constructor))"-            ])-  ]-  where-    template contentA contentB range expectedAction expectedContentB = do-      _docA <- createDoc "ModuleA.hs" "haskell" contentA-      docB  <- createDoc "ModuleB.hs" "haskell" contentB-      _diags <- waitForDiagnostics-      CACodeAction action@CodeAction { _title = actionTitle } : _-                  <- sortOn (\(CACodeAction CodeAction{_title=x}) -> x) <$>-                     getCodeActions docB range-      liftIO $ expectedAction @=? actionTitle-      executeCodeAction action-      contentAfterAction <- documentContents docB-      liftIO $ expectedContentB @=? contentAfterAction--importRenameActionTests :: TestTree-importRenameActionTests = testGroup "import rename actions"-  [ testSession "Data.Mape -> Data.Map"   $ check "Map"-  , testSession "Data.Mape -> Data.Maybe" $ check "Maybe" ] where-  check modname = do-      let content = T.unlines-            [ "module Testing where"-            , "import Data.Mape"-            ]-      doc <- createDoc "Testing.hs" "haskell" content-      _ <- waitForDiagnostics-      actionsOrCommands <- getCodeActions doc (Range (Position 2 8) (Position 2 16))-      let [changeToMap] = [action | CACodeAction action@CodeAction{ _title = actionTitle } <- actionsOrCommands, ("Data." <> modname) `T.isInfixOf` actionTitle ]-      executeCodeAction changeToMap-      contentAfterAction <- documentContents doc-      let expectedContentAfterAction = T.unlines-            [ "module Testing where"-            , "import Data." <> modname-            ]-      liftIO $ expectedContentAfterAction @=? contentAfterAction--fillTypedHoleTests :: TestTree-fillTypedHoleTests = let--  sourceCode :: T.Text -> T.Text -> T.Text -> T.Text-  sourceCode a b c = T.unlines-    [ "module Testing where"-      , ""-      , "globalConvert :: Int -> String"-      , "globalConvert = undefined"-      , ""-      , "globalInt :: Int"-      , "globalInt = 3"-      , ""-      , "bar :: Int -> Int -> String"-      , "bar n parameterInt = " <> a <> " (n + " <> b <> " + " <> c <> ")  where"-      , "  localConvert = (flip replicate) 'x'"--    ]--  check :: T.Text -> T.Text -> T.Text -> T.Text -> T.Text -> T.Text -> T.Text -> TestTree-  check actionTitle-        oldA oldB oldC-        newA newB newC = testSession (T.unpack actionTitle) $ do-    let originalCode = sourceCode oldA oldB oldC-    let expectedCode = sourceCode newA newB newC-    doc <- createDoc "Testing.hs" "haskell" originalCode-    _ <- waitForDiagnostics-    actionsOrCommands <- getCodeActions doc (Range (Position 9 0) (Position 9 maxBound))-    chosenAction <- liftIO $ pickActionWithTitle actionTitle actionsOrCommands-    executeCodeAction chosenAction-    modifiedCode <- documentContents doc-    liftIO $ expectedCode @=? modifiedCode-  in-  testGroup "fill typed holes"-  [ check "replace hole `_` with show"-          "_"    "n" "n"-          "show" "n" "n"--  , check "replace hole `_` with globalConvert"-          "_"             "n" "n"-          "globalConvert" "n" "n"--#if MIN_GHC_API_VERSION(8,6,0)-  , check "replace hole `_convertme` with localConvert"-          "_convertme"   "n" "n"-          "localConvert" "n" "n"-#endif--  , check "replace hole `_b` with globalInt"-          "_a" "_b"        "_c"-          "_a" "globalInt" "_c"--  , check "replace hole `_c` with globalInt"-          "_a" "_b"        "_c"-          "_a" "_b" "globalInt"--#if MIN_GHC_API_VERSION(8,6,0)-  , check "replace hole `_c` with parameterInt"-          "_a" "_b" "_c"-          "_a" "_b"  "parameterInt"-#endif-  ]--addSigActionTests :: TestTree-addSigActionTests = let-  header = "{-# OPTIONS_GHC -Wmissing-signatures -Wmissing-pattern-synonym-signatures #-}"-  moduleH = "{-# LANGUAGE PatternSynonyms #-}\nmodule Sigs where"-  before def     = T.unlines [header, moduleH,      def]-  after' def sig = T.unlines [header, moduleH, sig, def]--  def >:: sig = testSession (T.unpack def) $ do-    let originalCode = before def-    let expectedCode = after' def sig-    doc <- createDoc "Sigs.hs" "haskell" originalCode-    _ <- waitForDiagnostics-    actionsOrCommands <- getCodeActions doc (Range (Position 3 1) (Position 3 maxBound))-    chosenAction <- liftIO $ pickActionWithTitle ("add signature: " <> sig) actionsOrCommands-    executeCodeAction chosenAction-    modifiedCode <- documentContents doc-    liftIO $ expectedCode @=? modifiedCode-  in-  testGroup "add signature"-    [ "abc = True"              >:: "abc :: Bool"-    , "foo a b = a + b"         >:: "foo :: Num a => a -> a -> a"-    , "bar a b = show $ a + b"  >:: "bar :: (Show a, Num a) => a -> a -> String"-    , "(!!!) a b = a > b"       >:: "(!!!) :: Ord a => a -> a -> Bool"-    , "a >>>> b = a + b"        >:: "(>>>>) :: Num a => a -> a -> a"-    , "a `haha` b = a b"        >:: "haha :: (t1 -> t2) -> t1 -> t2"-    , "pattern Some a = Just a" >:: "pattern Some :: a -> Maybe a"-    ]--addSigLensesTests :: TestTree-addSigLensesTests = let-  missing = "{-# OPTIONS_GHC -Wmissing-signatures -Wmissing-pattern-synonym-signatures -Wunused-matches #-}"-  notMissing = "{-# OPTIONS_GHC -Wunused-matches #-}"-  moduleH = "{-# LANGUAGE PatternSynonyms #-}\nmodule Sigs where"-  other = T.unlines ["f :: Integer -> Integer", "f x = 3"]-  before  withMissing def-    = T.unlines $ (if withMissing then (missing :) else (notMissing :)) [moduleH, def, other]-  after'  withMissing def sig-    = T.unlines $ (if withMissing then (missing :) else (notMissing :)) [moduleH, sig, def, other]--  sigSession withMissing def sig = testSession (T.unpack def) $ do-    let originalCode = before withMissing def-    let expectedCode = after' withMissing def sig-    doc <- createDoc "Sigs.hs" "haskell" originalCode-    [CodeLens {_command = Just c}] <- getCodeLenses doc-    executeCommand c-    modifiedCode <- getDocumentEdit doc-    liftIO $ expectedCode @=? modifiedCode-  in-  testGroup "add signature"-    [ testGroup title-      [ sigSession enableWarnings "abc = True"              "abc :: Bool"-      , sigSession enableWarnings "foo a b = a + b"         "foo :: Num a => a -> a -> a"-      , sigSession enableWarnings "bar a b = show $ a + b"  "bar :: (Show a, Num a) => a -> a -> String"-      , sigSession enableWarnings "(!!!) a b = a > b"       "(!!!) :: Ord a => a -> a -> Bool"-      , sigSession enableWarnings "a >>>> b = a + b"        "(>>>>) :: Num a => a -> a -> a"-      , sigSession enableWarnings "a `haha` b = a b"        "haha :: (t1 -> t2) -> t1 -> t2"-      , sigSession enableWarnings "pattern Some a = Just a" "pattern Some :: a -> Maybe a"-      ]-      | (title, enableWarnings) <--        [("with warnings enabled", True)-        ,("with warnings disabled", False)-        ]-    ]--checkDefs :: [Location] -> Session [Expect] -> Session ()-checkDefs defs mkExpectations = traverse_ check =<< mkExpectations where--  check (ExpectRange expectedRange) = do-    assertNDefinitionsFound 1 defs-    assertRangeCorrect (head defs) expectedRange-  check (ExpectLocation expectedLocation) = do-    assertNDefinitionsFound 1 defs-    liftIO $ head defs @?= expectedLocation-  check ExpectNoDefinitions = do-    assertNDefinitionsFound 0 defs-  check ExpectExternFail = liftIO $ assertFailure "Expecting to fail to find in external file"-  check _ = pure () -- all other expectations not relevant to getDefinition--  assertNDefinitionsFound :: Int -> [a] -> Session ()-  assertNDefinitionsFound n defs = liftIO $ assertEqual "number of definitions" n (length defs)--  assertRangeCorrect Location{_range = foundRange} expectedRange =-    liftIO $ expectedRange @=? foundRange---findDefinitionAndHoverTests :: TestTree-findDefinitionAndHoverTests = let--  tst (get, check) pos targetRange title = testSessionWithExtraFiles "hover" title $ \dir -> do-    doc <- openTestDataDoc (dir </> sourceFilePath)-    found <- get doc pos-    check found targetRange----  checkHover :: Maybe Hover -> Session [Expect] -> Session ()-  checkHover hover expectations = traverse_ check =<< expectations where--    check expected =-      case hover of-        Nothing -> unless (expected == ExpectNoHover) $ liftIO $ assertFailure "no hover found"-        Just Hover{_contents = (HoverContents MarkupContent{_value = msg})-                  ,_range    = rangeInHover } ->-          case expected of-            ExpectRange  expectedRange -> checkHoverRange expectedRange rangeInHover msg-            ExpectHoverRange expectedRange -> checkHoverRange expectedRange rangeInHover msg-            ExpectHoverText snippets -> liftIO $ traverse_ (`assertFoundIn` msg) snippets-            ExpectNoHover -> liftIO $ assertFailure $ "Expected no hover but got " <> show hover-            _ -> pure () -- all other expectations not relevant to hover-        _ -> liftIO $ assertFailure $ "test not expecting this kind of hover info" <> show hover--  extractLineColFromHoverMsg :: T.Text -> [T.Text]-  extractLineColFromHoverMsg = T.splitOn ":" . head . T.splitOn "*" . last . T.splitOn (sourceFileName <> ":")--  checkHoverRange :: Range -> Maybe Range -> T.Text -> Session ()-  checkHoverRange expectedRange rangeInHover msg =-    let-      lineCol = extractLineColFromHoverMsg msg-      -- looks like hovers use 1-based numbering while definitions use 0-based-      -- turns out that they are stored 1-based in RealSrcLoc by GHC itself.-      adjust Position{_line = l, _character = c} =-        Position{_line = l + 1, _character = c + 1}-    in-    case map (read . T.unpack) lineCol of-      [l,c] -> liftIO $ (adjust $ _start expectedRange) @=? Position l c-      _     -> liftIO $ assertFailure $-        "expected: " <> show ("[...]" <> sourceFileName <> ":<LINE>:<COL>**[...]", Just expectedRange) <>-        "\n but got: " <> show (msg, rangeInHover)--  assertFoundIn :: T.Text -> T.Text -> Assertion-  assertFoundIn part whole = assertBool-    (T.unpack $ "failed to find: `" <> part <> "` in hover message:\n" <> whole)-    (part `T.isInfixOf` whole)--  sourceFilePath = T.unpack sourceFileName-  sourceFileName = "GotoHover.hs"--  mkFindTests tests = testGroup "get"-    [ testGroup "definition" $ mapMaybe fst tests-    , testGroup "hover"      $ mapMaybe snd tests-    , checkFileCompiles sourceFilePath ]--  test runDef runHover look expect = testM runDef runHover look (return expect)--  testM runDef runHover look expect title =-    ( runDef   $ tst def   look expect title-    , runHover $ tst hover look expect title ) where-      def   = (getDefinitions, checkDefs)-      hover = (getHover      , checkHover)-      --type_ = (getTypeDefinitions, checkTDefs) -- getTypeDefinitions always times out--  -- search locations            expectations on results-  fffL4  = _start fffR     ;  fffR = mkRange 8  4    8  7 ; fff  = [ExpectRange fffR]-  fffL8  = Position 12  4  ;-  fffL14 = Position 18  7  ;-  aaaL14 = Position 18 20  ;  aaa    = [mkR  11  0   11  3]-  dcL7   = Position 11 11  ;  tcDC   = [mkR   7 23    9 16]-  dcL12  = Position 16 11  ;-  xtcL5  = Position  9 11  ;  xtc    = [ExpectExternFail,   ExpectHoverText ["Int", "Defined in ‘GHC.Types’"]]-  tcL6   = Position 10 11  ;  tcData = [mkR   7  0    9 16, ExpectHoverText ["TypeConstructor", "GotoHover.hs:8:1"]]-  vvL16  = Position 20 12  ;  vv     = [mkR  20  4   20  6]-  opL16  = Position 20 15  ;  op     = [mkR  21  2   21  4]-  opL18  = Position 22 22  ;  opp    = [mkR  22 13   22 17]-  aL18   = Position 22 20  ;  apmp   = [mkR  22 10   22 11]-  b'L19  = Position 23 13  ;  bp     = [mkR  23  6   23  7]-  xvL20  = Position 24  8  ;  xvMsg  = [ExpectExternFail,   ExpectHoverText ["Data.Text.pack", ":: String -> Text"]]-  clL23  = Position 27 11  ;  cls    = [mkR  25  0   26 20, ExpectHoverText ["MyClass", "GotoHover.hs:26:1"]]-  clL25  = Position 29  9-  eclL15 = Position 19  8  ;  ecls   = [ExpectExternFail, ExpectHoverText ["Num", "Defined in ‘GHC.Num’"]]-  dnbL29 = Position 33 18  ;  dnb    = [ExpectHoverText [":: ()"],   mkR  33 12   33 21]-  dnbL30 = Position 34 23-  lcbL33 = Position 37 26  ;  lcb    = [ExpectHoverText [":: Char"], mkR  37 26   37 27]-  lclL33 = Position 37 22-  mclL36 = Position 40  1  ;  mcl    = [mkR  40  0   40 14]-  mclL37 = Position 41  1-  spaceL37 = Position 41  24 ; space = [ExpectNoDefinitions, ExpectHoverText [":: Char"]]-  docL41 = Position 45  1  ;  doc    = [ExpectHoverText ["Recognizable docs: kpqz"]]-                           ;  constr = [ExpectHoverText ["Monad m"]]-  eitL40 = Position 44 28  ;  kindE  = [ExpectHoverText [":: * -> * -> *\n"]]-  intL40 = Position 44 34  ;  kindI  = [ExpectHoverText [":: *\n"]]-  tvrL40 = Position 44 37  ;  kindV  = [ExpectHoverText [":: * -> *\n"]]-  intL41 = Position 45 20  ;  litI   = [ExpectHoverText ["7518"]]-  chrL36 = Position 41 24  ;  litC   = [ExpectHoverText ["'f'"]]-  txtL8  = Position 12 14  ;  litT   = [ExpectHoverText ["\"dfgy\""]]-  lstL43 = Position 47 12  ;  litL   = [ExpectHoverText ["[8391 :: Int, 6268]"]]-  outL45 = Position 49  3  ;  outSig = [ExpectHoverText ["outer", "Bool"], mkR 46 0 46 5]-  innL48 = Position 52  5  ;  innSig = [ExpectHoverText ["inner", "Char"], mkR 49 2 49 7]-  imported = Position 56 13 ; importedSig = getDocUri "Foo.hs" >>= \foo -> return [ExpectHoverText ["foo", "Foo"], mkL foo 4 0 4 3]-  reexported = Position 55 14 ; reexportedSig = getDocUri "Bar.hs" >>= \bar -> return [ExpectHoverText ["Bar", "Bar"], mkL bar 2 0 2 14]-  in-  mkFindTests-  --     def    hover  look       expect-  [ test  yes    yes    fffL4      fff           "field in record definition"-  , test  broken broken fffL8      fff           "field in record construction     #71"-  , test  yes    yes    fffL14     fff           "field name used as accessor"          -- 120 in Calculate.hs-  , test  yes    yes    aaaL14     aaa           "top-level name"                       -- 120-  , test  yes    yes    dcL7       tcDC          "data constructor record         #247"-  , test  yes    yes    dcL12      tcDC          "data constructor plain"               -- 121-  , test  yes    yes    tcL6       tcData        "type constructor                #248" -- 147-  , test  broken yes    xtcL5      xtc           "type constructor external   #248,249"-  , test  broken yes    xvL20      xvMsg         "value external package          #249" -- 120-  , test  yes    yes    vvL16      vv            "plain parameter"                      -- 120-  , test  yes    yes    aL18       apmp          "pattern match name"                   -- 120-  , test  yes    yes    opL16      op            "top-level operator"                   -- 120, 123-  , test  yes    yes    opL18      opp           "parameter operator"                   -- 120-  , test  yes    yes    b'L19      bp            "name in backticks"                    -- 120-  , test  yes    yes    clL23      cls           "class in instance declaration   #250"-  , test  yes    yes    clL25      cls           "class in signature              #250" -- 147-  , test  broken yes    eclL15     ecls          "external class in signature #249,250"-  , test  yes    yes    dnbL29     dnb           "do-notation   bind"                   -- 137-  , test  yes    yes    dnbL30     dnb           "do-notation lookup"-  , test  yes    yes    lcbL33     lcb           "listcomp   bind"                      -- 137-  , test  yes    yes    lclL33     lcb           "listcomp lookup"-  , test  yes    yes    mclL36     mcl           "top-level fn 1st clause"-  , test  yes    yes    mclL37     mcl           "top-level fn 2nd clause         #246"-  , test  yes    yes    spaceL37   space        "top-level fn on space #315"-  , test  no     broken docL41     doc           "documentation                     #7"-  , test  no     yes    eitL40     kindE         "kind of Either                  #273"-  , test  no     yes    intL40     kindI         "kind of Int                     #273"-  , test  no     broken tvrL40     kindV         "kind of (* -> *) type variable  #273"-  , test  no     yes    intL41     litI          "literal Int  in hover info      #274"-  , test  no     yes    chrL36     litC          "literal Char in hover info      #274"-  , test  no     yes    txtL8      litT          "literal Text in hover info      #274"-  , test  no     yes    lstL43     litL          "literal List in hover info      #274"-  , test  no     yes    docL41     constr        "type constraint in hover info   #283"-  , test  broken broken outL45     outSig        "top-level signature             #310"-  , test  broken broken innL48     innSig        "inner     signature             #310"-  , testM yes    yes    imported   importedSig   "Imported symbol"-  , testM yes    yes    reexported reexportedSig "Imported symbol (reexported)"-  ]-  where yes, broken :: (TestTree -> Maybe TestTree)-        yes    = Just -- test should run and pass-        broken = Just . (`xfail` "known broken")-        no = const Nothing -- don't run this test at all--checkFileCompiles :: FilePath -> TestTree-checkFileCompiles fp =-  testSessionWithExtraFiles "hover" ("Does " ++ fp ++ " compile") $ \dir -> do-    void (openTestDataDoc (dir </> fp))-    expectNoMoreDiagnostics 0.5----pluginTests :: TestTree-pluginTests = (`xfail8101` "known broken (#556)")-            $ testSessionWait "plugins" $ do-  let content =-        T.unlines-          [ "{-# OPTIONS_GHC -fplugin GHC.TypeLits.KnownNat.Solver #-}"-          , "{-# LANGUAGE DataKinds, ScopedTypeVariables, TypeOperators #-}"-          , "module Testing where"-          , "import Data.Proxy"-          , "import GHC.TypeLits"-          -- This function fails without plugins being initialized.-          , "f :: forall n. KnownNat n => Proxy n -> Integer"-          , "f _ = natVal (Proxy :: Proxy n) + natVal (Proxy :: Proxy (n+2))"-          , "foo :: Int -> Int -> Int"-          , "foo a b = a + c"-          ]-  _ <- createDoc "Testing.hs" "haskell" content-  expectDiagnostics-    [ ( "Testing.hs",-        [(DsError, (8, 14), "Variable not in scope: c")]-      )-    ]--cppTests :: TestTree-cppTests =-  testGroup "cpp"-    [ testCase "cpp-error" $ do-        let content =-              T.unlines-                [ "{-# LANGUAGE CPP #-}",-                  "module Testing where",-                  "#ifdef FOO",-                  "foo = 42"-                ]-        -- The error locations differ depending on which C-preprocessor is used.-        -- Some give the column number and others don't (hence -1). Assert either-        -- of them.-        (run $ expectError content (2, -1))-          `catch` ( \e -> do-                      let _ = e :: HUnitFailure-                      run $ expectError content (2, 1)-                  )-    , testSessionWait "cpp-ghcide" $ do-        _ <- createDoc "A.hs" "haskell" $ T.unlines-          ["{-# LANGUAGE CPP #-}"-          ,"main ="-          ,"#ifdef __GHCIDE__"-          ,"  worked"-          ,"#else"-          ,"  failed"-          ,"#endif"-          ]-        expectDiagnostics [("A.hs", [(DsError, (3, 2), "Variable not in scope: worked")])]-    ]-  where-    expectError :: T.Text -> Cursor -> Session ()-    expectError content cursor = do-      _ <- createDoc "Testing.hs" "haskell" content-      expectDiagnostics-        [ ( "Testing.hs",-            [(DsError, cursor, "error: unterminated")]-          )-        ]-      expectNoMoreDiagnostics 0.5--preprocessorTests :: TestTree-preprocessorTests = testSessionWait "preprocessor" $ do-  let content =-        T.unlines-          [ "{-# OPTIONS_GHC -F -pgmF=ghcide-test-preprocessor #-}"-          , "module Testing where"-          , "y = x + z" -- plugin replaces x with y, making this have only one diagnostic-          ]-  _ <- createDoc "Testing.hs" "haskell" content-  expectDiagnostics-    [ ( "Testing.hs",-        [(DsError, (2, 8), "Variable not in scope: z")]-      )-    ]---safeTests :: TestTree-safeTests =-  testGroup-    "SafeHaskell"-    [ -- Test for https://github.com/digital-asset/ghcide/issues/424-      testSessionWait "load" $ do-        let sourceA =-              T.unlines-                ["{-# LANGUAGE Trustworthy #-}"-                ,"module A where"-                ,"import System.IO.Unsafe"-                ,"import System.IO"-                ,"trustWorthyId :: a -> a"-                ,"trustWorthyId i = unsafePerformIO $ do"-                ,"  putStrLn \"I'm safe\""-                ,"  return i"]-            sourceB =-              T.unlines-                ["{-# LANGUAGE Safe #-}"-                ,"module B where"-                ,"import A"-                ,"safeId :: a -> a"-                ,"safeId = trustWorthyId"-                ]--        _ <- createDoc "A.hs" "haskell" sourceA-        _ <- createDoc "B.hs" "haskell" sourceB-        expectNoMoreDiagnostics 1 ]--thTests :: TestTree-thTests =-  testGroup-    "TemplateHaskell"-    [ -- Test for https://github.com/digital-asset/ghcide/pull/212-      testSessionWait "load" $ do-        let sourceA =-              T.unlines-                [ "{-# LANGUAGE PackageImports #-}",-                  "{-# LANGUAGE TemplateHaskell #-}",-                  "module A where",-                  "import \"template-haskell\" Language.Haskell.TH",-                  "a :: Integer",-                  "a = $(litE $ IntegerL 3)"-                ]-            sourceB =-              T.unlines-                [ "{-# LANGUAGE PackageImports #-}",-                  "{-# LANGUAGE TemplateHaskell #-}",-                  "module B where",-                  "import A",-                  "import \"template-haskell\" Language.Haskell.TH",-                  "b :: Integer",-                  "b = $(litE $ IntegerL $ a) + n"-                ]-        _ <- createDoc "A.hs" "haskell" sourceA-        _ <- createDoc "B.hs" "haskell" sourceB-        expectDiagnostics [ ( "B.hs", [(DsError, (6, 29), "Variable not in scope: n")] ) ]-    , testSessionWait "newtype-closure" $ do-        let sourceA =-              T.unlines-                [ "{-# LANGUAGE DeriveDataTypeable #-}"-                  ,"{-# LANGUAGE TemplateHaskell #-}"-                  ,"module A (a) where"-                  ,"import Data.Data"-                  ,"import Language.Haskell.TH"-                  ,"newtype A = A () deriving (Data)"-                  ,"a :: ExpQ"-                  ,"a = [| 0 |]"]-        let sourceB =-              T.unlines-                [ "{-# LANGUAGE TemplateHaskell #-}"-                ,"module B where"-                ,"import A"-                ,"b :: Int"-                ,"b = $( a )" ]-        _ <- createDoc "A.hs" "haskell" sourceA-        _ <- createDoc "B.hs" "haskell" sourceB-        return ()-    ]--completionTests :: TestTree-completionTests-  = testGroup "completion"-    [ testSessionWait "variable" $ do-        let source = T.unlines ["module A where", "f = hea"]-        docId <- createDoc "A.hs" "haskell" source-        compls <- getCompletions docId (Position 1 7)-        liftIO $ map dropDocs compls @?=-          [complItem "head" (Just CiFunction) (Just "[a] -> a")]-        let [CompletionItem { _documentation = headDocs}] = compls-        checkDocText "head" headDocs [ "Defined in 'Prelude'"-#if MIN_GHC_API_VERSION(8,6,5)-                                     , "Extract the first element of a list"-#endif-                                     ]-    , testSessionWait "constructor" $ do-        let source = T.unlines ["module A where", "f = Tru"]-        docId <- createDoc "A.hs" "haskell" source-        compls <- getCompletions docId (Position 1 7)-        liftIO $ map dropDocs compls @?=-          [ complItem "True" (Just CiConstructor) (Just "Bool")-#if MIN_GHC_API_VERSION(8,6,0)-          , complItem "truncate" (Just CiFunction) (Just "(RealFrac a, Integral b) => a -> b")-#else-          , complItem "truncate" (Just CiFunction) (Just "RealFrac a => forall b. Integral b => a -> b")-#endif-          ]-    , testSessionWait "type" $ do-        let source = T.unlines ["{-# OPTIONS_GHC -Wall #-}", "module A () where", "f :: ()", "f = ()"]-        docId <- createDoc "A.hs" "haskell" source-        expectDiagnostics [ ("A.hs", [(DsWarning, (3,0), "not used")]) ]-        changeDoc docId [TextDocumentContentChangeEvent Nothing Nothing $ T.unlines ["{-# OPTIONS_GHC -Wall #-}", "module A () where", "f :: Bo", "f = True"]]-        compls <- getCompletions docId (Position 2 7)-        liftIO $ map dropDocs compls @?=-            [ complItem "Bounded" (Just CiClass) (Just "* -> Constraint")-            , complItem "Bool" (Just CiStruct) (Just "*") ]-        let [ CompletionItem { _documentation = boundedDocs},-              CompletionItem { _documentation = boolDocs } ] = compls-        checkDocText "Bounded" boundedDocs [ "Defined in 'Prelude'"-#if MIN_GHC_API_VERSION(8,6,5)-                                           , "name the upper and lower limits"-#endif-                                           ]-        checkDocText "Bool" boolDocs [ "Defined in 'Prelude'" ]-    , testSessionWait "qualified" $ do-        let source = T.unlines ["{-# OPTIONS_GHC -Wunused-binds #-}", "module A () where", "f = ()"]-        docId <- createDoc "A.hs" "haskell" source-        expectDiagnostics [ ("A.hs", [(DsWarning, (2, 0), "not used")]) ]-        changeDoc docId [TextDocumentContentChangeEvent Nothing Nothing $ T.unlines ["{-# OPTIONS_GHC -Wunused-binds #-}", "module A () where", "f = Prelude.hea"]]-        compls <- getCompletions docId (Position 2 15)-        liftIO $ map dropDocs compls @?=-          [complItem "head" (Just CiFunction) (Just "[a] -> a")]-        let [CompletionItem { _documentation = headDocs}] = compls-        checkDocText "head" headDocs [ "Defined in 'Prelude'"-#if MIN_GHC_API_VERSION(8,6,5)-                                     , "Extract the first element of a list"-#endif-                                     ]-    , testSessionWait "keyword" $ do-        let source = T.unlines ["module A where", "f = newty"]-        docId <- createDoc "A.hs" "haskell" source-        compls <- getCompletions docId (Position 1 9)-        liftIO $ compls @?= [keywordItem "newtype"]-    , testSessionWait "type context" $ do-        let source = T.unlines-                [ "{-# OPTIONS_GHC -Wunused-binds #-}"-                , "module A () where"-                , "f = f"-                ]-        docId <- createDoc "A.hs" "haskell" source-        expectDiagnostics [("A.hs", [(DsWarning, (2, 0), "not used")])]-        changeDoc docId-             [ TextDocumentContentChangeEvent Nothing Nothing $ T.unlines-                   [ "{-# OPTIONS_GHC -Wunused-binds #-}"-                   , "module A () where"-                   , "f = f"-                   , "g :: Intege"-                   ]-             ]-        -- At this point the module parses but does not typecheck.-        -- This should be sufficient to detect that we are in a-        -- type context and only show the completion to the type.-        compls <- getCompletions docId (Position 3 11)-        liftIO $ map dropDocs compls @?= [complItem "Integer"(Just CiStruct) (Just "*")]-    ]-  where-    dropDocs :: CompletionItem -> CompletionItem-    dropDocs ci = ci { _documentation = Nothing }-    complItem label kind ty = CompletionItem-      { _label = label-      , _kind = kind-      , _tags = List []-      , _detail = (":: " <>) <$> ty-      , _documentation = Nothing-      , _deprecated = Nothing-      , _preselect = Nothing-      , _sortText = Nothing-      , _filterText = Nothing-      , _insertText = Nothing-      , _insertTextFormat = Just PlainText-      , _textEdit = Nothing-      , _additionalTextEdits = Nothing-      , _commitCharacters = Nothing-      , _command = Nothing-      , _xdata = Nothing-      }-    keywordItem label = CompletionItem-      { _label = label-      , _kind = Just CiKeyword-      , _tags = List []-      , _detail = Nothing-      , _documentation = Nothing-      , _deprecated = Nothing-      , _preselect = Nothing-      , _sortText = Nothing-      , _filterText = Nothing-      , _insertText = Nothing-      , _insertTextFormat = Nothing-      , _textEdit = Nothing-      , _additionalTextEdits = Nothing-      , _commitCharacters = Nothing-      , _command = Nothing-      , _xdata = Nothing-      }-    getDocText (CompletionDocString s) = s-    getDocText (CompletionDocMarkup (MarkupContent _ s)) = s-    checkDocText thing Nothing _-      = liftIO $ assertFailure $ "docs for " ++ thing ++ " not found"-    checkDocText thing (Just doc) items-      = liftIO $ assertBool ("docs for " ++ thing ++ " contain the strings") $-          all (`T.isInfixOf` getDocText doc) items--outlineTests :: TestTree-outlineTests = testGroup-  "outline"-  [ testSessionWait "type class" $ do-    let source = T.unlines ["module A where", "class A a where a :: a -> Bool"]-    docId   <- createDoc "A.hs" "haskell" source-    symbols <- getDocumentSymbols docId-    liftIO $ symbols @?= Left-      [ moduleSymbol-          "A"-          (R 0 7 0 8)-          [ classSymbol "A a"-                        (R 1 0 1 30)-                        [docSymbol' "a" SkMethod (R 1 16 1 30) (R 1 16 1 17)]-          ]-      ]-  , testSessionWait "type class instance " $ do-    let source = T.unlines ["class A a where", "instance A () where"]-    docId   <- createDoc "A.hs" "haskell" source-    symbols <- getDocumentSymbols docId-    liftIO $ symbols @?= Left-      [ classSymbol "A a" (R 0 0 0 15) []-      , docSymbol "A ()" SkInterface (R 1 0 1 19)-      ]-  , testSessionWait "type family" $ do-    let source = T.unlines ["{-# language TypeFamilies #-}", "type family A"]-    docId   <- createDoc "A.hs" "haskell" source-    symbols <- getDocumentSymbols docId-    liftIO $ symbols @?= Left [docSymbolD "A" "type family" SkClass (R 1 0 1 13)]-  , testSessionWait "type family instance " $ do-    let source = T.unlines-          [ "{-# language TypeFamilies #-}"-          , "type family A a"-          , "type instance A () = ()"-          ]-    docId   <- createDoc "A.hs" "haskell" source-    symbols <- getDocumentSymbols docId-    liftIO $ symbols @?= Left-      [ docSymbolD "A a"   "type family" SkClass     (R 1 0 1 15)-      , docSymbol "A ()" SkInterface (R 2 0 2 23)-      ]-  , testSessionWait "data family" $ do-    let source = T.unlines ["{-# language TypeFamilies #-}", "data family A"]-    docId   <- createDoc "A.hs" "haskell" source-    symbols <- getDocumentSymbols docId-    liftIO $ symbols @?= Left [docSymbolD "A" "data family" SkClass (R 1 0 1 11)]-  , testSessionWait "data family instance " $ do-    let source = T.unlines-          [ "{-# language TypeFamilies #-}"-          , "data family A a"-          , "data instance A () = A ()"-          ]-    docId   <- createDoc "A.hs" "haskell" source-    symbols <- getDocumentSymbols docId-    liftIO $ symbols @?= Left-      [ docSymbolD "A a"   "data family" SkClass     (R 1 0 1 11)-      , docSymbol "A ()" SkInterface (R 2 0 2 25)-      ]-  , testSessionWait "constant" $ do-    let source = T.unlines ["a = ()"]-    docId   <- createDoc "A.hs" "haskell" source-    symbols <- getDocumentSymbols docId-    liftIO $ symbols @?= Left-      [docSymbol "a" SkFunction (R 0 0 0 6)]-  , testSessionWait "pattern" $ do-    let source = T.unlines ["Just foo = Just 21"]-    docId   <- createDoc "A.hs" "haskell" source-    symbols <- getDocumentSymbols docId-    liftIO $ symbols @?= Left-      [docSymbol "Just foo" SkFunction (R 0 0 0 18)]-  , testSessionWait "pattern with type signature" $ do-    let source = T.unlines ["{-# language ScopedTypeVariables #-}", "a :: () = ()"]-    docId   <- createDoc "A.hs" "haskell" source-    symbols <- getDocumentSymbols docId-    liftIO $ symbols @?= Left-      [docSymbol "a :: ()" SkFunction (R 1 0 1 12)]-  , testSessionWait "function" $ do-    let source = T.unlines ["a x = ()"]-    docId   <- createDoc "A.hs" "haskell" source-    symbols <- getDocumentSymbols docId-    liftIO $ symbols @?= Left [docSymbol "a" SkFunction (R 0 0 0 8)]-  , testSessionWait "type synonym" $ do-    let source = T.unlines ["type A = Bool"]-    docId   <- createDoc "A.hs" "haskell" source-    symbols <- getDocumentSymbols docId-    liftIO $ symbols @?= Left-      [docSymbol' "A" SkTypeParameter (R 0 0 0 13) (R 0 5 0 6)]-  , testSessionWait "datatype" $ do-    let source = T.unlines ["data A = C"]-    docId   <- createDoc "A.hs" "haskell" source-    symbols <- getDocumentSymbols docId-    liftIO $ symbols @?= Left-      [ docSymbolWithChildren "A"-                              SkStruct-                              (R 0 0 0 10)-                              [docSymbol "C" SkConstructor (R 0 9 0 10)]-      ]-  , testSessionWait "record fields" $ do-    let source = T.unlines ["data A = B {", "  x :: Int", "  , y :: Int}"]-    docId   <- createDoc "A.hs" "haskell" source-    symbols <- getDocumentSymbols docId-    liftIO $ symbols @=? Left-      [ docSymbolWithChildren "A" SkStruct (R 0 0 2 13)-          [ docSymbolWithChildren' "B" SkConstructor (R 0 9 2 13) (R 0 9 0 10)-            [ docSymbol "x" SkField (R 1 2 1 3)-            , docSymbol "y" SkField (R 2 4 2 5)-            ]-          ]-      ]-  , testSessionWait "import" $ do-    let source = T.unlines ["import Data.Maybe"]-    docId   <- createDoc "A.hs" "haskell" source-    symbols <- getDocumentSymbols docId-    liftIO $ symbols @?= Left-      [docSymbolWithChildren "imports"-                             SkModule-                             (R 0 0 0 17)-                             [ docSymbol "import Data.Maybe" SkModule (R 0 0 0 17)-                             ]-      ]-  , testSessionWait "multiple import" $ do-    let source = T.unlines ["", "import Data.Maybe", "", "import Control.Exception", ""]-    docId   <- createDoc "A.hs" "haskell" source-    symbols <- getDocumentSymbols docId-    liftIO $ symbols @?= Left-      [docSymbolWithChildren "imports"-                             SkModule-                             (R 1 0 3 24)-                             [ docSymbol "import Data.Maybe" SkModule (R 1 0 1 17)-                             , docSymbol "import Control.Exception" SkModule (R 3 0 3 24)-                             ]-      ]-  , testSessionWait "foreign import" $ do-    let source = T.unlines-          [ "{-# language ForeignFunctionInterface #-}"-          , "foreign import ccall \"a\" a :: Int"-          ]-    docId   <- createDoc "A.hs" "haskell" source-    symbols <- getDocumentSymbols docId-    liftIO $ symbols @?= Left [docSymbolD "a" "import" SkObject (R 1 0 1 33)]-  , testSessionWait "foreign export" $ do-    let source = T.unlines-          [ "{-# language ForeignFunctionInterface #-}"-          , "foreign export ccall odd :: Int -> Bool"-          ]-    docId   <- createDoc "A.hs" "haskell" source-    symbols <- getDocumentSymbols docId-    liftIO $ symbols @?= Left [docSymbolD "odd" "export" SkObject (R 1 0 1 39)]-  ]- where-  docSymbol name kind loc =-    DocumentSymbol name Nothing kind Nothing loc loc Nothing-  docSymbol' name kind loc selectionLoc =-    DocumentSymbol name Nothing kind Nothing loc selectionLoc Nothing-  docSymbolD name detail kind loc =-    DocumentSymbol name (Just detail) kind Nothing loc loc Nothing-  docSymbolWithChildren name kind loc cc =-    DocumentSymbol name Nothing kind Nothing loc loc (Just $ List cc)-  docSymbolWithChildren' name kind loc selectionLoc cc =-    DocumentSymbol name Nothing kind Nothing loc selectionLoc (Just $ List cc)-  moduleSymbol name loc cc = DocumentSymbol name-                                            Nothing-                                            SkFile-                                            Nothing-                                            (R 0 0 maxBound 0)-                                            loc-                                            (Just $ List cc)-  classSymbol name loc cc = DocumentSymbol name-                                           (Just "class")-                                           SkClass-                                           Nothing-                                           loc-                                           loc-                                           (Just $ List cc)--pattern R :: Int -> Int -> Int -> Int -> Range-pattern R x y x' y' = Range (Position x y) (Position x' y')--xfail :: TestTree -> String -> TestTree-xfail = flip expectFailBecause--xfail8101 :: TestTree -> String -> TestTree-#if MIN_GHC_API_VERSION(8,10,0)-xfail8101 = flip expectFailBecause-#else-xfail8101 t _ = t-#endif--data Expect-  = ExpectRange Range -- Both gotoDef and hover should report this range-  | ExpectLocation Location---  | ExpectDefRange Range -- Only gotoDef should report this range-  | ExpectHoverRange Range -- Only hover should report this range-  | ExpectHoverText [T.Text] -- the hover message must contain these snippets-  | ExpectExternFail -- definition lookup in other file expected to fail-  | ExpectNoDefinitions-  | ExpectNoHover---  | ExpectExtern -- TODO: as above, but expected to succeed: need some more info in here, once we have some working examples-  deriving Eq--mkR :: Int -> Int -> Int -> Int -> Expect-mkR startLine startColumn endLine endColumn = ExpectRange $ mkRange startLine startColumn endLine endColumn--mkL :: Uri -> Int -> Int -> Int -> Int -> Expect-mkL uri startLine startColumn endLine endColumn = ExpectLocation $ Location uri $ mkRange startLine startColumn endLine endColumn--haddockTests :: TestTree-haddockTests-  = testGroup "haddock"-      [ testCase "Num" $ checkHaddock-          (unlines-             [ "However, '(+)' and '(*)' are"-             , "customarily expected to define a ring and have the following properties:"-             , ""-             , "[__Associativity of (+)__]: @(x + y) + z@ = @x + (y + z)@"-             , "[__Commutativity of (+)__]: @x + y@ = @y + x@"-             , "[__@fromInteger 0@ is the additive identity__]: @x + fromInteger 0@ = @x@"-             ]-          )-          (unlines-             [ ""-             , ""-             , "However,  `(+)`  and  `(*)`  are"-             , "customarily expected to define a ring and have the following properties: "-             , "+ ****Associativity of (+)****: `(x + y) + z`  =  `x + (y + z)`"-             , "+ ****Commutativity of (+)****: `x + y`  =  `y + x`"-             , "+ ****`fromInteger 0`  is the additive identity****: `x + fromInteger 0`  =  `x`"-             ]-          )-      , testCase "unsafePerformIO" $ checkHaddock-          (unlines-             [ "may require"-             , "different precautions:"-             , ""-             , "  * Use @{\\-\\# NOINLINE foo \\#-\\}@ as a pragma on any function @foo@"-             , "        that calls 'unsafePerformIO'.  If the call is inlined,"-             , "        the I\\/O may be performed more than once."-             , ""-             , "  * Use the compiler flag @-fno-cse@ to prevent common sub-expression"-             , "        elimination being performed on the module."-             , ""-             ]-          )-          (unlines-             [ ""-             , ""-             , "may require"-             , "different precautions: "-             , "+ Use  `{-# NOINLINE foo #-}`  as a pragma on any function  `foo` "-             , "  that calls  `unsafePerformIO` .  If the call is inlined,"-             , "  the I/O may be performed more than once."-             , ""-             , "+ Use the compiler flag  `-fno-cse`  to prevent common sub-expression"-             , "  elimination being performed on the module."-             , ""-             ]-          )-      ]-  where-    checkHaddock s txt = spanDocToMarkdownForTest s @?= txt--cradleTests :: TestTree-cradleTests = testGroup "cradle"-    [testGroup "dependencies" [sessionDepsArePickedUp]-    ,testGroup "loading" [loadCradleOnlyonce]-    ,testGroup "multi"   [simpleMultiTest, simpleMultiTest2]-    ]--loadCradleOnlyonce :: TestTree-loadCradleOnlyonce = testGroup "load cradle only once"-    [ testSession' "implicit" implicit-    , testSession' "direct"   direct-    ]-    where-        direct dir = do-            liftIO $ writeFileUTF8 (dir </> "hie.yaml")-                "cradle: {direct: {arguments: []}}"-            test dir-        implicit dir = test dir-        test _dir = do-            doc <- createDoc "B.hs" "haskell" "module B where\nimport Data.Foo"-            msgs <- someTill (skipManyTill anyMessage cradleLoadedMessage) (skipManyTill anyMessage (message @PublishDiagnosticsNotification))-            liftIO $ length msgs @?= 1-            changeDoc doc [TextDocumentContentChangeEvent Nothing Nothing "module B where\nimport Data.Maybe"]-            msgs <- manyTill (skipManyTill anyMessage cradleLoadedMessage) (skipManyTill anyMessage (message @PublishDiagnosticsNotification))-            liftIO $ length msgs @?= 0-            _ <- createDoc "A.hs" "haskell" "module A where\nimport LoadCradleBar"-            msgs <- manyTill (skipManyTill anyMessage cradleLoadedMessage) (skipManyTill anyMessage (message @PublishDiagnosticsNotification))-            liftIO $ length msgs @?= 0---dependentFileTest :: TestTree-dependentFileTest = testGroup "addDependentFile"-    [testGroup "file-changed" [testSession' "test" test]-    ]-    where-      test dir = do-        -- If the file contains B then no type error-        -- otherwise type error-        liftIO $ writeFile (dir </> "dep-file.txt") "A"-        let fooContent = T.unlines-              [ "{-# LANGUAGE TemplateHaskell #-}"-              , "module Foo where"-              , "import Language.Haskell.TH.Syntax"-              , "foo :: Int"-              , "foo = 1 + $(do"-              , "               qAddDependentFile \"dep-file.txt\""-              , "               f <- qRunIO (readFile \"dep-file.txt\")"-              , "               if f == \"B\" then [| 1 |] else lift f)"-              ]-        let bazContent = T.unlines ["module Baz where", "import Foo"]-        _ <-createDoc "Foo.hs" "haskell" fooContent-        doc <- createDoc "Baz.hs" "haskell" bazContent-        expectDiagnostics-          [("Foo.hs", [(DsError, (4, 6), "Couldn't match expected type")])]-        -- Now modify the dependent file-        liftIO $ writeFile (dir </> "dep-file.txt") "B"-        let change = TextDocumentContentChangeEvent-              { _range = Just (Range (Position 2 0) (Position 2 6))-              , _rangeLength = Nothing-              , _text = "f = ()"-              }-        -- Modifying Baz will now trigger Foo to be rebuilt as well-        changeDoc doc [change]-        expectDiagnostics [("Foo.hs", [])]---cradleLoadedMessage :: Session FromServerMessage-cradleLoadedMessage = satisfy $ \case-        NotCustomServer (NotificationMessage _ (CustomServerMethod m) _) -> m == cradleLoadedMethod-        _ -> False--cradleLoadedMethod :: T.Text-cradleLoadedMethod = "ghcide/cradle/loaded"---- Stack sets this which trips up cabal in the multi-component tests.--- However, our plugin tests rely on those env vars so we unset it locally.-withoutStackEnv :: IO a -> IO a-withoutStackEnv s =-  bracket-    (mapM getEnv vars >>= \prevState -> mapM_ unsetEnv vars >> pure prevState)-    (\prevState -> mapM_ (\(var, value) -> restore var value) (zip vars prevState))-    (const s)-  where vars =-          [ "GHC_PACKAGE_PATH"-          , "GHC_ENVIRONMENT"-          , "HASKELL_DIST_DIR"-          , "HASKELL_PACKAGE_SANDBOX"-          , "HASKELL_PACKAGE_SANDBOXES"-          ]-        restore var Nothing = unsetEnv var-        restore var (Just val) = setEnv var val True--simpleMultiTest :: TestTree-simpleMultiTest = testCase "simple-multi-test" $ withoutStackEnv $ runWithExtraFiles "multi" $ \dir -> do-    let aPath = dir </> "a/A.hs"-        bPath = dir </> "b/B.hs"-    aSource <- liftIO $ readFileUtf8 aPath-    (TextDocumentIdentifier adoc) <- createDoc aPath "haskell" aSource-    expectNoMoreDiagnostics 0.5-    bSource <- liftIO $ readFileUtf8 bPath-    bdoc <- createDoc bPath "haskell" bSource-    expectNoMoreDiagnostics 0.5-    locs <- getDefinitions bdoc (Position 2 7)-    let fooL = mkL adoc 2 0 2 3-    checkDefs locs (pure [fooL])-    expectNoMoreDiagnostics 0.5---- Like simpleMultiTest but open the files in the other order-simpleMultiTest2 :: TestTree-simpleMultiTest2 = testCase "simple-multi-test2" $ withoutStackEnv $ runWithExtraFiles "multi" $ \dir -> do-    let aPath = dir </> "a/A.hs"-        bPath = dir </> "b/B.hs"-    bSource <- liftIO $ readFileUtf8 bPath-    bdoc <- createDoc bPath "haskell" bSource-    expectNoMoreDiagnostics 5-    aSource <- liftIO $ readFileUtf8 aPath-    (TextDocumentIdentifier adoc) <- createDoc aPath "haskell" aSource-    -- Need to have some delay here or the test fails-    expectNoMoreDiagnostics 5-    locs <- getDefinitions bdoc (Position 2 7)-    let fooL = mkL adoc 2 0 2 3-    checkDefs locs (pure [fooL])-    expectNoMoreDiagnostics 0.5--sessionDepsArePickedUp :: TestTree-sessionDepsArePickedUp = testSession'-  "session-deps-are-picked-up"-  $ \dir -> do-    liftIO $-      writeFileUTF8-        (dir </> "hie.yaml")-        "cradle: {direct: {arguments: []}}"-    -- Open without OverloadedStrings and expect an error.-    doc <- createDoc "Foo.hs" "haskell" fooContent-    expectDiagnostics-      [("Foo.hs", [(DsError, (3, 6), "Couldn't match expected type")])]-    -- Update hie.yaml to enable OverloadedStrings.-    liftIO $-      writeFileUTF8-        (dir </> "hie.yaml")-        "cradle: {direct: {arguments: [-XOverloadedStrings]}}"-    -- Send change event.-    let change =-          TextDocumentContentChangeEvent-            { _range = Just (Range (Position 4 0) (Position 4 0)),-              _rangeLength = Nothing,-              _text = "\n"-            }-    changeDoc doc [change]-    -- Now no errors.-    expectDiagnostics [("Foo.hs", [])]-  where-    fooContent =-      T.unlines-        [ "module Foo where",-          "import Data.Text",-          "foo :: Text",-          "foo = \"hello\""-        ]---------------------------------------------------------------------------- Utils---testSession :: String -> Session () -> TestTree-testSession name = testCase name . run--testSessionWithExtraFiles :: FilePath -> String -> (FilePath -> Session ()) -> TestTree-testSessionWithExtraFiles prefix name = testCase name . runWithExtraFiles prefix--testSession' :: String -> (FilePath -> Session ()) -> TestTree-testSession' name = testCase name . run'--testSessionWait :: String -> Session () -> TestTree-testSessionWait name = testSession name .-      -- Check that any diagnostics produced were already consumed by the test case.-      ---      -- If in future we add test cases where we don't care about checking the diagnostics,-      -- this could move elsewhere.-      ---      -- Experimentally, 0.5s seems to be long enough to wait for any final diagnostics to appear.-      ( >> expectNoMoreDiagnostics 0.5)--pickActionWithTitle :: T.Text -> [CAResult] -> IO CodeAction-pickActionWithTitle title actions = do-  assertBool ("Found no matching actions: " <> show titles) (not $ null matches)-  return $ head matches-  where-    titles =-        [ actionTitle-        | CACodeAction CodeAction { _title = actionTitle } <- actions-        ]-    matches =-        [ action-        | CACodeAction action@CodeAction { _title = actionTitle } <- actions-        , title == actionTitle-        ]--mkRange :: Int -> Int -> Int -> Int -> Range-mkRange a b c d = Range (Position a b) (Position c d)--run :: Session a -> IO a-run s = withTempDir $ \dir -> runInDir dir s--runWithExtraFiles :: FilePath -> (FilePath -> Session a) -> IO a-runWithExtraFiles prefix s = withTempDir $ \dir -> do-  copyTestDataFiles dir prefix-  runInDir dir (s dir)--copyTestDataFiles :: FilePath -> FilePath -> IO ()-copyTestDataFiles dir prefix = do-  -- Copy all the test data files to the temporary workspace-  testDataFiles <- getDirectoryFilesIO ("test/data" </> prefix) ["//*"]-  for_ testDataFiles $ \f -> do-    createDirectoryIfMissing True $ dir </> takeDirectory f-    copyFile ("test/data" </> prefix </> f) (dir </> f)--run' :: (FilePath -> Session a) -> IO a-run' s = withTempDir $ \dir -> runInDir dir (s dir)--runInDir :: FilePath -> Session a -> IO a-runInDir dir s = do-  ghcideExe <- locateGhcideExecutable--  -- Temporarily hack around https://github.com/mpickering/hie-bios/pull/56-  -- since the package import test creates "Data/List.hs", which otherwise has no physical home-  createDirectoryIfMissing True $ dir ++ "/Data"---  let cmd = unwords [ghcideExe, "--lsp", "--test", "--cwd", dir]-  -- HIE calls getXgdDirectory which assumes that HOME is set.-  -- Only sets HOME if it wasn't already set.-  setEnv "HOME" "/homeless-shelter" False-  let lspTestCaps = fullCaps { _window = Just $ WindowClientCapabilities $ Just True }-  runSessionWithConfig conf cmd lspTestCaps dir s-  where-    conf = defaultConfig-      -- If you uncomment this you can see all logging-      -- which can be quite useful for debugging.-      -- { logStdErr = True, logColor = False }-      -- If you really want to, you can also see all messages-      -- { logMessages = True, logColor = False }--openTestDataDoc :: FilePath -> Session TextDocumentIdentifier-openTestDataDoc path = do-  source <- liftIO $ readFileUtf8 $ "test/data" </> path-  createDoc path "haskell" source--findCodeActions :: TextDocumentIdentifier -> Range -> [T.Text] -> Session [CodeAction]-findCodeActions doc range expectedTitles = do-  actions <- getCodeActions doc range-  let matches = sequence-        [ listToMaybe-          [ action-          | CACodeAction action@CodeAction { _title = actionTitle } <- actions-          , actionTitle == expectedTitle ]-        | expectedTitle <- expectedTitles]-  let msg = show-            [ actionTitle-            | CACodeAction CodeAction { _title = actionTitle } <- actions-            ]-            ++ " is not a superset of "-            ++ show expectedTitles-  liftIO $ case matches of-    Nothing -> assertFailure msg-    Just _ -> pure ()-  return (fromJust matches)--findCodeAction :: TextDocumentIdentifier -> Range -> T.Text -> Session CodeAction-findCodeAction doc range t = head <$> findCodeActions doc range [t]--unitTests :: TestTree-unitTests = do-  testGroup "Unit"-     [ testCase "empty file path does NOT work with the empty String literal" $-         uriToFilePath' (fromNormalizedUri $ filePathToUri' "") @?= Just "."-     , testCase "empty file path works using toNormalizedFilePath'" $-         uriToFilePath' (fromNormalizedUri $ filePathToUri' (toNormalizedFilePath' "")) @?= Just ""-     , testCase "empty path URI" $ do-         Just URI{..} <- pure $ parseURI (T.unpack $ getUri $ fromNormalizedUri emptyPathUri)-         uriScheme @?= "file:"-         uriPath @?= ""-     , testCase "from empty path URI" $ do-         let uri = Uri "file://"-         uriToFilePath' uri @?= Just ""-     ]--positionMappingTests :: TestTree-positionMappingTests =-    testGroup "position mapping"-        [ testGroup "toCurrent"-              [ testCase "before" $-                toCurrent-                    (Range (Position 0 1) (Position 0 3))-                    "ab"-                    (Position 0 0) @?= Just (Position 0 0)-              , testCase "after, same line, same length" $-                toCurrent-                    (Range (Position 0 1) (Position 0 3))-                    "ab"-                    (Position 0 3) @?= Just (Position 0 3)-              , testCase "after, same line, increased length" $-                toCurrent-                    (Range (Position 0 1) (Position 0 3))-                    "abc"-                    (Position 0 3) @?= Just (Position 0 4)-              , testCase "after, same line, decreased length" $-                toCurrent-                    (Range (Position 0 1) (Position 0 3))-                    "a"-                    (Position 0 3) @?= Just (Position 0 2)-              , testCase "after, next line, no newline" $-                toCurrent-                    (Range (Position 0 1) (Position 0 3))-                    "abc"-                    (Position 1 3) @?= Just (Position 1 3)-              , testCase "after, next line, newline" $-                toCurrent-                    (Range (Position 0 1) (Position 0 3))-                    "abc\ndef"-                    (Position 1 0) @?= Just (Position 2 0)-              , testCase "after, same line, newline" $-                toCurrent-                    (Range (Position 0 1) (Position 0 3))-                    "abc\nd"-                    (Position 0 4) @?= Just (Position 1 2)-              , testCase "after, same line, newline + newline at end" $-                toCurrent-                    (Range (Position 0 1) (Position 0 3))-                    "abc\nd\n"-                    (Position 0 4) @?= Just (Position 2 1)-              , testCase "after, same line, newline + newline at end" $-                toCurrent-                    (Range (Position 0 1) (Position 0 1))-                    "abc"-                    (Position 0 1) @?= Just (Position 0 4)-              ]-        , testGroup "fromCurrent"-              [ testCase "before" $-                fromCurrent-                    (Range (Position 0 1) (Position 0 3))-                    "ab"-                    (Position 0 0) @?= Just (Position 0 0)-              , testCase "after, same line, same length" $-                fromCurrent-                    (Range (Position 0 1) (Position 0 3))-                    "ab"-                    (Position 0 3) @?= Just (Position 0 3)-              , testCase "after, same line, increased length" $-                fromCurrent-                    (Range (Position 0 1) (Position 0 3))-                    "abc"-                    (Position 0 4) @?= Just (Position 0 3)-              , testCase "after, same line, decreased length" $-                fromCurrent-                    (Range (Position 0 1) (Position 0 3))-                    "a"-                    (Position 0 2) @?= Just (Position 0 3)-              , testCase "after, next line, no newline" $-                fromCurrent-                    (Range (Position 0 1) (Position 0 3))-                    "abc"-                    (Position 1 3) @?= Just (Position 1 3)-              , testCase "after, next line, newline" $-                fromCurrent-                    (Range (Position 0 1) (Position 0 3))-                    "abc\ndef"-                    (Position 2 0) @?= Just (Position 1 0)-              , testCase "after, same line, newline" $-                fromCurrent-                    (Range (Position 0 1) (Position 0 3))-                    "abc\nd"-                    (Position 1 2) @?= Just (Position 0 4)-              , testCase "after, same line, newline + newline at end" $-                fromCurrent-                    (Range (Position 0 1) (Position 0 3))-                    "abc\nd\n"-                    (Position 2 1) @?= Just (Position 0 4)-              , testCase "after, same line, newline + newline at end" $-                fromCurrent-                    (Range (Position 0 1) (Position 0 1))-                    "abc"-                    (Position 0 4) @?= Just (Position 0 1)-              ]-        , adjustOption (\(QuickCheckTests i) -> QuickCheckTests (max 1000 i)) $ testGroup "properties"-              [ testProperty "fromCurrent r t <=< toCurrent r t" $ do-                -- Note that it is important to use suchThatMap on all values at once-                -- instead of only using it on the position. Otherwise you can get-                -- into situations where there is no position that can be mapped back-                -- for the edit which will result in QuickCheck looping forever.-                let gen = do-                        rope <- genRope-                        range <- genRange rope-                        PrintableText replacement <- arbitrary-                        oldPos <- genPosition rope-                        pure (range, replacement, oldPos)-                forAll-                    (suchThatMap gen-                        (\(range, replacement, oldPos) -> (range, replacement, oldPos,) <$> toCurrent range replacement oldPos)) $-                    \(range, replacement, oldPos, newPos) ->-                    fromCurrent range replacement newPos === Just oldPos-              , testProperty "toCurrent r t <=< fromCurrent r t" $ do-                let gen = do-                        rope <- genRope-                        range <- genRange rope-                        PrintableText replacement <- arbitrary-                        let newRope = applyChange rope (TextDocumentContentChangeEvent (Just range) Nothing replacement)-                        newPos <- genPosition newRope-                        pure (range, replacement, newPos)-                forAll-                    (suchThatMap gen-                        (\(range, replacement, newPos) -> (range, replacement, newPos,) <$> fromCurrent range replacement newPos)) $-                    \(range, replacement, newPos, oldPos) ->-                    toCurrent range replacement oldPos === Just newPos-              ]-        ]--newtype PrintableText = PrintableText { getPrintableText :: T.Text }-    deriving Show--instance Arbitrary PrintableText where-    arbitrary = PrintableText . T.pack . getPrintableString <$> arbitrary---genRope :: Gen Rope-genRope = Rope.fromText . getPrintableText <$> arbitrary--genPosition :: Rope -> Gen Position-genPosition r = do-    row <- choose (0, max 0 $ rows - 1)-    let columns = Rope.columns (nthLine row r)-    column <- choose (0, max 0 $ columns - 1)-    pure $ Position row column-    where rows = Rope.rows r--genRange :: Rope -> Gen Range-genRange r = do-    startPos@(Position startLine startColumn) <- genPosition r-    let maxLineDiff = max 0 $ rows - 1 - startLine-    endLine <- choose (startLine, startLine + maxLineDiff)-    let columns = Rope.columns (nthLine endLine r)-    endColumn <--        if startLine == endLine-            then choose (startColumn, columns)-            else choose (0, max 0 $ columns - 1)-    pure $ Range startPos (Position endLine endColumn)-    where rows = Rope.rows r---- | Get the ith line of a rope, starting from 0. Trailing newline not included.-nthLine :: Int -> Rope -> Rope-nthLine i r-    | i < 0 = error $ "Negative line number: " <> show i-    | i == 0 && Rope.rows r == 0 = r-    | i >= Rope.rows r = error $ "Row number out of bounds: " <> show i <> "/" <> show (Rope.rows r)-    | otherwise = Rope.takeWhile (/= '\n') $ fst $ Rope.splitAtLine 1 $ snd $ Rope.splitAtLine (i - 1) r--getWatchedFilesSubscriptionsUntil :: forall end . (FromJSON end, Typeable end) => Session [Maybe Value]-getWatchedFilesSubscriptionsUntil = do-      msgs <- manyTill (Just <$> message @RegisterCapabilityRequest <|> Nothing <$ anyMessage) (message @end)-      return-            [ args-            | Just RequestMessage{_params = RegistrationParams (List regs)} <- msgs-            , Registration _id WorkspaceDidChangeWatchedFiles args <- regs-            ]+{-# LANGUAGE ImplicitParams  #-}+{-# LANGUAGE PatternSynonyms #-}+{-# LANGUAGE CPP #-}+#include "ghc-api-version.h"++module Main (main) where++import Control.Applicative.Combinators+import Control.Exception (bracket, catch)+import qualified Control.Lens as Lens+import Control.Monad+import Control.Monad.IO.Class (liftIO)+import Data.Aeson (FromJSON, Value)+import qualified Data.Binary as Binary+import Data.Foldable+import Data.List.Extra+import Data.Maybe+import Data.Rope.UTF16 (Rope)+import qualified Data.Rope.UTF16 as Rope+import Development.IDE.Core.PositionMapping (fromCurrent, toCurrent)+import Development.IDE.Core.Shake (Q(..))+import Development.IDE.GHC.Util+import qualified Data.Text as T+import Data.Typeable+import Development.IDE.Spans.Common+import Development.IDE.Test+import Development.IDE.Test.Runfiles+import Development.IDE.Types.Location+import Development.Shake (getDirectoryFilesIO)+import qualified Experiments as Bench+import Language.Haskell.LSP.Test+import Language.Haskell.LSP.Messages+import Language.Haskell.LSP.Types+import Language.Haskell.LSP.Types.Capabilities+import qualified Language.Haskell.LSP.Types.Lens as Lsp (diagnostics, params, message)+import Language.Haskell.LSP.VFS (applyChange)+import Network.URI+import System.Environment.Blank (getEnv, setEnv, unsetEnv)+import System.FilePath+import System.IO.Extra hiding (withTempDir)+import qualified System.IO.Extra+import System.Directory+import System.Exit (ExitCode(ExitSuccess))+import System.Process.Extra (readCreateProcessWithExitCode, CreateProcess(cwd), proc)+import Test.QuickCheck+import Test.QuickCheck.Instances ()+import Test.Tasty+import Test.Tasty.ExpectedFailure+import Test.Tasty.Ingredients.Rerun+import Test.Tasty.HUnit+import Test.Tasty.QuickCheck++main :: IO ()+main = do+  -- We mess with env vars so run single-threaded.+  setEnv "TASTY_NUM_THREADS" "1" True+  defaultMainWithRerun $ testGroup "ghcide"+    [ testSession "open close" $ do+        doc <- createDoc "Testing.hs" "haskell" ""+        void (skipManyTill anyMessage message :: Session WorkDoneProgressCreateRequest)+        void (skipManyTill anyMessage message :: Session WorkDoneProgressBeginNotification)+        closeDoc doc+        void (skipManyTill anyMessage message :: Session WorkDoneProgressEndNotification)+    , initializeResponseTests+    , completionTests+    , cppTests+    , diagnosticTests+    , codeActionTests+    , codeLensesTests+    , outlineTests+    , findDefinitionAndHoverTests+    , pluginTests+    , preprocessorTests+    , thTests+    , safeTests+    , unitTests+    , haddockTests+    , positionMappingTests+    , watchedFilesTests+    , cradleTests+    , dependentFileTest+    , nonLspCommandLine+    , benchmarkTests+    , ifaceTests+    ]++initializeResponseTests :: TestTree+initializeResponseTests = withResource acquire release tests where++  -- these tests document and monitor the evolution of the+  -- capabilities announced by the server in the initialize+  -- response. Currently the server advertises almost no capabilities+  -- at all, in some cases failing to announce capabilities that it+  -- actually does provide! Hopefully this will change ...+  tests :: IO InitializeResponse -> TestTree+  tests getInitializeResponse =+    testGroup "initialize response capabilities"+    [ chk "   text doc sync"             _textDocumentSync  tds+    , chk "   hover"                         _hoverProvider (Just True)+    , chk "   completion"               _completionProvider (Just $ CompletionOptions (Just False) (Just ["."]) Nothing)+    , chk "NO signature help"        _signatureHelpProvider  Nothing+    , chk "   goto definition"          _definitionProvider (Just True)+    , chk "   goto type definition" _typeDefinitionProvider (Just $ GotoOptionsStatic True)+    -- BUG in lsp-test, this test fails, just change the accepted response+    -- for now+    , chk "NO goto implementation"  _implementationProvider (Just $ GotoOptionsStatic True)+    , chk "NO find references"          _referencesProvider  Nothing+    , chk "NO doc highlight"     _documentHighlightProvider  Nothing+    , chk "   doc symbol"           _documentSymbolProvider  (Just True)+    , chk "NO workspace symbol"    _workspaceSymbolProvider  Nothing+    , chk "   code action"             _codeActionProvider $ Just $ CodeActionOptionsStatic True+    , chk "   code lens"                 _codeLensProvider $ Just $ CodeLensOptions Nothing+    , chk "NO doc formatting"   _documentFormattingProvider  Nothing+    , chk "NO doc range formatting"+                           _documentRangeFormattingProvider  Nothing+    , chk "NO doc formatting on typing"+                          _documentOnTypeFormattingProvider  Nothing+    , chk "NO renaming"                     _renameProvider (Just $ RenameOptionsStatic False)+    , chk "NO doc link"               _documentLinkProvider  Nothing+    , chk "NO color"                         _colorProvider (Just $ ColorOptionsStatic False)+    , chk "NO folding range"          _foldingRangeProvider (Just $ FoldingRangeOptionsStatic False)+    , che "   execute command"      _executeCommandProvider (Just $ ExecuteCommandOptions $ List ["typesignature.add"])+    , chk "   workspace"                         _workspace (Just $ WorkspaceOptions (Just WorkspaceFolderOptions{_supported = Just True, _changeNotifications = Just ( WorkspaceFolderChangeNotificationsBool True )}))+    , chk "NO experimental"                   _experimental  Nothing+    ] where++      tds = Just (TDSOptions (TextDocumentSyncOptions+                              { _openClose = Just True+                              , _change    = Just TdSyncIncremental+                              , _willSave  = Nothing+                              , _willSaveWaitUntil = Nothing+                              , _save = Just (SaveOptions {_includeText = Nothing})}))++      chk :: (Eq a, Show a) => TestName -> (InitializeResponseCapabilitiesInner -> a) -> a -> TestTree+      chk title getActual expected =+        testCase title $ getInitializeResponse >>= \ir -> expected @=? (getActual . innerCaps) ir++      che :: TestName -> (InitializeResponseCapabilitiesInner -> Maybe ExecuteCommandOptions) -> Maybe ExecuteCommandOptions -> TestTree+      che title getActual _expected = testCase title doTest+        where+            doTest = do+                ir <- getInitializeResponse+                let Just ExecuteCommandOptions {_commands = List [command]} = getActual $ innerCaps ir+                True @=? T.isSuffixOf "typesignature.add" command+++  innerCaps :: InitializeResponse -> InitializeResponseCapabilitiesInner+  innerCaps (ResponseMessage _ _ (Right (InitializeResponseCapabilities c))) = c+  innerCaps  _ = error "this test only expects inner capabilities"++  acquire :: IO InitializeResponse+  acquire = run initializeResponse++  release :: InitializeResponse -> IO ()+  release = const $ pure ()+++diagnosticTests :: TestTree+diagnosticTests = testGroup "diagnostics"+  [ testSessionWait "fix syntax error" $ do+      let content = T.unlines [ "module Testing wher" ]+      doc <- createDoc "Testing.hs" "haskell" content+      expectDiagnostics [("Testing.hs", [(DsError, (0, 15), "parse error")])]+      let change = TextDocumentContentChangeEvent+            { _range = Just (Range (Position 0 15) (Position 0 19))+            , _rangeLength = Nothing+            , _text = "where"+            }+      changeDoc doc [change]+      expectDiagnostics [("Testing.hs", [])]+  , testSessionWait "introduce syntax error" $ do+      let content = T.unlines [ "module Testing where" ]+      doc <- createDoc "Testing.hs" "haskell" content+      void $ skipManyTill anyMessage (message :: Session WorkDoneProgressCreateRequest)+      void $ skipManyTill anyMessage (message :: Session WorkDoneProgressBeginNotification)+      let change = TextDocumentContentChangeEvent+            { _range = Just (Range (Position 0 15) (Position 0 18))+            , _rangeLength = Nothing+            , _text = "wher"+            }+      changeDoc doc [change]+      expectDiagnostics [("Testing.hs", [(DsError, (0, 15), "parse error")])]+  , testSessionWait "variable not in scope" $ do+      let content = T.unlines+            [ "module Testing where"+            , "foo :: Int -> Int -> Int"+            , "foo a b = a + ab"+            , "bar :: Int -> Int -> Int"+            , "bar a b = cd + b"+            ]+      _ <- createDoc "Testing.hs" "haskell" content+      expectDiagnostics+        [ ( "Testing.hs"+          , [ (DsError, (2, 14), "Variable not in scope: ab")+            , (DsError, (4, 10), "Variable not in scope: cd")+            ]+          )+        ]+  , testSessionWait "type error" $ do+      let content = T.unlines+            [ "module Testing where"+            , "foo :: Int -> String -> Int"+            , "foo a b = a + b"+            ]+      _ <- createDoc "Testing.hs" "haskell" content+      expectDiagnostics+        [ ( "Testing.hs"+          , [(DsError, (2, 14), "Couldn't match type '[Char]' with 'Int'")]+          )+        ]+  , testSessionWait "typed hole" $ do+      let content = T.unlines+            [ "module Testing where"+            , "foo :: Int -> String"+            , "foo a = _ a"+            ]+      _ <- createDoc "Testing.hs" "haskell" content+      expectDiagnostics+        [ ( "Testing.hs"+          , [(DsError, (2, 8), "Found hole: _ :: Int -> String")]+          )+        ]++  , testGroup "deferral" $+    let sourceA a = T.unlines+          [ "module A where"+          , "a :: Int"+          , "a = " <> a]+        sourceB = T.unlines+          [ "module B where"+          , "import A"+          , "b :: Float"+          , "b = True"]+        bMessage = "Couldn't match expected type 'Float' with actual type 'Bool'"+        expectedDs aMessage =+          [ ("A.hs", [(DsError, (2,4), aMessage)])+          , ("B.hs", [(DsError, (3,4), bMessage)])]+        deferralTest title binding msg = testSessionWait title $ do+          _ <- createDoc "A.hs" "haskell" $ sourceA binding+          _ <- createDoc "B.hs" "haskell"   sourceB+          expectDiagnostics $ expectedDs msg+    in+    [ deferralTest "type error"          "True"    "Couldn't match expected type"+    , deferralTest "typed hole"          "_"       "Found hole"+    , deferralTest "out of scope var"    "unbound" "Variable not in scope"+    ]++  , testSessionWait "remove required module" $ do+      let contentA = T.unlines [ "module ModuleA where" ]+      docA <- createDoc "ModuleA.hs" "haskell" contentA+      let contentB = T.unlines+            [ "module ModuleB where"+            , "import ModuleA"+            ]+      _ <- createDoc "ModuleB.hs" "haskell" contentB+      let change = TextDocumentContentChangeEvent+            { _range = Just (Range (Position 0 0) (Position 0 20))+            , _rangeLength = Nothing+            , _text = ""+            }+      changeDoc docA [change]+      expectDiagnostics [("ModuleB.hs", [(DsError, (1, 0), "Could not find module")])]+  , testSessionWait "add missing module" $ do+      let contentB = T.unlines+            [ "module ModuleB where"+            , "import ModuleA"+            ]+      _ <- createDoc "ModuleB.hs" "haskell" contentB+      expectDiagnostics [("ModuleB.hs", [(DsError, (1, 7), "Could not find module")])]+      let contentA = T.unlines [ "module ModuleA where" ]+      _ <- createDoc "ModuleA.hs" "haskell" contentA+      expectDiagnostics [("ModuleB.hs", [])]+  , testSessionWait "add missing module (non workspace)" $ do+      let contentB = T.unlines+            [ "module ModuleB where"+            , "import ModuleA"+            ]+      _ <- createDoc "/tmp/ModuleB.hs" "haskell" contentB+      expectDiagnostics [("/tmp/ModuleB.hs", [(DsError, (1, 7), "Could not find module")])]+      let contentA = T.unlines [ "module ModuleA where" ]+      _ <- createDoc "/tmp/ModuleA.hs" "haskell" contentA+      expectDiagnostics [("/tmp/ModuleB.hs", [])]+  , testSessionWait "cyclic module dependency" $ do+      let contentA = T.unlines+            [ "module ModuleA where"+            , "import ModuleB"+            ]+      let contentB = T.unlines+            [ "module ModuleB where"+            , "import ModuleA"+            ]+      _ <- createDoc "ModuleA.hs" "haskell" contentA+      _ <- createDoc "ModuleB.hs" "haskell" contentB+      expectDiagnostics+        [ ( "ModuleA.hs"+          , [(DsError, (1, 7), "Cyclic module dependency between ModuleA, ModuleB")]+          )+        , ( "ModuleB.hs"+          , [(DsError, (1, 7), "Cyclic module dependency between ModuleA, ModuleB")]+          )+        ]+  , testSessionWait "cyclic module dependency with hs-boot" $ do+      let contentA = T.unlines+            [ "module ModuleA where"+            , "import {-# SOURCE #-} ModuleB"+            ]+      let contentB = T.unlines+            [ "module ModuleB where"+            , "import ModuleA"+            ]+      let contentBboot = T.unlines+            [ "module ModuleB where"+            ]+      _ <- createDoc "ModuleA.hs" "haskell" contentA+      _ <- createDoc "ModuleB.hs" "haskell" contentB+      _ <- createDoc "ModuleB.hs-boot" "haskell" contentBboot+      expectDiagnostics []+  , testSessionWait "correct reference used with hs-boot" $ do+      let contentB = T.unlines+            [ "module ModuleB where"+            , "import {-# SOURCE #-} ModuleA"+            ]+      let contentA = T.unlines+            [ "module ModuleA where"+            , "import ModuleB"+            , "x = 5"+            ]+      let contentAboot = T.unlines+            [ "module ModuleA where"+            ]+      let contentC = T.unlines+            [ "module ModuleC where"+            , "import ModuleA"+            -- this reference will fail if it gets incorrectly+            -- resolved to the hs-boot file+            , "y = x"+            ]+      _ <- createDoc "ModuleB.hs" "haskell" contentB+      _ <- createDoc "ModuleA.hs" "haskell" contentA+      _ <- createDoc "ModuleA.hs-boot" "haskell" contentAboot+      _ <- createDoc "ModuleC.hs" "haskell" contentC+      expectDiagnostics []+  , testSessionWait "redundant import" $ do+      let contentA = T.unlines ["module ModuleA where"]+      let contentB = T.unlines+            [ "{-# OPTIONS_GHC -Wunused-imports #-}"+            , "module ModuleB where"+            , "import ModuleA"+            ]+      _ <- createDoc "ModuleA.hs" "haskell" contentA+      _ <- createDoc "ModuleB.hs" "haskell" contentB+      expectDiagnostics+        [ ( "ModuleB.hs"+          , [(DsWarning, (2, 0), "The import of 'ModuleA' is redundant")]+          )+        ]+  , testSessionWait "package imports" $ do+      let thisDataListContent = T.unlines+            [ "module Data.List where"+            , "x :: Integer"+            , "x = 123"+            ]+      let mainContent = T.unlines+            [ "{-# LANGUAGE PackageImports #-}"+            , "module Main where"+            , "import qualified \"this\" Data.List as ThisList"+            , "import qualified \"base\" Data.List as BaseList"+            , "useThis = ThisList.x"+            , "useBase = BaseList.map"+            , "wrong1 = ThisList.map"+            , "wrong2 = BaseList.x"+            ]+      _ <- createDoc "Data/List.hs" "haskell" thisDataListContent+      _ <- createDoc "Main.hs" "haskell" mainContent+      expectDiagnostics+        [ ( "Main.hs"+          , [(DsError, (6, 9), "Not in scope: \8216ThisList.map\8217")+            ,(DsError, (7, 9), "Not in scope: \8216BaseList.x\8217")+            ]+          )+        ]+  , testSessionWait "unqualified warnings" $ do+      let fooContent = T.unlines+            [ "{-# OPTIONS_GHC -Wredundant-constraints #-}"+            , "module Foo where"+            , "foo :: Ord a => a -> Int"+            , "foo a = 1"+            ]+      _ <- createDoc "Foo.hs" "haskell" fooContent+      expectDiagnostics+        [ ( "Foo.hs"+      -- The test is to make sure that warnings contain unqualified names+      -- where appropriate. The warning should use an unqualified name 'Ord', not+      -- sometihng like 'GHC.Classes.Ord'. The choice of redundant-constraints to+      -- test this is fairly arbitrary.+          , [(DsWarning, (2, 0), "Redundant constraint: Ord a")+            ]+          )+        ]+    , testSessionWait "lower-case drive" $ do+          let aContent = T.unlines+                [ "module A.A where"+                , "import A.B ()"+                ]+              bContent = T.unlines+                [ "{-# OPTIONS_GHC -Wall #-}"+                , "module A.B where"+                , "import Data.List"+                ]+          uriB <- getDocUri "A/B.hs"+          Just pathB <- pure $ uriToFilePath uriB+          uriB <- pure $+              let (drive, suffix) = splitDrive pathB+              in filePathToUri (joinDrive (lower drive) suffix)+          liftIO $ createDirectoryIfMissing True (takeDirectory pathB)+          liftIO $ writeFileUTF8 pathB $ T.unpack bContent+          uriA <- getDocUri "A/A.hs"+          Just pathA <- pure $ uriToFilePath uriA+          uriA <- pure $+              let (drive, suffix) = splitDrive pathA+              in filePathToUri (joinDrive (lower drive) suffix)+          let itemA = TextDocumentItem uriA "haskell" 0 aContent+          let a = TextDocumentIdentifier uriA+          sendNotification TextDocumentDidOpen (DidOpenTextDocumentParams itemA)+          diagsNot <- skipManyTill anyMessage diagnostic+          let PublishDiagnosticsParams fileUri diags = _params (diagsNot :: PublishDiagnosticsNotification)+          -- Check that if we put a lower-case drive in for A.A+          -- the diagnostics for A.B will also be lower-case.+          liftIO $ fileUri @?= uriB+          let msg = _message (head (toList diags) :: Diagnostic)+          liftIO $ unless ("redundant" `T.isInfixOf` msg) $+              assertFailure ("Expected redundant import but got " <> T.unpack msg)+          closeDoc a+  , testSessionWait "haddock parse error" $ do+      let fooContent = T.unlines+            [ "module Foo where"+            , "foo :: Int"+            , "foo = 1 {-|-}"+            ]+      _ <- createDoc "Foo.hs" "haskell" fooContent+      expectDiagnostics+        [ ( "Foo.hs"+          , [(DsWarning, (2, 8), "Haddock parse error on input")+            ]+          )+        ]+  , testSessionWait "strip file path" $ do+      let+          name = "Testing"+          content = T.unlines+            [ "module " <> name <> " where"+            , "value :: Maybe ()"+            , "value = [()]"+            ]+      _ <- createDoc (T.unpack name <> ".hs") "haskell" content+      notification <- skipManyTill anyMessage diagnostic+      let+          offenders =+            Lsp.params .+            Lsp.diagnostics .+            Lens.folded .+            Lsp.message .+            Lens.filtered (T.isInfixOf ("/" <> name <> ".hs:"))+          failure msg = liftIO $ assertFailure $ "Expected file path to be stripped but got " <> T.unpack msg+      Lens.mapMOf_ offenders failure notification+  ]++codeActionTests :: TestTree+codeActionTests = testGroup "code actions"+  [ renameActionTests+  , typeWildCardActionTests+  , removeImportTests+  , extendImportTests+  , suggestImportTests+  , addExtensionTests+  , fixConstructorImportTests+  , importRenameActionTests+  , fillTypedHoleTests+  , addSigActionTests+  , insertNewDefinitionTests+  , deleteUnusedDefinitionTests+  , addInstanceConstraintTests+  , addFunctionConstraintTests+  , removeRedundantConstraintsTests+  , addTypeAnnotationsToLiteralsTest+  , exportUnusedTests+  ]++codeLensesTests :: TestTree+codeLensesTests = testGroup "code lenses"+  [ addSigLensesTests+  ]++watchedFilesTests :: TestTree+watchedFilesTests = testGroup "watched files"+  [ testSession' "workspace files" $ \sessionDir -> do+      liftIO $ writeFile (sessionDir </> "hie.yaml") "cradle: {direct: {arguments: [\"-isrc\"]}}"+      _doc <- createDoc "A.hs" "haskell" "{-#LANGUAGE NoImplicitPrelude #-}\nmodule A where\nimport WatchedFilesMissingModule"+      watchedFileRegs <- getWatchedFilesSubscriptionsUntil @PublishDiagnosticsNotification++      -- Expect 4 subscriptions (A does not get any because it's VFS):+      --  - /path-to-workspace/hie.yaml+      --  - /path-to-workspace/WatchedFilesMissingModule.hs+      --  - /path-to-workspace/WatchedFilesMissingModule.lhs+      --  - /path-to-workspace/src/WatchedFilesMissingModule.hs+      --  - /path-to-workspace/src/WatchedFilesMissingModule.lhs+      liftIO $ length watchedFileRegs @?= 5++  , testSession' "non workspace file" $ \sessionDir -> do+      liftIO $ writeFile (sessionDir </> "hie.yaml") "cradle: {direct: {arguments: [\"-i/tmp\"]}}"+      _doc <- createDoc "A.hs" "haskell" "{-# LANGUAGE NoImplicitPrelude#-}\nmodule A where\nimport WatchedFilesMissingModule"+      watchedFileRegs <- getWatchedFilesSubscriptionsUntil @PublishDiagnosticsNotification++      -- Expect 2 subscriptions (/tmp does not get any as it is out of the workspace):+      --  - /path-to-workspace/hie.yaml+      --  - /path-to-workspace/WatchedFilesMissingModule.hs+      --  - /path-to-workspace/WatchedFilesMissingModule.lhs+      liftIO $ length watchedFileRegs @?= 3++  -- TODO add a test for didChangeWorkspaceFolder+  ]++renameActionTests :: TestTree+renameActionTests = testGroup "rename actions"+  [ testSession "change to local variable name" $ do+      let content = T.unlines+            [ "module Testing where"+            , "foo :: Int -> Int"+            , "foo argName = argNme"+            ]+      doc <- createDoc "Testing.hs" "haskell" content+      _ <- waitForDiagnostics+      action <- findCodeAction doc (Range (Position 2 14) (Position 2 20)) "Replace with ‘argName’"+      executeCodeAction action+      contentAfterAction <- documentContents doc+      let expectedContentAfterAction = T.unlines+            [ "module Testing where"+            , "foo :: Int -> Int"+            , "foo argName = argName"+            ]+      liftIO $ expectedContentAfterAction @=? contentAfterAction+  , testSession "change to name of imported function" $ do+      let content = T.unlines+            [ "module Testing where"+            , "import Data.Maybe (maybeToList)"+            , "foo :: Maybe a -> [a]"+            , "foo = maybToList"+            ]+      doc <- createDoc "Testing.hs" "haskell" content+      _ <- waitForDiagnostics+      action <- findCodeAction doc (Range (Position 3 6) (Position 3 16))  "Replace with ‘maybeToList’"+      executeCodeAction action+      contentAfterAction <- documentContents doc+      let expectedContentAfterAction = T.unlines+            [ "module Testing where"+            , "import Data.Maybe (maybeToList)"+            , "foo :: Maybe a -> [a]"+            , "foo = maybeToList"+            ]+      liftIO $ expectedContentAfterAction @=? contentAfterAction+  , testSession "suggest multiple local variable names" $ do+      let content = T.unlines+            [ "module Testing where"+            , "foo :: Char -> Char -> Char -> Char"+            , "foo argument1 argument2 argument3 = argumentX"+            ]+      doc <- createDoc "Testing.hs" "haskell" content+      _ <- waitForDiagnostics+      _ <- findCodeActions doc (Range (Position 2 36) (Position 2 45))+                           ["Replace with ‘argument1’", "Replace with ‘argument2’", "Replace with ‘argument3’"]+      return()+  , testSession "change infix function" $ do+      let content = T.unlines+            [ "module Testing where"+            , "monus :: Int -> Int"+            , "monus x y = max 0 (x - y)"+            , "foo x y = x `monnus` y"+            ]+      doc <- createDoc "Testing.hs" "haskell" content+      _ <- waitForDiagnostics+      actionsOrCommands <- getCodeActions doc (Range (Position 3 12) (Position 3 20))+      [fixTypo] <- pure [action | CACodeAction action@CodeAction{ _title = actionTitle } <- actionsOrCommands, "monus" `T.isInfixOf` actionTitle ]+      executeCodeAction fixTypo+      contentAfterAction <- documentContents doc+      let expectedContentAfterAction = T.unlines+            [ "module Testing where"+            , "monus :: Int -> Int"+            , "monus x y = max 0 (x - y)"+            , "foo x y = x `monus` y"+            ]+      liftIO $ expectedContentAfterAction @=? contentAfterAction+  ]++typeWildCardActionTests :: TestTree+typeWildCardActionTests = testGroup "type wildcard actions"+  [ testSession "global signature" $ do+      let content = T.unlines+            [ "module Testing where"+            , "func :: _"+            , "func x = x"+            ]+      doc <- createDoc "Testing.hs" "haskell" content+      _ <- waitForDiagnostics+      actionsOrCommands <- getCodeActions doc (Range (Position 2 1) (Position 2 10))+      let [addSignature] = [action | CACodeAction action@CodeAction { _title = actionTitle } <- actionsOrCommands+                                   , "Use type signature" `T.isInfixOf` actionTitle+                           ]+      executeCodeAction addSignature+      contentAfterAction <- documentContents doc+      let expectedContentAfterAction = T.unlines+            [ "module Testing where"+            , "func :: (p -> p)"+            , "func x = x"+            ]+      liftIO $ expectedContentAfterAction @=? contentAfterAction+  , testSession "multi-line message" $ do+      let content = T.unlines+            [ "module Testing where"+            , "func :: _"+            , "func x y = x + y"+            ]+      doc <- createDoc "Testing.hs" "haskell" content+      _ <- waitForDiagnostics+      actionsOrCommands <- getCodeActions doc (Range (Position 2 1) (Position 2 10))+      let [addSignature] = [action | CACodeAction action@CodeAction { _title = actionTitle } <- actionsOrCommands+                                    , "Use type signature" `T.isInfixOf` actionTitle+                              ]+      executeCodeAction addSignature+      contentAfterAction <- documentContents doc+      let expectedContentAfterAction = T.unlines+            [ "module Testing where"+            , "func :: (Integer -> Integer -> Integer)"+            , "func x y = x + y"+            ]+      liftIO $ expectedContentAfterAction @=? contentAfterAction+  , testSession "local signature" $ do+      let content = T.unlines+            [ "module Testing where"+            , "func :: Int -> Int"+            , "func x ="+            , "  let y :: _"+            , "      y = x * 2"+            , "  in y"+            ]+      doc <- createDoc "Testing.hs" "haskell" content+      _ <- waitForDiagnostics+      actionsOrCommands <- getCodeActions doc (Range (Position 4 1) (Position 4 10))+      let [addSignature] = [action | CACodeAction action@CodeAction { _title = actionTitle } <- actionsOrCommands+                                    , "Use type signature" `T.isInfixOf` actionTitle+                              ]+      executeCodeAction addSignature+      contentAfterAction <- documentContents doc+      let expectedContentAfterAction = T.unlines+            [ "module Testing where"+            , "func :: Int -> Int"+            , "func x ="+            , "  let y :: (Int)"+            , "      y = x * 2"+            , "  in y"+            ]+      liftIO $ expectedContentAfterAction @=? contentAfterAction+  ]++removeImportTests :: TestTree+removeImportTests = testGroup "remove import actions"+  [ testSession "redundant" $ do+      let contentA = T.unlines+            [ "module ModuleA where"+            ]+      _docA <- createDoc "ModuleA.hs" "haskell" contentA+      let contentB = T.unlines+            [ "{-# OPTIONS_GHC -Wunused-imports #-}"+            , "module ModuleB where"+            , "import ModuleA"+            , "stuffB :: Integer"+            , "stuffB = 123"+            ]+      docB <- createDoc "ModuleB.hs" "haskell" contentB+      _ <- waitForDiagnostics+      [CACodeAction action@CodeAction { _title = actionTitle }]+          <- getCodeActions docB (Range (Position 2 0) (Position 2 5))+      liftIO $ "Remove import" @=? actionTitle+      executeCodeAction action+      contentAfterAction <- documentContents docB+      let expectedContentAfterAction = T.unlines+            [ "{-# OPTIONS_GHC -Wunused-imports #-}"+            , "module ModuleB where"+            , "stuffB :: Integer"+            , "stuffB = 123"+            ]+      liftIO $ expectedContentAfterAction @=? contentAfterAction+  , testSession "qualified redundant" $ do+      let contentA = T.unlines+            [ "module ModuleA where"+            ]+      _docA <- createDoc "ModuleA.hs" "haskell" contentA+      let contentB = T.unlines+            [ "{-# OPTIONS_GHC -Wunused-imports #-}"+            , "module ModuleB where"+            , "import qualified ModuleA"+            , "stuffB :: Integer"+            , "stuffB = 123"+            ]+      docB <- createDoc "ModuleB.hs" "haskell" contentB+      _ <- waitForDiagnostics+      [CACodeAction action@CodeAction { _title = actionTitle }]+          <- getCodeActions docB (Range (Position 2 0) (Position 2 5))+      liftIO $ "Remove import" @=? actionTitle+      executeCodeAction action+      contentAfterAction <- documentContents docB+      let expectedContentAfterAction = T.unlines+            [ "{-# OPTIONS_GHC -Wunused-imports #-}"+            , "module ModuleB where"+            , "stuffB :: Integer"+            , "stuffB = 123"+            ]+      liftIO $ expectedContentAfterAction @=? contentAfterAction+  , testSession "redundant binding" $ do+      let contentA = T.unlines+            [ "module ModuleA where"+            , "stuffA = False"+            , "stuffB :: Integer"+            , "stuffB = 123"+            , "stuffC = ()"+            ]+      _docA <- createDoc "ModuleA.hs" "haskell" contentA+      let contentB = T.unlines+            [ "{-# OPTIONS_GHC -Wunused-imports #-}"+            , "module ModuleB where"+            , "import ModuleA (stuffA, stuffB, stuffC, stuffA)"+            , "main = print stuffB"+            ]+      docB <- createDoc "ModuleB.hs" "haskell" contentB+      _ <- waitForDiagnostics+      [CACodeAction action@CodeAction { _title = actionTitle }]+          <- getCodeActions docB (Range (Position 2 0) (Position 2 5))+      liftIO $ "Remove stuffA, stuffC from import" @=? actionTitle+      executeCodeAction action+      contentAfterAction <- documentContents docB+      let expectedContentAfterAction = T.unlines+            [ "{-# OPTIONS_GHC -Wunused-imports #-}"+            , "module ModuleB where"+            , "import ModuleA (stuffB)"+            , "main = print stuffB"+            ]+      liftIO $ expectedContentAfterAction @=? contentAfterAction+  , testSession "redundant operator" $ do+      let contentA = T.unlines+            [ "module ModuleA where"+            , "a !! b = a"+            , "a <?> b = a"+            , "stuffB :: Integer"+            , "stuffB = 123"+            ]+      _docA <- createDoc "ModuleA.hs" "haskell" contentA+      let contentB = T.unlines+            [ "{-# OPTIONS_GHC -Wunused-imports #-}"+            , "module ModuleB where"+            , "import qualified ModuleA as A ((<?>), stuffB, (!!))"+            , "main = print A.stuffB"+            ]+      docB <- createDoc "ModuleB.hs" "haskell" contentB+      _ <- waitForDiagnostics+      [CACodeAction action@CodeAction { _title = actionTitle }]+          <- getCodeActions docB (Range (Position 2 0) (Position 2 5))+      liftIO $ "Remove !!, <?> from import" @=? actionTitle+      executeCodeAction action+      contentAfterAction <- documentContents docB+      let expectedContentAfterAction = T.unlines+            [ "{-# OPTIONS_GHC -Wunused-imports #-}"+            , "module ModuleB where"+            , "import qualified ModuleA as A (stuffB)"+            , "main = print A.stuffB"+            ]+      liftIO $ expectedContentAfterAction @=? contentAfterAction+  , testSession "redundant all import" $ do+      let contentA = T.unlines+            [ "module ModuleA where"+            , "data A = A"+            , "stuffB :: Integer"+            , "stuffB = 123"+            ]+      _docA <- createDoc "ModuleA.hs" "haskell" contentA+      let contentB = T.unlines+            [ "{-# OPTIONS_GHC -Wunused-imports #-}"+            , "module ModuleB where"+            , "import ModuleA (A(..), stuffB)"+            , "main = print stuffB"+            ]+      docB <- createDoc "ModuleB.hs" "haskell" contentB+      _ <- waitForDiagnostics+      [CACodeAction action@CodeAction { _title = actionTitle }]+          <- getCodeActions docB (Range (Position 2 0) (Position 2 5))+      liftIO $ "Remove A from import" @=? actionTitle+      executeCodeAction action+      contentAfterAction <- documentContents docB+      let expectedContentAfterAction = T.unlines+            [ "{-# OPTIONS_GHC -Wunused-imports #-}"+            , "module ModuleB where"+            , "import ModuleA (stuffB)"+            , "main = print stuffB"+            ]+      liftIO $ expectedContentAfterAction @=? contentAfterAction+  , testSession "redundant constructor import" $ do+      let contentA = T.unlines+            [ "module ModuleA where"+            , "data D = A | B"+            , "data E = F"+            ]+      _docA <- createDoc "ModuleA.hs" "haskell" contentA+      let contentB = T.unlines+            [ "{-# OPTIONS_GHC -Wunused-imports #-}"+            , "module ModuleB where"+            , "import ModuleA (D(A,B), E(F))"+            , "main = B"+            ]+      docB <- createDoc "ModuleB.hs" "haskell" contentB+      _ <- waitForDiagnostics+      [CACodeAction action@CodeAction { _title = actionTitle }]+          <- getCodeActions docB (Range (Position 2 0) (Position 2 5))+      liftIO $ "Remove A, E, F from import" @=? actionTitle+      executeCodeAction action+      contentAfterAction <- documentContents docB+      let expectedContentAfterAction = T.unlines+            [ "{-# OPTIONS_GHC -Wunused-imports #-}"+            , "module ModuleB where"+            , "import ModuleA (D(B))"+            , "main = B"+            ]+      liftIO $ expectedContentAfterAction @=? contentAfterAction+  , testSession "import containing the identifier Strict" $ do+      let contentA = T.unlines+            [ "module Strict where"+            ]+      _docA <- createDoc "Strict.hs" "haskell" contentA+      let contentB = T.unlines+            [ "{-# OPTIONS_GHC -Wunused-imports #-}"+            , "module ModuleB where"+            , "import Strict"+            ]+      docB <- createDoc "ModuleB.hs" "haskell" contentB+      _ <- waitForDiagnostics+      [CACodeAction action@CodeAction { _title = actionTitle }]+          <- getCodeActions docB (Range (Position 2 0) (Position 2 5))+      liftIO $ "Remove import" @=? actionTitle+      executeCodeAction action+      contentAfterAction <- documentContents docB+      let expectedContentAfterAction = T.unlines+            [ "{-# OPTIONS_GHC -Wunused-imports #-}"+            , "module ModuleB where"+            ]+      liftIO $ expectedContentAfterAction @=? contentAfterAction+  ]++extendImportTests :: TestTree+extendImportTests = testGroup "extend import actions"+  [ testSession "extend single line import with value" $ template+      (T.unlines+            [ "module ModuleA where"+            , "stuffA :: Double"+            , "stuffA = 0.00750"+            , "stuffB :: Integer"+            , "stuffB = 123"+            ])+      (T.unlines+            [ "module ModuleB where"+            , "import ModuleA as A (stuffB)"+            , "main = print (stuffA, stuffB)"+            ])+      (Range (Position 3 17) (Position 3 18))+      "Add stuffA to the import list of ModuleA"+      (T.unlines+            [ "module ModuleB where"+            , "import ModuleA as A (stuffA, stuffB)"+            , "main = print (stuffA, stuffB)"+            ])+  , testSession "extend single line import with operator" $ template+      (T.unlines+            [ "module ModuleA where"+            , "(.*) :: Integer -> Integer -> Integer"+            , "x .* y = x * y"+            , "stuffB :: Integer"+            , "stuffB = 123"+            ])+      (T.unlines+            [ "module ModuleB where"+            , "import ModuleA as A (stuffB)"+            , "main = print (stuffB .* stuffB)"+            ])+      (Range (Position 3 17) (Position 3 18))+      "Add .* to the import list of ModuleA"+      (T.unlines+            [ "module ModuleB where"+            , "import ModuleA as A ((.*), stuffB)"+            , "main = print (stuffB .* stuffB)"+            ])+  , testSession "extend single line import with type" $ template+      (T.unlines+            [ "module ModuleA where"+            , "type A = Double"+            ])+      (T.unlines+            [ "module ModuleB where"+            , "import ModuleA ()"+            , "b :: A"+            , "b = 0"+            ])+      (Range (Position 2 5) (Position 2 5))+      "Add A to the import list of ModuleA"+      (T.unlines+            [ "module ModuleB where"+            , "import ModuleA (A)"+            , "b :: A"+            , "b = 0"+            ])+  ,  (`xfail` "known broken") $ testSession "extend single line import with constructor" $ template+      (T.unlines+            [ "module ModuleA where"+            , "data A = Constructor"+            ])+      (T.unlines+            [ "module ModuleB where"+            , "import ModuleA (A)"+            , "b :: A"+            , "b = Constructor"+            ])+      (Range (Position 2 5) (Position 2 5))+      "Add Constructor to the import list of ModuleA"+      (T.unlines+            [ "module ModuleB where"+            , "import ModuleA (A(Constructor))"+            , "b :: A"+            , "b = Constructor"+            ])+  , testSession "extend single line qualified import with value" $ template+      (T.unlines+            [ "module ModuleA where"+            , "stuffA :: Double"+            , "stuffA = 0.00750"+            , "stuffB :: Integer"+            , "stuffB = 123"+            ])+      (T.unlines+            [ "module ModuleB where"+            , "import qualified ModuleA as A (stuffB)"+            , "main = print (A.stuffA, A.stuffB)"+            ])+      (Range (Position 3 17) (Position 3 18))+      "Add stuffA to the import list of ModuleA"+      (T.unlines+            [ "module ModuleB where"+            , "import qualified ModuleA as A (stuffA, stuffB)"+            , "main = print (A.stuffA, A.stuffB)"+            ])+  , testSession "extend multi line import with value" $ template+      (T.unlines+            [ "module ModuleA where"+            , "stuffA :: Double"+            , "stuffA = 0.00750"+            , "stuffB :: Integer"+            , "stuffB = 123"+            ])+      (T.unlines+            [ "module ModuleB where"+            , "import ModuleA (stuffB"+            , "               )"+            , "main = print (stuffA, stuffB)"+            ])+      (Range (Position 3 17) (Position 3 18))+      "Add stuffA to the import list of ModuleA"+      (T.unlines+            [ "module ModuleB where"+            , "import ModuleA (stuffA, stuffB"+            , "               )"+            , "main = print (stuffA, stuffB)"+            ])+  ]+  where+    template contentA contentB range expectedAction expectedContentB = do+      _docA <- createDoc "ModuleA.hs" "haskell" contentA+      docB <- createDoc "ModuleB.hs" "haskell" contentB+      _ <- waitForDiagnostics+      CACodeAction action@CodeAction { _title = actionTitle } : _+                  <- sortOn (\(CACodeAction CodeAction{_title=x}) -> x) <$>+                     getCodeActions docB range+      liftIO $ expectedAction @=? actionTitle+      executeCodeAction action+      contentAfterAction <- documentContents docB+      liftIO $ expectedContentB @=? contentAfterAction++suggestImportTests :: TestTree+suggestImportTests = testGroup "suggest import actions"+  [ testGroup "Dont want suggestion"+    [ -- extend import+      test False ["Data.List.NonEmpty ()"] "f = nonEmpty" []                "import Data.List.NonEmpty (nonEmpty)"+      -- data constructor+    , test False []                        "f = First"    []                "import Data.Monoid (First)"+      -- internal module+    , test False []         "f :: Typeable a => a"        ["f = undefined"] "import Data.Typeable.Internal (Typeable)"+      -- package not in scope+    , test False []         "f = quickCheck"              []                "import Test.QuickCheck (quickCheck)"+    ]+  , testGroup "want suggestion"+    [ test True []          "f = nonEmpty"                []                "import Data.List.NonEmpty (nonEmpty)"+    , test True []          "f = (:|)"                    []                "import Data.List.NonEmpty (NonEmpty((:|)))"+    , test True []          "f :: Natural"                ["f = undefined"] "import Numeric.Natural (Natural)"+    , test True []          "f :: NonEmpty ()"            ["f = () :| []"]  "import Data.List.NonEmpty (NonEmpty)"+    , test True []          "f = First"                   []                "import Data.Monoid (First(First))"+    , test True []          "f = Endo"                    []                "import Data.Monoid (Endo(Endo))"+    , test True []          "f = Version"                 []                "import Data.Version (Version(Version))"+    , test True []          "f ExitSuccess = ()"          []                "import System.Exit (ExitCode(ExitSuccess))"+    , test True []          "f = AssertionFailed"         []                "import Control.Exception (AssertionFailed(AssertionFailed))"+    , test True ["Prelude"] "f = nonEmpty"                []                "import Data.List.NonEmpty (nonEmpty)"+    , test True []          "f :: Alternative f => f ()"  ["f = undefined"] "import Control.Applicative (Alternative)"+    , test True []          "f = empty"                   []                "import Control.Applicative (Alternative(empty))"+    , test True []          "f = (&)"                     []                "import Data.Function ((&))"+    , test True []          "f = NE.nonEmpty"             []                "import qualified Data.List.NonEmpty as NE"+    , test True []          "f :: Typeable a => a"        ["f = undefined"] "import Data.Typeable (Typeable)"+    , test True []          "f = pack"                    []                "import Data.Text (pack)"+    , test True []          "f :: Text"                   ["f = undefined"] "import Data.Text (Text)"+    , test True []          "f = [] & id"                 []                "import Data.Function ((&))"+    , test True []          "f = (&) [] id"               []                "import Data.Function ((&))"+    ]+  ]+  where+    test wanted imps def other newImp = testSession' (T.unpack def) $ \dir -> do+      let before = T.unlines $ "module A where" : ["import " <> x | x <- imps] ++ def : other+          after  = T.unlines $ "module A where" : ["import " <> x | x <- imps] ++ [newImp] ++ def : other+          cradle = "cradle: {direct: {arguments: [-hide-all-packages, -package, base, -package, text, -package-env, -]}}"+      liftIO $ writeFileUTF8 (dir </> "hie.yaml") cradle+      doc <- createDoc "Test.hs" "haskell" before+      _diags <- waitForDiagnostics+      let defLine = length imps + 1+          range = Range (Position defLine 0) (Position defLine maxBound)+      actions <- getCodeActions doc range+      if wanted+         then do+             action <- liftIO $ pickActionWithTitle newImp actions+             executeCodeAction action+             contentAfterAction <- documentContents doc+             liftIO $ after @=? contentAfterAction+          else+              liftIO $ [_title | CACodeAction CodeAction{_title} <- actions, _title == newImp ] @?= []+++addExtensionTests :: TestTree+addExtensionTests = testGroup "add language extension actions"+  [ testSession "add NamedFieldPuns language extension" $ template+      (T.unlines+            [ "module Module where"+            , ""+            , "data A = A { getA :: Bool }"+            , ""+            , "f :: A -> Bool"+            , "f A { getA } = getA"+            ])+      (Range (Position 0 0) (Position 0 0))+      "Add NamedFieldPuns extension"+      (T.unlines+            [ "{-# LANGUAGE NamedFieldPuns #-}"+            , "module Module where"+            , ""+            , "data A = A { getA :: Bool }"+            , ""+            , "f :: A -> Bool"+            , "f A { getA } = getA"+            ])+  , testSession "add RecordWildCards language extension" $ template+      (T.unlines+            [ "module Module where"+            , ""+            , "data A = A { getA :: Bool }"+            , ""+            , "f :: A -> Bool"+            , "f A { .. } = getA"+            ])+      (Range (Position 0 0) (Position 0 0))+      "Add RecordWildCards extension"+      (T.unlines+            [ "{-# LANGUAGE RecordWildCards #-}"+            , "module Module where"+            , ""+            , "data A = A { getA :: Bool }"+            , ""+            , "f :: A -> Bool"+            , "f A { .. } = getA"+            ])+  ]+    where+      template initialContent range expectedAction expectedContents = do+        doc <- createDoc "Module.hs" "haskell" initialContent+        _ <- waitForDiagnostics+        CACodeAction action@CodeAction { _title = actionTitle } : _+                    <- sortOn (\(CACodeAction CodeAction{_title=x}) -> x) <$>+                       getCodeActions doc range+        liftIO $ expectedAction @=? actionTitle+        executeCodeAction action+        contentAfterAction <- documentContents doc+        liftIO $ expectedContents @=? contentAfterAction+++insertNewDefinitionTests :: TestTree+insertNewDefinitionTests = testGroup "insert new definition actions"+  [ testSession "insert new function definition" $ do+      let txtB =+            ["foo True = select [True]"+            , ""+            ,"foo False = False"+            ]+          txtB' =+            [""+            ,"someOtherCode = ()"+            ]+      docB <- createDoc "ModuleB.hs" "haskell" (T.unlines $ txtB ++ txtB')+      _ <- waitForDiagnostics+      CACodeAction action@CodeAction { _title = actionTitle } : _+                  <- sortOn (\(CACodeAction CodeAction{_title=x}) -> x) <$>+                     getCodeActions docB (R 1 0 1 50)+      liftIO $ actionTitle @?= "Define select :: [Bool] -> Bool"+      executeCodeAction action+      contentAfterAction <- documentContents docB+      liftIO $ contentAfterAction @?= T.unlines (txtB +++        [ ""+        , "select :: [Bool] -> Bool"+        , "select = error \"not implemented\""+        ]+        ++ txtB')+  , testSession "define a hole" $ do+      let txtB =+            ["foo True = _select [True]"+            , ""+            ,"foo False = False"+            ]+          txtB' =+            [""+            ,"someOtherCode = ()"+            ]+      docB <- createDoc "ModuleB.hs" "haskell" (T.unlines $ txtB ++ txtB')+      _ <- waitForDiagnostics+      CACodeAction action@CodeAction { _title = actionTitle } : _+                  <- sortOn (\(CACodeAction CodeAction{_title=x}) -> x) <$>+                     getCodeActions docB (R 1 0 1 50)+      liftIO $ actionTitle @?= "Define select :: [Bool] -> Bool"+      executeCodeAction action+      contentAfterAction <- documentContents docB+      liftIO $ contentAfterAction @?= T.unlines (+        ["foo True = select [True]"+        , ""+        ,"foo False = False"+        , ""+        , "select :: [Bool] -> Bool"+        , "select = error \"not implemented\""+        ]+        ++ txtB')+  ]+++deleteUnusedDefinitionTests :: TestTree+deleteUnusedDefinitionTests = testGroup "delete unused definition action"+  [ testSession "delete unused top level binding" $+    testFor+    (T.unlines [ "{-# OPTIONS_GHC -Wunused-top-binds #-}"+               , "module A (some) where"+               , ""+               , "f :: Int -> Int"+               , "f 1 = let a = 1"+               , "      in a"+               , "f 2 = 2"+               , ""+               , "some = ()"+               ])+    (4, 0)+    "Delete ‘f’"+    (T.unlines [+        "{-# OPTIONS_GHC -Wunused-top-binds #-}"+        , "module A (some) where"+        , ""+        , "some = ()"+        ])++  , testSession "delete unused top level binding defined in infix form" $+    testFor+    (T.unlines [ "{-# OPTIONS_GHC -Wunused-top-binds #-}"+               , "module A (some) where"+               , ""+               , "myPlus :: Int -> Int -> Int"+               , "a `myPlus` b = a + b"+               , ""+               , "some = ()"+               ])+    (4, 2)+    "Delete ‘myPlus’"+    (T.unlines [+        "{-# OPTIONS_GHC -Wunused-top-binds #-}"+        , "module A (some) where"+        , ""+        , "some = ()"+      ])+  ]+  where+    testFor source pos expectedTitle expectedResult = do+      docId <- createDoc "A.hs" "haskell" source+      expectDiagnostics [ ("A.hs", [(DsWarning, pos, "not used")]) ]++      (action, title) <- extractCodeAction docId "Delete"++      liftIO $ title @?= expectedTitle+      executeCodeAction action+      contentAfterAction <- documentContents docId+      liftIO $ contentAfterAction @?= expectedResult++    extractCodeAction docId actionPrefix = do+      [action@CodeAction { _title = actionTitle }]  <- findCodeActionsByPrefix docId (R 0 0 0 0) [actionPrefix]+      return (action, actionTitle)++addTypeAnnotationsToLiteralsTest :: TestTree+addTypeAnnotationsToLiteralsTest = testGroup "add type annotations to literals to satisfy contraints"+  [+    testSession "add default type to satisfy one contraint" $+    testFor+    (T.unlines [ "{-# OPTIONS_GHC -Wtype-defaults #-}"+               , "module A () where"+               , ""+               , "f = 1"+               ])+    [ (DsWarning, (3, 4), "Defaulting the following constraint") ]+    "Add type annotation ‘Integer’ to ‘1’"+    (T.unlines [ "{-# OPTIONS_GHC -Wtype-defaults #-}"+               , "module A () where"+               , ""+               , "f = (1 :: Integer)"+               ])++  , testSession "add default type to satisfy one contraint with duplicate literals" $+    testFor+    (T.unlines [ "{-# OPTIONS_GHC -Wtype-defaults #-}"+               , "{-# LANGUAGE OverloadedStrings #-}"+               , "module A () where"+               , ""+               , "import Debug.Trace"+               , ""+               , "f = seq \"debug\" traceShow \"debug\""+               ])+    [ (DsWarning, (6, 8), "Defaulting the following constraint")+    , (DsWarning, (6, 16), "Defaulting the following constraint")+    ]+    "Add type annotation ‘[Char]’ to ‘\"debug\"’"+    (T.unlines [ "{-# OPTIONS_GHC -Wtype-defaults #-}"+               , "{-# LANGUAGE OverloadedStrings #-}"+               , "module A () where"+               , ""+               , "import Debug.Trace"+               , ""+               , "f = seq (\"debug\" :: [Char]) traceShow \"debug\""+               ])+  , testSession "add default type to satisfy two contraints" $+    testFor+    (T.unlines [ "{-# OPTIONS_GHC -Wtype-defaults #-}"+               , "{-# LANGUAGE OverloadedStrings #-}"+               , "module A () where"+               , ""+               , "import Debug.Trace"+               , ""+               , "f a = traceShow \"debug\" a"+               ])+    [ (DsWarning, (6, 6), "Defaulting the following constraint") ]+    "Add type annotation ‘[Char]’ to ‘\"debug\"’"+    (T.unlines [ "{-# OPTIONS_GHC -Wtype-defaults #-}"+               , "{-# LANGUAGE OverloadedStrings #-}"+               , "module A () where"+               , ""+               , "import Debug.Trace"+               , ""+               , "f a = traceShow (\"debug\" :: [Char]) a"+               ])+  , testSession "add default type to satisfy two contraints with duplicate literals" $+    testFor+    (T.unlines [ "{-# OPTIONS_GHC -Wtype-defaults #-}"+               , "{-# LANGUAGE OverloadedStrings #-}"+               , "module A () where"+               , ""+               , "import Debug.Trace"+               , ""+               , "f = seq (\"debug\" :: [Char]) (seq (\"debug\" :: [Char]) (traceShow \"debug\"))"+               ])+    [ (DsWarning, (6, 54), "Defaulting the following constraint") ]+    "Add type annotation ‘[Char]’ to ‘\"debug\"’"+    (T.unlines [ "{-# OPTIONS_GHC -Wtype-defaults #-}"+               , "{-# LANGUAGE OverloadedStrings #-}"+               , "module A () where"+               , ""+               , "import Debug.Trace"+               , ""+               , "f = seq (\"debug\" :: [Char]) (seq (\"debug\" :: [Char]) (traceShow (\"debug\" :: [Char])))"+               ])+  ]+  where+    testFor source diag expectedTitle expectedResult = do+      docId <- createDoc "A.hs" "haskell" source+      expectDiagnostics [ ("A.hs", diag) ]++      (action, title) <- extractCodeAction docId "Add type annotation"++      liftIO $ title @?= expectedTitle+      executeCodeAction action+      contentAfterAction <- documentContents docId+      liftIO $ contentAfterAction @?= expectedResult++    extractCodeAction docId actionPrefix = do+      [action@CodeAction { _title = actionTitle }]  <- findCodeActionsByPrefix docId (R 0 0 0 0) [actionPrefix]+      return (action, actionTitle)+++fixConstructorImportTests :: TestTree+fixConstructorImportTests = testGroup "fix import actions"+  [ testSession "fix constructor import" $ template+      (T.unlines+            [ "module ModuleA where"+            , "data A = Constructor"+            ])+      (T.unlines+            [ "module ModuleB where"+            , "import ModuleA(Constructor)"+            ])+      (Range (Position 1 10) (Position 1 11))+      "Fix import of A(Constructor)"+      (T.unlines+            [ "module ModuleB where"+            , "import ModuleA(A(Constructor))"+            ])+  ]+  where+    template contentA contentB range expectedAction expectedContentB = do+      _docA <- createDoc "ModuleA.hs" "haskell" contentA+      docB  <- createDoc "ModuleB.hs" "haskell" contentB+      _diags <- waitForDiagnostics+      CACodeAction action@CodeAction { _title = actionTitle } : _+                  <- sortOn (\(CACodeAction CodeAction{_title=x}) -> x) <$>+                     getCodeActions docB range+      liftIO $ expectedAction @=? actionTitle+      executeCodeAction action+      contentAfterAction <- documentContents docB+      liftIO $ expectedContentB @=? contentAfterAction++importRenameActionTests :: TestTree+importRenameActionTests = testGroup "import rename actions"+  [ testSession "Data.Mape -> Data.Map"   $ check "Map"+  , testSession "Data.Mape -> Data.Maybe" $ check "Maybe" ] where+  check modname = do+      let content = T.unlines+            [ "module Testing where"+            , "import Data.Mape"+            ]+      doc <- createDoc "Testing.hs" "haskell" content+      _ <- waitForDiagnostics+      actionsOrCommands <- getCodeActions doc (Range (Position 2 8) (Position 2 16))+      let [changeToMap] = [action | CACodeAction action@CodeAction{ _title = actionTitle } <- actionsOrCommands, ("Data." <> modname) `T.isInfixOf` actionTitle ]+      executeCodeAction changeToMap+      contentAfterAction <- documentContents doc+      let expectedContentAfterAction = T.unlines+            [ "module Testing where"+            , "import Data." <> modname+            ]+      liftIO $ expectedContentAfterAction @=? contentAfterAction++fillTypedHoleTests :: TestTree+fillTypedHoleTests = let++  sourceCode :: T.Text -> T.Text -> T.Text -> T.Text+  sourceCode a b c = T.unlines+    [ "module Testing where"+      , ""+      , "globalConvert :: Int -> String"+      , "globalConvert = undefined"+      , ""+      , "globalInt :: Int"+      , "globalInt = 3"+      , ""+      , "bar :: Int -> Int -> String"+      , "bar n parameterInt = " <> a <> " (n + " <> b <> " + " <> c <> ")  where"+      , "  localConvert = (flip replicate) 'x'"++    ]++  check :: T.Text -> T.Text -> T.Text -> T.Text -> T.Text -> T.Text -> T.Text -> TestTree+  check actionTitle+        oldA oldB oldC+        newA newB newC = testSession (T.unpack actionTitle) $ do+    let originalCode = sourceCode oldA oldB oldC+    let expectedCode = sourceCode newA newB newC+    doc <- createDoc "Testing.hs" "haskell" originalCode+    _ <- waitForDiagnostics+    actionsOrCommands <- getCodeActions doc (Range (Position 9 0) (Position 9 maxBound))+    chosenAction <- liftIO $ pickActionWithTitle actionTitle actionsOrCommands+    executeCodeAction chosenAction+    modifiedCode <- documentContents doc+    liftIO $ expectedCode @=? modifiedCode+  in+  testGroup "fill typed holes"+  [ check "replace hole `_` with show"+          "_"    "n" "n"+          "show" "n" "n"++  , check "replace hole `_` with globalConvert"+          "_"             "n" "n"+          "globalConvert" "n" "n"++#if MIN_GHC_API_VERSION(8,6,0)+  , check "replace hole `_convertme` with localConvert"+          "_convertme"   "n" "n"+          "localConvert" "n" "n"+#endif++  , check "replace hole `_b` with globalInt"+          "_a" "_b"        "_c"+          "_a" "globalInt" "_c"++  , check "replace hole `_c` with globalInt"+          "_a" "_b"        "_c"+          "_a" "_b" "globalInt"++#if MIN_GHC_API_VERSION(8,6,0)+  , check "replace hole `_c` with parameterInt"+          "_a" "_b" "_c"+          "_a" "_b"  "parameterInt"+#endif+  ]++addInstanceConstraintTests :: TestTree+addInstanceConstraintTests = let+  missingConstraintSourceCode :: Maybe T.Text -> T.Text+  missingConstraintSourceCode mConstraint =+    let constraint = maybe "" (<> " => ") mConstraint+     in T.unlines+    [ "module Testing where"+    , ""+    , "data Wrap a = Wrap a"+    , ""+    , "instance " <> constraint <> "Eq (Wrap a) where"+    , "  (Wrap x) == (Wrap y) = x == y"+    ]++  incompleteConstraintSourceCode :: Maybe T.Text -> T.Text+  incompleteConstraintSourceCode mConstraint =+    let constraint = maybe "Eq a" (\c -> "(Eq a, " <> c <> ")")  mConstraint+     in T.unlines+    [ "module Testing where"+    , ""+    , "data Pair a b = Pair a b"+    , ""+    , "instance " <> constraint <> " => Eq (Pair a b) where"+    , "  (Pair x y) == (Pair x' y') = x == x' && y == y'"+    ]++  incompleteConstraintSourceCode2 :: Maybe T.Text -> T.Text+  incompleteConstraintSourceCode2 mConstraint =+    let constraint = maybe "(Eq a, Eq b)" (\c -> "(Eq a, Eq b, " <> c <> ")")  mConstraint+     in T.unlines+    [ "module Testing where"+    , ""+    , "data Three a b c = Three a b c"+    , ""+    , "instance " <> constraint <> " => Eq (Three a b c) where"+    , "  (Three x y z) == (Three x' y' z') = x == x' && y == y' && z == z'"+    ]++  check :: T.Text -> T.Text -> T.Text -> TestTree+  check actionTitle originalCode expectedCode = testSession (T.unpack actionTitle) $ do+    doc <- createDoc "Testing.hs" "haskell" originalCode+    _ <- waitForDiagnostics+    actionsOrCommands <- getCodeActions doc (Range (Position 6 0) (Position 6 68))+    chosenAction <- liftIO $ pickActionWithTitle actionTitle actionsOrCommands+    executeCodeAction chosenAction+    modifiedCode <- documentContents doc+    liftIO $ expectedCode @=? modifiedCode++  in testGroup "add instance constraint"+  [ check+    "Add `Eq a` to the context of the instance declaration"+    (missingConstraintSourceCode Nothing)+    (missingConstraintSourceCode $ Just "Eq a")+  , check+    "Add `Eq b` to the context of the instance declaration"+    (incompleteConstraintSourceCode Nothing)+    (incompleteConstraintSourceCode $ Just "Eq b")+  , check+    "Add `Eq c` to the context of the instance declaration"+    (incompleteConstraintSourceCode2 Nothing)+    (incompleteConstraintSourceCode2 $ Just "Eq c")+  ]++addFunctionConstraintTests :: TestTree+addFunctionConstraintTests = let+  missingConstraintSourceCode :: Maybe T.Text -> T.Text+  missingConstraintSourceCode mConstraint =+    let constraint = maybe "" (<> " => ") mConstraint+     in T.unlines+    [ "module Testing where"+    , ""+    , "eq :: " <> constraint <> "a -> a -> Bool"+    , "eq x y = x == y"+    ]++  incompleteConstraintSourceCode :: Maybe T.Text -> T.Text+  incompleteConstraintSourceCode mConstraint =+    let constraint = maybe "Eq a" (\c -> "(Eq a, " <> c <> ")") mConstraint+     in T.unlines+    [ "module Testing where"+    , ""+    , "data Pair a b = Pair a b"+    , ""+    , "eq :: " <> constraint <> " => Pair a b -> Pair a b -> Bool"+    , "eq (Pair x y) (Pair x' y') = x == x' && y == y'"+    ]++  incompleteConstraintSourceCode2 :: Maybe T.Text -> T.Text+  incompleteConstraintSourceCode2 mConstraint =+    let constraint = maybe "(Eq a, Eq b)" (\c -> "(Eq a, Eq b, " <> c <> ")") mConstraint+     in T.unlines+    [ "module Testing where"+    , ""+    , "data Three a b c = Three a b c"+    , ""+    , "eq :: " <> constraint <> " => Three a b c -> Three a b c -> Bool"+    , "eq (Three x y z) (Three x' y' z') = x == x' && y == y' && z == z'"+    ]++  check :: T.Text -> T.Text -> T.Text -> TestTree+  check actionTitle originalCode expectedCode = testSession (T.unpack actionTitle) $ do+    doc <- createDoc "Testing.hs" "haskell" originalCode+    _ <- waitForDiagnostics+    actionsOrCommands <- getCodeActions doc (Range (Position 6 0) (Position 6 maxBound))+    chosenAction <- liftIO $ pickActionWithTitle actionTitle actionsOrCommands+    executeCodeAction chosenAction+    modifiedCode <- documentContents doc+    liftIO $ expectedCode @=? modifiedCode++  in testGroup "add function constraint"+  [ check+    "Add `Eq a` to the context of the type signature for `eq`"+    (missingConstraintSourceCode Nothing)+    (missingConstraintSourceCode $ Just "Eq a")+  , check+    "Add `Eq b` to the context of the type signature for `eq`"+    (incompleteConstraintSourceCode Nothing)+    (incompleteConstraintSourceCode $ Just "Eq b")+  , check+    "Add `Eq c` to the context of the type signature for `eq`"+    (incompleteConstraintSourceCode2 Nothing)+    (incompleteConstraintSourceCode2 $ Just "Eq c")+  ]++removeRedundantConstraintsTests :: TestTree+removeRedundantConstraintsTests = let+  header =+    [ "{-# OPTIONS_GHC -Wredundant-constraints #-}"+    , "module Testing where"+    , ""+    ]++  redundantConstraintsCode :: Maybe T.Text -> T.Text+  redundantConstraintsCode mConstraint =+    let constraint = maybe "" (\c -> "" <> c <> " => ") mConstraint+      in T.unlines $ header <>+        [ "foo :: " <> constraint <> "a -> a"+        , "foo = id"+        ]++  redundantMixedConstraintsCode :: Maybe T.Text -> T.Text+  redundantMixedConstraintsCode mConstraint =+    let constraint = maybe "(Num a, Eq a)" (\c -> "(Num a, Eq a, " <> c <> ")") mConstraint+      in T.unlines $ header <>+        [ "foo :: " <> constraint <> " => a -> Bool"+        , "foo x = x == 1"+        ]++  typeSignatureSpaces :: T.Text+  typeSignatureSpaces = T.unlines $ header <>+    [ "foo ::  (Num a, Eq a, Monoid a)  => a -> Bool"+    , "foo x = x == 1"+    ]++  typeSignatureMultipleLines :: T.Text+  typeSignatureMultipleLines = T.unlines $ header <>+    [ "foo :: (Num a, Eq a, Monoid a)"+    , "=> a -> Bool"+    , "foo x = x == 1"+    ]++  check :: T.Text -> T.Text -> T.Text -> TestTree+  check actionTitle originalCode expectedCode = testSession (T.unpack actionTitle) $ do+    doc <- createDoc "Testing.hs" "haskell" originalCode+    _ <- waitForDiagnostics+    actionsOrCommands <- getCodeActions doc (Range (Position 4 0) (Position 4 maxBound))+    chosenAction <- liftIO $ pickActionWithTitle actionTitle actionsOrCommands+    executeCodeAction chosenAction+    modifiedCode <- documentContents doc+    liftIO $ expectedCode @=? modifiedCode++  checkPeculiarFormatting :: String -> T.Text -> TestTree+  checkPeculiarFormatting title code = testSession title $ do+    doc <- createDoc "Testing.hs" "haskell" code+    _ <- waitForDiagnostics+    actionsOrCommands <- getCodeActions doc (Range (Position 4 0) (Position 4 maxBound))+    liftIO $ assertBool "Found some actions" (null actionsOrCommands)++  in testGroup "remove redundant function constraints"+  [ check+    "Remove redundant constraint `Eq a` from the context of the type signature for `foo`"+    (redundantConstraintsCode $ Just "Eq a")+    (redundantConstraintsCode Nothing)+  , check+    "Remove redundant constraints `(Eq a, Monoid a)` from the context of the type signature for `foo`"+    (redundantConstraintsCode $ Just "(Eq a, Monoid a)")+    (redundantConstraintsCode Nothing)+  , check+    "Remove redundant constraints `(Monoid a, Show a)` from the context of the type signature for `foo`"+    (redundantMixedConstraintsCode $ Just "Monoid a, Show a")+    (redundantMixedConstraintsCode Nothing)+  , checkPeculiarFormatting+    "should do nothing when constraints contain an arbitrary number of spaces"+    typeSignatureSpaces+  , checkPeculiarFormatting+    "should do nothing when constraints contain line feeds"+    typeSignatureMultipleLines+  ]++addSigActionTests :: TestTree+addSigActionTests = let+  header = "{-# OPTIONS_GHC -Wmissing-signatures -Wmissing-pattern-synonym-signatures #-}"+  moduleH = "{-# LANGUAGE PatternSynonyms #-}\nmodule Sigs where"+  before def     = T.unlines [header, moduleH,      def]+  after' def sig = T.unlines [header, moduleH, sig, def]++  def >:: sig = testSession (T.unpack def) $ do+    let originalCode = before def+    let expectedCode = after' def sig+    doc <- createDoc "Sigs.hs" "haskell" originalCode+    _ <- waitForDiagnostics+    actionsOrCommands <- getCodeActions doc (Range (Position 3 1) (Position 3 maxBound))+    chosenAction <- liftIO $ pickActionWithTitle ("add signature: " <> sig) actionsOrCommands+    executeCodeAction chosenAction+    modifiedCode <- documentContents doc+    liftIO $ expectedCode @=? modifiedCode+  in+  testGroup "add signature"+    [ "abc = True"              >:: "abc :: Bool"+    , "foo a b = a + b"         >:: "foo :: Num a => a -> a -> a"+    , "bar a b = show $ a + b"  >:: "bar :: (Show a, Num a) => a -> a -> String"+    , "(!!!) a b = a > b"       >:: "(!!!) :: Ord a => a -> a -> Bool"+    , "a >>>> b = a + b"        >:: "(>>>>) :: Num a => a -> a -> a"+    , "a `haha` b = a b"        >:: "haha :: (t1 -> t2) -> t1 -> t2"+    , "pattern Some a = Just a" >:: "pattern Some :: a -> Maybe a"+    ]++exportUnusedTests :: TestTree+exportUnusedTests = testGroup "export unused actions"+  [ testGroup "don't want suggestion"+    [ testSession "implicit exports" $ template+        (T.unlines+              [ "{-# OPTIONS_GHC -Wunused-top-binds #-}"+              , "{-# OPTIONS_GHC -Wmissing-signatures #-}"+              , "module A where"+              , "foo = id"])+        (R 3 0 3 3)+        "Export ‘foo’"+        Nothing -- codeaction should not be available+    , testSession "not top-level" $ template+        (T.unlines+              [ "{-# OPTIONS_GHC -Wunused-top-binds #-}" +              , "{-# OPTIONS_GHC -Wunused-binds #-}" +              , "module A (foo,bar) where"+              , "foo = ()"+              , "  where bar = ()"+              , "bar = ()"])+        (R 2 0 2 11)+        "Export ‘bar’"+        Nothing+    , testSession "type is exported but not the constructor of same name" $ template+        (T.unlines+              [ "{-# OPTIONS_GHC -Wunused-top-binds #-}"+              , "module A (Foo) where"+              , "data Foo = Foo"])+        (R 2 0 2 8)+        "Export ‘Foo’"+        Nothing -- codeaction should not be available+    , testSession "unused data field" $ template+        (T.unlines+              [ "{-# OPTIONS_GHC -Wunused-top-binds #-}"+              , "module A (Foo(Foo)) where"+              , "data Foo = Foo {foo :: ()}"])+        (R 2 0 2 20)+        "Export ‘foo’"+        Nothing -- codeaction should not be available+    ]+  , testGroup "want suggestion"+    [ testSession "empty exports" $ template+        (T.unlines+              [ "{-# OPTIONS_GHC -Wunused-top-binds #-}"+              , "module A ("+              , ") where"+              , "foo = id"])+        (R 3 0 3 3)+        "Export ‘foo’"+        (Just $ T.unlines+              [ "{-# OPTIONS_GHC -Wunused-top-binds #-}" +              , "module A ("+              , "foo) where"+              , "foo = id"])+    , testSession "single line explicit exports" $ template+        (T.unlines+              [ "{-# OPTIONS_GHC -Wunused-top-binds #-}" +              , "module A (foo) where"+              , "foo = id"+              , "bar = foo"])+        (R 3 0 3 3)+        "Export ‘bar’"+        (Just $ T.unlines+              [ "{-# OPTIONS_GHC -Wunused-top-binds #-}" +              , "module A (foo,bar) where"+              , "foo = id"+              , "bar = foo"])+    , testSession "multi line explicit exports" $ template+        (T.unlines+              [ "{-# OPTIONS_GHC -Wunused-top-binds #-}" +              , "module A"+              , "  ("+              , "    foo) where"+              , "foo = id"+              , "bar = foo"])+        (R 5 0 5 3)+        "Export ‘bar’"+        (Just $ T.unlines+              [ "{-# OPTIONS_GHC -Wunused-top-binds #-}" +              , "module A"+              , "  ("+              , "    foo,bar) where"+              , "foo = id"+              , "bar = foo"])+    , testSession "export list ends in comma" $ template+        (T.unlines+              [ "{-# OPTIONS_GHC -Wunused-top-binds #-}" +              , "module A"+              , "  (foo,"+              , "  ) where"+              , "foo = id"+              , "bar = foo"])+        (R 4 0 4 3)+        "Export ‘bar’"+        (Just $ T.unlines+              [ "{-# OPTIONS_GHC -Wunused-top-binds #-}" +              , "module A"+              , "  (foo,"+              , "  bar) where"+              , "foo = id"+              , "bar = foo"])+    , testSession "unused pattern synonym" $ template+        (T.unlines+              [ "{-# OPTIONS_GHC -Wunused-top-binds #-}" +              , "{-# LANGUAGE PatternSynonyms #-}" +              , "module A () where"+              , "pattern Foo a <- (a, _)"])+        (R 3 0 3 10)+        "Export ‘Foo’"+        (Just $ T.unlines+              [ "{-# OPTIONS_GHC -Wunused-top-binds #-}" +              , "{-# LANGUAGE PatternSynonyms #-}" +              , "module A (pattern Foo) where"+              , "pattern Foo a <- (a, _)"])+    , testSession "unused data type" $ template+        (T.unlines+              [ "{-# OPTIONS_GHC -Wunused-top-binds #-}" +              , "module A () where"+              , "data Foo = Foo"])+        (R 2 0 2 7)+        "Export ‘Foo’"+        (Just $ T.unlines+              [ "{-# OPTIONS_GHC -Wunused-top-binds #-}" +              , "module A (Foo(..)) where"+              , "data Foo = Foo"])+    , testSession "unused newtype" $ template+        (T.unlines+              [ "{-# OPTIONS_GHC -Wunused-top-binds #-}" +              , "module A () where"+              , "newtype Foo = Foo ()"])+        (R 2 0 2 10)+        "Export ‘Foo’"+        (Just $ T.unlines+              [ "{-# OPTIONS_GHC -Wunused-top-binds #-}" +              , "module A (Foo(..)) where"+              , "newtype Foo = Foo ()"])+    , testSession "unused type synonym" $ template+        (T.unlines+              [ "{-# OPTIONS_GHC -Wunused-top-binds #-}" +              , "module A () where"+              , "type Foo = ()"])+        (R 2 0 2 7)+        "Export ‘Foo’"+        (Just $ T.unlines+              [ "{-# OPTIONS_GHC -Wunused-top-binds #-}" +              , "module A (Foo) where"+              , "type Foo = ()"])+    , testSession "unused type family" $ template+        (T.unlines+              [ "{-# OPTIONS_GHC -Wunused-top-binds #-}" +              , "{-# LANGUAGE TypeFamilies #-}" +              , "module A () where"+              , "type family Foo p"])+        (R 3 0 3 15)+        "Export ‘Foo’"+        (Just $ T.unlines+              [ "{-# OPTIONS_GHC -Wunused-top-binds #-}" +              , "{-# LANGUAGE TypeFamilies #-}" +              , "module A (Foo(..)) where"+              , "type family Foo p"])+    , testSession "unused typeclass" $ template+        (T.unlines+              [ "{-# OPTIONS_GHC -Wunused-top-binds #-}" +              , "module A () where"+              , "class Foo a"])+        (R 2 0 2 8)+        "Export ‘Foo’"+        (Just $ T.unlines+              [ "{-# OPTIONS_GHC -Wunused-top-binds #-}" +              , "module A (Foo(..)) where"+              , "class Foo a"])+    , testSession "infix" $ template+        (T.unlines+              [ "{-# OPTIONS_GHC -Wunused-top-binds #-}" +              , "module A () where"+              , "a `f` b = ()"])+        (R 2 0 2 11)+        "Export ‘f’"+        (Just $ T.unlines+              [ "{-# OPTIONS_GHC -Wunused-top-binds #-}" +              , "module A (f) where"+              , "a `f` b = ()"])+    ]+  ]+    where+      template initialContent range expectedAction expectedContents = do+        doc <- createDoc "A.hs" "haskell" initialContent+        _ <- waitForDiagnostics+        actions <- getCodeActions doc range+        case expectedContents of+          Just content -> do+            action <- liftIO $ pickActionWithTitle expectedAction actions+            executeCodeAction action+            contentAfterAction <- documentContents doc+            liftIO $ content @=? contentAfterAction+          Nothing ->+            liftIO $ [_title | CACodeAction CodeAction{_title} <- actions, _title == expectedAction ] @?= []++addSigLensesTests :: TestTree+addSigLensesTests = let+  missing = "{-# OPTIONS_GHC -Wmissing-signatures -Wmissing-pattern-synonym-signatures -Wunused-matches #-}"+  notMissing = "{-# OPTIONS_GHC -Wunused-matches #-}"+  moduleH = "{-# LANGUAGE PatternSynonyms #-}\nmodule Sigs where"+  other = T.unlines ["f :: Integer -> Integer", "f x = 3"]+  before  withMissing def+    = T.unlines $ (if withMissing then (missing :) else (notMissing :)) [moduleH, def, other]+  after'  withMissing def sig+    = T.unlines $ (if withMissing then (missing :) else (notMissing :)) [moduleH, sig, def, other]++  sigSession withMissing def sig = testSession (T.unpack def) $ do+    let originalCode = before withMissing def+    let expectedCode = after' withMissing def sig+    doc <- createDoc "Sigs.hs" "haskell" originalCode+    [CodeLens {_command = Just c}] <- getCodeLenses doc+    executeCommand c+    modifiedCode <- getDocumentEdit doc+    liftIO $ expectedCode @=? modifiedCode+  in+  testGroup "add signature"+    [ testGroup title+      [ sigSession enableWarnings "abc = True"              "abc :: Bool"+      , sigSession enableWarnings "foo a b = a + b"         "foo :: Num a => a -> a -> a"+      , sigSession enableWarnings "bar a b = show $ a + b"  "bar :: (Show a, Num a) => a -> a -> String"+      , sigSession enableWarnings "(!!!) a b = a > b"       "(!!!) :: Ord a => a -> a -> Bool"+      , sigSession enableWarnings "a >>>> b = a + b"        "(>>>>) :: Num a => a -> a -> a"+      , sigSession enableWarnings "a `haha` b = a b"        "haha :: (t1 -> t2) -> t1 -> t2"+      , sigSession enableWarnings "pattern Some a = Just a" "pattern Some :: a -> Maybe a"+      ]+      | (title, enableWarnings) <-+        [("with warnings enabled", True)+        ,("with warnings disabled", False)+        ]+    ]++checkDefs :: [Location] -> Session [Expect] -> Session ()+checkDefs defs mkExpectations = traverse_ check =<< mkExpectations where++  check (ExpectRange expectedRange) = do+    assertNDefinitionsFound 1 defs+    assertRangeCorrect (head defs) expectedRange+  check (ExpectLocation expectedLocation) = do+    assertNDefinitionsFound 1 defs+    liftIO $ do+      canonActualLoc <- canonicalizeLocation (head defs)+      canonExpectedLoc <- canonicalizeLocation expectedLocation+      canonActualLoc @?= canonExpectedLoc+  check ExpectNoDefinitions = do+    assertNDefinitionsFound 0 defs+  check ExpectExternFail = liftIO $ assertFailure "Expecting to fail to find in external file"+  check _ = pure () -- all other expectations not relevant to getDefinition++  assertNDefinitionsFound :: Int -> [a] -> Session ()+  assertNDefinitionsFound n defs = liftIO $ assertEqual "number of definitions" n (length defs)++  assertRangeCorrect Location{_range = foundRange} expectedRange =+    liftIO $ expectedRange @=? foundRange++canonicalizeLocation :: Location -> IO Location+canonicalizeLocation (Location uri range) = Location <$> canonicalizeUri uri <*> pure range++findDefinitionAndHoverTests :: TestTree+findDefinitionAndHoverTests = let++  tst (get, check) pos targetRange title = testSessionWithExtraFiles "hover" title $ \dir -> do++    -- Dirty the cache to check that definitions work even in the presence of iface files+    liftIO $ runInDir dir $ do+      let fooPath = dir </> "Foo.hs"+      fooSource <- liftIO $ readFileUtf8 fooPath+      fooDoc <- createDoc fooPath "haskell" fooSource+      _ <- getHover fooDoc $ Position 4 3+      closeDoc fooDoc++    doc <- openTestDataDoc (dir </> sourceFilePath)+    found <- get doc pos+    check found targetRange++++  checkHover :: Maybe Hover -> Session [Expect] -> Session ()+  checkHover hover expectations = traverse_ check =<< expectations where++    check expected =+      case hover of+        Nothing -> unless (expected == ExpectNoHover) $ liftIO $ assertFailure "no hover found"+        Just Hover{_contents = (HoverContents MarkupContent{_value = msg})+                  ,_range    = rangeInHover } ->+          case expected of+            ExpectRange  expectedRange -> checkHoverRange expectedRange rangeInHover msg+            ExpectHoverRange expectedRange -> checkHoverRange expectedRange rangeInHover msg+            ExpectHoverText snippets -> liftIO $ traverse_ (`assertFoundIn` msg) snippets+            ExpectNoHover -> liftIO $ assertFailure $ "Expected no hover but got " <> show hover+            _ -> pure () -- all other expectations not relevant to hover+        _ -> liftIO $ assertFailure $ "test not expecting this kind of hover info" <> show hover++  extractLineColFromHoverMsg :: T.Text -> [T.Text]+  extractLineColFromHoverMsg = T.splitOn ":" . head . T.splitOn "*" . last . T.splitOn (sourceFileName <> ":")++  checkHoverRange :: Range -> Maybe Range -> T.Text -> Session ()+  checkHoverRange expectedRange rangeInHover msg =+    let+      lineCol = extractLineColFromHoverMsg msg+      -- looks like hovers use 1-based numbering while definitions use 0-based+      -- turns out that they are stored 1-based in RealSrcLoc by GHC itself.+      adjust Position{_line = l, _character = c} =+        Position{_line = l + 1, _character = c + 1}+    in+    case map (read . T.unpack) lineCol of+      [l,c] -> liftIO $ (adjust $ _start expectedRange) @=? Position l c+      _     -> liftIO $ assertFailure $+        "expected: " <> show ("[...]" <> sourceFileName <> ":<LINE>:<COL>**[...]", Just expectedRange) <>+        "\n but got: " <> show (msg, rangeInHover)++  assertFoundIn :: T.Text -> T.Text -> Assertion+  assertFoundIn part whole = assertBool+    (T.unpack $ "failed to find: `" <> part <> "` in hover message:\n" <> whole)+    (part `T.isInfixOf` whole)++  sourceFilePath = T.unpack sourceFileName+  sourceFileName = "GotoHover.hs"++  mkFindTests tests = testGroup "get"+    [ testGroup "definition" $ mapMaybe fst tests+    , testGroup "hover"      $ mapMaybe snd tests+    , checkFileCompiles sourceFilePath+    , testGroup "type-definition" typeDefinitionTests ]++  typeDefinitionTests = [ tst (getTypeDefinitions, checkDefs) aaaL14 (pure tcData) "Saturated data con"+                        , tst (getTypeDefinitions, checkDefs) opL16 (pure [ExpectNoDefinitions]) "Polymorphic variable"]++  test runDef runHover look expect = testM runDef runHover look (return expect)++  testM runDef runHover look expect title =+    ( runDef   $ tst def   look expect title+    , runHover $ tst hover look expect title ) where+      def   = (getDefinitions, checkDefs)+      hover = (getHover      , checkHover)++  -- search locations            expectations on results+  fffL4  = _start fffR     ;  fffR = mkRange 8  4    8  7 ; fff  = [ExpectRange fffR]+  fffL8  = Position 12  4  ;+  fffL14 = Position 18  7  ;+  aaaL14 = Position 18 20  ;  aaa    = [mkR  11  0   11  3]+  dcL7   = Position 11 11  ;  tcDC   = [mkR   7 23    9 16]+  dcL12  = Position 16 11  ;+  xtcL5  = Position  9 11  ;  xtc    = [ExpectExternFail,   ExpectHoverText ["Int", "Defined in ‘GHC.Types’"]]+  tcL6   = Position 10 11  ;  tcData = [mkR   7  0    9 16, ExpectHoverText ["TypeConstructor", "GotoHover.hs:8:1"]]+  vvL16  = Position 20 12  ;  vv     = [mkR  20  4   20  6]+  opL16  = Position 20 15  ;  op     = [mkR  21  2   21  4]+  opL18  = Position 22 22  ;  opp    = [mkR  22 13   22 17]+  aL18   = Position 22 20  ;  apmp   = [mkR  22 10   22 11]+  b'L19  = Position 23 13  ;  bp     = [mkR  23  6   23  7]+  xvL20  = Position 24  8  ;  xvMsg  = [ExpectExternFail,   ExpectHoverText ["Data.Text.pack", ":: String -> Text"]]+  clL23  = Position 27 11  ;  cls    = [mkR  25  0   26 20, ExpectHoverText ["MyClass", "GotoHover.hs:26:1"]]+  clL25  = Position 29  9+  eclL15 = Position 19  8  ;  ecls   = [ExpectExternFail, ExpectHoverText ["Num", "Defined in ‘GHC.Num’"]]+  dnbL29 = Position 33 18  ;  dnb    = [ExpectHoverText [":: ()"],   mkR  33 12   33 21]+  dnbL30 = Position 34 23+  lcbL33 = Position 37 26  ;  lcb    = [ExpectHoverText [":: Char"], mkR  37 26   37 27]+  lclL33 = Position 37 22+  mclL36 = Position 40  1  ;  mcl    = [mkR  40  0   40 14]+  mclL37 = Position 41  1+  spaceL37 = Position 41  24 ; space = [ExpectNoDefinitions, ExpectHoverText [":: Char"]]+  docL41 = Position 45  1  ;  doc    = [ExpectHoverText ["Recognizable docs: kpqz"]]+                           ;  constr = [ExpectHoverText ["Monad m"]]+  eitL40 = Position 44 28  ;  kindE  = [ExpectHoverText [":: * -> * -> *\n"]]+  intL40 = Position 44 34  ;  kindI  = [ExpectHoverText [":: *\n"]]+  tvrL40 = Position 44 37  ;  kindV  = [ExpectHoverText [":: * -> *\n"]]+  intL41 = Position 45 20  ;  litI   = [ExpectHoverText ["7518"]]+  chrL36 = Position 41 24  ;  litC   = [ExpectHoverText ["'f'"]]+  txtL8  = Position 12 14  ;  litT   = [ExpectHoverText ["\"dfgy\""]]+  lstL43 = Position 47 12  ;  litL   = [ExpectHoverText ["[8391 :: Int, 6268]"]]+  outL45 = Position 49  3  ;  outSig = [ExpectHoverText ["outer", "Bool"], mkR 46 0 46 5]+  innL48 = Position 52  5  ;  innSig = [ExpectHoverText ["inner", "Char"], mkR 49 2 49 7]+  cccL17 = Position 17 11  ;  docLink = [ExpectHoverText ["[Documentation](file://"]]+#if MIN_GHC_API_VERSION(8,6,0)+  imported = Position 56 13 ; importedSig = getDocUri "Foo.hs" >>= \foo -> return [ExpectHoverText ["foo", "Foo", "Haddock"], mkL foo 5 0 5 3]+  reexported = Position 55 14 ; reexportedSig = getDocUri "Bar.hs" >>= \bar -> return [ExpectHoverText ["Bar", "Bar", "Haddock"], mkL bar 3 0 3 14]+#else+  imported = Position 56 13 ; importedSig = getDocUri "Foo.hs" >>= \foo -> return [ExpectHoverText ["foo", "Foo"], mkL foo 5 0 5 3]+  reexported = Position 55 14 ; reexportedSig = getDocUri "Bar.hs" >>= \bar -> return [ExpectHoverText ["Bar", "Bar"], mkL bar 3 0 3 14]+#endif+  in+  mkFindTests+  --      def    hover  look       expect+  [ test  yes    yes    fffL4      fff           "field in record definition"+  , test  broken broken fffL8      fff           "field in record construction     #71"+  , test  yes    yes    fffL14     fff           "field name used as accessor"          -- 120 in Calculate.hs+  , test  yes    yes    aaaL14     aaa           "top-level name"                       -- 120+  , test  yes    yes    dcL7       tcDC          "data constructor record         #247"+  , test  yes    yes    dcL12      tcDC          "data constructor plain"               -- 121+  , test  yes    yes    tcL6       tcData        "type constructor                #248" -- 147+  , test  broken yes    xtcL5      xtc           "type constructor external   #248,249"+  , test  broken yes    xvL20      xvMsg         "value external package          #249" -- 120+  , test  yes    yes    vvL16      vv            "plain parameter"                      -- 120+  , test  yes    yes    aL18       apmp          "pattern match name"                   -- 120+  , test  yes    yes    opL16      op            "top-level operator"                   -- 120, 123+  , test  yes    yes    opL18      opp           "parameter operator"                   -- 120+  , test  yes    yes    b'L19      bp            "name in backticks"                    -- 120+  , test  yes    yes    clL23      cls           "class in instance declaration   #250"+  , test  yes    yes    clL25      cls           "class in signature              #250" -- 147+  , test  broken yes    eclL15     ecls          "external class in signature #249,250"+  , test  yes    yes    dnbL29     dnb           "do-notation   bind"                   -- 137+  , test  yes    yes    dnbL30     dnb           "do-notation lookup"+  , test  yes    yes    lcbL33     lcb           "listcomp   bind"                      -- 137+  , test  yes    yes    lclL33     lcb           "listcomp lookup"+  , test  yes    yes    mclL36     mcl           "top-level fn 1st clause"+  , test  yes    yes    mclL37     mcl           "top-level fn 2nd clause         #246"+  , test  yes    yes    spaceL37   space        "top-level fn on space #315"+  , test  no     broken docL41     doc           "documentation                     #7"+  , test  no     yes    eitL40     kindE         "kind of Either                  #273"+  , test  no     yes    intL40     kindI         "kind of Int                     #273"+  , test  no     broken tvrL40     kindV         "kind of (* -> *) type variable  #273"+  , test  no     yes    intL41     litI          "literal Int  in hover info      #274"+  , test  no     yes    chrL36     litC          "literal Char in hover info      #274"+  , test  no     yes    txtL8      litT          "literal Text in hover info      #274"+  , test  no     yes    lstL43     litL          "literal List in hover info      #274"+  , test  no     yes    docL41     constr        "type constraint in hover info   #283"+  , test  broken broken outL45     outSig        "top-level signature             #310"+  , test  broken broken innL48     innSig        "inner     signature             #310"+  , test  no     yes    cccL17     docLink       "Haddock html links"+  , testM yes    yes    imported   importedSig   "Imported symbol"+  , testM yes    yes    reexported reexportedSig "Imported symbol (reexported)"+  ]+  where yes, broken :: (TestTree -> Maybe TestTree)+        yes    = Just -- test should run and pass+        broken = Just . (`xfail` "known broken")+        no = const Nothing -- don't run this test at all++checkFileCompiles :: FilePath -> TestTree+checkFileCompiles fp =+  testSessionWithExtraFiles "hover" ("Does " ++ fp ++ " compile") $ \dir -> do+    void (openTestDataDoc (dir </> fp))+    expectNoMoreDiagnostics 0.5++++pluginTests :: TestTree+pluginTests = (`xfail8101` "known broken (#556)")+            $ testSessionWait "plugins" $ do+  let content =+        T.unlines+          [ "{-# OPTIONS_GHC -fplugin GHC.TypeLits.KnownNat.Solver #-}"+          , "{-# LANGUAGE DataKinds, ScopedTypeVariables, TypeOperators #-}"+          , "module Testing where"+          , "import Data.Proxy"+          , "import GHC.TypeLits"+          -- This function fails without plugins being initialized.+          , "f :: forall n. KnownNat n => Proxy n -> Integer"+          , "f _ = natVal (Proxy :: Proxy n) + natVal (Proxy :: Proxy (n+2))"+          , "foo :: Int -> Int -> Int"+          , "foo a b = a + c"+          ]+  _ <- createDoc "Testing.hs" "haskell" content+  expectDiagnostics+    [ ( "Testing.hs",+        [(DsError, (8, 14), "Variable not in scope: c")]+      )+    ]++cppTests :: TestTree+cppTests =+  testGroup "cpp"+    [ testCase "cpp-error" $ do+        let content =+              T.unlines+                [ "{-# LANGUAGE CPP #-}",+                  "module Testing where",+                  "#ifdef FOO",+                  "foo = 42"+                ]+        -- The error locations differ depending on which C-preprocessor is used.+        -- Some give the column number and others don't (hence -1). Assert either+        -- of them.+        (run $ expectError content (2, -1))+          `catch` ( \e -> do+                      let _ = e :: HUnitFailure+                      run $ expectError content (2, 1)+                  )+    , testSessionWait "cpp-ghcide" $ do+        _ <- createDoc "A.hs" "haskell" $ T.unlines+          ["{-# LANGUAGE CPP #-}"+          ,"main ="+          ,"#ifdef __GHCIDE__"+          ,"  worked"+          ,"#else"+          ,"  failed"+          ,"#endif"+          ]+        expectDiagnostics [("A.hs", [(DsError, (3, 2), "Variable not in scope: worked")])]+    ]+  where+    expectError :: T.Text -> Cursor -> Session ()+    expectError content cursor = do+      _ <- createDoc "Testing.hs" "haskell" content+      expectDiagnostics+        [ ( "Testing.hs",+            [(DsError, cursor, "error: unterminated")]+          )+        ]+      expectNoMoreDiagnostics 0.5++preprocessorTests :: TestTree+preprocessorTests = testSessionWait "preprocessor" $ do+  let content =+        T.unlines+          [ "{-# OPTIONS_GHC -F -pgmF=ghcide-test-preprocessor #-}"+          , "module Testing where"+          , "y = x + z" -- plugin replaces x with y, making this have only one diagnostic+          ]+  _ <- createDoc "Testing.hs" "haskell" content+  expectDiagnostics+    [ ( "Testing.hs",+        [(DsError, (2, 8), "Variable not in scope: z")]+      )+    ]+++safeTests :: TestTree+safeTests =+  testGroup+    "SafeHaskell"+    [ -- Test for https://github.com/digital-asset/ghcide/issues/424+      testSessionWait "load" $ do+        let sourceA =+              T.unlines+                ["{-# LANGUAGE Trustworthy #-}"+                ,"module A where"+                ,"import System.IO.Unsafe"+                ,"import System.IO"+                ,"trustWorthyId :: a -> a"+                ,"trustWorthyId i = unsafePerformIO $ do"+                ,"  putStrLn \"I'm safe\""+                ,"  return i"]+            sourceB =+              T.unlines+                ["{-# LANGUAGE Safe #-}"+                ,"module B where"+                ,"import A"+                ,"safeId :: a -> a"+                ,"safeId = trustWorthyId"+                ]++        _ <- createDoc "A.hs" "haskell" sourceA+        _ <- createDoc "B.hs" "haskell" sourceB+        expectNoMoreDiagnostics 1 ]++thTests :: TestTree+thTests =+  testGroup+    "TemplateHaskell"+    [ -- Test for https://github.com/digital-asset/ghcide/pull/212+      testSessionWait "load" $ do+        let sourceA =+              T.unlines+                [ "{-# LANGUAGE PackageImports #-}",+                  "{-# LANGUAGE TemplateHaskell #-}",+                  "module A where",+                  "import \"template-haskell\" Language.Haskell.TH",+                  "a :: Integer",+                  "a = $(litE $ IntegerL 3)"+                ]+            sourceB =+              T.unlines+                [ "{-# LANGUAGE PackageImports #-}",+                  "{-# LANGUAGE TemplateHaskell #-}",+                  "module B where",+                  "import A",+                  "import \"template-haskell\" Language.Haskell.TH",+                  "b :: Integer",+                  "b = $(litE $ IntegerL $ a) + n"+                ]+        _ <- createDoc "A.hs" "haskell" sourceA+        _ <- createDoc "B.hs" "haskell" sourceB+        expectDiagnostics [ ( "B.hs", [(DsError, (6, 29), "Variable not in scope: n")] ) ]+    , testSessionWait "newtype-closure" $ do+        let sourceA =+              T.unlines+                [ "{-# LANGUAGE DeriveDataTypeable #-}"+                  ,"{-# LANGUAGE TemplateHaskell #-}"+                  ,"module A (a) where"+                  ,"import Data.Data"+                  ,"import Language.Haskell.TH"+                  ,"newtype A = A () deriving (Data)"+                  ,"a :: ExpQ"+                  ,"a = [| 0 |]"]+        let sourceB =+              T.unlines+                [ "{-# LANGUAGE TemplateHaskell #-}"+                ,"module B where"+                ,"import A"+                ,"b :: Int"+                ,"b = $( a )" ]+        _ <- createDoc "A.hs" "haskell" sourceA+        _ <- createDoc "B.hs" "haskell" sourceB+        return ()+    , thReloadingTest `xfail` "expect broken (#672)"+    ]++-- | test that TH is reevaluated on typecheck+thReloadingTest :: TestTree+thReloadingTest = testCase "reloading-th-test" $ withoutStackEnv $ runWithExtraFiles "TH" $ \dir -> do+    let aPath = dir </> "THA.hs"+        bPath = dir </> "THB.hs"+        cPath = dir </> "THC.hs"++    aSource <- liftIO $ readFileUtf8 aPath --  th = [d|a :: ()|]+    bSource <- liftIO $ readFileUtf8 bPath --  $th+    cSource <- liftIO $ readFileUtf8 cPath --  c = a :: ()++    adoc <- createDoc aPath "haskell" aSource+    bdoc <- createDoc bPath "haskell" bSource+    cdoc <- createDoc cPath "haskell" cSource++    expectDiagnostics [("THB.hs", [(DsWarning, (4,0), "Top-level binding")])]++    -- Change th from () to Bool+    let aSource' = T.unlines $ init (T.lines aSource) ++ ["th_a = [d| a = False|]"]+    changeDoc adoc [TextDocumentContentChangeEvent Nothing Nothing aSource']+    -- generate an artificial warning to avoid timing out if the TH change does not propagate+    changeDoc cdoc [TextDocumentContentChangeEvent Nothing Nothing $ cSource <> "\nfoo=()"]++    -- Check that the change propagates to C+    expectDiagnostics+        [("THC.hs", [(DsError, (4, 4), "Couldn't match expected type '()' with actual type 'Bool'")])+        ,("THC.hs", [(DsWarning, (6,0), "Top-level binding")])+        ]++    closeDoc adoc+    closeDoc bdoc+    closeDoc cdoc+++completionTests :: TestTree+completionTests+  = testGroup "completion"+    [ testGroup "non local" nonLocalCompletionTests+    , testGroup "local" localCompletionTests+    , testGroup "other" otherCompletionTests+    ]++completionTest :: String -> [T.Text] -> Position -> [(T.Text, CompletionItemKind, Bool, Bool)] -> TestTree+completionTest name src pos expected = testSessionWait name $ do+    docId <- createDoc "A.hs" "haskell" (T.unlines src)+    compls <- getCompletions docId pos+    let compls' = [ (_label, _kind) | CompletionItem{..} <- compls]+    liftIO $ do+        compls' @?= [ (l, Just k) | (l,k,_,_) <- expected]+        forM_ (zip compls expected) $ \(CompletionItem{..}, (_,_,expectedSig, expectedDocs)) -> do+            when expectedSig $+                assertBool ("Missing type signature: " <> T.unpack _label) (isJust _detail)+            when expectedDocs $+                assertBool ("Missing docs: " <> T.unpack _label) (isJust _documentation)++localCompletionTests :: [TestTree]+localCompletionTests = [+    completionTest+        "variable"+        ["bar = xx", "-- | haddock", "xxx :: ()", "xxx = ()", "-- | haddock", "data Xxx = XxxCon"]+        (Position 0 8)+        [("xxx", CiFunction, True, True),+         ("XxxCon", CiConstructor, False, True)+        ],+    completionTest+        "constructor"+        ["bar = xx", "-- | haddock", "xxx :: ()", "xxx = ()", "-- | haddock", "data Xxx = XxxCon"]+        (Position 0 8)+        [("xxx", CiFunction, True, True),+         ("XxxCon", CiConstructor, False, True)+        ],+    completionTest+        "class method"+        ["bar = xx", "class Xxx a where", "-- | haddock", "xxx :: ()", "xxx = ()"]+        (Position 0 8)+        [("xxx", CiFunction, True, True)],+    completionTest+        "type"+        ["bar :: Xx", "xxx = ()", "-- | haddock", "data Xxx = XxxCon"]+        (Position 0 9)+        [("Xxx", CiStruct, False, True)],+    completionTest+        "class"+        ["bar :: Xx", "xxx = ()", "-- | haddock", "class Xxx a"]+        (Position 0 9)+        [("Xxx", CiClass, False, True)]+    ]++nonLocalCompletionTests :: [TestTree]+nonLocalCompletionTests =+  [ completionTest+      "variable"+      ["module A where", "f = hea"]+      (Position 1 7)+      [("head", CiFunction, True, True)],+    completionTest+      "constructor"+      ["module A where", "f = Tru"]+      (Position 1 7)+      [ ("True", CiConstructor, True, True),+        ("truncate", CiFunction, True, True)+      ],+    completionTest+      "type"+      ["{-# OPTIONS_GHC -Wall #-}", "module A () where", "f :: Bo", "f = True"]+      (Position 2 7)+      [ ("Bounded", CiClass, True, True),+        ("Bool", CiStruct, True, True)+      ],+    completionTest+      "qualified"+      ["{-# OPTIONS_GHC -Wunused-binds #-}", "module A () where", "f = Prelude.hea"]+      (Position 2 15)+      [ ("head", CiFunction, True, True)+      ]+  ]++otherCompletionTests :: [TestTree]+otherCompletionTests = [+    completionTest+      "keyword"+      ["module A where", "f = newty"]+      (Position 1 9)+      [("newtype", CiKeyword, False, False)],+    completionTest+      "type context"+      [ "{-# OPTIONS_GHC -Wunused-binds #-}",+        "module A () where",+        "f = f",+        "g :: Intege"+      ]+      -- At this point the module parses but does not typecheck.+      -- This should be sufficient to detect that we are in a+      -- type context and only show the completion to the type.+      (Position 3 11)+      [("Integer", CiStruct, True, True)]+  ]++outlineTests :: TestTree+outlineTests = testGroup+  "outline"+  [ testSessionWait "type class" $ do+    let source = T.unlines ["module A where", "class A a where a :: a -> Bool"]+    docId   <- createDoc "A.hs" "haskell" source+    symbols <- getDocumentSymbols docId+    liftIO $ symbols @?= Left+      [ moduleSymbol+          "A"+          (R 0 7 0 8)+          [ classSymbol "A a"+                        (R 1 0 1 30)+                        [docSymbol' "a" SkMethod (R 1 16 1 30) (R 1 16 1 17)]+          ]+      ]+  , testSessionWait "type class instance " $ do+    let source = T.unlines ["class A a where", "instance A () where"]+    docId   <- createDoc "A.hs" "haskell" source+    symbols <- getDocumentSymbols docId+    liftIO $ symbols @?= Left+      [ classSymbol "A a" (R 0 0 0 15) []+      , docSymbol "A ()" SkInterface (R 1 0 1 19)+      ]+  , testSessionWait "type family" $ do+    let source = T.unlines ["{-# language TypeFamilies #-}", "type family A"]+    docId   <- createDoc "A.hs" "haskell" source+    symbols <- getDocumentSymbols docId+    liftIO $ symbols @?= Left [docSymbolD "A" "type family" SkClass (R 1 0 1 13)]+  , testSessionWait "type family instance " $ do+    let source = T.unlines+          [ "{-# language TypeFamilies #-}"+          , "type family A a"+          , "type instance A () = ()"+          ]+    docId   <- createDoc "A.hs" "haskell" source+    symbols <- getDocumentSymbols docId+    liftIO $ symbols @?= Left+      [ docSymbolD "A a"   "type family" SkClass     (R 1 0 1 15)+      , docSymbol "A ()" SkInterface (R 2 0 2 23)+      ]+  , testSessionWait "data family" $ do+    let source = T.unlines ["{-# language TypeFamilies #-}", "data family A"]+    docId   <- createDoc "A.hs" "haskell" source+    symbols <- getDocumentSymbols docId+    liftIO $ symbols @?= Left [docSymbolD "A" "data family" SkClass (R 1 0 1 11)]+  , testSessionWait "data family instance " $ do+    let source = T.unlines+          [ "{-# language TypeFamilies #-}"+          , "data family A a"+          , "data instance A () = A ()"+          ]+    docId   <- createDoc "A.hs" "haskell" source+    symbols <- getDocumentSymbols docId+    liftIO $ symbols @?= Left+      [ docSymbolD "A a"   "data family" SkClass     (R 1 0 1 11)+      , docSymbol "A ()" SkInterface (R 2 0 2 25)+      ]+  , testSessionWait "constant" $ do+    let source = T.unlines ["a = ()"]+    docId   <- createDoc "A.hs" "haskell" source+    symbols <- getDocumentSymbols docId+    liftIO $ symbols @?= Left+      [docSymbol "a" SkFunction (R 0 0 0 6)]+  , testSessionWait "pattern" $ do+    let source = T.unlines ["Just foo = Just 21"]+    docId   <- createDoc "A.hs" "haskell" source+    symbols <- getDocumentSymbols docId+    liftIO $ symbols @?= Left+      [docSymbol "Just foo" SkFunction (R 0 0 0 18)]+  , testSessionWait "pattern with type signature" $ do+    let source = T.unlines ["{-# language ScopedTypeVariables #-}", "a :: () = ()"]+    docId   <- createDoc "A.hs" "haskell" source+    symbols <- getDocumentSymbols docId+    liftIO $ symbols @?= Left+      [docSymbol "a :: ()" SkFunction (R 1 0 1 12)]+  , testSessionWait "function" $ do+    let source = T.unlines ["a x = ()"]+    docId   <- createDoc "A.hs" "haskell" source+    symbols <- getDocumentSymbols docId+    liftIO $ symbols @?= Left [docSymbol "a" SkFunction (R 0 0 0 8)]+  , testSessionWait "type synonym" $ do+    let source = T.unlines ["type A = Bool"]+    docId   <- createDoc "A.hs" "haskell" source+    symbols <- getDocumentSymbols docId+    liftIO $ symbols @?= Left+      [docSymbol' "A" SkTypeParameter (R 0 0 0 13) (R 0 5 0 6)]+  , testSessionWait "datatype" $ do+    let source = T.unlines ["data A = C"]+    docId   <- createDoc "A.hs" "haskell" source+    symbols <- getDocumentSymbols docId+    liftIO $ symbols @?= Left+      [ docSymbolWithChildren "A"+                              SkStruct+                              (R 0 0 0 10)+                              [docSymbol "C" SkConstructor (R 0 9 0 10)]+      ]+  , testSessionWait "record fields" $ do+    let source = T.unlines ["data A = B {", "  x :: Int", "  , y :: Int}"]+    docId   <- createDoc "A.hs" "haskell" source+    symbols <- getDocumentSymbols docId+    liftIO $ symbols @=? Left+      [ docSymbolWithChildren "A" SkStruct (R 0 0 2 13)+          [ docSymbolWithChildren' "B" SkConstructor (R 0 9 2 13) (R 0 9 0 10)+            [ docSymbol "x" SkField (R 1 2 1 3)+            , docSymbol "y" SkField (R 2 4 2 5)+            ]+          ]+      ]+  , testSessionWait "import" $ do+    let source = T.unlines ["import Data.Maybe"]+    docId   <- createDoc "A.hs" "haskell" source+    symbols <- getDocumentSymbols docId+    liftIO $ symbols @?= Left+      [docSymbolWithChildren "imports"+                             SkModule+                             (R 0 0 0 17)+                             [ docSymbol "import Data.Maybe" SkModule (R 0 0 0 17)+                             ]+      ]+  , testSessionWait "multiple import" $ do+    let source = T.unlines ["", "import Data.Maybe", "", "import Control.Exception", ""]+    docId   <- createDoc "A.hs" "haskell" source+    symbols <- getDocumentSymbols docId+    liftIO $ symbols @?= Left+      [docSymbolWithChildren "imports"+                             SkModule+                             (R 1 0 3 24)+                             [ docSymbol "import Data.Maybe" SkModule (R 1 0 1 17)+                             , docSymbol "import Control.Exception" SkModule (R 3 0 3 24)+                             ]+      ]+  , testSessionWait "foreign import" $ do+    let source = T.unlines+          [ "{-# language ForeignFunctionInterface #-}"+          , "foreign import ccall \"a\" a :: Int"+          ]+    docId   <- createDoc "A.hs" "haskell" source+    symbols <- getDocumentSymbols docId+    liftIO $ symbols @?= Left [docSymbolD "a" "import" SkObject (R 1 0 1 33)]+  , testSessionWait "foreign export" $ do+    let source = T.unlines+          [ "{-# language ForeignFunctionInterface #-}"+          , "foreign export ccall odd :: Int -> Bool"+          ]+    docId   <- createDoc "A.hs" "haskell" source+    symbols <- getDocumentSymbols docId+    liftIO $ symbols @?= Left [docSymbolD "odd" "export" SkObject (R 1 0 1 39)]+  ]+ where+  docSymbol name kind loc =+    DocumentSymbol name Nothing kind Nothing loc loc Nothing+  docSymbol' name kind loc selectionLoc =+    DocumentSymbol name Nothing kind Nothing loc selectionLoc Nothing+  docSymbolD name detail kind loc =+    DocumentSymbol name (Just detail) kind Nothing loc loc Nothing+  docSymbolWithChildren name kind loc cc =+    DocumentSymbol name Nothing kind Nothing loc loc (Just $ List cc)+  docSymbolWithChildren' name kind loc selectionLoc cc =+    DocumentSymbol name Nothing kind Nothing loc selectionLoc (Just $ List cc)+  moduleSymbol name loc cc = DocumentSymbol name+                                            Nothing+                                            SkFile+                                            Nothing+                                            (R 0 0 maxBound 0)+                                            loc+                                            (Just $ List cc)+  classSymbol name loc cc = DocumentSymbol name+                                           (Just "class")+                                           SkClass+                                           Nothing+                                           loc+                                           loc+                                           (Just $ List cc)++pattern R :: Int -> Int -> Int -> Int -> Range+pattern R x y x' y' = Range (Position x y) (Position x' y')++xfail :: TestTree -> String -> TestTree+xfail = flip expectFailBecause++xfail8101 :: TestTree -> String -> TestTree+#if MIN_GHC_API_VERSION(8,10,0)+xfail8101 = flip expectFailBecause+#else+xfail8101 t _ = t+#endif++expectFailCabal :: String -> TestTree -> TestTree+#ifdef STACK+expectFailCabal _ = id+#else+expectFailCabal = expectFailBecause+#endif++data Expect+  = ExpectRange Range -- Both gotoDef and hover should report this range+  | ExpectLocation Location+--  | ExpectDefRange Range -- Only gotoDef should report this range+  | ExpectHoverRange Range -- Only hover should report this range+  | ExpectHoverText [T.Text] -- the hover message must contain these snippets+  | ExpectExternFail -- definition lookup in other file expected to fail+  | ExpectNoDefinitions+  | ExpectNoHover+--  | ExpectExtern -- TODO: as above, but expected to succeed: need some more info in here, once we have some working examples+  deriving Eq++mkR :: Int -> Int -> Int -> Int -> Expect+mkR startLine startColumn endLine endColumn = ExpectRange $ mkRange startLine startColumn endLine endColumn++mkL :: Uri -> Int -> Int -> Int -> Int -> Expect+mkL uri startLine startColumn endLine endColumn = ExpectLocation $ Location uri $ mkRange startLine startColumn endLine endColumn++haddockTests :: TestTree+haddockTests+  = testGroup "haddock"+      [ testCase "Num" $ checkHaddock+          (unlines+             [ "However, '(+)' and '(*)' are"+             , "customarily expected to define a ring and have the following properties:"+             , ""+             , "[__Associativity of (+)__]: @(x + y) + z@ = @x + (y + z)@"+             , "[__Commutativity of (+)__]: @x + y@ = @y + x@"+             , "[__@fromInteger 0@ is the additive identity__]: @x + fromInteger 0@ = @x@"+             ]+          )+          (unlines+             [ ""+             , ""+             , "However,  `(+)`  and  `(*)`  are"+             , "customarily expected to define a ring and have the following properties: "+             , "+ ****Associativity of (+)****: `(x + y) + z`  =  `x + (y + z)`"+             , "+ ****Commutativity of (+)****: `x + y`  =  `y + x`"+             , "+ ****`fromInteger 0`  is the additive identity****: `x + fromInteger 0`  =  `x`"+             ]+          )+      , testCase "unsafePerformIO" $ checkHaddock+          (unlines+             [ "may require"+             , "different precautions:"+             , ""+             , "  * Use @{\\-\\# NOINLINE foo \\#-\\}@ as a pragma on any function @foo@"+             , "        that calls 'unsafePerformIO'.  If the call is inlined,"+             , "        the I\\/O may be performed more than once."+             , ""+             , "  * Use the compiler flag @-fno-cse@ to prevent common sub-expression"+             , "        elimination being performed on the module."+             , ""+             ]+          )+          (unlines+             [ ""+             , ""+             , "may require"+             , "different precautions: "+             , "+ Use  `{-# NOINLINE foo #-}`  as a pragma on any function  `foo` "+             , "  that calls  `unsafePerformIO` .  If the call is inlined,"+             , "  the I/O may be performed more than once."+             , ""+             , "+ Use the compiler flag  `-fno-cse`  to prevent common sub-expression"+             , "  elimination being performed on the module."+             , ""+             ]+          )+      ]+  where+    checkHaddock s txt = spanDocToMarkdownForTest s @?= txt++cradleTests :: TestTree+cradleTests = testGroup "cradle"+    [testGroup "dependencies" [sessionDepsArePickedUp]+    ,testGroup "loading" [loadCradleOnlyonce]+    ,testGroup "multi"   [simpleMultiTest, simpleMultiTest2]+    ]++loadCradleOnlyonce :: TestTree+loadCradleOnlyonce = testGroup "load cradle only once"+    [ testSession' "implicit" implicit+    , testSession' "direct"   direct+    ]+    where+        direct dir = do+            liftIO $ writeFileUTF8 (dir </> "hie.yaml")+                "cradle: {direct: {arguments: []}}"+            test dir+        implicit dir = test dir+        test _dir = do+            doc <- createDoc "B.hs" "haskell" "module B where\nimport Data.Foo"+            msgs <- someTill (skipManyTill anyMessage cradleLoadedMessage) (skipManyTill anyMessage (message @PublishDiagnosticsNotification))+            liftIO $ length msgs @?= 1+            changeDoc doc [TextDocumentContentChangeEvent Nothing Nothing "module B where\nimport Data.Maybe"]+            msgs <- manyTill (skipManyTill anyMessage cradleLoadedMessage) (skipManyTill anyMessage (message @PublishDiagnosticsNotification))+            liftIO $ length msgs @?= 0+            _ <- createDoc "A.hs" "haskell" "module A where\nimport LoadCradleBar"+            msgs <- manyTill (skipManyTill anyMessage cradleLoadedMessage) (skipManyTill anyMessage (message @PublishDiagnosticsNotification))+            liftIO $ length msgs @?= 0+++dependentFileTest :: TestTree+dependentFileTest = testGroup "addDependentFile"+    [testGroup "file-changed" [testSession' "test" test]+    ]+    where+      test dir = do+        -- If the file contains B then no type error+        -- otherwise type error+        liftIO $ writeFile (dir </> "dep-file.txt") "A"+        let fooContent = T.unlines+              [ "{-# LANGUAGE TemplateHaskell #-}"+              , "module Foo where"+              , "import Language.Haskell.TH.Syntax"+              , "foo :: Int"+              , "foo = 1 + $(do"+              , "               qAddDependentFile \"dep-file.txt\""+              , "               f <- qRunIO (readFile \"dep-file.txt\")"+              , "               if f == \"B\" then [| 1 |] else lift f)"+              ]+        let bazContent = T.unlines ["module Baz where", "import Foo"]+        _ <-createDoc "Foo.hs" "haskell" fooContent+        doc <- createDoc "Baz.hs" "haskell" bazContent+        expectDiagnostics+          [("Foo.hs", [(DsError, (4, 6), "Couldn't match expected type")])]+        -- Now modify the dependent file+        liftIO $ writeFile (dir </> "dep-file.txt") "B"+        let change = TextDocumentContentChangeEvent+              { _range = Just (Range (Position 2 0) (Position 2 6))+              , _rangeLength = Nothing+              , _text = "f = ()"+              }+        -- Modifying Baz will now trigger Foo to be rebuilt as well+        changeDoc doc [change]+        expectDiagnostics [("Foo.hs", [])]+++cradleLoadedMessage :: Session FromServerMessage+cradleLoadedMessage = satisfy $ \case+        NotCustomServer (NotificationMessage _ (CustomServerMethod m) _) -> m == cradleLoadedMethod+        _ -> False++cradleLoadedMethod :: T.Text+cradleLoadedMethod = "ghcide/cradle/loaded"++-- Stack sets this which trips up cabal in the multi-component tests.+-- However, our plugin tests rely on those env vars so we unset it locally.+withoutStackEnv :: IO a -> IO a+withoutStackEnv s =+  bracket+    (mapM getEnv vars >>= \prevState -> mapM_ unsetEnv vars >> pure prevState)+    (\prevState -> mapM_ (\(var, value) -> restore var value) (zip vars prevState))+    (const s)+  where vars =+          [ "GHC_PACKAGE_PATH"+          , "GHC_ENVIRONMENT"+          , "HASKELL_DIST_DIR"+          , "HASKELL_PACKAGE_SANDBOX"+          , "HASKELL_PACKAGE_SANDBOXES"+          ]+        restore var Nothing = unsetEnv var+        restore var (Just val) = setEnv var val True++simpleMultiTest :: TestTree+simpleMultiTest = testCase "simple-multi-test" $ withoutStackEnv $ runWithExtraFiles "multi" $ \dir -> do+    let aPath = dir </> "a/A.hs"+        bPath = dir </> "b/B.hs"+    aSource <- liftIO $ readFileUtf8 aPath+    (TextDocumentIdentifier adoc) <- createDoc aPath "haskell" aSource+    expectNoMoreDiagnostics 0.5+    bSource <- liftIO $ readFileUtf8 bPath+    bdoc <- createDoc bPath "haskell" bSource+    expectNoMoreDiagnostics 0.5+    locs <- getDefinitions bdoc (Position 2 7)+    let fooL = mkL adoc 2 0 2 3+    checkDefs locs (pure [fooL])+    expectNoMoreDiagnostics 0.5++-- Like simpleMultiTest but open the files in the other order+simpleMultiTest2 :: TestTree+simpleMultiTest2 = testCase "simple-multi-test2" $ withoutStackEnv $ runWithExtraFiles "multi" $ \dir -> do+    let aPath = dir </> "a/A.hs"+        bPath = dir </> "b/B.hs"+    bSource <- liftIO $ readFileUtf8 bPath+    bdoc <- createDoc bPath "haskell" bSource+    expectNoMoreDiagnostics 5+    aSource <- liftIO $ readFileUtf8 aPath+    (TextDocumentIdentifier adoc) <- createDoc aPath "haskell" aSource+    -- Need to have some delay here or the test fails+    expectNoMoreDiagnostics 6+    locs <- getDefinitions bdoc (Position 2 7)+    let fooL = mkL adoc 2 0 2 3+    checkDefs locs (pure [fooL])+    expectNoMoreDiagnostics 0.5++ifaceTests :: TestTree+ifaceTests = testGroup "Interface loading tests"+    [ -- https://github.com/digital-asset/ghcide/pull/645/+      ifaceErrorTest+    , ifaceErrorTest2+    , ifaceErrorTest3+    , ifaceTHTest+    ]++-- | test that TH reevaluates across interfaces+ifaceTHTest :: TestTree+ifaceTHTest = testCase "iface-th-test" $ withoutStackEnv $ runWithExtraFiles "TH" $ \dir -> do+    let aPath = dir </> "THA.hs"+        bPath = dir </> "THB.hs"+        cPath = dir </> "THC.hs"++    aSource <- liftIO $ readFileUtf8 aPath -- [TH] a :: ()+    _bSource <- liftIO $ readFileUtf8 bPath -- a :: ()+    cSource <- liftIO $ readFileUtf8 cPath -- c = a :: ()++    cdoc <- createDoc cPath "haskell" cSource++    -- Change [TH]a from () to Bool+    liftIO $ writeFileUTF8 aPath (unlines $ init (lines $ T.unpack aSource) ++ ["th_a = [d| a = False|]"])++    -- Check that the change propogates to C+    changeDoc cdoc [TextDocumentContentChangeEvent Nothing Nothing cSource]+    expectDiagnostics+      [("THC.hs", [(DsError, (4, 4), "Couldn't match expected type '()' with actual type 'Bool'")])+      ,("THB.hs", [(DsWarning, (4,0), "Top-level binding")])]+    closeDoc cdoc++ifaceErrorTest :: TestTree+ifaceErrorTest = testCase "iface-error-test-1" $ withoutStackEnv $ runWithExtraFiles "recomp" $ \dir -> do+    let aPath = dir </> "A.hs"+        bPath = dir </> "B.hs"+        pPath = dir </> "P.hs"++    aSource <- liftIO $ readFileUtf8 aPath -- x = y :: Int+    bSource <- liftIO $ readFileUtf8 bPath -- y :: Int+    pSource <- liftIO $ readFileUtf8 pPath -- bar = x :: Int++    bdoc <- createDoc bPath "haskell" bSource+    pdoc <- createDoc pPath "haskell" pSource+    expectDiagnostics [("P.hs", [(DsWarning,(4,0), "Top-level binding")]) -- So what we know P has been loaded+                      ]++    -- Change y from Int to B+    changeDoc bdoc [TextDocumentContentChangeEvent Nothing Nothing $ T.unlines ["module B where", "y :: Bool", "y = undefined"]]++    -- Check that the error propogates to A+    adoc <- createDoc aPath "haskell" aSource+    expectDiagnostics+      [("A.hs", [(DsError, (5, 4), "Couldn't match expected type 'Int' with actual type 'Bool'")])]+    closeDoc adoc -- Close A++    changeDoc pdoc [TextDocumentContentChangeEvent Nothing Nothing $ pSource <> "\nfoo = y :: Bool" ]+    -- Now in P we have+    -- bar = x :: Int+    -- foo = y :: Bool+    -- HOWEVER, in A...+    -- x = y  :: Int+    -- This is clearly inconsistent, and the expected outcome a bit surprising:+    --   - The diagnostic for A has already been received. Ghcide does not repeat diagnostics+    --   - P is being typechecked with the last successful artifacts for A.+    expectDiagnostics [("P.hs", [(DsWarning,(4,0), "Top-level binding")])+                      ,("P.hs", [(DsWarning,(6,0), "Top-level binding")])+                      ]+    expectNoMoreDiagnostics 2++ifaceErrorTest2 :: TestTree+ifaceErrorTest2 = testCase "iface-error-test-2" $ withoutStackEnv $ runWithExtraFiles "recomp" $ \dir -> do+    let bPath = dir </> "B.hs"+        pPath = dir </> "P.hs"++    bSource <- liftIO $ readFileUtf8 bPath -- y :: Int+    pSource <- liftIO $ readFileUtf8 pPath -- bar = x :: Int++    bdoc <- createDoc bPath "haskell" bSource+    pdoc <- createDoc pPath "haskell" pSource+    expectDiagnostics [("P.hs", [(DsWarning,(4,0), "Top-level binding")]) -- So that we know P has been loaded+                      ]++    -- Change y from Int to B+    changeDoc bdoc [TextDocumentContentChangeEvent Nothing Nothing $ T.unlines ["module B where", "y :: Bool", "y = undefined"]]++    -- Add a new definition to P+    changeDoc pdoc [TextDocumentContentChangeEvent Nothing Nothing $ pSource <> "\nfoo = y :: Bool" ]+    -- Now in P we have+    -- bar = x :: Int+    -- foo = y :: Bool+    -- HOWEVER, in A...+    -- x = y  :: Int+    expectDiagnostics+    -- As in the other test, P is being typechecked with the last successful artifacts for A+    -- (ot thanks to -fdeferred-type-errors)+      [("A.hs", [(DsError, (5, 4), "Couldn't match expected type 'Int' with actual type 'Bool'")])+      ,("P.hs", [(DsWarning,(4,0), "Top-level binding")])+      ,("P.hs", [(DsWarning,(6,0), "Top-level binding")])+      ]+    expectNoMoreDiagnostics 2++ifaceErrorTest3 :: TestTree+ifaceErrorTest3 = testCase "iface-error-test-3" $ withoutStackEnv $ runWithExtraFiles "recomp" $ \dir -> do+    let bPath = dir </> "B.hs"+        pPath = dir </> "P.hs"++    bSource <- liftIO $ readFileUtf8 bPath -- y :: Int+    pSource <- liftIO $ readFileUtf8 pPath -- bar = x :: Int++    bdoc <- createDoc bPath "haskell" bSource++    -- Change y from Int to B+    changeDoc bdoc [TextDocumentContentChangeEvent Nothing Nothing $ T.unlines ["module B where", "y :: Bool", "y = undefined"]]++    -- P should not typecheck, as there are no last valid artifacts for A+    _pdoc <- createDoc pPath "haskell" pSource++    -- In this example the interface file for A should not exist (modulo the cache folder)+    -- Despite that P still type checks, as we can generate an interface file for A thanks to -fdeferred-type-errors+    expectDiagnostics+      [("A.hs", [(DsError, (5, 4), "Couldn't match expected type 'Int' with actual type 'Bool'")])+      ,("P.hs", [(DsWarning,(4,0), "Top-level binding")])+      ]+    expectNoMoreDiagnostics 2++sessionDepsArePickedUp :: TestTree+sessionDepsArePickedUp = testSession'+  "session-deps-are-picked-up"+  $ \dir -> do+    liftIO $+      writeFileUTF8+        (dir </> "hie.yaml")+        "cradle: {direct: {arguments: []}}"+    -- Open without OverloadedStrings and expect an error.+    doc <- createDoc "Foo.hs" "haskell" fooContent+    expectDiagnostics+      [("Foo.hs", [(DsError, (3, 6), "Couldn't match expected type")])]+    -- Update hie.yaml to enable OverloadedStrings.+    liftIO $+      writeFileUTF8+        (dir </> "hie.yaml")+        "cradle: {direct: {arguments: [-XOverloadedStrings]}}"+    -- Send change event.+    let change =+          TextDocumentContentChangeEvent+            { _range = Just (Range (Position 4 0) (Position 4 0)),+              _rangeLength = Nothing,+              _text = "\n"+            }+    changeDoc doc [change]+    -- Now no errors.+    expectDiagnostics [("Foo.hs", [])]+  where+    fooContent =+      T.unlines+        [ "module Foo where",+          "import Data.Text",+          "foo :: Text",+          "foo = \"hello\""+        ]++-- A test to ensure that the command line ghcide workflow stays working+nonLspCommandLine :: TestTree+nonLspCommandLine = testGroup "ghcide command line"+  [ testCase "works" $ withTempDir $ \dir -> do+        ghcide <- locateGhcideExecutable+        copyTestDataFiles dir "multi"+        let cmd = (proc ghcide ["a/A.hs"]){cwd = Just dir}++        setEnv "HOME" "/homeless-shelter" False++        (ec, _, _) <- withoutStackEnv $ readCreateProcessWithExitCode cmd ""++        ec @=? ExitSuccess+  ]++benchmarkTests :: TestTree+-- These tests require stack and will fail with cabal test+benchmarkTests =+    let ?config = Bench.defConfig+            { Bench.verbosity = Bench.Quiet+            , Bench.repetitions = Just 3+            , Bench.buildTool = Bench.Stack+            } in+    withResource Bench.setup id $ \_ -> testGroup "benchmark experiments"+    [ expectFailCabal "Requires stack" $ testCase (Bench.name e) $ do+        res <- Bench.runBench runInDir e+        assertBool "did not successfully complete 5 repetitions" $ Bench.success res+        | e <- Bench.experiments+        , Bench.name e /= "edit" -- the edit experiment does not ever fail+    ]++----------------------------------------------------------------------+-- Utils+++testSession :: String -> Session () -> TestTree+testSession name = testCase name . run++testSessionWithExtraFiles :: FilePath -> String -> (FilePath -> Session ()) -> TestTree+testSessionWithExtraFiles prefix name = testCase name . runWithExtraFiles prefix++testSession' :: String -> (FilePath -> Session ()) -> TestTree+testSession' name = testCase name . run'++testSessionWait :: String -> Session () -> TestTree+testSessionWait name = testSession name .+      -- Check that any diagnostics produced were already consumed by the test case.+      --+      -- If in future we add test cases where we don't care about checking the diagnostics,+      -- this could move elsewhere.+      --+      -- Experimentally, 0.5s seems to be long enough to wait for any final diagnostics to appear.+      ( >> expectNoMoreDiagnostics 0.5)++pickActionWithTitle :: T.Text -> [CAResult] -> IO CodeAction+pickActionWithTitle title actions = do+  assertBool ("Found no matching actions for " <> show title <> " in " <> show titles) (not $ null matches)+  return $ head matches+  where+    titles =+        [ actionTitle+        | CACodeAction CodeAction { _title = actionTitle } <- actions+        ]+    matches =+        [ action+        | CACodeAction action@CodeAction { _title = actionTitle } <- actions+        , title == actionTitle+        ]++mkRange :: Int -> Int -> Int -> Int -> Range+mkRange a b c d = Range (Position a b) (Position c d)++run :: Session a -> IO a+run s = withTempDir $ \dir -> runInDir dir s++runWithExtraFiles :: FilePath -> (FilePath -> Session a) -> IO a+runWithExtraFiles prefix s = withTempDir $ \dir -> do+  copyTestDataFiles dir prefix+  runInDir dir (s dir)++copyTestDataFiles :: FilePath -> FilePath -> IO ()+copyTestDataFiles dir prefix = do+  -- Copy all the test data files to the temporary workspace+  testDataFiles <- getDirectoryFilesIO ("test/data" </> prefix) ["//*"]+  for_ testDataFiles $ \f -> do+    createDirectoryIfMissing True $ dir </> takeDirectory f+    copyFile ("test/data" </> prefix </> f) (dir </> f)++run' :: (FilePath -> Session a) -> IO a+run' s = withTempDir $ \dir -> runInDir dir (s dir)++runInDir :: FilePath -> Session a -> IO a+runInDir dir s = do+  ghcideExe <- locateGhcideExecutable++  -- Temporarily hack around https://github.com/mpickering/hie-bios/pull/56+  -- since the package import test creates "Data/List.hs", which otherwise has no physical home+  createDirectoryIfMissing True $ dir ++ "/Data"+++  let cmd = unwords [ghcideExe, "--lsp", "--test", "--cwd", dir]+  -- HIE calls getXgdDirectory which assumes that HOME is set.+  -- Only sets HOME if it wasn't already set.+  setEnv "HOME" "/homeless-shelter" False+  let lspTestCaps = fullCaps { _window = Just $ WindowClientCapabilities $ Just True }+  runSessionWithConfig conf cmd lspTestCaps dir s+  where+    conf = defaultConfig+      -- If you uncomment this you can see all logging+      -- which can be quite useful for debugging.+    --   { logStdErr = True, logColor = False }+      -- If you really want to, you can also see all messages+    --   { logMessages = True, logColor = False }++openTestDataDoc :: FilePath -> Session TextDocumentIdentifier+openTestDataDoc path = do+  source <- liftIO $ readFileUtf8 $ "test/data" </> path+  createDoc path "haskell" source++findCodeActions :: TextDocumentIdentifier -> Range -> [T.Text] -> Session [CodeAction]+findCodeActions = findCodeActions' (==) "is not a superset of"++findCodeActionsByPrefix :: TextDocumentIdentifier -> Range -> [T.Text] -> Session [CodeAction]+findCodeActionsByPrefix = findCodeActions' T.isPrefixOf "is not prefix of"++findCodeActions' :: (T.Text -> T.Text -> Bool) -> String -> TextDocumentIdentifier -> Range -> [T.Text] -> Session [CodeAction]+findCodeActions' op errMsg doc range expectedTitles = do+  actions <- getCodeActions doc range+  let matches = sequence+        [ listToMaybe+          [ action+          | CACodeAction action@CodeAction { _title = actionTitle } <- actions+          , expectedTitle `op` actionTitle]+        | expectedTitle <- expectedTitles]+  let msg = show+            [ actionTitle+            | CACodeAction CodeAction { _title = actionTitle } <- actions+            ]+            ++ " " <> errMsg <> " "+            ++ show expectedTitles+  liftIO $ case matches of+    Nothing -> assertFailure msg+    Just _ -> pure ()+  return (fromJust matches)++findCodeAction :: TextDocumentIdentifier -> Range -> T.Text -> Session CodeAction+findCodeAction doc range t = head <$> findCodeActions doc range [t]++unitTests :: TestTree+unitTests = do+  testGroup "Unit"+     [ testCase "empty file path does NOT work with the empty String literal" $+         uriToFilePath' (fromNormalizedUri $ filePathToUri' "") @?= Just "."+     , testCase "empty file path works using toNormalizedFilePath'" $+         uriToFilePath' (fromNormalizedUri $ filePathToUri' (toNormalizedFilePath' "")) @?= Just ""+     , testCase "empty path URI" $ do+         Just URI{..} <- pure $ parseURI (T.unpack $ getUri $ fromNormalizedUri emptyPathUri)+         uriScheme @?= "file:"+         uriPath @?= ""+     , testCase "from empty path URI" $ do+         let uri = Uri "file://"+         uriToFilePath' uri @?= Just ""+     , testCase "Key with empty file path roundtrips via Binary"  $+         Binary.decode (Binary.encode (Q ((), emptyFilePath))) @?= Q ((), emptyFilePath)+     ]++positionMappingTests :: TestTree+positionMappingTests =+    testGroup "position mapping"+        [ testGroup "toCurrent"+              [ testCase "before" $+                toCurrent+                    (Range (Position 0 1) (Position 0 3))+                    "ab"+                    (Position 0 0) @?= Just (Position 0 0)+              , testCase "after, same line, same length" $+                toCurrent+                    (Range (Position 0 1) (Position 0 3))+                    "ab"+                    (Position 0 3) @?= Just (Position 0 3)+              , testCase "after, same line, increased length" $+                toCurrent+                    (Range (Position 0 1) (Position 0 3))+                    "abc"+                    (Position 0 3) @?= Just (Position 0 4)+              , testCase "after, same line, decreased length" $+                toCurrent+                    (Range (Position 0 1) (Position 0 3))+                    "a"+                    (Position 0 3) @?= Just (Position 0 2)+              , testCase "after, next line, no newline" $+                toCurrent+                    (Range (Position 0 1) (Position 0 3))+                    "abc"+                    (Position 1 3) @?= Just (Position 1 3)+              , testCase "after, next line, newline" $+                toCurrent+                    (Range (Position 0 1) (Position 0 3))+                    "abc\ndef"+                    (Position 1 0) @?= Just (Position 2 0)+              , testCase "after, same line, newline" $+                toCurrent+                    (Range (Position 0 1) (Position 0 3))+                    "abc\nd"+                    (Position 0 4) @?= Just (Position 1 2)+              , testCase "after, same line, newline + newline at end" $+                toCurrent+                    (Range (Position 0 1) (Position 0 3))+                    "abc\nd\n"+                    (Position 0 4) @?= Just (Position 2 1)+              , testCase "after, same line, newline + newline at end" $+                toCurrent+                    (Range (Position 0 1) (Position 0 1))+                    "abc"+                    (Position 0 1) @?= Just (Position 0 4)+              ]+        , testGroup "fromCurrent"+              [ testCase "before" $+                fromCurrent+                    (Range (Position 0 1) (Position 0 3))+                    "ab"+                    (Position 0 0) @?= Just (Position 0 0)+              , testCase "after, same line, same length" $+                fromCurrent+                    (Range (Position 0 1) (Position 0 3))+                    "ab"+                    (Position 0 3) @?= Just (Position 0 3)+              , testCase "after, same line, increased length" $+                fromCurrent+                    (Range (Position 0 1) (Position 0 3))+                    "abc"+                    (Position 0 4) @?= Just (Position 0 3)+              , testCase "after, same line, decreased length" $+                fromCurrent+                    (Range (Position 0 1) (Position 0 3))+                    "a"+                    (Position 0 2) @?= Just (Position 0 3)+              , testCase "after, next line, no newline" $+                fromCurrent+                    (Range (Position 0 1) (Position 0 3))+                    "abc"+                    (Position 1 3) @?= Just (Position 1 3)+              , testCase "after, next line, newline" $+                fromCurrent+                    (Range (Position 0 1) (Position 0 3))+                    "abc\ndef"+                    (Position 2 0) @?= Just (Position 1 0)+              , testCase "after, same line, newline" $+                fromCurrent+                    (Range (Position 0 1) (Position 0 3))+                    "abc\nd"+                    (Position 1 2) @?= Just (Position 0 4)+              , testCase "after, same line, newline + newline at end" $+                fromCurrent+                    (Range (Position 0 1) (Position 0 3))+                    "abc\nd\n"+                    (Position 2 1) @?= Just (Position 0 4)+              , testCase "after, same line, newline + newline at end" $+                fromCurrent+                    (Range (Position 0 1) (Position 0 1))+                    "abc"+                    (Position 0 4) @?= Just (Position 0 1)+              ]+        , adjustOption (\(QuickCheckTests i) -> QuickCheckTests (max 1000 i)) $ testGroup "properties"+              [ testProperty "fromCurrent r t <=< toCurrent r t" $ do+                -- Note that it is important to use suchThatMap on all values at once+                -- instead of only using it on the position. Otherwise you can get+                -- into situations where there is no position that can be mapped back+                -- for the edit which will result in QuickCheck looping forever.+                let gen = do+                        rope <- genRope+                        range <- genRange rope+                        PrintableText replacement <- arbitrary+                        oldPos <- genPosition rope+                        pure (range, replacement, oldPos)+                forAll+                    (suchThatMap gen+                        (\(range, replacement, oldPos) -> (range, replacement, oldPos,) <$> toCurrent range replacement oldPos)) $+                    \(range, replacement, oldPos, newPos) ->+                    fromCurrent range replacement newPos === Just oldPos+              , testProperty "toCurrent r t <=< fromCurrent r t" $ do+                let gen = do+                        rope <- genRope+                        range <- genRange rope+                        PrintableText replacement <- arbitrary+                        let newRope = applyChange rope (TextDocumentContentChangeEvent (Just range) Nothing replacement)+                        newPos <- genPosition newRope+                        pure (range, replacement, newPos)+                forAll+                    (suchThatMap gen+                        (\(range, replacement, newPos) -> (range, replacement, newPos,) <$> fromCurrent range replacement newPos)) $+                    \(range, replacement, newPos, oldPos) ->+                    toCurrent range replacement oldPos === Just newPos+              ]+        ]++newtype PrintableText = PrintableText { getPrintableText :: T.Text }+    deriving Show++instance Arbitrary PrintableText where+    arbitrary = PrintableText . T.pack . getPrintableString <$> arbitrary+++genRope :: Gen Rope+genRope = Rope.fromText . getPrintableText <$> arbitrary++genPosition :: Rope -> Gen Position+genPosition r = do+    row <- choose (0, max 0 $ rows - 1)+    let columns = Rope.columns (nthLine row r)+    column <- choose (0, max 0 $ columns - 1)+    pure $ Position row column+    where rows = Rope.rows r++genRange :: Rope -> Gen Range+genRange r = do+    startPos@(Position startLine startColumn) <- genPosition r+    let maxLineDiff = max 0 $ rows - 1 - startLine+    endLine <- choose (startLine, startLine + maxLineDiff)+    let columns = Rope.columns (nthLine endLine r)+    endColumn <-+        if startLine == endLine+            then choose (startColumn, columns)+            else choose (0, max 0 $ columns - 1)+    pure $ Range startPos (Position endLine endColumn)+    where rows = Rope.rows r++-- | Get the ith line of a rope, starting from 0. Trailing newline not included.+nthLine :: Int -> Rope -> Rope+nthLine i r+    | i < 0 = error $ "Negative line number: " <> show i+    | i == 0 && Rope.rows r == 0 = r+    | i >= Rope.rows r = error $ "Row number out of bounds: " <> show i <> "/" <> show (Rope.rows r)+    | otherwise = Rope.takeWhile (/= '\n') $ fst $ Rope.splitAtLine 1 $ snd $ Rope.splitAtLine (i - 1) r++getWatchedFilesSubscriptionsUntil :: forall end . (FromJSON end, Typeable end) => Session [Maybe Value]+getWatchedFilesSubscriptionsUntil = do+      msgs <- manyTill (Just <$> message @RegisterCapabilityRequest <|> Nothing <$ anyMessage) (message @end)+      return+            [ args+            | Just RequestMessage{_params = RegistrationParams (List regs)} <- msgs+            , Registration _id WorkspaceDidChangeWatchedFiles args <- regs+            ]++-- | Version of 'System.IO.Extra.withTempDir' that canonicalizes the path+-- Which we need to do on macOS since the $TMPDIR can be in @/private/var@ or+-- @/var@+withTempDir :: (FilePath -> IO a) -> IO a+withTempDir f = System.IO.Extra.withTempDir $ \dir -> do+  dir' <- canonicalizePath dir+  f dir'
test/src/Development/IDE/Test.hs view
@@ -10,6 +10,7 @@   , diagnostic   , expectDiagnostics   , expectNoMoreDiagnostics+  , canonicalizeUri   ) where  import Control.Applicative.Combinators@@ -24,6 +25,8 @@ import Language.Haskell.LSP.Types.Lens as Lsp import System.Time.Extra import Test.Tasty.HUnit+import System.Directory (canonicalizePath)+import Data.Maybe (fromJust)   -- | (0-based line number, 0-based column number)@@ -74,7 +77,8 @@  expectDiagnostics :: [(FilePath, [(DiagnosticSeverity, Cursor, T.Text)])] -> Session () expectDiagnostics expected = do-    expected' <- Map.fromListWith (<>) <$> traverseOf (traverse . _1) (fmap toNormalizedUri . getDocUri) expected+    let f = getDocUri >=> liftIO . canonicalizeUri >=> pure . toNormalizedUri+    expected' <- Map.fromListWith (<>) <$> traverseOf (traverse . _1) f expected     go expected'     where         go m@@ -82,7 +86,8 @@             | otherwise = do                   diagsNot <- skipManyTill anyMessage diagnostic                   let fileUri = diagsNot ^. params . uri-                  case Map.lookup (diagsNot ^. params . uri . to toNormalizedUri) m of+                  canonUri <- liftIO $ toNormalizedUri <$> canonicalizeUri fileUri+                  case Map.lookup canonUri m of                       Nothing -> do                           let actual = diagsNot ^. params . diagnostics                           liftIO $ assertFailure $@@ -97,7 +102,10 @@                               "Incorrect number of diagnostics for " <> show fileUri <>                               ", expected " <> show expected <>                               " but got " <> show actual-                          go $ Map.delete (diagsNot ^. params . uri . to toNormalizedUri) m+                          go $ Map.delete canonUri m++canonicalizeUri :: Uri -> IO Uri+canonicalizeUri uri = filePathToUri <$> canonicalizePath (fromJust (uriToFilePath uri))  diagnostic :: Session PublishDiagnosticsNotification diagnostic = LspTest.message