diff --git a/src/DiffSummary.hs b/src/DiffSummary.hs index cc9bdc61e..aa531b7b4 100644 --- a/src/DiffSummary.hs +++ b/src/DiffSummary.hs @@ -72,7 +72,7 @@ data DiffInfo = LeafInfo { categoryName :: Text, termName :: Text, sourceSpan :: | HideInfo -- Hide/Strip from summary output entirely. deriving (Eq, Show) -data Branch = BIndexed | BFixed | BCommented deriving (Show, Eq, Generic) +data Branch = BIndexed | BFixed | BCommented | BIf deriving (Show, Eq, Generic) data DiffSummary a = DiffSummary { patch :: Patch a, @@ -246,9 +246,10 @@ termToDiffInfo blob term = case unwrap term of S.Comment _ -> HideInfo S.Commented cs leaf -> BranchInfo (termToDiffInfo' <$> cs <> maybeToList leaf) (toCategoryName term) BCommented S.Error _ -> ErrorInfo (getField $ extract term) (toTermName' term) - _ -> LeafInfo (toCategoryName term) (toTermName' term) (getField $ extract term) + _ -> toLeafInfo term where toTermName' = toTermName blob termToDiffInfo' = termToDiffInfo blob + toLeafInfo term = LeafInfo (toCategoryName term) (toTermName' term) (getField $ extract term) -- | Append a parentAnnotation to the current DiffSummary instance. -- | For a DiffSummary without a parentAnnotation, we append a parentAnnotation with the first identifiable term. diff --git a/src/Language/JavaScript.hs b/src/Language/JavaScript.hs index 54f261295..8876966ca 100644 --- a/src/Language/JavaScript.hs +++ b/src/Language/JavaScript.hs @@ -50,8 +50,8 @@ termConstructor source sourceSpan name range children ("object", _) -> S.Object $ foldMap toTuple children ("pair", _) -> S.Fixed children ("comment", _) -> S.Comment . toText $ slice range source - ("if_statement", [ expr, clause1, clause2 ]) -> S.If expr clause1 (Just clause2) - ("if_statement", [ expr, clause ]) -> S.If expr clause Nothing + ("if_statement", [ expr, thenClause, elseClause ]) -> toElseIf expr thenClause elseClause + ("if_statement", [ expr, thenClause ]) -> S.If expr thenClause [] ("while_statement", [ expr, body ]) -> S.While expr body ("do_statement", [ expr, body ]) -> S.DoWhile expr body ("throw_statement", [ expr ]) -> S.Throw expr @@ -157,6 +157,19 @@ categoryForJavaScriptProductionName name = case name of toVarDecl :: (HasField fields Category) => Term (S.Syntax Text) (Record fields) -> Term (S.Syntax Text) (Record fields) toVarDecl child = cofree $ setCategory (extract child) VarDecl :< S.VarDecl child +-- | Convert a If Term to If Syntax. This handles nested else-if clauses recursively, +-- | and satisfies arbitrarily long else-if clauses. +toElseIf :: Term (S.Syntax Text) (Record fields) + -> Term (S.Syntax Text) (Record fields) + -> Term (S.Syntax Text) (Record fields) + -> S.Syntax Text (Term (S.Syntax Text) (Record fields)) +toElseIf expr thenClause elseClause = S.If expr thenClause (elseClause' elseClause) + where + elseClause' term = case unwrap term of + S.If _ _ [] -> [ term ] + S.If then' else' children -> [ cofree (extract term :< S.If then' else' []) ] <> (elseClause' =<< children) + _ -> [ term ] + toTuple :: Term (S.Syntax Text) (Record fields) -> [Term (S.Syntax Text) (Record fields)] toTuple child | S.Indexed [key,value] <- unwrap child = [cofree (extract child :< S.Pair key value)] toTuple child | S.Fixed [key,value] <- unwrap child = [cofree (extract child :< S.Pair key value)] diff --git a/src/Syntax.hs b/src/Syntax.hs index 253e9a9d7..3baf604f6 100644 --- a/src/Syntax.hs +++ b/src/Syntax.hs @@ -70,7 +70,8 @@ data Syntax a f | Class f (Maybe f) [f] -- | A method definition with an identifier, params, and a list of expressions. | Method f [f] [f] - | If f f (Maybe f) + -- | An if statement with an expression, a clause, and maybe more expressions, clauses. + | If f f [f] -- | A module with an identifier, and a list of syntaxes. | Module { moduleId:: f, moduleBody :: [f] } | Import f [f] diff --git a/test/corpus/diff-summaries/javascript/if-else.json b/test/corpus/diff-summaries/javascript/if-else.json index fa28d3b31..40a3cd790 100644 --- a/test/corpus/diff-summaries/javascript/if-else.json +++ b/test/corpus/diff-summaries/javascript/if-else.json @@ -11,8 +11,8 @@ 1 ], "end": [ - 1, - 25 + 2, + 1 ] } }, @@ -25,9 +25,9 @@ "filePaths": [ "if-else.js" ], - "sha1": "177b3db7ca070dc750876553a0cd7fde8b5df54c", + "sha1": "3903cb97b8c7fe507a17fa52ec09e6eaa1e95ad8", "gitDir": "test/corpus/repos/javascript", - "sha2": "fd499e58d749df1da475f0d6033825f265734210" + "sha2": "182d895f1ed34f6ea3f5e01ebec34f3872486ae2" } ,{ "testCaseDescription": "javascript-if-else-replacement-insert-test", @@ -42,12 +42,12 @@ 1 ], "end": [ - 1, - 29 + 2, + 1 ] } }, - "summary": "Added the 'a' if statement" + "summary": "Added the 'g' if statement" }, { "span": { @@ -57,8 +57,8 @@ 1 ], "end": [ - 2, - 25 + 3, + 1 ] } }, @@ -71,9 +71,9 @@ "filePaths": [ "if-else.js" ], - "sha1": "fd499e58d749df1da475f0d6033825f265734210", + "sha1": "182d895f1ed34f6ea3f5e01ebec34f3872486ae2", "gitDir": "test/corpus/repos/javascript", - "sha2": "1f6c19a2b78ca415ac6e06f69c051ba6c23a250e" + "sha2": "b27dbe99809ec3a3cff8c1bdac1829a7ec7f3a2a" } ,{ "testCaseDescription": "javascript-if-else-delete-insert-test", @@ -86,26 +86,248 @@ { "start": [ 1, - 1 + 5 ], "end": [ 1, - 29 + 6 ] }, { "start": [ 1, - 1 + 5 ], "end": [ 1, - 25 + 6 ] } ] }, - "summary": "Replaced the 'a' if statement with the 'x' if statement" + "summary": "Replaced the 'g' identifier with the 'x' identifier" + }, + { + "span": { + "replace": [ + { + "start": [ + 1, + 8 + ], + "end": [ + 1, + 9 + ] + }, + { + "start": [ + 1, + 8 + ], + "end": [ + 1, + 9 + ] + } + ] + }, + "summary": "Replaced the 'h' identifier with the 'y' identifier" + }, + { + "span": { + "replace": [ + { + "start": [ + 1, + 20 + ], + "end": [ + 1, + 21 + ] + }, + { + "start": [ + 1, + 20 + ], + "end": [ + 1, + 21 + ] + } + ] + }, + "summary": "Replaced the 'i' identifier with the 'a' identifier" + }, + { + "span": { + "insert": { + "start": [ + 1, + 23 + ], + "end": [ + 1, + 24 + ] + } + }, + "summary": "Added the 'b' identifier" + }, + { + "span": { + "delete": { + "start": [ + 1, + 25 + ], + "end": [ + 1, + 26 + ] + } + }, + "summary": "Deleted the 'j' identifier" + }, + { + "span": { + "replace": [ + { + "start": [ + 1, + 39 + ], + "end": [ + 1, + 40 + ] + }, + { + "start": [ + 1, + 35 + ], + "end": [ + 1, + 36 + ] + } + ] + }, + "summary": "Replaced the 'k' identifier with the 'c' identifier" + }, + { + "span": { + "replace": [ + { + "start": [ + 1, + 42 + ], + "end": [ + 1, + 43 + ] + }, + { + "start": [ + 1, + 38 + ], + "end": [ + 1, + 39 + ] + } + ] + }, + "summary": "Replaced the 'l' identifier with the 'd' identifier" + }, + { + "span": { + "replace": [ + { + "start": [ + 1, + 54 + ], + "end": [ + 1, + 55 + ] + }, + { + "start": [ + 1, + 50 + ], + "end": [ + 1, + 51 + ] + } + ] + }, + "summary": "Replaced the 'm' identifier with the 'e' identifier" + }, + { + "span": { + "insert": { + "start": [ + 1, + 53 + ], + "end": [ + 1, + 54 + ] + } + }, + "summary": "Added the 'f' identifier" + }, + { + "span": { + "delete": { + "start": [ + 1, + 59 + ], + "end": [ + 1, + 60 + ] + } + }, + "summary": "Deleted the 'n' identifier" + }, + { + "span": { + "replace": [ + { + "start": [ + 1, + 69 + ], + "end": [ + 1, + 70 + ] + }, + { + "start": [ + 1, + 61 + ], + "end": [ + 1, + 62 + ] + } + ] + }, + "summary": "Replaced the 'o' identifier with the 'g' identifier" } ] }, @@ -114,9 +336,9 @@ "filePaths": [ "if-else.js" ], - "sha1": "1f6c19a2b78ca415ac6e06f69c051ba6c23a250e", + "sha1": "b27dbe99809ec3a3cff8c1bdac1829a7ec7f3a2a", "gitDir": "test/corpus/repos/javascript", - "sha2": "946c2d3269de0a2f284a9922b8da111323729827" + "sha2": "2713de071b224835fcb35bf709342334422c4fb7" } ,{ "testCaseDescription": "javascript-if-else-replacement-test", @@ -129,26 +351,248 @@ { "start": [ 1, - 1 + 5 ], "end": [ 1, - 25 + 6 ] }, { "start": [ 1, - 1 + 5 ], "end": [ 1, - 29 + 6 ] } ] }, - "summary": "Replaced the 'x' if statement with the 'a' if statement" + "summary": "Replaced the 'x' identifier with the 'g' identifier" + }, + { + "span": { + "replace": [ + { + "start": [ + 1, + 8 + ], + "end": [ + 1, + 9 + ] + }, + { + "start": [ + 1, + 8 + ], + "end": [ + 1, + 9 + ] + } + ] + }, + "summary": "Replaced the 'y' identifier with the 'h' identifier" + }, + { + "span": { + "replace": [ + { + "start": [ + 1, + 20 + ], + "end": [ + 1, + 21 + ] + }, + { + "start": [ + 1, + 20 + ], + "end": [ + 1, + 21 + ] + } + ] + }, + "summary": "Replaced the 'a' identifier with the 'i' identifier" + }, + { + "span": { + "insert": { + "start": [ + 1, + 25 + ], + "end": [ + 1, + 26 + ] + } + }, + "summary": "Added the 'j' identifier" + }, + { + "span": { + "delete": { + "start": [ + 1, + 23 + ], + "end": [ + 1, + 24 + ] + } + }, + "summary": "Deleted the 'b' identifier" + }, + { + "span": { + "replace": [ + { + "start": [ + 1, + 35 + ], + "end": [ + 1, + 36 + ] + }, + { + "start": [ + 1, + 39 + ], + "end": [ + 1, + 40 + ] + } + ] + }, + "summary": "Replaced the 'c' identifier with the 'k' identifier" + }, + { + "span": { + "replace": [ + { + "start": [ + 1, + 38 + ], + "end": [ + 1, + 39 + ] + }, + { + "start": [ + 1, + 42 + ], + "end": [ + 1, + 43 + ] + } + ] + }, + "summary": "Replaced the 'd' identifier with the 'l' identifier" + }, + { + "span": { + "replace": [ + { + "start": [ + 1, + 50 + ], + "end": [ + 1, + 51 + ] + }, + { + "start": [ + 1, + 54 + ], + "end": [ + 1, + 55 + ] + } + ] + }, + "summary": "Replaced the 'e' identifier with the 'm' identifier" + }, + { + "span": { + "insert": { + "start": [ + 1, + 59 + ], + "end": [ + 1, + 60 + ] + } + }, + "summary": "Added the 'n' identifier" + }, + { + "span": { + "delete": { + "start": [ + 1, + 53 + ], + "end": [ + 1, + 54 + ] + } + }, + "summary": "Deleted the 'f' identifier" + }, + { + "span": { + "replace": [ + { + "start": [ + 1, + 61 + ], + "end": [ + 1, + 62 + ] + }, + { + "start": [ + 1, + 69 + ], + "end": [ + 1, + 70 + ] + } + ] + }, + "summary": "Replaced the 'g' identifier with the 'o' identifier" } ] }, @@ -157,9 +601,9 @@ "filePaths": [ "if-else.js" ], - "sha1": "946c2d3269de0a2f284a9922b8da111323729827", + "sha1": "2713de071b224835fcb35bf709342334422c4fb7", "gitDir": "test/corpus/repos/javascript", - "sha2": "71792b4ff0291e41c9e3ec3157abfea9cd67daa7" + "sha2": "acdc250e3e92d45007edc022e7a46bd7c8870264" } ,{ "testCaseDescription": "javascript-if-else-delete-replacement-test", @@ -174,12 +618,12 @@ 1 ], "end": [ - 1, - 29 + 2, + 1 ] } }, - "summary": "Deleted the 'a' if statement" + "summary": "Deleted the 'g' if statement" }, { "span": { @@ -189,8 +633,8 @@ 1 ], "end": [ - 2, - 25 + 3, + 1 ] } }, @@ -204,12 +648,12 @@ 1 ], "end": [ - 2, - 29 + 3, + 1 ] } }, - "summary": "Added the 'a' if statement" + "summary": "Added the 'g' if statement" } ] }, @@ -218,9 +662,9 @@ "filePaths": [ "if-else.js" ], - "sha1": "71792b4ff0291e41c9e3ec3157abfea9cd67daa7", + "sha1": "acdc250e3e92d45007edc022e7a46bd7c8870264", "gitDir": "test/corpus/repos/javascript", - "sha2": "95edd1d597a111bbe508c047a0f75d0342b35cea" + "sha2": "c05504705f6307d70ec027ce0da03266c41b4333" } ,{ "testCaseDescription": "javascript-if-else-delete-test", @@ -235,8 +679,8 @@ 1 ], "end": [ - 1, - 25 + 2, + 1 ] } }, @@ -249,9 +693,9 @@ "filePaths": [ "if-else.js" ], - "sha1": "95edd1d597a111bbe508c047a0f75d0342b35cea", + "sha1": "c05504705f6307d70ec027ce0da03266c41b4333", "gitDir": "test/corpus/repos/javascript", - "sha2": "58fd81ed8b29ab258997ccdcb2a0602e64748fc8" + "sha2": "dbba6da8532f1191731609e596468ea525643576" } ,{ "testCaseDescription": "javascript-if-else-delete-rest-test", @@ -266,12 +710,12 @@ 1 ], "end": [ - 1, - 29 + 2, + 1 ] } }, - "summary": "Deleted the 'a' if statement" + "summary": "Deleted the 'g' if statement" } ] }, @@ -280,7 +724,7 @@ "filePaths": [ "if-else.js" ], - "sha1": "58fd81ed8b29ab258997ccdcb2a0602e64748fc8", + "sha1": "dbba6da8532f1191731609e596468ea525643576", "gitDir": "test/corpus/repos/javascript", - "sha2": "73e8a48299a8c408fadbf83077ab1e56ea81b5b0" + "sha2": "4c75eac553b89390d3a122886e4797b7e470dc3f" }] diff --git a/test/corpus/generated/javascript.json b/test/corpus/generated/javascript.json index b52646b51..be4b4d739 100644 --- a/test/corpus/generated/javascript.json +++ b/test/corpus/generated/javascript.json @@ -385,8 +385,8 @@ { "syntax": "if-else", "repoFilePath": "if-else.js", - "insert": "if (x) y; else if (a) b;", - "replacement": "if (a) { c; d; } else { e; }", + "insert": "if (x) y; else if (a) b; else if (c) d; else if (e) f; else g", + "replacement": "if (g) h; else if (i) { j; } else if (k) l; else if (m) { n; } else o", "testCaseFilePath": "test/corpus/diff-summaries/javascript/if-else.json" }, { diff --git a/test/corpus/repos/javascript b/test/corpus/repos/javascript index dce5b472e..0fcaa2c97 160000 --- a/test/corpus/repos/javascript +++ b/test/corpus/repos/javascript @@ -1 +1 @@ -Subproject commit dce5b472e5bcc43861e65b412644c7931f12d313 +Subproject commit 0fcaa2c972c37d8b90d03e71ec04376f26c8ef22