mirror of
https://github.com/github/semantic.git
synced 2024-11-30 14:47:30 +03:00
Start moving Blob around.
This commit is contained in:
parent
6162dbd191
commit
d2bd643745
@ -40,6 +40,7 @@ library
|
|||||||
import: common
|
import: common
|
||||||
hs-source-dirs: src
|
hs-source-dirs: src
|
||||||
exposed-modules:
|
exposed-modules:
|
||||||
|
Analysis.Blob
|
||||||
Analysis.Carrier.Env.Monovariant
|
Analysis.Carrier.Env.Monovariant
|
||||||
Analysis.Carrier.Env.Precise
|
Analysis.Carrier.Env.Precise
|
||||||
Analysis.Carrier.Heap.Monovariant
|
Analysis.Carrier.Heap.Monovariant
|
||||||
|
45
semantic-analysis/src/Analysis/Blob.hs
Normal file
45
semantic-analysis/src/Analysis/Blob.hs
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
|
module Analysis.Blob
|
||||||
|
( Blob (..)
|
||||||
|
, fromSource
|
||||||
|
, blobLanguage
|
||||||
|
, blobPath
|
||||||
|
, nullBlob
|
||||||
|
) where
|
||||||
|
|
||||||
|
import Analysis.File
|
||||||
|
import Data.Aeson
|
||||||
|
import Source.Language as Language
|
||||||
|
import Source.Source as Source
|
||||||
|
import qualified System.Path as Path
|
||||||
|
import qualified System.Path.PartClass as Path.PartClass
|
||||||
|
|
||||||
|
-- | The source, path information, and language of a file read from disk.
|
||||||
|
data Blob = Blob
|
||||||
|
{ blobSource :: Source -- ^ The UTF-8 encoded source text of the blob.
|
||||||
|
, blobFile :: File Language -- ^ Path/language information for this blob.
|
||||||
|
} deriving (Show, Eq)
|
||||||
|
|
||||||
|
instance FromJSON Blob where
|
||||||
|
parseJSON = withObject "Blob" $ \b -> do
|
||||||
|
src <- b .: "content"
|
||||||
|
Right pth <- fmap Path.parse (b .: "path")
|
||||||
|
lang <- b .: "language"
|
||||||
|
let lang' = if knownLanguage lang then lang else Language.forPath pth
|
||||||
|
pure (fromSource (pth :: Path.AbsRelFile) lang' src)
|
||||||
|
|
||||||
|
|
||||||
|
-- | Create a Blob from a provided path, language, and UTF-8 source.
|
||||||
|
-- The resulting Blob's span is taken from the 'totalSpan' of the source.
|
||||||
|
fromSource :: Path.PartClass.AbsRel ar => Path.File ar -> Language -> Source -> Blob
|
||||||
|
fromSource filepath language source
|
||||||
|
= Blob source (Analysis.File.File (Path.toAbsRel filepath) (totalSpan source) language)
|
||||||
|
|
||||||
|
blobLanguage :: Blob -> Language
|
||||||
|
blobLanguage = Analysis.File.fileBody . blobFile
|
||||||
|
|
||||||
|
blobPath :: Blob -> FilePath
|
||||||
|
blobPath = Path.toString . Analysis.File.filePath . blobFile
|
||||||
|
|
||||||
|
nullBlob :: Blob -> Bool
|
||||||
|
nullBlob = Source.null . blobSource
|
@ -3,22 +3,16 @@ module Analysis.Project
|
|||||||
, projectExtensions
|
, projectExtensions
|
||||||
, projectName
|
, projectName
|
||||||
, projectFiles
|
, projectFiles
|
||||||
, readProjectFromPaths
|
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Prelude hiding (readFile)
|
import Prelude hiding (readFile)
|
||||||
|
|
||||||
|
import Analysis.Blob
|
||||||
import Analysis.File
|
import Analysis.File
|
||||||
import Control.Monad.IO.Class
|
|
||||||
import Data.Blob
|
|
||||||
import Data.Blob.IO
|
|
||||||
import Data.Language
|
import Data.Language
|
||||||
import Data.Semilattice.Lower
|
|
||||||
import Data.Text (Text)
|
import Data.Text (Text)
|
||||||
import qualified Data.Text as T
|
import qualified Data.Text as T
|
||||||
import Semantic.IO
|
|
||||||
import System.FilePath.Posix
|
import System.FilePath.Posix
|
||||||
import qualified System.Path as Path
|
|
||||||
|
|
||||||
-- | A 'Project' contains all the information that semantic needs
|
-- | A 'Project' contains all the information that semantic needs
|
||||||
-- to execute an analysis, diffing, or graphing pass.
|
-- to execute an analysis, diffing, or graphing pass.
|
||||||
@ -37,27 +31,3 @@ projectExtensions = extensionsForLanguage . projectLanguage
|
|||||||
|
|
||||||
projectFiles :: Project -> [File Language]
|
projectFiles :: Project -> [File Language]
|
||||||
projectFiles = fmap blobFile . projectBlobs
|
projectFiles = fmap blobFile . projectBlobs
|
||||||
|
|
||||||
readProjectFromPaths :: MonadIO m
|
|
||||||
=> Maybe Path.AbsRelDir -- ^ An optional root directory for the project
|
|
||||||
-> Path.AbsRelFileDir -- ^ A file or directory to parse. Passing a file path loads all files in that file's parent directory.
|
|
||||||
-> Language
|
|
||||||
-> [Path.AbsRelDir] -- ^ Directories to exclude.
|
|
||||||
-> m Project
|
|
||||||
readProjectFromPaths maybeRoot path lang excludeDirs = do
|
|
||||||
let rootDir :: Path.AbsRelDir
|
|
||||||
rootDir = case maybeRoot >>= Path.fromAbsRel of
|
|
||||||
-- If we were provided a root directory, use that.
|
|
||||||
Just root -> root
|
|
||||||
Nothing -> case Path.fileFromFileDir path of
|
|
||||||
-- If we weren't and the path is a file, drop its file name.
|
|
||||||
Just fp -> Path.takeDirectory fp
|
|
||||||
-- Otherwise, load from the path.
|
|
||||||
Nothing -> Path.dirFromFileDir path
|
|
||||||
|
|
||||||
paths <- liftIO $ findFilesInDir rootDir exts excludeDirs
|
|
||||||
blobs <- liftIO $ traverse (readBlobFromFile' . toFile) paths
|
|
||||||
pure $ Project (Path.toString rootDir) blobs lang (fmap Path.toString excludeDirs)
|
|
||||||
where
|
|
||||||
toFile path = File path lowerBound lang
|
|
||||||
exts = extensionsForLanguage lang
|
|
||||||
|
@ -5,9 +5,9 @@
|
|||||||
{-# LANGUAGE FlexibleInstances #-}
|
{-# LANGUAGE FlexibleInstances #-}
|
||||||
{-# LANGUAGE OverloadedStrings #-}
|
{-# LANGUAGE OverloadedStrings #-}
|
||||||
{-# LANGUAGE RecordWildCards #-}
|
{-# LANGUAGE RecordWildCards #-}
|
||||||
|
-- | Semantic-specific functionality for blob handling.
|
||||||
module Data.Blob
|
module Data.Blob
|
||||||
( Blob(..)
|
( Blobs(..)
|
||||||
, Blobs(..)
|
|
||||||
, blobLanguage
|
, blobLanguage
|
||||||
, NoLanguageForBlob (..)
|
, NoLanguageForBlob (..)
|
||||||
, blobPath
|
, blobPath
|
||||||
@ -23,9 +23,11 @@ module Data.Blob
|
|||||||
, languageTagForBlobPair
|
, languageTagForBlobPair
|
||||||
, pathForBlobPair
|
, pathForBlobPair
|
||||||
, pathKeyForBlobPair
|
, pathKeyForBlobPair
|
||||||
|
, module Analysis.Blob
|
||||||
) where
|
) where
|
||||||
|
|
||||||
|
|
||||||
|
import Analysis.Blob
|
||||||
import Analysis.File (File (..))
|
import Analysis.File (File (..))
|
||||||
import Control.Effect.Error
|
import Control.Effect.Error
|
||||||
import Control.Exception
|
import Control.Exception
|
||||||
@ -45,38 +47,10 @@ import qualified System.FilePath as FP
|
|||||||
import qualified System.Path as Path
|
import qualified System.Path as Path
|
||||||
import qualified System.Path.PartClass as Path.PartClass
|
import qualified System.Path.PartClass as Path.PartClass
|
||||||
|
|
||||||
-- | The source, path information, and language of a file read from disk.
|
|
||||||
data Blob = Blob
|
|
||||||
{ blobSource :: Source -- ^ The UTF-8 encoded source text of the blob.
|
|
||||||
, blobFile :: File Language -- ^ Path/language information for this blob.
|
|
||||||
} deriving (Show, Eq)
|
|
||||||
|
|
||||||
blobLanguage :: Blob -> Language
|
|
||||||
blobLanguage = Analysis.File.fileBody . blobFile
|
|
||||||
|
|
||||||
blobPath :: Blob -> FilePath
|
|
||||||
blobPath = Path.toString . Analysis.File.filePath . blobFile
|
|
||||||
|
|
||||||
newtype Blobs a = Blobs { blobs :: [a] }
|
newtype Blobs a = Blobs { blobs :: [a] }
|
||||||
deriving (Generic, FromJSON)
|
deriving (Generic, FromJSON)
|
||||||
|
|
||||||
instance FromJSON Blob where
|
|
||||||
parseJSON = withObject "Blob" $ \b -> do
|
|
||||||
src <- b .: "content"
|
|
||||||
Right pth <- fmap Path.parse (b .: "path")
|
|
||||||
lang <- b .: "language"
|
|
||||||
let lang' = if knownLanguage lang then lang else Language.forPath pth
|
|
||||||
pure (fromSource (pth :: Path.AbsRelFile) lang' src)
|
|
||||||
|
|
||||||
nullBlob :: Blob -> Bool
|
|
||||||
nullBlob Blob{..} = Source.null blobSource
|
|
||||||
|
|
||||||
-- | Create a Blob from a provided path, language, and UTF-8 source.
|
|
||||||
-- The resulting Blob's span is taken from the 'totalSpan' of the source.
|
|
||||||
fromSource :: Path.PartClass.AbsRel ar => Path.File ar -> Language -> Source -> Blob
|
|
||||||
fromSource filepath language source
|
|
||||||
= Blob source (Analysis.File.File (Path.toAbsRel filepath) (totalSpan source) language)
|
|
||||||
|
|
||||||
decodeBlobs :: BL.ByteString -> Either String [Blob]
|
decodeBlobs :: BL.ByteString -> Either String [Blob]
|
||||||
decodeBlobs = fmap blobs <$> eitherDecode
|
decodeBlobs = fmap blobs <$> eitherDecode
|
||||||
|
|
||||||
|
@ -9,6 +9,7 @@ module Data.Blob.IO
|
|||||||
, readFilePair
|
, readFilePair
|
||||||
) where
|
) where
|
||||||
|
|
||||||
|
import Analysis.Blob
|
||||||
import Analysis.File as File
|
import Analysis.File as File
|
||||||
import qualified Control.Concurrent.Async as Async
|
import qualified Control.Concurrent.Async as Async
|
||||||
import Control.Monad.IO.Class
|
import Control.Monad.IO.Class
|
||||||
@ -20,6 +21,32 @@ import Semantic.IO
|
|||||||
import qualified Source.Source as Source
|
import qualified Source.Source as Source
|
||||||
import qualified System.Path as Path
|
import qualified System.Path as Path
|
||||||
|
|
||||||
|
-- | Deprecated: this has very weird semantics.
|
||||||
|
readProjectFromPaths :: MonadIO m
|
||||||
|
=> Maybe Path.AbsRelDir -- ^ An optional root directory for the project
|
||||||
|
-> Path.AbsRelFileDir -- ^ A file or directory to parse. Passing a file path loads all files in that file's parent directory.
|
||||||
|
-> Language
|
||||||
|
-> [Path.AbsRelDir] -- ^ Directories to exclude.
|
||||||
|
-> m Project
|
||||||
|
readProjectFromPaths maybeRoot path lang excludeDirs = do
|
||||||
|
let rootDir :: Path.AbsRelDir
|
||||||
|
rootDir = case maybeRoot >>= Path.fromAbsRel of
|
||||||
|
-- If we were provided a root directory, use that.
|
||||||
|
Just root -> root
|
||||||
|
Nothing -> case Path.fileFromFileDir path of
|
||||||
|
-- If we weren't and the path is a file, drop its file name.
|
||||||
|
Just fp -> Path.takeDirectory fp
|
||||||
|
-- Otherwise, load from the path.
|
||||||
|
Nothing -> Path.dirFromFileDir path
|
||||||
|
|
||||||
|
paths <- liftIO $ findFilesInDir rootDir exts excludeDirs
|
||||||
|
blobs <- liftIO $ traverse (readBlobFromFile' . toFile) paths
|
||||||
|
pure $ Project (Path.toString rootDir) blobs lang (fmap Path.toString excludeDirs)
|
||||||
|
where
|
||||||
|
toFile path = File path lowerBound lang
|
||||||
|
exts = extensionsForLanguage lang
|
||||||
|
|
||||||
|
|
||||||
-- | Read a utf8-encoded file to a 'Blob'.
|
-- | Read a utf8-encoded file to a 'Blob'.
|
||||||
readBlobFromFile :: MonadIO m => File Language -> m (Maybe Blob)
|
readBlobFromFile :: MonadIO m => File Language -> m (Maybe Blob)
|
||||||
readBlobFromFile (File (Path.toString -> "/dev/null") _ _) = pure Nothing
|
readBlobFromFile (File (Path.toString -> "/dev/null") _ _) = pure Nothing
|
||||||
|
Loading…
Reference in New Issue
Block a user