1
1
mirror of https://github.com/github/semantic.git synced 2024-12-26 08:25:19 +03:00
semantic/test/SpecHelpers.hs

110 lines
3.6 KiB
Haskell

{-# LANGUAGE DataKinds, GADTs, ScopedTypeVariables, TypeFamilies, TypeOperators, TypeApplications #-}
module SpecHelpers
( file
, evaluateFiles
, diffFilePaths
, parseFilePath
, readFilePair
, languageForFilePath
, Verbatim(..)
, verbatim
, readFileVerbatim
) where
import Control.Monad ((<=<))
import Control.Monad.IO.Class
import Control.Exception
import Data.Blob
import qualified Data.ByteString as B
import Data.Functor.Both
import Data.Language
import Data.Maybe (fromMaybe, fromJust)
import Data.Source
import Rendering.Renderer
import Semantic
import Semantic.Task
import qualified Semantic.IO as IO
import System.FilePath
import qualified Data.Text as T
import Data.Text.Encoding (decodeUtf8)
import Analysis.Abstract.Evaluating
import Data.Map as Map
import Data.Union
import Data.Semigroup
import Data.Functor.Foldable
import Data.Abstract.Evaluatable
import Data.Abstract.Address
import Data.Abstract.Environment
import Data.Abstract.FreeVariables
import Data.Abstract.ModuleTable
import Data.Abstract.Store
import Data.Abstract.Value as Value
import Parsing.Parser
file :: MonadIO m => FilePath -> m Blob
file path = fromJust <$> IO.readFile path (IO.languageForFilePath path)
evaluateFiles :: forall v term.
( Data.Abstract.Evaluatable.Evaluatable (Data.Functor.Foldable.Base term)
, FreeVariables term
, MonadAddressable (LocationFor v) v (Evaluation term v)
, MonadValue term v (Evaluation term v)
, Ord (LocationFor v)
, Recursive term
, Semigroup (Cell (LocationFor v) v)
)
=> Parser term
-> [FilePath]
-> IO (
(
(
( Either Prelude.String v
, Store (LocationFor v) v
)
, Map.Map Data.Abstract.FreeVariables.Name (Data.Abstract.FreeVariables.Name, Maybe (Address (LocationFor v) v))
)
, Environment (LocationFor v) v
)
, ModuleTable (Environment (LocationFor v) v)
)
evaluateFiles parser paths = do
blobs@(b:bs) <- traverse file paths
(t:ts) <- runTask $ traverse (parse parser) blobs
pure $ evaluates @v (zip bs ts) (b, t)
-- | Returns an s-expression formatted diff for the specified FilePath pair.
diffFilePaths :: Both FilePath -> IO B.ByteString
diffFilePaths paths = readFilePair paths >>= runTask . diffBlobPair SExpressionDiffRenderer
-- | Returns an s-expression parse tree for the specified FilePath.
parseFilePath :: FilePath -> IO B.ByteString
parseFilePath path = IO.readFile path (languageForFilePath path) >>= pure . fromJust >>= runTask . parseBlob SExpressionTermRenderer
-- | Read two files to a BlobPair.
readFilePair :: Both FilePath -> IO BlobPair
readFilePair paths = let paths' = fmap (\p -> (p, languageForFilePath p)) paths in
runBothWith IO.readFilePair paths'
-- | Returns a Maybe Language based on the FilePath's extension.
languageForFilePath :: FilePath -> Maybe Language
languageForFilePath = languageForType . takeExtension
readFileVerbatim :: FilePath -> IO Verbatim
readFileVerbatim = fmap verbatim . B.readFile
newtype Verbatim = Verbatim B.ByteString
deriving (Eq)
instance Show Verbatim where
show (Verbatim x) = show x
verbatim :: B.ByteString -> Verbatim
verbatim = Verbatim . stripWhitespace
where
stripWhitespace :: B.ByteString -> B.ByteString
stripWhitespace = B.foldl' go B.empty
where go acc x | x `B.elem` " \t\n" = acc
| otherwise = B.snoc acc x