2016-06-03 23:02:06 +03:00
|
|
|
{-# LANGUAGE DataKinds, TypeFamilies, ScopedTypeVariables #-}
|
2016-06-07 02:41:07 +03:00
|
|
|
|
2016-05-17 20:09:14 +03:00
|
|
|
module DiffSummary (DiffSummary(..), diffSummary, DiffInfo(..)) where
|
2016-04-25 18:46:10 +03:00
|
|
|
|
2016-06-07 02:41:07 +03:00
|
|
|
import Prologue hiding (fst, snd, intercalate)
|
2016-04-25 18:46:10 +03:00
|
|
|
import Diff
|
2016-06-03 02:10:41 +03:00
|
|
|
import Info (Info, category)
|
2016-04-25 18:46:10 +03:00
|
|
|
import Patch
|
2016-05-17 22:59:07 +03:00
|
|
|
import Term
|
2016-04-25 18:46:10 +03:00
|
|
|
import Syntax
|
2016-05-16 20:19:30 +03:00
|
|
|
import Category
|
2016-05-03 19:17:38 +03:00
|
|
|
import Data.Functor.Foldable as Foldable
|
2016-05-18 00:34:27 +03:00
|
|
|
import Data.Functor.Both
|
2016-05-18 20:27:19 +03:00
|
|
|
import Data.OrderedMap
|
2016-06-07 02:41:07 +03:00
|
|
|
import Data.Text as Text (intercalate, unpack)
|
2016-04-25 18:46:10 +03:00
|
|
|
|
2016-06-08 21:50:33 +03:00
|
|
|
data DiffInfo = DiffInfo { categoryName :: Text, termName :: Text } deriving (Eq, Show)
|
2016-05-18 17:18:26 +03:00
|
|
|
|
2016-06-08 21:50:33 +03:00
|
|
|
toTermName :: HasCategory leaf => Term leaf Info -> Text
|
2016-06-14 23:50:34 +03:00
|
|
|
toTermName term = case unwrap term of
|
|
|
|
Fixed children -> fromMaybe "EmptyFixedNode" $ (toCategoryName . category) . extract <$> head children
|
2016-06-15 18:06:13 +03:00
|
|
|
Indexed children -> fromMaybe "EmptyIndexedNode" $ (toCategoryName . category) . extract <$> head children
|
|
|
|
Keyed children -> mconcat $ keys children
|
|
|
|
Leaf leaf -> toCategoryName leaf
|
2016-06-14 23:50:34 +03:00
|
|
|
Syntax.Assignment identifier value -> toTermName identifier <> toTermName value
|
2016-06-15 18:06:13 +03:00
|
|
|
Syntax.Function identifier _ _ -> (maybe "anonymous" toTermName identifier)
|
|
|
|
Syntax.FunctionCall i _ -> toTermName i
|
2016-06-14 23:50:34 +03:00
|
|
|
Syntax.MemberAccess base property -> case (unwrap base, unwrap property) of
|
2016-06-14 01:34:35 +03:00
|
|
|
(Syntax.FunctionCall{}, Syntax.FunctionCall{}) -> toTermName base <> "()." <> toTermName property <> "()"
|
|
|
|
(Syntax.FunctionCall{}, _) -> toTermName base <> "()." <> toTermName property
|
|
|
|
(_, Syntax.FunctionCall{}) -> toTermName base <> "." <> toTermName property <> "()"
|
|
|
|
(_, _) -> toTermName base <> "." <> toTermName property
|
2016-06-15 00:04:27 +03:00
|
|
|
Syntax.MethodCall targetId methodId _ -> toTermName targetId <> sep <> toTermName methodId <> "()"
|
|
|
|
where sep = case unwrap targetId of
|
|
|
|
Syntax.FunctionCall{} -> "()."
|
|
|
|
_ -> "."
|
2016-06-17 22:40:33 +03:00
|
|
|
Syntax.SubscriptAccess base element -> case (unwrap base, unwrap element) of
|
|
|
|
(Syntax.FunctionCall{}, Syntax.FunctionCall{}) -> toTermName base <> "()." <> toTermName element <> "()"
|
|
|
|
(Syntax.FunctionCall{}, _) -> toTermName base <> "()." <> toTermName element
|
|
|
|
(_, Syntax.FunctionCall{}) -> toTermName base <> "[" <> toTermName element <> "()" <> "]"
|
|
|
|
(_, _) -> toTermName base <> "[" <> toTermName element <> "]"
|
2016-06-15 03:47:51 +03:00
|
|
|
Syntax.VarAssignment varId _ -> toTermName varId
|
2016-06-15 18:06:13 +03:00
|
|
|
Syntax.VarDecl decl -> toTermName decl
|
2016-06-16 01:51:17 +03:00
|
|
|
-- TODO: We should remove Args from Syntax since I don't think we should ever
|
2016-06-15 21:15:09 +03:00
|
|
|
-- evaluate Args as a single toTermName Text - joshvera
|
|
|
|
Syntax.Args args -> mconcat $ toTermName <$> args
|
2016-06-16 01:51:17 +03:00
|
|
|
-- TODO: We should remove Case from Syntax since I don't think we should ever
|
|
|
|
-- evaluate Case as a single toTermName Text - joshvera
|
|
|
|
Syntax.Case expr _ -> toTermName expr
|
2016-06-16 01:57:55 +03:00
|
|
|
Syntax.Switch expr _ -> toTermName expr
|
2016-05-18 20:27:19 +03:00
|
|
|
|
2016-05-24 19:49:16 +03:00
|
|
|
class HasCategory a where
|
2016-06-06 22:45:44 +03:00
|
|
|
toCategoryName :: a -> Text
|
2016-05-18 00:34:27 +03:00
|
|
|
|
2016-05-24 19:49:16 +03:00
|
|
|
instance HasCategory Text where
|
2016-06-06 22:45:44 +03:00
|
|
|
toCategoryName = identity
|
2016-05-18 19:01:16 +03:00
|
|
|
|
2016-06-09 01:14:55 +03:00
|
|
|
instance HasCategory Info where
|
|
|
|
toCategoryName = toCategoryName . category
|
|
|
|
|
2016-05-24 19:49:16 +03:00
|
|
|
instance HasCategory Category where
|
2016-06-10 22:24:37 +03:00
|
|
|
toCategoryName = \case
|
2016-06-15 18:06:13 +03:00
|
|
|
ArrayLiteral -> "array"
|
2016-05-18 00:34:27 +03:00
|
|
|
BinaryOperator -> "binary operator"
|
2016-06-16 17:54:20 +03:00
|
|
|
Boolean -> "boolean"
|
2016-05-18 20:37:02 +03:00
|
|
|
DictionaryLiteral -> "dictionary"
|
2016-06-15 18:06:13 +03:00
|
|
|
Error -> "error"
|
2016-06-10 22:24:37 +03:00
|
|
|
ExpressionStatements -> "expression statements"
|
2016-06-14 00:32:00 +03:00
|
|
|
Category.Assignment -> "assignment"
|
2016-06-15 18:06:13 +03:00
|
|
|
Category.Function -> "function"
|
|
|
|
Category.FunctionCall -> "function call"
|
2016-06-14 01:34:07 +03:00
|
|
|
Category.MemberAccess -> "member access"
|
2016-06-15 18:06:13 +03:00
|
|
|
Category.MethodCall -> "method call"
|
2016-06-15 21:15:29 +03:00
|
|
|
Category.Args -> "arguments"
|
|
|
|
Category.VarAssignment -> "var assignment"
|
2016-06-16 01:09:44 +03:00
|
|
|
Category.VarDecl -> "variable"
|
2016-06-16 02:51:48 +03:00
|
|
|
Category.Switch -> "switch statement"
|
|
|
|
Category.Case -> "case statement"
|
2016-06-17 22:40:33 +03:00
|
|
|
Category.SubscriptAccess -> "subscript access"
|
2016-06-17 22:57:51 +03:00
|
|
|
Category.MathAssignment -> "math assignment"
|
2016-06-15 18:06:13 +03:00
|
|
|
Identifier -> "identifier"
|
|
|
|
IntegerLiteral -> "integer"
|
2016-06-04 01:34:42 +03:00
|
|
|
Other s -> s
|
2016-06-15 18:06:13 +03:00
|
|
|
Pair -> "pair"
|
|
|
|
Params -> "params"
|
|
|
|
Program -> "top level"
|
2016-06-15 19:09:52 +03:00
|
|
|
Regex -> "regex"
|
2016-06-15 18:06:13 +03:00
|
|
|
StringLiteral -> "string"
|
|
|
|
SymbolLiteral -> "symbol"
|
2016-06-15 18:39:18 +03:00
|
|
|
TemplateString -> "template string"
|
2016-05-17 20:09:14 +03:00
|
|
|
|
2016-05-24 19:49:16 +03:00
|
|
|
instance HasCategory leaf => HasCategory (Term leaf Info) where
|
2016-05-31 23:13:01 +03:00
|
|
|
toCategoryName = toCategoryName . category . extract
|
2016-05-24 19:49:16 +03:00
|
|
|
|
2016-05-17 20:09:14 +03:00
|
|
|
data DiffSummary a = DiffSummary {
|
2016-05-31 23:11:11 +03:00
|
|
|
patch :: Patch a,
|
2016-06-08 21:46:38 +03:00
|
|
|
parentAnnotations :: [Category]
|
2016-05-17 20:09:14 +03:00
|
|
|
} deriving (Eq, Functor)
|
2016-05-13 18:44:03 +03:00
|
|
|
|
2016-05-31 23:11:11 +03:00
|
|
|
instance Show (DiffSummary DiffInfo) where
|
2016-06-08 21:46:38 +03:00
|
|
|
showsPrec _ DiffSummary{..} s = (++s) . unpack $ case patch of
|
|
|
|
(Insert diffInfo) -> "Added the " <> "'" <> termName diffInfo <> "' " <> categoryName diffInfo <> maybeParentContext parentAnnotations
|
|
|
|
(Delete diffInfo) -> "Deleted the " <> "'" <> termName diffInfo <> "' " <> categoryName diffInfo <> maybeParentContext parentAnnotations
|
|
|
|
(Replace t1 t2) ->
|
|
|
|
"Replaced the " <> "'" <> termName t1 <> "' " <> categoryName t1
|
|
|
|
<> " with the " <> "'" <> termName t2 <> "' " <> categoryName t2
|
2016-06-06 22:45:44 +03:00
|
|
|
<> maybeParentContext parentAnnotations
|
2016-05-24 19:37:44 +03:00
|
|
|
where maybeParentContext parentAnnotations = if null parentAnnotations
|
|
|
|
then ""
|
2016-06-08 21:46:38 +03:00
|
|
|
else " in the " <> intercalate "/" (toCategoryName <$> parentAnnotations) <> " context"
|
2016-04-25 18:46:10 +03:00
|
|
|
|
2016-05-24 19:49:16 +03:00
|
|
|
diffSummary :: HasCategory leaf => Diff leaf Info -> [DiffSummary DiffInfo]
|
2016-06-06 21:45:45 +03:00
|
|
|
diffSummary = cata $ \case
|
|
|
|
(Free (_ :< Leaf _)) -> [] -- Skip leaves since they don't have any changes
|
2016-06-08 21:46:38 +03:00
|
|
|
(Free (infos :< Indexed children)) -> prependSummary (category $ snd infos) <$> join children
|
|
|
|
(Free (infos :< Fixed children)) -> prependSummary (category $ snd infos) <$> join children
|
|
|
|
(Free (infos :< Keyed children)) -> prependSummary (category $ snd infos) <$> join (Prologue.toList children)
|
2016-06-10 20:27:20 +03:00
|
|
|
(Free (infos :< Syntax.FunctionCall identifier children)) -> prependSummary (category $ snd infos) <$> join (Prologue.toList (identifier : children))
|
2016-06-10 22:10:37 +03:00
|
|
|
(Free (infos :< Syntax.Function id ps body)) -> prependSummary (category $ snd infos) <$> (fromMaybe [] id) <> (fromMaybe [] ps) <> body
|
2016-06-14 00:32:00 +03:00
|
|
|
(Free (infos :< Syntax.Assignment id value)) -> prependSummary (category $ snd infos) <$> id <> value
|
2016-06-14 01:34:07 +03:00
|
|
|
(Free (infos :< Syntax.MemberAccess base property)) -> prependSummary (category $ snd infos) <$> base <> property
|
2016-06-17 22:40:33 +03:00
|
|
|
(Free (infos :< Syntax.SubscriptAccess base property)) -> prependSummary (category $ snd infos) <$> base <> property
|
2016-06-13 00:26:31 +03:00
|
|
|
(Free (infos :< Syntax.MethodCall targetId methodId ps)) -> prependSummary (category $ snd infos) <$> targetId <> methodId <> ps
|
2016-06-15 21:15:46 +03:00
|
|
|
(Free (infos :< Syntax.VarAssignment varId value)) -> prependSummary (category $ snd infos) <$> varId <> value
|
|
|
|
(Free (infos :< Syntax.VarDecl decl)) -> prependSummary (category $ snd infos) <$> decl
|
|
|
|
(Free (infos :< Syntax.Args args)) -> prependSummary (category $ snd infos) <$> join args
|
2016-06-16 02:52:05 +03:00
|
|
|
(Free (infos :< Syntax.Switch expr cases)) -> prependSummary (category $ snd infos) <$> expr <> join cases
|
|
|
|
(Free (infos :< Syntax.Case expr body)) -> prependSummary (category $ snd infos) <$> expr <> body
|
2016-06-08 22:18:44 +03:00
|
|
|
(Pure (Insert term)) -> (\info -> DiffSummary (Insert info) []) <$> termToDiffInfo term
|
|
|
|
(Pure (Delete term)) -> (\info -> DiffSummary (Delete info) []) <$> termToDiffInfo term
|
|
|
|
(Pure (Replace t1 t2)) -> (\(info1, info2) -> DiffSummary (Replace info1 info2) []) <$> zip (termToDiffInfo t1) (termToDiffInfo t2)
|
|
|
|
|
|
|
|
termToDiffInfo :: HasCategory leaf => Term leaf Info -> [DiffInfo]
|
|
|
|
termToDiffInfo term = case runCofree term of
|
|
|
|
(_ :< Leaf _) -> [ DiffInfo (toCategoryName term) (toTermName term) ]
|
|
|
|
(_ :< Indexed children) -> join $ termToDiffInfo <$> children
|
|
|
|
(_ :< Fixed children) -> join $ termToDiffInfo <$> children
|
|
|
|
(_ :< Keyed children) -> join $ termToDiffInfo <$> Prologue.toList children
|
2016-06-09 01:14:55 +03:00
|
|
|
(info :< Syntax.FunctionCall identifier _) -> [ DiffInfo (toCategoryName info) (toTermName identifier) ]
|
2016-06-13 00:32:03 +03:00
|
|
|
(info :< Syntax.Function identifier _ _) -> [ DiffInfo (toCategoryName info) (maybe "anonymous" toTermName identifier) ]
|
2016-06-15 03:48:04 +03:00
|
|
|
(info :< Syntax.Assignment identifier _) -> [ DiffInfo (toCategoryName info) (toTermName identifier) ]
|
2016-06-17 22:57:51 +03:00
|
|
|
(info :< Syntax.MathAssignment identifier _) -> [ DiffInfo (toCategoryName info) (toTermName identifier) ]
|
2016-06-14 01:34:07 +03:00
|
|
|
memberAccess@(info :< Syntax.MemberAccess{}) -> [ DiffInfo (toCategoryName info) (toTermName $ cofree memberAccess) ]
|
2016-06-17 22:40:33 +03:00
|
|
|
subscriptAccess@(info :< Syntax.SubscriptAccess{}) -> [ DiffInfo (toCategoryName info) (toTermName $ cofree subscriptAccess) ]
|
2016-06-15 03:48:04 +03:00
|
|
|
methodCall@(info :< Syntax.MethodCall{}) -> [ DiffInfo (toCategoryName info) (toTermName $ cofree methodCall) ]
|
2016-06-15 21:16:07 +03:00
|
|
|
-- TODO: We should remove Args from Syntax since I don't think we shouldn ever
|
|
|
|
-- evaluate Args as a single toTermName Text - joshvera
|
|
|
|
args@(info :< Syntax.Args{}) -> [ DiffInfo (toCategoryName info) (toTermName $ cofree args) ]
|
|
|
|
varDecl@(info :< Syntax.VarDecl{}) -> [ DiffInfo (toCategoryName info) (toTermName $ cofree varDecl) ]
|
|
|
|
varAssignment@(info :< Syntax.VarAssignment{}) -> [ DiffInfo (toCategoryName info) (toTermName $ cofree varAssignment) ]
|
2016-06-16 01:58:08 +03:00
|
|
|
switch@(info :< Syntax.Switch{}) -> [ DiffInfo (toCategoryName info) (toTermName $ cofree switch) ]
|
2016-06-16 03:03:59 +03:00
|
|
|
caseExpr@(info :< Syntax.Case{}) -> [ DiffInfo (toCategoryName info) (toTermName $ cofree caseExpr) ]
|
2016-05-16 17:54:05 +03:00
|
|
|
|
2016-06-08 21:46:38 +03:00
|
|
|
prependSummary :: Category -> DiffSummary DiffInfo -> DiffSummary DiffInfo
|
2016-05-16 17:54:05 +03:00
|
|
|
prependSummary annotation summary = summary { parentAnnotations = annotation : parentAnnotations summary }
|