HaskellAnalysisProgram-0.1.0: src/MetaHS/DataModel/Extractor/Module/Source.hs
{-|
Module : MetaHS.DataModel.Extractor.Module.Source
Description : The MetaHS extractor for source relations
Copyright : Copyright (C) 2017-2019 H.H.R.F. Vos, S. Kamps
License : -- This file is distributed under the terms of the Apache License 2.0.
For more information, see the file "LICENSE", which is included in the distribution.
Stability : experimental
MetaHS extractor for module level source relations
-}
module MetaHS.DataModel.Extractor.Module.Source
( source
) where
import Data.Maybe (fromMaybe)
import Data.Set (empty,
fromList)
import Language.Haskell.Exts
import qualified MetaHS.DataModel.MetaModel as MetaModel
import MetaHS.DataModel.Utils
import qualified MetaHS.DataModel.Utils.Language.Haskell.Exts.SrcLoc as SrcLoc
import qualified MetaHS.DataModel.Utils.Language.Haskell.Exts.Syntax.Decl as Decl
import qualified MetaHS.DataModel.Utils.Language.Haskell.Exts.Syntax.DeclHead as DeclHead
import qualified MetaHS.DataModel.Utils.Language.Haskell.Exts.Syntax.Module as Module
import qualified MetaHS.DataModel.Utils.Language.Haskell.Exts.Syntax.QName as QName
-- | Creates Location relations for all supported top-level declarations in the
-- provided Module.
source :: Module SrcSpanInfo -- ^ The Module to analyze.
-> MetaModel.Relation -- ^ The resulting MetaModel.Relation items.
source m = case Module.name m of
Just mn -> fromList $ mlr ++ mlhr ++ mli ++ mle ++ dlr
where
mlr = locationModule mn m -- mlr = Module-Location Relation
mlhr = locationModuleHead mn m -- mlhr = ModuleHead-Location Relation
mli = concat [locationImportDecl mn d | d <- Module.imports m] -- mli = ImportDecl-Location Relation
mle = concat [locationExportSpec mn d | d <- Module.getModuleExports m] -- mle = ExportSpec-Location Relation
dlr = concat [locationDecl mn d | d <- Module.declarations m] -- dlr = Decl-Location Relation
Nothing -> empty
-- | Creates a Module "m",Location "ml" pair for the whole module
locationModule :: String -- ^ The module (head) name.
-> Module SrcSpanInfo -- ^ The Declaration with var l.
-> [(MetaModel.Element,MetaModel.Element)] -- ^ list of (Module "mn",Location) pairs
locationModule mn (Module l _ _ _ _) = [(m,ml)]
where m = MetaModel.Module mn
ml = SrcLoc.srcSpanInfoToLocationElement l
locationModule _ _ = []
-- | Creates a list of (Module head "mh",Location "mhl") pair for the ModuleHead
locationModuleHead :: String -- ^ The module (head) name.
-> Module SrcSpanInfo -- ^ The Declaration with var l.
-> [(MetaModel.Element,MetaModel.Element)] -- ^ list of (Module head "mh",Location "mhl") pairs
locationModuleHead mn (Module _ (Just (ModuleHead l _ _ _)) _ _ _) = [(mh,mhl)]
where mh = MetaModel.ModuleHead $ makeQualifiedId mn mn
mhl = SrcLoc.srcSpanInfoToLocationElement l
locationModuleHead _ _ = []
-- | Creates a list of (imported Module "mi",Location "mil") pair for the ImportDecl
locationImportDecl :: String -- ^ The module name.
-> ImportDecl SrcSpanInfo -- ^ The Declaration with var l.
-> [(MetaModel.Element,MetaModel.Element)] -- ^ list of (imported Module "mi",Location "mil") pairs
locationImportDecl mn ImportDecl{importAnn=ia, importModule=im} = [(mi,mil)]
where mi = MetaModel.ModuleImport $ makeQualifiedId mn $ hn im
mil = SrcLoc.srcSpanInfoToLocationElement ia
hn (ModuleName _ x) = x
-- | Creates a (exported Modules "me",Location "mel") pair for the ExportSpec
locationExportSpec :: String -- ^ The module name.
-> ExportSpec SrcSpanInfo -- ^ The Declaration with var l.
-> [(MetaModel.Element,MetaModel.Element)] -- ^ list of (exported Modules "me",Location "mel") pairs
locationExportSpec mn (EVar l qnm) = case QName.name qnm of
Just es -> [(me,mel)]
where me = MetaModel.ModuleExport $ makeQualifiedId mn es
mel = SrcLoc.srcSpanInfoToLocationElement l
Nothing -> []
locationExportSpec _ _ = []
-- | Creates a list of (Element,Location) pairs for a given top-level declaration.
locationDecl :: String -- ^ The module name.
-> Decl SrcSpanInfo -- ^ The Declaration with var l.
-> [(MetaModel.Element,MetaModel.Element)] -- ^ list of (Element "te", Location "tl") pairs.
locationDecl mn td@TypeDecl{} = locationType mn td
locationDecl mn dd@DataDecl{} = locationData mn dd
locationDecl mn dd@GDataDecl{} = locationData mn dd
locationDecl mn pb@PatBind{} = locationPattern mn pb
locationDecl mn fb@FunBind{} = locationFunction mn fb
locationDecl mn ts@TypeSig{} = locationTypeSig mn ts
locationDecl mn tc@ClassDecl{} = locationTypeClass mn tc
locationDecl mn id@InstDecl{} = locationInstance mn id
locationDecl mn is@InlineSig{} = locationInlineSig mn is
locationDecl _ _ = []
-- | Creates a list of (TypeSynonym qname "ts", Location "dl") pairs for (g)DataDecl declarations.
locationType :: String -- ^ The module name.
-> Decl SrcSpanInfo -- ^ The Declaration with var l.
-> [(MetaModel.Element,MetaModel.Element)] -- ^ list of (TypeSynonym qname "ts", Location "dl") pairs.
locationType mn decl = case decl of
(TypeDecl l h _) -> [(ts,tsl)]
where
ts = MetaModel.TypeSynonym $ makeQualifiedId mn $ DeclHead.name h
tsl = SrcLoc.srcSpanInfoToLocationElement l
_ -> []
-- | Creates a list of ((G)Dataconstructor qname "d", Location "dl") pairs for (g)DataDecl declarations.
locationData :: String -- ^ The module name.
-> Decl SrcSpanInfo -- ^ The Declaration with var l.
-> [(MetaModel.Element,MetaModel.Element)] -- ^ list of ((G)Dataconstructor qname "d", Location "dl") pairs.
locationData mn decl = case Decl.dataConstructor decl of
Just dc -> [(d,dl)]
where
d = MetaModel.DataType $ makeQualifiedId mn $ Decl.dataConstructorName dc
dl = SrcLoc.srcSpanInfoToLocationElement $ ann decl
Nothing -> []
-- | Creates a list of (Pattern qname "p", Location "pl") pairs for PatBind declarations.
locationPattern :: String -- ^ The module name.
-> Decl SrcSpanInfo -- ^ The Declaration with var l.
-> [(MetaModel.Element,MetaModel.Element)] -- ^ list of (Pattern qname "p", Location "pl") pairs.
locationPattern mn patbin@PatBind{} = case Decl.patternName patbin of
Just pn -> [(p,pl)]
where
p = MetaModel.Function $ makeQualifiedId mn pn
pl = SrcLoc.srcSpanInfoToLocationElement $ ann patbin
Nothing -> []
-- | Creates a list of (Module "mn",Location) pairs for FunBind declarations.
locationFunction :: String -- ^ The module name.
-> Decl SrcSpanInfo -- ^ The Declaration with var l.
-> [(MetaModel.Element,MetaModel.Element)] -- ^ list of (Function qname "f", Location "fl") pairs.
locationFunction mn funbin@FunBind{} = case Decl.functionName funbin of
Just fn -> [(f,fl)]
where
f = MetaModel.Function $ makeQualifiedId mn fn
fl = SrcLoc.srcSpanInfoToLocationElement $ ann funbin
Nothing -> []
-- | Creates a list of (TypeSignature "ts",Location "tsl") pairs for TypeSignature declarations.
locationTypeSig :: String -- ^ The module name.
-> Decl SrcSpanInfo -- ^ The Declaration with var l.
-> [(MetaModel.Element,MetaModel.Element)] -- ^ list of (TypeSignature qname, "ts",Location "tsl") pairs.
locationTypeSig mn tysig@TypeSig{} = case Decl.typeSigName tysig of
Just tsn -> [(ts,tsl)]
where ts = MetaModel.TypeSignature $ makeQualifiedId mn tsn
tsl = SrcLoc.srcSpanInfoToLocationElement $ ann tysig
Nothing -> []
-- | Creates a list of (TypeClass "tc",Location "tcl") pairs for TypeClass declarations.
locationTypeClass :: String -- ^ The module name.
-> Decl SrcSpanInfo -- ^ The Declaration with var l.
-> [(MetaModel.Element,MetaModel.Element)] -- ^ list of (TypeClass qname, "tc",Location "tcl") pairs.
locationTypeClass mn tycla@ClassDecl{} = case Decl.typeClassName tycla of
Just tcn -> [(tc,tcl)]
where tc = MetaModel.TypeClass $ makeQualifiedId mn tcn
tcl = SrcLoc.srcSpanInfoToLocationElement $ ann tycla
Nothing -> []
-- | Creates a list of (Instance "i",Location "il") pairs for Instance declarations.
locationInstance :: String -- ^ The module name.
-> Decl SrcSpanInfo -- ^ The Declaration with var l.
-> [(MetaModel.Element,MetaModel.Element)] -- ^ list of (Instance qname, "i",Location "il") pairs.
locationInstance mn inst@InstDecl{} = case Decl.instanceName inst of
Just inm -> [(i,il)]
where i = MetaModel.Instance $ makeQualifiedId mn inm
il = SrcLoc.srcSpanInfoToLocationElement $ ann inst
Nothing -> []
-- | Creates a list of (Pragma "p",Location "pl") pairs for InlineSig declarations.
locationInlineSig :: String -- ^ The module name.
-> Decl SrcSpanInfo -- ^ The Declaration with var l.
-> [(MetaModel.Element,MetaModel.Element)] -- ^ list of (Pragma qname, "p",Location "pl") pairs.
locationInlineSig mn inlsig@InlineSig{} = case Decl.inlineSigName inlsig of
Just isnm -> [(p,pl)]
where p = MetaModel.Pragma $ makeQualifiedId mn isnm
pl = SrcLoc.srcSpanInfoToLocationElement $ ann inlsig
Nothing -> []