mirror of
https://github.com/github/semantic.git
synced 2025-01-01 11:46:14 +03:00
Merge branch 'master' into strict-equals
This commit is contained in:
commit
7da61bd4c9
@ -11,6 +11,10 @@ build-type: Simple
|
|||||||
-- extra-source-files:
|
-- extra-source-files:
|
||||||
cabal-version: >=1.10
|
cabal-version: >=1.10
|
||||||
|
|
||||||
|
flag release
|
||||||
|
description: Build with optimizations on (for CI or deployment builds)
|
||||||
|
default: False
|
||||||
|
|
||||||
library
|
library
|
||||||
hs-source-dirs: src
|
hs-source-dirs: src
|
||||||
exposed-modules:
|
exposed-modules:
|
||||||
@ -221,13 +225,19 @@ library
|
|||||||
, StandaloneDeriving
|
, StandaloneDeriving
|
||||||
, StrictData
|
, StrictData
|
||||||
, TypeApplications
|
, TypeApplications
|
||||||
ghc-options: -Wall -Wcompat -Wincomplete-record-updates -Wincomplete-uni-patterns -Wredundant-constraints -fno-warn-name-shadowing -O -j
|
if flag(release)
|
||||||
|
ghc-options: -Wall -Werror -Wcompat -Wincomplete-record-updates -Wincomplete-uni-patterns -Wredundant-constraints -fno-warn-name-shadowing -O1 -j
|
||||||
|
else
|
||||||
|
ghc-options: -Wall -Wcompat -Wincomplete-record-updates -Wincomplete-uni-patterns -Wredundant-constraints -fno-warn-name-shadowing -O0 -j
|
||||||
ghc-prof-options: -fprof-auto
|
ghc-prof-options: -fprof-auto
|
||||||
|
|
||||||
executable semantic
|
executable semantic
|
||||||
hs-source-dirs: app
|
hs-source-dirs: app
|
||||||
main-is: Main.hs
|
main-is: Main.hs
|
||||||
ghc-options: -threaded -rtsopts "-with-rtsopts=-N -A4m -n2m" -static -j -O
|
if flag(release)
|
||||||
|
ghc-options: -threaded -rtsopts "-with-rtsopts=-N -A4m -n2m" -static -j -O1 -j
|
||||||
|
else
|
||||||
|
ghc-options: -threaded -rtsopts "-with-rtsopts=-N -A4m -n2m" -static -j -O0 -j
|
||||||
cc-options: -DU_STATIC_IMPLEMENTATION=1
|
cc-options: -DU_STATIC_IMPLEMENTATION=1
|
||||||
cpp-options: -DU_STATIC_IMPLEMENTATION=1
|
cpp-options: -DU_STATIC_IMPLEMENTATION=1
|
||||||
build-depends: base
|
build-depends: base
|
||||||
@ -268,6 +278,7 @@ test-suite test
|
|||||||
, Test.Hspec.LeanCheck
|
, Test.Hspec.LeanCheck
|
||||||
build-depends: aeson
|
build-depends: aeson
|
||||||
, array
|
, array
|
||||||
|
, async
|
||||||
, base
|
, base
|
||||||
, bifunctors
|
, bifunctors
|
||||||
, bytestring
|
, bytestring
|
||||||
@ -327,7 +338,7 @@ benchmark evaluation
|
|||||||
hs-source-dirs: bench
|
hs-source-dirs: bench
|
||||||
type: exitcode-stdio-1.0
|
type: exitcode-stdio-1.0
|
||||||
main-is: Main.hs
|
main-is: Main.hs
|
||||||
ghc-options: -threaded -rtsopts "-with-rtsopts=-N -A4m -n2m -T" -static -j -O
|
ghc-options: -threaded -rtsopts "-with-rtsopts=-N -A4m -n2m -T" -static -j -O1
|
||||||
cc-options: -DU_STATIC_IMPLEMENTATION=1
|
cc-options: -DU_STATIC_IMPLEMENTATION=1
|
||||||
cpp-options: -DU_STATIC_IMPLEMENTATION=1
|
cpp-options: -DU_STATIC_IMPLEMENTATION=1
|
||||||
default-language: Haskell2010
|
default-language: Haskell2010
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
{-# LANGUAGE TypeFamilies, TypeOperators, UndecidableInstances #-}
|
{-# LANGUAGE ScopedTypeVariables, TypeFamilies, TypeOperators #-}
|
||||||
module Analysis.Abstract.Graph
|
module Analysis.Abstract.Graph
|
||||||
( Graph(..)
|
( Graph(..)
|
||||||
, Vertex(..)
|
, Vertex(..)
|
||||||
@ -7,9 +7,8 @@ module Analysis.Abstract.Graph
|
|||||||
, variableDefinition
|
, variableDefinition
|
||||||
, moduleInclusion
|
, moduleInclusion
|
||||||
, packageInclusion
|
, packageInclusion
|
||||||
, packageGraph
|
|
||||||
, graphingTerms
|
, graphingTerms
|
||||||
, graphingLoadErrors
|
, graphingPackages
|
||||||
, graphingModules
|
, graphingModules
|
||||||
, graphing
|
, graphing
|
||||||
) where
|
) where
|
||||||
@ -17,7 +16,6 @@ module Analysis.Abstract.Graph
|
|||||||
import Algebra.Graph.Export.Dot hiding (vertexName)
|
import Algebra.Graph.Export.Dot hiding (vertexName)
|
||||||
import Control.Abstract
|
import Control.Abstract
|
||||||
import Data.Abstract.Address
|
import Data.Abstract.Address
|
||||||
import Data.Abstract.Evaluatable (LoadError (..))
|
|
||||||
import Data.Abstract.FreeVariables
|
import Data.Abstract.FreeVariables
|
||||||
import Data.Abstract.Module (Module(moduleInfo), ModuleInfo(..))
|
import Data.Abstract.Module (Module(moduleInfo), ModuleInfo(..))
|
||||||
import Data.Abstract.Package (PackageInfo(..))
|
import Data.Abstract.Package (PackageInfo(..))
|
||||||
@ -56,7 +54,6 @@ style = (defaultStyle (byteString . vertexName))
|
|||||||
graphingTerms :: ( Element Syntax.Identifier syntax
|
graphingTerms :: ( Element Syntax.Identifier syntax
|
||||||
, Members '[ Reader (Environment (Located location) value)
|
, Members '[ Reader (Environment (Located location) value)
|
||||||
, Reader ModuleInfo
|
, Reader ModuleInfo
|
||||||
, Reader PackageInfo
|
|
||||||
, State (Environment (Located location) value)
|
, State (Environment (Located location) value)
|
||||||
, State (Graph Vertex)
|
, State (Graph Vertex)
|
||||||
] effects
|
] effects
|
||||||
@ -72,34 +69,34 @@ graphingTerms recur term@(In _ syntax) = do
|
|||||||
_ -> pure ()
|
_ -> pure ()
|
||||||
recur term
|
recur term
|
||||||
|
|
||||||
-- | Add vertices to the graph for 'LoadError's.
|
graphingPackages :: Members '[ Reader ModuleInfo
|
||||||
graphingLoadErrors :: Members '[ Reader ModuleInfo
|
, Reader PackageInfo
|
||||||
, Resumable (LoadError location value)
|
, State (Graph Vertex)
|
||||||
, State (Graph Vertex)
|
] effects
|
||||||
] effects
|
=> SubtermAlgebra Module term (TermEvaluator term location value effects a)
|
||||||
=> SubtermAlgebra (Base term) term (TermEvaluator term location value effects a)
|
-> SubtermAlgebra Module term (TermEvaluator term location value effects a)
|
||||||
-> SubtermAlgebra (Base term) term (TermEvaluator term location value effects a)
|
graphingPackages recur m = packageInclusion (moduleVertex (moduleInfo m)) *> recur m
|
||||||
graphingLoadErrors recur term = TermEvaluator (runTermEvaluator (recur term) `resumeLoadError` (\ (ModuleNotFound name) -> moduleInclusion (Module (BC.pack name)) *> moduleNotFound name))
|
|
||||||
|
|
||||||
-- | Add vertices to the graph for evaluated modules and the packages containing them.
|
-- | Add vertices to the graph for evaluated modules and the packages containing them.
|
||||||
graphingModules :: Members '[ Reader ModuleInfo
|
graphingModules :: forall term location value effects a
|
||||||
, Reader PackageInfo
|
. Members '[ Modules location value
|
||||||
|
, Reader ModuleInfo
|
||||||
, State (Graph Vertex)
|
, State (Graph Vertex)
|
||||||
] effects
|
] effects
|
||||||
=> SubtermAlgebra Module term (TermEvaluator term location value effects a)
|
=> SubtermAlgebra Module term (TermEvaluator term location value effects a)
|
||||||
-> SubtermAlgebra Module term (TermEvaluator term location value effects a)
|
-> SubtermAlgebra Module term (TermEvaluator term location value effects a)
|
||||||
graphingModules recur m = do
|
graphingModules recur m = interpose @(Modules location value) pure (\ m yield -> case m of
|
||||||
let name = BC.pack (modulePath (moduleInfo m))
|
Load path -> moduleInclusion (moduleVertex (ModuleInfo path)) >> send m >>= yield
|
||||||
packageInclusion (Module name)
|
Lookup path -> moduleInclusion (moduleVertex (ModuleInfo path)) >> send m >>= yield
|
||||||
moduleInclusion (Module name)
|
_ -> send m >>= yield)
|
||||||
recur m
|
(recur m)
|
||||||
|
|
||||||
|
|
||||||
packageGraph :: PackageInfo -> Graph Vertex
|
packageVertex :: PackageInfo -> Vertex
|
||||||
packageGraph = vertex . Package . unName . packageName
|
packageVertex = Package . unName . packageName
|
||||||
|
|
||||||
moduleGraph :: ModuleInfo -> Graph Vertex
|
moduleVertex :: ModuleInfo -> Vertex
|
||||||
moduleGraph = vertex . Module . BC.pack . modulePath
|
moduleVertex = Module . BC.pack . modulePath
|
||||||
|
|
||||||
-- | Add an edge from the current package to the passed vertex.
|
-- | Add an edge from the current package to the passed vertex.
|
||||||
packageInclusion :: ( Effectful m
|
packageInclusion :: ( Effectful m
|
||||||
@ -112,7 +109,7 @@ packageInclusion :: ( Effectful m
|
|||||||
-> m effects ()
|
-> m effects ()
|
||||||
packageInclusion v = do
|
packageInclusion v = do
|
||||||
p <- currentPackage
|
p <- currentPackage
|
||||||
appendGraph (packageGraph p `connect` vertex v)
|
appendGraph (vertex (packageVertex p) `connect` vertex v)
|
||||||
|
|
||||||
-- | Add an edge from the current module to the passed vertex.
|
-- | Add an edge from the current module to the passed vertex.
|
||||||
moduleInclusion :: ( Effectful m
|
moduleInclusion :: ( Effectful m
|
||||||
@ -125,7 +122,7 @@ moduleInclusion :: ( Effectful m
|
|||||||
-> m effects ()
|
-> m effects ()
|
||||||
moduleInclusion v = do
|
moduleInclusion v = do
|
||||||
m <- currentModule
|
m <- currentModule
|
||||||
appendGraph (moduleGraph m `connect` vertex v)
|
appendGraph (vertex (moduleVertex m) `connect` vertex v)
|
||||||
|
|
||||||
-- | Add an edge from the passed variable name to the module it originated within.
|
-- | Add an edge from the passed variable name to the module it originated within.
|
||||||
variableDefinition :: ( Member (Reader (Environment (Located location) value)) effects
|
variableDefinition :: ( Member (Reader (Environment (Located location) value)) effects
|
||||||
@ -135,7 +132,7 @@ variableDefinition :: ( Member (Reader (Environment (Located location) value)) e
|
|||||||
=> Name
|
=> Name
|
||||||
-> TermEvaluator term (Located location) value effects ()
|
-> TermEvaluator term (Located location) value effects ()
|
||||||
variableDefinition name = do
|
variableDefinition name = do
|
||||||
graph <- maybe lowerBound (moduleGraph . locationModule . unAddress) <$> TermEvaluator (lookupEnv name)
|
graph <- maybe lowerBound (vertex . moduleVertex . locationModule . unAddress) <$> TermEvaluator (lookupEnv name)
|
||||||
appendGraph (vertex (Variable (unName name)) `connect` graph)
|
appendGraph (vertex (Variable (unName name)) `connect` graph)
|
||||||
|
|
||||||
appendGraph :: (Effectful m, Member (State (Graph Vertex)) effects) => Graph Vertex -> m effects ()
|
appendGraph :: (Effectful m, Member (State (Graph Vertex)) effects) => Graph Vertex -> m effects ()
|
||||||
|
@ -1,10 +1,14 @@
|
|||||||
{-# LANGUAGE DataKinds, ScopedTypeVariables, TypeOperators #-}
|
{-# LANGUAGE DataKinds, GADTs, ScopedTypeVariables, TypeOperators #-}
|
||||||
module Parsing.TreeSitter
|
module Parsing.TreeSitter
|
||||||
( parseToAST
|
( Timeout (..)
|
||||||
|
, parseToAST
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import Prologue
|
import Prologue
|
||||||
import Data.AST (AST, Node(Node))
|
|
||||||
|
import Control.Concurrent.Async
|
||||||
|
import Control.Monad
|
||||||
|
import Data.AST (AST, Node (Node))
|
||||||
import Data.Blob
|
import Data.Blob
|
||||||
import Data.ByteString.Unsafe (unsafeUseAsCStringLen)
|
import Data.ByteString.Unsafe (unsafeUseAsCStringLen)
|
||||||
import Data.Range
|
import Data.Range
|
||||||
@ -12,24 +16,61 @@ import Data.Source
|
|||||||
import Data.Span
|
import Data.Span
|
||||||
import Data.Term
|
import Data.Term
|
||||||
import Foreign
|
import Foreign
|
||||||
import Foreign.C.Types (CBool(..))
|
import Foreign.C.Types (CBool (..))
|
||||||
import Foreign.Marshal.Array (allocaArray)
|
import Foreign.Marshal.Array (allocaArray)
|
||||||
import qualified TreeSitter.Tree as TS
|
import System.Timeout
|
||||||
import qualified TreeSitter.Parser as TS
|
|
||||||
import qualified TreeSitter.Node as TS
|
|
||||||
import qualified TreeSitter.Language as TS
|
import qualified TreeSitter.Language as TS
|
||||||
|
import qualified TreeSitter.Node as TS
|
||||||
|
import qualified TreeSitter.Parser as TS
|
||||||
|
import qualified TreeSitter.Tree as TS
|
||||||
|
|
||||||
|
newtype Timeout = Milliseconds Int
|
||||||
|
|
||||||
|
-- Change this to putStrLn if you want to debug the locking/cancellation code.
|
||||||
|
-- TODO: Someday we should run this all in Eff so that we can 'trace'.
|
||||||
|
dbg :: String -> IO ()
|
||||||
|
dbg = const (pure ())
|
||||||
|
|
||||||
|
runParser :: (Enum grammar, Bounded grammar) => Ptr TS.Parser -> Source -> IO (Maybe (AST [] grammar))
|
||||||
|
runParser parser blobSource = unsafeUseAsCStringLen (sourceBytes blobSource) $ \ (source, len) ->
|
||||||
|
alloca (\ rootPtr -> do
|
||||||
|
let acquire = do
|
||||||
|
dbg "Starting parse"
|
||||||
|
-- Change this to TS.ts_parser_loop_until_cancelled if you want to test out cancellation
|
||||||
|
TS.ts_parser_parse_string parser nullPtr source len
|
||||||
|
|
||||||
|
let release t
|
||||||
|
| t == nullPtr = dbg "Parse failed"
|
||||||
|
| otherwise = dbg "Parse completed" *> TS.ts_tree_delete t
|
||||||
|
|
||||||
|
let go treePtr = do
|
||||||
|
if treePtr == nullPtr
|
||||||
|
then pure Nothing
|
||||||
|
else do
|
||||||
|
TS.ts_tree_root_node_p treePtr rootPtr
|
||||||
|
fmap Just (peek rootPtr >>= anaM toAST)
|
||||||
|
bracket acquire release go)
|
||||||
|
|
||||||
-- | Parse 'Source' with the given 'TS.Language' and return its AST.
|
-- | Parse 'Source' with the given 'TS.Language' and return its AST.
|
||||||
parseToAST :: (Bounded grammar, Enum grammar) => Ptr TS.Language -> Blob -> IO (AST [] grammar)
|
-- Returns Nothing if the operation timed out.
|
||||||
parseToAST language Blob{..} = bracket TS.ts_parser_new TS.ts_parser_delete $ \ parser -> do
|
parseToAST :: (Bounded grammar, Enum grammar) => Timeout -> Ptr TS.Language -> Blob -> IO (Maybe (AST [] grammar))
|
||||||
|
parseToAST (Milliseconds s) language Blob{..} = bracket TS.ts_parser_new TS.ts_parser_delete $ \ parser -> do
|
||||||
|
let parserTimeout = s * 1000
|
||||||
|
|
||||||
TS.ts_parser_halt_on_error parser (CBool 1)
|
TS.ts_parser_halt_on_error parser (CBool 1)
|
||||||
TS.ts_parser_set_language parser language
|
TS.ts_parser_set_language parser language
|
||||||
unsafeUseAsCStringLen (sourceBytes blobSource) $ \ (source, len) -> do
|
|
||||||
alloca (\ rootPtr -> do
|
parsing <- async (runParser parser blobSource)
|
||||||
bracket (TS.ts_parser_parse_string parser nullPtr source len) TS.ts_tree_delete $ \ tree -> do
|
|
||||||
TS.ts_tree_root_node_p tree rootPtr
|
-- Kick the parser off asynchronously and wait according to the provided timeout.
|
||||||
peek rootPtr >>= anaM toAST
|
res <- timeout parserTimeout (wait parsing)
|
||||||
)
|
|
||||||
|
-- If we get a Nothing back, then we failed, so we need to disable the parser, which
|
||||||
|
-- will let the call to runParser terminate, cleaning up appropriately
|
||||||
|
when (isNothing res) (TS.ts_parser_set_enabled parser (CBool 0))
|
||||||
|
|
||||||
|
pure (join res)
|
||||||
|
|
||||||
|
|
||||||
toAST :: forall grammar . (Bounded grammar, Enum grammar) => TS.Node -> IO (Base (AST [] grammar) TS.Node)
|
toAST :: forall grammar . (Bounded grammar, Enum grammar) => TS.Node -> IO (Base (AST [] grammar) TS.Node)
|
||||||
|
@ -7,7 +7,6 @@ module Semantic.CLI
|
|||||||
) where
|
) where
|
||||||
|
|
||||||
import Data.Project
|
import Data.Project
|
||||||
import Data.Language (Language)
|
|
||||||
import Data.List (intercalate)
|
import Data.List (intercalate)
|
||||||
import Data.List.Split (splitWhen)
|
import Data.List.Split (splitWhen)
|
||||||
import Data.Version (showVersion)
|
import Data.Version (showVersion)
|
||||||
@ -18,7 +17,7 @@ import Prologue
|
|||||||
import Rendering.Renderer
|
import Rendering.Renderer
|
||||||
import qualified Semantic.AST as AST
|
import qualified Semantic.AST as AST
|
||||||
import qualified Semantic.Diff as Diff
|
import qualified Semantic.Diff as Diff
|
||||||
import Semantic.Graph as Semantic (Graph, GraphType(..), Vertex, graph, style)
|
import qualified Semantic.Graph as Graph
|
||||||
import Semantic.IO as IO
|
import Semantic.IO as IO
|
||||||
import qualified Semantic.Log as Log
|
import qualified Semantic.Log as Log
|
||||||
import qualified Semantic.Parse as Parse
|
import qualified Semantic.Parse as Parse
|
||||||
@ -29,9 +28,6 @@ import Text.Read
|
|||||||
main :: IO ()
|
main :: IO ()
|
||||||
main = customExecParser (prefs showHelpOnEmpty) arguments >>= uncurry Task.runTaskWithOptions
|
main = customExecParser (prefs showHelpOnEmpty) arguments >>= uncurry Task.runTaskWithOptions
|
||||||
|
|
||||||
runGraph :: Semantic.GraphType -> Maybe FilePath -> FilePath -> Language -> [FilePath] -> Task.TaskEff (Graph Vertex)
|
|
||||||
runGraph graphType rootDir dir excludeDirs = Semantic.graph graphType <=< Task.readProject rootDir dir excludeDirs
|
|
||||||
|
|
||||||
-- | A parser for the application's command-line arguments.
|
-- | A parser for the application's command-line arguments.
|
||||||
--
|
--
|
||||||
-- Returns a 'Task' to read the input, run the requested operation, and write the output to the specified output path or stdout.
|
-- Returns a 'Task' to read the input, run the requested operation, and write the output to the specified output path or stdout.
|
||||||
@ -88,14 +84,16 @@ arguments = info (version <*> helper <*> ((,) <$> optionsParser <*> argumentsPar
|
|||||||
|
|
||||||
graphCommand = command "graph" (info graphArgumentsParser (progDesc "Compute a graph for a directory or entry point"))
|
graphCommand = command "graph" (info graphArgumentsParser (progDesc "Compute a graph for a directory or entry point"))
|
||||||
graphArgumentsParser = do
|
graphArgumentsParser = do
|
||||||
graphType <- flag ImportGraph ImportGraph (long "imports" <> help "Compute an import graph (default)")
|
graphType <- flag Graph.ImportGraph Graph.ImportGraph (long "imports" <> help "Compute an import graph (default)")
|
||||||
<|> flag' CallGraph (long "calls" <> help "Compute a call graph")
|
<|> flag' Graph.CallGraph (long "calls" <> help "Compute a call graph")
|
||||||
|
let style = Graph.style
|
||||||
|
includePackages <- switch (long "packages" <> help "Include a vertex for the package, with edges from it to each module")
|
||||||
serializer <- flag (Task.serialize (DOT style)) (Task.serialize (DOT style)) (long "dot" <> help "Output in DOT graph format (default)")
|
serializer <- flag (Task.serialize (DOT style)) (Task.serialize (DOT style)) (long "dot" <> help "Output in DOT graph format (default)")
|
||||||
<|> flag' (Task.serialize JSON) (long "json" <> help "Output JSON graph")
|
<|> flag' (Task.serialize JSON) (long "json" <> help "Output JSON graph")
|
||||||
rootDir <- rootDirectoryOption
|
rootDir <- rootDirectoryOption
|
||||||
excludeDirs <- excludeDirsOption
|
excludeDirs <- excludeDirsOption
|
||||||
File{..} <- argument filePathReader (metavar "DIR:LANGUAGE | FILE")
|
File{..} <- argument filePathReader (metavar "DIR:LANGUAGE | FILE")
|
||||||
pure $ runGraph graphType rootDir filePath (fromJust fileLanguage) excludeDirs >>= serializer
|
pure $ Task.readProject rootDir filePath (fromJust fileLanguage) excludeDirs >>= Graph.runGraph graphType includePackages >>= serializer
|
||||||
|
|
||||||
rootDirectoryOption = optional (strOption (long "root" <> help "Root directory of project. Optional, defaults to entry file/directory." <> metavar "DIR"))
|
rootDirectoryOption = optional (strOption (long "root" <> help "Root directory of project. Optional, defaults to entry file/directory." <> metavar "DIR"))
|
||||||
excludeDirsOption = many (strOption (long "exclude-dir" <> help "Exclude a directory (e.g. vendor)" <> metavar "DIR"))
|
excludeDirsOption = many (strOption (long "exclude-dir" <> help "Exclude a directory (e.g. vendor)" <> metavar "DIR"))
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{-# LANGUAGE GADTs, TypeOperators #-}
|
{-# LANGUAGE GADTs, TypeOperators #-}
|
||||||
module Semantic.Graph
|
module Semantic.Graph
|
||||||
( graph
|
( runGraph
|
||||||
, GraphType(..)
|
, GraphType(..)
|
||||||
, Graph
|
, Graph
|
||||||
, Vertex
|
, Vertex
|
||||||
@ -39,18 +39,20 @@ import Semantic.Task as Task
|
|||||||
|
|
||||||
data GraphType = ImportGraph | CallGraph
|
data GraphType = ImportGraph | CallGraph
|
||||||
|
|
||||||
graph :: Members '[Distribute WrappedTask, Files, Resolution, Task, Exc SomeException, Telemetry, Trace] effs
|
runGraph :: Members '[Distribute WrappedTask, Files, Resolution, Task, Exc SomeException, Telemetry, Trace] effs
|
||||||
=> GraphType
|
=> GraphType
|
||||||
-> Project
|
-> Bool
|
||||||
-> Eff effs (Graph Vertex)
|
-> Project
|
||||||
graph graphType project
|
-> Eff effs (Graph Vertex)
|
||||||
|
runGraph graphType includePackages project
|
||||||
| SomeAnalysisParser parser prelude <- someAnalysisParser
|
| SomeAnalysisParser parser prelude <- someAnalysisParser
|
||||||
(Proxy :: Proxy '[ Evaluatable, Declarations1, FreeVariables1, Functor, Eq1, Ord1, Show1 ]) (projectLanguage project) = do
|
(Proxy :: Proxy '[ Evaluatable, Declarations1, FreeVariables1, Functor, Eq1, Ord1, Show1 ]) (projectLanguage project) = do
|
||||||
package <- parsePackage parser prelude project
|
package <- parsePackage parser prelude project
|
||||||
let analyzeTerm = case graphType of
|
let analyzeTerm = withTermSpans . case graphType of
|
||||||
ImportGraph -> id
|
ImportGraph -> id
|
||||||
CallGraph -> graphingTerms
|
CallGraph -> graphingTerms
|
||||||
analyze runGraphAnalysis (evaluatePackageWith graphingModules (withTermSpans . graphingLoadErrors . analyzeTerm) package) >>= extractGraph
|
analyzeModule = (if includePackages then graphingPackages else id) . graphingModules
|
||||||
|
analyze runGraphAnalysis (evaluatePackageWith analyzeModule analyzeTerm package) >>= extractGraph
|
||||||
where extractGraph result = case result of
|
where extractGraph result = case result of
|
||||||
(Right ((_, graph), _), _) -> pure graph
|
(Right ((_, graph), _), _) -> pure graph
|
||||||
_ -> Task.throwError (toException (Exc.ErrorCall ("graphImports: import graph rendering failed " <> show result)))
|
_ -> Task.throwError (toException (Exc.ErrorCall ("graphImports: import graph rendering failed " <> show result)))
|
||||||
|
@ -180,12 +180,21 @@ runTaskF = interpret $ \ task -> case task of
|
|||||||
logError :: Member Telemetry effs => Options -> Level -> Blob -> Error.Error String -> [(String, String)] -> Eff effs ()
|
logError :: Member Telemetry effs => Options -> Level -> Blob -> Error.Error String -> [(String, String)] -> Eff effs ()
|
||||||
logError Options{..} level blob err = writeLog level (Error.formatError optionsPrintSource (optionsIsTerminal && optionsEnableColour) blob err)
|
logError Options{..} level blob err = writeLog level (Error.formatError optionsPrintSource (optionsIsTerminal && optionsEnableColour) blob err)
|
||||||
|
|
||||||
|
data ParserCancelled = ParserTimedOut deriving (Show, Typeable)
|
||||||
|
|
||||||
|
instance Exception ParserCancelled
|
||||||
|
|
||||||
|
defaultTimeout :: Timeout
|
||||||
|
defaultTimeout = Milliseconds 5000
|
||||||
|
|
||||||
-- | Parse a 'Blob' in 'IO'.
|
-- | Parse a 'Blob' in 'IO'.
|
||||||
runParser :: Members '[Reader Options, Telemetry, Exc SomeException, IO, Trace] effs => Blob -> Parser term -> Eff effs term
|
runParser :: Members '[Reader Options, Telemetry, Exc SomeException, IO, Trace] effs => Blob -> Parser term -> Eff effs term
|
||||||
runParser blob@Blob{..} parser = case parser of
|
runParser blob@Blob{..} parser = case parser of
|
||||||
ASTParser language ->
|
ASTParser language ->
|
||||||
time "parse.tree_sitter_ast_parse" languageTag $
|
time "parse.tree_sitter_ast_parse" languageTag $
|
||||||
IO.rethrowing (parseToAST language blob)
|
IO.rethrowing (parseToAST defaultTimeout language blob)
|
||||||
|
>>= maybeM (throwError (SomeException ParserTimedOut))
|
||||||
|
|
||||||
AssignmentParser parser assignment -> do
|
AssignmentParser parser assignment -> do
|
||||||
ast <- runParser blob parser `catchError` \ (SomeException err) -> do
|
ast <- runParser blob parser `catchError` \ (SomeException err) -> do
|
||||||
writeStat (Stat.increment "parse.parse_failures" languageTag)
|
writeStat (Stat.increment "parse.parse_failures" languageTag)
|
||||||
|
@ -1,9 +1,20 @@
|
|||||||
module Semantic.IO.Spec (spec) where
|
module Semantic.IO.Spec (spec) where
|
||||||
|
|
||||||
import Prelude hiding (readFile)
|
import Prelude hiding (readFile)
|
||||||
|
|
||||||
|
import Control.Concurrent.Async
|
||||||
|
import Foreign
|
||||||
|
import Foreign.C.Types (CBool (..))
|
||||||
import Semantic.IO
|
import Semantic.IO
|
||||||
import System.Exit (ExitCode(..))
|
import System.Exit (ExitCode (..))
|
||||||
import System.IO (IOMode(..))
|
import System.IO (IOMode (..))
|
||||||
|
import Parsing.TreeSitter
|
||||||
|
import System.Timeout
|
||||||
|
|
||||||
|
import qualified TreeSitter.Language as TS
|
||||||
|
import qualified TreeSitter.Node as TS
|
||||||
|
import qualified TreeSitter.Parser as TS
|
||||||
|
import qualified TreeSitter.Tree as TS
|
||||||
|
|
||||||
import SpecHelpers
|
import SpecHelpers
|
||||||
|
|
||||||
@ -64,6 +75,24 @@ spec = parallel $ do
|
|||||||
h <- openFileForReading "test/fixtures/cli/diff-null-both-sides.json"
|
h <- openFileForReading "test/fixtures/cli/diff-null-both-sides.json"
|
||||||
readBlobPairsFromHandle h `shouldThrow` (== ExitFailure 1)
|
readBlobPairsFromHandle h `shouldThrow` (== ExitFailure 1)
|
||||||
|
|
||||||
|
describe "cancelable parsing" $
|
||||||
|
it "should be cancelable asynchronously" $ do
|
||||||
|
p <- TS.ts_parser_new
|
||||||
|
|
||||||
|
churn <- async $ do
|
||||||
|
TS.ts_parser_loop_until_cancelled p nullPtr nullPtr 0
|
||||||
|
pure True
|
||||||
|
|
||||||
|
res <- timeout 500 (wait churn)
|
||||||
|
res `shouldBe` Nothing
|
||||||
|
|
||||||
|
TS.ts_parser_set_enabled p (CBool 0)
|
||||||
|
done <- timeout 500 (wait churn)
|
||||||
|
|
||||||
|
done `shouldBe` (Just True)
|
||||||
|
|
||||||
|
TS.ts_parser_delete p
|
||||||
|
|
||||||
describe "readBlobsFromHandle" $ do
|
describe "readBlobsFromHandle" $ do
|
||||||
it "returns blobs for valid JSON encoded parse input" $ do
|
it "returns blobs for valid JSON encoded parse input" $ do
|
||||||
h <- openFileForReading "test/fixtures/cli/parse.json"
|
h <- openFileForReading "test/fixtures/cli/parse.json"
|
||||||
|
2
vendor/haskell-tree-sitter
vendored
2
vendor/haskell-tree-sitter
vendored
@ -1 +1 @@
|
|||||||
Subproject commit 897785918ce87f51e541777978f33de09619dcc7
|
Subproject commit 4d08262bc306fe8e233feff4714a9c77b83edd77
|
Loading…
Reference in New Issue
Block a user