scion-browser-0.2.7: src/Scion/PersistentBrowser/ToDb.hs
{-# LANGUAGE RankNTypes, KindSignatures #-}
module Scion.PersistentBrowser.ToDb where
import qualified Data.Map as M
import qualified Data.Text as T
import Data.Version (showVersion)
import Database.Persist
import Distribution.Package hiding (Package)
import Language.Haskell.Exts.Annotated.Syntax hiding (String)
import Language.Haskell.Exts.Pretty
import Scion.PersistentBrowser.DbTypes
import Scion.PersistentBrowser.Types
-- SAVING IN THE DATABASE
-- ======================
-- savePackageToDb :: PersistBackend backend m => Documented Package -> backend m ()
savePackageToDb (Package doc (PackageIdentifier (PackageName name) version) modules) =
do pkgId <- insert $ DbPackage name (showVersion version) (docToString doc)
mapM_ (saveModuleToDb pkgId) (M.elems modules)
-- saveModuleToDb :: PersistBackend backend m => DbPackageId -> Documented Module -> backend m ()
saveModuleToDb pkgId (Module doc (Just (ModuleHead _ (ModuleName _ name) _ _)) _ _ decls) =
do moduleId <- insert $ DbModule name (docToString doc) pkgId
mapM_ (saveDeclToDb moduleId) decls
saveModuleToDb _ _ = error "This should never happen"
-- saveDeclToDb :: PersistBackend backend m => DbModuleId -> Documented Decl -> backend m ()
-- Datatypes
saveDeclToDb moduleId (GDataDecl doc (DataType _) ctx hd kind decls _) =
do let (declName, declVars) = declHeadToDb hd
declId <- insert $ DbDecl DbData declName (docToString doc)
(fmap singleLinePrettyPrint kind) Nothing Nothing moduleId
mapM_ (saveTyVarToDb declId) declVars
mapM_ (saveContextToDb declId) (contextToDb (maybeEmptyContext ctx))
mapM_ (saveConstructorToDb declId) decls
-- Newtypes
saveDeclToDb moduleId (GDataDecl doc (NewType _) ctx hd kind decls _) =
do let (declName, declVars) = declHeadToDb hd
declId <- insert $ DbDecl DbNewType declName (docToString doc)
(fmap singleLinePrettyPrint kind) Nothing Nothing moduleId
mapM_ (saveTyVarToDb declId) declVars
mapM_ (saveContextToDb declId) (contextToDb (maybeEmptyContext ctx))
mapM_ (saveConstructorToDb declId) decls
-- Classes
saveDeclToDb moduleId (ClassDecl doc ctx hd fdeps _) =
do let (declName, declVars) = declHeadToDb hd
declId <- insert $ DbDecl DbClass declName (docToString doc)
Nothing Nothing Nothing moduleId
mapM_ (saveTyVarToDb declId) declVars
mapM_ (saveContextToDb declId) (contextToDb (maybeEmptyContext ctx))
mapM_ (saveFunDepToDb declId) (map singleLinePrettyPrint fdeps)
-- Instances
saveDeclToDb moduleId (InstDecl doc ctx hd _) =
do let (declName, declVars) = instHeadToDb hd
declId <- insert $ DbDecl DbInstance declName (docToString doc)
Nothing Nothing Nothing moduleId
mapM_ (saveTyVarToDb declId) declVars
mapM_ (saveContextToDb declId) (contextToDb (maybeEmptyContext ctx))
-- Signatures
saveDeclToDb moduleId (TypeSig doc names ty) =
do mapM_ saveSignatureToDb names
where saveSignatureToDb name = do
insert $ DbDecl DbSignature (getNameString name) (docToString doc)
Nothing (Just (singleLinePrettyPrint ty)) Nothing moduleId
-- Types
saveDeclToDb moduleId (TypeDecl doc hd ty) =
do let (declName, declVars) = declHeadToDb hd
declId <- insert $ DbDecl DbType declName (docToString doc)
Nothing Nothing (Just (singleLinePrettyPrint ty)) moduleId
mapM_ (saveTyVarToDb declId) declVars
-- Other
saveDeclToDb _ _ = error "This should never happen"
-- saveTyVarToDb :: PersistBackend backend m => DbDeclId -> String -> backend m ()
saveTyVarToDb declId var = insert $ DbTyVar var declId
-- saveFunDepToDb :: PersistBackend backend m => DbDeclId -> String -> backend m ()
saveFunDepToDb declId var = insert $ DbTyVar var declId
-- saveContextToDb :: PersistBackend backend m => DbDeclId -> String -> backend m ()
saveContextToDb declId ctx = insert $ DbContext ctx declId
-- saveConstructorToDb :: PersistBackend backend m => DbDeclId -> Documented GadtDecl -> backend m ()
saveConstructorToDb declId (GadtDecl _ name ty) = insert $ DbConstructor (getNameString name) (singleLinePrettyPrint ty) declId
-- DELETE PACKAGE FROM DATABASE
-- ============================
-- deletePackageByInfo :: PersistBackend backend m => PackageIdentifier -> backend m ()
deletePackageByInfo (PackageIdentifier (PackageName name) version) =
do Just pkg <- selectFirst [ DbPackageName ==. name, DbPackageVersion ==. showVersion version ] []
let pkgId = entityKey pkg
deletePackage pkgId
-- deletePackage :: PersistBackend backend m => DbPackageId -> backend m ()
deletePackage pkgId =
do modules <- selectList [ DbModulePackageId ==. pkgId ] []
mapM_ (deleteModule . entityKey) modules
delete pkgId
-- deleteModule :: PersistBackend backend m => DbModuleId -> backend m ()
deleteModule moduleId =
do decls <- selectList [ DbDeclModuleId ==. moduleId ] []
mapM_ (deleteDecl . entityKey) decls
delete moduleId
-- deleteDecl :: PersistBackend backend m => DbModuleId -> backend m ()
deleteDecl declId =
do deleteWhere [ DbTyVarDeclId ==. declId ]
deleteWhere [ DbFunDepDeclId ==. declId ]
deleteWhere [ DbContextDeclId ==. declId ]
deleteWhere [ DbConstructorDeclId ==. declId ]
delete declId
-- UTILITIES FOR CONVERTING TO STRINGS
-- ===================================
docToString :: Doc -> Maybe String
docToString NoDoc = Nothing
docToString (Doc doc) = Just (T.unpack doc)
declHeadToDb :: DeclHead l -> (String, [String])
declHeadToDb (DHead _ name vars) = (getNameString name, map singleLinePrettyPrint vars)
declHeadToDb _ = error "This should never happen"
instHeadToDb :: InstHead l -> (String, [String])
instHeadToDb (IHead _ name vars) = (getQNameString name, map singleLinePrettyPrint vars)
instHeadToDb _ = error "This should never happen"
singleLinePrettyPrint :: Pretty a => a -> String
singleLinePrettyPrint = prettyPrintWithMode $ defaultMode { layout = PPNoLayout }
maybeEmptyContext :: Maybe (Documented Context) -> Documented Context
maybeEmptyContext Nothing = CxEmpty NoDoc
maybeEmptyContext (Just ctx) = ctx
contextToDb :: Context l -> [String]
contextToDb (CxSingle _ a) = [ singleLinePrettyPrint a ]
contextToDb (CxTuple _ as) = map singleLinePrettyPrint as
contextToDb (CxParen _ ctx) = contextToDb ctx
contextToDb (CxEmpty _) = []