src/CC/ShellCheck/Fingerprint.hs
{-# LANGUAGE OverloadedStrings #-}
module CC.ShellCheck.Fingerprint
( issueFingerprint
) where
import Data.Char (isSpace)
import Data.Maybe (fromMaybe)
import Data.Text (Text)
import Data.Text.Lazy (fromStrict)
import Data.Text.Lazy.Encoding (encodeUtf8)
import ShellCheck.Interface
( Comment(..)
, Position(..)
, PositionedComment(..)
)
import qualified Data.Digest.Pure.MD5 as MD5
import qualified Data.Text as T
-- | Given a positioned comment and the file's contents, generate a fingerprint
-- unique to that issue
issueFingerprint :: PositionedComment -> Text -> Text
issueFingerprint pc script =
md5 $ T.intercalate "|"
[ T.pack $ posFile pos
, T.pack $ show code
, T.filter (not . isSpace) $ fetchLine (fromIntegral $ posLine pos) script
]
where
pos = pcStartPos pc
comment = pcComment pc
code = cCode comment
md5 :: Text -> Text
md5 = T.pack . show . MD5.md5 . encodeUtf8 . fromStrict
fetchLine :: Int -> Text -> Text
fetchLine idx = fromMaybe "" . safeIndex (idx - 1) . T.lines
safeIndex :: Int -> [a] -> Maybe a
safeIndex idx xs
| idx >= 0 && idx < length xs = Just $ xs !! idx
| otherwise = Nothing