Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

updated for ghc 8.4.2; released source code as a library #7

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@ cabal-dev
cabal.sandbox.config
cabal.config
TAGS
*.DS_Store
12 changes: 6 additions & 6 deletions Analyse.hs → Language/Haskell/SourceGraph/Analyse.hs
Original file line number Diff line number Diff line change
Expand Up @@ -27,13 +27,13 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

Analyse Haskell software
-}
module Analyse(analyse, sgLegend) where
module Language.Haskell.SourceGraph.Analyse(analyse, sgLegend) where

import Analyse.Module
import Analyse.Imports
import Analyse.Everything
import Analyse.Colors
import Parsing.Types
import Language.Haskell.SourceGraph.Analyse.Module
import Language.Haskell.SourceGraph.Analyse.Imports
import Language.Haskell.SourceGraph.Analyse.Everything
import Language.Haskell.SourceGraph.Analyse.Colors
import Language.Haskell.SourceGraph.Parsing.Types

import Data.Graph.Analysis hiding (Bold)
import qualified Data.Graph.Analysis.Reporting as R (DocInline(Bold))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

Utility functions and types for analysis.
-}
module Analyse.Colors where
module Language.Haskell.SourceGraph.Analyse.Colors where

import Data.GraphViz.Attributes

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

Analysis of the entire overall piece of software.
-}
module Analyse.Everything(analyseEverything) where
module Language.Haskell.SourceGraph.Analyse.Everything(analyseEverything,codeToGraph) where

import Parsing.Types
import Analyse.Utils
import Analyse.GraphRepr
import Analyse.Visualise
import Language.Haskell.SourceGraph.Parsing.Types
import Language.Haskell.SourceGraph.Analyse.Utils
import Language.Haskell.SourceGraph.Analyse.GraphRepr
import Language.Haskell.SourceGraph.Analyse.Visualise

import Data.Graph.Analysis

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

Interacting with GraphData from Graphalyze.
-}
module Analyse.GraphRepr
module Language.Haskell.SourceGraph.Analyse.GraphRepr
( -- * General stuff
GData(..)
, mapData
Expand Down Expand Up @@ -62,9 +62,9 @@ module Analyse.GraphRepr
, ModGraph
) where

import Analyse.Colors
import Analyse.Utils
import Parsing.Types
import Language.Haskell.SourceGraph.Analyse.Colors
import Language.Haskell.SourceGraph.Analyse.Utils
import Language.Haskell.SourceGraph.Parsing.Types

import Data.Graph.Analysis
import Data.Graph.Inductive
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

Analysis of Haskell module importing.
-}
module Analyse.Imports (analyseImports) where
module Language.Haskell.SourceGraph.Analyse.Imports (analyseImports) where

import Parsing.Types
import Analyse.Utils
import Analyse.GraphRepr
import Analyse.Visualise
import Language.Haskell.SourceGraph.Parsing.Types
import Language.Haskell.SourceGraph.Analyse.Utils
import Language.Haskell.SourceGraph.Analyse.GraphRepr
import Language.Haskell.SourceGraph.Analyse.Visualise

import Data.Graph.Analysis

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

Analysis of Haskell modules.
-}
module Analyse.Module(analyseModules) where
module Language.Haskell.SourceGraph.Analyse.Module(analyseModules,moduleToGraph) where

import Parsing.Types
import Analyse.Utils
import Analyse.GraphRepr
import Analyse.Visualise
import Language.Haskell.SourceGraph.Parsing.Types
import Language.Haskell.SourceGraph.Analyse.Utils
import Language.Haskell.SourceGraph.Analyse.GraphRepr
import Language.Haskell.SourceGraph.Analyse.Visualise

import Data.Graph.Analysis

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

Utility functions and types for analysis.
-}
module Analyse.Utils where
module Language.Haskell.SourceGraph.Analyse.Utils where

import Data.Graph.Analysis hiding (Bold)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,12 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

Utility functions and types for analysis.
-}
module Analyse.Visualise where
module Language.Haskell.SourceGraph.Analyse.Visualise where

import Analyse.Colors
import Analyse.GraphRepr
import Analyse.Utils
import Parsing.Types
import Language.Haskell.SourceGraph.Analyse.Colors
import Language.Haskell.SourceGraph.Analyse.GraphRepr
import Language.Haskell.SourceGraph.Analyse.Utils
import Language.Haskell.SourceGraph.Parsing.Types

