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
savePackageToDb (Package doc (PackageIdentifier (PackageName name) version) modules) =
do pkgId <- insert $ DbPackage name (showVersion version) (docToString doc)
mapM_ (saveModuleToDb pkgId) (M.elems modules)
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 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
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
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)
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))
saveDeclToDb moduleId (TypeSig doc names ty) =
do mapM_ saveSignatureToDb names
where saveSignatureToDb name =
insert $ DbDecl DbSignature (getNameString name) (docToString doc)
Nothing (Just (singleLinePrettyPrint ty)) Nothing moduleId
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
saveDeclToDb _ _ = error "This should never happen"
saveTyVarToDb declId var = insert $ DbTyVar var declId
saveFunDepToDb declId var = insert $ DbTyVar var declId
saveContextToDb declId ctx = insert $ DbContext ctx declId
saveConstructorToDb declId (GadtDecl _ name ty) = insert $ DbConstructor (getNameString name) (singleLinePrettyPrint ty) declId
deletePackageByInfo (PackageIdentifier (PackageName name) version) =
do Just pkg <- selectFirst [ DbPackageName ==. name, DbPackageVersion ==. showVersion version ] []
let pkgId = entityKey pkg
deletePackage pkgId
deletePackage pkgId =
do modules <- selectList [ DbModulePackageId ==. pkgId ] []
mapM_ (deleteModule . entityKey) modules
delete pkgId
deleteModule moduleId =
do decls <- selectList [ DbDeclModuleId ==. moduleId ] []
mapM_ (deleteDecl . entityKey) decls
delete moduleId
deleteDecl declId =
do deleteWhere [ DbTyVarDeclId ==. declId ]
deleteWhere [ DbFunDepDeclId ==. declId ]
deleteWhere [ DbContextDeclId ==. declId ]
deleteWhere [ DbConstructorDeclId ==. declId ]
delete declId
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 _) = []