packages feed

SourceGraph 0.5.0.0 → 0.5.1.0

raw patch · 5 files changed

+119/−40 lines, 5 files

Files

Analyse/Everything.hs view
@@ -43,8 +43,8 @@ import System.Random(RandomGen)  -- | Performs analysis of the entire codebase.-analyseEverything :: (RandomGen g) => g -> [ModName] -> ParsedModules-                  -> DocElement+analyseEverything           :: (RandomGen g) => g -> [ModName] -> ParsedModules+                            -> DocElement analyseEverything g exps hm = Section sec elems     where       cd = codeToGraph exps hm@@ -87,7 +87,7 @@  clustersOf      :: (RandomGen g) => g -> HSData -> Maybe DocElement clustersOf g cd = Just $ Section sec [ text, gc, textAfter-                                     , blank, cwMsg, cw, blank, rngMsg, rng]+                                     , blank, cwMsg, cw] -- , blank, rngMsg, rng]     where       blank = Paragraph [BlankSpace]       sec = Text "Visualisation of overall function calls"@@ -95,15 +95,18 @@       text = Paragraph              [Text "Here is the current module grouping of functions:"]       lbl = "Current module groupings"-      textAfter = Paragraph [Text "Here are two proposed module groupings:"]+      textAfter = Paragraph [Text "Here is a proposed alternate module grouping:"]+                  -- [Text "Here are two proposed module groupings:"]       cwMsg = Paragraph [Emphasis $ Text "Using the Chinese Whispers algorithm:"]       cw = GraphImage ("codeCW", Text cwLbl, drawClusters cwLbl (chineseWhispers g) cd)       cwLbl = "Chinese Whispers module suggestions"+{-       rngMsg = Paragraph [Emphasis $ Text "Using the Relative Neighbourhood algorithm:"]       rng = GraphImage ("codeRNG", Text rngLbl, drawClusters lbl relNbrhd cd)       -- Being naughty to avoid having to define drawClusters'       relNbrhd = relativeNeighbourhood $ directedData cd       rngLbl = "Relative Neighbourhood module suggestions"+-}  componentAnal :: HSData -> Maybe DocElement componentAnal cd
Analyse/Utils.hs view
@@ -37,7 +37,7 @@ import Data.GraphViz  import Data.List(groupBy, sortBy)-import Data.Maybe(isJust)+-- import Data.Maybe(isJust) import Data.Function(on) import qualified Data.Set as S import Data.Set(Set)@@ -240,7 +240,11 @@ clustAttributes' = return . GraphAttrs . clustAttributes  modClustAttrs   :: ModName -> [GlobalAttributes]-modClustAttrs m = [GraphAttrs [Label . StrLabel $ nameOfModule m]]+modClustAttrs m = [GraphAttrs [ Label . StrLabel $ nameOfModule m+                              , Style [SItem Filled []]+                              , FillColor $ ColorName "wheat1"+                              ]+                  ]  -- ----------------------------------------------------------------------------- @@ -249,11 +253,15 @@ drawClusters gid cf dg = setID (Str gid)                          $ graphvizClusters dg'                                             gAttrs-                                            (const [])+                                            (const cAttr)                                             nAttr                                             callAttributes'     where       gAttrs = [] -- [GraphAttrs [Label $ StrLabel t]]+      cAttr = [GraphAttrs [ Style [SItem Filled []]+                          , FillColor $ ColorName "wheat1"+                          ]+              ]       dg' = updateGraph (compactSame . cf . collapseStructures') dg       rs = getRoots dg       ls = getLeaves dg
+ ChangeLog view
@@ -0,0 +1,19 @@+Changes since 0.5.1.0+=====================++* Add support for passing a single Haskell source file rather than a+  Cabal file as the argument, as requested by Curt Sampson.++* Shade backgrounds of modules when clustering Entities.++* RelativeNeighbourhood doesn't provide good alternate modules and+  takes up too much runtime, and so has been removed.++Changes since 0.5.0.0+=====================++* Re-write of parsing.++* Usage of new graphviz and Graphalyze features.++* More abstraction into common routines into Analyse.Utils
Main.hs view
@@ -31,6 +31,7 @@ module Main where  import Parsing+import Parsing.Types(nameOfModule) import Analyse  import Data.Graph.Analysis@@ -44,15 +45,16 @@  import Data.Char(toLower) import Data.List(nub)-import Data.Maybe(isJust, fromJust, listToMaybe, catMaybes)+import Data.Maybe(isJust, fromJust, catMaybes)+import qualified Data.Map as M import System.IO(hPutStrLn, stderr) import System.Directory( getCurrentDirectory                        , doesDirectoryExist+                       , doesFileExist                        , getDirectoryContents) import System.FilePath( dropFileName                       , dropExtension                       , takeExtension-                      , extSeparator                       , isPathSeparator                       , (</>)                       , (<.>))@@ -68,22 +70,16 @@  main :: IO () main = do input <- getArgs-          let mcbl = getCabalFile input-          case mcbl of-            Nothing-                -> putErrLn "Please pass in a .cabal file"-            Just cbl-                -> do pcbl <- parseCabal cbl-                      case pcbl of-                        Nothing-                            -> putErrLn $ unwords [cbl,"is unparseable"]-                        Just (nm,exps)-                            -> do let dir = dropFileName cbl-                                  dir' <- if null dir-                                            then getCurrentDirectory-                                            else return dir-                                  hms <- parseFilesFrom dir'-                                  analyseCode dir nm exps hms+          mInfo <- getPkgInfo input+          case mInfo of+            Nothing -> putErrLn "No parseable package information found."+            Just (f,(nm,exps))+                -> do let dir = dropFileName f+                      dir' <- if null dir+                                then getCurrentDirectory+                                else return dir+                      hms <- parseFilesFrom dir'+                      analyseCode dir nm exps hms  programmeName :: String programmeName = "SourceGraph"@@ -96,6 +92,24 @@  -- ----------------------------------------------------------------------------- +getPkgInfo :: [String] -> IO (Maybe (FilePath, (String, [ModName])))+getPkgInfo [] = do putErrLn "Please provide either a Cabal file \+                            \or a Haskell source file as an argument."+                   return Nothing+getPkgInfo [f]+    | isCabalFile f   = withF parseCabal+    | isHaskellFile f = withF parseMain+    where+      withF func = do ex <- doesFileExist f+                      if ex+                         then addF $ func f+                         else do putErrLn "The provided file does not exist."+                                 return Nothing+      addF = fmap (fmap ((,) f))+getPkgInfo _        = do putErrLn "Please provide a single Cabal \+                                  \or Haskell source file as an argument."+                         return Nothing+ parseCabal    :: FilePath -> IO (Maybe (String, [ModName])) parseCabal fp = do gpd <- try $ readPackageDescription silent fp                    case gpd of@@ -121,11 +135,21 @@                  | otherwise        = error "No exposed modules"             exps' = map fpToModule exps -getCabalFile :: [FilePath] -> Maybe FilePath-getCabalFile = listToMaybe . filter isCabalFile-    where-      isCabalFile f  = takeExtension f == extSeparator : "cabal"+isCabalFile :: FilePath -> Bool+isCabalFile = hasExt "cabal" +parseMain    :: FilePath -> IO (Maybe (String, [ModName]))+parseMain fp = do pms <- parseHaskellFiles [fp]+                  let mn = fst $ M.findMin pms+                  return $ Just (nameOfModule mn, [mn])++-- | Determine if this is the path of a Haskell file.+isHaskellFile    :: FilePath -> Bool+isHaskellFile fp = any (flip hasExt fp) haskellExtensions++hasExt     :: String -> FilePath -> Bool+hasExt ext = (==) ext . drop 1 . takeExtension+ fpToModule :: FilePath -> ModName fpToModule = createModule . map pSep     where@@ -137,10 +161,11 @@  -- | Recursively parse all files from this directory parseFilesFrom    :: FilePath -> IO ParsedModules-parseFilesFrom fp = do files <- getHaskellFilesFrom fp-                       cnts <- readFiles files-                       return $ parseHaskell cnts+parseFilesFrom fp = parseHaskellFiles =<< getHaskellFilesFrom fp +parseHaskellFiles :: [FilePath] -> IO ParsedModules+parseHaskellFiles = liftM parseHaskell . readFiles+ -- -----------------------------------------------------------------------------  -- Reading in the files.@@ -168,12 +193,8 @@                       recursiveFiles <- concatMapM getHaskellFilesFrom dirs                       return (hFiles ++ recursiveFiles) --- | Determine if this is the path of a Haskell file.-isHaskellFile   :: FilePath -> Bool-isHaskellFile f = takeExtension f `elem` haskellExtensions- haskellExtensions :: [FilePath]-haskellExtensions = map (extSeparator :) ["hs","lhs"]+haskellExtensions = ["hs","lhs"]  -- | Read in all the files that it can. readFiles :: [FilePath] -> IO [FileContents]
SourceGraph.cabal view
@@ -1,8 +1,35 @@ Name:                SourceGraph-Version:             0.5.0.0+Version:             0.5.1.0 Synopsis:            Use graph-theory to analyse your code-Description:         SourceGraph uses the Graphalyze library to analyse-                     Cabalized Haskell code.+Description: {+Statically analyse Haskell source code using graph-theoretic+techniques.+.+To use SourceGraph, call it as either:+.+> SourceGraph path/to/Foo.cabal+.+Or, if your project doesn't use Cabal, then there is limited support+for using an overall module from your program\/library:+.+> SourceGraph path/to/Foo.hs+.+Note that the Cabal method is preferred, as it is better able to+determine the project name and exported modules (when passing a+Haskell file to SourceGraph, it uses that module's name as the overall+name of project and assumes that it is the only exported module; as+such, it works better for programs than libraries).+.+Whichever way your run SourceGraph, it then creates a @SourceGraph@+subdirectory in the same directory as the file that was passed to it,+and within that subdirectory creates the analysis report in+@Foo.html@.+.+SourceGraph is still experimental in terms of its ability to parse and+properly understand Haskell source code and in the types of analyses+it performs.+}+ Category:            Development License:             GPL License-file:        COPYRIGHT@@ -12,6 +39,7 @@ Cabal-Version:       >= 1.6 Build-Type:          Simple Extra-Source-Files: TODO+                    ChangeLog                     KnownProblems.txt                     ParsingProblems.txt