homplexity-0.2: Language/Haskell/Homplexity/SrcSlice.hs
{-# LANGUAGE RecordWildCards #-}
{-# LANGUAGE FlexibleInstances #-}
-- | Showing references to slices of code
module Language.Haskell.Homplexity.SrcSlice (
SrcSlice
, srcSlice
, srcLoc
, showSrcSpan
, mergeSrcLocs
, sliceFirstLine
, sliceLastLine
, sliceFilename
) where
import Data.Data
import Data.Generics.Uniplate.Data
import Data.List
import Control.Arrow
import Control.Exception (assert)
import Language.Haskell.Exts.Syntax
import Language.Haskell.Exts
import Language.Haskell.Exts.SrcLoc
-- * Slice of code
type SrcSlice = SrcSpan
sliceFilename = srcSpanFilename
sliceFirstLine = srcSpanStartLine
sliceLastLine = srcSpanEndLine
srcLoc :: (Data code, Show code) => code -> SrcLoc
srcLoc code = checkHead $
universeBi code
where
msg = "Cannot find SrcLoc in the code fragment: " ++ show code
checkHead [] = error msg
checkHead (e:es) = e
-- | Compute the slice of code that given source fragment is in (for naming)
srcSlice code = mergeSrcLocs
. checkNonEmpty
. universeBi $ code
where
checkNonEmpty [] = error $ "Can't know how make a SrcSlice from code fragment: " ++ show code
checkNonEmpty other = other
mergeSrcLocs :: [SrcLoc] -> SrcSpan
mergeSrcLocs [] = error "Don't know how make a SrcSpan from an empty list of locations!"
mergeSrcLocs sliceLocs = assert (allEqual $ map srcFilename sliceLocs) $
SrcSpan {..}
where
srcSpanFilename = srcFilename $ head sliceLocs
((srcSpanStartLine, srcSpanStartColumn),
(srcSpanEndLine, srcSpanEndColumn )) = (minimum &&& maximum) $
map (srcLine &&& srcColumn) sliceLocs
allEqual :: Eq a => [a] -> Bool
allEqual [] = True
allEqual (b:bs) = all (b==) bs
showSrcSpan :: SrcSpan -> ShowS
showSrcSpan (SrcSpan {..}) = shows srcSpanFilename
. (':':)
. shows srcSpanStartLine
. ('-':)
. shows srcSpanEndLine