import Data.Graph.Analysis hiding (Bold)
import Data.GraphViz
Expand Down
30 changes: 26 additions & 4 deletions CabalInfo.hs → Language/Haskell/SourceGraph/CabalInfo.hs
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
{-# LANGUAGE CPP #-}
#if !defined(MIN_VERSION_Cabal)
# define MIN_VERSION_Cabal(a,b,c) 0
#endif

{-
Copyright (C) 2009 Ivan Lazar Miljenovic <[email protected]>

Expand Down Expand Up @@ -27,14 +32,18 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

Used to parse and obtain information from the provided Cabal file.
-}
module CabalInfo(parseCabal) where
module Language.Haskell.SourceGraph.CabalInfo(parseCabal) where

import Distribution.Compiler (CompilerInfo)
import Distribution.ModuleName (toFilePath)
import Distribution.Package
import Distribution.PackageDescription hiding (author)
import Distribution.PackageDescription.Configuration
#if MIN_VERSION_Cabal(2,0,0)
import Distribution.PackageDescription.Parsec
#else
import Distribution.PackageDescription.Parse
#endif
import Distribution.Simple.Compiler (compilerInfo)
import Distribution.Simple.GHC (configure)
import Distribution.Simple.Program (defaultProgramConfiguration)
Expand All @@ -49,6 +58,19 @@ import System.FilePath (dropExtension)

-- -----------------------------------------------------------------------------

emptyFlagAssignment :: FlagAssignment
#if MIN_VERSION_Cabal(2,0,0)
emptyFlagAssignment = mkFlagAssignment []
#else
emptyFlagAssignment = []
#endif

#if MIN_VERSION_Cabal(2,0,0)
readDescription = readGenericPackageDescription
#else
readDescription = readPackageDescription
#endif

ghcID :: IO CompilerInfo
ghcID = liftM (compilerInfo . getCompiler)
$ configure silent Nothing Nothing defaultProgramConfiguration
Expand All @@ -61,10 +83,10 @@ parseCabal fp = do cID <- ghcID
where
-- Need to specify the Exception type
getDesc :: FilePath -> IO (Either SomeException GenericPackageDescription)
getDesc = try . readPackageDescription silent
getDesc = try . readDescription silent
parseDesc cID = fmap parse . compactEithers . fmap (unGeneric cID)
unGeneric cID = fmap fst
. finalizePackageDescription [] -- flags, use later
. finalizePackageDescription emptyFlagAssignment -- flags, use later
(const True) -- ignore
-- deps
buildPlatform
Expand All @@ -73,7 +95,7 @@ parseCabal fp = do cID <- ghcID
parse pd = (nm, exps)
where
nm = pName . pkgName $ package pd
pName (PackageName nm') = nm'
pName nm' = unPackageName nm'
exes = filter (buildable . buildInfo) $ executables pd
lib = library pd
moduleNames = map toFilePath
Expand Down
177 changes: 177 additions & 0 deletions Language/Haskell/SourceGraph/Parsing.hs
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
{-
Copyright (C) 2009 Ivan Lazar Miljenovic <[email protected]>

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 : Parsing
Description : Parse the given Haskell modules.
Copyright : (c) Ivan Lazar Miljenovic 2009
License : GPL-3 or later.
Maintainer : [email protected]

Parse the given Haskell modules.
-}
module Language.Haskell.SourceGraph.Parsing where

import Language.Haskell.SourceGraph.Parsing.Types
import Language.Haskell.SourceGraph.Parsing.ParseModule

import Language.Haskell.Exts(parseFileContentsWithMode)
import Language.Haskell.Exts.Parser( ParseMode(..)
, ParseResult(..)
, defaultParseMode)
import Language.Haskell.Exts.Syntax(Module)
import Language.Haskell.Exts.SrcLoc

import Data.Either(partitionEithers)

import Control.Exception
import Control.Monad
import Data.Maybe
import Data.Char

import System.Directory( getCurrentDirectory
, doesDirectoryExist
, doesFileExist
, getDirectoryContents)
import System.FilePath( dropFileName
, takeExtension
, isPathSeparator
, (</>)
, (<.>))

type FileContents = (FilePath,String)

-- | Parse all the files and return the map.
-- This uses laziness to evaluate the 'HaskellModules' result
-- whilst also using it to parse all the modules to create it.
parseHaskell :: [FileContents] -> ([FilePath],ParsedModules)
parseHaskell fc = (failed,hms)
where
(failed,ms) = parseFiles fc
hms = createModuleMap hss
hss = map (parseModule hms) ms

-- | Attempt to parse an individual file.
parseFile :: FileContents -> Either FilePath (Module SrcSpanInfo)
parseFile (p,f) = case (parseFileContentsWithMode mode f) of
(ParseOk hs) -> Right hs
_ -> Left p
where
mode = defaultParseMode { parseFilename = p
, fixities = Nothing
}

-- | Parse all the files that you can.
parseFiles :: [FileContents] -> ([FilePath],[Module SrcSpanInfo])
parseFiles = partitionEithers . map parseFile

-- | Read in all the files that it can.
readFiles :: [FilePath] -> IO [FileContents]
readFiles = liftM catMaybes . mapM readFileContents

-- | Try to read the given file.
readFileContents :: FilePath -> IO (Maybe FileContents)
readFileContents f = do cnts <- try $ readFile f
case cnts of
(Right str) -> return $ Just (f,str)
(Left SomeException{}) -> return Nothing

-- -----------------------------------------------------------------------------

-- | Recursively parse all files from this directory
parseFilesFrom :: FilePath -> IO ([FilePath],ParsedModules)
parseFilesFrom fp = parseHaskellFiles =<< getHaskellFilesFrom fp

parseHaskellFiles :: [FilePath] -> IO ([FilePath],ParsedModules)
parseHaskellFiles = liftM parseHaskell . readFiles

-- Reading in the files.

-- | Recursively find all Haskell source files from the current directory.
getHaskellFilesFrom :: FilePath -> IO [FilePath]
getHaskellFilesFrom fp
= do isDir <- doesDirectoryExist fp -- Ensure it's a directory.
if isDir
then do r <- try getFilesIn -- Ensure we can read the directory.
case r of
(Right fs) -> return fs
(Left SomeException{}) -> return []
else return []
where
-- Filter out "." and ".." to stop infinite recursion.
nonTrivialContents :: IO [FilePath]
nonTrivialContents = do contents <- getDirectoryContents fp
let contents' = filter (not . isTrivial) contents
return $ map (fp </>) contents'
getFilesIn :: IO [FilePath]
getFilesIn = do contents <- nonTrivialContents
(dirs,files) <- partitionM doesDirectoryExist contents
let hFiles = filter isHaskellFile files
recursiveFiles <- concatMapM getHaskellFilesFrom dirs
return (hFiles ++ recursiveFiles)

-- | A version of 'concatMap' for use in monads.
concatMapM :: (Monad m) => (a -> m [b]) -> [a] -> m [b]
concatMapM f = liftM concat . mapM f

-- | Determine if this is the path of a Haskell file.
isHaskellFile :: FilePath -> Bool
isHaskellFile fp = any (`hasExt` fp) haskellExtensions

hasExt :: String -> FilePath -> Bool
hasExt ext = (==) ext . drop 1 . takeExtension

fpToModule :: FilePath -> ModName
fpToModule = createModule . map pSep
where
pSep c
| isPathSeparator c = moduleSep
| otherwise = c

-- -----------------------------------------------------------------------------

haskellExtensions :: [FilePath]
haskellExtensions = ["hs","lhs"]

-- | A version of 'partition' for use in monads.
partitionM :: (Monad m) => (a -> m Bool) -> [a] -> m ([a], [a])
partitionM _ [] = return ([],[])
partitionM p (x:xs) = do ~(ts,fs) <- partitionM p xs
matches <- p x
if matches
then return (x:ts,fs)
else return (ts,x:fs)

-- | Trivial paths are the current directory, the parent directory and
-- such directories
isTrivial :: FilePath -> Bool
isTrivial "." = True
isTrivial ".." = True
isTrivial "_darcs" = True
isTrivial "dist" = True
isTrivial "HLInt.hs" = True
isTrivial f | isSetup f = True
isTrivial _ = False

lowerCase :: String -> String
lowerCase = map toLower

isSetup :: String -> Bool
isSetup f = lowerCase f `elem` map ("setup" <.>) haskellExtensions
Loading