SourceGraph-0.3: Analyse/Imports.hs
{-
Copyright (C) 2008 Ivan Lazar Miljenovic <Ivan.Miljenovic@gmail.com>
This file is part of SourceGraph.
SourceGraph is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-}
{- |
Module : Analyse.Imports
Description : Analyse module imports.
Copyright : (c) Ivan Lazar Miljenovic 2008
License : GPL-3 or later.
Maintainer : Ivan.Miljenovic@gmail.com
Analysis of Haskell module importing.
-}
module Analyse.Imports (analyseImports) where
import Parsing.Types
import Analyse.Utils
import Data.Graph.Analysis
import Data.Maybe
import Text.Printf
type ImportData = GraphData ModuleName
-- | Analyse the imports present in the software. Takes in a random seed
-- as well as a list of all modules exported.
analyseImports :: [ModuleName] -> HaskellModules -> DocElement
analyseImports exps hm = Section sec elems
where
imd = importsToGraph exps hm
sec = Text "Analysis of module imports"
elems = catMaybes
$ map ($imd) [ graphOf
, cycleCompAnal
, rootAnal
, componentAnal
, cycleAnal
, chainAnal
]
importsToGraph :: [ModuleName] -> HaskellModules -> ImportData
importsToGraph exps hms = importData params
where
params = Params { dataPoints = modulesIn hms
, relationships = moduleImports hms
, roots = exps
, directed = True
}
graphOf :: ImportData -> Maybe DocElement
graphOf imd = Just $ Section sec [gi]
where
sec = Text "Visualisation of imports"
gi = GraphImage $ applyAlg dg imd
dg g = toGraph "imports" lbl g
lbl = "Import visualisation"
componentAnal :: ImportData -> Maybe DocElement
componentAnal imd
| single comp = Nothing
| otherwise = Just el
where
comp = applyAlg componentsOf imd
len = length comp
el = Section sec [Paragraph [Text text]]
sec = Text "Import component analysis"
text = printf "The imports have %d components. \
\You may wish to consider splitting the code up." len
cycleAnal :: ImportData -> Maybe DocElement
cycleAnal imd
| null cycs = Nothing
| otherwise = Just el
where
cycs = applyAlg cyclesIn imd
cycs' = return . Itemized
$ map (Paragraph . return . Text . showCycle) cycs
text = Text "The imports have the following cycles:"
textAfter = Text "Whilst this is valid, it may make it difficult \
\to use in ghci, etc."
el = Section sec
$ (Paragraph [text]) : cycs' ++ [Paragraph [textAfter]]
sec = Text "Cycle analysis of imports"
chainAnal :: ImportData -> Maybe DocElement
chainAnal imd
| null chns = Nothing
| otherwise = Just el
where
chns = interiorChains imd
chns' = return . Itemized
$ map (Paragraph . return . Text . showPath) chns
text = Text "The imports have the following chains:"
textAfter = Text "These chains can all be compressed down to \
\a single module."
el = Section sec $
[Paragraph [text]] ++ chns' ++ [Paragraph [textAfter]]
sec = Text "Import chain analysis"
rootAnal :: ImportData -> Maybe DocElement
rootAnal imd
| asExpected = Nothing
| otherwise = Just $ Section sec ps
where
(wntd, ntRs, ntWd) = classifyRoots imd
asExpected = (null ntRs) && (null ntWd)
rpt (s,ns) = if (null ns)
then Nothing
else Just [ Paragraph
[Text
$ concat ["These modules are those that are "
, s, ":"]]
, Paragraph [Emphasis . Text $ showNodes ns]]
ps = concat . catMaybes
$ map rpt [ ("in the export list and roots",wntd)
, ("in the export list but not roots",ntRs)
, ("not in the export list but roots",ntWd)]
sec = Text "Import root analysis"
cycleCompAnal :: ImportData -> Maybe DocElement
cycleCompAnal imd = Just $ Section sec pars
where
cc = cyclomaticComplexity imd
sec = Text "Cyclomatic Complexity of imports"
pars = [Paragraph [text], Paragraph [textAfter, link]]
text = Text
$ printf "The cyclomatic complexity of the imports is: %d" cc
textAfter = Text "For more information on cyclomatic complexity, \
\please see: "
link = DocLink (Text "Wikipedia: Cyclomatic Complexity")
(URL "http://en.wikipedia.org/wiki/Cyclomatic_complexity")