Skip to content
This repository was archived by the owner on May 18, 2019. It is now read-only.

Commit 5c05ef6

Browse files
sjoelundOpenModelica-Hudson
authored andcommitted
Move comments after doing the diff algorithm
This handles some cases with whitespace better. Belonging to [master]: - #2099 - OpenModelica/OpenModelica-testsuite#815
1 parent efcef39 commit 5c05ef6

File tree

1 file changed

+189
-0
lines changed

1 file changed

+189
-0
lines changed

Compiler/Parsers/SimpleModelicaParser.mo

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ import LexerModelicaDiff.{Token,TokenId,tokenContent,printToken,modelicaDiffToke
3535

3636
protected
3737

38+
import AvlSetString;
3839
import DiffAlgorithm;
3940
import DiffAlgorithm.{diff,Diff};
4041
import Error;
@@ -99,6 +100,7 @@ algorithm
99100
end match;
100101
t2_updated := moveComments(t1, t2_updated);
101102
res := treeDiffWork1(t1, t2_updated, nTokens);
103+
res := moveCommentsAfterDiff(res);
102104
end treeDiff;
103105

104106
partial function CmpParseTreeFunc
@@ -1543,6 +1545,193 @@ algorithm
15431545
end for;
15441546
end moveComments;
15451547

1548+
function moveCommentsAfterDiff
1549+
input output list<tuple<Diff,list<ParseTree>>> res;
1550+
protected
1551+
list<tuple<Token, list<ParseTree>, String>> c1, c2, remaining;
1552+
Token tok;
1553+
String foundComment;
1554+
ParseTree tree, foundTree;
1555+
list<ParseTree> trees, before, after, acc2;
1556+
AvlSetString.Tree comments;
1557+
list<tuple<Diff,list<ParseTree>>> acc, lst;
1558+
tuple<Diff,list<ParseTree>> diff;
1559+
Boolean found;
1560+
algorithm
1561+
// O(N*D); scales with number of diffs since we restart whenever we move a comment
1562+
comments := findAddedComments(res);
1563+
acc := {};
1564+
lst := res;
1565+
if AvlSetString.isEmpty(comments) then
1566+
return;
1567+
end if;
1568+
while not listEmpty(lst) loop
1569+
diff::lst := lst;
1570+
_ := match diff
1571+
case (Diff.Delete, trees)
1572+
algorithm
1573+
acc2 := {};
1574+
while not listEmpty(trees) loop
1575+
tree::trees := trees;
1576+
(found,before,foundTree,after,foundComment) := fixDeletedComments(tree, comments);
1577+
if found then
1578+
acc := (Diff.Add, listAppend(listReverse(acc2),before))::acc;
1579+
res := listAppend(listReverse(acc),(Diff.Equal,{foundTree})::(Diff.Add, listAppend(after, trees))::lst);
1580+
res := removeAddedCommentFromDiff(res, foundComment);
1581+
// Continue until we can't fix more comments
1582+
res := moveCommentsAfterDiff(res);
1583+
return;
1584+
end if;
1585+
acc2 := tree::acc2;
1586+
end while;
1587+
then ();
1588+
else ();
1589+
end match;
1590+
acc := diff::acc;
1591+
end while;
1592+
end moveCommentsAfterDiff;
1593+
1594+
function findAddedComments
1595+
input list<tuple<Diff,list<ParseTree>>> tree;
1596+
output AvlSetString.Tree comments = AvlSetString.EMPTY();
1597+
protected
1598+
list<ParseTree> addedTrees;
1599+
algorithm
1600+
(addedTrees,) := extractAdditionsDeletions(tree);
1601+
for t in addedTrees loop
1602+
comments := findAddedComments2(t, comments);
1603+
end for;
1604+
end findAddedComments;
1605+
1606+
function findAddedComments2
1607+
input ParseTree tree;
1608+
input output AvlSetString.Tree comments;
1609+
protected
1610+
list<ParseTree> nodes;
1611+
Token tok;
1612+
algorithm
1613+
comments := match tree
1614+
case LEAF() guard parseTreeIsComment(tree) then AvlSetString.add(comments, tokenContent(tree.token));
1615+
case NODE(nodes=nodes)
1616+
algorithm
1617+
for n in nodes loop
1618+
comments := findAddedComments2(n, comments);
1619+
end for;
1620+
then comments;
1621+
else comments;
1622+
end match;
1623+
end findAddedComments2;
1624+
1625+
function removeAddedCommentFromDiff
1626+
input output list<tuple<Diff,list<ParseTree>>> tree;
1627+
input String comment;
1628+
protected
1629+
list<tuple<Diff,list<ParseTree>>> acc, lst;
1630+
tuple<Diff,list<ParseTree>> diff;
1631+
list<ParseTree> lst2;
1632+
Boolean b;
1633+
algorithm
1634+
lst := tree;
1635+
acc := {};
1636+
while not listEmpty(lst) loop
1637+
diff::lst := lst;
1638+
_ := match diff
1639+
case (Diff.Add,lst2)
1640+
algorithm
1641+
(b,lst2) := removeAddedCommentFromDiff2(lst2, comment);
1642+
if b then
1643+
tree := listAppend(listReverse(acc),(Diff.Add,lst2)::lst);
1644+
return;
1645+
end if;
1646+
then ();
1647+
else ();
1648+
end match;
1649+
acc := diff::acc;
1650+
end while;
1651+
Error.addInternalError("Failed to remove comment `"+comment+"` from diff; but we know it is in there somewhere", sourceInfo());
1652+
end removeAddedCommentFromDiff;
1653+
1654+
function removeAddedCommentFromDiff2
1655+
output Boolean removed=false;
1656+
input output list<ParseTree> trees;
1657+
input String comment;
1658+
protected
1659+
list<ParseTree> acc, lst, nodes;
1660+
ParseTree tree;
1661+
String content;
1662+
algorithm
1663+
acc := {};
1664+
lst := trees;
1665+
while not listEmpty(lst) loop
1666+
tree::lst := lst;
1667+
(removed, tree) := match tree
1668+
case LEAF() guard parseTreeIsComment(tree)
1669+
algorithm
1670+
content := tokenContent(tree.token);
1671+
then (content==comment, if content==comment then EMPTY() else tree);
1672+
case NODE(nodes=nodes)
1673+
algorithm
1674+
(removed, nodes) := removeAddedCommentFromDiff2(nodes, comment);
1675+
if removed then
1676+
tree.nodes := nodes;
1677+
end if;
1678+
then (removed, tree);
1679+
else (false, tree);
1680+
end match;
1681+
if removed then
1682+
lst := if isEmpty(tree) then lst else (tree::lst);
1683+
lst := listAppend(listReverse(acc), lst);
1684+
trees := lst;
1685+
return;
1686+
end if;
1687+
acc := tree::acc;
1688+
end while;
1689+
end removeAddedCommentFromDiff2;
1690+
1691+
function fixDeletedComments
1692+
input ParseTree tree;
1693+
input AvlSetString.Tree addedComments;
1694+
output Boolean found = false;
1695+
output list<ParseTree> before = {};
1696+
output ParseTree foundTree = tree;
1697+
output list<ParseTree> after = {};
1698+
output String foundComment = "";
1699+
protected
1700+
list<ParseTree> nodes, before2, after2;
1701+
Boolean b;
1702+
ParseTree t;
1703+
String content;
1704+
algorithm
1705+
found := match tree
1706+
case LEAF() guard parseTreeIsComment(tree)
1707+
algorithm
1708+
content := tokenContent(tree.token);
1709+
b := AvlSetString.hasKey(addedComments, content);
1710+
if b then
1711+
foundComment := content;
1712+
end if;
1713+
then b;
1714+
case NODE(nodes=nodes)
1715+
algorithm
1716+
while not listEmpty(nodes) loop
1717+
t::nodes := nodes;
1718+
(found, before2, foundTree, after2, foundComment) := fixDeletedComments(t, addedComments);
1719+
if found then
1720+
before := listAppend(listReverse(before), before2);
1721+
after := listAppend(after2, nodes);
1722+
return;
1723+
end if;
1724+
before := t::before;
1725+
end while;
1726+
before := {};
1727+
foundTree := tree;
1728+
after := {};
1729+
foundComment := "";
1730+
then false;
1731+
else false;
1732+
end match;
1733+
end fixDeletedComments;
1734+
15461735
function addCommentAtLabelPath
15471736
input output list<ParseTree> tree;
15481737
input Token tok;

0 commit comments

Comments
 (0)