1
1
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:
Rob Rix 2017-02-10 15:33:41 -05:00
parent 3298641a3b
commit 672ff179ed
3 changed files with 18 additions and 19 deletions

View File

@ -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

View File

@ -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 []

View File

@ -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 weve exited -- Without it, we may not evaluate the value until after weve 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