module IdeSession.Types.Private (
FilePathPtr(..)
, IdPropPtr(..)
, UseSites
, Public.IdNameSpace(..)
, IdInfo(..)
, IdProp(..)
, IdScope(..)
, SourceSpan(..)
, EitherSpan(..)
, SourceError(..)
, Public.SourceErrorKind(..)
, Public.ModuleName
, ModuleId(..)
, PackageId(..)
, IdList
, IdMap(..)
, ExpMap(..)
, SpanInfo(..)
, ImportEntities(..)
, Import(..)
, RunResult(..)
, BreakInfo(..)
, ExplicitSharingCache(..)
, unionCache
, mkIdMap
, mkExpMap
, dominators
) where
import Prelude hiding (span, mod)
import Data.Text (Text)
import Data.ByteString (ByteString)
import Control.Applicative ((<$>), (<*>))
import Control.Arrow (first)
import Data.Binary (Binary(..), getWord8, putWord8)
import Data.Typeable (Typeable)
import GHC.Generics (Generic)
import qualified IdeSession.Types.Public as Public
import IdeSession.Strict.Container
import IdeSession.Strict.IntervalMap (StrictIntervalMap, Interval(..))
import qualified IdeSession.Strict.IntervalMap as IntervalMap
import qualified IdeSession.Strict.IntMap as IntMap
import IdeSession.Util.PrettyVal
newtype FilePathPtr = FilePathPtr { filePathPtr :: Int }
deriving (Eq, Ord, Show, Generic)
newtype IdPropPtr = IdPropPtr { idPropPtr :: Int }
deriving (Eq, Ord, Show, Generic)
data IdInfo = IdInfo {
idProp :: !IdPropPtr
, idScope :: !IdScope
}
deriving (Show, Typeable, Generic)
data IdProp = IdProp {
idName :: !Text
, idSpace :: !Public.IdNameSpace
, idType :: !(Strict Maybe Public.Type)
, idDefinedIn :: !ModuleId
, idDefSpan :: !EitherSpan
, idHomeModule :: !(Strict Maybe ModuleId)
}
deriving (Show, Generic)
data IdScope =
Binder
| Local
| Imported {
idImportedFrom :: !ModuleId
, idImportSpan :: !EitherSpan
, idImportQual :: !Text
}
| WiredIn
deriving (Show, Generic)
data SourceSpan = SourceSpan
{ spanFilePath :: !FilePathPtr
, spanFromLine :: !Int
, spanFromColumn :: !Int
, spanToLine :: !Int
, spanToColumn :: !Int
}
deriving (Eq, Ord, Show, Generic)
data EitherSpan =
ProperSpan !SourceSpan
| TextSpan !Text
deriving (Show, Generic)
data SourceError = SourceError
{ errorKind :: !Public.SourceErrorKind
, errorSpan :: !EitherSpan
, errorMsg :: !Text
}
deriving (Show, Generic)
data ModuleId = ModuleId
{ moduleName :: !Public.ModuleName
, modulePackage :: !PackageId
}
deriving (Show, Eq, Generic)
data PackageId = PackageId
{ packageName :: !Text
, packageVersion :: !(Strict Maybe Text)
, packageKey :: !Text
}
deriving (Show, Eq, Ord, Generic)
type IdList = [(SourceSpan, SpanInfo)]
data SpanInfo =
SpanId IdInfo
| SpanQQ IdInfo
| SpanInSplice IdInfo
deriving (Show, Generic)
newtype IdMap = IdMap { idMapToMap :: StrictIntervalMap (FilePathPtr, Int, Int) SpanInfo }
deriving (Show, Generic)
newtype ExpMap = ExpMap { expMapToMap :: StrictIntervalMap (FilePathPtr, Int, Int) Text }
deriving (Show, Generic)
type UseSites = Strict (Map IdPropPtr) [SourceSpan]
data ImportEntities =
ImportOnly !(Strict [] Text)
| ImportHiding !(Strict [] Text)
| ImportAll
deriving (Show, Eq, Generic)
data Import = Import {
importModule :: !ModuleId
, importPackage :: !(Strict Maybe Text)
, importQualified :: !Bool
, importImplicit :: !Bool
, importAs :: !(Strict Maybe Public.ModuleName)
, importEntities :: !ImportEntities
}
deriving (Show, Eq, Generic)
data RunResult =
RunOk
| RunProgException String
| RunGhcException String
| RunBreak BreakInfo
deriving (Typeable, Show, Generic)
data BreakInfo = BreakInfo {
breakInfoModule :: Public.ModuleName
, breakInfoSpan :: SourceSpan
, breakInfoResultType :: Public.Type
, breakInfoVariableEnv :: Public.VariableEnv
}
deriving (Typeable, Show, Generic)
data ExplicitSharingCache = ExplicitSharingCache {
filePathCache :: !(Strict IntMap ByteString)
, idPropCache :: !(Strict IntMap IdProp)
}
deriving (Show, Generic)
unionCache :: ExplicitSharingCache -> ExplicitSharingCache -> ExplicitSharingCache
unionCache a b = ExplicitSharingCache {
filePathCache = IntMap.union (filePathCache a) (filePathCache b)
, idPropCache = IntMap.union (idPropCache a) (idPropCache b)
}
instance Binary FilePathPtr where
put = put . filePathPtr
get = FilePathPtr <$> get
instance Binary SourceSpan where
put SourceSpan{..} = do
put spanFilePath
put spanFromLine
put spanFromColumn
put spanToLine
put spanToColumn
get = SourceSpan <$> get <*> get <*> get <*> get <*> get
instance Binary EitherSpan where
put (ProperSpan span) = putWord8 0 >> put span
put (TextSpan text) = putWord8 1 >> put text
get = do
header <- getWord8
case header of
0 -> ProperSpan <$> get
1 -> TextSpan <$> get
_ -> fail "EitherSpan.get: invalid header"
instance Binary SourceError where
put SourceError{..} = do
put errorKind
put errorSpan
put errorMsg
get = SourceError <$> get <*> get <*> get
instance Binary IdInfo where
put IdInfo{..} = put idProp >> put idScope
get = IdInfo <$> get <*> get
instance Binary IdScope where
put Binder = putWord8 0
put Local = do putWord8 1
put Imported{..} = do putWord8 2
put idImportedFrom
put idImportSpan
put idImportQual
put WiredIn = putWord8 3
get = do
header <- getWord8
case header of
0 -> return Binder
1 -> return Local
2 -> Imported <$> get <*> get <*> get
3 -> return WiredIn
_ -> fail "IdScope.get: invalid header"
instance Binary IdPropPtr where
put = put . idPropPtr
get = IdPropPtr <$> get
instance Binary ModuleId where
put ModuleId{..} = put moduleName >> put modulePackage
get = ModuleId <$> get <*> get
instance Binary PackageId where
put PackageId{..} = do
put packageName
put packageVersion
put packageKey
get = PackageId <$> get <*> get <*> get
instance Binary IdProp where
put IdProp{..} = do
put idName
put idSpace
put idType
put idDefinedIn
put idDefSpan
put idHomeModule
get = IdProp <$> get <*> get <*> get <*> get <*> get <*> get
instance Binary ImportEntities where
put (ImportOnly names) = putWord8 0 >> put names
put (ImportHiding names) = putWord8 1 >> put names
put ImportAll = putWord8 2
get = do
header <- getWord8
case header of
0 -> ImportOnly <$> get
1 -> ImportHiding <$> get
2 -> return ImportAll
_ -> fail "ImportEntities.get: invalid header"
instance Binary Import where
put Import{..} = do
put importModule
put importPackage
put importQualified
put importImplicit
put importAs
put importEntities
get = Import <$> get <*> get <*> get <*> get <*> get <*> get
instance Binary ExplicitSharingCache where
put ExplicitSharingCache{..} = do
put filePathCache
put idPropCache
get = ExplicitSharingCache <$> get <*> get
instance Binary SpanInfo where
put (SpanId idInfo) = putWord8 0 >> put idInfo
put (SpanQQ idInfo) = putWord8 1 >> put idInfo
put (SpanInSplice idInfo) = putWord8 2 >> put idInfo
get = do
header <- getWord8
case header of
0 -> SpanId <$> get
1 -> SpanQQ <$> get
2 -> SpanInSplice <$> get
_ -> fail "SpanInfo.get: invalid header"
instance Binary RunResult where
put RunOk = putWord8 0
put (RunProgException str) = putWord8 1 >> put str
put (RunGhcException str) = putWord8 2 >> put str
put (RunBreak info) = putWord8 3 >> put info
get = do
header <- getWord8
case header of
0 -> return RunOk
1 -> RunProgException <$> get
2 -> RunGhcException <$> get
3 -> RunBreak <$> get
_ -> fail "RunResult.get: invalid header"
instance Binary BreakInfo where
put (BreakInfo{..}) = do
put breakInfoModule
put breakInfoSpan
put breakInfoResultType
put breakInfoVariableEnv
get = BreakInfo <$> get <*> get <*> get <*> get
instance PrettyVal FilePathPtr
instance PrettyVal IdPropPtr
instance PrettyVal IdInfo
instance PrettyVal IdProp
instance PrettyVal IdScope
instance PrettyVal SourceSpan
instance PrettyVal EitherSpan
instance PrettyVal SourceError
instance PrettyVal ModuleId
instance PrettyVal PackageId
instance PrettyVal SpanInfo
instance PrettyVal IdMap
instance PrettyVal ExpMap
instance PrettyVal ImportEntities
instance PrettyVal Import
instance PrettyVal RunResult
instance PrettyVal BreakInfo
instance PrettyVal ExplicitSharingCache
mkIdMap :: IdList -> IdMap
mkIdMap = IdMap . IntervalMap.fromList . map (first spanToInterval)
mkExpMap :: [(SourceSpan, Text)] -> ExpMap
mkExpMap = ExpMap . IntervalMap.fromList . map (first spanToInterval)
dominators :: SourceSpan -> StrictIntervalMap (FilePathPtr, Int, Int) a -> [(SourceSpan, a)]
dominators span ivalmap =
map (\(ival, idInfo) -> (intervalToSpan ival, idInfo))
(IntervalMap.dominators (spanToInterval span) ivalmap)
spanToInterval :: SourceSpan -> Interval (FilePathPtr, Int, Int)
spanToInterval SourceSpan{..} =
Interval (spanFilePath, spanFromLine, spanFromColumn)
(spanFilePath, spanToLine, spanToColumn)
intervalToSpan :: Interval (FilePathPtr, Int, Int) -> SourceSpan
intervalToSpan (Interval (spanFilePath, spanFromLine, spanFromColumn)
(_, spanToLine, spanToColumn)) =
SourceSpan{..}