From c191312ece6ce4c17ca74850d6b5cfafe6ad5465 Mon Sep 17 00:00:00 2001 From: joshvera Date: Mon, 8 Aug 2016 12:21:56 -0400 Subject: [PATCH 1/7] Move instances down and exported types up --- src/DiffSummary.hs | 184 +++++++++++++++++++++++---------------------- 1 file changed, 93 insertions(+), 91 deletions(-) diff --git a/src/DiffSummary.hs b/src/DiffSummary.hs index 001cd79d3..90b828b6c 100644 --- a/src/DiffSummary.hs +++ b/src/DiffSummary.hs @@ -26,6 +26,67 @@ data DiffInfo = LeafInfo { categoryName :: Text, termName :: Text } | ErrorInfo { errorSpan :: SourceSpan, categoryName :: Text } deriving (Eq, Show) +data Branch = BIndexed | BFixed | BCommented deriving (Show, Eq, Generic) +data DiffSummary a = DiffSummary { + patch :: Patch a, + parentAnnotations :: [Category] +} deriving (Eq, Functor, Show, Generic) + +annotatedSummaries :: DiffSummary DiffInfo -> [Text] +annotatedSummaries DiffSummary{..} = show . (P.<> maybeParentContext parentAnnotations) <$> summaries patch + +diffSummaries :: (HasCategory leaf, HasField fields Category, HasField fields Range) => Both (Source Char) -> Diff leaf (Record fields) -> [DiffSummary DiffInfo] +diffSummaries sources = cata $ \case + -- Skip comments and leaves since they don't have any changes + (Free (_ :< Leaf _)) -> [] + Free (_ :< (S.Comment _)) -> [] + (Free (infos :< S.Indexed children)) -> annotateWithCategory infos <$> join children + (Free (infos :< S.Fixed children)) -> annotateWithCategory infos <$> join children + (Free (infos :< S.FunctionCall identifier children)) -> annotateWithCategory infos <$> join (Prologue.toList (identifier : children)) + (Free (infos :< S.Function id ps body)) -> annotateWithCategory infos <$> (fromMaybe [] id) <> (fromMaybe [] ps) <> body + (Free (infos :< S.Assignment id value)) -> annotateWithCategory infos <$> id <> value + (Free (infos :< S.MemberAccess base property)) -> annotateWithCategory infos <$> base <> property + (Free (infos :< S.SubscriptAccess base property)) -> annotateWithCategory infos <$> base <> property + (Free (infos :< S.MethodCall targetId methodId ps)) -> annotateWithCategory infos <$> targetId <> methodId <> ps + (Free (infos :< S.VarAssignment varId value)) -> annotateWithCategory infos <$> varId <> value + (Free (infos :< S.VarDecl decl)) -> annotateWithCategory infos <$> decl + (Free (infos :< S.Args args)) -> annotateWithCategory infos <$> join args + (Free (infos :< S.Switch expr cases)) -> annotateWithCategory infos <$> expr <> join cases + (Free (infos :< S.Case expr body)) -> annotateWithCategory infos <$> expr <> body + Free (infos :< (S.Ternary expr cases)) -> annotateWithCategory infos <$> expr <> join cases + Free (infos :< (S.MathAssignment id value)) -> annotateWithCategory infos <$> id <> value + Free (infos :< (S.Operator syntaxes)) -> annotateWithCategory infos <$> join syntaxes + Free (infos :< (S.Object kvs)) -> annotateWithCategory infos <$> join kvs + Free (infos :< (S.Return expr)) -> annotateWithCategory infos <$> fromMaybe [] expr + Free (infos :< (S.Pair a b)) -> annotateWithCategory infos <$> a <> b + Free (infos :< (S.Commented cs leaf)) -> annotateWithCategory infos <$> join cs <> fromMaybe [] leaf + Free (infos :< (S.Error _ children)) -> annotateWithCategory infos <$> join children + (Free (infos :< S.For exprs body)) -> annotateWithCategory infos <$> join exprs <> body + (Free (infos :< S.While expr body)) -> annotateWithCategory infos <$> expr <> body + (Free (infos :< S.DoWhile expr body)) -> annotateWithCategory infos <$> expr <> body + (Free (infos :< S.Throw expr)) -> annotateWithCategory infos <$> expr + (Free (infos :< S.Constructor expr)) -> annotateWithCategory infos <$> expr + (Free (infos :< S.Try expr catch finally)) -> annotateWithCategory infos <$> expr <> fromMaybe [] catch <> fromMaybe [] finally + (Free (infos :< S.Array children)) -> annotateWithCategory infos <$> join children + (Free (infos :< S.Class identifier superclass definitions)) -> annotateWithCategory infos <$> identifier <> fromMaybe [] superclass <> join definitions + (Free (infos :< S.Method identifier params definitions)) -> annotateWithCategory infos <$> identifier <> join params <> join definitions + (Pure (Insert term)) -> [ DiffSummary (Insert $ termToDiffInfo afterSource term) [] ] + (Pure (Delete term)) -> [ DiffSummary (Delete $ termToDiffInfo beforeSource term) [] ] + (Pure (Replace t1 t2)) -> [ DiffSummary (Replace (termToDiffInfo beforeSource t1) (termToDiffInfo afterSource t2)) [] ] + where + (beforeSource, afterSource) = runJoin sources + annotateWithCategory infos = prependSummary (category $ snd infos) + +summaries :: Patch DiffInfo -> [P.Doc] +summaries (Insert info) = (("Added" <+> "the") <+>) <$> toLeafInfos info +summaries (Delete info) = (("Deleted" <+> "the") <+>) <$> toLeafInfos info +summaries (Replace i1 i2) = zipWith (\a b -> "Replaced" <+> "the" <+> a <+> "with the" <+> b) (toLeafInfos i1) (toLeafInfos i2) + +toLeafInfos :: DiffInfo -> [Doc] +toLeafInfos LeafInfo{..} = pure $ squotes (toDoc termName) <+> (toDoc categoryName) +toLeafInfos BranchInfo{..} = pretty <$> branches +toLeafInfos err@ErrorInfo{} = pure $ pretty err + toTermName :: (HasCategory leaf, HasField fields Category, HasField fields Range) => Source Char -> Term leaf (Record fields) -> Text toTermName source term = case unwrap term of S.Fixed children -> fromMaybe "branch" $ (toCategoryName . category) . extract <$> head children @@ -81,9 +142,41 @@ toTermName source term = case unwrap term of termNameFromRange range = toText $ Source.slice range source range = characterRange . extract +maybeParentContext :: [Category] -> Doc +maybeParentContext annotations = if null annotations + then "" + else space <> "in the" <+> (toDoc . intercalate "/" $ toCategoryName <$> annotations) <+> "context" +toDoc :: Text -> Doc +toDoc = string . toS + +termToDiffInfo :: (HasCategory leaf, HasField fields Category, HasField fields Range) => Source Char -> Term leaf (Record fields) -> DiffInfo +termToDiffInfo blob term = case unwrap term of + Leaf _ -> LeafInfo (toCategoryName term) (toTermName' term) + S.Indexed children -> BranchInfo (termToDiffInfo' <$> children) (toCategoryName term) BIndexed + S.Fixed children -> BranchInfo (termToDiffInfo' <$> children) (toCategoryName term) BFixed + S.FunctionCall identifier _ -> LeafInfo (toCategoryName term) (toTermName' identifier) + S.Ternary ternaryCondition _ -> LeafInfo (toCategoryName term) (toTermName' ternaryCondition) + S.Function identifier _ _ -> LeafInfo (toCategoryName term) (maybe "anonymous" toTermName' identifier) + S.Assignment identifier _ -> LeafInfo (toCategoryName term) (toTermName' identifier) + S.MathAssignment identifier _ -> LeafInfo (toCategoryName term) (toTermName' identifier) + -- Currently we cannot express the operator for an operator production from TreeSitter. Eventually we should be able to + -- use the term name of the operator identifier when we have that production value. Until then, I'm using a placeholder value + -- to indicate where that value should be when constructing DiffInfos. + Commented cs leaf -> BranchInfo (termToDiffInfo' <$> cs <> maybeToList leaf) (toCategoryName term) BCommented + S.Error sourceSpan _ -> ErrorInfo sourceSpan (toCategoryName term) + _ -> LeafInfo (toCategoryName term) (toTermName' term) + where toTermName' = toTermName blob + termToDiffInfo' = termToDiffInfo blob + +prependSummary :: Category -> DiffSummary DiffInfo -> DiffSummary DiffInfo +prependSummary annotation summary = summary { parentAnnotations = annotation : parentAnnotations summary } + +-- The user-facing category name of 'a'. class HasCategory a where toCategoryName :: a -> Text +-- Instances + instance HasCategory Text where toCategoryName = identity @@ -135,16 +228,10 @@ instance HasCategory Category where instance (HasCategory leaf, HasField fields Category) => HasCategory (Term leaf (Record fields)) where toCategoryName = toCategoryName . category . extract -data Branch = BIndexed | BFixed | BCommented deriving (Show, Eq, Generic) instance Arbitrary Branch where arbitrary = oneof [ pure BIndexed, pure BFixed ] shrink = genericShrink -data DiffSummary a = DiffSummary { - patch :: Patch a, - parentAnnotations :: [Category] -} deriving (Eq, Functor, Show, Generic) - instance (Eq a, Arbitrary a) => Arbitrary (DiffSummary a) where arbitrary = DiffSummary <$> arbitrary <*> arbitrary shrink = genericShrink @@ -153,88 +240,3 @@ instance P.Pretty DiffInfo where pretty LeafInfo{..} = squotes (string $ toSL termName) <+> (string $ toSL categoryName) pretty BranchInfo{..} = mconcat $ punctuate (string "," <> space) (pretty <$> branches) pretty ErrorInfo{..} = "syntax error at" <+> (string . toSL $ displayStartEndPos errorSpan) <+> "in" <+> (string . toSL $ spanName errorSpan) - -annotatedSummaries :: DiffSummary DiffInfo -> [Text] -annotatedSummaries DiffSummary{..} = show . (P.<> maybeParentContext parentAnnotations) <$> summaries patch - -summaries :: Patch DiffInfo -> [P.Doc] -summaries (Insert info) = (("Added" <+> "the") <+>) <$> toLeafInfos info -summaries (Delete info) = (("Deleted" <+> "the") <+>) <$> toLeafInfos info -summaries (Replace i1 i2) = zipWith (\a b -> "Replaced" <+> "the" <+> a <+> "with the" <+> b) (toLeafInfos i1) (toLeafInfos i2) - -toLeafInfos :: DiffInfo -> [Doc] -toLeafInfos LeafInfo{..} = pure $ squotes (toDoc termName) <+> (toDoc categoryName) -toLeafInfos BranchInfo{..} = pretty <$> branches -toLeafInfos err@ErrorInfo{} = pure $ pretty err - -maybeParentContext :: [Category] -> Doc -maybeParentContext annotations = if null annotations - then "" - else space <> "in the" <+> (toDoc . intercalate "/" $ toCategoryName <$> annotations) <+> "context" -toDoc :: Text -> Doc -toDoc = string . toS - -diffSummaries :: (HasCategory leaf, HasField fields Category, HasField fields Range) => Both (Source Char) -> Diff leaf (Record fields) -> [DiffSummary DiffInfo] -diffSummaries sources = cata $ \case - -- Skip comments and leaves since they don't have any changes - (Free (_ :< Leaf _)) -> [] - Free (_ :< (S.Comment _)) -> [] - (Free (infos :< S.Indexed children)) -> annotateWithCategory infos <$> join children - (Free (infos :< S.Fixed children)) -> annotateWithCategory infos <$> join children - (Free (infos :< S.FunctionCall identifier children)) -> annotateWithCategory infos <$> join (Prologue.toList (identifier : children)) - (Free (infos :< S.Function id ps body)) -> annotateWithCategory infos <$> (fromMaybe [] id) <> (fromMaybe [] ps) <> body - (Free (infos :< S.Assignment id value)) -> annotateWithCategory infos <$> id <> value - (Free (infos :< S.MemberAccess base property)) -> annotateWithCategory infos <$> base <> property - (Free (infos :< S.SubscriptAccess base property)) -> annotateWithCategory infos <$> base <> property - (Free (infos :< S.MethodCall targetId methodId ps)) -> annotateWithCategory infos <$> targetId <> methodId <> ps - (Free (infos :< S.VarAssignment varId value)) -> annotateWithCategory infos <$> varId <> value - (Free (infos :< S.VarDecl decl)) -> annotateWithCategory infos <$> decl - (Free (infos :< S.Args args)) -> annotateWithCategory infos <$> join args - (Free (infos :< S.Switch expr cases)) -> annotateWithCategory infos <$> expr <> join cases - (Free (infos :< S.Case expr body)) -> annotateWithCategory infos <$> expr <> body - Free (infos :< (S.Ternary expr cases)) -> annotateWithCategory infos <$> expr <> join cases - Free (infos :< (S.MathAssignment id value)) -> annotateWithCategory infos <$> id <> value - Free (infos :< (S.Operator syntaxes)) -> annotateWithCategory infos <$> join syntaxes - Free (infos :< (S.Object kvs)) -> annotateWithCategory infos <$> join kvs - Free (infos :< (S.Return expr)) -> annotateWithCategory infos <$> fromMaybe [] expr - Free (infos :< (S.Pair a b)) -> annotateWithCategory infos <$> a <> b - Free (infos :< (S.Commented cs leaf)) -> annotateWithCategory infos <$> join cs <> fromMaybe [] leaf - Free (infos :< (S.Error _ children)) -> annotateWithCategory infos <$> join children - (Free (infos :< S.For exprs body)) -> annotateWithCategory infos <$> join exprs <> body - (Free (infos :< S.While expr body)) -> annotateWithCategory infos <$> expr <> body - (Free (infos :< S.DoWhile expr body)) -> annotateWithCategory infos <$> expr <> body - (Free (infos :< S.Throw expr)) -> annotateWithCategory infos <$> expr - (Free (infos :< S.Constructor expr)) -> annotateWithCategory infos <$> expr - (Free (infos :< S.Try expr catch finally)) -> annotateWithCategory infos <$> expr <> fromMaybe [] catch <> fromMaybe [] finally - (Free (infos :< S.Array children)) -> annotateWithCategory infos <$> join children - (Free (infos :< S.Class identifier superclass definitions)) -> annotateWithCategory infos <$> identifier <> fromMaybe [] superclass <> join definitions - (Free (infos :< S.Method identifier params definitions)) -> annotateWithCategory infos <$> identifier <> join params <> join definitions - (Pure (Insert term)) -> [ DiffSummary (Insert $ termToDiffInfo afterSource term) [] ] - (Pure (Delete term)) -> [ DiffSummary (Delete $ termToDiffInfo beforeSource term) [] ] - (Pure (Replace t1 t2)) -> [ DiffSummary (Replace (termToDiffInfo beforeSource t1) (termToDiffInfo afterSource t2)) [] ] - where - (beforeSource, afterSource) = runJoin sources - annotateWithCategory infos = prependSummary (category $ snd infos) - - -termToDiffInfo :: (HasCategory leaf, HasField fields Category, HasField fields Range) => Source Char -> Term leaf (Record fields) -> DiffInfo -termToDiffInfo blob term = case unwrap term of - Leaf _ -> LeafInfo (toCategoryName term) (toTermName' term) - S.Indexed children -> BranchInfo (termToDiffInfo' <$> children) (toCategoryName term) BIndexed - S.Fixed children -> BranchInfo (termToDiffInfo' <$> children) (toCategoryName term) BFixed - S.FunctionCall identifier _ -> LeafInfo (toCategoryName term) (toTermName' identifier) - S.Ternary ternaryCondition _ -> LeafInfo (toCategoryName term) (toTermName' ternaryCondition) - S.Function identifier _ _ -> LeafInfo (toCategoryName term) (maybe "anonymous" toTermName' identifier) - S.Assignment identifier _ -> LeafInfo (toCategoryName term) (toTermName' identifier) - S.MathAssignment identifier _ -> LeafInfo (toCategoryName term) (toTermName' identifier) - -- Currently we cannot express the operator for an operator production from TreeSitter. Eventually we should be able to - -- use the term name of the operator identifier when we have that production value. Until then, I'm using a placeholder value - -- to indicate where that value should be when constructing DiffInfos. - Commented cs leaf -> BranchInfo (termToDiffInfo' <$> cs <> maybeToList leaf) (toCategoryName term) BCommented - S.Error sourceSpan _ -> ErrorInfo sourceSpan (toCategoryName term) - _ -> LeafInfo (toCategoryName term) (toTermName' term) - where toTermName' = toTermName blob - termToDiffInfo' = termToDiffInfo blob - -prependSummary :: Category -> DiffSummary DiffInfo -> DiffSummary DiffInfo -prependSummary annotation summary = summary { parentAnnotations = annotation : parentAnnotations summary } From 51cb8918a94c6f8a85a6e39516ed897a876c381d Mon Sep 17 00:00:00 2001 From: joshvera Date: Mon, 8 Aug 2016 14:06:07 -0400 Subject: [PATCH 2/7] Prepend (Category, TermName) to DiffSummary.parentAnnotations --- src/DiffSummary.hs | 71 ++++++++++++++++------------------------------ 1 file changed, 24 insertions(+), 47 deletions(-) diff --git a/src/DiffSummary.hs b/src/DiffSummary.hs index 90b828b6c..1b2f67d9d 100644 --- a/src/DiffSummary.hs +++ b/src/DiffSummary.hs @@ -2,7 +2,7 @@ module DiffSummary (DiffSummary(..), diffSummaries, DiffInfo(..), annotatedSummaries) where -import Prologue hiding (snd, intercalate) +import Prologue hiding (intercalate) import Diff import Patch import Term @@ -11,7 +11,8 @@ import Range import Syntax as S import Category as C import Data.Functor.Foldable as Foldable -import Data.Functor.Both +import Data.Functor.Both hiding (fst, snd) +import qualified Data.Functor.Both as Both import Data.Text as Text (intercalate) import Test.QuickCheck hiding (Fixed) import Patch.Arbitrary() @@ -27,55 +28,31 @@ data DiffInfo = LeafInfo { categoryName :: Text, termName :: Text } deriving (Eq, Show) data Branch = BIndexed | BFixed | BCommented deriving (Show, Eq, Generic) + data DiffSummary a = DiffSummary { patch :: Patch a, - parentAnnotations :: [Category] + parentAnnotations :: [(Category, Text)] } deriving (Eq, Functor, Show, Generic) annotatedSummaries :: DiffSummary DiffInfo -> [Text] annotatedSummaries DiffSummary{..} = show . (P.<> maybeParentContext parentAnnotations) <$> summaries patch diffSummaries :: (HasCategory leaf, HasField fields Category, HasField fields Range) => Both (Source Char) -> Diff leaf (Record fields) -> [DiffSummary DiffInfo] -diffSummaries sources = cata $ \case - -- Skip comments and leaves since they don't have any changes - (Free (_ :< Leaf _)) -> [] - Free (_ :< (S.Comment _)) -> [] - (Free (infos :< S.Indexed children)) -> annotateWithCategory infos <$> join children - (Free (infos :< S.Fixed children)) -> annotateWithCategory infos <$> join children - (Free (infos :< S.FunctionCall identifier children)) -> annotateWithCategory infos <$> join (Prologue.toList (identifier : children)) - (Free (infos :< S.Function id ps body)) -> annotateWithCategory infos <$> (fromMaybe [] id) <> (fromMaybe [] ps) <> body - (Free (infos :< S.Assignment id value)) -> annotateWithCategory infos <$> id <> value - (Free (infos :< S.MemberAccess base property)) -> annotateWithCategory infos <$> base <> property - (Free (infos :< S.SubscriptAccess base property)) -> annotateWithCategory infos <$> base <> property - (Free (infos :< S.MethodCall targetId methodId ps)) -> annotateWithCategory infos <$> targetId <> methodId <> ps - (Free (infos :< S.VarAssignment varId value)) -> annotateWithCategory infos <$> varId <> value - (Free (infos :< S.VarDecl decl)) -> annotateWithCategory infos <$> decl - (Free (infos :< S.Args args)) -> annotateWithCategory infos <$> join args - (Free (infos :< S.Switch expr cases)) -> annotateWithCategory infos <$> expr <> join cases - (Free (infos :< S.Case expr body)) -> annotateWithCategory infos <$> expr <> body - Free (infos :< (S.Ternary expr cases)) -> annotateWithCategory infos <$> expr <> join cases - Free (infos :< (S.MathAssignment id value)) -> annotateWithCategory infos <$> id <> value - Free (infos :< (S.Operator syntaxes)) -> annotateWithCategory infos <$> join syntaxes - Free (infos :< (S.Object kvs)) -> annotateWithCategory infos <$> join kvs - Free (infos :< (S.Return expr)) -> annotateWithCategory infos <$> fromMaybe [] expr - Free (infos :< (S.Pair a b)) -> annotateWithCategory infos <$> a <> b - Free (infos :< (S.Commented cs leaf)) -> annotateWithCategory infos <$> join cs <> fromMaybe [] leaf - Free (infos :< (S.Error _ children)) -> annotateWithCategory infos <$> join children - (Free (infos :< S.For exprs body)) -> annotateWithCategory infos <$> join exprs <> body - (Free (infos :< S.While expr body)) -> annotateWithCategory infos <$> expr <> body - (Free (infos :< S.DoWhile expr body)) -> annotateWithCategory infos <$> expr <> body - (Free (infos :< S.Throw expr)) -> annotateWithCategory infos <$> expr - (Free (infos :< S.Constructor expr)) -> annotateWithCategory infos <$> expr - (Free (infos :< S.Try expr catch finally)) -> annotateWithCategory infos <$> expr <> fromMaybe [] catch <> fromMaybe [] finally - (Free (infos :< S.Array children)) -> annotateWithCategory infos <$> join children - (Free (infos :< S.Class identifier superclass definitions)) -> annotateWithCategory infos <$> identifier <> fromMaybe [] superclass <> join definitions - (Free (infos :< S.Method identifier params definitions)) -> annotateWithCategory infos <$> identifier <> join params <> join definitions - (Pure (Insert term)) -> [ DiffSummary (Insert $ termToDiffInfo afterSource term) [] ] - (Pure (Delete term)) -> [ DiffSummary (Delete $ termToDiffInfo beforeSource term) [] ] - (Pure (Replace t1 t2)) -> [ DiffSummary (Replace (termToDiffInfo beforeSource t1) (termToDiffInfo afterSource t2)) [] ] +diffSummaries sources = para $ \diff -> + let diff' = free (Prologue.fst <$> diff) + annotateWithCategory :: [(Diff leaf (Record fields), [DiffSummary DiffInfo])] -> [DiffSummary DiffInfo] + annotateWithCategory children = maybeToList (prependSummary (Both.snd sources) <$> (afterTerm diff')) <*> (children >>= snd) in + case diff of + -- Skip comments and leaves since they don't have any changes + Free (_ :< Leaf _) -> [] + Free (_ :< (S.Comment _)) -> [] + (Free (_ :< syntax)) -> annotateWithCategory (toList syntax) + (Pure (Insert term)) -> [ DiffSummary (Insert $ termToDiffInfo afterSource term) [] ] + (Pure (Delete term)) -> [ DiffSummary (Delete $ termToDiffInfo beforeSource term) [] ] + (Pure (Replace t1 t2)) -> [ DiffSummary (Replace (termToDiffInfo beforeSource t1) (termToDiffInfo afterSource t2)) [] ] where (beforeSource, afterSource) = runJoin sources - annotateWithCategory infos = prependSummary (category $ snd infos) + summaries :: Patch DiffInfo -> [P.Doc] summaries (Insert info) = (("Added" <+> "the") <+>) <$> toLeafInfos info @@ -142,10 +119,10 @@ toTermName source term = case unwrap term of termNameFromRange range = toText $ Source.slice range source range = characterRange . extract -maybeParentContext :: [Category] -> Doc -maybeParentContext annotations = if null annotations - then "" - else space <> "in the" <+> (toDoc . intercalate "/" $ toCategoryName <$> annotations) <+> "context" +maybeParentContext :: [(Category, Text)] -> Doc +maybeParentContext annotations = case annotations of + [] -> "" + (annotation:xs) -> space <> "in the" <+> (toDoc $ snd annotation) <+> toDoc (toCategoryName $ fst annotation) toDoc :: Text -> Doc toDoc = string . toS @@ -168,8 +145,8 @@ termToDiffInfo blob term = case unwrap term of where toTermName' = toTermName blob termToDiffInfo' = termToDiffInfo blob -prependSummary :: Category -> DiffSummary DiffInfo -> DiffSummary DiffInfo -prependSummary annotation summary = summary { parentAnnotations = annotation : parentAnnotations summary } +prependSummary :: (HasCategory leaf, HasField fields Range, HasField fields Category) => Source Char -> Term leaf (Record fields) -> DiffSummary DiffInfo -> DiffSummary DiffInfo +prependSummary source term summary = summary { parentAnnotations = (category $ extract term, toTermName source term) : parentAnnotations summary } -- The user-facing category name of 'a'. class HasCategory a where From d8ff761f4053e29668c9dc76dca1aef4d24f1ff5 Mon Sep 17 00:00:00 2001 From: joshvera Date: Mon, 8 Aug 2016 14:19:47 -0400 Subject: [PATCH 3/7] Add mapPatch --- src/DiffSummary.hs | 8 ++------ src/Patch.hs | 6 ++++++ 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/src/DiffSummary.hs b/src/DiffSummary.hs index 1b2f67d9d..1393c9cdf 100644 --- a/src/DiffSummary.hs +++ b/src/DiffSummary.hs @@ -44,12 +44,8 @@ diffSummaries sources = para $ \diff -> annotateWithCategory children = maybeToList (prependSummary (Both.snd sources) <$> (afterTerm diff')) <*> (children >>= snd) in case diff of -- Skip comments and leaves since they don't have any changes - Free (_ :< Leaf _) -> [] - Free (_ :< (S.Comment _)) -> [] (Free (_ :< syntax)) -> annotateWithCategory (toList syntax) - (Pure (Insert term)) -> [ DiffSummary (Insert $ termToDiffInfo afterSource term) [] ] - (Pure (Delete term)) -> [ DiffSummary (Delete $ termToDiffInfo beforeSource term) [] ] - (Pure (Replace t1 t2)) -> [ DiffSummary (Replace (termToDiffInfo beforeSource t1) (termToDiffInfo afterSource t2)) [] ] + (Pure patch) -> [ DiffSummary (mapPatch (termToDiffInfo beforeSource) (termToDiffInfo afterSource) patch) [] ] where (beforeSource, afterSource) = runJoin sources @@ -122,7 +118,7 @@ toTermName source term = case unwrap term of maybeParentContext :: [(Category, Text)] -> Doc maybeParentContext annotations = case annotations of [] -> "" - (annotation:xs) -> space <> "in the" <+> (toDoc $ snd annotation) <+> toDoc (toCategoryName $ fst annotation) + (annotation:_) -> space <> "in the" <+> (toDoc $ snd annotation) <+> toDoc (toCategoryName $ fst annotation) toDoc :: Text -> Doc toDoc = string . toS diff --git a/src/Patch.hs b/src/Patch.hs index c4dcc8e69..a156f01f2 100644 --- a/src/Patch.hs +++ b/src/Patch.hs @@ -9,6 +9,7 @@ module Patch , patchSum , maybeFst , maybeSnd +, mapPatch ) where import Data.These @@ -51,6 +52,11 @@ unPatch (Replace a b) = These a b unPatch (Insert b) = That b unPatch (Delete a) = This a +mapPatch :: (a -> b) -> (a -> b) -> Patch a -> Patch b +mapPatch f _ (Delete a ) = Delete (f a) +mapPatch _ g (Insert b) = Insert (g b) +mapPatch f g (Replace a b) = Replace (f a) (g b) + -- | Calculate the cost of the patch given a function to compute the cost of a item. patchSum :: (a -> Integer) -> Patch a -> Integer patchSum termCost patch = maybe 0 termCost (before patch) + maybe 0 termCost (after patch) From 11e35ac9c6578e7a7f292af982ef1537b904b3fe Mon Sep 17 00:00:00 2001 From: joshvera Date: Mon, 8 Aug 2016 14:30:55 -0400 Subject: [PATCH 4/7] Only prepend summaries if the parent term has an identifier --- src/DiffSummary.hs | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/DiffSummary.hs b/src/DiffSummary.hs index 1393c9cdf..9068b44ad 100644 --- a/src/DiffSummary.hs +++ b/src/DiffSummary.hs @@ -142,7 +142,21 @@ termToDiffInfo blob term = case unwrap term of termToDiffInfo' = termToDiffInfo blob prependSummary :: (HasCategory leaf, HasField fields Range, HasField fields Category) => Source Char -> Term leaf (Record fields) -> DiffSummary DiffInfo -> DiffSummary DiffInfo -prependSummary source term summary = summary { parentAnnotations = (category $ extract term, toTermName source term) : parentAnnotations summary } +prependSummary source term summary = if hasIdentifier term + then summary { parentAnnotations = (category $ extract term, toTermName source term) : parentAnnotations summary } + else summary + where hasIdentifier term = case unwrap term of + S.FunctionCall{} -> True + S.Function id _ _ -> isJust id + S.Assignment{} -> True + S.MathAssignment{} -> True + S.MemberAccess{} -> True + S.MethodCall{} -> True + S.VarAssignment{} -> True + S.SubscriptAccess{} -> True + S.Class{} -> True + S.Method{} -> True + _ -> False -- The user-facing category name of 'a'. class HasCategory a where From 4efa6f6fa5d22a8487da4cb1bac9fed59d1bd445 Mon Sep 17 00:00:00 2001 From: joshvera Date: Mon, 8 Aug 2016 14:37:51 -0400 Subject: [PATCH 5/7] Add parent annotation to the end of the list --- src/DiffSummary.hs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/DiffSummary.hs b/src/DiffSummary.hs index 9068b44ad..33693d3bd 100644 --- a/src/DiffSummary.hs +++ b/src/DiffSummary.hs @@ -143,7 +143,7 @@ termToDiffInfo blob term = case unwrap term of prependSummary :: (HasCategory leaf, HasField fields Range, HasField fields Category) => Source Char -> Term leaf (Record fields) -> DiffSummary DiffInfo -> DiffSummary DiffInfo prependSummary source term summary = if hasIdentifier term - then summary { parentAnnotations = (category $ extract term, toTermName source term) : parentAnnotations summary } + then summary { parentAnnotations = parentAnnotations summary <> [(category $ extract term, toTermName source term)] } else summary where hasIdentifier term = case unwrap term of S.FunctionCall{} -> True From 81e42933ce40cd12e582e59cd1656c29d3cb3223 Mon Sep 17 00:00:00 2001 From: joshvera Date: Mon, 8 Aug 2016 14:49:19 -0400 Subject: [PATCH 6/7] Just keep track of the immediate parent annotation --- src/DiffSummary.hs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/DiffSummary.hs b/src/DiffSummary.hs index 33693d3bd..766e85306 100644 --- a/src/DiffSummary.hs +++ b/src/DiffSummary.hs @@ -31,11 +31,11 @@ data Branch = BIndexed | BFixed | BCommented deriving (Show, Eq, Generic) data DiffSummary a = DiffSummary { patch :: Patch a, - parentAnnotations :: [(Category, Text)] + parentAnnotation :: Maybe (Category, Text) } deriving (Eq, Functor, Show, Generic) annotatedSummaries :: DiffSummary DiffInfo -> [Text] -annotatedSummaries DiffSummary{..} = show . (P.<> maybeParentContext parentAnnotations) <$> summaries patch +annotatedSummaries DiffSummary{..} = show . (P.<> maybeParentContext parentAnnotation) <$> summaries patch diffSummaries :: (HasCategory leaf, HasField fields Category, HasField fields Range) => Both (Source Char) -> Diff leaf (Record fields) -> [DiffSummary DiffInfo] diffSummaries sources = para $ \diff -> @@ -45,7 +45,7 @@ diffSummaries sources = para $ \diff -> case diff of -- Skip comments and leaves since they don't have any changes (Free (_ :< syntax)) -> annotateWithCategory (toList syntax) - (Pure patch) -> [ DiffSummary (mapPatch (termToDiffInfo beforeSource) (termToDiffInfo afterSource) patch) [] ] + (Pure patch) -> [ DiffSummary (mapPatch (termToDiffInfo beforeSource) (termToDiffInfo afterSource) patch) Nothing ] where (beforeSource, afterSource) = runJoin sources @@ -115,10 +115,10 @@ toTermName source term = case unwrap term of termNameFromRange range = toText $ Source.slice range source range = characterRange . extract -maybeParentContext :: [(Category, Text)] -> Doc -maybeParentContext annotations = case annotations of - [] -> "" - (annotation:_) -> space <> "in the" <+> (toDoc $ snd annotation) <+> toDoc (toCategoryName $ fst annotation) +maybeParentContext :: Maybe (Category, Text) -> Doc +maybeParentContext = maybe "" (\annotation -> + space <> "in the" <+> (toDoc $ snd annotation) <+> toDoc (toCategoryName $ fst annotation)) + toDoc :: Text -> Doc toDoc = string . toS @@ -142,8 +142,8 @@ termToDiffInfo blob term = case unwrap term of termToDiffInfo' = termToDiffInfo blob prependSummary :: (HasCategory leaf, HasField fields Range, HasField fields Category) => Source Char -> Term leaf (Record fields) -> DiffSummary DiffInfo -> DiffSummary DiffInfo -prependSummary source term summary = if hasIdentifier term - then summary { parentAnnotations = parentAnnotations summary <> [(category $ extract term, toTermName source term)] } +prependSummary source term summary = if (isNothing $ parentAnnotation summary) && hasIdentifier term + then summary { parentAnnotation = Just (category $ extract term, toTermName source term) } else summary where hasIdentifier term = case unwrap term of S.FunctionCall{} -> True From 0bee997724ecc65887d8d58b25503268c3c4fecb Mon Sep 17 00:00:00 2001 From: joshvera Date: Mon, 8 Aug 2016 14:59:51 -0400 Subject: [PATCH 7/7] fix tests --- test/DiffSummarySpec.hs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/DiffSummarySpec.hs b/test/DiffSummarySpec.hs index dc648c4bf..e3f0710e3 100644 --- a/test/DiffSummarySpec.hs +++ b/test/DiffSummarySpec.hs @@ -31,10 +31,10 @@ testDiff :: Diff Text (Record '[Category, Range]) testDiff = free $ Free (pure arrayInfo :< Indexed [ free $ Pure (Insert (cofree $ literalInfo :< Leaf "a")) ]) testSummary :: DiffSummary DiffInfo -testSummary = DiffSummary { patch = Insert (LeafInfo "string" "a"), parentAnnotations = [] } +testSummary = DiffSummary { patch = Insert (LeafInfo "string" "a"), parentAnnotation = Nothing } replacementSummary :: DiffSummary DiffInfo -replacementSummary = DiffSummary { patch = Replace (LeafInfo "string" "a") (LeafInfo "symbol" "b"), parentAnnotations = [ ArrayLiteral ] } +replacementSummary = DiffSummary { patch = Replace (LeafInfo "string" "a") (LeafInfo "symbol" "b"), parentAnnotation = Just (Info.FunctionCall, "foo") } sources :: Both (Source Char) sources = both (fromText "[]") (fromText "[a]") @@ -43,7 +43,7 @@ spec :: Spec spec = parallel $ do describe "diffSummaries" $ do it "outputs a diff summary" $ do - diffSummaries sources testDiff `shouldBe` [ DiffSummary { patch = Insert (LeafInfo "string" "a"), parentAnnotations = [ ArrayLiteral ] } ] + diffSummaries sources testDiff `shouldBe` [ DiffSummary { patch = Insert (LeafInfo "string" "a"), parentAnnotation = Nothing } ] prop "equal terms produce identity diffs" $ \ a -> let term = toTerm (a :: ArbitraryTerm Text (Record '[Category, Range])) in @@ -53,7 +53,7 @@ spec = parallel $ do it "should print adds" $ annotatedSummaries testSummary `shouldBe` ["Added the 'a' string"] it "prints a replacement" $ do - annotatedSummaries replacementSummary `shouldBe` ["Replaced the 'a' string with the 'b' symbol in the array context"] + annotatedSummaries replacementSummary `shouldBe` ["Replaced the 'a' string with the 'b' symbol in the foo function call"] describe "DiffInfo" $ do prop "patches in summaries match the patches in diffs" $ \a -> let