1
1
mirror of https://github.com/github/semantic.git synced 2024-12-27 17:05:33 +03:00
semantic/src/Data/Project.hs

104 lines
3.3 KiB
Haskell
Raw Normal View History

2018-06-13 19:47:35 +03:00
{-# LANGUAGE DeriveAnyClass, KindSignatures, MultiWayIf #-}
2018-06-13 19:47:35 +03:00
module Data.Project (
-- * Projects
ProjectF (..)
, Project
, PBProject
, ProjectException (..)
, fromPB
, projectExtensions
, projectName
, projectFiles
, readFile
-- * Files
, File (..)
, file
) where
2018-04-20 21:10:27 +03:00
2018-06-13 19:47:35 +03:00
import Prelude hiding (readFile)
import Prologue hiding (throwError)
import Control.Effect
2018-06-13 19:47:35 +03:00
import Data.Blob
import Data.Language
import qualified Data.Text as T
import Proto3.Suite
import System.FilePath.Posix
-- | A 'ProjectF' contains all the information that semantic needs
-- to execute an analysis, diffing, or graphing pass. It is higher-kinded
-- in terms of the container type for paths and blobs, as well as the
-- path type (this is necessary because protobuf uses different vector
-- representations for @repeated string@ and @repeated Blob@.
-- You probably want to use the 'Project' or 'PB' type aliases.
data ProjectF (blobs :: * -> *) (paths :: * -> *) path = Project
{ projectRootDir :: path
, projectBlobs :: blobs Blob
, projectLanguage :: Language
2018-06-13 19:47:35 +03:00
, projectExcludeDirs :: paths path
} deriving (Functor, Generic)
deriving instance (Eq path, Eq (blobs Blob), Eq (paths path)) => Eq (ProjectF blobs paths path)
deriving instance (Show path, Show (blobs Blob), Show (paths path)) => Show (ProjectF blobs paths path)
-- | This 'Project' type is the one used during semantic's normal
-- course of diffing, evaluation, and graphing. You probably want to
-- use this one.
type Project = ProjectF [] [] FilePath
-- | This 'Project' type is protobuf-compatible, and corresponds with
-- the @Project@ message declaration present in types.proto.
type PBProject = ProjectF NestedVec UnpackedVec Text
deriving instance Message PBProject
instance Named PBProject where nameOf _ = "Project"
-- | Convert from a packed protobuf representation to a more useful one.
fromPB :: PBProject -> Project
fromPB Project {..} = Project
{ projectRootDir = T.unpack projectRootDir
, projectBlobs = toList projectBlobs
, projectLanguage = projectLanguage
, projectExcludeDirs = T.unpack <$> toList projectExcludeDirs
2018-06-11 21:43:35 +03:00
}
2018-06-08 19:41:07 +03:00
2018-06-12 21:10:28 +03:00
projectName :: Project -> Text
projectName = T.pack . dropExtensions . takeFileName . projectRootDir
2018-06-12 21:10:28 +03:00
projectExtensions :: Project -> [String]
projectExtensions = extensionsForLanguage . projectLanguage
2018-06-13 19:47:35 +03:00
projectFiles :: Project -> [File]
projectFiles = fmap toFile . projectBlobs
2018-06-08 19:41:07 +03:00
data File = File
{ filePath :: FilePath
, fileLanguage :: Language
} deriving (Eq, Ord, Show)
file :: FilePath -> File
file path = File path (languageForFilePath path)
where languageForFilePath = languageForType . takeExtension
2018-06-13 19:47:35 +03:00
-- This is kind of a wart; Blob and File should be two views of
-- the same higher-kinded datatype.
toFile :: Blob -> File
toFile (Blob _ p l) = File p l
newtype ProjectException
= FileNotFound FilePath
deriving (Show, Eq, Typeable, Exception)
readFile :: (Member (Error SomeException) sig, Applicative m, Carrier sig m)
2018-06-13 19:47:35 +03:00
=> Project
-> File
-> m (Maybe Blob)
2018-06-13 19:47:35 +03:00
readFile Project{..} f =
let p = filePath f
candidate = find (\b -> blobPath b == p) projectBlobs
in if
| p == "/dev/null" -> pure Nothing
| isJust candidate -> pure candidate
| otherwise -> throwError (SomeException (FileNotFound p))