mirror of
https://github.com/github/semantic.git
synced 2024-12-19 21:01:35 +03:00
Merge branch 'master' into parse-jquery
This commit is contained in:
commit
538961285a
@ -21,13 +21,22 @@ type Parser f a = SourceBlob -> IO (Cofree f a)
|
|||||||
isOperator :: Category -> Bool
|
isOperator :: Category -> Bool
|
||||||
isOperator = flip Set.member (Set.fromList [ Operator, BinaryOperator ])
|
isOperator = flip Set.member (Set.fromList [ Operator, BinaryOperator ])
|
||||||
|
|
||||||
-- | Given a function that maps production names to sets of categories, produce
|
-- | Construct a term given source, the span covered, the annotation for the term, and its children.
|
||||||
-- | a Constructor.
|
--
|
||||||
termConstructor :: forall fields. (Show (Record fields), HasField fields Category, HasField fields Range) => Source Char -> SourceSpan -> (Record fields) -> [Term Text (Record fields)] -> Term Text (Record fields)
|
-- This is typically called during parsing, building terms up leaf-to-root.
|
||||||
termConstructor source sourceSpan info = cofree . construct
|
termConstructor :: forall fields. (Show (Record fields), HasField fields Category, HasField fields Range)
|
||||||
|
=> Source Char -- ^ The source that the term occurs within.
|
||||||
|
-> IO SourceSpan -- ^ The span that the term occupies. This is passed in 'IO' to guarantee some access constraints & encourage its use only when needed (improving performance).
|
||||||
|
-> Record fields -- ^ The annotation for the term.
|
||||||
|
-> [Term Text (Record fields)] -- ^ The child nodes of the term.
|
||||||
|
-> IO (Term Text (Record fields)) -- ^ The resulting term, in IO.
|
||||||
|
termConstructor source sourceSpan info = fmap cofree . construct
|
||||||
where
|
where
|
||||||
withDefaultInfo syntax = (info :< syntax)
|
withDefaultInfo syntax = pure (info :< syntax)
|
||||||
construct :: (Show (Record fields), HasField fields Category, HasField fields Range) => [Term Text (Record fields)] -> CofreeF (S.Syntax Text) (Record fields) (Term Text (Record fields))
|
errorWith children = do
|
||||||
|
sourceSpan' <- sourceSpan
|
||||||
|
withDefaultInfo (S.Error sourceSpan' children)
|
||||||
|
construct :: (Show (Record fields), HasField fields Category, HasField fields Range) => [Term Text (Record fields)] -> IO (CofreeF (S.Syntax Text) (Record fields) (Term Text (Record fields)))
|
||||||
construct [] = case category info of
|
construct [] = case category info of
|
||||||
Return -> withDefaultInfo $ S.Return Nothing -- Map empty return statements to Return Nothing
|
Return -> withDefaultInfo $ S.Return Nothing -- Map empty return statements to Return Nothing
|
||||||
_ -> withDefaultInfo . S.Leaf . pack . toString $ slice (characterRange info) source
|
_ -> withDefaultInfo . S.Leaf . pack . toString $ slice (characterRange info) source
|
||||||
@ -35,16 +44,16 @@ termConstructor source sourceSpan info = cofree . construct
|
|||||||
withDefaultInfo $ S.Return (listToMaybe children)
|
withDefaultInfo $ S.Return (listToMaybe children)
|
||||||
construct children | Assignment == category info = case children of
|
construct children | Assignment == category info = case children of
|
||||||
(identifier:value:[]) -> withDefaultInfo $ S.Assignment identifier value
|
(identifier:value:[]) -> withDefaultInfo $ S.Assignment identifier value
|
||||||
children -> withDefaultInfo $ S.Error sourceSpan children
|
children -> errorWith children
|
||||||
construct children | MathAssignment == category info = case children of
|
construct children | MathAssignment == category info = case children of
|
||||||
(identifier:value:[]) -> withDefaultInfo $ S.MathAssignment identifier value
|
(identifier:value:[]) -> withDefaultInfo $ S.MathAssignment identifier value
|
||||||
children -> withDefaultInfo $ S.Error sourceSpan children
|
children -> errorWith children
|
||||||
construct children | MemberAccess == category info = case children of
|
construct children | MemberAccess == category info = case children of
|
||||||
(base:property:[]) -> withDefaultInfo $ S.MemberAccess base property
|
(base:property:[]) -> withDefaultInfo $ S.MemberAccess base property
|
||||||
children -> withDefaultInfo $ S.Error sourceSpan children
|
children -> errorWith children
|
||||||
construct children | SubscriptAccess == category info = case children of
|
construct children | SubscriptAccess == category info = case children of
|
||||||
(base:element:[]) -> withDefaultInfo $ S.SubscriptAccess base element
|
(base:element:[]) -> withDefaultInfo $ S.SubscriptAccess base element
|
||||||
_ -> withDefaultInfo $ S.Error sourceSpan children
|
_ -> errorWith children
|
||||||
construct children | isOperator (category info) = withDefaultInfo $ S.Operator children
|
construct children | isOperator (category info) = withDefaultInfo $ S.Operator children
|
||||||
construct children | Function == category info = case children of
|
construct children | Function == category info = case children of
|
||||||
(body:[]) -> withDefaultInfo $ S.Function Nothing Nothing body
|
(body:[]) -> withDefaultInfo $ S.Function Nothing Nothing body
|
||||||
@ -54,18 +63,18 @@ termConstructor source sourceSpan info = cofree . construct
|
|||||||
withDefaultInfo $ S.Function (Just id) Nothing body
|
withDefaultInfo $ S.Function (Just id) Nothing body
|
||||||
(id:params:body:[]) | (info :< _) <- runCofree id, Identifier == category info ->
|
(id:params:body:[]) | (info :< _) <- runCofree id, Identifier == category info ->
|
||||||
withDefaultInfo $ S.Function (Just id) (Just params) body
|
withDefaultInfo $ S.Function (Just id) (Just params) body
|
||||||
_ -> withDefaultInfo $ S.Error sourceSpan children
|
_ -> errorWith children
|
||||||
|
|
||||||
construct children | FunctionCall == category info = case runCofree <$> children of
|
construct children | FunctionCall == category info = case runCofree <$> children of
|
||||||
[ (_ :< S.MemberAccess{..}), params@(_ :< S.Args{}) ] ->
|
[ (_ :< S.MemberAccess{..}), params@(_ :< S.Args{}) ] ->
|
||||||
setCategory info MethodCall :< S.MethodCall memberId property (cofree params)
|
pure $! setCategory info MethodCall :< S.MethodCall memberId property (cofree params)
|
||||||
(x:xs) ->
|
(x:xs) ->
|
||||||
withDefaultInfo $ S.FunctionCall (cofree x) (cofree <$> xs)
|
withDefaultInfo $ S.FunctionCall (cofree x) (cofree <$> xs)
|
||||||
_ -> withDefaultInfo $ S.Error sourceSpan children
|
_ -> errorWith children
|
||||||
|
|
||||||
construct children | Ternary == category info = case children of
|
construct children | Ternary == category info = case children of
|
||||||
(condition:cases) -> withDefaultInfo $ S.Ternary condition cases
|
(condition:cases) -> withDefaultInfo $ S.Ternary condition cases
|
||||||
_ -> withDefaultInfo $ S.Error sourceSpan children
|
_ -> errorWith children
|
||||||
construct children | Args == category info = withDefaultInfo $ S.Args children
|
construct children | Args == category info = withDefaultInfo $ S.Args children
|
||||||
construct children | VarAssignment == category info
|
construct children | VarAssignment == category info
|
||||||
, [x, y] <- children = withDefaultInfo $ S.VarAssignment x y
|
, [x, y] <- children = withDefaultInfo $ S.VarAssignment x y
|
||||||
@ -90,12 +99,12 @@ termConstructor source sourceSpan info = cofree . construct
|
|||||||
|
|
||||||
construct children | Pair == (category info) = withDefaultInfo $ S.Fixed children
|
construct children | Pair == (category info) = withDefaultInfo $ S.Fixed children
|
||||||
construct children | C.Error == category info =
|
construct children | C.Error == category info =
|
||||||
withDefaultInfo $ S.Error sourceSpan children
|
errorWith children
|
||||||
construct children | If == category info, Just (expr, clauses) <- uncons children =
|
construct children | If == category info, Just (expr, clauses) <- uncons children =
|
||||||
withDefaultInfo $ case clauses of
|
case clauses of
|
||||||
[clause1, clause2] -> S.If expr clause1 (Just clause2)
|
[clause1, clause2] -> withDefaultInfo $ S.If expr clause1 (Just clause2)
|
||||||
[clause] -> S.If expr clause Nothing
|
[clause] -> withDefaultInfo $ S.If expr clause Nothing
|
||||||
_ -> S.Error sourceSpan children
|
_ -> errorWith children
|
||||||
construct children | For == category info, Just (exprs, body) <- unsnoc children =
|
construct children | For == category info, Just (exprs, body) <- unsnoc children =
|
||||||
withDefaultInfo $ S.For exprs body
|
withDefaultInfo $ S.For exprs body
|
||||||
construct children | While == category info, [expr, body] <- children =
|
construct children | While == category info, [expr, body] <- children =
|
||||||
@ -113,7 +122,7 @@ termConstructor source sourceSpan info = cofree . construct
|
|||||||
[body, catch, finally] | Catch <- category (extract catch),
|
[body, catch, finally] | Catch <- category (extract catch),
|
||||||
Finally <- category (extract finally) ->
|
Finally <- category (extract finally) ->
|
||||||
withDefaultInfo $ S.Try body (Just catch) (Just finally)
|
withDefaultInfo $ S.Try body (Just catch) (Just finally)
|
||||||
_ -> withDefaultInfo $ S.Error sourceSpan children
|
_ -> errorWith children
|
||||||
construct children | ArrayLiteral == category info =
|
construct children | ArrayLiteral == category info =
|
||||||
withDefaultInfo $ S.Array children
|
withDefaultInfo $ S.Array children
|
||||||
construct children | Method == category info = case children of
|
construct children | Method == category info = case children of
|
||||||
@ -123,14 +132,12 @@ termConstructor source sourceSpan info = cofree . construct
|
|||||||
withDefaultInfo $ S.Method identifier params' (toList (unwrap exprs))
|
withDefaultInfo $ S.Method identifier params' (toList (unwrap exprs))
|
||||||
[identifier, exprs] ->
|
[identifier, exprs] ->
|
||||||
withDefaultInfo $ S.Method identifier mempty (toList (unwrap exprs))
|
withDefaultInfo $ S.Method identifier mempty (toList (unwrap exprs))
|
||||||
_ ->
|
_ -> errorWith children
|
||||||
withDefaultInfo $ S.Error sourceSpan children
|
|
||||||
construct children | Class == category info = case children of
|
construct children | Class == category info = case children of
|
||||||
[identifier, superclass, definitions] ->
|
[identifier, superclass, definitions] ->
|
||||||
withDefaultInfo $ S.Class identifier (Just superclass) (toList (unwrap definitions))
|
withDefaultInfo $ S.Class identifier (Just superclass) (toList (unwrap definitions))
|
||||||
[identifier, definitions] ->
|
[identifier, definitions] ->
|
||||||
withDefaultInfo $ S.Class identifier Nothing (toList (unwrap definitions))
|
withDefaultInfo $ S.Class identifier Nothing (toList (unwrap definitions))
|
||||||
_ ->
|
_ -> errorWith children
|
||||||
withDefaultInfo $ S.Error sourceSpan children
|
|
||||||
construct children =
|
construct children =
|
||||||
withDefaultInfo $ S.Indexed children
|
withDefaultInfo $ S.Indexed children
|
||||||
|
@ -2,8 +2,9 @@
|
|||||||
module TreeSitter where
|
module TreeSitter where
|
||||||
|
|
||||||
import Prologue hiding (Constructor)
|
import Prologue hiding (Constructor)
|
||||||
import Data.Record
|
import Control.Monad
|
||||||
import Category
|
import Category
|
||||||
|
import Data.Record
|
||||||
import Language
|
import Language
|
||||||
import Parser
|
import Parser
|
||||||
import Range
|
import Range
|
||||||
@ -55,6 +56,7 @@ categoriesForLanguage language name = case (language, name) of
|
|||||||
|
|
||||||
(Ruby, "hash") -> Object
|
(Ruby, "hash") -> Object
|
||||||
_ -> defaultCategoryForNodeName name
|
_ -> defaultCategoryForNodeName name
|
||||||
|
{-# INLINE categoriesForLanguage #-}
|
||||||
|
|
||||||
-- | Given a node name from TreeSitter, return the correct categories.
|
-- | Given a node name from TreeSitter, return the correct categories.
|
||||||
defaultCategoryForNodeName :: Text -> Category
|
defaultCategoryForNodeName :: Text -> Category
|
||||||
@ -94,6 +96,7 @@ defaultCategoryForNodeName name = case name of
|
|||||||
"try_statement" -> Try
|
"try_statement" -> Try
|
||||||
"method_definition" -> Method
|
"method_definition" -> Method
|
||||||
_ -> Other name
|
_ -> Other name
|
||||||
|
{-# INLINE defaultCategoryForNodeName #-}
|
||||||
|
|
||||||
-- | Return a parser for a tree sitter language & document.
|
-- | Return a parser for a tree sitter language & document.
|
||||||
documentToTerm :: Language -> Ptr Document -> Parser (Syntax.Syntax Text) (Record '[Range, Category])
|
documentToTerm :: Language -> Ptr Document -> Parser (Syntax.Syntax Text) (Record '[Range, Category])
|
||||||
@ -105,15 +108,15 @@ documentToTerm language document blob = alloca $ \ root -> do
|
|||||||
name <- peekCString name
|
name <- peekCString name
|
||||||
count <- ts_node_p_named_child_count node
|
count <- ts_node_p_named_child_count node
|
||||||
children <- traverse (alloca . getChild node) $ take (fromIntegral count) [0..]
|
children <- traverse (alloca . getChild node) $ take (fromIntegral count) [0..]
|
||||||
|
|
||||||
|
let range = Range { start = fromIntegral $ ts_node_p_start_char node, end = fromIntegral $ ts_node_p_end_char node }
|
||||||
|
|
||||||
|
let sourceSpan = SourceSpan { spanName = toS (path blob)
|
||||||
|
, spanStart = SourcePos (fromIntegral $! ts_node_p_start_point_row node) (fromIntegral $! ts_node_p_start_point_column node)
|
||||||
|
, spanEnd = SourcePos (fromIntegral $! ts_node_p_end_point_row node) (fromIntegral $! ts_node_p_end_point_column node) }
|
||||||
|
|
||||||
-- Note: The strict application here is semantically important. Without it, we may not evaluate the range until after we’ve exited the scope that `node` was allocated within, meaning `alloca` will free it & other stack data may overwrite it.
|
-- Note: The strict application here is semantically important. Without it, we may not evaluate the range until after we’ve exited the scope that `node` was allocated within, meaning `alloca` will free it & other stack data may overwrite it.
|
||||||
range <- pure $! Range { start = fromIntegral $ ts_node_p_start_char node, end = fromIntegral $ ts_node_p_end_char node }
|
let info = range `seq` range .: categoriesForLanguage language (toS name) .: RNil
|
||||||
|
termConstructor (source blob) (sourceSpan `seq` pure sourceSpan) info children
|
||||||
sourceSpan <- pure $! SourceSpan { spanName = toS (path blob)
|
getChild node n out = ts_node_p_named_child node n out >> toTerm out
|
||||||
, spanStart = SourcePos (fromIntegral $ ts_node_p_start_point_row node) (fromIntegral $ ts_node_p_start_point_column node)
|
{-# INLINE getChild #-}
|
||||||
, spanEnd = SourcePos (fromIntegral $ ts_node_p_end_point_row node) (fromIntegral $ ts_node_p_end_point_column node) }
|
|
||||||
|
|
||||||
let info = range .: (categoriesForLanguage language (toS name)) .: RNil
|
|
||||||
pure $! termConstructor (source blob) sourceSpan info children
|
|
||||||
getChild node n out = do
|
|
||||||
_ <- ts_node_p_named_child node n out
|
|
||||||
toTerm out
|
|
||||||
|
Loading…
Reference in New Issue
Block a user