HaskellAnalysisProgram-0.1.0: src/MetaHS/DataModel/Extractor/Module/Contains.hs
{-|
Module : MetaHS.DataModel.Extractor.Module.Contains
Description : The MetaHS extractor for contains 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 contains relations
-}
module MetaHS.DataModel.Extractor.Module.Contains
( contains
) where
import Data.Set (fromList, empty)
import Language.Haskell.Exts
import qualified MetaHS.DataModel.MetaModel as MetaModel
import MetaHS.DataModel.Utils
import qualified MetaHS.DataModel.Utils.Language.Haskell.Exts.Syntax.Module
as Module
import qualified MetaHS.DataModel.Utils.Language.Haskell.Exts.Syntax.Decl
as Decl
import qualified MetaHS.DataModel.Utils.Language.Haskell.Exts.Syntax.QName
as QName
import qualified MetaHS.DataModel.Utils.Language.Haskell.Exts.Syntax.DeclHead
as DeclHead
-- | Create MetaModel.Relations for top-level declarations of a module.
contains :: Module SrcSpanInfo -- ^ The module to analyze
-> MetaModel.Relation -- ^ list of Element `Contains` Element
contains m = case Module.name m of
Just mn -> fromList $ mlhr ++ mli ++ mle ++ dlr
where
mlhr = containsModuleHead mn m -- mlhr = ModuleHead-Location Relation
mli = concat [containsImportDecl mn d | d <- Module.imports m] -- mli = ImportDecl-Location Relation
mle = concat [containsExportSpec mn d | d <- Module.getModuleExports m] -- mle = ExportSpec-Location Relation
dlr = concat [containsDecl mn d | d <- Module.declarations m] -- dlr = Decl-Location Relation
Nothing -> empty
-- | Creates a list of (Module "m",Module head "mh") pair for the ModuleHead
containsModuleHead :: String -- ^ The module (head) name.
-> Module SrcSpanInfo -- ^ The Declaration with var l.
-> [(MetaModel.Element,MetaModel.Element)] -- ^ list of (Module "m",Module head "mh") pairs
containsModuleHead mn mod = [(m,mh)]
where m = MetaModel.Module mn
mh = MetaModel.ModuleHead $ makeQualifiedId mn mn
-- | Creates a list of (Module "m",ModuleImport "mi") pair for the ImportDecl
containsImportDecl :: String -- ^ The module name.
-> ImportDecl SrcSpanInfo -- ^ The Declaration with var l.
-> [(MetaModel.Element,MetaModel.Element)] -- ^ list of (Module "m",ModuleImport "mi") pairs
containsImportDecl mn ImportDecl{importModule=im} = [(m,mi)]
where m = MetaModel.Module mn
mi = MetaModel.ModuleImport $ makeQualifiedId mn $ hn im
hn (ModuleName _ x) = x
-- | Creates a (Module "m",ModuleExport "me") pair for the ExportSpec
containsExportSpec :: String -- ^ The module name.
-> ExportSpec SrcSpanInfo -- ^ The Declaration with var l.
-> [(MetaModel.Element,MetaModel.Element)] -- ^ list of (Module "m",ModuleExport "me") pairs
containsExportSpec mn (EVar _ qnm) = case QName.name qnm of
Just es -> [(m,me)]
where m = MetaModel.Module mn
me = MetaModel.ModuleExport $ makeQualifiedId mn es
Nothing -> []
containsExportSpec _ _ = []
-- | Analyzes a declaration for location information.
containsDecl :: String -- ^ The name of the Module.
-> Decl SrcSpanInfo -- ^ The declaration to analyze.
-> [(MetaModel.Element,MetaModel.Element)] -- ^ The resulting list of (Element,Element) pairs.
containsDecl mn td@TypeDecl{} = containsType mn td
containsDecl mn dd@DataDecl{} = containsData mn dd
containsDecl mn dd@GDataDecl{} = containsData mn dd
containsDecl mn pb@PatBind{} = containsPattern mn pb
containsDecl mn fb@FunBind{} = containsFunction mn fb
containsDecl mn ts@TypeSig{} = containsTypeSig mn ts
containsDecl mn tc@ClassDecl{} = containsTypeClass mn tc
containsDecl mn id@InstDecl{} = containsInstance mn id
containsDecl mn id@InlineSig{} = containsInlineSig mn id
containsDecl _ _ = []
-- | Creates a list of (Module "mn",TypeSynonym "tsn") pairs for a top-level
-- type (TypeDecl) declarations.
containsType :: String -- ^ Name of the module
-> Decl SrcSpanInfo -- ^ The top-level declaration
-> [(MetaModel.Element,MetaModel.Element)] -- ^ list of (Module "mn",TypeSynonym "tsn") pairs
containsType mn d = case d of
(TypeDecl _ h _) -> [(p,c)]
where
p = MetaModel.Module mn
c = MetaModel.TypeSynonym $ makeQualifiedId mn $ DeclHead.name h
_ -> []
-- | Creates a list of (Element,Element) pairs for a top-level data (DataDecl)
-- declaration.
containsData :: String -- ^ Name of the module
-> Decl SrcSpanInfo -- ^ The top-level declaration
-> [(MetaModel.Element,MetaModel.Element)] -- ^ list of (Element,Element) pairs
containsData mn d = case Decl.dataConstructor d of
Just a -> cdc a
where
me = MetaModel.Module mn -- module element
dcn = Decl.dataConstructorName a -- dcn = data constructor name
dce = MetaModel.DataType $ makeQualifiedId mn dcn -- dce = data constructor element
-- Creates `Contain` relation for the data constructor.
cdc :: Decl.DataConstructor -> [(MetaModel.Element,MetaModel.Element)] -- cdc = contains data constructor
cdc dc = (me,dce) : cvcs
where
vcs = Decl.valueConstructors dc -- vcs = value constructors
cvcs = concat [cvc vc | vc <- vcs] -- cvcs = `Contains` relation for sub value constructors
-- Creates `Contain` relation for the value constructor.
cvc :: Decl.ValueConstructor -> [(MetaModel.Element,MetaModel.Element)] -- cvc = contains value constructor
cvc vc = mvcr : dvcr : cfs
where
mvcr = (me,vce) -- Module `Contains` value constructor relation
dvcr = (dce,vce) -- Data `Contains` value constructor relation
vce = MetaModel.Function $ makeQualifiedId mn vcn -- vce = value constructor element
vcn = Decl.valueConstructorName vc -- vcn = value constructor name
cfs = concat [cf f | f <- Decl.valueConstructorFields vc] -- cfs = `Contains` relation for sub fields (if present)
-- Creates `Contain` relation for the supplied field
cf :: Decl.Field -> [(MetaModel.Element,MetaModel.Element)]
cf f = mfr ++ dfr
where
mfr = [(me,fe) | fe <- fes] -- Module `Contains` field relation
dfr = [(dce,fe) | fe <- fes] -- Data `Contains` field relation
fes = [MetaModel.Function (makeQualifiedId mn n) | n <- Decl.fieldNames f] -- fes = field elements
Nothing -> []
-- | Creates a list of (Module "mn",Function "fn") pairs for a top-level pattern
-- (PatBind) declaration.
containsPattern :: String -- ^ Name of the module
-> Decl SrcSpanInfo -- ^ The top-level declaration
-> [(MetaModel.Element,MetaModel.Element)] -- ^ list of (Module "mn",Function "fn") pairs
containsPattern mn pb@PatBind{} = case Decl.patternName pb of
Just pn -> [(p,c)]
where
p = MetaModel.Module mn
c = MetaModel.Function $ makeQualifiedId mn pn
Nothing -> []
-- | Creates a list of (Module "mn",Function "fn") pairs for a top-level
-- function (FunBind) declaration.
containsFunction :: String -- ^ Name of the module
-> Decl SrcSpanInfo -- ^ The top-level declaration
-> [(MetaModel.Element,MetaModel.Element)] -- ^ list of (Module "mn",Function "fn") pairs
containsFunction mn fb@FunBind{} = case Decl.functionName fb of
Just pn -> [(p,c)]
where
p = MetaModel.Module mn
c = MetaModel.Function $ makeQualifiedId mn pn
Nothing -> []
-- | Creates a list of (Module "m", TypeSignature "ts") pairs for TypeSignature declarations.
containsTypeSig :: String -- ^ The module name.
-> Decl SrcSpanInfo -- ^ The Declaration with var l.
-> [(MetaModel.Element,MetaModel.Element)] -- ^ list of (Module "m", TypeSignature "ts") pairs.
containsTypeSig mn tysig@TypeSig{} = case Decl.typeSigName tysig of
Just tsn -> [(m,ts)]
where m = MetaModel.Module mn
ts = MetaModel.TypeSignature $ makeQualifiedId mn tsn
Nothing -> []
-- | Creates a list of (Module "m",TypeClass "tc") pairs for TypeClass declarations.
containsTypeClass :: String -- ^ The module name.
-> Decl SrcSpanInfo -- ^ The Declaration with var l.
-> [(MetaModel.Element,MetaModel.Element)] -- ^ list of (Module "m",TypeClass "tc") pairs.
containsTypeClass mn tycla@ClassDecl{} = case Decl.typeClassName tycla of
Just tcn -> [(m,tc)]
where m = MetaModel.Module mn
tc = MetaModel.TypeClass $ makeQualifiedId mn tcn
Nothing -> []
-- | Creates a list of (Module "m",Instance "i") pairs for Instance declarations.
containsInstance :: String -- ^ The module name.
-> Decl SrcSpanInfo -- ^ The Declaration with var l.
-> [(MetaModel.Element,MetaModel.Element)] -- ^ list of (Module "m",Instance "i") pairs.
containsInstance mn inst@InstDecl{} = case Decl.instanceName inst of
Just inm -> [(m,i)]
where m = MetaModel.Module mn
i = MetaModel.Instance $ makeQualifiedId mn inm
Nothing -> []
-- | Creates a list of (Module "m",Pragma "p") pairs for Instance declarations.
containsInlineSig :: String -- ^ The module name.
-> Decl SrcSpanInfo -- ^ The Declaration with var l.
-> [(MetaModel.Element,MetaModel.Element)] -- ^ list of (Module "m",Pragma "p") pairs.
containsInlineSig mn inlsig@InlineSig{} = case Decl.inlineSigName inlsig of
Just inm -> [(m,i)]
where m = MetaModel.Module mn
i = MetaModel.Pragma $ makeQualifiedId mn inm
Nothing -> []