{-# 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 _) = []