mirror of
https://github.com/github/semantic.git
synced 2025-01-05 14:11:33 +03:00
Source carries its Range.
This commit is contained in:
parent
3298641a3b
commit
672ff179ed
@ -9,7 +9,6 @@ import Data.Record
|
|||||||
import Diff
|
import Diff
|
||||||
import Info
|
import Info
|
||||||
import Prologue
|
import Prologue
|
||||||
import Range
|
|
||||||
import qualified Data.List as List
|
import qualified Data.List as List
|
||||||
import qualified Data.Map as Map hiding (null)
|
import qualified Data.Map as Map hiding (null)
|
||||||
import Renderer
|
import Renderer
|
||||||
@ -152,10 +151,9 @@ termToDiffInfo source term = case unwrap term of
|
|||||||
_ -> toLeafInfo term
|
_ -> toLeafInfo term
|
||||||
where
|
where
|
||||||
toTermName' :: SyntaxTerm leaf fields -> Text
|
toTermName' :: SyntaxTerm leaf fields -> Text
|
||||||
toTermName' subterm = toTermName (Source.slice (subtermRange subterm) source) subterm
|
toTermName' subterm = toTermName (Source.slice (range subterm) source) subterm
|
||||||
range = characterRange . extract
|
range = characterRange . extract
|
||||||
subtermRange subterm = offsetRange (range subterm) (negate (start (range term)))
|
termToDiffInfo' subterm = termToDiffInfo (Source.slice (range subterm) source) subterm
|
||||||
termToDiffInfo' subterm = termToDiffInfo (Source.slice (subtermRange subterm) source) subterm
|
|
||||||
toLeafInfo term = LeafInfo (category $ extract term) (toTermName' term) (getField $ extract term)
|
toLeafInfo term = LeafInfo (category $ extract term) (toTermName' term) (getField $ extract term)
|
||||||
|
|
||||||
toTermName :: forall leaf fields. DefaultFields fields => Source -> SyntaxTerm leaf fields -> Text
|
toTermName :: forall leaf fields. DefaultFields fields => Source -> SyntaxTerm leaf fields -> Text
|
||||||
@ -166,6 +164,5 @@ toTermName source term = case unwrap term of
|
|||||||
_ -> toText source
|
_ -> toText source
|
||||||
where
|
where
|
||||||
toTermName' :: SyntaxTerm leaf fields -> Text
|
toTermName' :: SyntaxTerm leaf fields -> Text
|
||||||
toTermName' subterm = toTermName (Source.slice (range' subterm) source) subterm
|
toTermName' subterm = toTermName (Source.slice (range subterm) source) subterm
|
||||||
range' subterm = offsetRange (range subterm) (negate (start (range term)))
|
|
||||||
range = characterRange . extract
|
range = characterRange . extract
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
|
|
||||||
{-# OPTIONS_GHC -funbox-strict-fields #-}
|
{-# OPTIONS_GHC -funbox-strict-fields #-}
|
||||||
module Source where
|
module Source where
|
||||||
|
|
||||||
@ -14,7 +13,7 @@ data SourceBlob = SourceBlob { source :: Source, oid :: String, path :: FilePath
|
|||||||
deriving (Show, Eq)
|
deriving (Show, Eq)
|
||||||
|
|
||||||
-- | The contents of a source file, represented as Text.
|
-- | The contents of a source file, represented as Text.
|
||||||
newtype Source = Source { sourceText :: Text }
|
data Source = Source { sourceText :: Text, sourceRange :: Range }
|
||||||
deriving (Eq, Show)
|
deriving (Eq, Show)
|
||||||
|
|
||||||
-- | The kind of a blob, along with it's file mode.
|
-- | The kind of a blob, along with it's file mode.
|
||||||
@ -46,17 +45,18 @@ idOrEmptySourceBlob blob = if isNothing (blobKind blob)
|
|||||||
nullOid :: String
|
nullOid :: String
|
||||||
nullOid = "0000000000000000000000000000000000000000"
|
nullOid = "0000000000000000000000000000000000000000"
|
||||||
|
|
||||||
-- | Return a Source from a list of items.
|
-- | Return a Source from a finite string.
|
||||||
fromList :: [Char] -> Source
|
fromList :: [Char] -> Source
|
||||||
fromList = Source . Text.pack
|
fromList = fromText . Text.pack
|
||||||
|
|
||||||
-- | Return a Source of Chars from a Text.
|
-- | Return a Source of Chars from a Text.
|
||||||
fromText :: Text -> Source
|
fromText :: Text -> Source
|
||||||
fromText = Source
|
fromText sourceText = Source sourceText sourceRange
|
||||||
|
where sourceRange = Range 0 (Text.length sourceText)
|
||||||
|
|
||||||
-- | Return a Source that contains a slice of the given Source.
|
-- | Return a Source that contains a slice of the given Source.
|
||||||
slice :: Range -> Source -> Source
|
slice :: Range -> Source -> Source
|
||||||
slice range = Source . Text.take (rangeLength range) . Text.drop (start range) . sourceText
|
slice range Source{..} = Source (Text.take (rangeLength range) (Text.drop (start range - start sourceRange) sourceText)) range
|
||||||
|
|
||||||
-- | Return a String with the contents of the Source.
|
-- | Return a String with the contents of the Source.
|
||||||
toString :: Source -> String
|
toString :: Source -> String
|
||||||
@ -72,11 +72,13 @@ at = Text.index . sourceText
|
|||||||
|
|
||||||
-- | Remove the first item and return it with the rest of the source.
|
-- | Remove the first item and return it with the rest of the source.
|
||||||
uncons :: Source -> Maybe (Char, Source)
|
uncons :: Source -> Maybe (Char, Source)
|
||||||
uncons (Source text) = if Text.null text then Nothing else Just (Text.head text, Source $ Text.tail text)
|
uncons Source{..} = if Text.null sourceText then Nothing else Just (Text.head sourceText, Source (Text.tail sourceText) (snd (divideRange sourceRange (start sourceRange + 1))))
|
||||||
|
|
||||||
-- | Split the source into the longest prefix of elements that do not satisfy the predicate and the rest without copying.
|
-- | Split the source into the longest prefix of elements that do not satisfy the predicate and the rest without copying.
|
||||||
break :: (Char -> Bool) -> Source -> (Source, Source)
|
break :: (Char -> Bool) -> Source -> (Source, Source)
|
||||||
break predicate (Source text) = let (start, remainder) = Text.break predicate text in (Source start, Source remainder)
|
break predicate Source{..} = (Source initial initialRange, Source remainder remainderRange)
|
||||||
|
where (initial, remainder) = Text.break predicate sourceText
|
||||||
|
(initialRange, remainderRange) = divideRange sourceRange (start sourceRange + Text.length initial)
|
||||||
|
|
||||||
-- | Split the contents of the source after newlines.
|
-- | Split the contents of the source after newlines.
|
||||||
actualLines :: Source -> [Source]
|
actualLines :: Source -> [Source]
|
||||||
@ -118,7 +120,7 @@ null :: Source -> Bool
|
|||||||
null = Text.null . sourceText
|
null = Text.null . sourceText
|
||||||
|
|
||||||
instance Semigroup Source where
|
instance Semigroup Source where
|
||||||
Source a <> Source b = Source (a <> b)
|
Source a ar <> Source b br = Source (a <> b) (ar <> br)
|
||||||
|
|
||||||
instance Monoid Source where
|
instance Monoid Source where
|
||||||
mempty = fromList []
|
mempty = fromList []
|
||||||
|
@ -48,24 +48,24 @@ documentToTerm language document SourceBlob{..} = alloca $ \ root -> do
|
|||||||
name <- ts_node_p_name node document
|
name <- ts_node_p_name node document
|
||||||
name <- peekCString name
|
name <- peekCString name
|
||||||
count <- ts_node_p_named_child_count node
|
count <- ts_node_p_named_child_count node
|
||||||
children <- filter isNonEmpty <$> traverse (alloca . getChild ts_node_p_named_child (start range) node) (take (fromIntegral count) [0..])
|
children <- filter isNonEmpty <$> traverse (alloca . getChild ts_node_p_named_child node) (take (fromIntegral count) [0..])
|
||||||
|
|
||||||
let startPos = SourcePos (1 + (fromIntegral $! ts_node_p_start_point_row node)) (1 + (fromIntegral $! ts_node_p_start_point_column node))
|
let startPos = SourcePos (1 + (fromIntegral $! ts_node_p_start_point_row node)) (1 + (fromIntegral $! ts_node_p_start_point_column node))
|
||||||
let endPos = SourcePos (1 + (fromIntegral $! ts_node_p_end_point_row node)) (1 + (fromIntegral $! ts_node_p_end_point_column node))
|
let endPos = SourcePos (1 + (fromIntegral $! ts_node_p_end_point_row node)) (1 + (fromIntegral $! ts_node_p_end_point_column node))
|
||||||
let sourceSpan = SourceSpan { spanStart = startPos , spanEnd = endPos }
|
let sourceSpan = SourceSpan { spanStart = startPos , spanEnd = endPos }
|
||||||
|
|
||||||
allChildrenCount <- ts_node_p_child_count node
|
allChildrenCount <- ts_node_p_child_count node
|
||||||
let allChildren = filter isNonEmpty <$> traverse (alloca . getChild ts_node_p_child (start range) node) (take (fromIntegral allChildrenCount) [0..])
|
let allChildren = filter isNonEmpty <$> traverse (alloca . getChild ts_node_p_child node) (take (fromIntegral allChildrenCount) [0..])
|
||||||
|
|
||||||
-- Note: The strict application here is semantically important.
|
-- Note: The strict application here is semantically important.
|
||||||
-- Without it, we may not evaluate the value until after we’ve exited
|
-- Without it, we may not evaluate the value until after we’ve exited
|
||||||
-- the scope that `node` was allocated within, meaning `alloca` will
|
-- the scope that `node` was allocated within, meaning `alloca` will
|
||||||
-- free it & other stack data may overwrite it.
|
-- free it & other stack data may overwrite it.
|
||||||
range `seq` sourceSpan `seq` assignTerm language source (range :. categoryForLanguageProductionName language (toS name) :. sourceSpan :. Nil) children allChildren
|
range `seq` sourceSpan `seq` assignTerm language source (range :. categoryForLanguageProductionName language (toS name) :. sourceSpan :. Nil) children allChildren
|
||||||
getChild getter start node n out = do
|
getChild getter node n out = do
|
||||||
_ <- getter node n out
|
_ <- getter node n out
|
||||||
let childRange = nodeRange node
|
let childRange = nodeRange node
|
||||||
toTerm out childRange (slice (offsetRange childRange (negate start)) source)
|
toTerm out childRange (slice childRange source)
|
||||||
{-# INLINE getChild #-}
|
{-# INLINE getChild #-}
|
||||||
isNonEmpty child = category (extract child) /= Empty
|
isNonEmpty child = category (extract child) /= Empty
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user